Merge m-c to fx-team a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 06 Nov 2014 19:11:53 -0800
changeset 214573 19ed982b37213f07b2f41f33d0c16ba1b9908782
parent 214572 40e3339da787c8bab6bf6f7db9a79d7faddc985b (current diff)
parent 214464 17e19083908620e8a83876e49bac6f6ba2fcc272 (diff)
child 214574 df923a9845b93399bc0f44baeb3770040f1b0416
push id27785
push usercbook@mozilla.com
push dateFri, 07 Nov 2014 13:56:26 +0000
treeherdermozilla-central@69198f0cc0bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team a=merge
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1087560 changed a mochitest manifest without touching its moz.build.
+Bug 1095234 - Bug 1091260 stopped packaging a devtools file with EXTRA_JS_MODULES while making it require pre-processing.
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="70eb0cb0977d6295e7da8896f9efb9f3ca1c13ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="67f2907bc340bad250b4ea6ce2902b52896c9ef0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="70eb0cb0977d6295e7da8896f9efb9f3ca1c13ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="67f2907bc340bad250b4ea6ce2902b52896c9ef0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "1380aa2d9459bc1711cb5504c4c806038107428e", 
+    "revision": "ce1789cc91feafe53596cfd0360cd12f7cc69d3b", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="70eb0cb0977d6295e7da8896f9efb9f3ca1c13ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="70eb0cb0977d6295e7da8896f9efb9f3ca1c13ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="70eb0cb0977d6295e7da8896f9efb9f3ca1c13ea">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1b974ce130eed3988ff5d012c7bd8431c4aba93b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="62c9bd93341fbfa8bf850c21e73465708f93b503"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ad276e6d4ec40ae2ac214e42c6c81cfc8cd86c3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/dev/config/mozconfigs/linux64/mulet
+++ b/b2g/dev/config/mozconfigs/linux64/mulet
@@ -1,3 +1,7 @@
 . "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
 
 ac_add_options --enable-application=b2g/dev
+
+# Include Firefox OS fonts.
+# TODO Uncomment after Mulet ships with the fonts (bug 1011562).
+#MOZTTDIR=$topsrcdir/moztt
--- a/b2g/dev/config/mozconfigs/macosx64/mulet
+++ b/b2g/dev/config/mozconfigs/macosx64/mulet
@@ -16,9 +16,13 @@ export MOZILLA_OFFICIAL=1
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
+# Include Firefox OS fonts.
+# TODO Uncomment after Mulet ships with the fonts (bug 1011562).
+#MOZTTDIR=$topsrcdir/moztt
+
 . "$topsrcdir/build/mozconfig.common.override"
--- a/b2g/dev/config/mozconfigs/win32/mulet
+++ b/b2g/dev/config/mozconfigs/win32/mulet
@@ -1,3 +1,7 @@
 . "$topsrcdir/browser/config/mozconfigs/win32/nightly"
 
 ac_add_options --enable-application=b2g/dev
+
+# Include Firefox OS fonts.
+# TODO Uncomment after Mulet ships with the fonts (bug 1011562).
+#MOZTTDIR=$topsrcdir/moztt
new file mode 100644
--- /dev/null
+++ b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest
@@ -0,0 +1,27 @@
+[
+{
+"size": 82,
+"digest": "70a6126249e40aa1da32248bf6bfe45e0d8c87334579ec0cf69403e61b635e27c766d9bf08d530978286552f158ee24c74b0168a57cc6b734dcfed4fc5e09cff",
+"algorithm": "sha512",
+"filename": "setup.sh"
+},
+{
+"size": 80458572,
+"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
+"algorithm": "sha512",
+"filename": "gcc.tar.xz"
+},
+{
+"size": 168320,
+"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"algorithm": "sha512",
+"filename": "sccache.tar.bz2"
+},
+{
+"size": 31057326,
+"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
+"algorithm": "sha512",
+"filename": "moztt.tar.bz2",
+"unpack": "True"
+}
+]
new file mode 100644
--- /dev/null
+++ b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest
@@ -0,0 +1,30 @@
+[
+{
+"clang_version": "r183744"
+},
+{
+"size": 88,
+"digest": "0d2ae9bcd7cea34ec0b768270725e98410dbb3bc150c7381e0dcf3eb5dbb3e69ac76dbb0f46b056151d6a6fa8681cab06da68173ae8598f3397b8f7628e67381",
+"algorithm": "sha512",
+"filename": "setup.sh"
+},
+{
+"size": 59602619,
+"digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b",
+"algorithm": "sha512",
+"filename": "clang.tar.bz2"
+},
+{
+"size": 168320,
+"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"algorithm": "sha512",
+"filename": "sccache.tar.bz2"
+},
+{
+"size": 31057326,
+"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
+"algorithm": "sha512",
+"filename": "moztt.tar.bz2",
+"unpack": "True"
+}
+]
new file mode 100644
--- /dev/null
+++ b/b2g/dev/config/tooltool-manifests/win32/releng.manifest
@@ -0,0 +1,27 @@
+[
+{
+"size": 266240,
+"digest": "bb345b0e700ffab4d09436981f14b5de84da55a3f18a7f09ebc4364a4488acdeab8d46f447b12ac70f2da1444a68b8ce8b8675f0dae2ccf845e966d1df0f0869",
+"algorithm": "sha512",
+"filename": "mozmake.exe"
+},
+{
+"size": 51,
+"digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986",
+"algorithm": "sha512",
+"filename": "setup.sh"
+},
+{
+"size": 168320,
+"digest": "c0f4a2da0b07ca6fc69290fbc5ed68f56c6b1ba4d593b220fd49b14ac4885e6ec949e695fd9a7ac464e0e86b652e99f6bd4af849fec072264b29a8f9686d2fc4",
+"algorithm": "sha512",
+"filename": "sccache.tar.bz2"
+},
+{
+"size": 31057326,
+"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
+"algorithm": "sha512",
+"filename": "moztt.tar.bz2",
+"unpack": "True"
+}
+]
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1804,16 +1804,20 @@ pref("media.gmp-gmpopenh264.provider.ena
 
 pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
 
 #ifdef NIGHTLY_BUILD
 pref("browser.polaris.enabled", false);
 pref("privacy.trackingprotection.ui.enabled", false);
 #endif
 
+#ifdef NIGHTLY_BUILD
+pref("browser.tabs.remote.autostart.1", true);
+#endif
+
 // Temporary pref to allow printing in e10s windows on some platforms.
 #ifdef UNIX_BUT_NOT_MAC
 pref("print.enable_e10s_testing", false);
 #else
 pref("print.enable_e10s_testing", true);
 #endif
 
 pref("browser.defaultbrowser.notificationbar", false);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2406,17 +2406,17 @@ let DefaultBrowserCheck = {
     }
   },
 };
 
 #ifdef E10S_TESTING_ONLY
 let E10SUINotification = {
   // Increase this number each time we want to roll out an
   // e10s testing period to Nightly users.
-  CURRENT_NOTICE_COUNT: 1,
+  CURRENT_NOTICE_COUNT: 2,
   CURRENT_PROMPT_PREF: "browser.displayedE10SPrompt.1",
   PREVIOUS_PROMPT_PREF: "browser.displayedE10SPrompt",
 
   checkStatus: function() {
     let skipE10sChecks = false;
     try {
       // This order matters, because
       // browser.tabs.remote.autostart.disabled-because-using-a11y is not
@@ -2509,17 +2509,17 @@ let E10SUINotification = {
   _showE10sActivatedNotice: function() {
     let win = RecentWindow.getMostRecentBrowserWindow();
     if (!win)
       return;
 
     Services.prefs.setIntPref("browser.displayedE10SNotice", this.CURRENT_NOTICE_COUNT);
 
     let nb = win.document.getElementById("high-priority-global-notificationbox");
-    let message = "Thanks for helping to test multiprocess Firefox (e10s). Some functions might not work yet."
+    let message = "You're now helping to test Process Separation (e10s)! Please report problems you find.";
     let buttons = [
       {
         label: "Learn More",
         accessKey: "L",
         callback: function () {
           win.openUILinkIn("https://wiki.mozilla.org/Electrolysis", "tab");
         }
       }
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -87,19 +87,42 @@ var gMainPane = {
                      gMainPane.restoreDefaultHomePage);
     setEventListener("chooseFolder", "command",
                      gMainPane.chooseFolder);
 
 #ifdef E10S_TESTING_ONLY
     setEventListener("e10sAutoStart", "command",
                      gMainPane.enableE10SChange);
     let e10sCheckbox = document.getElementById("e10sAutoStart");
-    let e10sPref = document.getElementById("browser.tabs.remote.autostart");
-    let e10sTempPref = document.getElementById("e10sTempPref");
-    e10sCheckbox.checked = e10sPref.value || e10sTempPref.value;
+    e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart;
+
+    // If e10s is blocked for some reason unrelated to prefs, we want to disable
+    // the checkbox.
+    if (!Services.appinfo.browserTabsRemoteAutostart) {
+      let e10sBlockedReason = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+      let appinfo = Services.appinfo.QueryInterface(Ci.nsIObserver);
+      appinfo.observe(e10sBlockedReason, "getE10SBlocked", "")
+      if (e10sBlockedReason.data) {
+        if (e10sBlockedReason.data == "Safe mode") {
+          // If the only reason we're disabled is because of safe mode, then
+          // we want to allow the user to un-toggle the pref.
+          // We're relying on the nsAppRunner code only specifying "Safe mode"
+          // as the reason if the pref is otherwise enabled, and there are no
+          // other reasons to block e10s.
+          // Update the checkbox to reflect the pref state.
+          e10sCheckbox.checked = true;
+        } else {
+          e10sCheckbox.disabled = true;
+          e10sCheckbox.label += " (disabled: " + e10sBlockedReason.data + ")";
+        }
+      }
+    }
+
+    // If E10S is blocked because of safe mode, we want the checkbox to be
+    // enabled
 #endif
 
 #ifdef MOZ_DEV_EDITION
     Cu.import("resource://gre/modules/osfile.jsm");
     let uAppData = OS.Constants.Path.userApplicationDataDir;
     let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
 
     setEventListener("separateProfileMode", "command", gMainPane.separateProfileModeChange);
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -129,29 +129,29 @@ skip-if = e10s && debug
 skip-if = e10s && debug
 [browser_dbg_blackboxing-06.js]
 skip-if = e10s && debug
 [browser_dbg_breadcrumbs-access.js]
 skip-if = e10s
 [browser_dbg_break-on-dom-01.js]
 skip-if = e10s
 [browser_dbg_break-on-dom-02.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-03.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-04.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-05.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-06.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-07.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-08.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_break-on-dom-event-01.js]
 skip-if = e10s || os == "mac" || e10s # Bug 895426
 [browser_dbg_break-on-dom-event-02.js]
 skip-if = e10s
 [browser_dbg_breakpoints-actual-location.js]
 skip-if = e10s
 [browser_dbg_breakpoints-actual-location2.js]
 skip-if = e10s
@@ -305,43 +305,43 @@ skip-if = e10s
 skip-if = e10s
 [browser_dbg_pause-resume.js]
 skip-if = e10s
 [browser_dbg_pause-warning.js]
 skip-if = e10s
 [browser_dbg_paused-keybindings.js]
 skip-if = e10s
 [browser_dbg_pretty-print-01.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-02.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-03.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-04.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-05.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-06.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-07.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-08.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-09.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-10.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-11.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-12.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-13.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_pretty-print-on-paused.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_progress-listener-bug.js]
 skip-if = e10s
 [browser_dbg_reload-preferred-script-01.js]
 skip-if = e10s
 [browser_dbg_reload-preferred-script-02.js]
 skip-if = e10s
 [browser_dbg_reload-preferred-script-03.js]
 skip-if = e10s
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-02.js
@@ -4,17 +4,17 @@
 /**
  * Tests that event listeners are fetched when the events tab is selected
  * or while sources are fetched and the events tab is focused.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
       yield testFetchOnFocus();
       yield testFetchOnReloadWhenFocused();
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that event listeners are properly displayed in the view.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-04.js
@@ -4,17 +4,17 @@
 /**
  * Tests that checking/unchecking an event listener in the view correctly
  * causes the active thread to get updated with the new event breakpoints.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-05.js
@@ -5,17 +5,17 @@
  * Tests that checking/unchecking an event listener's group in the view will
  * cause the active thread to get updated with the new event breakpoints for
  * all children inside that group.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-06.js
@@ -4,17 +4,17 @@
 /**
  * Tests that the event listener states are preserved in the view after the
  * target navigates.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-07.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that system event listeners don't get duplicated in the view.
  */
 
 function test() {
-  initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger("about:blank").then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
     let gL10N = gDebugger.L10N;
 
     is(gEvents.itemCount, 0,
       "There are no events displayed in the corresponding pane yet.");
 
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-08.js
@@ -3,24 +3,25 @@
 
 /**
  * Tests that breaking on an event selects the variables view tab.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
+    let gTab = aTab;
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, ".html");
-      aDebuggee.addBodyClickEventListener();
+      yield callInTab(gTab, "addBodyClickEventListener");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
       yield ensureThreadClientState(aPanel, "resumed");
 
       is(gView.instrumentsPaneHidden, false,
         "The instruments pane should be visible.");
@@ -28,21 +29,17 @@ function test() {
         "The events tab should be selected.");
 
       let updated = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_BREAKPOINTS_UPDATED);
       EventUtils.sendMouseEvent({ type: "click" }, getItemCheckboxNode(1), gDebugger);
       yield updated;
       yield ensureThreadClientState(aPanel, "resumed");
 
       let paused = waitForCaretAndScopes(aPanel, 48);
-      // Spin the event loop before causing the debuggee to pause, to allow
-      // this function to yield first.
-      executeSoon(() => {
-        EventUtils.sendMouseEvent({ type: "click" }, aDebuggee.document.body, aDebuggee);
-      });
+      sendMouseClickToTab(gTab, content.document.body);
       yield paused;
       yield ensureThreadClientState(aPanel, "paused");
 
       is(gView.instrumentsPaneHidden, false,
         "The instruments pane should be visible.");
       is(gView.instrumentsPaneTab, "variables-tab",
         "The variables tab should be selected.");
 
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
@@ -2,23 +2,22 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that clicking the pretty print button prettifies the source.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(testSourceIsUgly)
       .then(() => {
@@ -71,14 +70,13 @@ function testSourceIsStillPretty() {
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
@@ -3,23 +3,22 @@
 
 /**
  * Make sure that right clicking and selecting the pretty print context menu
  * item prettifies the source.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gContextMenu;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gContextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(() => {
         const finished = waitForSourceShown(gPanel, "code_ugly.js");
@@ -44,14 +43,13 @@ function selectContextMenuItem() {
 
 function testSourceIsPretty() {
   ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gContextMenu = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-03.js
@@ -2,22 +2,21 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that we have the correct line selected after pretty printing.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(runCodeAndPause)
       .then(() => {
         const sourceShown = waitForSourceShown(gPanel, "code_ugly.js");
         const caretUpdated = waitForCaretUpdated(gPanel, 7);
@@ -30,23 +29,21 @@ function test() {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function runCodeAndPause() {
   const deferred = promise.defer();
   once(gDebugger.gThreadClient, "paused").then(deferred.resolve);
-  // Have to executeSoon so that we don't pause before this function returns.
-  executeSoon(gDebuggee.foo);
+  callInTab(gTab, "foo");
   return deferred.promise;
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-04.js
@@ -2,23 +2,22 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that the function searching works with pretty printed sources.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gSearchBox;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(testUglySearch)
       .then(() => {
         const finished = waitForSourceShown(gPanel, "code_ugly.js");
@@ -60,13 +59,12 @@ function testPrettyPrintedSearch() {
   });
 
   setText(gSearchBox, "@bar");
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gSearchBox = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
@@ -2,23 +2,22 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that prettifying HTML sources doesn't do anything.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_included-script.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources, gControllerSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gControllerSources = gDebugger.DebuggerController.SourceScripts;
 
     Task.spawn(function() {
       yield waitForSourceShown(gPanel, TAB_URL);
@@ -63,15 +62,14 @@ function clickPrettyPrintButton() {
 }
 
 function prepareDebugger(aPanel) {
   aPanel._view.Sources.preferredSource = TAB_URL;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
   gControllerSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
@@ -3,23 +3,22 @@
 
 /**
  * Make sure that prettifying JS sources with type errors works as expected.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_included-script.html";
 const JS_URL = EXAMPLE_URL + "code_location-changes.js";
 
-let gTab, gDebuggee, gPanel, gDebugger, gClient;
+let gTab, gPanel, gDebugger, gClient;
 let gEditor, gSources, gControllerSources, gPrettyPrinted;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gClient = gDebugger.gClient;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gControllerSources = gDebugger.DebuggerController.SourceScripts;
 
     // We can't feed javascript files with syntax errors to the debugger,
@@ -78,17 +77,16 @@ function test() {
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gClient = null;
   gEditor = null;
   gSources = null;
   gControllerSources = null;
   gPrettyPrinted = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js
@@ -1,23 +1,22 @@
 /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test basic pretty printing functionality. Would be an xpcshell test, except
 // for bug 921252.
 
-let gTab, gDebuggee, gPanel, gClient, gThreadClient, gSource;
+let gTab, gPanel, gClient, gThreadClient, gSource;
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print-2.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gClient = gPanel.panelWin.gClient;
     gThreadClient = gPanel.panelWin.DebuggerController.activeThread;
 
     findSource();
   });
 }
 
@@ -47,10 +46,10 @@ function disablePrettyPrint() {
 
 function testUgly({ error, source }) {
   ok(!error);
   ok(!source.contains("\n    "));
   closeDebuggerAndFinish(gPanel);
 }
 
 registerCleanupFunction(function() {
-  gTab = gDebuggee = gPanel = gClient = gThreadClient = gSource = null;
+  gTab = gPanel = gClient = gThreadClient = gSource = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
@@ -1,27 +1,25 @@
 /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test stepping through pretty printed sources.
 
-let gTab, gDebuggee, gPanel, gClient, gThreadClient, gSource;
+let gTab, gPanel, gClient, gThreadClient, gSource;
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print-2.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gClient = gPanel.panelWin.gClient;
     gThreadClient = gPanel.panelWin.DebuggerController.activeThread;
 
-    gDebuggee.noop = x => x;
     findSource();
   });
 }
 
 let CODE_URL;
 
 const BP_LOCATION = {
   line: 5,
@@ -42,17 +40,17 @@ function findSource() {
 
 function prettyPrintSource(source) {
   gThreadClient.source(gSource).prettyPrint(2, runCode);
 }
 
 function runCode({ error }) {
   ok(!error);
   gClient.addOneTimeListener("paused", testDbgStatement);
-  gDebuggee.main3();
+  callInTab(gTab, "main3");
 }
 
 function testDbgStatement(event, { why, frame }) {
   is(why.type, "debuggerStatement");
   const { url, line, column } = frame.where;
   is(url, CODE_URL);
   is(line, 3);
   setBreakpoint();
@@ -85,10 +83,10 @@ function testHitBreakpoint() {
     is(line, BP_LOCATION.line);
 
     resumeDebuggerThenCloseAndFinish(gPanel);
   });
   gThreadClient.resume();
 }
 
 registerCleanupFunction(function() {
-  gTab = gDebuggee = gPanel = gClient = gThreadClient = gSource = null;
+  gTab = gPanel = gClient = gThreadClient = gSource = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-09.js
@@ -1,27 +1,25 @@
 /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test pretty printing source mapped sources.
 
-var gDebuggee;
 var gClient;
 var gThreadClient;
 var gSource;
 
-let gTab, gDebuggee, gPanel, gClient, gThreadClient, gSource;
+let gTab, gPanel, gClient, gThreadClient, gSource;
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print-2.html";
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gClient = gPanel.panelWin.gClient;
     gThreadClient = gPanel.panelWin.DebuggerController.activeThread;
 
     findSource();
   });
 }
 
@@ -45,17 +43,17 @@ function findSource() {
 
 function prettyPrint() {
   gThreadClient.source(gSource).prettyPrint(2, runCode);
 }
 
 function runCode({ error }) {
   ok(!error);
   gClient.addOneTimeListener("paused", testDbgStatement);
-  gDebuggee.a();
+  callInTab(gTab, "a");
 }
 
 function testDbgStatement(event, { frame, why }) {
   is(why.type, "debuggerStatement");
   const { url, line } = frame.where;
   is(url, B_URL);
   is(line, 2);
 
@@ -80,10 +78,10 @@ function testFrame({ frames: [frame] }) 
   const { url, line } = frame.where;
   is(url, B_URL);
   is(line, 1);
 
   resumeDebuggerThenCloseAndFinish(gPanel);
 }
 
 registerCleanupFunction(function() {
-  gTab = gDebuggee = gPanel = gClient = gThreadClient = null;
+  gTab = gPanel = gClient = gThreadClient = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-10.js
@@ -3,23 +3,22 @@
 
 /**
  * Make sure that we disable the pretty print button for black boxed sources,
  * and that clicking it doesn't do anything.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(testSourceIsUgly)
       .then(toggleBlackBoxing.bind(null, gPanel))
@@ -50,14 +49,13 @@ function testSourceIsStillUgly() {
   const { source } = gSources.selectedItem.attachment;
   return gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
     ok(!text.contains("\n    "));
   });
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
@@ -2,23 +2,22 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure that pretty printing is maintained across refreshes.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceShown(gPanel, "code_ugly.js")
       .then(testSourceIsUgly)
       .then(() => {
@@ -47,14 +46,13 @@ function clickPrettyPrintButton() {
 
 function testSourceIsPretty() {
   ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-12.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-12.js
@@ -3,23 +3,22 @@
 
 /**
  * Make sure that we don't leave the pretty print button checked when we fail to
  * pretty print a source (because it isn't a JS file, for example).
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceShown(gPanel, "")
       .then(() => {
         let shown = ensureSourceIs(gPanel, TAB_URL, true)
@@ -41,14 +40,13 @@ function clickPrettyPrintButton() {
 
 function testButtonIsntChecked() {
   is(gDebugger.document.getElementById("pretty-print").checked, false,
      "The button shouldn't be checked after trying to pretty print a non-js file.");
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
@@ -4,23 +4,22 @@
 /**
  * Make sure that clicking the pretty print button prettifies the source, even
  * when the source URL does not end in ".js", but the content type is
  * JavaScript.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print-3.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     promise.all([waitForSourceShown(gPanel, "code_ugly-8"),
                  waitForEditorLocationSet(gPanel)])
       .then(testSourceIsUgly)
@@ -74,14 +73,13 @@ function testSourceIsStillPretty() {
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-on-paused.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-on-paused.js
@@ -3,24 +3,23 @@
 
 /**
  * Test that pretty printing when the debugger is paused does not switch away
  * from the selected source.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pretty-print-on-paused.html";
 
-let gTab, gDebuggee, gPanel, gDebugger, gThreadClient, gSources;
+let gTab, gPanel, gDebugger, gThreadClient, gSources;
 
 const SECOND_SOURCE_VALUE = EXAMPLE_URL + "code_ugly-2.js";
 
 function test(){
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gThreadClient = gDebugger.gThreadClient;
     gSources = gDebugger.DebuggerView.Sources;
 
     Task.spawn(function* () {
       try {
         yield ensureSourceIs(gPanel, "code_script-switching-02.js", true);
@@ -28,19 +27,17 @@ function test(){
         yield doInterrupt(gPanel);
         yield rdpInvoke(gThreadClient, gThreadClient.setBreakpoint, {
           url: gSources.selectedValue,
           line: 6
         });
         yield doResume(gPanel);
 
         const bpHit = waitForCaretAndScopes(gPanel, 6);
-        // Get the debuggee call off this tick so that we aren't accidentally
-        // blocking the yielding of bpHit which causes a deadlock.
-        executeSoon(() => gDebuggee.secondCall());
+        callInTab(gTab, "secondCall");
         yield bpHit;
 
         info("Switch to the second source.");
         const sourceShown = waitForSourceShown(gPanel, SECOND_SOURCE_VALUE);
         gSources.selectedValue = SECOND_SOURCE_VALUE;
         yield sourceShown;
 
         info("Pretty print the source.");
@@ -54,14 +51,13 @@ function test(){
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
       }
     });
   });
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gThreadClient = null;
   gSources = null;
 });
--- a/browser/devtools/debugger/test/code_frame-script.js
+++ b/browser/devtools/debugger/test/code_frame-script.js
@@ -1,9 +1,25 @@
 "use strict";
 
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
+                          getService(Ci.mozIJSSubScriptLoader);
+
+const EventUtils = {};
+loadSubScript("chrome://marionette/content/EventUtils.js", EventUtils);
+
 dump("Frame script loaded.\n");
 
 addMessageListener("test:call", function (message) {
   dump("Calling function with name " + message.data + ".\n");
 
   XPCNativeWrapper.unwrap(content)[message.data]();
+  sendAsyncMessage("test:call");
 });
+
+addMessageListener("test:click", function (message) {
+  dump("Sending mouse click.\n");
+
+  let target = message.objects.target;
+  EventUtils.synthesizeMouseAtCenter(target, {},
+                                     target.ownerDocument.defaultView);
+});
--- a/browser/devtools/debugger/test/doc_pretty-print-2.html
+++ b/browser/devtools/debugger/test/doc_pretty-print-2.html
@@ -3,8 +3,13 @@
 <!DOCTYPE html>
 <head>
   <meta charset="utf-8"/>
   <title>Debugger Pretty Printing Test Page</title>
 </head>
 <script src="code_ugly-2.js"></script>
 <script src="code_ugly-3.js"></script>
 <script src="code_ugly-4.js"></script>
+<script>
+  function noop(x) {
+    return x;
+  }
+</script>
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -959,9 +959,18 @@ function waitForMessageFromTab(tab, name
     });
   });
 }
 
 function callInTab(tab, name) {
   info("Calling function with name " + name + " in tab.");
 
   sendMessageToTab(tab, "test:call", name);
+  waitForMessageFromTab(tab, "test:call");
 }
+
+function sendMouseClickToTab(tab, target) {
+  info("Sending mouse click to tab.");
+
+  sendMessageToTab(tab, "test:click", undefined, {
+    target: target
+  });
+}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -328,21 +328,16 @@ protected:
                                   nsIChannel * aChannel);
     virtual nsresult DoChannelLoad(nsIChannel * aChannel,
                                    nsIURILoader * aURILoader,
                                    bool aBypassClassifier);
 
     nsresult ScrollToAnchor(nsACString & curHash, nsACString & newHash,
                             uint32_t aLoadType);
 
-    // Tries to serialize a given variant using structured clone.  This only
-    // works if the variant is backed by a JSVal.
-    nsresult SerializeJSValVariant(JSContext *aCx, nsIVariant *aData,
-                                   nsAString &aResult);
-
     // Returns true if would have called FireOnLocationChange,
     // but did not because aFireOnLocationChange was false on entry.
     // In this case it is the caller's responsibility to ensure
     // FireOnLocationChange is called.
     // In all other cases false is returned.
     bool OnLoadingSite(nsIChannel * aChannel,
                          bool aFireOnLocationChange,
                          bool aAddToGlobalHistory = true);
--- a/dom/base/ImportManager.cpp
+++ b/dom/base/ImportManager.cpp
@@ -144,16 +144,17 @@ ImportLoader::Updater::UpdateMainReferre
   // This new link means we have to execute our scripts sooner...
   // Let's make sure that unblocking a loader does not trigger a script execution.
   // So we start with placing the new blockers and only then will we remove any
   // blockers.
   if (mLoader->IsBlocking()) {
     // Our import parent is changed, let's block the new one and later unblock
     // the old one.
     newMainReferrer->OwnerDoc()->ScriptLoader()->AddExecuteBlocker();
+    newMainReferrer->OwnerDoc()->BlockDOMContentLoaded();
   }
 
   if (mLoader->mDocument) {
     // Our nearest predecessor has changed. So let's add the ScriptLoader to the
     // new one if there is any. And remove it from the old one.
     nsRefPtr<ImportManager> manager = mLoader->Manager();
     nsScriptLoader* loader = mLoader->mDocument->ScriptLoader();
     ImportLoader*& pred = mLoader->mBlockingPredecessor;
@@ -163,16 +164,17 @@ ImportLoader::Updater::UpdateMainReferre
         newPred->AddBlockedScriptLoader(loader);
       }
       pred->RemoveBlockedScriptLoader(loader);
     }
   }
 
   if (mLoader->IsBlocking()) {
     mLoader->mImportParent->ScriptLoader()->RemoveExecuteBlocker();
+    mLoader->mImportParent->UnblockDOMContentLoaded();
   }
 
   // Finally update mMainReferrer to point to the newly added link.
   mLoader->mMainReferrer = aNewIdx;
   mLoader->mImportParent = newMainReferrer->OwnerDoc();
 }
 
 nsINode*
@@ -295,24 +297,26 @@ ImportLoader::ImportLoader(nsIURI* aURI,
 {
 }
 
 void
 ImportLoader::BlockScripts()
 {
   MOZ_ASSERT(!mBlockingScripts);
   mImportParent->ScriptLoader()->AddExecuteBlocker();
+  mImportParent->BlockDOMContentLoaded();
   mBlockingScripts = true;
 }
 
 void
 ImportLoader::UnblockScripts()
 {
   MOZ_ASSERT(mBlockingScripts);
   mImportParent->ScriptLoader()->RemoveExecuteBlocker();
+  mImportParent->UnblockDOMContentLoaded();
   for (uint32_t i = 0; i < mBlockedScriptLoaders.Length(); i++) {
     mBlockedScriptLoaders[i]->RemoveExecuteBlocker();
   }
   mBlockedScriptLoaders.Clear();
   mBlockingScripts = false;
 }
 
 void
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2302,17 +2302,22 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
       mChildren.RemoveChildAt(i);
       nsNodeUtils::ContentRemoved(this, content, i, previousSibling);
       content->UnbindFromTree();
     }
     mCachedRootElement = nullptr;
   }
   mInUnlinkOrDeletion = oldVal;
 
-  mRegistry = nullptr;
+  if (!mMasterDocument) {
+    // "When creating an import, use the registry of the master document."
+    // Note: at this point the mMasterDocument is already set for imports
+    // (and only for imports)
+    mRegistry = nullptr;
+  }
 
   // Reset our stylesheets
   ResetStylesheetsToURI(aURI);
 
   // Release the listener manager
   if (mListenerManager) {
     mListenerManager->Disconnect();
     mListenerManager = nullptr;
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1299,17 +1299,19 @@ public:
   virtual nsIDocument* MasterDocument()
   {
     return mMasterDocument ? mMasterDocument.get()
                            : this;
   }
 
   virtual void SetMasterDocument(nsIDocument* master)
   {
+    MOZ_ASSERT(master);
     mMasterDocument = master;
+    UseRegistryFromDocument(mMasterDocument);
   }
 
   virtual bool IsMasterDocument()
   {
     return !mMasterDocument;
   }
 
   virtual mozilla::dom::ImportManager* ImportManager()
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -306,17 +306,21 @@ nsDOMCameraControl::nsDOMCameraControl(u
     // Start the camera...
     if (haveInitialConfig) {
       rv = mCameraControl->Start(&config);
     } else {
       rv = mCameraControl->Start();
     }
 #ifdef MOZ_WIDGET_GONK
   } else {
-    rv = mCameraControl->SetConfiguration(config);
+    if (haveInitialConfig) {
+      rv = mCameraControl->SetConfiguration(config);
+    } else {
+      rv = NS_OK;
+    }
   }
 #endif
   if (NS_FAILED(rv)) {
     mListener->OnUserError(DOMCameraControlListener::kInStartCamera, rv);
   }
 }
 
 nsDOMCameraControl::~nsDOMCameraControl()
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <script>
+    order.push("AS0");
+  </script>
+  <link rel="import" href="file_blocking_DOMContentLoaded_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <script>
+    order.push("BS0");
+  </script>
+  <link rel="import" href="file_blocking_DOMContentLoaded_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <script>
+    order.push("CS0");
+  </script>
+  <link rel="import" href="file_blocking_DOMContentLoaded_D.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <script>
+    order.push("DS0");
+  </script>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/file_element_upgrade.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+</head>
+<body>
+  <x-foo></x-foo>
+  <script>
+    var prototype = Object.create(HTMLElement.prototype);
+    prototype.createdCallback = function() {
+      createdCallbackCalled = true;
+    }
+    document.registerElement('x-foo', {prototype: prototype});
+  </script>
+</body>
+</html>
--- a/dom/html/test/imports/mochitest.ini
+++ b/dom/html/test/imports/mochitest.ini
@@ -28,19 +28,28 @@ support-files =
   file_cycle_3_C.html
   file_cycle_4_A.html
   file_cycle_4_B.html
   file_cycle_4_C.html
   file_cycle_4_D.html
   file_cycle_4_E.html
   file_encoding.html
   file_simple_import.html
+  file_blocking_DOMContentLoaded_A.html
+  file_blocking_DOMContentLoaded_B.html
+  file_blocking_DOMContentLoaded_C.html
+  file_blocking_DOMContentLoaded_D.html
+  file_element_upgrade.html
+
 
 [test_cycle_1.html]
 skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
 [test_cycle_2.html]
 skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
 [test_cycle_3.html]
 skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
 [test_cycle_4.html]
 skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
+[test_blocking_DOMContentLoaded.html]
+skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
 [test_encoding.html]
 [test_defaultView.html]
+[test_element_upgrade.html]
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/test_blocking_DOMContentLoaded.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1093028
+-->
+<head>
+  <title>Test for Bug 1093028</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093028">Mozilla Bug 1093028</a>
+  <script type="text/javascript">
+    SimpleTest.waitForExplicitFinish();
+    var counter = 0;
+    var fcounter = 0;
+    var order = [];
+    function loaded() {
+      counter++;
+    }
+    function failed() {
+      fcounter++;
+    }
+  </script>
+  <link rel="import" href="file_blocking_DOMContentLoaded_A.html" onload="loaded()" onerror="failed()"></link>
+  <script type="text/javascript">
+    is(counter, 4, "Imports are loaded");
+    is(fcounter, 0, "No error in imports");
+    var expected = ["AS0","BS0","CS0","DS0"];
+    for (i in expected)
+      is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+    SimpleTest.finish();
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/test/imports/test_element_upgrade.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1081107
+-->
+<head>
+  <title>Test for Bug 1081107</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081107">Mozilla Bug 1081107</a>
+  <script type="text/javascript">
+    SimpleTest.waitForExplicitFinish();
+    var counter = 0;
+    var fcounter = 0;
+    var createdCallbackCalled = false;
+    function loaded() {
+      counter++;
+    }
+    function failed() {
+      fcounter++;
+    }
+  </script>
+  <link rel="import" href="file_element_upgrade.html" onload="loaded()" onerror="failed()"></link>
+  <script type="text/javascript">
+    is(counter, 1, "Imports are loaded");
+    is(fcounter, 0, "No error in imports");
+    ok(createdCallbackCalled, "custom element in import has been upgraded");
+    SimpleTest.finish();
+  </script>
+</body>
+</html>
--- a/dom/media/AbstractMediaDecoder.h
+++ b/dom/media/AbstractMediaDecoder.h
@@ -122,16 +122,20 @@ public:
   virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) {}
 
   // Called by Decoder/State machine to check audio offload condtions are met
   virtual bool CheckDecoderCanOffloadAudio() { return false; }
 
   // Called from HTMLMediaElement when owner document activity changes
   virtual void SetElementVisibility(bool aIsVisible) {}
 
+  // Called by some MediaDecoderReader to determine if we can rely
+  // on the resource length to limit reads.
+  virtual bool HasInitializationData() { return false; }
+
   // Stack based class to assist in notifying the frame statistics of
   // parsed and decoded frames. Use inside video demux & decode functions
   // to ensure all parsed and decoded frames are reported on all return paths.
   class AutoNotifyDecoded {
   public:
     AutoNotifyDecoded(AbstractMediaDecoder* aDecoder, uint32_t& aParsed, uint32_t& aDecoded)
       : mDecoder(aDecoder), mParsed(aParsed), mDecoded(aDecoded) {}
     ~AutoNotifyDecoded() {
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -58,53 +58,48 @@ PRLogModuleInfo* GetMediaSourceAPILog()
 #endif
 
 // Arbitrary limit.
 static const unsigned int MAX_SOURCE_BUFFERS = 16;
 
 namespace mozilla {
 
 static const char* const gMediaSourceTypes[6] = {
-// XXX: Disabled other temporarily on desktop to allow WebM testing.  For now,
-// set the developer-only media.mediasource.ignore_codecs pref to true to test
-// other codecs, and expect things to be broken.
-//
-// Disabled WebM in favour of MP4 on Firefox OS.
-#ifdef MOZ_GONK_MEDIACODEC
   "video/mp4",
   "audio/mp4",
-#else
   "video/webm",
   "audio/webm",
-#endif
-#if 0
-  "audio/mpeg",
-#endif
   nullptr
 };
 
 static nsresult
 IsTypeSupported(const nsAString& aType)
 {
   if (aType.IsEmpty()) {
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
-  if (Preferences::GetBool("media.mediasource.ignore_codecs", false)) {
-    return NS_OK;
-  }
-  // TODO: Further restrict this to formats in the spec.
   nsContentTypeParser parser(aType);
   nsAutoString mimeType;
   nsresult rv = parser.GetType(mimeType);
   if (NS_FAILED(rv)) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
   bool found = false;
   for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
     if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
+      if ((mimeType.EqualsASCII("video/mp4") ||
+           mimeType.EqualsASCII("audio/mp4")) &&
+          !Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
+        break;
+      }
+      if ((mimeType.EqualsASCII("video/webm") ||
+           mimeType.EqualsASCII("audio/webm")) &&
+          !Preferences::GetBool("media.mediasource.webm.enabled", false)) {
+        break;
+      }
       found = true;
       break;
     }
   }
   if (!found) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
   // Check aType against HTMLMediaElement list of MIME types.  Since we've
--- a/dom/media/mediasource/SourceBufferDecoder.cpp
+++ b/dom/media/mediasource/SourceBufferDecoder.cpp
@@ -114,16 +114,22 @@ SourceBufferDecoder::SetMediaEndTime(int
 }
 
 void
 SourceBufferDecoder::UpdatePlaybackPosition(int64_t aTime)
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::UpdatePlaybackPosition UNIMPLEMENTED", this);
 }
 
+bool
+SourceBufferDecoder::HasInitializationData()
+{
+  return true;
+}
+
 void
 SourceBufferDecoder::OnReadMetadataCompleted()
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::OnReadMetadataCompleted UNIMPLEMENTED", this);
 }
 
 void
 SourceBufferDecoder::NotifyWaitingForResourcesStatusChanged()
--- a/dom/media/mediasource/SourceBufferDecoder.h
+++ b/dom/media/mediasource/SourceBufferDecoder.h
@@ -55,16 +55,17 @@ public:
   virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
   virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
   virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
   virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
   virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
+  virtual bool HasInitializationData() MOZ_FINAL MOZ_OVERRIDE;
 
   // SourceBufferResource specific interface below.
 
   // Warning: this mirrors GetBuffered in MediaDecoder, but this class's base is
   // AbstractMediaDecoder, which does not supply this interface.
   nsresult GetBuffered(dom::TimeRanges* aBuffered);
 
   void SetReader(MediaDecoderReader* aReader)
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -63,16 +63,45 @@ public:
     mDecoder = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<SourceBufferDecoder> mDecoder;
 };
 
+MOZ_STACK_CLASS class DecodersToInitialize MOZ_FINAL {
+public:
+  explicit DecodersToInitialize(TrackBuffer* aOwner)
+    : mOwner(aOwner)
+  {
+  }
+
+  ~DecodersToInitialize()
+  {
+    for (size_t i = 0; i < mDecoders.Length(); i++) {
+      mOwner->QueueInitializeDecoder(mDecoders[i]);
+    }
+  }
+
+  bool NewDecoder()
+  {
+    nsRefPtr<SourceBufferDecoder> decoder = mOwner->NewDecoder();
+    if (!decoder) {
+      return false;
+    }
+    mDecoders.AppendElement(decoder);
+    return true;
+  }
+
+private:
+  TrackBuffer* mOwner;
+  nsAutoTArray<nsRefPtr<SourceBufferDecoder>,2> mDecoders;
+};
+
 void
 TrackBuffer::Shutdown()
 {
   // Finish any decoder initialization, which may add to mInitializedDecoders.
   // Shutdown waits for any pending events, which may require the monitor,
   // so we must not hold the monitor during this call.
   mParentDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
   mTaskQueue->Shutdown();
@@ -85,37 +114,38 @@ TrackBuffer::Shutdown()
   mInitializedDecoders.Clear();
   mParentDecoder = nullptr;
 }
 
 bool
 TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  DecodersToInitialize decoders(this);
   // TODO: Run more of the buffer append algorithm asynchronously.
   if (mParser->IsInitSegmentPresent(aData, aLength)) {
     MSE_DEBUG("TrackBuffer(%p)::AppendData: New initialization segment.", this);
-    if (!NewDecoder()) {
+    if (!decoders.NewDecoder()) {
       return false;
     }
   } else if (!mParser->HasInitData()) {
     MSE_DEBUG("TrackBuffer(%p)::AppendData: Non-init segment appended during initialization.", this);
     return false;
   }
 
   int64_t start, end;
   if (mParser->ParseStartAndEndTimestamps(aData, aLength, start, end)) {
     if (mParser->IsMediaSegmentPresent(aData, aLength) &&
         !mParser->TimestampsFuzzyEqual(start, mLastEndTimestamp)) {
       MSE_DEBUG("TrackBuffer(%p)::AppendData: Data last=[%lld, %lld] overlaps [%lld, %lld]",
                 this, mLastStartTimestamp, mLastEndTimestamp, start, end);
 
       // This data is earlier in the timeline than data we have already
       // processed, so we must create a new decoder to handle the decoding.
-      if (!NewDecoder()) {
+      if (!decoders.NewDecoder()) {
         return false;
       }
       MSE_DEBUG("TrackBuffer(%p)::AppendData: Decoder marked as initialized.", this);
       const nsTArray<uint8_t>& initData = mParser->InitData();
       AppendDataToCurrentResource(initData.Elements(), initData.Length());
       mLastStartTimestamp = start;
     }
     mLastEndTimestamp = end;
@@ -213,37 +243,37 @@ TrackBuffer::Buffered(dom::TimeRanges* a
       highestEndTime = std::max(highestEndTime, r->GetEndTime());
       aRanges->Union(r);
     }
   }
 
   return highestEndTime;
 }
 
-bool
+already_AddRefed<SourceBufferDecoder>
 TrackBuffer::NewDecoder()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mParentDecoder);
 
   DiscardDecoder();
 
   nsRefPtr<SourceBufferDecoder> decoder = mParentDecoder->CreateSubDecoder(mType);
   if (!decoder) {
-    return false;
+    return nullptr;
   }
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   mCurrentDecoder = decoder;
   mDecoders.AppendElement(decoder);
 
   mLastStartTimestamp = 0;
   mLastEndTimestamp = 0;
 
   decoder->SetTaskQueue(mTaskQueue);
-  return QueueInitializeDecoder(decoder);
+  return decoder.forget();
 }
 
 bool
 TrackBuffer::QueueInitializeDecoder(SourceBufferDecoder* aDecoder)
 {
   RefPtr<nsIRunnable> task =
     NS_NewRunnableMethodWithArg<SourceBufferDecoder*>(this,
                                                       &TrackBuffer::InitializeDecoder,
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -77,22 +77,25 @@ public:
   nsresult SetCDMProxy(CDMProxy* aProxy);
 #endif
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif
 
 private:
+  friend class DecodersToInitialize;
   ~TrackBuffer();
 
-  // Create a new decoder, set mCurrentDecoder to the new decoder, and queue
-  // the decoder for initialization.  The decoder is not considered
-  // initialized until it is added to mDecoders.
-  bool NewDecoder();
+  // Create a new decoder, set mCurrentDecoder to the new decoder and
+  // returns it. The new decoder must be queued using QueueInitializeDecoder
+  // for initialization.
+  // The decoder is not considered initialized until it is added to
+  // mInitializedDecoders.
+  already_AddRefed<SourceBufferDecoder> NewDecoder();
 
   // Helper for AppendData, ensures NotifyDataArrived is called whenever
   // data is appended to the current decoder's SourceBufferResource.
   bool AppendDataToCurrentResource(const uint8_t* aData, uint32_t aLength);
 
   // Queue execution of InitializeDecoder on mTaskQueue.
   bool QueueInitializeDecoder(SourceBufferDecoder* aDecoder);
 
--- a/dom/media/test/test_eme_canvas_blocked.html
+++ b/dom/media/test/test_eme_canvas_blocked.html
@@ -44,17 +44,17 @@ function startTest(test, token)
 }
 
 function beginTest() {
   manager.runTests(gEMETests, startTest);
 }
 
 var prefs = [
   [ "media.mediasource.enabled", true ],
-  [ "media.mediasource.ignore_codecs", true ],
+  [ "media.mediasource.mp4.enabled", true ],
 ];
 
 if (/Linux/.test(navigator.userAgent) ||
     !document.createElement('video').canPlayType("video/mp4")) {
   // XXX remove once we have mp4 PlatformDecoderModules on all platforms.
   prefs.push([ "media.fragmented-mp4.exposed", true ]);
   prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
 }
--- a/dom/media/test/test_eme_playback.html
+++ b/dom/media/test/test_eme_playback.html
@@ -105,17 +105,17 @@ function testIsTypeSupported()
 
 function beginTest() {
   testIsTypeSupported();
   manager.runTests(gEMETests, startTest);
 }
 
 var prefs = [
   [ "media.mediasource.enabled", true ],
-  [ "media.mediasource.ignore_codecs", true ],
+  [ "media.mediasource.mp4.enabled", true ],
 ];
 
 if (/Linux/.test(navigator.userAgent) ||
     !document.createElement('video').canPlayType("video/mp4")) {
   // XXX remove once we have mp4 PlatformDecoderModules on all platforms.
   prefs.push([ "media.fragmented-mp4.exposed", true ]);
   prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
 }
--- a/dom/media/test/test_eme_stream_capture_blocked.html
+++ b/dom/media/test/test_eme_stream_capture_blocked.html
@@ -79,17 +79,17 @@ function startTest(test, token)
 }
 
 function beginTest() {
   manager.runTests(gEMETests, startTest);
 }
 
 var prefs = [
   [ "media.mediasource.enabled", true ],
-  [ "media.mediasource.ignore_codecs", true ],
+  [ "media.mediasource.mp4.enabled", true ],
 ];
 
 if (/Linux/.test(navigator.userAgent) ||
     !document.createElement('video').canPlayType("video/mp4")) {
   // XXX remove once we have mp4 PlatformDecoderModules on all platforms.
   prefs.push([ "media.fragmented-mp4.exposed", true ]);
   prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
 }
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -282,17 +282,18 @@ nsresult WebMReader::ReadMetadata(MediaI
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   nestegg_io io;
   io.read = webm_read;
   io.seek = webm_seek;
   io.tell = webm_tell;
   io.userdata = mDecoder;
-  int64_t maxOffset = -1;
+  int64_t maxOffset = mDecoder->HasInitializationData() ?
+    mDecoder->GetResource()->GetLength() : -1;
   int r = nestegg_init(&mContext, io, &webm_log, maxOffset);
   if (r == -1) {
     return NS_ERROR_FAILURE;
   }
 
   uint64_t duration = 0;
   r = nestegg_duration(mContext, &duration);
   if (r == 0) {
--- a/dom/settings/SettingsRequestManager.jsm
+++ b/dom/settings/SettingsRequestManager.jsm
@@ -393,16 +393,38 @@ let SettingsRequestManager = {
       let key = keys[i];
       if (DEBUG) debug("key: " + key + ", val: " + JSON.stringify(data.settings[key]) + ", type: " + typeof(data.settings[key]));
       lock.queuedSets[key] = data.settings[key];
     }
 
     return this.queueTaskReturn(aTask, {task: aTask});
   },
 
+  startRunning: function(aLockID) {
+    let lock = this.lockInfo[aLockID];
+
+    if (!lock) {
+      if (DEBUG) debug("Lock no longer alive, cannot start running");
+      return;
+    }
+
+    lock.consumable = true;
+    if (aLockID == this.settingsLockQueue[0] || this.settingsLockQueue.length == 0) {
+      // If a lock is currently at the head of the queue, run all tasks for
+      // it.
+      if (DEBUG) debug("Start running tasks for " + aLockID);
+      this.queueConsume();
+    } else {
+      // If a lock isn't at the head of the queue, but requests to be run,
+      // simply mark it as consumable, which means it will automatically run
+      // once it comes to the head of the queue.
+      if (DEBUG) debug("Queuing tasks for " + aLockID + " while waiting for " + this.settingsLockQueue[0]);
+    }
+  },
+
   queueConsume: function() {
     if (this.settingsLockQueue.length > 0 && this.lockInfo[this.settingsLockQueue[0]].consumable) {
       Services.tm.currentThread.dispatch(SettingsRequestManager.consumeTasks.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
     }
   },
 
   finalizeSets: function(aTask) {
     let data = aTask.data;
@@ -766,47 +788,48 @@ let SettingsRequestManager = {
     return false;
   },
 
   enqueueForceFinalize: function(lock, principal) {
     if (!this.hasLockFinalizeTask(lock)) {
       if (DEBUG) debug("Alive lock has pending tasks: " + lock.lockID);
       this.queueTask("finalize", {lockID: lock.lockID}, principal).then(
         function() {
-          if (DEBUG) debug("Alive lock " + lockId + " succeeded to force-finalize");
+          if (DEBUG) debug("Alive lock " + lock.lockID + " succeeded to force-finalize");
         },
         function(error) {
-          if (DEBUG) debug("Alive lock " + lockId + " failed to force-finalize due to error: " + error);
+          if (DEBUG) debug("Alive lock " + lock.lockID + " failed to force-finalize due to error: " + error);
         }
       );
+      // Finalize is considered a task running situation, but it also needs to
+      // queue a task.
+      this.startRunning(lock.lockID);
     }
   },
 
   forceFinalizeChildLocksNonOOP: function(windowId) {
     if (DEBUG) debug("Forcing finalize on child locks, non OOP");
 
     for (let lockId of Object.keys(this.lockInfo)) {
       let lock = this.lockInfo[lockId];
       if (lock.windowID === windowId) {
         let principal = this.mmPrincipals.get(lock._mm);
         this.enqueueForceFinalize(lock, principal);
       }
     }
   },
 
-  forceFinalizeChildLocksOOP: function(aMsgMgr, aPrincipal) {
+  forceFinalizeChildLocksOOP: function(aMsgMgr) {
     if (DEBUG) debug("Forcing finalize on child locks, OOP");
 
-    let msgMgrPrincipal = this.mmPrincipals.get(aMsgMgr);
-    this.removeObserver(aMsgMgr);
-
     for (let lockId of Object.keys(this.lockInfo)) {
       let lock = this.lockInfo[lockId];
-      if (lock._mm === aMsgMgr && msgMgrPrincipal === aPrincipal) {
-        this.enqueueForceFinalize(lock, aPrincipal);
+      if (lock._mm === aMsgMgr) {
+        let principal = this.mmPrincipals.get(lock._mm);
+        this.enqueueForceFinalize(lock, principal);
       }
     }
   },
 
   receiveMessage: function(aMessage) {
     if (DEBUG) debug("receiveMessage " + aMessage.name + ": " + JSON.stringify(aMessage.data));
 
     let msg = aMessage.data;
@@ -854,17 +877,18 @@ let SettingsRequestManager = {
         }
       default:
       break;
     }
 
     switch (aMessage.name) {
       case "child-process-shutdown":
         if (DEBUG) debug("Child process shutdown received.");
-        this.forceFinalizeChildLocksOOP(mm, aMessage.principal);
+        this.forceFinalizeChildLocksOOP(mm);
+        this.removeObserver(mm);
         break;
       case "Settings:RegisterForMessages":
         if (!SettingsPermissions.hasSomeReadPermission(aMessage.principal)) {
           Cu.reportError("Settings message " + aMessage.name +
                          " from a content process with no 'settings-api-read' privileges.");
           aMessage.target.assertPermission("message-manager-no-read-kill");
           return;
         }
@@ -948,28 +972,17 @@ let SettingsRequestManager = {
             lockID: msg.lockID,
             errorMsg: error
           });
         });
       // YES THIS IS SUPPOSED TO FALL THROUGH. Finalize is considered a task
       // running situation, but it also needs to queue a task.
       case "Settings:Run":
         if (DEBUG) debug("Received Run");
-        this.lockInfo[msg.lockID].consumable = true;
-        if (msg.lockID == this.settingsLockQueue[0] || this.settingsLockQueue.length == 0) {
-          // If a lock is currently at the head of the queue, run all tasks for
-          // it.
-          if (DEBUG) debug("Running tasks for " + msg.lockID);
-          this.queueConsume();
-        } else {
-          // If a lock isn't at the head of the queue, but requests to be run,
-          // simply mark it as consumable, which means it will automatically run
-          // once it comes to the head of the queue.
-          if (DEBUG) debug("Queuing tasks for " + msg.lockID + " while waiting for " + this.settingsLockQueue[0]);
-        }
+        this.startRunning(msg.lockID);
         break;
       default:
         if (DEBUG) debug("Wrong message: " + aMessage.name);
     }
   }
 };
 
 SettingsRequestManager.init();
--- a/dom/svg/SVGSwitchElement.cpp
+++ b/dom/svg/SVGSwitchElement.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGSwitchElement.h"
 
-#include "nsSVGEffects.h"
+#include "nsLayoutUtils.h"
 #include "nsSVGUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/SVGSwitchElementBinding.h"
 
 class nsIFrame;
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Switch)
 
@@ -57,17 +57,19 @@ SVGSwitchElement::MaybeInvalidate()
   nsIContent *newActiveChild = FindActiveChild();
 
   if (newActiveChild == mActiveChild) {
     return;
   }
 
   nsIFrame *frame = GetPrimaryFrame();
   if (frame) {
-    nsSVGEffects::InvalidateRenderingObservers(frame);
+    nsLayoutUtils::PostRestyleEvent(
+      this, nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(frame);
   }
 
   mActiveChild = newActiveChild;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
--- a/dom/webidl/DOMError.webidl
+++ b/dom/webidl/DOMError.webidl
@@ -5,16 +5,17 @@
  *
  * The origin of this IDL file is
  * http://dom.spec.whatwg.org/#domerror
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Constructor(DOMString name, optional DOMString message = "")]
+[Constructor(DOMString name, optional DOMString message = ""),
+ Exposed=(Window,System)]
 interface DOMError {
   [Constant]
   readonly attribute DOMString name;
 
   [Constant]
   readonly attribute DOMString message;
 };
--- a/dom/webidl/TextDecoder.webidl
+++ b/dom/webidl/TextDecoder.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * http://encoding.spec.whatwg.org/#interface-textdecoder
  *
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 [Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options),
- Exposed=(Window,Worker)]
+ Exposed=(Window,Worker,System)]
 interface TextDecoder {
   [Constant]
   readonly attribute DOMString encoding;
   [Throws]
   DOMString decode();
   [Throws]
   DOMString decode(ArrayBufferView input, optional TextDecodeOptions options);
 };
--- a/dom/webidl/TextEncoder.webidl
+++ b/dom/webidl/TextEncoder.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * http://encoding.spec.whatwg.org/#interface-textencoder
  *
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 [Constructor(optional DOMString utfLabel = "utf-8"),
- Exposed=(Window,Worker)]
+ Exposed=(Window,Worker,System)]
 interface TextEncoder {
   [Constant]
   readonly attribute DOMString encoding;
   [Throws]
   Uint8Array encode(optional DOMString input = "", optional TextEncodeOptions options);
 };
 
 dictionary TextEncodeOptions {
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -176,26 +176,16 @@ RuntimeService* gRuntimeService = nullpt
 
 // Only true during the call to Init.
 bool gRuntimeServiceDuringInit = false;
 
 #ifdef ENABLE_TESTS
 bool gTestPBackground = false;
 #endif // ENABLE_TESTS
 
-enum {
-  ID_Worker = 0,
-  ID_ChromeWorker,
-  ID_Event,
-  ID_MessageEvent,
-  ID_ErrorEvent,
-
-  ID_COUNT
-};
-
 class LiteralRebindingCString : public nsDependentCString
 {
 public:
   template<int N>
   void RebindLiteral(const char (&aStr)[N])
   {
     Rebind(aStr, N-1);
   }
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -63,16 +63,36 @@ AppendToString(std::stringstream& aStrea
   aStream << pfx;
   aStream << nsPrintfCString(
     "rgba(%d, %d, %d, %g)",
     uint8_t(c.r*255.0), uint8_t(c.g*255.0), uint8_t(c.b*255.0), c.a).get();
   aStream << sfx;
 }
 
 void
+AppendToString(std::stringstream& aStream, const nsPoint& p,
+               const char* pfx, const char* sfx)
+{
+  aStream << pfx;
+  aStream << nsPrintfCString("(x=%d, y=%d)", p.x, p.y).get();
+  aStream << sfx;
+}
+
+void
+AppendToString(std::stringstream& aStream, const nsRect& r,
+               const char* pfx, const char* sfx)
+{
+  aStream << pfx;
+  aStream << nsPrintfCString(
+    "(x=%d, y=%d, w=%d, h=%d)",
+    r.x, r.y, r.width, r.height).get();
+  aStream << sfx;
+}
+
+void
 AppendToString(std::stringstream& aStream, const nsIntPoint& p,
                const char* pfx, const char* sfx)
 {
   aStream << pfx;
   aStream << nsPrintfCString("(x=%d, y=%d)", p.x, p.y).get();
   aStream << sfx;
 }
 
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -41,16 +41,24 @@ void
 AppendToString(std::stringstream& aStream, FrameMetrics::ViewID n,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, const gfxRGBA& c,
                const char* pfx="", const char* sfx="");
 
 void
+AppendToString(std::stringstream& aStream, const nsPoint& p,
+               const char* pfx="", const char* sfx="");
+
+void
+AppendToString(std::stringstream& aStream, const nsRect& r,
+               const char* pfx="", const char* sfx="");
+
+void
 AppendToString(std::stringstream& aStream, const nsIntPoint& p,
                const char* pfx="", const char* sfx="");
 
 template<class T>
 void
 AppendToString(std::stringstream& aStream, const mozilla::gfx::PointTyped<T>& p,
                const char* pfx="", const char* sfx="")
 {
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -564,17 +564,17 @@ class Type
         }
         MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid Type");
     }
 
     Type simdToScalarType() const {
         MOZ_ASSERT(isSimd());
         switch (which_) {
           case Int32x4:
-            return Int;
+            return Signed;
           case Float32x4:
             return Float;
           // Scalar types
           case Double:
           case DoubleLit:
           case MaybeDouble:
           case Float:
           case MaybeFloat:
@@ -4315,17 +4315,17 @@ CheckDotAccess(FunctionCompiler &f, Pars
 
     ModuleCompiler &m = f.m();
     PropertyName *field = DotMember(elem);
 
     SimdLane lane;
     JSAtomState &names = m.cx()->names();
 
     if (field == names.signMask) {
-        *type = Type::Int;
+        *type = Type::Signed;
         *def = f.extractSignMask(baseDef);
         return true;
     }
 
     if (field == names.x)
         lane = LaneX;
     else if (field == names.y)
         lane = LaneY;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3057,26 +3057,29 @@ frontend::EmitFunctionScript(ExclusiveCo
             return false;
 
         if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
             return false;
 
         if (bce->sc->asFunctionBox()->isStarGenerator() && !EmitFinishIteratorResult(cx, bce, true))
             return false;
 
+        if (Emit1(cx, bce, JSOP_SETRVAL) < 0)
+            return false;
+
         ScopeCoordinate sc;
         // We know that .generator is on the top scope chain node, as we are
         // at the function end.
         sc.setHops(0);
         MOZ_ALWAYS_TRUE(LookupAliasedNameSlot(bce, bce->script, cx->names().dotGenerator, &sc));
         if (!EmitAliasedVarOp(cx, JSOP_GETALIASEDVAR, sc, DontCheckLexical, bce))
             return false;
 
         // No need to check for finally blocks, etc as in EmitReturn.
-        if (Emit1(cx, bce, JSOP_FINALYIELD) < 0)
+        if (Emit1(cx, bce, JSOP_FINALYIELDRVAL) < 0)
             return false;
     }
 
     /*
      * Always end the script with a JSOP_RETRVAL. Some other parts of the codebase
      * depend on this opcode, e.g. js_InternalInterpret.
      */
     if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
@@ -5593,16 +5596,19 @@ EmitYield(ExclusiveContext *cx, Bytecode
     }
 
     if (!EmitTree(cx, bce, pn->pn_right))
         return false;
 
     if (Emit1(cx, bce, pn->getOp()) < 0)
         return false;
 
+    if (pn->getOp() == JSOP_INITIALYIELD && Emit1(cx, bce, JSOP_POP) < 0)
+        return false;
+
     return true;
 }
 
 static bool
 EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter, ParseNode *gen)
 {
     MOZ_ASSERT(bce->sc->isFunctionBox());
     MOZ_ASSERT(bce->sc->asFunctionBox()->isStarGenerator());
--- a/js/src/jit-test/tests/asm.js/testSIMD.js
+++ b/js/src/jit-test/tests/asm.js/testSIMD.js
@@ -31,43 +31,26 @@ function assertEqX4(real, expected, asse
     assertFunc(real.x, expected[0]);
     assertFunc(real.y, expected[1]);
     assertFunc(real.z, expected[2]);
     assertFunc(real.w, expected[3]);
 }
 
 function CheckI4(header, code, expected) {
     // code needs to contain a local called x
-    header = USE_ASM + I32 + header;
-    var lanes = ['x', 'y', 'z', 'w'];
-    for (var i = 0; i < 4; ++i) {
-        var lane = lanes[i];
-        assertEq(asmLink(asmCompile('glob', header + ';function f() {' + code + ';return x.' + lane + '|0} return f'), this)(), expected[i]);
-    }
+    header = USE_ASM + I32 + F32 + header;
+    var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return i4(x)} return f'), this)();
+    assertEqX4(observed, expected);
 }
 
 function CheckF4(header, code, expected) {
     // code needs to contain a local called x
-    var lanes = ['x', 'y', 'z', 'w'];
     header = USE_ASM + F32 + header;
-    for (var i = 0; i < 4; ++i) {
-        var lane = lanes[i];
-        assertEq(asmLink(asmCompile('glob', header + ';function f() {' + code + ';return +x.' + lane + '} return f'), this)(), Math.fround(expected[i]));
-    }
-}
-
-function CheckF4Comp(header, code, expected) {
-    // code needs to contain a local called x containing the result of the
-    // comparison
-    var lanes = ['x', 'y', 'z', 'w'];
-    header = USE_ASM + F32 + I32 + header;
-    for (var i = 0; i < 4; ++i) {
-        var lane = lanes[i];
-        assertEq(asmLink(asmCompile('glob', header + ';function f() {' + code + ';return x.' + lane + '|0} return f'), this)(), expected[i]);
-    }
+    var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return f4(x)} return f'), this)();
+    assertEqX4(observed, expected.map(Math.fround));
 }
 
 try {
 
 // 1. Constructors
 
 // 1.1 Compilation
 assertAsmTypeFail('glob', USE_ASM + "var i4 = int32x4               ; return {}") ;
@@ -160,31 +143,44 @@ assertEqX4(asmLink(asmCompile('glob', US
 // 1.3.2 Reading values out of lanes
 assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return x.y | 0;} return f");
 assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return (x + x).y | 0;} return f");
 assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1.; return x.y | 0;} return f");
 assertAsmTypeFail('glob', USE_ASM + "var f32=glob.Math.fround;" + I32 + "function f() {var x=f32(1); return x.y | 0;} return f");
 
 assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return x.length|0;} return f");
 assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4).y; return x|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return (x.x > (1>>>0)) | 0;} return f");
 
-CheckI4('', 'var x=i4(0,0,0,0)', [0,0,0,0]);
-CheckI4('', 'var x=i4(1,2,3,4)', [1,2,3,4]);
-CheckI4('', 'var x=i4(' + INT32_MIN + ',2,3,' + INT32_MAX + ')', [INT32_MIN,2,3,INT32_MAX]);
-CheckI4('', 'var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
-CheckI4('', 'var a=1; var b=i4(9,8,7,6); var c=13.37; var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
-CheckI4('', 'var y=i4(5,6,7,8); var x=i4(1,2,3,4)', [1,2,3,4]);
+function CheckSignMask(innerBody, coerceBefore, coerceAfter, expected) {
+    var lanes = ['x', 'y', 'z', 'w'];
+    for (var i = 0; i < lanes.length; i++) {
+        var lane = lanes[i];
+        var laneCheckCode = `"use asm"; var i4=glob.SIMD.int32x4; var f4=glob.SIMD.float32x4; function f() {${innerBody}; return ${coerceBefore}x.${lane}${coerceAfter} } return f;`;
+        assertEq(asmLink(asmCompile('glob', laneCheckCode), this)(), expected[i]);
+    }
+}
+function CheckSignMaskI4(innerBody, expected) { return CheckSignMask(innerBody, '', '|0', expected); }
+function CheckSignMaskF4(innerBody, expected) { return CheckSignMask(innerBody, '+', '', expected.map(Math.fround)); }
 
-CheckF4('', 'var x=f4(' + INT32_MAX + ', 2, 3, ' + INT32_MIN + ')', [INT32_MAX, 2, 3, INT32_MIN]);
-CheckF4('', 'var x=f4(' + (INT32_MAX + 1) + ', 2, 3, 4)', [INT32_MAX + 1, 2, 3, 4]);
-CheckF4('', 'var x=f4(1.3, 2.4, 3.5, 98.76)', [1.3, 2.4, 3.5, 98.76]);
-CheckF4('', 'var x=f4(13.37, 2., 3., -0)', [13.37, 2, 3, -0]);
+CheckSignMaskI4('var x=i4(0,0,0,0);', [0,0,0,0]);
+CheckSignMaskI4('var x=i4(1,2,3,4);', [1,2,3,4]);
+CheckSignMaskI4('var x=i4(' + INT32_MIN + ',2,3,' + INT32_MAX + ')', [INT32_MIN,2,3,INT32_MAX]);
+CheckSignMaskI4('var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
+CheckSignMaskI4('var a=1; var b=i4(9,8,7,6); var c=13.37; var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
+CheckSignMaskI4('var y=i4(5,6,7,8); var x=i4(1,2,3,4)', [1,2,3,4]);
+
+CheckSignMaskF4('var x=f4(' + INT32_MAX + ', 2, 3, ' + INT32_MIN + ')', [INT32_MAX, 2, 3, INT32_MIN]);
+CheckSignMaskF4('var x=f4(' + (INT32_MAX + 1) + ', 2, 3, 4)', [INT32_MAX + 1, 2, 3, 4]);
+CheckSignMaskF4('var x=f4(1.3, 2.4, 3.5, 98.76)', [1.3, 2.4, 3.5, 98.76]);
+CheckSignMaskF4('var x=f4(13.37, 2., 3., -0)', [13.37, 2, 3, -0]);
 
 // signMask
 assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); var y=0.0; y=x.signMask;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return (x.signMask > (1>>>0)) | 0;} return f");
 assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {var x=i4(1,2,3,4); var y=f32(0.0); y=x.signMask;} return f");
 
 assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42; return x.signMask;} return f");
 assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42.; return x.signMask;} return f");
 assertAsmTypeFail('glob', USE_ASM + FROUND + "function f() {var x=f32(42.); return x.signMask;} return f");
 
 assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(1,2,3,4); return x.signMask | 0 } return f'), this)(), 0b0000);
 assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(0,-1, ' + INT32_MAX + ',' + INT32_MIN  + '); return x.signMask | 0 } return f'), this)(), 0b1010);
@@ -601,45 +597,45 @@ const LTF32 = 'var lt=f4.lessThan;';
 const LEF32 = 'var le=f4.lessThanOrEqual;';
 const GTF32 = 'var gt=f4.greaterThan;';
 const GEF32 = 'var ge=f4.greaterThanOrEqual;';
 const EQF32 = 'var eq=f4.equal;';
 const NEF32 = 'var ne=f4.notEqual;';
 
 assertAsmTypeFail('glob', USE_ASM + F32 + "var lt=f4.lessThan; function f() {var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=lt(x,y);} return f");
 
-CheckF4Comp(LTF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=lt(y,z)', [F, F, F, F]);
-CheckF4Comp(LTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=lt(y,z)', [T, T, T, T]);
-CheckF4Comp(LTF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=lt(y,z)', [F, T, T, F]);
-CheckF4Comp(LTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=lt(y,z);', [F, F, F, F]);
+CheckI4(LTF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=lt(y,z)', [F, F, F, F]);
+CheckI4(LTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=lt(y,z)', [T, T, T, T]);
+CheckI4(LTF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=lt(y,z)', [F, T, T, F]);
+CheckI4(LTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=lt(y,z);', [F, F, F, F]);
 
-CheckF4Comp(LEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=le(y,z)', [F, F, F, F]);
-CheckF4Comp(LEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=le(y,z)', [T, T, T, T]);
-CheckF4Comp(LEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=le(y,z)', [T, T, T, F]);
-CheckF4Comp(LEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=le(y,z);', [T, T, F, F]);
+CheckI4(LEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=le(y,z)', [F, F, F, F]);
+CheckI4(LEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=le(y,z)', [T, T, T, T]);
+CheckI4(LEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=le(y,z)', [T, T, T, F]);
+CheckI4(LEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=le(y,z);', [T, T, F, F]);
 
-CheckF4Comp(EQF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
-CheckF4Comp(EQF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
-CheckF4Comp(EQF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=eq(y,z)', [T, F, F, F]);
-CheckF4Comp(EQF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=eq(y,z);', [T, T, F, F]);
+CheckI4(EQF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
+CheckI4(EQF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
+CheckI4(EQF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=eq(y,z)', [T, F, F, F]);
+CheckI4(EQF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=eq(y,z);', [T, T, F, F]);
 
-CheckF4Comp(NEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
-CheckF4Comp(NEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
-CheckF4Comp(NEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=ne(y,z)', [F, T, T, T]);
-CheckF4Comp(NEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ne(y,z);', [F, F, T, T]);
+CheckI4(NEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
+CheckI4(NEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
+CheckI4(NEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=ne(y,z)', [F, T, T, T]);
+CheckI4(NEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ne(y,z);', [F, F, T, T]);
 
-CheckF4Comp(GTF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=gt(y,z)', [T, T, T, T]);
-CheckF4Comp(GTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=gt(y,z)', [F, F, F, F]);
-CheckF4Comp(GTF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=gt(y,z)', [F, F, F, T]);
-CheckF4Comp(GTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=gt(y,z);', [F, F, F, F]);
+CheckI4(GTF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=gt(y,z)', [T, T, T, T]);
+CheckI4(GTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=gt(y,z)', [F, F, F, F]);
+CheckI4(GTF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=gt(y,z)', [F, F, F, T]);
+CheckI4(GTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=gt(y,z);', [F, F, F, F]);
 
-CheckF4Comp(GEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=ge(y,z)', [T, T, T, T]);
-CheckF4Comp(GEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=ge(y,z)', [F, F, F, F]);
-CheckF4Comp(GEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=ge(y,z)', [T, F, F, T]);
-CheckF4Comp(GEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ge(y,z);', [T, T, F, F]);
+CheckI4(GEF32, 'var y=f4(1,2,3,4);  var z=f4(-1,1,0,2); var x=i4(0,0,0,0); x=ge(y,z)', [T, T, T, T]);
+CheckI4(GEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4);  var x=i4(0,0,0,0); x=ge(y,z)', [F, F, F, F]);
+CheckI4(GEF32, 'var y=f4(1,0,3,4);  var z=f4(1,1,7,0);  var x=i4(0,0,0,0); x=ge(y,z)', [T, F, F, T]);
+CheckI4(GEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=i4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ge(y,z);', [T, T, F, F]);
 
 // Conversions operators
 const CVTIF = 'var cvt=f4.fromInt32x4;';
 const CVTFI = 'var cvt=i4.fromFloat32x4;';
 
 assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromInt32x4; return {}");
 assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}");
 assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -351,19 +351,16 @@ class BaselineFrame
         return isNonStrictEvalFrame() && isDirectEvalFrame();
     }
     bool isNonEvalFunctionFrame() const {
         return isFunctionFrame() && !isEvalFrame();
     }
     bool isDebuggerFrame() const {
         return false;
     }
-    bool isGeneratorFrame() const {
-        return false;
-    }
 
     IonJSFrameLayout *framePrefix() const {
         uint8_t *fp = (uint8_t *)this + Size() + FramePointerOffset;
         return (IonJSFrameLayout *)fp;
     }
 
     // Methods below are used by the compiler.
     static size_t offsetOfCalleeToken() {
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -55,17 +55,17 @@ BaselineScript::BaselineScript(uint32_t 
     flags_(0)
 { }
 
 static const unsigned BASELINE_MAX_ARGS_LENGTH = 20000;
 
 static bool
 CheckFrame(InterpreterFrame *fp)
 {
-    if (fp->isGeneratorFrame()) {
+    if (fp->script()->isGenerator()) {
         JitSpew(JitSpew_BaselineAbort, "generator frame");
         return false;
     }
 
     if (fp->isDebuggerFrame()) {
         // Debugger eval-in-frame. These are likely short-running scripts so
         // don't bother compiling them for now.
         JitSpew(JitSpew_BaselineAbort, "debugger frame");
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2131,17 +2131,17 @@ IonCompile(JSContext *cx, JSScript *scri
     bool success = codegen->link(cx, builder->constraints());
 
     return success ? AbortReason_NoAbort : AbortReason_Disable;
 }
 
 static bool
 CheckFrame(BaselineFrame *frame)
 {
-    MOZ_ASSERT(!frame->isGeneratorFrame());
+    MOZ_ASSERT(!frame->script()->isGenerator());
     MOZ_ASSERT(!frame->isDebuggerFrame());
 
     // This check is to not overrun the stack.
     if (frame->isFunctionFrame()) {
         if (TooManyActualArguments(frame->numActualArgs())) {
             JitSpew(JitSpew_IonAbort, "too many actual args");
             return false;
         }
@@ -2161,16 +2161,21 @@ CheckScript(JSContext *cx, JSScript *scr
     if (script->isForEval()) {
         // Eval frames are not yet supported. Supporting this will require new
         // logic in pushBailoutFrame to deal with linking prev.
         // Additionally, JSOP_DEFVAR support will require baking in isEvalFrame().
         JitSpew(JitSpew_IonAbort, "eval script");
         return false;
     }
 
+    if (script->isGenerator()) {
+        JitSpew(JitSpew_IonAbort, "generator script");
+        return false;
+    }
+
     if (!script->compileAndGo() && !script->functionNonDelazifying()) {
         // Support non-CNG functions but not other scripts. For global scripts,
         // IonBuilder currently uses the global object as scope chain, this is
         // not valid for non-CNG code.
         JitSpew(JitSpew_IonAbort, "not compile-and-go");
         return false;
     }
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -530,34 +530,48 @@ jit::EliminateDeadResumePointOperands(MI
                 use->replaceProducer(constant);
             }
         }
     }
 
     return true;
 }
 
+// Test whether |def| would be needed if it had no uses.
+bool
+js::jit::DeadIfUnused(const MDefinition *def)
+{
+    return !def->isEffectful() && !def->isGuard() && !def->isControlInstruction() &&
+           (!def->isInstruction() || !def->toInstruction()->resumePoint());
+}
+
+// Test whether |def| may be safely discarded, due to being dead or due to being
+// located in a basic block which has itself been marked for discarding.
+bool
+js::jit::IsDiscardable(const MDefinition *def)
+{
+    return !def->hasUses() && (DeadIfUnused(def) || def->block()->isMarked());
+}
+
 // Instructions are useless if they are unused and have no side effects.
 // This pass eliminates useless instructions.
 // The graph itself is unchanged.
 bool
 jit::EliminateDeadCode(MIRGenerator *mir, MIRGraph &graph)
 {
     // Traverse in postorder so that we hit uses before definitions.
     // Traverse instruction list backwards for the same reason.
     for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
         if (mir->shouldCancel("Eliminate Dead Code (main loop)"))
             return false;
 
         // Remove unused instructions.
         for (MInstructionReverseIterator iter = block->rbegin(); iter != block->rend(); ) {
             MInstruction *inst = *iter++;
-            if (!inst->isEffectful() && !inst->resumePoint() &&
-                !inst->hasUses() && !inst->isGuard() &&
-                !inst->isControlInstruction())
+            if (js::jit::IsDiscardable(inst))
             {
                 block->discard(inst);
             } else if (!inst->isRecoveredOnBailout() && !inst->isGuard() &&
                        !inst->hasLiveDefUses() && inst->canRecoverOnBailout())
             {
                 inst->setRecoveredOnBailout();
             }
         }
--- a/js/src/jit/IonAnalysis.h
+++ b/js/src/jit/IonAnalysis.h
@@ -163,12 +163,18 @@ ConvertLinearInequality(TempAllocator &a
 bool
 AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
                                    types::TypeObject *type, HandleNativeObject baseobj,
                                    Vector<types::TypeNewScript::Initializer> *initializerList);
 
 bool
 AnalyzeArgumentsUsage(JSContext *cx, JSScript *script);
 
+bool
+DeadIfUnused(const MDefinition *def);
+
+bool
+IsDiscardable(const MDefinition *def);
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_IonAnalysis_h */
--- a/js/src/jit/ValueNumbering.cpp
+++ b/js/src/jit/ValueNumbering.cpp
@@ -132,32 +132,16 @@ ValueNumberer::VisibleValues::clear()
 bool
 ValueNumberer::VisibleValues::has(const MDefinition *def) const
 {
     Ptr p = set_.lookup(def);
     return p && *p == def;
 }
 #endif
 
-// Test whether |def| would be needed if it had no uses.
-static bool
-DeadIfUnused(const MDefinition *def)
-{
-    return !def->isEffectful() && !def->isGuard() && !def->isControlInstruction() &&
-           (!def->isInstruction() || !def->toInstruction()->resumePoint());
-}
-
-// Test whether |def| may be safely discarded, due to being dead or due to being
-// located in a basic block which has itself been marked for discarding.
-static bool
-IsDiscardable(const MDefinition *def)
-{
-    return !def->hasUses() && (DeadIfUnused(def) || def->block()->isMarked());
-}
-
 // Call MDefinition::justReplaceAllUsesWith, and add some GVN-specific asserts.
 static void
 ReplaceAllUsesWith(MDefinition *from, MDefinition *to)
 {
     MOZ_ASSERT(from != to, "GVN shouldn't try to replace a value with itself");
     MOZ_ASSERT(from->type() == to->type(), "Def replacement has different type");
     MOZ_ASSERT(!to->isDiscarded(), "GVN replaces an instruction by a removed instruction");
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4125,18 +4125,16 @@ js_DumpInterpreterFrame(JSContext *cx, I
 
         fprintf(stderr, "  flags:");
         if (i.isConstructing())
             fprintf(stderr, " constructing");
         if (!i.isJit() && i.interpFrame()->isDebuggerFrame())
             fprintf(stderr, " debugger");
         if (i.isEvalFrame())
             fprintf(stderr, " eval");
-        if (!i.isJit() && i.interpFrame()->isGeneratorFrame())
-            fprintf(stderr, " generator");
         fputc('\n', stderr);
 
         fprintf(stderr, "  scopeChain: (JSObject *) %p\n", (void *) i.scopeChain());
 
         fputc('\n', stderr);
     }
 }
 
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -283,17 +283,16 @@ IsJumpOpcode(JSOp op)
 static inline bool
 BytecodeFallsThrough(JSOp op)
 {
     switch (op) {
       case JSOP_GOTO:
       case JSOP_DEFAULT:
       case JSOP_RETURN:
       case JSOP_RETRVAL:
-      case JSOP_FINALYIELD:
       case JSOP_FINALYIELDRVAL:
       case JSOP_THROW:
       case JSOP_TABLESWITCH:
         return false;
       case JSOP_GOSUB:
         /* These fall through indirectly, after executing a 'finally'. */
         return true;
       default:
@@ -592,17 +591,16 @@ FlowsIntoNext(JSOp op)
 {
     /* JSOP_YIELD is considered to flow into the next instruction, like JSOP_CALL. */
     switch (op) {
       case JSOP_RETRVAL:
       case JSOP_RETURN:
       case JSOP_THROW:
       case JSOP_GOTO:
       case JSOP_RETSUB:
-      case JSOP_FINALYIELD:
       case JSOP_FINALYIELDRVAL:
         return false;
       default:
         return true;
     }
 }
 
 inline bool
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4740,17 +4740,17 @@ DebuggerFrame_getCallee(JSContext *cx, u
     args.rval().set(calleev);
     return true;
 }
 
 static bool
 DebuggerFrame_getGenerator(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME(cx, argc, vp, "get generator", args, thisobj, frame);
-    args.rval().setBoolean(frame.isGeneratorFrame());
+    args.rval().setBoolean(frame.script()->isGenerator());
     return true;
 }
 
 static bool
 DebuggerFrame_getConstructing(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME_ITER(cx, argc, vp, "get constructing", args, thisobj, _, iter);
     args.rval().setBoolean(iter.isFunctionFrame() && iter.isConstructing());
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -11,78 +11,74 @@
 
 #include "vm/NativeObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::types;
 
 JSObject *
-GeneratorObject::create(JSContext *cx, const InterpreterRegs &regs)
+GeneratorObject::create(JSContext *cx, AbstractFramePtr frame)
 {
-    MOZ_ASSERT(regs.stackDepth() == 0);
-    InterpreterFrame *fp = regs.fp();
+    MOZ_ASSERT(frame.script()->isGenerator());
+    MOZ_ASSERT(frame.script()->nfixed() == 0);
 
-    MOZ_ASSERT(fp->script()->isGenerator());
-    MOZ_ASSERT(fp->script()->nfixed() == 0);
-
-    Rooted<GlobalObject*> global(cx, &fp->global());
+    Rooted<GlobalObject*> global(cx, cx->global());
     RootedNativeObject obj(cx);
-    if (fp->script()->isStarGenerator()) {
+    if (frame.script()->isStarGenerator()) {
         RootedValue pval(cx);
-        RootedObject fun(cx, fp->fun());
+        RootedObject fun(cx, frame.fun());
         // FIXME: This would be faster if we could avoid doing a lookup to get
         // the prototype for the instance.  Bug 906600.
         if (!JSObject::getProperty(cx, fun, fun, cx->names().prototype, &pval))
             return nullptr;
         JSObject *proto = pval.isObject() ? &pval.toObject() : nullptr;
         if (!proto) {
             proto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
             if (!proto)
                 return nullptr;
         }
         obj = NewNativeObjectWithGivenProto(cx, &StarGeneratorObject::class_, proto, global);
     } else {
-        MOZ_ASSERT(fp->script()->isLegacyGenerator());
+        MOZ_ASSERT(frame.script()->isLegacyGenerator());
         JSObject *proto = GlobalObject::getOrCreateLegacyGeneratorObjectPrototype(cx, global);
         if (!proto)
             return nullptr;
         obj = NewNativeObjectWithGivenProto(cx, &LegacyGeneratorObject::class_, proto, global);
     }
     if (!obj)
         return nullptr;
 
-    Rooted<GeneratorObject *> genObj(cx, &obj->as<GeneratorObject>());
-
-    genObj->setCallee(fp->callee());
-    genObj->setThisValue(fp->thisValue());
-    genObj->setScopeChain(*fp->scopeChain());
-    if (fp->script()->needsArgsObj())
-        genObj->setArgsObj(fp->argsObj());
+    GeneratorObject *genObj = &obj->as<GeneratorObject>();
+    genObj->setCallee(*frame.callee());
+    genObj->setThisValue(frame.thisValue());
+    genObj->setScopeChain(*frame.scopeChain());
+    if (frame.script()->needsArgsObj())
+        genObj->setArgsObj(frame.argsObj());
     genObj->clearExpressionStack();
 
     return obj;
 }
 
 bool
-GeneratorObject::suspend(JSContext *cx, HandleObject obj, InterpreterFrame *fp, jsbytecode *pc,
+GeneratorObject::suspend(JSContext *cx, HandleObject obj, AbstractFramePtr frame, jsbytecode *pc,
                          Value *vp, unsigned nvalues, GeneratorObject::SuspendKind suspendKind)
 {
     Rooted<GeneratorObject*> genObj(cx, &obj->as<GeneratorObject>());
     MOZ_ASSERT(!genObj->hasExpressionStack());
 
     if (suspendKind == NORMAL && genObj->isClosing()) {
         MOZ_ASSERT(genObj->is<LegacyGeneratorObject>());
-        RootedValue val(cx, ObjectValue(fp->callee()));
-        js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, val, js::NullPtr());
+        RootedValue val(cx, ObjectValue(*frame.callee()));
+        js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, val, NullPtr());
         return false;
     }
 
-    genObj->setSuspendedBytecodeOffset(pc - fp->script()->code(), suspendKind == INITIAL);
-    genObj->setScopeChain(*fp->scopeChain());
+    genObj->setSuspendedBytecodeOffset(pc - frame.script()->code(), suspendKind == INITIAL);
+    genObj->setScopeChain(*frame.scopeChain());
 
     if (nvalues) {
         ArrayObject *stack = NewDenseCopiedArray(cx, nvalues, vp);
         if (!stack)
             return false;
         genObj->setExpressionStack(*stack);
     }
 
@@ -127,25 +123,22 @@ GeneratorObject::resume(JSContext *cx, I
         RootedObject array(cx, &genObj->expressionStack());
         GetElements(cx, array, len, activation.regs().sp);
         activation.regs().sp += len;
         genObj->clearExpressionStack();
     }
 
     activation.regs().pc = callee->nonLazyScript()->code() + genObj->suspendedBytecodeOffset();
 
-    // If we are resuming a JSOP_YIELD, always push on a value, even if we are
-    // raising an exception.  In the exception case, the stack needs to have
-    // something on it so that exception handling doesn't skip the catch
-    // blocks.  See TryNoteIter::settle.
-    if (!genObj->isNewborn()) {
-        activation.regs().sp++;
-        MOZ_ASSERT(activation.regs().spForStackDepth(activation.regs().stackDepth()));
-        activation.regs().sp[-1] = arg;
-    }
+    // Always push on a value, even if we are raising an exception. In the
+    // exception case, the stack needs to have something on it so that exception
+    // handling doesn't skip the catch blocks. See TryNoteIter::settle.
+    activation.regs().sp++;
+    MOZ_ASSERT(activation.regs().spForStackDepth(activation.regs().stackDepth()));
+    activation.regs().sp[-1] = arg;
 
     switch (resumeKind) {
       case NEXT:
         genObj->setRunning();
         return true;
 
       case THROW:
         cx->setPendingException(arg);
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -45,31 +45,31 @@ class GeneratorObject : public NativeObj
         if (atom == cx->names().next)
             return NEXT;
         if (atom == cx->names().throw_)
             return THROW;
         MOZ_ASSERT(atom == cx->names().close);
         return CLOSE;
     }
 
-    static JSObject *create(JSContext *cx, const InterpreterRegs &regs);
+    static JSObject *create(JSContext *cx, AbstractFramePtr frame);
 
-    static bool suspend(JSContext *cx, HandleObject obj, InterpreterFrame *fp, jsbytecode *pc,
+    static bool suspend(JSContext *cx, HandleObject obj, AbstractFramePtr frame, jsbytecode *pc,
                         Value *vp, unsigned nvalues, SuspendKind kind);
 
     static bool resume(JSContext *cx, InterpreterActivation &activation,
                        HandleObject obj, HandleValue arg, ResumeKind resumeKind);
 
-    static bool initialSuspend(JSContext *cx, HandleObject obj, InterpreterFrame *fp, jsbytecode *pc) {
-        return suspend(cx, obj, fp, pc, nullptr, 0, INITIAL);
+    static bool initialSuspend(JSContext *cx, HandleObject obj, AbstractFramePtr frame, jsbytecode *pc) {
+        return suspend(cx, obj, frame, pc, nullptr, 0, INITIAL);
     }
 
-    static bool normalSuspend(JSContext *cx, HandleObject obj, InterpreterFrame *fp, jsbytecode *pc,
+    static bool normalSuspend(JSContext *cx, HandleObject obj, AbstractFramePtr frame, jsbytecode *pc,
                               Value *vp, unsigned nvalues) {
-        return suspend(cx, obj, fp, pc, vp, nvalues, NORMAL);
+        return suspend(cx, obj, frame, pc, vp, nvalues, NORMAL);
     }
 
     static bool finalSuspend(JSContext *cx, HandleObject obj);
 
     JSFunction &callee() const {
         return getFixedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
     }
     void setCallee(JSFunction &callee) {
@@ -161,16 +161,35 @@ class GeneratorObject : public NativeObj
     void setClosed() {
         setFixedSlot(CALLEE_SLOT, NullValue());
         setFixedSlot(THIS_SLOT, NullValue());
         setFixedSlot(SCOPE_CHAIN_SLOT, NullValue());
         setFixedSlot(ARGS_OBJ_SLOT, NullValue());
         setFixedSlot(EXPRESSION_STACK_SLOT, NullValue());
         setFixedSlot(BYTECODE_OFFSET_SLOT, NullValue());
     }
+
+    static size_t offsetOfCalleeSlot() {
+        return getFixedSlotOffset(CALLEE_SLOT);
+    }
+    static size_t offsetOfThisSlot() {
+        return getFixedSlotOffset(THIS_SLOT);
+    }
+    static size_t offsetOfScopeChainSlot() {
+        return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
+    }
+    static size_t offsetOfArgsObjSlot() {
+        return getFixedSlotOffset(ARGS_OBJ_SLOT);
+    }
+    static size_t offsetOfBytecodeOffsetSlot() {
+        return getFixedSlotOffset(BYTECODE_OFFSET_SLOT);
+    }
+    static size_t offsetOfExpressionStackSlot() {
+        return getFixedSlotOffset(EXPRESSION_STACK_SLOT);
+    }
 };
 
 class LegacyGeneratorObject : public GeneratorObject
 {
   public:
     static const Class class_;
 
     static bool close(JSContext *cx, HandleObject obj);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1473,43 +1473,21 @@ Interpret(JSContext *cx, RunState &state
     RootedFunction rootFunction0(cx);
     RootedTypeObject rootType0(cx);
     RootedPropertyName rootName0(cx);
     RootedId rootId0(cx);
     RootedShape rootShape0(cx);
     RootedScript rootScript0(cx);
     DebugOnly<uint32_t> blockDepth;
 
-    if (MOZ_UNLIKELY(REGS.fp()->isGeneratorFrame())) {
-        MOZ_ASSERT(script->containsPC(REGS.pc));
-        MOZ_ASSERT(REGS.stackDepth() <= script->nslots());
-
-        /*
-         * To support generator_throw and to catch ignored exceptions,
-         * fail if cx->isExceptionPending() is true.
-         */
-        if (cx->isExceptionPending()) {
-            probes::EnterScript(cx, script, script->functionNonDelazifying(), REGS.fp());
-            goto error;
-        }
-    }
-
     /* State communicated between non-local jumps: */
     bool interpReturnOK;
 
-    if (!activation.entryFrame()->isGeneratorFrame()) {
-        if (!activation.entryFrame()->prologue(cx))
-            goto error;
-    } else {
-        if (!probes::EnterScript(cx, script, script->functionNonDelazifying(),
-                                 activation.entryFrame()))
-        {
-            goto error;
-        }
-    }
+    if (!activation.entryFrame()->prologue(cx))
+        goto error;
 
     switch (Debugger::onEnterFrame(cx, activation.entryFrame())) {
       case JSTRAP_CONTINUE:
         break;
       case JSTRAP_RETURN:
         ForcedReturn(cx, REGS);
         goto successful_return_continuation;
       case JSTRAP_THROW:
@@ -1654,16 +1632,17 @@ CASE(JSOP_UNUSED183)
 CASE(JSOP_UNUSED185)
 CASE(JSOP_UNUSED186)
 CASE(JSOP_UNUSED187)
 CASE(JSOP_UNUSED189)
 CASE(JSOP_UNUSED190)
 CASE(JSOP_UNUSED191)
 CASE(JSOP_UNUSED192)
 CASE(JSOP_UNUSED196)
+CASE(JSOP_UNUSED207)
 CASE(JSOP_UNUSED208)
 CASE(JSOP_UNUSED209)
 CASE(JSOP_UNUSED210)
 CASE(JSOP_UNUSED211)
 CASE(JSOP_UNUSED212)
 CASE(JSOP_UNUSED213)
 CASE(JSOP_UNUSED219)
 CASE(JSOP_UNUSED220)
@@ -3362,18 +3341,18 @@ CASE(JSOP_DEBUGLEAVEBLOCK)
     if (MOZ_UNLIKELY(cx->compartment()->debugMode()))
         DebugScopes::onPopBlock(cx, REGS.fp(), REGS.pc);
 }
 END_CASE(JSOP_DEBUGLEAVEBLOCK)
 
 CASE(JSOP_GENERATOR)
 {
     MOZ_ASSERT(!cx->isExceptionPending());
-    REGS.fp()->initGeneratorFrame();
-    JSObject *obj = GeneratorObject::create(cx, REGS);
+    MOZ_ASSERT(REGS.stackDepth() == 0);
+    JSObject *obj = GeneratorObject::create(cx, REGS.fp());
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_GENERATOR)
 
 CASE(JSOP_INITIALYIELD)
 {
@@ -3419,21 +3398,16 @@ CASE(JSOP_RESUME)
     bool ok = GeneratorObject::resume(cx, activation, gen, val, resumeKind);
     SET_SCRIPT(REGS.fp()->script());
     if (!ok)
         goto error;
 
     ADVANCE_AND_DISPATCH(0);
 }
 
-CASE(JSOP_FINALYIELD)
-    REGS.fp()->setReturnValue(REGS.sp[-2]);
-    REGS.sp[-2] = REGS.sp[-1];
-    REGS.sp--;
-    /* FALL THROUGH */
 CASE(JSOP_FINALYIELDRVAL)
 {
     RootedObject &gen = rootObject0;
     gen = &REGS.sp[-1].toObject();
     REGS.sp--;
 
     if (!GeneratorObject::finalSuspend(cx, gen)) {
         interpReturnOK = false;
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1563,66 +1563,58 @@ 1234567890123456789012345678901234567890
     /*
      * Pops the generator from the top of the stack, suspends it and stops
      * interpretation.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: generator =>
      */ \
-    macro(JSOP_INITIALYIELD,  202,"initialyield", NULL,   1,  1,  0,  JOF_BYTE) \
+    macro(JSOP_INITIALYIELD,  202,"initialyield", NULL,   1,  1,  1,  JOF_BYTE) \
     /*
      * Pops the generator and the return value 'rval1', stops interpretation and
      * returns 'rval1'. Pushes sent value from 'send()' onto the stack.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: rval1, gen => rval2
      */ \
     macro(JSOP_YIELD,         203,"yield",       NULL,    1,  2,  1,  JOF_BYTE) \
     /*
-     * Pops the generator and the value to yield from the stack. Then suspends
-     * and closes the generator.
-     *   Category: Statements
-     *   Type: Generator
-     *   Operands:
-     *   Stack: gen, val =>
-     */ \
-    macro(JSOP_FINALYIELD,    204,"finalyield",  NULL,    1,  2,  0,  JOF_BYTE) \
-    /*
      * Pops the generator and suspends and closes it. Yields the value in the
      * frame's return value slot.
      *   Category: Statements
      *   Type: Generator
      *   Operands:
      *   Stack: gen =>
      */ \
-    macro(JSOP_FINALYIELDRVAL,205,"finalyieldrval",NULL,  1,  1,  0,  JOF_BYTE) \
+    macro(JSOP_FINALYIELDRVAL,204,"finalyieldrval",NULL,  1,  1,  0,  JOF_BYTE) \
     /*
      * Pops the generator and argument from the stack, pushes a new generator
      * frame and resumes execution of it. Pushes the return value after the
      * generator yields.
      *   Category: Statements
      *   Type: Generator
      *   Operands: resume kind (GeneratorObject::ResumeKind)
      *   Stack: gen, val => rval
      */ \
-    macro(JSOP_RESUME,        206,"resume",      NULL,    3,  2,  1,  JOF_UINT8|JOF_INVOKE) \
+    macro(JSOP_RESUME,        205,"resume",      NULL,    3,  2,  1,  JOF_UINT8|JOF_INVOKE) \
     /*
      * Pops the top two values on the stack as 'obj' and 'v', pushes 'v' to
      * 'obj'.
      *
      * This opcode is used for Array Comprehension.
      *   Category: Literals
      *   Type: Array
      *   Operands:
      *   Stack: v, obj =>
      */ \
-    macro(JSOP_ARRAYPUSH,     207,"arraypush",   NULL,    1,  2,  0,  JOF_BYTE) \
+    macro(JSOP_ARRAYPUSH,     206,"arraypush",   NULL,    1,  2,  0,  JOF_BYTE) \
     \
+    macro(JSOP_UNUSED207,     207, "unused207",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED208,     208, "unused208",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED211,     211, "unused211",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED212,     212, "unused212",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED213,     213, "unused213",    NULL,  1,  0,  0,  JOF_BYTE) \
     /*
      * Pushes the global scope onto the stack.
--- a/js/src/vm/Probes-inl.h
+++ b/js/src/vm/Probes-inl.h
@@ -50,17 +50,17 @@ probes::EnterScript(JSContext *cx, JSScr
 #ifdef MOZ_TRACE_JSCALLS
     cx->doFunctionCallback(maybeFun, script, 1);
 #endif
 
     JSRuntime *rt = cx->runtime();
     if (rt->spsProfiler.enabled()) {
         if (!rt->spsProfiler.enter(script, maybeFun))
             return false;
-        MOZ_ASSERT_IF(!fp->isGeneratorFrame(), !fp->hasPushedSPSFrame());
+        MOZ_ASSERT_IF(!fp->script()->isGenerator(), !fp->hasPushedSPSFrame());
         fp->setPushedSPSFrame();
     }
 
     return true;
 }
 
 inline void
 probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun, bool popSPSFrame)
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -524,24 +524,16 @@ inline bool
 AbstractFramePtr::useNewType() const
 {
     if (isInterpreterFrame())
         return asInterpreterFrame()->useNewType();
     return false;
 }
 
 inline bool
-AbstractFramePtr::isGeneratorFrame() const
-{
-    if (isInterpreterFrame())
-        return asInterpreterFrame()->isGeneratorFrame();
-    return false;
-}
-
-inline bool
 AbstractFramePtr::isFunctionFrame() const
 {
     if (isInterpreterFrame())
         return asInterpreterFrame()->isFunctionFrame();
     if (isBaselineFrame())
         return asBaselineFrame()->isFunctionFrame();
     return asRematerializedFrame()->isFunctionFrame();
 }
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -181,17 +181,16 @@ InterpreterFrame::initFunctionScopeObjec
     return true;
 }
 
 bool
 InterpreterFrame::prologue(JSContext *cx)
 {
     RootedScript script(cx, this->script());
 
-    MOZ_ASSERT(!isGeneratorFrame());
     MOZ_ASSERT(cx->interpreterRegs().pc == script->code());
 
     if (isEvalFrame()) {
         if (script->strict()) {
             CallObject *callobj = CallObject::createForStrictEval(cx, this);
             if (!callobj)
                 return false;
             pushOnScopeChain(*callobj);
@@ -846,32 +845,16 @@ FrameIter::isNonEvalFunctionFrame() cons
       case JIT:
         return !isEvalFrame() && isFunctionFrame();
       case ASMJS:
         return true;
     }
     MOZ_CRASH("Unexpected state");
 }
 
-bool
-FrameIter::isGeneratorFrame() const
-{
-    switch (data_.state_) {
-      case DONE:
-        break;
-      case INTERP:
-        return interpFrame()->isGeneratorFrame();
-      case JIT:
-        return false;
-      case ASMJS:
-        return false;
-    }
-    MOZ_CRASH("Unexpected state");
-}
-
 JSAtom *
 FrameIter::functionDisplayAtom() const
 {
     MOZ_ASSERT(isNonEvalFunctionFrame());
 
     switch (data_.state_) {
       case DONE:
         break;
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -176,17 +176,16 @@ class AbstractFramePtr
     inline JSObject *scopeChain() const;
     inline CallObject &callObj() const;
     inline bool initFunctionScopeObjects(JSContext *cx);
     inline void pushOnScopeChain(ScopeObject &scope);
 
     inline JSCompartment *compartment() const;
 
     inline bool hasCallObj() const;
-    inline bool isGeneratorFrame() const;
     inline bool isFunctionFrame() const;
     inline bool isGlobalFrame() const;
     inline bool isEvalFrame() const;
     inline bool isDebuggerFrame() const;
 
     inline JSScript *script() const;
     inline JSFunction *fun() const;
     inline JSFunction *maybeFun() const;
@@ -238,17 +237,17 @@ class NullFramePtr : public AbstractFram
     { }
 };
 
 /*****************************************************************************/
 
 /* Flags specified for a frame as it is constructed. */
 enum InitialFrameFlags {
     INITIAL_NONE           =          0,
-    INITIAL_CONSTRUCT      =       0x20, /* == InterpreterFrame::CONSTRUCTING, asserted below */
+    INITIAL_CONSTRUCT      =       0x10, /* == InterpreterFrame::CONSTRUCTING, asserted below */
 };
 
 enum ExecuteType {
     EXECUTE_GLOBAL         =        0x1, /* == InterpreterFrame::GLOBAL */
     EXECUTE_DIRECT_EVAL    =        0x4, /* == InterpreterFrame::EVAL */
     EXECUTE_INDIRECT_EVAL  =        0x5, /* == InterpreterFrame::GLOBAL | EVAL */
     EXECUTE_DEBUG          =        0xc, /* == InterpreterFrame::EVAL | DEBUGGER */
     EXECUTE_DEBUG_GLOBAL   =        0xd  /* == InterpreterFrame::EVAL | DEBUGGER | GLOBAL */
@@ -277,20 +276,19 @@ class InterpreterFrame
          * - If evalInFramePrev_ is set, then this frame was created for an
          *   "eval in frame" call, which can push a successor to any live
          *   frame; so its logical "prev" frame is not necessarily the
          *   previous frame in memory. Iteration should treat
          *   evalInFramePrev_ as this frame's previous frame.
          */
         DEBUGGER           =        0x8,
 
-        GENERATOR          =       0x10,  /* frame is associated with a generator */
-        CONSTRUCTING       =       0x20,  /* frame is for a constructor invocation */
+        CONSTRUCTING       =       0x10,  /* frame is for a constructor invocation */
 
-        /* (0x40 and 0x80 are unused) */
+        /* (0x20, 0x40 and 0x80 are unused) */
 
         /* Function prologue state */
         HAS_CALL_OBJ       =      0x100,  /* CallObject created for heavyweight fun */
         HAS_ARGS_OBJ       =      0x200,  /* ArgumentsObject created for needsArgsObj script */
 
         /* Lazy frame initialization */
         HAS_RVAL           =      0x800,  /* frame has rval_ set */
         HAS_SCOPECHAIN     =     0x1000,  /* frame has scopeChain_ set */
@@ -753,44 +751,20 @@ class InterpreterFrame
         markReturnValue();
     }
 
     void clearReturnValue() {
         rval_.setUndefined();
         markReturnValue();
     }
 
-    /*
-     * A "generator" frame is a function frame associated with a generator.
-     * Since generators are not executed LIFO, the VM copies a single abstract
-     * generator frame back and forth between the LIFO VM stack (when the
-     * generator is active) and a snapshot stored in JSGenerator (when the
-     * generator is inactive). A generator frame is comprised of an
-     * InterpreterFrame structure and the values that make up the arguments,
-     * locals, and expression stack. The layout in the JSGenerator snapshot
-     * matches the layout on the stack (see the "VM stack layout" comment
-     * above).
-     */
-
-    bool isGeneratorFrame() const {
-        bool ret = flags_ & GENERATOR;
-        MOZ_ASSERT_IF(ret, isNonEvalFunctionFrame());
-        return ret;
-    }
-
-    void initGeneratorFrame() const {
-        MOZ_ASSERT(!isGeneratorFrame());
+    void resumeGeneratorFrame(JSObject *scopeChain) {
+        MOZ_ASSERT(script()->isGenerator());
         MOZ_ASSERT(isNonEvalFunctionFrame());
-        flags_ |= GENERATOR;
-    }
-
-    void resumeGeneratorFrame(HandleObject scopeChain) {
-        MOZ_ASSERT(!isGeneratorFrame());
-        MOZ_ASSERT(isNonEvalFunctionFrame());
-        flags_ |= GENERATOR | HAS_CALL_OBJ | HAS_SCOPECHAIN;
+        flags_ |= HAS_CALL_OBJ | HAS_SCOPECHAIN;
         scopeChain_ = scopeChain;
     }
 
     /*
      * Other flags
      */
 
     InitialFrameFlags initialFlags() const {
@@ -1579,17 +1553,16 @@ class FrameIter
     bool isAsmJS() const { MOZ_ASSERT(!done()); return data_.state_ == ASMJS; }
     inline bool isIon() const;
     inline bool isBaseline() const;
 
     bool isFunctionFrame() const;
     bool isGlobalFrame() const;
     bool isEvalFrame() const;
     bool isNonEvalFunctionFrame() const;
-    bool isGeneratorFrame() const;
     bool hasArgs() const { return isNonEvalFunctionFrame(); }
 
     ScriptSource *scriptSource() const;
     const char *scriptFilename() const;
     const char16_t *scriptDisplayURL() const;
     unsigned computeLine(uint32_t *column = nullptr) const;
     JSAtom *functionDisplayAtom() const;
     bool mutedErrors() const;
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -29,17 +29,17 @@ namespace js {
  *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
  *
  * === GREETINGS, FELLOW SUBTRAHEND INCREMENTER! ===
  * For the time being, please increment the subtrahend by 2 each time it
  * changes, because we have two flavors of bytecode: with JSOP_SYMBOL (in
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 192;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 194;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND
 #ifdef JS_HAS_SYMBOLS
                                                            + 1
 #endif
                                                               ));
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -18,19 +18,16 @@
 #include "nsDOMJSUtils.h"
 
 #include "WrapperFactory.h"
 #include "AccessCheck.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/TextDecoderBinding.h"
-#include "mozilla/dom/TextEncoderBinding.h"
-#include "mozilla/dom/DOMErrorBinding.h"
 
 #include "nsDOMMutationObserver.h"
 #include "nsICycleCollectorListener.h"
 #include "nsThread.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsScriptSecurityManager.h"
@@ -432,27 +429,16 @@ InitGlobalObject(JSContext* aJSContext, 
         bool isSystem = nsContentUtils::IsSystemPrincipal(prin);
         if (isSystem)
             JS::CompartmentOptionsRef(aGlobal).extraWarningsOverride().set(true);
     }
 
     // Stuff coming through this path always ends up as a DOM global.
     MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL);
 
-    // Init WebIDL binding constructors wanted on all XPConnect globals.
-    //
-    // XXX Please do not add any additional classes here without the approval of
-    //     the XPConnect module owner.
-    if (!PromiseBinding::GetConstructorObject(aJSContext, aGlobal) ||
-        !TextDecoderBinding::GetConstructorObject(aJSContext, aGlobal) ||
-        !TextEncoderBinding::GetConstructorObject(aJSContext, aGlobal) ||
-        !DOMErrorBinding::GetConstructorObject(aJSContext, aGlobal)) {
-        return UnexpectedFailure(false);
-    }
-
     if (!(aFlags & nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK))
         JS_FireOnNewGlobalObject(aJSContext, aGlobal);
 
     return true;
 }
 
 } // namespace xpc
 
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -11,16 +11,22 @@
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "nsPrintfCString.h"
 #include "mozilla/dom/Element.h"
 #include "nsRegion.h"
 #include "nsDeviceContext.h"
 #include "nsIFrame.h"
 #include <algorithm>
+#include "LayersLogging.h"
+
+// If debugging this code you may wish to enable this logging, and also
+// uncomment the DumpFrameTree call near the bottom of the file.
+#define PET_LOG(...)
+// #define PET_LOG(...) printf_stderr("PET: " __VA_ARGS__);
 
 namespace mozilla {
 
 /*
  * The basic goal of FindFrameTargetedByInputEvent() is to find a good
  * target element that can respond to mouse events. Both mouse events and touch
  * events are targeted at this element. Note that even for touch events, we
  * check responsiveness to mouse events. We assume Web authors
@@ -313,54 +319,60 @@ GetClosest(nsIFrame* aRoot, const nsPoin
            nsIFrame* aRestrictToDescendants, nsTArray<nsIFrame*>& aCandidates)
 {
   nsIFrame* bestTarget = nullptr;
   // Lower is better; distance is in appunits
   float bestDistance = 1e6f;
   nsRegion exposedRegion(aTargetRect);
   for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
     nsIFrame* f = aCandidates[i];
+    PET_LOG("Checking candidate %p\n", f);
 
     bool preservesAxisAlignedRectangles = false;
     nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
         nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
     nsRegion region;
     region.And(exposedRegion, borderBox);
 
     if (region.IsEmpty()) {
+      PET_LOG("  candidate %p had empty hit region\n", f);
       continue;
     }
 
     if (preservesAxisAlignedRectangles) {
       // Subtract from the exposed region if we have a transform that won't make
       // the bounds include a bunch of area that we don't actually cover.
       SubtractFromExposedRegion(&exposedRegion, region);
     }
 
-    if (!IsElementClickable(f)) {
+    if (!IsElementClickable(f, nsGkAtoms::body)) {
+      PET_LOG("  candidate %p was not clickable\n", f);
       continue;
     }
     // If our current closest frame is a descendant of 'f', skip 'f' (prefer
     // the nested frame).
     if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
+      PET_LOG("  candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
       continue;
     }
     if (!nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
+      PET_LOG("  candidate %p was not descendant of restrictroot %p\n", f, aRestrictToDescendants);
       continue;
     }
 
     // distance is in appunits
     float distance = ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
     nsIContent* content = f->GetContent();
     if (content && content->IsElement() &&
         content->AsElement()->State().HasState(
                                         EventStates(NS_EVENT_STATE_VISITED))) {
       distance *= aPrefs->mVisitedWeight / 100.0f;
     }
     if (distance < bestDistance) {
+      PET_LOG("  candidate %p is the new best\n", f);
       bestDistance = distance;
       bestTarget = f;
     }
   }
   return bestTarget;
 }
 
 nsIFrame*
@@ -368,53 +380,67 @@ FindFrameTargetedByInputEvent(WidgetGUIE
                               nsIFrame* aRootFrame,
                               const nsPoint& aPointRelativeToRootFrame,
                               uint32_t aFlags)
 {
   uint32_t flags = (aFlags & INPUT_IGNORE_ROOT_SCROLL_FRAME) ?
      nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME : 0;
   nsIFrame* target =
     nsLayoutUtils::GetFrameForPoint(aRootFrame, aPointRelativeToRootFrame, flags);
+  PET_LOG("Found initial target %p for event class %s point %s relative to root frame %p\n",
+    target, (aEvent->mClass == eMouseEventClass ? "mouse" :
+             (aEvent->mClass == eTouchEventClass ? "touch" : "other")),
+    mozilla::layers::Stringify(aPointRelativeToRootFrame).c_str(), aRootFrame);
 
   const EventRadiusPrefs* prefs = GetPrefsFor(aEvent->mClass);
   if (!prefs || !prefs->mEnabled || (target && IsElementClickable(target, nsGkAtoms::body))) {
+    PET_LOG("Retargeting disabled or target %p is clickable\n", target);
     return target;
   }
 
   // Do not modify targeting for actual mouse hardware; only for mouse
   // events generated by touch-screen hardware.
   if (aEvent->mClass == eMouseEventClass &&
       prefs->mTouchOnly &&
       aEvent->AsMouseEvent()->inputSource !=
         nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
+    PET_LOG("Mouse input event is not from a touch source\n");
     return target;
   }
 
   // If the exact target is non-null, only consider candidate targets in the same
   // document as the exact target. Otherwise, if an ancestor document has
   // a mouse event handler for example, targets that are !IsElementClickable can
   // never be targeted --- something nsSubDocumentFrame in an ancestor document
   // would be targeted instead.
   nsIFrame* restrictToDescendants = target ?
     target->PresContext()->PresShell()->GetRootFrame() : aRootFrame;
 
   nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame,
                                     restrictToDescendants, prefs, aFlags);
+  PET_LOG("Expanded point to target rect %s\n",
+    mozilla::layers::Stringify(targetRect).c_str());
   nsAutoTArray<nsIFrame*,8> candidates;
   nsresult rv = nsLayoutUtils::GetFramesForArea(aRootFrame, targetRect, candidates, flags);
   if (NS_FAILED(rv)) {
     return target;
   }
 
   nsIFrame* closestClickable =
     GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
                restrictToDescendants, candidates);
   if (closestClickable) {
     target = closestClickable;
   }
+  PET_LOG("Final target is %p\n", target);
+
+  // Uncomment this to dump the frame tree to help with debugging.
+  // Note that dumping the frame tree at the top of the function may flood
+  // logcat on Android devices and cause the PET_LOGs to get dropped.
+  // aRootFrame->DumpFrameTree();
 
   if (!target || !prefs->mRepositionEventCoords) {
     // No repositioning required for this event
     return target;
   }
 
   // Take the point relative to the root frame, make it relative to the target,
   // clamp it to the bounds, and then make it relative to the root frame again.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1127,17 +1127,17 @@ ScrollFrameHelper::ThumbMoved(nsScrollba
                               nscoord aOldPos,
                               nscoord aNewPos)
 {
   MOZ_ASSERT(aScrollbar != nullptr);
   bool isHorizontal = aScrollbar->IsHorizontal();
   nsPoint current = GetScrollPosition();
   nsPoint dest = current;
   if (isHorizontal) {
-    dest.x = aNewPos;
+    dest.x = IsLTR() ? aNewPos : aNewPos - GetScrollRange().width;
   } else {
     dest.y = aNewPos;
   }
   nsRect allowedRange = GetOnePixelRangeAroundPoint(dest, isHorizontal);
 
   // Don't try to scroll if we're already at an acceptable place.
   // Don't call Contains here since Contains returns false when the point is
   // on the bottom or right edge of the rectangle.
--- a/layout/svg/SVGFEContainerFrame.cpp
+++ b/layout/svg/SVGFEContainerFrame.cpp
@@ -96,14 +96,16 @@ SVGFEContainerFrame::GetType() const
 
 nsresult
 SVGFEContainerFrame::AttributeChanged(int32_t  aNameSpaceID,
                                       nsIAtom* aAttribute,
                                       int32_t  aModType)
 {
   nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+               "Observers observe the filter, so that's what we must invalidate");
+    nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return SVGFEContainerFrameBase::AttributeChanged(aNameSpaceID,
                                                      aAttribute, aModType);
 }
--- a/layout/svg/SVGFEImageFrame.cpp
+++ b/layout/svg/SVGFEImageFrame.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Keep in (case-insensitive) order:
+#include "nsContainerFrame.h"
 #include "nsContentUtils.h"
 #include "nsFrame.h"
 #include "nsGkAtoms.h"
 #include "nsLiteralString.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilters.h"
 #include "mozilla/dom/SVGFEImageElement.h"
 
@@ -117,17 +118,19 @@ SVGFEImageFrame::GetType() const
 
 nsresult
 SVGFEImageFrame::AttributeChanged(int32_t  aNameSpaceID,
                                   nsIAtom* aAttribute,
                                   int32_t  aModType)
 {
   SVGFEImageElement *element = static_cast<SVGFEImageElement*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+               "Observers observe the filter, so that's what we must invalidate");
+    nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
   if (aNameSpaceID == kNameSpaceID_XLink &&
       aAttribute == nsGkAtoms::href) {
 
     // Prevent setting image.src by exiting early
     if (nsContentUtils::IsImageSrcSetDisabled()) {
       return NS_OK;
     }
@@ -135,10 +138,10 @@ SVGFEImageFrame::AttributeChanged(int32_
     if (element->mStringAttributes[SVGFEImageElement::HREF].IsExplicitlySet()) {
       element->LoadSVGImage(true, true);
     } else {
       element->CancelImageRequests(true);
     }
   }
 
   return SVGFEImageFrameBase::AttributeChanged(aNameSpaceID,
-                                                 aAttribute, aModType);
+                                               aAttribute, aModType);
 }
--- a/layout/svg/SVGFELeafFrame.cpp
+++ b/layout/svg/SVGFELeafFrame.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Keep in (case-insensitive) order:
+#include "nsContainerFrame.h"
 #include "nsFrame.h"
 #include "nsGkAtoms.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilters.h"
 
 typedef nsFrame SVGFELeafFrameBase;
 
 /*
@@ -94,14 +95,16 @@ SVGFELeafFrame::GetType() const
 
 nsresult
 SVGFELeafFrame::AttributeChanged(int32_t  aNameSpaceID,
                                  nsIAtom* aAttribute,
                                  int32_t  aModType)
 {
   nsSVGFE *element = static_cast<nsSVGFE*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+               "Observers observe the filter, so that's what we must invalidate");
+    nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return SVGFELeafFrameBase::AttributeChanged(aNameSpaceID,
-                                                aAttribute, aModType);
+                                              aAttribute, aModType);
 }
--- a/layout/svg/SVGFEUnstyledLeafFrame.cpp
+++ b/layout/svg/SVGFEUnstyledLeafFrame.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Keep in (case-insensitive) order:
+#include "nsContainerFrame.h"
 #include "nsFrame.h"
 #include "nsGkAtoms.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilters.h"
 
 typedef nsFrame SVGFEUnstyledLeafFrameBase;
 
 class SVGFEUnstyledLeafFrame : public SVGFEUnstyledLeafFrameBase
@@ -21,18 +22,18 @@ protected:
   {
     AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
   }
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
-                              const nsRect&           aDirtyRect,
-                              const nsDisplayListSet& aLists) MOZ_OVERRIDE {}
+                                const nsRect&           aDirtyRect,
+                                const nsDisplayListSet& aLists) MOZ_OVERRIDE {}
 
   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   {
     return SVGFEUnstyledLeafFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
@@ -74,14 +75,16 @@ SVGFEUnstyledLeafFrame::GetType() const
 
 nsresult
 SVGFEUnstyledLeafFrame::AttributeChanged(int32_t  aNameSpaceID,
                                          nsIAtom* aAttribute,
                                          int32_t  aModType)
 {
   SVGFEUnstyledElement *element = static_cast<SVGFEUnstyledElement*>(mContent);
   if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    MOZ_ASSERT(GetParent()->GetParent()->GetType() == nsGkAtoms::svgFilterFrame,
+               "Observers observe the filter, so that's what we must invalidate");
+    nsSVGEffects::InvalidateDirectRenderingObservers(GetParent()->GetParent());
   }
 
   return SVGFEUnstyledLeafFrameBase::AttributeChanged(aNameSpaceID,
                                                         aAttribute, aModType);
 }
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3319,17 +3319,19 @@ SVGTextFrame::ReflowSVGNonDisplayText()
   // We had a style change, so we mark this frame as dirty so that the next
   // time it is painted, we reflow the anonymous block frame.
   AddStateBits(NS_FRAME_IS_DIRTY);
 
   // We also need to call InvalidateRenderingObservers, so that if the <text>
   // element is within a <mask>, say, the element referencing the <mask> will
   // be updated, which will then cause this SVGTextFrame to be painted and
   // in doing so cause the anonymous block frame to be reflowed.
-  nsSVGEffects::InvalidateRenderingObservers(this);
+  nsLayoutUtils::PostRestyleEvent(
+    mContent->AsElement(), nsRestyleHint(0),
+    nsChangeHint_InvalidateRenderingObservers);
 
   // Finally, we need to actually reflow the anonymous block frame and update
   // mPositions, in case we are being reflowed immediately after a DOM
   // mutation that needs frame reconstruction.
   MaybeReflowAnonymousBlockChild();
   UpdateGlyphPositioning();
 }
 
@@ -5190,17 +5192,19 @@ SVGTextFrame::ScheduleReflowSVG()
     nsSVGUtils::ScheduleReflowSVG(this);
   }
 }
 
 void
 SVGTextFrame::NotifyGlyphMetricsChange()
 {
   AddStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
-  nsSVGEffects::InvalidateRenderingObservers(this);
+  nsLayoutUtils::PostRestyleEvent(
+    mContent->AsElement(), nsRestyleHint(0),
+    nsChangeHint_InvalidateRenderingObservers);
   ScheduleReflowSVG();
 }
 
 void
 SVGTextFrame::UpdateGlyphPositioning()
 {
   nsIFrame* kid = GetFirstPrincipalChild();
   if (!kid) {
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -310,17 +310,17 @@ nsSVGClipPathFrame::AttributeChanged(int
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::transform) {
       nsSVGEffects::InvalidateDirectRenderingObservers(this);
       nsSVGUtils::NotifyChildrenOfSVGChange(this,
                                             nsISVGChildFrame::TRANSFORM_CHANGED);
     }
     if (aAttribute == nsGkAtoms::clipPathUnits) {
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsSVGEffects::InvalidateDirectRenderingObservers(this);
     }
   }
 
   return nsSVGClipPathFrameBase::AttributeChanged(aNameSpaceID,
                                                   aAttribute, aModType);
 }
 
 void
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -223,17 +223,19 @@ void
 nsSVGRenderingObserverProperty::DoUpdate()
 {
   nsSVGIDRenderingObserver::DoUpdate();
 
   nsIFrame* frame = mFrameReference.Get();
   if (frame && frame->IsFrameOfType(nsIFrame::eSVG)) {
     // Changes should propagate out to things that might be observing
     // the referencing frame or its ancestors.
-    nsSVGEffects::InvalidateRenderingObservers(frame);
+    nsLayoutUtils::PostRestyleEvent(
+      frame->GetContent()->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
   }
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGFilterReference)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGFilterReference)
 
 NS_IMPL_CYCLE_COLLECTION(nsSVGFilterReference, mElement)
 
@@ -311,26 +313,26 @@ nsSVGFilterChainObserver::IsInObserverLi
 
 void
 nsSVGFilterProperty::DoUpdate()
 {
   nsIFrame* frame = mFrameReference.Get();
   if (!frame)
     return;
 
+  // Repaint asynchronously in case the filter frame is being torn down
+  nsChangeHint changeHint =
+    nsChangeHint(nsChangeHint_RepaintFrame);
+
   if (frame && frame->IsFrameOfType(nsIFrame::eSVG)) {
     // Changes should propagate out to things that might be observing
     // the referencing frame or its ancestors.
-    nsSVGEffects::InvalidateRenderingObservers(frame);
+    NS_UpdateHint(changeHint, nsChangeHint_InvalidateRenderingObservers);
   }
 
-  // Repaint asynchronously in case the filter frame is being torn down
-  nsChangeHint changeHint =
-    nsChangeHint(nsChangeHint_RepaintFrame);
-
   // Don't need to request UpdateOverflow if we're being reflowed.
   if (!(frame->GetStateBits() & NS_FRAME_IN_REFLOW)) {
     NS_UpdateHint(changeHint, nsChangeHint_UpdateOverflow);
   }
   frame->PresContext()->RestyleManager()->PostRestyleEvent(
     frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
@@ -346,19 +348,19 @@ nsSVGMarkerProperty::DoUpdate()
   NS_ASSERTION(frame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
 
   // Repaint asynchronously in case the marker frame is being torn down
   nsChangeHint changeHint =
     nsChangeHint(nsChangeHint_RepaintFrame);
 
   // Don't need to request ReflowFrame if we're being reflowed.
   if (!(frame->GetStateBits() & NS_FRAME_IN_REFLOW)) {
+    NS_UpdateHint(changeHint, nsChangeHint_InvalidateRenderingObservers);
     // XXXjwatt: We need to unify SVG into standard reflow so we can just use
     // nsChangeHint_NeedReflow | nsChangeHint_NeedDirtyReflow here.
-    nsSVGEffects::InvalidateRenderingObservers(frame);
     // XXXSDL KILL THIS!!!
     nsSVGUtils::ScheduleReflowSVG(frame);
   }
   frame->PresContext()->RestyleManager()->PostRestyleEvent(
     frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
 bool
@@ -418,17 +420,19 @@ nsSVGPaintingProperty::DoUpdate()
 {
   nsSVGRenderingObserverProperty::DoUpdate();
 
   nsIFrame* frame = mFrameReference.Get();
   if (!frame)
     return;
 
   if (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
-    nsSVGEffects::InvalidateRenderingObservers(frame);
+    nsLayoutUtils::PostRestyleEvent(
+      frame->GetContent()->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     frame->InvalidateFrameSubtree();
   } else {
     InvalidateAllContinuations(frame);
   }
 }
 
 static nsSVGRenderingObserver *
 CreateMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, bool aReferenceImage)
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -86,35 +86,41 @@ nsSVGForeignObjectFrame::GetType() const
 nsresult
 nsSVGForeignObjectFrame::AttributeChanged(int32_t  aNameSpaceID,
                                           nsIAtom *aAttribute,
                                           int32_t  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::width ||
         aAttribute == nsGkAtoms::height) {
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        mContent->AsElement(), nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
       // XXXjwatt: why mark intrinsic widths dirty? can't we just use eResize?
       RequestReflow(nsIPresShell::eStyleChange);
     } else if (aAttribute == nsGkAtoms::x ||
                aAttribute == nsGkAtoms::y) {
       // make sure our cached transform matrix gets (lazily) updated
       mCanvasTM = nullptr;
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        mContent->AsElement(), nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
     } else if (aAttribute == nsGkAtoms::transform) {
       // We don't invalidate for transform changes (the layers code does that).
       // Also note that SVGTransformableElement::GetAttributeChangeHint will
       // return nsChangeHint_UpdateOverflow for "transform" attribute changes
       // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
       mCanvasTM = nullptr;
     } else if (aAttribute == nsGkAtoms::viewBox ||
                aAttribute == nsGkAtoms::preserveAspectRatio) {
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        mContent->AsElement(), nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
     }
   }
 
   return NS_OK;
 }
 
 void
 nsSVGForeignObjectFrame::Reflow(nsPresContext*           aPresContext,
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -186,17 +186,19 @@ nsSVGImageFrame::AttributeChanged(int32_
                                   nsIAtom*        aAttribute,
                                   int32_t         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::x ||
         aAttribute == nsGkAtoms::y ||
         aAttribute == nsGkAtoms::width ||
         aAttribute == nsGkAtoms::height) {
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        mContent->AsElement(), nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
       return NS_OK;
     }
     else if (aAttribute == nsGkAtoms::preserveAspectRatio) {
       // We don't paint the content of the image using display lists, therefore
       // we have to invalidate for this children-only transform changes since
       // there is no layer tree to notice that the transform changed and
       // recomposite.
@@ -579,30 +581,36 @@ nsSVGImageListener::nsSVGImageListener(n
 NS_IMETHODIMP
 nsSVGImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
 {
   if (!mFrame)
     return NS_ERROR_FAILURE;
 
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     mFrame->InvalidateFrame();
-    nsSVGEffects::InvalidateRenderingObservers(mFrame);
+    nsLayoutUtils::PostRestyleEvent(
+      mFrame->GetContent()->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(mFrame);
   }
 
   if (aType == imgINotificationObserver::FRAME_UPDATE) {
     // No new dimensions, so we don't need to call
     // nsSVGUtils::InvalidateAndScheduleBoundsUpdate.
-    nsSVGEffects::InvalidateRenderingObservers(mFrame);
+    nsLayoutUtils::PostRestyleEvent(
+      mFrame->GetContent()->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     mFrame->InvalidateFrame();
   }
 
   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
     // Called once the resource's dimensions have been obtained.
     aRequest->GetImage(getter_AddRefs(mFrame->mImageContainer));
     mFrame->InvalidateFrame();
-    nsSVGEffects::InvalidateRenderingObservers(mFrame);
+    nsLayoutUtils::PostRestyleEvent(
+      mFrame->GetContent()->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(mFrame);
   }
 
   return NS_OK;
 }
 
--- a/layout/svg/nsSVGInnerSVGFrame.cpp
+++ b/layout/svg/nsSVGInnerSVGFrame.cpp
@@ -7,17 +7,16 @@
 #include "nsSVGInnerSVGFrame.h"
 
 // Keep others in (case-insensitive) order:
 #include "gfx2DGlue.h"
 #include "gfxContext.h"
 #include "nsIFrame.h"
 #include "nsISVGChildFrame.h"
 #include "nsSVGContainerFrame.h"
-#include "nsSVGEffects.h"
 #include "nsSVGIntegrationUtils.h"
 #include "mozilla/dom/SVGSVGElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 nsIFrame*
@@ -192,17 +191,19 @@ nsSVGInnerSVGFrame::AttributeChanged(int
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       !(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
 
     SVGSVGElement* content = static_cast<SVGSVGElement*>(mContent);
 
     if (aAttribute == nsGkAtoms::width ||
         aAttribute == nsGkAtoms::height) {
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        mContent->AsElement(), nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
 
       if (content->HasViewBoxOrSyntheticViewBox()) {
         // make sure our cached transform matrix gets (lazily) updated
         mCanvasTM = nullptr;
         content->ChildrenOnlyTransformChanged();
         nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED);
       } else {
@@ -227,17 +228,19 @@ nsSVGInnerSVGFrame::AttributeChanged(int
                   TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED : TRANSFORM_CHANGED);
 
       // We don't invalidate for transform changes (the layers code does that).
       // Also note that SVGTransformableElement::GetAttributeChangeHint will
       // return nsChangeHint_UpdateOverflow for "transform" attribute changes
       // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
 
       if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) {
-        nsSVGEffects::InvalidateRenderingObservers(this);
+        nsLayoutUtils::PostRestyleEvent(
+          mContent->AsElement(), nsRestyleHint(0),
+          nsChangeHint_InvalidateRenderingObservers);
         nsSVGUtils::ScheduleReflowSVG(this);
       } else if (aAttribute == nsGkAtoms::viewBox ||
                  (aAttribute == nsGkAtoms::preserveAspectRatio &&
                   content->HasViewBoxOrSyntheticViewBox())) {
         content->ChildrenOnlyTransformChanged();
         // SchedulePaint sets a global state flag so we only need to call it once
         // (on ourself is fine), not once on each child (despite bug 828240).
         SchedulePaint();
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -134,17 +134,19 @@ nsSVGPathGeometryFrame::AttributeChanged
   // We don't invalidate for transform changes (the layers code does that).
   // Also note that SVGTransformableElement::GetAttributeChangeHint will
   // return nsChangeHint_UpdateOverflow for "transform" attribute changes
   // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
 
   if (aNameSpaceID == kNameSpaceID_None &&
       (static_cast<nsSVGPathGeometryElement*>
                   (mContent)->AttributeDefinesGeometry(aAttribute))) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    nsLayoutUtils::PostRestyleEvent(
+      mContent->AsElement(), nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(this);
   }
   return NS_OK;
 }
 
 /* virtual */ void
 nsSVGPathGeometryFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
--- a/layout/svg/nsSVGStopFrame.cpp
+++ b/layout/svg/nsSVGStopFrame.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Keep in (case-insensitive) order:
+#include "nsContainerFrame.h"
 #include "nsFrame.h"
 #include "nsGkAtoms.h"
 #include "nsStyleContext.h"
 #include "nsSVGEffects.h"
 
 // This is a very simple frame whose only purpose is to capture style change
 // events and propagate them to the parent.  Most of the heavy lifting is done
 // within the nsSVGGradientFrame, which is the parent for this frame
@@ -92,17 +93,20 @@ nsSVGStopFrame::GetType() const
 
 nsresult
 nsSVGStopFrame::AttributeChanged(int32_t         aNameSpaceID,
                                  nsIAtom*        aAttribute,
                                  int32_t         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::offset) {
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    MOZ_ASSERT(GetParent()->GetType() == nsGkAtoms::svgLinearGradientFrame ||
+               GetParent()->GetType() == nsGkAtoms::svgRadialGradientFrame,
+               "Observers observe the gradient, so that's what we must invalidate");
+    nsSVGEffects::InvalidateDirectRenderingObservers(GetParent());
   }
 
   return nsSVGStopFrameBase::AttributeChanged(aNameSpaceID,
                                               aAttribute, aModType);
 }
 
 // -------------------------------------------------------------------------
 // Public functions
--- a/layout/svg/nsSVGUseFrame.cpp
+++ b/layout/svg/nsSVGUseFrame.cpp
@@ -119,39 +119,45 @@ nsSVGUseFrame::AttributeChanged(int32_t 
 {
   SVGUseElement *useElement = static_cast<SVGUseElement*>(mContent);
 
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::x ||
         aAttribute == nsGkAtoms::y) {
       // make sure our cached transform matrix gets (lazily) updated
       mCanvasTM = nullptr;
-      nsSVGEffects::InvalidateRenderingObservers(this);
+      nsLayoutUtils::PostRestyleEvent(
+        useElement, nsRestyleHint(0),
+        nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
       nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED);
     } else if (aAttribute == nsGkAtoms::width ||
                aAttribute == nsGkAtoms::height) {
       bool invalidate = false;
       if (mHasValidDimensions != useElement->HasValidDimensions()) {
         mHasValidDimensions = !mHasValidDimensions;
         invalidate = true;
       }
       if (useElement->OurWidthAndHeightAreUsed()) {
         invalidate = true;
         useElement->SyncWidthOrHeight(aAttribute);
       }
       if (invalidate) {
-        nsSVGEffects::InvalidateRenderingObservers(this);
+        nsLayoutUtils::PostRestyleEvent(
+          useElement, nsRestyleHint(0),
+          nsChangeHint_InvalidateRenderingObservers);
         nsSVGUtils::ScheduleReflowSVG(this);
       }
     }
   } else if (aNameSpaceID == kNameSpaceID_XLink &&
              aAttribute == nsGkAtoms::href) {
     // we're changing our nature, clear out the clone information
-    nsSVGEffects::InvalidateRenderingObservers(this);
+    nsLayoutUtils::PostRestyleEvent(
+      useElement, nsRestyleHint(0),
+      nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(this);
     useElement->mOriginal = nullptr;
     useElement->UnlinkSource();
     useElement->TriggerReclone();
   }
 
   return nsSVGUseFrameBase::AttributeChanged(aNameSpaceID,
                                              aAttribute, aModType);
@@ -229,17 +235,18 @@ nsSVGUseFrame::NotifySVGChanged(uint32_t
 // nsIAnonymousContentCreator methods:
 
 nsresult
 nsSVGUseFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   SVGUseElement *use = static_cast<SVGUseElement*>(mContent);
 
   nsIContent* clone = use->CreateAnonymousContent();
-  nsSVGEffects::InvalidateRenderingObservers(this);
+  nsLayoutUtils::PostRestyleEvent(
+    use, nsRestyleHint(0), nsChangeHint_InvalidateRenderingObservers);
   if (!clone)
     return NS_ERROR_FAILURE;
   if (!aElements.AppendElement(clone))
     return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 void
--- a/layout/xul/nsIScrollbarMediator.h
+++ b/layout/xul/nsIScrollbarMediator.h
@@ -36,16 +36,19 @@ public:
    * RepeatButtonScroll is called when the scrollbar's button is held down. When the
    * button is first clicked the increment is set; RepeatButtonScroll adds this
    * increment to the current position.
    * @note This method might destroy the frame, pres shell, and other objects.
    */
   virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) = 0;
   /**
    * aOldPos and aNewPos are scroll positions.
+   * The scroll positions start with zero at the left edge; implementors that want
+   * zero at the right edge for RTL content will need to adjust accordingly.
+   * (See ScrollFrameHelper::ThumbMoved in nsGfxScrollFrame.cpp.)
    * @note This method might destroy the frame, pres shell, and other objects.
    */
   virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
                           nscoord aOldPos,
                           nscoord aNewPos) = 0;
   virtual void VisibilityChanged(bool aVisible) = 0;
 
   /**
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -415,16 +415,24 @@ pref("media.track.enabled", false);
 
 // Whether to enable MediaSource support
 #ifdef RELEASE_BUILD
 pref("media.mediasource.enabled", false);
 #else
 pref("media.mediasource.enabled", true);
 #endif
 
+#ifdef MOZ_WIDGET_GONK
+pref("media.mediasource.mp4.enabled", false);
+pref("media.mediasource.webm.enabled", false);
+#else
+pref("media.mediasource.mp4.enabled", false);
+pref("media.mediasource.webm.enabled", true);
+#endif
+
 #ifdef MOZ_WEBSPEECH
 pref("media.webspeech.recognition.enable", false);
 pref("media.webspeech.synth.enabled", false);
 #endif
 #ifdef MOZ_WEBM_ENCODER
 pref("media.encoder.webm.enabled", true);
 #endif
 #ifdef MOZ_OMX_ENCODER
--- a/testing/mozbase/mozlog/setup.py
+++ b/testing/mozbase/mozlog/setup.py
@@ -1,16 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from setuptools import setup, find_packages
 
 PACKAGE_NAME = 'mozlog'
-PACKAGE_VERSION = '2.6'
+PACKAGE_VERSION = '2.7'
 
 setup(name=PACKAGE_NAME,
       version=PACKAGE_VERSION,
       description="Robust log handling specialized for logging in the Mozilla universe",
       long_description="see http://mozbase.readthedocs.org/",
       author='Mozilla Automation and Testing Team',
       author_email='tools@lists.mozilla.org',
       url='https://wiki.mozilla.org/Auto-tools/Projects/Mozbase',
--- a/testing/web-platform/meta/custom-elements/creating-and-passing-registries/share-registry-import-document.html.ini
+++ b/testing/web-platform/meta/custom-elements/creating-and-passing-registries/share-registry-import-document.html.ini
@@ -1,17 +1,15 @@
 [share-registry-import-document.html]
   type: testharness
+  expected: TIMEOUT
   [Registry of the import should share master document registry]
     expected: TIMEOUT
 
   [Registry of the master document should be shared with imported document\'s registry]
     expected: TIMEOUT
 
-  [Registry of the master document should be shared with imported document. Import is asynchronous]
-    expected: FAIL
+  [Registry of the imported document should be shared with master document. Import is asynchronous]
+    expected: TIMEOUT
 
-  [Registry of the imported document should be shared with master document. Import is syncronous]
-    expected: FAIL
+  [Registry of the master document should be shared with imported document. Import is asynchronous]
+    expected: TIMEOUT
 
-  [Registry of the master document should be shared with imported document. Import is syncronous]
-    expected: FAIL
-
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -610,43 +610,52 @@ KeyboardMayHaveIME()
 
 bool gSafeMode = false;
 
 /**
  * The nsXULAppInfo object implements nsIFactory so that it can be its own
  * singleton.
  */
 class nsXULAppInfo : public nsIXULAppInfo,
+#ifdef NIGHTLY_BUILD
+                     public nsIObserver,
+#endif
 #ifdef XP_WIN
                      public nsIWinAppHelper,
 #endif
 #ifdef MOZ_CRASHREPORTER
                      public nsICrashReporter,
                      public nsIFinishDumpingCallback,
 #endif
                      public nsIXULRuntime
 
 {
 public:
   MOZ_CONSTEXPR nsXULAppInfo() {}
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIXULAPPINFO
   NS_DECL_NSIXULRUNTIME
+#ifdef NIGHTLY_BUILD
+  NS_DECL_NSIOBSERVER
+#endif
 #ifdef MOZ_CRASHREPORTER
   NS_DECL_NSICRASHREPORTER
   NS_DECL_NSIFINISHDUMPINGCALLBACK
 #endif
 #ifdef XP_WIN
   NS_DECL_NSIWINAPPHELPER
 #endif
 };
 
 NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
   NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
+#ifdef NIGHTLY_BUILD
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+#endif
 #ifdef XP_WIN
   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
 #endif
 #ifdef MOZ_CRASHREPORTER
   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
   NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)
 #endif
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
@@ -837,18 +846,35 @@ nsXULAppInfo::GetProcessID(uint32_t* aRe
   *aResult = GetCurrentProcessId();
 #else
   *aResult = getpid();
 #endif
   return NS_OK;
 }
 
 static bool gBrowserTabsRemoteAutostart = false;
+static nsString gBrowserTabsRemoteDisabledReason;
 static bool gBrowserTabsRemoteAutostartInitialized = false;
 
+#ifdef NIGHTLY_BUILD
+NS_IMETHODIMP
+nsXULAppInfo::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) {
+  if (!nsCRT::strcmp(aTopic, "getE10SBlocked")) {
+    nsCOMPtr<nsISupportsString> ret = do_QueryInterface(aSubject);
+    if (!ret)
+      return NS_ERROR_FAILURE;
+
+    ret->SetData(gBrowserTabsRemoteDisabledReason);
+
+    return NS_OK;
+  }
+  return NS_ERROR_FAILURE;
+}
+#endif
+
 NS_IMETHODIMP
 nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult)
 {
   *aResult = BrowserTabsRemoteAutostart();
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -4533,18 +4559,20 @@ XRE_DeinitCommandLine()
 GeckoProcessType
 XRE_GetProcessType()
 {
   return mozilla::startup::sChildProcessType;
 }
 
 static void
 LogE10sBlockedReason(const char *reason) {
+  gBrowserTabsRemoteDisabledReason.Assign(NS_ConvertASCIItoUTF16(reason));
+
   nsAutoString msg(NS_LITERAL_STRING("==================\nE10s has been blocked from running because:\n"));
-  msg.Append(NS_ConvertASCIItoUTF16(reason));
+  msg.Append(gBrowserTabsRemoteDisabledReason);
   msg.AppendLiteral("\n==================\n");
   nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
   if (console) {
     console->LogStringMessage(msg.get());
   }
 }
 
 bool
@@ -4569,21 +4597,21 @@ mozilla::BrowserTabsRemoteAutostart()
   // Nightly builds, update gBrowserTabsRemoteAutostart based on all the
   // e10s remote relayed prefs we watch.
   bool disabledForA11y = Preferences::GetBool("browser.tabs.remote.autostart.disabled-because-using-a11y", false);
   // Only disable for IME for the automatic pref, not the opt-in one.
   bool disabledForIME = trialPref && KeyboardMayHaveIME();
 
   if (prefEnabled) {
     if (gSafeMode) {
-      LogE10sBlockedReason("Firefox is in safe mode.");
+      LogE10sBlockedReason("Safe mode");
     } else if (disabledForA11y) {
-      LogE10sBlockedReason("An accessibility tool is active.");
+      LogE10sBlockedReason("An accessibility tool is active");
     } else if (disabledForIME) {
-      LogE10sBlockedReason("The keyboard being used has activated IME.");
+      LogE10sBlockedReason("The keyboard being used has activated IME");
     } else {
       gBrowserTabsRemoteAutostart = true;
     }
   }
 #endif
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
   // If for any reason we suspect acceleration will be disabled, disabled
@@ -4630,17 +4658,17 @@ mozilla::BrowserTabsRemoteAutostart()
       const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
       if (acceleratedEnv && (*acceleratedEnv != '0')) {
         accelDisabled = false;
       }
     }
 
     if (accelDisabled) {
       gBrowserTabsRemoteAutostart = false;
-      LogE10sBlockedReason("Hardware acceleration is disabled.");
+      LogE10sBlockedReason("Hardware acceleration is disabled");
     }
   }
 #endif
 
   bool tpEnabled = Preferences::GetBool("privacy.trackingprotection.enabled",
                                         false);
   if (tpEnabled) {
     gBrowserTabsRemoteAutostart = false;
--- a/webapprt/mac/webapprt.mm
+++ b/webapprt/mac/webapprt.mm
@@ -163,20 +163,28 @@ main(int argc, char **argv)
 
       NSFileManager* fileClerk = [[NSFileManager alloc] init];
       NSError *errorDesc = nil;
 
       //we know the firefox path, so copy the new webapprt here
       NSString *newWebRTPath =
         [NSString stringWithFormat: @"%@%s%s", firefoxPath, APP_RESOURCES_PATH,
                                                WEBAPPRT_EXECUTABLE];
-      NSLog(@"### Firefox webapprt path: %@", newWebRTPath);
+      NSLog(@"### Trying Firefox webapprt path: %@", newWebRTPath);
       if (![fileClerk fileExistsAtPath:newWebRTPath]) {
-        NSString* msg = [NSString stringWithFormat: @"This version of Firefox (%@) cannot run web applications, because it is not recent enough or damaged", firefoxVersion];
-        @throw MakeException(@"Missing Web Runtime Files", msg);
+        newWebRTPath =
+          [NSString stringWithFormat: @"%@%s%s", firefoxPath, APP_MACOS_PATH,
+                                                 WEBAPPRT_EXECUTABLE];
+        NSLog(@"### Trying Firefox webapprt path: %@", newWebRTPath);
+        if (![fileClerk fileExistsAtPath:newWebRTPath]) {
+          NSString* msg =
+            [NSString stringWithFormat:
+              @"This version of Firefox (%@) cannot run web applications, because it is not recent enough or damaged", firefoxVersion];
+          @throw MakeException(@"Missing Web Runtime Files", msg);
+        }
       }
 
       [fileClerk removeItemAtPath: myWebRTPath error: &errorDesc];
       if (errorDesc != nil) {
         NSLog(@"failed to unlink old binary file at path: %@ with error: %@", myWebRTPath, errorDesc);
         @throw MakeException(@"Unable To Update", @"Failed preparation for Web Runtime update");
       }
 
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -521,25 +521,36 @@ nsWindow::StartRemoteDrawing()
                                GRALLOC_USAGE_HW_FB,
                                0, 0, width, height, &vaddr)) {
         EndRemoteDrawing();
         return nullptr;
     }
     int bytepp;
     SurfaceFormat format = HalFormatToSurfaceFormat(display->surfaceformat,
                                                     &bytepp);
-    return mFramebufferTarget = Factory::CreateDrawTargetForData(
-        BackendType::CAIRO, (uint8_t*)vaddr,
-        IntSize(width, height), mFramebuffer->stride * bytepp, format);
+    mFramebufferTarget = Factory::CreateDrawTargetForData(
+         BackendType::CAIRO, (uint8_t*)vaddr,
+         IntSize(width, height), mFramebuffer->stride * bytepp, format);
+    if (!mBackBuffer ||
+        mBackBuffer->GetSize() != mFramebufferTarget->GetSize() ||
+        mBackBuffer->GetFormat() != mFramebufferTarget->GetFormat()) {
+        mBackBuffer = mFramebufferTarget->CreateSimilarDrawTarget(
+            mFramebufferTarget->GetSize(), mFramebufferTarget->GetFormat());
+    }
+    return mBackBuffer;
 }
 
 void
 nsWindow::EndRemoteDrawing()
 {
     if (mFramebufferTarget) {
+        IntSize size = mFramebufferTarget->GetSize();
+        Rect rect(0, 0, size.width, size.height);
+        RefPtr<SourceSurface> source = mBackBuffer->Snapshot();
+        mFramebufferTarget->DrawSurface(source, rect, rect);
         gralloc_module()->unlock(gralloc_module(), mFramebuffer->handle);
     }
     if (mFramebuffer) {
         GetGonkDisplay()->QueueBuffer(mFramebuffer);
     }
     mFramebuffer = nullptr;
     mFramebufferTarget = nullptr;
 }
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -125,16 +125,25 @@ protected:
     bool mVisible;
     InputContext mInputContext;
     nsCOMPtr<nsIIdleServiceInternal> mIdleService;
     // If we're using a BasicCompositor, these fields are temporarily
     // set during frame composition.  They wrap the hardware
     // framebuffer.
     mozilla::RefPtr<mozilla::gfx::DrawTarget> mFramebufferTarget;
     ANativeWindowBuffer* mFramebuffer;
+    // If we're using a BasicCompositor, this is our window back
+    // buffer.  The gralloc framebuffer driver expects us to draw the
+    // entire framebuffer on every frame, but gecko expects the
+    // windowing system to be tracking buffer updates for invalidated
+    // regions.  We get stuck holding that bag.
+    //
+    // Only accessed on the compositor thread, except during
+    // destruction.
+    mozilla::RefPtr<mozilla::gfx::DrawTarget> mBackBuffer;
 
     void BringToTop();
 
     // Call this function when the users activity is the direct cause of an
     // event (like a keypress or mouse click).
     void UserActivity();
 };
 
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1015,16 +1015,22 @@ GfxInfo::GetGfxDriverInfo()
         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_BETWEEN_INCLUSIVE_START, V(14,1,0,0), V(14,2,0,0), "ATI Catalyst 14.6+");
     APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_ALL,
         (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_BETWEEN_INCLUSIVE_START, V(14,1,0,0), V(14,2,0,0), "ATI Catalyst 14.6+");
 
+    // Disable D2D on some ATI drivers which don't support dxgi keyed mutex correctly (bug 1089183)
+    APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_ALL,
+        (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_BETWEEN_INCLUSIVE_START, V(8,653,0,0), V(8,691,0,0), "ATI Catalyst 14.6+");
+
     /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
      * whilst scrolling. See bugs: 612007, 644787 & 645872.
      */
     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers),
       nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );