Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 29 Jan 2016 13:44:12 -0800
changeset 320604 bff6cfc7e67b46b55431ccbdbedf025272f54220
parent 320603 75c6a6c1fec29d30999b7b0f6251ada5d0efc0c2 (current diff)
parent 320589 54eea211e234217c0faa8c05bf4de9fd3005f5c2 (diff)
child 320605 2323e6b411c13d588cab7beb88d64fc957eab9e9
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone47.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
build/unix/mozconfig.rust
configure.in
testing/docker/tester/b2g-desktop-config.py
testing/docker/tester/buildprops.json
testing/docker/tester/mozharness_configs/emulator_override.py
testing/docker/tester/mozharness_configs/gaia_integration_override.py
testing/docker/tester/mozharness_configs/remove_executables.py
testing/mozharness/configs/b2g/desktop_automation_config.py
testing/mozharness/configs/b2g/emulator_test_config.py
testing/mozharness/configs/b2g/gaia_integration_config.py
testing/mozharness/configs/b2g/gaia_unit_production_config.py
testing/mozharness/configs/b2g/generic_config.py
testing/mozharness/configs/b2g/mulet_config.py
toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in
toolkit/crashreporter/google-breakpad/src/common/pathname_stripper.h
toolkit/crashreporter/google-breakpad/src/common/pathname_stripper_unittest.cc
toolkit/modules/moz.build
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1461,17 +1461,17 @@ HyperTextAccessible::CaretLineNumber()
     if (hyperTextContent == caretFrame->GetContent()) {
       return lineNumber; // Must be in a single line hyper text, there is no line iterator
     }
     nsContainerFrame *parentFrame = caretFrame->GetParent();
     if (!parentFrame)
       break;
 
     // Add lines for the sibling frames before the caret
-    nsIFrame *sibling = parentFrame->GetFirstPrincipalChild();
+    nsIFrame *sibling = parentFrame->PrincipalChildList().FirstChild();
     while (sibling && sibling != caretFrame) {
       nsAutoLineIterator lineIterForSibling = sibling->GetLineIterator();
       if (lineIterForSibling) {
         // For the frames before that grab all the lines
         int32_t addLines = lineIterForSibling->GetNumLines();
         lineNumber += addLines;
       }
       sibling = sibling->GetNextSibling();
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -276,17 +276,16 @@ int main(int argc, _CONST char* argv[])
 #else
   #error "Unknown platform"  // having this here keeps cppcheck happy
 #endif
   }
 
   int result;
   {
     ScopedLogging log;
-    mozilla::LogModule::Init();
     char **_argv;
 
     /*
      * Duplicate argument vector to conform non-const argv of
      * do_main() since XRE_main() is very stupid with non-const argv.
      */
     _argv = new char *[argc + 1];
     for (int i = 0; i < argc; i++) {
--- a/b2g/config/aries-l/sources.xml
+++ b/b2g/config/aries-l/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="be4b291a90b371b41b62ade68c31ad173bb87baa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d5b6b107d77a31935aa4fe53ba67a8574372672"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="be4b291a90b371b41b62ade68c31ad173bb87baa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
@@ -130,17 +132,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
   <project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="205ac4204bbbb2098a8046444acba551ba5dc75a"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="8a066f7fa7410e32b58def35f322aa33f03db283"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="1e562fa3ac618fe136d3515bb14a070b4153e0cd"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
   <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="d5e53ed6f22fa06052351dc03510af9473af01ea"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="3e85c4683c121530c1c3a48c696a569bf5f587e2"/>
   <project name="platform_external_bluetooth_bluedroid" path="external/bluetooth/bluedroid" remote="b2g" revision="70f536bd97d901b96b94669ae1aa2fd0fb54b258"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform_external_libnfc-pn547" path="external/libnfc-pn547" remote="b2g" revision="5bb999b84b8adc14f6bea004d523ba258dea8188"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0", 
+        "git_revision": "4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "256902cd676226f40965b353e0ec12e9b0372290", 
+    "revision": "07d30dcbe75d2c053a6e98697fd2e362fb786ca9", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d5b6b107d77a31935aa4fe53ba67a8574372672"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -16,20 +16,22 @@
   <remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!--
     B2G repositories for all targets
     -->
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="77c0e08caa0dda8c6e50f6e7cbad9f79b320a3b0"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="4f0e2a1a42a2d049b6fe8f4f095cdcdf0fd5465c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4eb8f37d2239ea7746462aa603f585116a9eaa92"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
+  <project name="platform_system_libpdu" path="system/libpdu" remote="b2g" revision="ac4e539dbd73522c466ebffba53edea61702082f"/>
+  <project name="platform_system_sensorsd" path="system/sensorsd" remote="b2g" revision="3799a1cb57f08e9468d1cec6c74f8abe93ddae36"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="be4b291a90b371b41b62ade68c31ad173bb87baa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -13,11 +13,11 @@ export MOZILLA_OFFICIAL=1
 # Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
-. "$topsrcdir/build/unix/mozconfig.rust"
+. "$topsrcdir/build/mozconfig.rust"
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -5,11 +5,11 @@ ac_add_options --enable-verify-mar
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 ac_add_options --with-branding=browser/branding/nightly
 
-. "$topsrcdir/build/unix/mozconfig.rust"
+. "$topsrcdir/build/mozconfig.rust"
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/whitelist
+++ b/browser/config/mozconfigs/whitelist
@@ -35,17 +35,17 @@ whitelist['nightly']['linux32'] += [
 
 whitelist['nightly']['linux64'] += [
     'export MOZILLA_OFFICIAL=1',
     'export MOZ_TELEMETRY_REPORTING=1',
     "mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'",
     'STRIP_FLAGS="--strip-debug"',
     'ac_add_options --with-ccache=/usr/bin/ccache',
     '. "$topsrcdir/build/mozconfig.cache"',
-    '. "$topsrcdir/build/unix/mozconfig.rust"',
+    '. "$topsrcdir/build/mozconfig.rust"',
 ]
 
 whitelist['nightly']['macosx-universal'] += [
     'if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then',
     'ac_add_options --with-macbundlename-prefix=Firefox',
     'fi',
     'mk_add_options MOZ_MAKE_FLAGS="-j12"',
     'ac_add_options --with-ccache',
@@ -62,16 +62,17 @@ whitelist['nightly']['win32'] += [
     '. "$topsrcdir/build/mozconfig.cache"',
     'if test "$IS_NIGHTLY" != ""; then',
     'ac_add_options --disable-auto-deps',
     'fi',
 ]
 whitelist['nightly']['win64'] += [
     '. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"',
     '. "$topsrcdir/build/mozconfig.cache"',
+    '. "$topsrcdir/build/mozconfig.rust"',
 ]
 
 for platform in all_platforms:
     whitelist['release'][platform] = [
         'ac_add_options --enable-update-channel=release',
         'ac_add_options --enable-official-branding',
         'mk_add_options MOZ_MAKE_FLAGS="-j4"',
         'export BUILDING_RELEASE=1',
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -25,10 +25,12 @@ ac_add_options --enable-warnings-as-erro
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . $topsrcdir/build/win64/mozconfig.vs2013
 
+. "$topsrcdir/build/mozconfig.rust"
+
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -2,10 +2,12 @@
 . "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 . "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
 
 ac_add_options --enable-profiling
 ac_add_options --enable-verify-mar
 
 ac_add_options --with-branding=browser/branding/nightly
 
+. "$topsrcdir/build/mozconfig.rust"
+
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/tooltool-manifests/win64/releng.manifest
+++ b/browser/config/tooltool-manifests/win64/releng.manifest
@@ -1,15 +1,23 @@
 [
 {
 "size": 266240,
 "digest": "bb345b0e700ffab4d09436981f14b5de84da55a3f18a7f09ebc4364a4488acdeab8d46f447b12ac70f2da1444a68b8ce8b8675f0dae2ccf845e966d1df0f0869",
 "algorithm": "sha512",
 "filename": "mozmake.exe"
 },
 {
+"size": 72442063,
+"digest": "899da5af9b322ba63ec04de06f92b5bb82a2700f9fe03001e75fdc6f678a435cd66a474190fd93863327456270aef5649d3788aa50d852121059ced99a6004db",
+"algorithm": "sha512",
+"visibility": "public",
+"filename": "rustc.tar.bz2",
+"unpack": true
+},
+{
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
 "filename": "sccache.tar.bz2",
 "unpack": true
 }
 ]
new file mode 100644
--- /dev/null
+++ b/build/mozconfig.rust
@@ -0,0 +1,9 @@
+# Options to enable rust in automation builds.
+
+# Tell configure to use the tooltool rustc.
+# Assume this is compiled with --enable-rpath so we don't
+# have to set LD_LIBRARY_PATH.
+RUSTC="$topsrcdir/rustc/bin/rustc"
+
+# Enable rust in the build.
+ac_add_options --enable-rust
deleted file mode 100644
--- a/build/unix/mozconfig.rust
+++ /dev/null
@@ -1,9 +0,0 @@
-# Options to enable rust in automation builds.
-
-# Tell configure to use the tooltool rustc.
-# Assume this is compiled with --enable-rpath so we don't
-# have to set LD_LIBRARY_PATH.
-RUSTC="$topsrcdir/rustc/bin/rustc"
-
-# Enable rust in the build.
-ac_add_options --enable-rust
--- a/configure.in
+++ b/configure.in
@@ -3498,17 +3498,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.20.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.22, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_NATIVE_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS="-I${DIST}/include/nss"
 fi
 
@@ -9195,16 +9195,17 @@ if test -n "$ZLIB_IN_MOZGLUE"; then
 fi
 export MOZ_NATIVE_ZLIB
 export MOZ_ZLIB_CFLAGS
 export MOZ_ZLIB_LIBS
 export MOZ_APP_NAME
 export MOZ_APP_REMOTINGNAME
 export DONT_POPULATE_VIRTUALENV=1
 export PYTHON
+export RUSTC
 export MOZILLA_CENTRAL_PATH=$_topsrcdir
 export STLPORT_CPPFLAGS
 export STLPORT_LIBS
 export JS_STANDALONE=no
 export DIST
 export MOZ_LINKER
 export ZLIB_IN_MOZGLUE
 export MOZ_MEMORY
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -261,19 +261,19 @@ static uint32_t gValidateOrigin = 0xffff
 
 // Hint for native dispatch of events on how long to delay after
 // all documents have loaded in milliseconds before favoring normal
 // native event dispatch priorites over performance
 // Can be overridden with docshell.event_starvation_delay_hint pref.
 #define NS_EVENT_STARVATION_DELAY_HINT 2000
 
 #ifdef DEBUG
-static mozilla::LazyLogModule gDocShellLog("nsDocShell");
+static PRLogModuleInfo* gDocShellLog;
 #endif
-static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");;
+static PRLogModuleInfo* gDocShellLeakLog;
 
 const char kBrandBundleURL[]      = "chrome://branding/locale/brand.properties";
 const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
 
 static void
 FavorPerformanceHint(bool aPerfOverStarvation)
 {
   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
@@ -813,17 +813,27 @@ nsDocShell::nsDocShell()
   mHistoryID = ++gDocshellIDCounter;
   if (gDocShellCount++ == 0) {
     NS_ASSERTION(sURIFixup == nullptr,
                  "Huh, sURIFixup not null in first nsDocShell ctor!");
 
     CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup);
   }
 
-  MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this));
+#ifdef DEBUG
+  if (!gDocShellLog) {
+    gDocShellLog = PR_NewLogModule("nsDocShell");
+  }
+#endif
+  if (!gDocShellLeakLog) {
+    gDocShellLeakLog = PR_NewLogModule("nsDocShellLeak");
+  }
+  if (gDocShellLeakLog) {
+    MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this));
+  }
 
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
   ++gNumberOfDocShells;
   if (!PR_GetEnv("MOZ_QUIET")) {
     printf_stderr("++DOCSHELL %p == %ld [pid = %d] [id = %llu]\n",
                   (void*)this,
                   gNumberOfDocShells,
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -54,29 +54,36 @@ static PRCList gSHistoryList;
 // Max viewers allowed total, across all SHistory objects - negative default
 // means we will calculate how many viewers to cache based on total memory
 int32_t nsSHistory::sHistoryMaxTotalViewers = -1;
 
 // A counter that is used to be able to know the order in which
 // entries were touched, so that we can evict older entries first.
 static uint32_t gTouchCounter = 0;
 
-static LazyLogModule gSHistoryLog("nsSHistory");
-
-#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
+static PRLogModuleInfo*
+GetSHistoryLog()
+{
+  static PRLogModuleInfo* sLog;
+  if (!sLog) {
+    sLog = PR_NewLogModule("nsSHistory");
+  }
+  return sLog;
+}
+#define LOG(format) MOZ_LOG(GetSHistoryLog(), mozilla::LogLevel::Debug, format)
 
 // This macro makes it easier to print a log message which includes a URI's
 // spec.  Example use:
 //
 //  nsIURI *uri = [...];
 //  LOG_SPEC(("The URI is %s.", _spec), uri);
 //
 #define LOG_SPEC(format, uri)                              \
   PR_BEGIN_MACRO                                           \
-    if (MOZ_LOG_TEST(gSHistoryLog, LogLevel::Debug)) {     \
+    if (MOZ_LOG_TEST(GetSHistoryLog(), LogLevel::Debug)) {     \
       nsAutoCString _specStr(NS_LITERAL_CSTRING("(null)"));\
       if (uri) {                                           \
         uri->GetSpec(_specStr);                            \
       }                                                    \
       const char* _spec = _specStr.get();                  \
       LOG(format);                                         \
     }                                                      \
   PR_END_MACRO
@@ -84,17 +91,17 @@ static LazyLogModule gSHistoryLog("nsSHi
 // This macro makes it easy to log a message including an SHEntry's URI.
 // For example:
 //
 //  nsCOMPtr<nsISHEntry> shentry = [...];
 //  LOG_SHENTRY_SPEC(("shentry %p has uri %s.", shentry.get(), _spec), shentry);
 //
 #define LOG_SHENTRY_SPEC(format, shentry)                  \
   PR_BEGIN_MACRO                                           \
-    if (MOZ_LOG_TEST(gSHistoryLog, LogLevel::Debug)) {     \
+    if (MOZ_LOG_TEST(GetSHistoryLog(), LogLevel::Debug)) {     \
       nsCOMPtr<nsIURI> uri;                                \
       shentry->GetURI(getter_AddRefs(uri));                \
       LOG_SPEC(format, uri);                               \
     }                                                      \
   PR_END_MACRO
 
 // Iterates over all registered session history listeners.
 #define ITERATE_LISTENERS(body)                            \
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6,17 +6,16 @@
 
 /* A namespace class for static layout utilities. */
 
 #include "nsContentUtils.h"
 
 #include <algorithm>
 #include <math.h>
 
-#include "prprf.h"
 #include "DecoderTraits.h"
 #include "harfbuzz/hb.h"
 #include "imgICache.h"
 #include "imgIContainer.h"
 #include "imgINotificationObserver.h"
 #include "imgLoader.h"
 #include "imgRequestProxy.h"
 #include "jsapi.h"
@@ -3520,35 +3519,25 @@ nsContentUtils::ReportToConsoleNonLocali
                                      aErrorFlags, aCategory,
                                      innerWindowID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return sConsoleService->LogMessage(errorObject);
 }
 
 void
-nsContentUtils::LogMessageToConsole(const char* aMsg, ...)
+nsContentUtils::LogMessageToConsole(const char* aMsg)
 {
   if (!sConsoleService) { // only need to bother null-checking here
     CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
     if (!sConsoleService) {
       return;
     }
   }
-
-  va_list args;
-  va_start(args, aMsg);
-  char* formatted = PR_vsmprintf(aMsg, args);
-  va_end(args);
-  if (!formatted) {
-    return;
-  }
-
-  sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(formatted).get());
-  PR_smprintf_free(formatted);
+  sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
 }
 
 bool
 nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
 {
   if (!aDocument) {
     return false;
   }
@@ -6923,30 +6912,30 @@ nsContentUtils::GetAdjustedOffsetInTextC
 {
   // The structure of the anonymous frames within a text control frame is
   // an optional block frame, followed by an optional br frame.
 
   // If the offset frame has a child, then this frame is the block which
   // has the text frames (containing the content) as its children. This will
   // be the case if we click to the right of any of the text frames, or at the
   // bottom of the text area.
-  nsIFrame* firstChild = aOffsetFrame->GetFirstPrincipalChild();
+  nsIFrame* firstChild = aOffsetFrame->PrincipalChildList().FirstChild();
   if (firstChild) {
     // In this case, the passed-in offset is incorrect, and we want the length
     // of the entire content in the text control frame.
     return firstChild->GetContent()->Length();
   }
 
   if (aOffsetFrame->GetPrevSibling() &&
       !aOffsetFrame->GetNextSibling()) {
     // In this case, we're actually within the last frame, which is a br
     // frame. Our offset should therefore be the length of the first child of
     // our parent.
     int32_t aOutOffset =
-      aOffsetFrame->GetParent()->GetFirstPrincipalChild()->GetContent()->Length();
+      aOffsetFrame->GetParent()->PrincipalChildList().FirstChild()->GetContent()->Length();
     return aOutOffset;
   }
 
   // Otherwise, we're within one of the text frames, in which case our offset
   // has already been correctly calculated.
   return aOffset;
 }
 
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -888,18 +888,18 @@ public:
                                   const char16_t **aParams = nullptr,
                                   uint32_t aParamsLength = 0,
                                   nsIURI* aURI = nullptr,
                                   const nsAFlatString& aSourceLine
                                     = EmptyString(),
                                   uint32_t aLineNumber = 0,
                                   uint32_t aColumnNumber = 0);
 
-  static void LogMessageToConsole(const char* aMsg, ...);
-  
+  static void LogMessageToConsole(const char* aMsg);
+
   /**
    * Get the localized string named |aKey| in properties file |aFile|.
    */
   static nsresult GetLocalizedString(PropertiesFile aFile,
                                      const char* aKey,
                                      nsXPIDLString& aResult);
 
   /**
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -101,17 +101,16 @@
 #include "nsIDOMStyleSheet.h"
 #include "nsIStyleSheetService.h"
 #include "nsContentPermissionHelper.h"
 #include "nsNetUtil.h"
 #include "nsDocument.h"
 #include "HTMLImageElement.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
-#include "mozilla/dom/Promise.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -2146,39 +2145,36 @@ nsDOMWindowUtils::GetLayerManagerRemote(
   if (!mgr)
     return NS_ERROR_FAILURE;
 
   *retval = !!mgr->AsShadowForwarder();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::GetSupportsHardwareH264Decoding(JS::MutableHandle<JS::Value> aPromise)
+nsDOMWindowUtils::GetSupportsHardwareH264Decoding(nsAString& aRetval)
 {
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
-  NS_ENSURE_STATE(window);
-  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(window);
-  NS_ENSURE_STATE(parentObject);
 #ifdef MOZ_FMP4
   nsCOMPtr<nsIWidget> widget = GetWidget();
-  NS_ENSURE_STATE(widget);
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
   LayerManager *mgr = widget->GetLayerManager();
-  NS_ENSURE_STATE(mgr);
-  RefPtr<Promise> promise =
-    MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), parentObject);
-  NS_ENSURE_STATE(promise);
-  aPromise.setObject(*promise->GetWrapper());
+  if (!mgr)
+    return NS_ERROR_FAILURE;
+
+  nsCString failureReason;
+  if (MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), failureReason)) {
+    aRetval.AssignLiteral("Yes");
+  } else {
+    aRetval.AssignLiteral("No; ");
+    AppendUTF8toUTF16(failureReason, aRetval);
+  }
 #else
-  ErrorResult rv;
-  RefPtr<Promise> promise = Promise::Create(parentObject, rv);
-  if (rv.Failed()) {
-    return rv.StealNSResult();
-  }
-  promise.MaybeResolve(NS_LITERAL_STRING("No; Compiled without MP4 support."));
-  aPromise.setObject(*promise->GetWrapper());
+  aRetval.AssignLiteral("No; Compiled without MP4 support.");
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
 {
   NS_ENSURE_ARG_POINTER(startIndex);
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -326,22 +326,20 @@ nsDocumentEncoder::IncludeInContext(nsIN
 
 static
 bool
 LineHasNonEmptyContentWorker(nsIFrame* aFrame)
 {
   // Look for non-empty frames, but ignore inline and br frames.
   // For inline frames, descend into the children, if any.
   if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
-    nsIFrame* child = aFrame->GetFirstPrincipalChild();
-    while (child) {
+    for (nsIFrame* child : aFrame->PrincipalChildList()) {
       if (LineHasNonEmptyContentWorker(child)) {
         return true;
       }
-      child = child->GetNextSibling();
     }
   } else {
     if (aFrame->GetType() != nsGkAtoms::brFrame &&
         !aFrame->IsEmpty()) {
       return true;
     }
   }
   return false;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9880,23 +9880,21 @@ nsGlobalWindow::DispatchSyncPopState()
 // child lists.  aFrame must be non-null.
 static nsCanvasFrame* FindCanvasFrame(nsIFrame* aFrame)
 {
     nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
     if (canvasFrame) {
         return canvasFrame;
     }
 
-    nsIFrame* kid = aFrame->GetFirstPrincipalChild();
-    while (kid) {
+    for (nsIFrame* kid : aFrame->PrincipalChildList()) {
         canvasFrame = FindCanvasFrame(kid);
         if (canvasFrame) {
             return canvasFrame;
         }
-        kid = kid->GetNextSibling();
     }
 
     return nullptr;
 }
 
 //-------------------------------------------------------
 // Tells the HTMLFrame/CanvasFrame that is now has focus
 void
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -3330,17 +3330,17 @@ IsLastRowOfRowGroup(nsIFrame* aFrame)
 static bool
 IsLastNonemptyRowGroupOfTable(nsIFrame* aFrame)
 {
   if (aFrame->GetType() != nsGkAtoms::tableRowGroupFrame) {
     return true;
   }
   for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
     for (nsIFrame* next = c->GetNextSibling(); next; next = next->GetNextSibling()) {
-      if (next->GetFirstPrincipalChild()) {
+      if (next->PrincipalChildList().FirstChild()) {
         return false;
       }
     }
   }
   return true;
 }
 
 void
--- a/dom/canvas/WebGLValidateStrings.cpp
+++ b/dom/canvas/WebGLValidateStrings.cpp
@@ -136,17 +136,17 @@ ValidateGLSLString(const nsAString& stri
 }
 
 bool
 ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl, const char* funcName)
 {
     if (name.IsEmpty())
         return false;
 
-    const uint32_t maxSize = 256;
+    const uint32_t maxSize = webgl->IsWebGL2() ? 1024 : 256;
     if (name.Length() > maxSize) {
         webgl->ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
                                  " maximum allowed length of %d characters.",
                                  funcName, name.Length(), maxSize);
         return false;
     }
 
     if (!ValidateGLSLString(name, webgl, funcName))
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2912,19 +2912,17 @@ HTMLInputElement::Focus(ErrorResult& aEr
     return;
   }
 
   // For file inputs, focus the first button instead. In the case of there
   // being two buttons (when the picker is a directory picker) the user can
   // tab to the next one.
   nsIFrame* frame = GetPrimaryFrame();
   if (frame) {
-    for (nsIFrame* childFrame = frame->GetFirstPrincipalChild();
-         childFrame;
-         childFrame = childFrame->GetNextSibling()) {
+    for (nsIFrame* childFrame : frame->PrincipalChildList()) {
       // See if the child is a button control.
       nsCOMPtr<nsIFormControl> formCtrl =
         do_QueryInterface(childFrame->GetContent());
       if (formCtrl && formCtrl->GetType() == NS_FORM_BUTTON_BUTTON) {
         nsCOMPtr<nsIDOMElement> element = do_QueryInterface(formCtrl);
         nsIFocusManager* fm = nsFocusManager::GetFocusManager();
         if (fm && element) {
           fm->SetFocus(element, 0);
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3053,63 +3053,57 @@ private:
 /**
  * This listener observes the first video frame to arrive with a non-empty size,
  * and calls HTMLMediaElement::ReceivedMediaStreamInitialSize() with that size.
  */
 class HTMLMediaElement::StreamSizeListener : public MediaStreamListener {
 public:
   explicit StreamSizeListener(HTMLMediaElement* aElement) :
     mElement(aElement),
-    mMutex("HTMLMediaElement::StreamSizeListener")
+    mInitialSizeFound(false)
   {}
   void Forget() { mElement = nullptr; }
 
-  void ReceivedSize()
+  void ReceivedSize(gfx::IntSize aSize)
   {
     if (!mElement) {
       return;
     }
-    gfx::IntSize size;
-    {
-      MutexAutoLock lock(mMutex);
-      size = mInitialSize;
-    }
     RefPtr<HTMLMediaElement> deathGrip = mElement;
-    mElement->UpdateInitialMediaSize(size);
-  }
-  virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
-                                        StreamTime aTrackOffset,
-                                        uint32_t aTrackEvents,
-                                        const MediaSegment& aQueuedMedia,
-                                        MediaStream* aInputStream,
-                                        TrackID aInputTrackID) override
+    mElement->UpdateInitialMediaSize(aSize);
+  }
+
+  void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
+                                StreamTime aTrackOffset,
+                                uint32_t aTrackEvents,
+                                const MediaSegment& aQueuedMedia,
+                                MediaStream* aInputStream,
+                                TrackID aInputTrackID) override
   {
-    MutexAutoLock lock(mMutex);
-    if (mInitialSize != gfx::IntSize(0,0) ||
-        aQueuedMedia.GetType() != MediaSegment::VIDEO) {
+    if (mInitialSizeFound || aQueuedMedia.GetType() != MediaSegment::VIDEO) {
       return;
     }
     const VideoSegment& video = static_cast<const VideoSegment&>(aQueuedMedia);
     for (VideoSegment::ConstChunkIterator c(video); !c.IsEnded(); c.Next()) {
       if (c->mFrame.GetIntrinsicSize() != gfx::IntSize(0,0)) {
-        mInitialSize = c->mFrame.GetIntrinsicSize();
         nsCOMPtr<nsIRunnable> event =
-          NS_NewRunnableMethod(this, &StreamSizeListener::ReceivedSize);
+          NS_NewRunnableMethodWithArgs<gfx::IntSize>(
+              this, &StreamSizeListener::ReceivedSize,
+              c->mFrame.GetIntrinsicSize());
         aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
       }
     }
   }
 
 private:
   // These fields may only be accessed on the main thread
   HTMLMediaElement* mElement;
 
-  // mMutex protects the fields below; they can be accessed on any thread
-  Mutex mMutex;
-  gfx::IntSize mInitialSize;
+  // These fields may only be accessed on the MSG thread
+  bool mInitialSizeFound;
 };
 
 class HTMLMediaElement::MediaStreamTracksAvailableCallback:
     public DOMMediaStream::OnTracksAvailableCallback
 {
 public:
   explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement):
       DOMMediaStream::OnTracksAvailableCallback(),
@@ -3169,53 +3163,48 @@ void HTMLMediaElement::UpdateSrcMediaStr
                         this, shouldPlay ? "Setting up" : "Removing",
                         mSrcStream.get()));
 
   if (shouldPlay) {
     mSrcStreamPausedCurrentTime = -1;
 
     mMediaStreamListener = new StreamListener(this,
         "HTMLMediaElement::mMediaStreamListener");
-    mMediaStreamSizeListener = new StreamSizeListener(this);
     stream->AddListener(mMediaStreamListener);
-    stream->AddListener(mMediaStreamSizeListener);
 
     mWatchManager.Watch(*mMediaStreamListener,
         &HTMLMediaElement::UpdateReadyStateInternal);
 
     stream->AddAudioOutput(this);
     SetVolumeInternal();
 
     VideoFrameContainer* container = GetVideoFrameContainer();
     if (container) {
       stream->AddVideoOutput(container);
     }
   } else {
     if (stream) {
       mSrcStreamPausedCurrentTime = CurrentTime();
 
       stream->RemoveListener(mMediaStreamListener);
-      stream->RemoveListener(mMediaStreamSizeListener);
 
       stream->RemoveAudioOutput(this);
       VideoFrameContainer* container = GetVideoFrameContainer();
       if (container) {
         stream->RemoveVideoOutput(container);
       }
     }
     // If stream is null, then DOMMediaStream::Destroy must have been
     // called and that will remove all listeners/outputs.
 
     mWatchManager.Unwatch(*mMediaStreamListener,
         &HTMLMediaElement::UpdateReadyStateInternal);
 
     mMediaStreamListener->Forget();
     mMediaStreamListener = nullptr;
-    mMediaStreamSizeListener->Forget();
-    mMediaStreamSizeListener = nullptr;
   }
 }
 
 void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
 {
   NS_ASSERTION(!mSrcStream && !mMediaStreamListener && !mMediaStreamSizeListener,
                "Should have been ended already");
 
@@ -3224,16 +3213,19 @@ void HTMLMediaElement::SetupSrcMediaStre
   nsIDOMWindow* window = OwnerDoc()->GetInnerWindow();
   if (!window) {
     return;
   }
 
   RefPtr<MediaStream> stream = GetSrcMediaStream();
   if (stream) {
     stream->SetAudioChannelType(mAudioChannel);
+
+    mMediaStreamSizeListener = new StreamSizeListener(this);
+    stream->AddListener(mMediaStreamSizeListener);
   }
 
   UpdateSrcMediaStreamPlaying();
 
   // If we pause this media element, track changes in the underlying stream
   // will continue to fire events at this element and alter its track list.
   // That's simpler than delaying the events, but probably confusing...
   ConstructMediaTracks();
@@ -3250,16 +3242,25 @@ void HTMLMediaElement::SetupSrcMediaStre
 }
 
 void HTMLMediaElement::EndSrcMediaStreamPlayback()
 {
   MOZ_ASSERT(mSrcStream);
 
   UpdateSrcMediaStreamPlaying(REMOVING_SRC_STREAM);
 
+  if (mMediaStreamSizeListener) {
+    RefPtr<MediaStream> stream = GetSrcMediaStream();
+    if (stream) {
+      stream->RemoveListener(mMediaStreamSizeListener);
+    }
+    mMediaStreamSizeListener->Forget();
+    mMediaStreamSizeListener = nullptr;
+  }
+
   mSrcStream->UnregisterTrackListener(mMediaStreamTrackListener);
   mMediaStreamTrackListener = nullptr;
 
   mSrcStream = nullptr;
 }
 
 static already_AddRefed<AudioTrack>
 CreateAudioTrack(AudioStreamTrack* aStreamTrack)
@@ -3398,16 +3399,20 @@ void HTMLMediaElement::MetadataLoaded(co
   mTags = aTags.forget();
   mLoadedDataFired = false;
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
 
   DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   if (IsVideo() && HasVideo()) {
     DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
   }
+  NS_ASSERTION(!HasVideo() ||
+               (mMediaInfo.mVideo.mDisplay.width > 0 &&
+                mMediaInfo.mVideo.mDisplay.height > 0),
+               "Video resolution must be known on 'loadedmetadata'");
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
     ProcessMediaFragmentURI();
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
   if (mIsEncrypted) {
     if (!mMediaSource && Preferences::GetBool("media.eme.mse-only", true)) {
       DecodeError();
@@ -4155,16 +4160,26 @@ void HTMLMediaElement::UpdateMediaSize(c
   mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal);
 }
 
 void HTMLMediaElement::UpdateInitialMediaSize(const nsIntSize& aSize)
 {
   if (!mMediaInfo.HasVideo()) {
     UpdateMediaSize(aSize);
   }
+
+  if (!mMediaStreamSizeListener) {
+    return;
+  }
+  RefPtr<MediaStream> stream = GetSrcMediaStream();
+  if (stream) {
+    stream->RemoveListener(mMediaStreamSizeListener);
+  }
+  mMediaStreamSizeListener->Forget();
+  mMediaStreamSizeListener = nullptr;
 }
 
 void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)
 {
   LOG(LogLevel::Debug, ("%p SuspendOrResumeElement(pause=%d, suspendEvents=%d) hidden=%d",
       this, aPauseElement, aSuspendEvents, OwnerDoc()->Hidden()));
 
   if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1106,17 +1106,17 @@ nsGenericHTMLElement::GetFormControlFram
   if (frame) {
     nsIFormControlFrame* form_frame = do_QueryFrame(frame);
     if (form_frame) {
       return form_frame;
     }
 
     // If we have generated content, the primary frame will be a
     // wrapper frame..  out real frame will be in its child list.
-    for (frame = frame->GetFirstPrincipalChild();
+    for (frame = frame->PrincipalChildList().FirstChild();
          frame;
          frame = frame->GetNextSibling()) {
       form_frame = do_QueryFrame(frame);
       if (form_frame) {
         return form_frame;
       }
     }
   }
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -2163,17 +2163,17 @@ nsTextEditorState::InitializeKeyboardEve
     manager->AddEventListenerByType(mTextListener,
                                     NS_LITERAL_STRING("keypress"),
                                     TrustedEventsAtSystemGroupBubble());
     manager->AddEventListenerByType(mTextListener,
                                     NS_LITERAL_STRING("keyup"),
                                     TrustedEventsAtSystemGroupBubble());
   }
 
-  mSelCon->SetScrollableFrame(do_QueryFrame(mBoundFrame->GetFirstPrincipalChild()));
+  mSelCon->SetScrollableFrame(do_QueryFrame(mBoundFrame->PrincipalChildList().FirstChild()));
 }
 
 void
 nsTextEditorState::ValueWasChanged(bool aNotify)
 {
   UpdatePlaceholderVisibility(aNotify);
 }
 
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -44,17 +44,17 @@ interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(46b44e33-13c2-4eb3-bf80-76a4e0857ccc)]
+[scriptable, uuid(ca6a458c-82e7-4979-886e-6d214eac6f0b)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1329,22 +1329,21 @@ interface nsIDOMWindowUtils : nsISupport
   /**
    * True if the layer manager for the widget associated with this window is
    * forwarding layers to a remote compositor, false otherwise. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute boolean layerManagerRemote;
 
   /**
-   * Returns a Promise that will be resolved with a string once the capabilities
-   * of the h264 decoder have been determined.
-   * Success does not mean that all h264 video decoding will be done
+   * True if we can initialize a hardware-backed h264 decoder for a simple
+   * test video, does not mean that all h264 video decoding will be done
    * in hardware.
    */
-  readonly attribute jsval supportsHardwareH264Decoding;
+  readonly attribute AString supportsHardwareH264Decoding;
 
   /**
    * Record (and return) frame-intervals for frames which were presented
    *   between calling StartFrameTimeRecording and StopFrameTimeRecording.
    *
    * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late
    *     (elements were overwritten since Start), result is considered invalid and hence empty.
    * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent).
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -177,118 +177,58 @@ MP4Decoder::CanHandleMediaType(const nsA
 
 /* static */
 bool
 MP4Decoder::IsEnabled()
 {
   return Preferences::GetBool("media.mp4.enabled");
 }
 
-// sTestH264ExtraData represents the content of the avcC atom found in
-// an AVC1 h264 video. It contains the H264 SPS and PPS NAL.
-// the structure of the avcC atom is as follow:
-// write(0x1);  // version, always 1
-// write(sps[0].data[1]); // profile
-// write(sps[0].data[2]); // compatibility
-// write(sps[0].data[3]); // level
-// write(0xFC | 3); // reserved (6 bits), NULA length size - 1 (2 bits)
-// write(0xE0 | 1); // reserved (3 bits), num of SPS (5 bits)
-// write_word(sps[0].size); // 2 bytes for length of SPS
-// for(size_t i=0 ; i < sps[0].size ; ++i)
-//   write(sps[0].data[i]); // data of SPS
-// write(&b, pps.size());  // num of PPS
-// for(size_t i=0 ; i < pps.size() ; ++i) {
-//   write_word(pps[i].size);  // 2 bytes for length of PPS
-//   for(size_t j=0 ; j < pps[i].size ; ++j)
-//     write(pps[i].data[j]);  // data of PPS
-//   }
-// }
-// here we have a h264 Baseline, 640x360
-// We use a 640x360 extradata, as some video framework (Apple VT) will never
-// attempt to use hardware decoding for small videos.
 static const uint8_t sTestH264ExtraData[] = {
-  0x01, 0x42, 0xc0, 0x1e, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x42,
-  0xc0, 0x1e, 0xbb, 0x40, 0x50, 0x17, 0xfc, 0xb8, 0x08, 0x80,
-  0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0xb5, 0x07, 0x8b, 0x17,
-  0x50, 0x01, 0x00, 0x04, 0x68, 0xce, 0x32, 0xc8
+  0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64,
+  0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
+  0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96,
+  0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0
 };
 
 static already_AddRefed<MediaDataDecoder>
 CreateTestH264Decoder(layers::LayersBackend aBackend,
-                      VideoInfo& aConfig,
-                      FlushableTaskQueue* aTaskQueue)
+                      VideoInfo& aConfig)
 {
   aConfig.mMimeType = "video/avc";
   aConfig.mId = 1;
   aConfig.mDuration = 40000;
   aConfig.mMediaTime = 0;
-  aConfig.mDisplay = nsIntSize(640, 360);
-  aConfig.mImage = nsIntRect(0, 0, 640, 360);
+  aConfig.mDisplay = nsIntSize(64, 64);
+  aConfig.mImage = nsIntRect(0, 0, 64, 64);
   aConfig.mExtraData = new MediaByteBuffer();
   aConfig.mExtraData->AppendElements(sTestH264ExtraData,
                                      MOZ_ARRAY_LENGTH(sTestH264ExtraData));
 
   PDMFactory::Init();
 
   RefPtr<PDMFactory> platform = new PDMFactory();
   RefPtr<MediaDataDecoder> decoder(
-    platform->CreateDecoder(aConfig, aTaskQueue, nullptr, aBackend, nullptr));
+    platform->CreateDecoder(aConfig, nullptr, nullptr, aBackend, nullptr));
 
   return decoder.forget();
 }
 
-/* static */ already_AddRefed<dom::Promise>
-MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent)
+/* static */ bool
+MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aFailureReason)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  ErrorResult rv;
-  RefPtr<dom::Promise> promise;
-  promise = dom::Promise::Create(aParent, rv);
-  if (rv.Failed()) {
-    rv.SuppressException();
-    return nullptr;
-  }
-  RefPtr<FlushableTaskQueue> taskQueue =
-    new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   VideoInfo config;
-  RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config, taskQueue));
+  RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config));
   if (!decoder) {
-    promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to create H264 decoder"));
-    return promise.forget();
+    aFailureReason.AssignLiteral("Failed to create H264 decoder");
+    return false;
   }
-
-  decoder->Init()
-    ->Then(AbstractThread::MainThread(), __func__,
-           [promise, decoder, taskQueue] (TrackInfo::TrackType aTrack) {
-             nsCString failureReason;
-             bool ok = decoder->IsHardwareAccelerated(failureReason);
-             nsAutoString result;
-             if (ok) {
-               result.AssignLiteral("Yes");
-             } else {
-               result.AssignLiteral("No");
-               if (failureReason.Length()) {
-                 result.AppendLiteral("; ");
-                 AppendUTF8toUTF16(failureReason, result);
-               }
-             }
-             promise->MaybeResolve(result);
-             decoder->Shutdown();
-             taskQueue->BeginShutdown();
-             taskQueue->AwaitShutdownAndIdle();
-           },
-           [promise, decoder, taskQueue] (MediaDataDecoder::DecoderFailureReason aResult) {
-             promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to initialize H264 decoder"));
-             decoder->Shutdown();
-             taskQueue->BeginShutdown();
-             taskQueue->AwaitShutdownAndIdle();
-           });
-
-  return promise.forget();
+  bool result = decoder->IsHardwareAccelerated(aFailureReason);
+  decoder->Shutdown();
+  return result;
 }
 
 void
 MP4Decoder::GetMozDebugReaderData(nsAString& aString)
 {
   if (mReader) {
     mReader->GetMozDebugReaderData(aString);
   }
--- a/dom/media/fmp4/MP4Decoder.h
+++ b/dom/media/fmp4/MP4Decoder.h
@@ -3,17 +3,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/. */
 #if !defined(MP4Decoder_h_)
 #define MP4Decoder_h_
 
 #include "MediaDecoder.h"
 #include "MediaFormatReader.h"
-#include "mozilla/dom/Promise.h"
 
 namespace mozilla {
 
 // Decoder that uses a bundled MP4 demuxer and platform decoders to play MP4.
 class MP4Decoder : public MediaDecoder
 {
 public:
   explicit MP4Decoder(MediaDecoderOwner* aOwner);
@@ -34,18 +33,17 @@ public:
   static bool CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs,
                                  const nsAString& aCodecs);
 
   static bool CanHandleMediaType(const nsAString& aMIMEType);
 
   // Returns true if the MP4 backend is preffed on.
   static bool IsEnabled();
 
-  static already_AddRefed<dom::Promise>
-  IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent);
+  static bool IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aReason);
 
   void GetMozDebugReaderData(nsAString& aString) override;
 
 private:
   RefPtr<MediaFormatReader> mReader;
 };
 
 } // namespace mozilla
--- a/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp
+++ b/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp
@@ -38,16 +38,17 @@ MozAVLink(const char* aName)
 /* static */ bool
 FFVPXRuntimeLinker::Init()
 {
   if (sLinkStatus) {
     return sLinkStatus == LinkStatus_SUCCEEDED;
   }
 
   MOZ_ASSERT(NS_IsMainThread());
+  sLinkStatus = LinkStatus_FAILED;
 
   // We retrieve the path of the XUL library as this is where mozavcodec and
   // mozavutil libs are located.
   char* path =
     PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Init);
   if (!path) {
     return false;
   }
@@ -80,18 +81,16 @@ FFVPXRuntimeLinker::Init()
   if (libname) {
     sFFVPXLib.mAVCodecLib = MozAVLink(libname);
     PR_FreeLibraryName(libname);
   }
   if (sFFVPXLib.Link()) {
     sLinkStatus = LinkStatus_SUCCEEDED;
     return true;
   }
-  sLinkStatus = LinkStatus_FAILED;
-
   return false;
 }
 
 /* static */ already_AddRefed<PlatformDecoderModule>
 FFVPXRuntimeLinker::CreateDecoderModule()
 {
   if (!Init()) {
     return nullptr;
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -49,16 +49,17 @@ skip-if = buildapp == 'b2g' || toolkit =
 skip-if = buildapp == 'b2g' || toolkit == 'android' # no windowshare on b2g/android # Bug 1141029 Mulet parity with B2G Desktop for TC
 [test_getUserMedia_basicVideoAudio.html]
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure, turned an intermittent (bug 962579) into a permanant orange
 [test_getUserMedia_bug1223696.html]
 [test_getUserMedia_constraints.html]
 [test_getUserMedia_callbacks.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # Bug 1063290, intermittent timeout # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
 [test_getUserMedia_gumWithinGum.html]
+[test_getUserMedia_loadedmetadata.html]
 [test_getUserMedia_mediaStreamConstructors.html]
 [test_getUserMedia_playAudioTwice.html]
 [test_getUserMedia_playVideoAudioTwice.html]
 [test_getUserMedia_playVideoTwice.html]
 [test_getUserMedia_spinEventLoop.html]
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # copied from basicAudio
 [test_getUserMedia_stopAudioStream.html]
 [test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_loadedmetadata.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    title: "getUserMedia in media element should have video dimensions on loadedmetadata",
+    bug: "1240478"
+  });
+  /**
+   * Tests that assigning a stream to a media element results in the
+   * "loadedmetadata" event without having to play() the media element.
+   *
+   * Also makes sure that the video size has been set on "loadedmetadata".
+   */
+  runTest(function () {
+    var v = document.createElement("video");
+    v.preload = "metadata";
+
+    var constraints = {video: true, audio: true};
+    return getUserMedia(constraints).then(stream => new Promise(resolve => {
+      v.srcObject = stream;
+      v.onloadedmetadata = resolve;
+    })).then(() => {
+      isnot(v.videoWidth, 0, "videoWidth shall be set on 'loadedmetadata'");
+      isnot(v.videoHeight, 0, "videoHeight shall be set on 'loadedmetadata'");
+    });
+  });
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -51,16 +51,23 @@
 #endif
 
 #ifdef AGPS_TYPE_INVALID
 #define AGPS_HAVE_DUAL_APN
 #endif
 
 #define FLUSH_AIDE_DATA 0
 
+#undef LOG
+#undef ERR
+#undef DBG
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO,  "GonkGPSGeolocationProvider", ## args)
+#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "GonkGPSGeolocationProvider", ## args)
+#define DBG(args...)  __android_log_print(ANDROID_LOG_DEBUG, "GonkGPSGeolocationProvider" , ## args)
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static const int kDefaultPeriod = 1000; // ms
 static bool gDebug_isLoggingEnabled = false;
 static bool gDebug_isGPSLocationIgnored = false;
 #ifdef MOZ_B2G_RIL
 static const char* kNetworkConnStateChangedTopic = "network-connection-state-changed";
@@ -134,20 +141,20 @@ GonkGPSGeolocationProvider::LocationCall
                                                         PR_Now() / PR_USEC_PER_MSEC);
   // Note above: Can't use location->timestamp as the time from the satellite is a
   // minimum of 16 secs old (see http://leapsecond.com/java/gpsclock.htm).
   // All code from this point on expects the gps location to be timestamped with the
   // current time, most notably: the geolocation service which respects maximumAge
   // set in the DOM JS.
 
   if (gDebug_isLoggingEnabled) {
-    nsContentUtils::LogMessageToConsole("geo: GPS got a fix (%f, %f). accuracy: %f",
-                                        location->latitude,
-                                        location->longitude,
-                                        location->accuracy);
+    DBG("geo: GPS got a fix (%f, %f). accuracy: %f",
+        location->latitude,
+        location->longitude,
+        location->accuracy);
   }
 
   RefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
   NS_DispatchToMainThread(event);
 
 #ifdef MOZ_B2G_RIL
   MozStumble(somewhere);
 #endif
@@ -194,17 +201,17 @@ GonkGPSGeolocationProvider::StatusCallba
       msgStream = "geo: GPS_STATUS_ENGINE_OFF\n";
       NS_DispatchToMainThread(new NotifyObserversGPSTask( MOZ_UTF16("GPSShutdown")));
       break;
     default:
       msgStream = "geo: Unknown GPS status\n";
       break;
   }
   if (gDebug_isLoggingEnabled){
-    nsContentUtils::LogMessageToConsole(msgStream);
+    DBG("%s", msgStream);
   }
 }
 
 void
 GonkGPSGeolocationProvider::SvStatusCallback(GpsSvStatus* sv_info)
 {
   if (gDebug_isLoggingEnabled) {
     static int numSvs = 0;
@@ -235,35 +242,34 @@ GonkGPSGeolocationProvider::SvStatusCall
     }
 
     // Log the message only if the the status changed.
     if (sv_info->num_svs != numSvs ||
         svAlmanacCount != numAlmanac ||
         svEphemerisCount != numEphemeris ||
         svUsedCount != numUsedInFix) {
 
-      nsContentUtils::LogMessageToConsole(
+      LOG(
         "geo: Number of SVs have (visibility, almanac, ephemeris): (%d, %d, %d)."
         "  %d of these SVs were used in fix.\n",
         sv_info->num_svs, svAlmanacCount, svEphemerisCount, svUsedCount);
 
       numSvs = sv_info->num_svs;
       numAlmanac = svAlmanacCount;
       numEphemeris = svEphemerisCount;
       numUsedInFix = svUsedCount;
     }
   }
 }
 
 void
 GonkGPSGeolocationProvider::NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length)
 {
   if (gDebug_isLoggingEnabled) {
-    nsContentUtils::LogMessageToConsole("geo: NMEA: timestamp:\t%lld, length: %d, %s",
-                                        timestamp, length, nmea);
+    DBG("NMEA: timestamp:\t%lld, length: %d, %s", timestamp, length, nmea);
   }
 }
 
 void
 GonkGPSGeolocationProvider::SetCapabilitiesCallback(uint32_t capabilities)
 {
   class UpdateCapabilitiesEvent : public nsRunnable {
   public:
@@ -527,25 +533,23 @@ GonkGPSGeolocationProvider::RequestSetti
   if (!ss) {
     MOZ_ASSERT(ss);
     return;
   }
 
   nsCOMPtr<nsISettingsServiceLock> lock;
   nsresult rv = ss->CreateLock(nullptr, getter_AddRefs(lock));
   if (NS_FAILED(rv)) {
-    nsContentUtils::LogMessageToConsole(
-      "geo: error while createLock setting '%s': %d\n", aKey, rv);
+    ERR("error while createLock setting '%s': %d\n", aKey, rv);
     return;
   }
 
   rv = lock->Get(aKey, this);
   if (NS_FAILED(rv)) {
-    nsContentUtils::LogMessageToConsole(
-      "geo: error while get setting '%s': %d\n", aKey, rv);
+    ERR("error while get setting '%s': %d\n", aKey, rv);
     return;
   }
 }
 
 #ifdef MOZ_B2G_RIL
 void
 GonkGPSGeolocationProvider::RequestDataConnection()
 {
@@ -634,18 +638,18 @@ ConvertToGpsRefLocationType(const nsAStr
 
   for (auto type: UMTS_TYPES) {
     if (aConnectionType.EqualsASCII(type)) {
       return AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
     }
   }
 
   if (gDebug_isLoggingEnabled) {
-    nsContentUtils::LogMessageToConsole("geo: Unsupported connection type %s\n",
-                                        NS_ConvertUTF16toUTF8(aConnectionType).get());
+    DBG("geo: Unsupported connection type %s\n",
+        NS_ConvertUTF16toUTF8(aConnectionType).get());
   }
   return AGPS_REF_LOCATION_TYPE_GSM_CELLID;
 }
 } // namespace
 
 void
 GonkGPSGeolocationProvider::SetReferenceLocation()
 {
@@ -739,18 +743,17 @@ GonkGPSGeolocationProvider::SetReference
 #endif // MOZ_B2G_RIL
 
 void
 GonkGPSGeolocationProvider::InjectLocation(double latitude,
                                            double longitude,
                                            float accuracy)
 {
   if (gDebug_isLoggingEnabled) {
-    nsContentUtils::LogMessageToConsole("geo: injecting location (%f, %f) accuracy: %f",
-                                        latitude, longitude, accuracy);
+    DBG("injecting location (%f, %f) accuracy: %f", latitude, longitude, accuracy);
   }
 
   MOZ_ASSERT(NS_IsMainThread());
   if (!mGpsInterface) {
     return;
   }
 
   mGpsInterface->inject_location(latitude, longitude, accuracy);
@@ -942,24 +945,22 @@ GonkGPSGeolocationProvider::NetworkLocat
   const bool isGPSFullyInactive = diff_ms > 1000 * 60 * 2; // two mins
   const bool isGPSTempInactive = diff_ms > 1000 * 10; // 10 secs
 
   if (provider->mLocationCallback) {
     if (isGPSFullyInactive ||
        (isGPSTempInactive && delta > kMinMLSCoordChangeInMeters))
     {
       if (gDebug_isLoggingEnabled) {
-        nsContentUtils::LogMessageToConsole("geo: Using MLS, GPS age:%fs, MLS Delta:%fm\n",
-                                            diff_ms / 1000.0, delta);
+        DBG("Using MLS, GPS age:%fs, MLS Delta:%fm\n", diff_ms / 1000.0, delta);
       }
       provider->mLocationCallback->Update(position);
     } else if (provider->mLastGPSPosition) {
       if (gDebug_isLoggingEnabled) {
-        nsContentUtils::LogMessageToConsole("geo: Using old GPS age:%fs\n",
-                                            diff_ms / 1000.0);
+        DBG("Using old GPS age:%fs\n", diff_ms / 1000.0);
       }
 
       // This is a fallback case so that the GPS provider responds with its last
       // location rather than waiting for a more recent GPS or network location.
       // The service decides if the location is too old, not the provider.
       provider->mLocationCallback->Update(provider->mLastGPSPosition);
     }
   }
@@ -1180,26 +1181,25 @@ GonkGPSGeolocationProvider::Observe(nsIS
   if (!strcmp(aTopic, kMozSettingsChangedTopic)) {
     // Read changed setting value
     RootedDictionary<SettingChangeNotification> setting(nsContentUtils::RootingCx());
     if (!WrappedJSToDictionary(aSubject, setting)) {
       return NS_OK;
     }
 
     if (setting.mKey.EqualsASCII(kSettingDebugGpsIgnored)) {
-      nsContentUtils::LogMessageToConsole("geo: received mozsettings-changed: ignoring\n");
+      LOG("received mozsettings-changed: ignoring\n");
       gDebug_isGPSLocationIgnored =
         setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
       if (gDebug_isLoggingEnabled) {
-        nsContentUtils::LogMessageToConsole("geo: Debug: GPS ignored %d\n",
-                                            gDebug_isGPSLocationIgnored);
+        DBG("GPS ignored %d\n", gDebug_isGPSLocationIgnored);
       }
       return NS_OK;
     } else if (setting.mKey.EqualsASCII(kSettingDebugEnabled)) {
-      nsContentUtils::LogMessageToConsole("geo: received mozsettings-changed: logging\n");
+      LOG("received mozsettings-changed: logging\n");
       gDebug_isLoggingEnabled =
         setting.mValue.isBoolean() ? setting.mValue.toBoolean() : false;
       return NS_OK;
     }
 #ifdef MOZ_B2G_RIL
     else if (setting.mKey.EqualsASCII(kSettingRilDefaultServiceId)) {
       if (!setting.mValue.isNumber() ||
           !IsValidRilServiceId(setting.mValue.toNumber())) {
--- a/dom/workers/ServiceWorkerRegistrar.cpp
+++ b/dom/workers/ServiceWorkerRegistrar.cpp
@@ -305,18 +305,18 @@ ServiceWorkerRegistrar::ReadData()
   nsAutoCString version;
   bool hasMoreLines;
   rv = lineInputStream->ReadLine(version, &hasMoreLines);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!IsSupportedVersion(version)) {
-    nsContentUtils::LogMessageToConsole(
-      "Unsupported service worker registrar version: %s", version.get());
+    nsContentUtils::LogMessageToConsole(nsPrintfCString(
+      "Unsupported service worker registrar version: %s", version.get()).get());
     return NS_ERROR_FAILURE;
   }
 
   bool overwrite = false;
   while (hasMoreLines) {
     ServiceWorkerRegistrationData* entry = mData.AppendElement();
 
 #define GET_LINE(x)                                   \
--- a/extensions/auth/nsAuth.h
+++ b/extensions/auth/nsAuth.h
@@ -15,13 +15,13 @@ enum pType {
 #include "mozilla/Logging.h"
 
 //
 // in order to do logging, the following environment variables need to be set:
 // 
 //      set NSPR_LOG_MODULES=negotiateauth:4
 //      set NSPR_LOG_FILE=negotiateauth.log
 //
-extern mozilla::LazyLogModule gNegotiateLog;
+extern PRLogModuleInfo* gNegotiateLog;
 
 #define LOG(args) MOZ_LOG(gNegotiateLog, mozilla::LogLevel::Debug, args)
 
 #endif /* !defined( nsAuth_h__ ) */
--- a/extensions/auth/nsAuthFactory.cpp
+++ b/extensions/auth/nsAuthFactory.cpp
@@ -215,22 +215,23 @@ static const mozilla::Module::ContractID
   { NS_AUTH_MODULE_CONTRACTID_PREFIX "sys-ntlm", &kNS_SAMBANTLMAUTH_CID },
 #endif
   { NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX "negotiate", &kNS_HTTPNEGOTIATEAUTH_CID },
   { NS_AUTH_MODULE_CONTRACTID_PREFIX "sasl-gssapi", &kNS_AUTHSASL_CID },
   { nullptr }
 };
 
 //-----------------------------------------------------------------------------
-mozilla::LazyLogModule gNegotiateLog("negotiateauth");
+PRLogModuleInfo *gNegotiateLog;
 
 // setup nspr logging ...
 static nsresult
 InitNegotiateAuth()
 {
+  gNegotiateLog = PR_NewLogModule("negotiateauth");
   return NS_OK;
 }
 
 static void
 DestroyNegotiateAuth()
 {
   nsAuthGSSAPI::Shutdown();
 }
--- a/extensions/gio/nsGIOProtocolHandler.cpp
+++ b/extensions/gio/nsGIOProtocolHandler.cpp
@@ -32,17 +32,17 @@
 #include <algorithm>
 
 #define MOZ_GIO_SCHEME              "moz-gio"
 #define MOZ_GIO_SUPPORTED_PROTOCOLS "network.gio.supported-protocols"
 
 //-----------------------------------------------------------------------------
 
 // NSPR_LOG_MODULES=gio:5
-static mozilla::LazyLogModule sGIOLog("gio");
+static PRLogModuleInfo *sGIOLog;
 #define LOG(args) MOZ_LOG(sGIOLog, mozilla::LogLevel::Debug, args)
 
 
 //-----------------------------------------------------------------------------
 static nsresult
 MapGIOResult(gint code) 
 {
   switch (code)
@@ -906,16 +906,18 @@ class nsGIOProtocolHandler final : publi
     nsCString mSupportedProtocols;
 };
 
 NS_IMPL_ISUPPORTS(nsGIOProtocolHandler, nsIProtocolHandler, nsIObserver)
 
 nsresult
 nsGIOProtocolHandler::Init()
 {
+  sGIOLog = PR_NewLogModule("gio");
+
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefs)
   {
     InitSupportedProtocolsPref(prefs);
     prefs->AddObserver(MOZ_GIO_SUPPORTED_PROTOCOLS, this, false);
   }
 
   return NS_OK;
--- a/extensions/pref/autoconfig/src/nsAutoConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.cpp
@@ -21,17 +21,17 @@
 #include "nsNetUtil.h"
 #include "nspr.h"
 #include <algorithm>
 
 #include "mozilla/Logging.h"
 
 using mozilla::LogLevel;
 
-mozilla::LazyLogModule MCD("MCD");
+PRLogModuleInfo *MCD;
 
 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
                                           const char *filename, 
                                           bool bGlobalContext, 
                                           bool bCallbacks, 
                                           bool skipFirstLine);
 
 // nsISupports Implementation
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -14,17 +14,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsJSPrincipals.h"
 #include "nsIScriptError.h"
 #include "jswrapper.h"
 
-extern mozilla::LazyLogModule MCD;
+extern PRLogModuleInfo *MCD;
 using mozilla::AutoSafeJSContext;
 
 //*****************************************************************************
 
 static JS::PersistentRooted<JSObject *> autoconfigSb;
 
 nsresult CentralizedAdminPrefManagerInit()
 {
--- a/extensions/pref/autoconfig/src/nsReadConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp
@@ -21,17 +21,17 @@
 #include "nsNetUtil.h"
 #include "prmem.h"
 #include "nsString.h"
 #include "nsCRT.h"
 #include "nspr.h"
 #include "nsXULAppAPI.h"
 #include "nsContentUtils.h"
 
-extern mozilla::LazyLogModule MCD;
+extern PRLogModuleInfo *MCD;
 
 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
                                           const char *filename, 
                                           bool bGlobalContext, 
                                           bool bCallbacks, 
                                           bool skipFirstLine);
 extern nsresult CentralizedAdminPrefManagerInit();
 extern nsresult CentralizedAdminPrefManagerFinish();
@@ -70,16 +70,18 @@ static void DisplayError(void)
 
 // nsISupports Implementation
 
 NS_IMPL_ISUPPORTS(nsReadConfig, nsIReadConfig, nsIObserver)
 
 nsReadConfig::nsReadConfig() :
     mRead(false)
 {
+    if (!MCD)
+      MCD = PR_NewLogModule("MCD");
 }
 
 nsresult nsReadConfig::Init()
 {
     nsresult rv;
     
     nsCOMPtr<nsIObserverService> observerService = 
         do_GetService("@mozilla.org/observer-service;1", &rv);
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -56,20 +56,23 @@ using namespace mozilla::dom;
     } else {                                      \
       return hal_impl::_call;                     \
     }                                             \
   } while (0)
 
 namespace mozilla {
 namespace hal {
 
-mozilla::LogModule *
+PRLogModuleInfo *
 GetHalLog()
 {
-  static mozilla::LazyLogModule sHalLog("hal");
+  static PRLogModuleInfo *sHalLog;
+  if (!sHalLog) {
+    sHalLog = PR_NewLogModule("hal");
+  }
   return sHalLog;
 }
 
 namespace {
 
 void
 AssertMainThread()
 {
--- a/hal/HalLog.h
+++ b/hal/HalLog.h
@@ -15,17 +15,17 @@
  * This should be considered a private include and not used in non-HAL code.
  * To enable logging in non-debug builds define the PR_FORCE_LOG macro here.
  */
 
 namespace mozilla {
 
 namespace hal {
 
-mozilla::LogModule *GetHalLog();
+extern PRLogModuleInfo *GetHalLog();
 #define HAL_LOG(...) \
   MOZ_LOG(mozilla::hal::GetHalLog(), LogLevel::Debug, (__VA_ARGS__))
 #define HAL_ERR(...) \
   MOZ_LOG(mozilla::hal::GetHalLog(), LogLevel::Error, (__VA_ARGS__))
 
 } // namespace hal
 
 } // namespace mozilla
--- a/ipc/chromium/src/base/logging.cc
+++ b/ipc/chromium/src/base/logging.cc
@@ -37,33 +37,41 @@ Logger::~Logger()
     break;
 
   case LOG_FATAL:
     prlevel = LogLevel::Error;
     xpcomlevel = NS_DEBUG_ABORT;
     break;
   }
 
-  MOZ_LOG(gChromiumPRLog, prlevel, ("%s:%i: %s", mFile, mLine, mMsg ? mMsg : "<no message>"));
+  MOZ_LOG(GetLog(), prlevel, ("%s:%i: %s", mFile, mLine, mMsg ? mMsg : "<no message>"));
   if (xpcomlevel != -1)
     NS_DebugBreak(xpcomlevel, mMsg, NULL, mFile, mLine);
 
   PR_Free(mMsg);
 }
 
 void
 Logger::printf(const char* fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
   mMsg = PR_vsprintf_append(mMsg, fmt, args);
   va_end(args);
 }
 
-LazyLogModule Logger::gChromiumPRLog("chromium");
+PRLogModuleInfo* Logger::gChromiumPRLog;
+
+PRLogModuleInfo* Logger::GetLog()
+{
+  if (!gChromiumPRLog)
+    gChromiumPRLog = PR_NewLogModule("chromium");
+  return gChromiumPRLog;
+}
+
 } // namespace mozilla 
 
 mozilla::Logger&
 operator<<(mozilla::Logger& log, const char* s)
 {
   log.printf("%s", s);
   return log;
 }
--- a/ipc/chromium/src/base/logging.h
+++ b/ipc/chromium/src/base/logging.h
@@ -40,18 +40,18 @@ public:
   { }
 
   ~Logger();
 
   // not private so that the operator<< overloads can get to it
   void printf(const char* fmt, ...);
 
 private:
-  static mozilla::LazyLogModule gChromiumPRLog;
-//  static PRLogModuleInfo* GetLog();
+  static PRLogModuleInfo* gChromiumPRLog;
+  static PRLogModuleInfo* GetLog();
 
   LogSeverity mSeverity;
   const char* mFile;
   int mLine;
   char* mMsg;
 
   DISALLOW_EVIL_CONSTRUCTORS(Logger);
 };
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -1669,21 +1669,16 @@ class MOZ_STACK_CLASS ModuleValidator
         *sigIndex = sigMap_.count();
         if (*sigIndex >= MaxSigs)
             return failCurrentOffset("too many unique signatures");
 
         mg_.initSig(*sigIndex, Move(sig));
         return sigMap_.add(p, &mg_.sig(*sigIndex), *sigIndex);
     }
 
-    // ModuleGeneratorData limits:
-    static const unsigned MaxSigs    =   4 * 1024;
-    static const unsigned MaxFuncs   = 512 * 1024;
-    static const unsigned MaxImports =   4 * 1024;
-
   public:
     ModuleValidator(ExclusiveContext* cx, AsmJSParser& parser, ParseNode* moduleFunctionNode)
       : cx_(cx),
         parser_(parser),
         moduleFunctionNode_(moduleFunctionNode),
         moduleFunctionName_(FunctionName(moduleFunctionNode)),
         standardLibraryMathNames_(cx),
         standardLibraryAtomicsNames_(cx),
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -317,30 +317,36 @@ DecodeFuncBody(JSContext* cx, Decoder& d
 static bool
 DecodeSignatureSection(JSContext* cx, Decoder& d, ModuleGeneratorData* init)
 {
     if (!d.readCStringIf(SigSection))
         return true;
 
     uint32_t sectionStart;
     if (!d.startSection(&sectionStart))
-        return Fail(cx, d, "expected decl section byte size");
+        return Fail(cx, d, "expected signature section byte size");
 
     uint32_t numSigs;
     if (!d.readVarU32(&numSigs))
-        return Fail(cx, d, "expected number of declarations");
+        return Fail(cx, d, "expected number of signatures");
+
+    if (numSigs > MaxSigs)
+        return Fail(cx, d, "too many signatures");
 
     if (!init->sigs.resize(numSigs))
         return false;
 
     for (uint32_t sigIndex = 0; sigIndex < numSigs; sigIndex++) {
         uint32_t numArgs;
         if (!d.readVarU32(&numArgs))
             return Fail(cx, d, "bad number of signature args");
 
+        if (numArgs > MaxArgsPerFunc)
+            return Fail(cx, d, "too many arguments in signature");
+
         ExprType result;
         if (!DecodeExprType(cx, d, &result))
             return false;
 
         ValTypeVector args;
         if (!args.resize(numArgs))
             return false;
 
@@ -382,16 +388,19 @@ DecodeDeclarationSection(JSContext* cx, 
     uint32_t sectionStart;
     if (!d.startSection(&sectionStart))
         return Fail(cx, d, "expected decl section byte size");
 
     uint32_t numDecls;
     if (!d.readVarU32(&numDecls))
         return Fail(cx, d, "expected number of declarations");
 
+    if (numDecls > MaxFuncs)
+        return Fail(cx, d, "too many functions");
+
     if (!init->funcSigs.resize(numDecls))
         return false;
 
     for (uint32_t i = 0; i < numDecls; i++) {
         if (!DecodeSignatureIndex(cx, d, *init, &init->funcSigs[i]))
             return false;
     }
 
@@ -460,16 +469,19 @@ DecodeImportSection(JSContext* cx, Decod
     uint32_t sectionStart;
     if (!d.startSection(&sectionStart))
         return Fail(cx, d, "expected import section byte size");
 
     uint32_t numImports;
     if (!d.readVarU32(&numImports))
         return Fail(cx, d, "expected number of imports");
 
+    if (numImports > MaxImports)
+        return Fail(cx, d, "too many imports");
+
     for (uint32_t i = 0; i < numImports; i++) {
         if (!DecodeImport(cx, d, init, imports))
             return false;
     }
 
     if (!d.finishSection(sectionStart))
         return Fail(cx, d, "import section byte size mismatch");
 
@@ -521,16 +533,19 @@ DecodeExportsSection(JSContext* cx, Deco
     uint32_t sectionStart;
     if (!d.startSection(&sectionStart))
         return Fail(cx, d, "expected export section byte size");
 
     uint32_t numExports;
     if (!d.readVarU32(&numExports))
         return Fail(cx, d, "expected number of exports");
 
+    if (numExports > MaxExports)
+        return Fail(cx, d, "too many exports");
+
     for (uint32_t i = 0; i < numExports; i++) {
         if (!DecodeExport(cx, d, mg, exportMap))
             return false;
     }
 
     if (!d.finishSection(sectionStart))
         return Fail(cx, d, "export section byte size mismatch");
 
--- a/js/src/asmjs/WasmBinary.h
+++ b/js/src/asmjs/WasmBinary.h
@@ -23,16 +23,23 @@
 #include "builtin/SIMD.h"
 
 namespace js {
 
 class PropertyName;
 
 namespace wasm {
 
+// Module generator limits
+static const unsigned MaxSigs        =   4 * 1024;
+static const unsigned MaxFuncs       = 512 * 1024;
+static const unsigned MaxImports     =   4 * 1024;
+static const unsigned MaxExports     =   4 * 1024;
+static const unsigned MaxArgsPerFunc =   4 * 1024;
+
 // Module header constants
 static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
 static const uint32_t EncodingVersion = -1;     // experimental
 
 // Module section names:
 static const char SigSection[] =     "sig";
 static const char DeclSection[] =    "decl";
 static const char ImportSection[] =  "import";
--- a/js/src/jit-test/tests/wasm/binary.js
+++ b/js/src/jit-test/tests/wasm/binary.js
@@ -44,16 +44,18 @@ function toBuf(array) {
 }
 
 function varU32(u32) {
     // TODO
     assertEq(u32 < 128, true);
     return [u32];
 }
 
+const U32MAX_LEB = [255, 255, 255, 255, 15];
+
 function moduleHeaderThen(...rest) {
     return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest];
 }
 
 assertErrorMessage(() => wasmEval(toBuf([])), TypeError, magicError);
 assertErrorMessage(() => wasmEval(toBuf([42])), TypeError, magicError);
 assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2])), TypeError, magicError);
 assertErrorMessage(() => wasmEval(toBuf([1,2,3,4])), TypeError, magicError);
@@ -134,16 +136,22 @@ function importSection(imports) {
     }
     return { name: importSectionStr, body };
 }
 
 const trivialSigSection = sigSection([{args:[], ret:VoidCode}]);
 const trivialDeclSection = declSection([0]);
 const trivialCodeSection = codeSection([{locals:[], body:[0, 0]}]);
 
+assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([ {name: sigSectionStr, body: U32MAX_LEB, } ]))), Error, /too many signatures/);
+assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([ {name: sigSectionStr, body: [1, ...U32MAX_LEB], } ]))), Error, /too many arguments in signature/);
+assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([trivialSigSection, {name: declSectionStr, body: U32MAX_LEB, }]))), Error, /too many functions/);
+assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([trivialSigSection, {name: importSectionStr, body: U32MAX_LEB, }]))), Error, /too many imports/);
+assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([trivialSigSection, {name: exportSectionStr, body: U32MAX_LEB, }]))), Error, /too many exports/);
+
 assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([{name: sigSectionStr, body: [1]}]))), TypeError);
 assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([{name: sigSectionStr, body: [1, 1, 0]}]))), TypeError);
 
 wasmEval(toBuf(moduleWithSections([sigSection([])])));
 wasmEval(toBuf(moduleWithSections([sigSection([{args:[], ret:VoidCode}])])));
 wasmEval(toBuf(moduleWithSections([sigSection([{args:[I32Code], ret:VoidCode}])])));
 
 assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([{args:[], ret:100}])]))), TypeError, /bad expression type/);
--- a/js/src/jit/arm/BaselineIC-arm.cpp
+++ b/js/src/jit/arm/BaselineIC-arm.cpp
@@ -26,18 +26,18 @@ ICCompare_Int32::Compiler::generateStubC
     // Guard that R0 is an integer and R1 is an integer.
     Label failure;
     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
     // Compare payload regs of R0 and R1.
     Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
     masm.cmp32(R0.payloadReg(), R1.payloadReg());
-    masm.ma_mov(Imm32(1), R0.payloadReg(), LeaveCC, cond);
-    masm.ma_mov(Imm32(0), R0.payloadReg(), LeaveCC, Assembler::InvertCondition(cond));
+    masm.ma_mov(Imm32(1), R0.payloadReg(), cond);
+    masm.ma_mov(Imm32(0), R0.payloadReg(), Assembler::InvertCondition(cond));
 
     // Result is implicitly boxed already.
     masm.tagValue(JSVAL_TYPE_BOOLEAN, R0.payloadReg(), R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub.
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
@@ -54,17 +54,17 @@ ICCompare_Double::Compiler::generateStub
 
     Register dest = R0.scratchReg();
 
     Assembler::DoubleCondition doubleCond = JSOpToDoubleCondition(op);
     Assembler::Condition cond = Assembler::ConditionFromDoubleCondition(doubleCond);
 
     masm.compareDouble(FloatReg0, FloatReg1);
     masm.ma_mov(Imm32(0), dest);
-    masm.ma_mov(Imm32(1), dest, LeaveCC, cond);
+    masm.ma_mov(Imm32(1), dest, cond);
 
     masm.tagValue(JSVAL_TYPE_BOOLEAN, dest, R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub.
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -85,17 +85,17 @@ CodeGeneratorARM::visitCompare(LCompare*
     const LAllocation* right = comp->getOperand(1);
     const LDefinition* def = comp->getDef(0);
 
     if (right->isConstant())
         masm.ma_cmp(ToRegister(left), Imm32(ToInt32(right)));
     else
         masm.ma_cmp(ToRegister(left), ToOperand(right));
     masm.ma_mov(Imm32(0), ToRegister(def));
-    masm.ma_mov(Imm32(1), ToRegister(def), LeaveCC, cond);
+    masm.ma_mov(Imm32(1), ToRegister(def), cond);
 }
 
 void
 CodeGeneratorARM::visitCompareAndBranch(LCompareAndBranch* comp)
 {
     Assembler::Condition cond = JSOpToCondition(comp->cmpMir()->compareType(), comp->jsop());
     if (comp->right()->isConstant())
         masm.ma_cmp(ToRegister(comp->left()), Imm32(ToInt32(comp->right())));
@@ -1578,18 +1578,18 @@ CodeGeneratorARM::visitNotD(LNotD* ins)
         masm.as_vmrs(dest);
         masm.ma_lsr(Imm32(28), dest, dest);
         // 28 + 2 = 30
         masm.ma_alu(dest, lsr(dest, 2), dest, OpOrr);
         masm.ma_and(Imm32(1), dest);
     } else {
         masm.as_vmrs(pc);
         masm.ma_mov(Imm32(0), dest);
-        masm.ma_mov(Imm32(1), dest, LeaveCC, Assembler::Equal);
-        masm.ma_mov(Imm32(1), dest, LeaveCC, Assembler::Overflow);
+        masm.ma_mov(Imm32(1), dest, Assembler::Equal);
+        masm.ma_mov(Imm32(1), dest, Assembler::Overflow);
     }
 }
 
 void
 CodeGeneratorARM::visitNotF(LNotF* ins)
 {
     // Since this operation is not, we want to set a bit if the double is
     // falsey, which means 0.0, -0.0 or NaN. When comparing with 0, an input of
@@ -1606,18 +1606,18 @@ CodeGeneratorARM::visitNotF(LNotF* ins)
         masm.as_vmrs(dest);
         masm.ma_lsr(Imm32(28), dest, dest);
         // 28 + 2 = 30
         masm.ma_alu(dest, lsr(dest, 2), dest, OpOrr);
         masm.ma_and(Imm32(1), dest);
     } else {
         masm.as_vmrs(pc);
         masm.ma_mov(Imm32(0), dest);
-        masm.ma_mov(Imm32(1), dest, LeaveCC, Assembler::Equal);
-        masm.ma_mov(Imm32(1), dest, LeaveCC, Assembler::Overflow);
+        masm.ma_mov(Imm32(1), dest, Assembler::Equal);
+        masm.ma_mov(Imm32(1), dest, Assembler::Overflow);
     }
 }
 
 void
 CodeGeneratorARM::visitGuardShape(LGuardShape* guard)
 {
     Register obj = ToRegister(guard->input());
     Register tmp = ToRegister(guard->tempInt());
@@ -2178,17 +2178,17 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAs
                          vd, Assembler::AboveOrEqual);
             masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
         }
     } else {
         Register d = ToRegister(ins->output());
         if (mir->isAtomicAccess())
             masm.ma_b(masm.asmOnOutOfBoundsLabel(), Assembler::AboveOrEqual);
         else
-            masm.ma_mov(Imm32(0), d, LeaveCC, Assembler::AboveOrEqual);
+            masm.ma_mov(Imm32(0), d, Assembler::AboveOrEqual);
         masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg, d, Offset, Assembler::Below);
     }
     memoryBarrier(mir->barrierAfter());
     masm.append(wasm::HeapAccess(bo.getOffset()));
 }
 
 void
 CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins)
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -267,16 +267,20 @@ MacroAssemblerARM::alu_dbl(Register src1
     as_alu(dest, dest, Operand2(both.snd), op, s, c);
     return true;
 }
 
 void
 MacroAssemblerARM::ma_alu(Register src1, Imm32 imm, Register dest,
                           ALUOp op, SBit s, Condition c)
 {
+    // ma_mov should be used for moves.
+    MOZ_ASSERT(op != OpMov);
+    MOZ_ASSERT(op != OpMvn);
+
     // As it turns out, if you ask for a compare-like instruction you *probably*
     // want it to set condition codes.
     if (dest == InvalidReg)
         MOZ_ASSERT(s == SetCC);
 
     // The operator gives us the ability to determine how this can be used.
     Imm8 imm8 = Imm8(imm.value);
     // One instruction: If we can encode it using an imm8m, then do so.
@@ -296,115 +300,44 @@ MacroAssemblerARM::ma_alu(Register src1,
     // used) dest, but its negation is bic *requires* a dest. We can accomodate,
     // but it will need to clobber *something*, and the scratch register isn't
     // being used, so...
     if (negOp != OpInvalid && !negImm8.invalid) {
         as_alu(negDest, src1, negImm8, negOp, s, c);
         return;
     }
 
-    if (HasMOVWT()) {
-        // If the operation is a move-a-like then we can try to use movw to move
-        // the bits into the destination. Otherwise, we'll need to fall back on
-        // a multi-instruction format :(
-        // movw/movt does not set condition codes, so don't hold your breath.
-        if (s == LeaveCC && (op == OpMov || op == OpMvn)) {
-            // ARMv7 supports movw/movt. movw zero-extends its 16 bit argument,
-            // so we can set the register this way. movt leaves the bottom 16
-            // bits in tact, so it is unsuitable to move a constant that
-            if (op == OpMov && ((imm.value & ~ 0xffff) == 0)) {
-                MOZ_ASSERT(src1 == InvalidReg);
-                as_movw(dest, Imm16((uint16_t)imm.value), c);
-                return;
-            }
-
-            // If they asked for a mvn rfoo, imm, where ~imm fits into 16 bits
-            // then do it.
-            if (op == OpMvn && (((~imm.value) & ~ 0xffff) == 0)) {
-                MOZ_ASSERT(src1 == InvalidReg);
-                as_movw(dest, Imm16((uint16_t)~imm.value), c);
-                return;
-            }
-
-            // TODO: constant dedup may enable us to add dest, r0, 23 *if* we
-            // are attempting to load a constant that looks similar to one that
-            // already exists. If it can't be done with a single movw then we
-            // *need* to use two instructions since this must be some sort of a
-            // move operation, we can just use a movw/movt pair and get the
-            // whole thing done in two moves. This does not work for ops like
-            // add, since we'd need to do: movw tmp; movt tmp; add dest, tmp,
-            // src1.
-            if (op == OpMvn)
-                imm.value = ~imm.value;
-            as_movw(dest, Imm16(imm.value & 0xffff), c);
-            as_movt(dest, Imm16((imm.value >> 16) & 0xffff), c);
-            return;
-        }
-        // If we weren't doing a movalike, a 16 bit immediate will require 2
-        // instructions. With the same amount of space and (less)time, we can do
-        // two 8 bit operations, reusing the dest register. e.g.
-        //  movw tmp, 0xffff; add dest, src, tmp ror 4
-        // vs.
-        //  add dest, src, 0xff0; add dest, dest, 0xf000000f
-        //
-        // It turns out that there are some immediates that we miss with the
-        // second approach. A sample value is: add dest, src, 0x1fffe this can
-        // be done by movw tmp, 0xffff; add dest, src, tmp lsl 1 since imm8m's
-        // only get even offsets, we cannot encode this. I'll try to encode as
-        // two imm8's first, since they are faster. Both operations should take
-        // 1 cycle, where as add dest, tmp ror 4 takes two cycles to execute.
-    }
-
-    // Either a) this isn't ARMv7 b) this isn't a move start by attempting to
-    // generate a two instruction form. Some things cannot be made into two-inst
-    // forms correctly. Namely, adds dest, src, 0xffff. Since we want the
-    // condition codes (and don't know which ones will be checked), we need to
-    // assume that the overflow flag will be checked and add{,s} dest, src,
-    // 0xff00; add{,s} dest, dest, 0xff is not guaranteed to set the overflow
-    // flag the same as the (theoretical) one instruction variant.
+    // Start by attempting to generate a two instruction form. Some things
+    // cannot be made into two-inst forms correctly. Namely, adds dest, src,
+    // 0xffff. Since we want the condition codes (and don't know which ones
+    // will be checked), we need to assume that the overflow flag will be
+    // checked and add{,s} dest, src, 0xff00; add{,s} dest, dest, 0xff is not
+    // guaranteed to set the overflof flag the same as the (theoretical) one
+    // instruction variant.
     if (alu_dbl(src1, imm, dest, op, s, c))
         return;
 
     // And try with its negative.
-    if (negOp != OpInvalid &&
-        alu_dbl(src1, negImm, negDest, negOp, s, c))
+    if (negOp != OpInvalid && alu_dbl(src1, negImm, negDest, negOp, s, c))
         return;
 
     // Often this code is called with dest as the ScratchRegister.  The register
     // is logically owned by the caller after this call.
     const Register& scratch = ScratchRegister;
     MOZ_ASSERT(src1 != scratch);
 #ifdef DEBUG
     if (dest != scratch) {
         // If the destination register is not the scratch register, double check
         // that the current function does not erase the content of the scratch
         // register.
         ScratchRegisterScope assertScratch(asMasm());
     }
 #endif
 
-    // Well, damn. We can use two 16 bit mov's, then do the op or we can do a
-    // single load from a pool then op.
-    if (HasMOVWT()) {
-        // Try to load the immediate into a scratch register then use that
-        as_movw(scratch, Imm16(imm.value & 0xffff), c);
-        if ((imm.value >> 16) != 0)
-            as_movt(scratch, Imm16((imm.value >> 16) & 0xffff), c);
-    } else {
-        // Going to have to use a load. If the operation is a move, then just
-        // move it into the destination register
-        if (op == OpMov) {
-            as_Imm32Pool(dest, imm.value, c);
-            return;
-        } else {
-            // If this isn't just going into a register, then stick it in a
-            // temp, and then proceed.
-            as_Imm32Pool(scratch, imm.value, c);
-        }
-    }
+    ma_mov(imm, scratch, c);
     as_alu(dest, src1, O2Reg(scratch), op, s, c);
 }
 
 void
 MacroAssemblerARM::ma_alu(Register src1, Operand op2, Register dest, ALUOp op,
             SBit s, Assembler::Condition c)
 {
     MOZ_ASSERT(op2.getTag() == Operand::OP2);
@@ -474,27 +407,54 @@ MacroAssemblerARM::ma_mov_patch(ImmPtr i
 void
 MacroAssemblerARM::ma_mov(Register src, Register dest, SBit s, Assembler::Condition c)
 {
     if (s == SetCC || dest != src)
         as_mov(dest, O2Reg(src), s, c);
 }
 
 void
-MacroAssemblerARM::ma_mov(Imm32 imm, Register dest,
-                          SBit s, Assembler::Condition c)
-{
-    ma_alu(InvalidReg, imm, dest, OpMov, s, c);
-}
-
-void
-MacroAssemblerARM::ma_mov(ImmWord imm, Register dest,
-                          SBit s, Assembler::Condition c)
-{
-    ma_alu(InvalidReg, Imm32(imm.value), dest, OpMov, s, c);
+MacroAssemblerARM::ma_mov(Imm32 imm, Register dest, Assembler::Condition c)
+{
+    // Try mov with Imm8 operand.
+    Imm8 imm8 = Imm8(imm.value);
+    if (!imm8.invalid) {
+        as_alu(dest, InvalidReg, imm8, OpMov, LeaveCC, c);
+        return;
+    }
+
+    // Try mvn with Imm8 operand.
+    Imm32 negImm = imm;
+    Register negDest;
+    ALUOp negOp = ALUNeg(OpMov, dest, &negImm, &negDest);
+    Imm8 negImm8 = Imm8(negImm.value);
+    if (negOp != OpInvalid && !negImm8.invalid) {
+        as_alu(negDest, InvalidReg, negImm8, negOp, LeaveCC, c);
+        return;
+    }
+
+    // Try movw/movt.
+    if (HasMOVWT()) {
+        // ARMv7 supports movw/movt. movw zero-extends its 16 bit argument,
+        // so we can set the register this way. movt leaves the bottom 16
+        // bits in tact, so we always need a movw.
+        as_movw(dest, Imm16(imm.value & 0xffff), c);
+        if (uint32_t(imm.value) >> 16)
+            as_movt(dest, Imm16(uint32_t(imm.value) >> 16), c);
+        return;
+    }
+
+    // If we don't have movw/movt, we need a load.
+    as_Imm32Pool(dest, imm.value, c);
+}
+
+void
+MacroAssemblerARM::ma_mov(ImmWord imm, Register dest, Assembler::Condition c)
+{
+    ma_mov(Imm32(imm.value), dest, c);
 }
 
 void
 MacroAssemblerARM::ma_mov(ImmGCPtr ptr, Register dest)
 {
     // As opposed to x86/x64 version, the data relocation has to be executed
     // before to recover the pointer, and not after.
     writeDataRelocation(ptr);
@@ -562,22 +522,16 @@ MacroAssemblerARM::ma_rol(Register shift
 {
     ScratchRegisterScope scratch(asMasm());
     ma_rsb(shift, Imm32(32), scratch);
     as_mov(dst, ror(src, scratch));
 }
 
 // Move not (dest <- ~src)
 void
-MacroAssemblerARM::ma_mvn(Imm32 imm, Register dest, SBit s, Assembler::Condition c)
-{
-    ma_alu(InvalidReg, imm, dest, OpMvn, s, c);
-}
-
-void
 MacroAssemblerARM::ma_mvn(Register src1, Register dest, SBit s, Assembler::Condition c)
 {
     as_alu(dest, InvalidReg, O2Reg(src1), OpMvn, s, c);
 }
 
 // Negate (dest <- -src), src is a register, rather than a general op2.
 void
 MacroAssemblerARM::ma_neg(Register src1, Register dest, SBit s, Assembler::Condition c)
@@ -1010,17 +964,17 @@ MacroAssemblerARM::ma_mod_mask(Register 
     // Note that we cannot use ScratchRegister in place of tmp here, as ma_and
     // below on certain architectures move the mask into ScratchRegister before
     // performing the bitwise and.
     as_mov(tmp, O2Reg(src), SetCC);
     // Zero out the dest.
     ma_mov(Imm32(0), dest);
     // Set the hold appropriately.
     ma_mov(Imm32(1), hold);
-    ma_mov(Imm32(-1), hold, LeaveCC, Signed);
+    ma_mov(Imm32(-1), hold, Signed);
     ma_rsb(Imm32(0), tmp, SetCC, Signed);
 
     // Begin the main loop.
     bind(&head);
     {
         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
 
         // Extract the bottom bits into lr.
@@ -2405,20 +2359,20 @@ MacroAssembler::clampDoubleToUint8(Float
         ma_vcmpz(input);
         // Do the add, in place so we can reference it later.
         ma_vadd(input, scratchDouble, input);
         // Do the conversion to an integer.
         as_vcvt(VFPRegister(scratchDouble).uintOverlay(), VFPRegister(input));
         // Copy the converted value out.
         as_vxfer(output, InvalidReg, scratchDouble, FloatToCore);
         as_vmrs(pc);
-        ma_mov(Imm32(0), output, LeaveCC, Overflow);  // NaN => 0
+        ma_mov(Imm32(0), output, Overflow);  // NaN => 0
         ma_b(&outOfRange, Overflow);  // NaN
         ma_cmp(output, Imm32(0xff));
-        ma_mov(Imm32(0xff), output, LeaveCC, Above);
+        ma_mov(Imm32(0xff), output, Above);
         ma_b(&outOfRange, Above);
         // Convert it back to see if we got the same value back.
         as_vcvt(scratchDouble, VFPRegister(scratchDouble).uintOverlay());
         // Do the check.
         as_vcmp(scratchDouble, input);
         as_vmrs(pc);
         ma_bic(Imm32(1), output, LeaveCC, Zero);
         bind(&outOfRange);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -118,52 +118,40 @@ class MacroAssemblerARM : public Assembl
     void ma_movPatchable(Imm32 imm, Register dest, Assembler::Condition c);
     void ma_movPatchable(ImmPtr imm, Register dest, Assembler::Condition c);
 
     static void ma_mov_patch(Imm32 imm, Register dest, Assembler::Condition c,
                              RelocStyle rs, Instruction* i);
     static void ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
                              RelocStyle rs, Instruction* i);
 
-    // These should likely be wrapped up as a set of macros or something like
-    // that. I cannot think of a good reason to explicitly have all of this
-    // code.
-
     // ALU based ops
     // mov
-    void ma_mov(Register src, Register dest,
-                SBit s = LeaveCC, Condition c = Always);
+    void ma_mov(Register src, Register dest, SBit s = LeaveCC, Condition c = Always);
 
-    void ma_mov(Imm32 imm, Register dest,
-                SBit s = LeaveCC, Condition c = Always);
-    void ma_mov(ImmWord imm, Register dest,
-                SBit s = LeaveCC, Condition c = Always);
+    void ma_mov(Imm32 imm, Register dest, Condition c = Always);
+    void ma_mov(ImmWord imm, Register dest, Condition c = Always);
 
     void ma_mov(ImmGCPtr ptr, Register dest);
 
     // Shifts (just a move with a shifting op2)
     void ma_lsl(Imm32 shift, Register src, Register dst);
     void ma_lsr(Imm32 shift, Register src, Register dst);
     void ma_asr(Imm32 shift, Register src, Register dst);
     void ma_ror(Imm32 shift, Register src, Register dst);
     void ma_rol(Imm32 shift, Register src, Register dst);
-    // Shifts (just a move with a shifting op2)
+
     void ma_lsl(Register shift, Register src, Register dst);
     void ma_lsr(Register shift, Register src, Register dst);
     void ma_asr(Register shift, Register src, Register dst);
     void ma_ror(Register shift, Register src, Register dst);
     void ma_rol(Register shift, Register src, Register dst);
 
     // Move not (dest <- ~src)
-    void ma_mvn(Imm32 imm, Register dest,
-                SBit s = LeaveCC, Condition c = Always);
-
-
-    void ma_mvn(Register src1, Register dest,
-                SBit s = LeaveCC, Condition c = Always);
+    void ma_mvn(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
 
     // Negate (dest <- -src) implemented as rsb dest, src, 0
     void ma_neg(Register src, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
 
     // And
     void ma_and(Register src, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
@@ -172,18 +160,16 @@ class MacroAssemblerARM : public Assembl
                 SBit s = LeaveCC, Condition c = Always);
 
     void ma_and(Imm32 imm, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
 
     void ma_and(Imm32 imm, Register src1, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
 
-
-
     // Bit clear (dest <- dest & ~imm) or (dest <- src1 & ~src2)
     void ma_bic(Imm32 imm, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
 
     // Exclusive or
     void ma_eor(Register src, Register dest,
                 SBit s = LeaveCC, Condition c = Always);
 
@@ -1590,18 +1576,18 @@ class MacroAssemblerARMCompat : public M
     void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value,
                                        Register temp, AnyRegister output);
 
     void clampIntToUint8(Register reg) {
         // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
         // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
         ScratchRegisterScope scratch(asMasm());
         as_mov(scratch, asr(reg, 8), SetCC);
-        ma_mov(Imm32(0xff), reg, LeaveCC, NotEqual);
-        ma_mov(Imm32(0), reg, LeaveCC, Signed);
+        ma_mov(Imm32(0xff), reg, NotEqual);
+        ma_mov(Imm32(0), reg, Signed);
     }
 
     inline void incrementInt32Value(const Address& addr);
 
     void cmp32(Register lhs, Imm32 rhs);
     void cmp32(Register lhs, Register rhs);
     void cmp32(const Operand& lhs, Imm32 rhs);
     void cmp32(const Operand& lhs, Register rhs);
@@ -1643,17 +1629,17 @@ class MacroAssemblerARMCompat : public M
     // If source is a double, load it into dest. If source is int32, convert it
     // to double. Else, branch to failure.
     void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
 
     void
     emitSet(Assembler::Condition cond, Register dest)
     {
         ma_mov(Imm32(0), dest);
-        ma_mov(Imm32(1), dest, LeaveCC, cond);
+        ma_mov(Imm32(1), dest, cond);
     }
 
     template <typename T1, typename T2>
     void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
     {
         cmpPtr(lhs, rhs);
         emitSet(cond, dest);
     }
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -66,17 +66,17 @@ static const char kJSCachePrefix[] = "js
 /**
  * Buffer sizes for serialization and deserialization of scripts.
  * FIXME: bug #411579 (tune this macro!) Last updated: Jan 2008
  */
 #define XPC_SERIALIZATION_BUFFER_SIZE   (64 * 1024)
 #define XPC_DESERIALIZATION_BUFFER_SIZE (12 * 8192)
 
 // NSPR_LOG_MODULES=JSComponentLoader:5
-static LazyLogModule gJSCLLog("JSComponentLoader");
+static PRLogModuleInfo* gJSCLLog;
 
 #define LOG(args) MOZ_LOG(gJSCLLog, mozilla::LogLevel::Debug, args)
 
 // Components.utils.import error messages
 #define ERROR_SCOPE_OBJ "%s - Second argument must be an object."
 #define ERROR_NOT_PRESENT "%s - EXPORTED_SYMBOLS is not present."
 #define ERROR_NOT_AN_ARRAY "%s - EXPORTED_SYMBOLS is not an array."
 #define ERROR_GETTING_ARRAY_LENGTH "%s - Error getting array length of EXPORTED_SYMBOLS."
@@ -193,16 +193,20 @@ mozJSComponentLoader::mozJSComponentLoad
     : mModules(16),
       mImports(16),
       mInProgressImports(16),
       mInitialized(false),
       mReuseLoaderGlobal(false)
 {
     MOZ_ASSERT(!sSelf, "mozJSComponentLoader should be a singleton");
 
+    if (!gJSCLLog) {
+        gJSCLLog = PR_NewLogModule("JSComponentLoader");
+    }
+
     sSelf = this;
 }
 
 #define ENSURE_DEP(name) { nsresult rv = Ensure##name(); NS_ENSURE_SUCCESS(rv, rv); }
 #define ENSURE_DEPS(...) MOZ_FOR_EACH(ENSURE_DEP, (), (__VA_ARGS__));
 #define BEGIN_ENSURE(self, ...) { \
     if (m##self) \
         return NS_OK; \
--- a/js/xpconnect/src/XPCLog.cpp
+++ b/js/xpconnect/src/XPCLog.cpp
@@ -20,37 +20,40 @@
 #define LINE_LEN        200
 #define INDENT_FACTOR   2
 
 #define CAN_RUN (g_InitState == 1 || (g_InitState == 0 && Init()))
 
 static char*    g_Spaces;
 static int      g_InitState = 0;
 static int      g_Indent = 0;
-static mozilla::LazyLogModule g_LogMod("xpclog");
+static PRLogModuleInfo* g_LogMod = nullptr;
 
 static bool Init()
 {
+    g_LogMod = PR_NewLogModule("xpclog");
     g_Spaces = new char[SPACE_COUNT+1];
-    if (!g_Spaces || !MOZ_LOG_TEST(g_LogMod,LogLevel::Error)) {
+    if (!g_LogMod || !g_Spaces || !MOZ_LOG_TEST(g_LogMod,LogLevel::Error)) {
         g_InitState = 1;
         XPC_Log_Finish();
         return false;
     }
     memset(g_Spaces, ' ', SPACE_COUNT);
     g_Spaces[SPACE_COUNT] = 0;
     g_InitState = 1;
     return true;
 }
 
 void
 XPC_Log_Finish()
 {
     if (g_InitState == 1) {
         delete [] g_Spaces;
+        // we'd like to properly cleanup the LogModule, but nspr owns that
+        g_LogMod = nullptr;
     }
     g_InitState = -1;
 }
 
 void
 XPC_Log_print(const char* fmt, ...)
 {
     va_list ap;
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -197,17 +197,17 @@ xpc::ErrorReport::Init(JSErrorReport* aR
     mSourceLine = static_cast<const char16_t*>(aReport->uclinebuf);
 
     mLineNumber = aReport->lineno;
     mColumn = aReport->column;
     mFlags = aReport->flags;
     mIsMuted = aReport->isMuted;
 }
 
-static LazyLogModule gJSDiagnostics("JSDiagnostics");
+static PRLogModuleInfo* gJSDiagnostics;
 
 void
 xpc::ErrorReport::LogToConsole()
 {
   LogToConsoleWithStack(nullptr);
 }
 void
 xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
@@ -227,20 +227,25 @@ xpc::ErrorReport::LogToConsoleWithStack(
         error.AppendInt(mLineNumber, 10);
         error.AppendLiteral(": ");
         error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
 
         fprintf(stderr, "%s\n", error.get());
         fflush(stderr);
     }
 
-    MOZ_LOG(gJSDiagnostics,
-            JSREPORT_IS_WARNING(mFlags) ? LogLevel::Warning : LogLevel::Error,
-            ("file %s, line %u\n%s", NS_LossyConvertUTF16toASCII(mFileName).get(),
-             mLineNumber, NS_LossyConvertUTF16toASCII(mErrorMsg).get()));
+    // Log to the PR Log Module.
+    if (!gJSDiagnostics)
+        gJSDiagnostics = PR_NewLogModule("JSDiagnostics");
+    if (gJSDiagnostics) {
+        MOZ_LOG(gJSDiagnostics,
+                JSREPORT_IS_WARNING(mFlags) ? LogLevel::Warning : LogLevel::Error,
+                ("file %s, line %u\n%s", NS_LossyConvertUTF16toASCII(mFileName).get(),
+                 mLineNumber, NS_LossyConvertUTF16toASCII(mErrorMsg).get()));
+    }
 
     // Log to the console. We do this last so that we can simply return if
     // there's no console service without affecting the other reporting
     // mechanisms.
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
 
     nsCOMPtr<nsIScriptError> errorObject;
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -218,23 +218,23 @@ SyncViewsAndInvalidateDescendants(nsIFra
  */
 static nsIFrame*
 GetFrameForChildrenOnlyTransformHint(nsIFrame *aFrame)
 {
   if (aFrame->GetType() == nsGkAtoms::viewportFrame) {
     // This happens if the root-<svg> is fixed positioned, in which case we
     // can't use aFrame->GetContent() to find the primary frame, since
     // GetContent() returns nullptr for ViewportFrame.
-    aFrame = aFrame->GetFirstPrincipalChild();
+    aFrame = aFrame->PrincipalChildList().FirstChild();
   }
   // For an nsHTMLScrollFrame, this will get the SVG frame that has the
   // children-only transforms:
   aFrame = aFrame->GetContent()->GetPrimaryFrame();
   if (aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
-    aFrame = aFrame->GetFirstPrincipalChild();
+    aFrame = aFrame->PrincipalChildList().FirstChild();
     MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame,
                "Where is the nsSVGOuterSVGFrame's anon child??");
   }
   MOZ_ASSERT(aFrame->IsFrameOfType(nsIFrame::eSVG |
                                    nsIFrame::eSVGContainer),
              "Children-only transforms only expected on SVG frames");
   return aFrame;
 }
@@ -322,17 +322,17 @@ DoApplyRenderingChangeToTree(nsIFrame* a
           nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(layer,
             nullptr, nullptr, aFrame, eCSSProperty_transform);
         }
       }
     }
     if (aChange & nsChangeHint_ChildrenOnlyTransform) {
       needInvalidatingPaint = true;
       nsIFrame* childFrame =
-        GetFrameForChildrenOnlyTransformHint(aFrame)->GetFirstPrincipalChild();
+        GetFrameForChildrenOnlyTransformHint(aFrame)->PrincipalChildList().FirstChild();
       for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
         ActiveLayerTracker::NotifyRestyle(childFrame, eCSSProperty_transform);
       }
     }
     if (aChange & nsChangeHint_SchedulePaint) {
       needInvalidatingPaint = true;
     }
     aFrame->SchedulePaint(needInvalidatingPaint ?
@@ -897,17 +897,17 @@ RestyleManager::ProcessRestyledFrames(ns
           // subsumes some of the other hints:
           hint = NS_SubtractHint(hint,
                    NS_CombineHint(nsChangeHint_UpdateOverflow,
                                   nsChangeHint_UpdatePostTransformOverflow));
         }
         if (hint & nsChangeHint_ChildrenOnlyTransform) {
           // The overflow areas of the child frames need to be updated:
           nsIFrame* hintFrame = GetFrameForChildrenOnlyTransformHint(frame);
-          nsIFrame* childFrame = hintFrame->GetFirstPrincipalChild();
+          nsIFrame* childFrame = hintFrame->PrincipalChildList().FirstChild();
           NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame),
                        "SVG frames should not have continuations "
                        "or ib-split siblings");
           NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrIBSplitSibling(hintFrame),
                        "SVG frames should not have continuations "
                        "or ib-split siblings");
           for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
             MOZ_ASSERT(childFrame->IsFrameOfType(nsIFrame::eSVG),
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -459,17 +459,17 @@ IsBidiSplittable(nsIFrame* aFrame)
           frameType != nsGkAtoms::lineFrame) ||
          frameType == nsGkAtoms::textFrame;
 }
 
 // Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
 static bool
 IsBidiLeaf(nsIFrame* aFrame)
 {
-  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
+  nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   return !kid || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
 }
 
 /**
  * Create non-fluid continuations for the ancestors of a given frame all the way
  * up the frame tree until we hit a non-splittable frame (a line or a block).
  *
  * @param aParent the first parent frame to be split
@@ -665,17 +665,17 @@ nsBidiPresUtils::Resolve(nsBlockFrame* a
   if (ch != 0) {
     bpd.PushBidiControl(ch);
   }
   for (nsBlockFrame* block = aBlockFrame; block;
        block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
     block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
     nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
     bpd.ResetForNewBlock();
-    TraverseFrames(aBlockFrame, &lineIter, block->GetFirstPrincipalChild(), &bpd);
+    TraverseFrames(aBlockFrame, &lineIter, block->PrincipalChildList().FirstChild(), &bpd);
     // XXX what about overflow lines?
   }
 
   if (ch != 0) {
     bpd.PopBidiControl();
   }
 
   BidiParagraphData* subParagraph = bpd.GetSubParagraph();
@@ -1179,17 +1179,17 @@ nsBidiPresUtils::TraverseFrames(nsBlockF
                             kZWSP : kObjectSubstitute);
         if (!frame->IsInlineOutside()) {
           // if it is not inline, end the paragraph
           ResolveParagraphWithinBlock(aBlockFrame, aBpd);
         }
       }
     } else {
       // For a non-leaf frame, recurse into TraverseFrames
-      nsIFrame* kid = frame->GetFirstPrincipalChild();
+      nsIFrame* kid = frame->PrincipalChildList().FirstChild();
       MOZ_ASSERT(!frame->GetChildList(nsIFrame::kOverflowList).FirstChild(),
                  "should have drained the overflow list above");
       if (kid) {
         const nsStyleTextReset* text = frame->StyleTextReset();
         if (text->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_ISOLATE ||
             text->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
           // css "unicode-bidi: isolate" and html5 bdi: 
           //  resolve the element as a separate paragraph
@@ -1258,17 +1258,17 @@ nsBidiPresUtils::ReorderFrames(nsIFrame*
   nsSize containerSize(aContainerSize);
 
   // If this line consists of a line frame, reorder the line frame's children.
   if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
     // The line frame is positioned at the start-edge, so use its size
     // as the container size.
     containerSize = aFirstFrameOnLine->GetSize();
 
-    aFirstFrameOnLine = aFirstFrameOnLine->GetFirstPrincipalChild();
+    aFirstFrameOnLine = aFirstFrameOnLine->PrincipalChildList().FirstChild();
     if (!aFirstFrameOnLine) {
       return 0;
     }
     // All children of the line frame are on the first line. Setting aNumFramesOnLine
     // to -1 makes InitLogicalArrayFromLine look at all of them.
     aNumFramesOnLine = -1;
   }
 
@@ -1276,17 +1276,17 @@ nsBidiPresUtils::ReorderFrames(nsIFrame*
   return RepositionInlineFrames(&bld, aLineWM, containerSize, aStart);
 }
 
 nsIFrame*
 nsBidiPresUtils::GetFirstLeaf(nsIFrame* aFrame)
 {
   nsIFrame* firstLeaf = aFrame;
   while (!IsBidiLeaf(firstLeaf)) {
-    nsIFrame* firstChild = firstLeaf->GetFirstPrincipalChild();
+    nsIFrame* firstChild = firstLeaf->PrincipalChildList().FirstChild();
     nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(firstChild);
     firstLeaf = (realFrame->GetType() == nsGkAtoms::letterFrame) ?
                  realFrame : firstChild;
   }
   return firstLeaf;
 }
 
 nsBidiLevel
@@ -1302,17 +1302,17 @@ nsBidiPresUtils::GetParagraphDepth(nsIFr
 }
 
 
 nsBidiLevel
 nsBidiPresUtils::GetFrameBaseLevel(nsIFrame* aFrame)
 {
   nsIFrame* firstLeaf = aFrame;
   while (!IsBidiLeaf(firstLeaf)) {
-    firstLeaf = firstLeaf->GetFirstPrincipalChild();
+    firstLeaf = firstLeaf->PrincipalChildList().FirstChild();
   }
   return NS_GET_BASE_LEVEL(firstLeaf);
 }
 
 void
 nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
                                const nsContinuationStates* aContinuationStates,
                                bool aSpanDirMatchesLineDir,
@@ -1645,20 +1645,17 @@ nsBidiPresUtils::InitContinuationStates(
                                         nsContinuationStates*  aContinuationStates)
 {
   nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame);
   state->mFirstVisualFrame = nullptr;
   state->mFrameCount = 0;
 
   if (!IsBidiLeaf(aFrame) || RubyUtils::IsRubyBox(aFrame->GetType())) {
     // Continue for child frames
-    nsIFrame* frame;
-    for (frame = aFrame->GetFirstPrincipalChild();
-         frame;
-         frame = frame->GetNextSibling()) {
+    for (nsIFrame* frame : aFrame->PrincipalChildList()) {
       InitContinuationStates(frame,
                              aContinuationStates);
     }
   }
 }
 
 /* static */ nscoord
 nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -356,17 +356,17 @@ AssertAnonymousFlexOrGridItemParent(cons
 #else
 #define AssertAnonymousFlexOrGridItemParent(x, y) do { /* nothing */ } while(0)
 #endif
 
 static inline nsContainerFrame*
 GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
 {
   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
-  nsIFrame* firstChild = aFieldsetFrame->GetFirstPrincipalChild();
+  nsIFrame* firstChild = aFieldsetFrame->PrincipalChildList().FirstChild();
   nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
   return inner ? inner->GetContentInsertionFrame() : nullptr;
 }
 
 #define FCDATA_DECL(_flags, _func)                          \
   { _flags, { (FrameCreationFunc)_func }, nullptr, nullptr }
 #define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
   { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
@@ -487,17 +487,17 @@ static nsContainerFrame* GetIBSplitPrevS
 }
 
 static nsContainerFrame*
 GetLastIBSplitSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
 {
   for (nsIFrame *frame = aFrame, *next; ; frame = next) {
     next = GetIBSplitSibling(frame);
     if (!next ||
-        (!aReturnEmptyTrailingInline && !next->GetFirstPrincipalChild() &&
+        (!aReturnEmptyTrailingInline && !next->PrincipalChildList().FirstChild() &&
          !GetIBSplitSibling(next))) {
       NS_ASSERTION(!next || !frame->IsInlineOutside(),
                    "Should have a block here!");
       return static_cast<nsContainerFrame*>(frame);
     }
   }
   NS_NOTREACHED("unreachable code");
   return nullptr;
@@ -1862,19 +1862,19 @@ IsTablePseudo(nsIFrame* aFrame)
      pseudoType == nsCSSAnonBoxes::tableColGroup ||
      pseudoType == nsCSSAnonBoxes::tableRowGroup ||
      pseudoType == nsCSSAnonBoxes::tableRow ||
      pseudoType == nsCSSAnonBoxes::tableCell ||
      (pseudoType == nsCSSAnonBoxes::cellContent &&
       aFrame->GetParent()->StyleContext()->GetPseudo() ==
         nsCSSAnonBoxes::tableCell) ||
      (pseudoType == nsCSSAnonBoxes::tableOuter &&
-      (aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo() ==
+      (aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo() ==
          nsCSSAnonBoxes::table ||
-       aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo() ==
+       aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo() ==
          nsCSSAnonBoxes::inlineTable)));
 }
 
 static bool
 IsRubyPseudo(nsIFrame* aFrame)
 {
   return RubyUtils::IsRubyPseudo(aFrame->StyleContext()->GetPseudo());
 }
@@ -2881,34 +2881,34 @@ nsCSSFrameConstructor::ConstructPageFram
 
   nsContainerFrame* pageContentFrame =
     NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
 
   // Initialize the page content frame and force it to have a view. Also make it the
   // containing block for fixed elements which are repeated on every page.
   nsIFrame* prevPageContentFrame = nullptr;
   if (aPrevPageFrame) {
-    prevPageContentFrame = aPrevPageFrame->GetFirstPrincipalChild();
+    prevPageContentFrame = aPrevPageFrame->PrincipalChildList().FirstChild();
     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
   }
   pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
   SetInitialSingleChild(pageFrame, pageContentFrame);
   // Make it an absolute container for fixed-pos elements
   pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   pageContentFrame->MarkAsAbsoluteContainingBlock();
 
   RefPtr<nsStyleContext> canvasPseudoStyle;
   canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
                                                          pageContentPseudoStyle);
 
   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
 
   nsIFrame* prevCanvasFrame = nullptr;
   if (prevPageContentFrame) {
-    prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
+    prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
     NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
   }
   aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
   SetInitialSingleChild(pageContentFrame, aCanvasFrame);
   return pageFrame;
 }
 
 /* static */
@@ -6177,17 +6177,17 @@ AdjustAppendParentForAfterContent(nsFram
  * null).
  */
 static nsIFrame*
 FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
 {
   if (aAfterFrame) {
     NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
     NS_ASSERTION(aAfterFrame->GetPrevSibling() ||
-                 aParentFrame->GetFirstPrincipalChild() == aAfterFrame,
+                 aParentFrame->PrincipalChildList().FirstChild() == aAfterFrame,
                  ":after frame must be on the principal child list here");
     return aAfterFrame->GetPrevSibling();
   }
 
   aParentFrame->DrainSelfOverflowList();
 
   return aParentFrame->GetChildList(kPrincipalList).LastChild();
 }
@@ -6198,43 +6198,43 @@ FindAppendPrevSibling(nsIFrame* aParentF
  */
 static nsIFrame*
 GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling)
 {
   if (aPrevSibling) {
     return aPrevSibling->GetNextSibling();
   }
 
-  return aParentFrame->GetFirstPrincipalChild();
+  return aParentFrame->PrincipalChildList().FirstChild();
 }
 
 /**
  * This function is called by ContentAppended() and ContentInserted() when
  * appending flowed frames to a parent's principal child list. It handles the
  * case where the parent is the trailing inline of an {ib} split.
  */
 nsresult
 nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&       aState,
                                             nsContainerFrame*              aParentFrame,
                                             nsFrameItems&                  aFrameList,
                                             nsIFrame*                      aPrevSibling,
                                             bool                           aIsRecursiveCall)
 {
   NS_PRECONDITION(!IsFramePartOfIBSplit(aParentFrame) ||
                   !GetIBSplitSibling(aParentFrame) ||
-                  !GetIBSplitSibling(aParentFrame)->GetFirstPrincipalChild(),
+                  !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild(),
                   "aParentFrame has a ib-split sibling with kids?");
   NS_PRECONDITION(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,
                   "Parent and prevsibling don't match");
 
   nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
 
   NS_ASSERTION(nextSibling ||
                !aParentFrame->GetNextContinuation() ||
-               !aParentFrame->GetNextContinuation()->GetFirstPrincipalChild() ||
+               !aParentFrame->GetNextContinuation()->PrincipalChildList().FirstChild() ||
                aIsRecursiveCall,
                "aParentFrame has later continuations with kids?");
   NS_ASSERTION(nextSibling ||
                !IsFramePartOfIBSplit(aParentFrame) ||
                (IsInlineFrame(aParentFrame) &&
                 !GetIBSplitSibling(aParentFrame) &&
                 !aParentFrame->GetNextContinuation()) ||
                aIsRecursiveCall,
@@ -7715,17 +7715,17 @@ nsCSSFrameConstructor::ContentRangeInser
       container = insertion.mParentFrame->GetContent();
       frameType = insertion.mParentFrame->GetType();
     }
   }
 
   if (!prevSibling) {
     // We're inserting the new frames as the first child. See if the
     // parent has a :before pseudo-element
-    nsIFrame* firstChild = insertion.mParentFrame->GetFirstPrincipalChild();
+    nsIFrame* firstChild = insertion.mParentFrame->PrincipalChildList().FirstChild();
 
     if (firstChild &&
         nsLayoutUtils::IsGeneratedContentFor(container, firstChild,
                                              nsCSSPseudoElements::before)) {
       // Insert the new frames after the last continuation of the :before
       prevSibling = firstChild->GetTailContinuation();
       insertion.mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
       // Don't change isAppend here; we'll can call AppendFrames as needed, and
@@ -8059,17 +8059,17 @@ nsCSSFrameConstructor::ContentRemoved(ns
   // particular, having a null aContainer is necessary but NOT sufficient.  Due
   // to how we process reframes, the content node might not even be in our
   // document by now.  So explicitly check whether the viewport's first kid's
   // content node is aChild.
   bool isRoot = false;
   if (!aContainer) {
     nsIFrame* viewport = GetRootFrame();
     if (viewport) {
-      nsIFrame* firstChild = viewport->GetFirstPrincipalChild();
+      nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
       if (firstChild && firstChild->GetContent() == aChild) {
         isRoot = true;
         childFrame = firstChild;
         NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?");
       }
     }
   }
 
@@ -8141,17 +8141,17 @@ nsCSSFrameConstructor::ContentRemoved(ns
 
     // Undo XUL wrapping if it's no longer needed.
     // (If we're in the XUL block-wrapping situation, parentFrame is the
     // wrapper frame.)
     nsIFrame* grandparentFrame = parentFrame->GetParent();
     if (grandparentFrame && grandparentFrame->IsBoxFrame() &&
         (grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
         // check if this frame is the only one needing wrapping
-        aChild == AnyKidsNeedBlockParent(parentFrame->GetFirstPrincipalChild()) &&
+        aChild == AnyKidsNeedBlockParent(parentFrame->PrincipalChildList().FirstChild()) &&
         !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
       *aDidReconstruct = true;
       LAYOUT_PHASE_TEMP_EXIT();
       nsresult rv = RecreateFramesForContent(grandparentFrame->GetContent(), true,
                                              aFlags, aDestroyedFramesFor);
       LAYOUT_PHASE_TEMP_REENTER();
       return rv;
     }
@@ -8533,17 +8533,17 @@ nsCSSFrameConstructor::CreateContinuingO
   nsTableOuterFrame* newFrame = NS_NewTableOuterFrame(aPresShell, aStyleContext);
 
   newFrame->Init(aContent, aParentFrame, aFrame);
 
   // Create a continuing inner table frame, and if there's a caption then
   // replicate the caption
   nsFrameItems  newChildFrames;
 
-  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
   if (childFrame) {
     nsIFrame* continuingTableFrame =
       CreateContinuingFrame(aPresContext, childFrame, newFrame);
     newChildFrames.AddChild(continuingTableFrame);
 
     NS_ASSERTION(!childFrame->GetNextSibling(),"there can be only one inner table frame");
   }
 
@@ -8561,18 +8561,17 @@ nsCSSFrameConstructor::CreateContinuingT
                                                   nsStyleContext*   aStyleContext)
 {
   nsTableFrame* newFrame = NS_NewTableFrame(aPresShell, aStyleContext);
 
   newFrame->Init(aContent, aParentFrame, aFrame);
 
   // Replicate any header/footer frames
   nsFrameItems  childFrames;
-  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
-  for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
+  for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
     // See if it's a header/footer, possibly wrapped in a scroll frame.
     nsTableRowGroupFrame* rowGroupFrame =
       static_cast<nsTableRowGroupFrame*>(childFrame);
     // If the row group was continued, then don't replicate it.
     nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
     if (rgNextInFlow) {
       rowGroupFrame->SetRepeatable(false);
     }
@@ -8684,17 +8683,17 @@ nsCSSFrameConstructor::CreateContinuingF
 
     rowFrame->Init(content, aParentFrame, aFrame);
     if (rowFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
       nsTableFrame::RegisterPositionedTablePart(rowFrame);
     }
 
     // Create a continuing frame for each table cell frame
     nsFrameItems  newChildList;
-    nsIFrame* cellFrame = aFrame->GetFirstPrincipalChild();
+    nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
     while (cellFrame) {
       // See if it's a table cell frame
       if (IS_TABLE_CELL(cellFrame->GetType())) {
         nsIFrame* continuingCellFrame =
           CreateContinuingFrame(aPresContext, cellFrame, rowFrame);
         newChildList.AddChild(continuingCellFrame);
       }
       cellFrame = cellFrame->GetNextSibling();
@@ -8713,17 +8712,17 @@ nsCSSFrameConstructor::CreateContinuingF
       NS_NewTableCellFrame(shell, styleContext, tableFrame);
 
     cellFrame->Init(content, aParentFrame, aFrame);
     if (cellFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
       nsTableFrame::RegisterPositionedTablePart(cellFrame);
     }
 
     // Create a continuing area frame
-    nsIFrame* blockFrame = aFrame->GetFirstPrincipalChild();
+    nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
     nsIFrame* continuingBlockFrame =
       CreateContinuingFrame(aPresContext, blockFrame,
                             static_cast<nsContainerFrame*>(cellFrame));
 
     SetInitialSingleChild(cellFrame, continuingBlockFrame);
     newFrame = cellFrame;
   } else if (nsGkAtoms::lineFrame == frameType) {
     newFrame = NS_NewFirstLineFrame(shell, styleContext);
@@ -8826,18 +8825,18 @@ nsCSSFrameConstructor::ReplicateFixedFra
   // so we want to move over the placeholders when processing the child
   // of the pageContentFrame.
 
   nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
   if (!prevPageContentFrame) {
     return NS_OK;
   }
   nsContainerFrame* canvasFrame =
-    do_QueryFrame(aParentFrame->GetFirstPrincipalChild());
-  nsIFrame* prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
+    do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
+  nsIFrame* prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
   if (!canvasFrame || !prevCanvasFrame) {
     // document's root element frame missing
     return NS_ERROR_UNEXPECTED;
   }
 
   nsFrameItems fixedPlaceholders;
   nsIFrame* firstFixed = prevPageContentFrame->GetChildList(nsIFrame::kFixedList).FirstChild();
   if (!firstFixed) {
@@ -8882,17 +8881,17 @@ nsCSSFrameConstructor::ReplicateFixedFra
                                         nullptr, items);
       ConstructFramesFromItemList(state, items, canvasFrame, fixedPlaceholders);
     }
   }
 
   // Add the placeholders to our primary child list.
   // XXXbz this is a little screwed up, since the fixed frames will have
   // broken auto-positioning. Oh, well.
-  NS_ASSERTION(!canvasFrame->GetFirstPrincipalChild(),
+  NS_ASSERTION(!canvasFrame->PrincipalChildList().FirstChild(),
                "leaking frames; doc root continuation must be empty");
   canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
   return NS_OK;
 }
 
 nsCSSFrameConstructor::InsertionPoint
 nsCSSFrameConstructor::GetInsertionPoint(nsIContent* aContainer,
                                          nsIContent* aChild)
@@ -9029,17 +9028,17 @@ IsWhitespaceFrame(nsIFrame* aFrame)
   MOZ_ASSERT(aFrame, "invalid argument");
   return aFrame->GetType() == nsGkAtoms::textFrame &&
     aFrame->GetContent()->TextIsOnlyWhitespace();
 }
 
 static nsIFrame*
 FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
 {
-  nsIFrame* f = aParentFrame->GetFirstPrincipalChild();
+  nsIFrame* f = aParentFrame->PrincipalChildList().FirstChild();
   while (f && IsWhitespaceFrame(f)) {
     f = f->GetNextSibling();
   }
   return f;
 }
 
 static nsIFrame*
 FindNextNonWhitespaceSibling(nsIFrame* aFrame)
@@ -9248,17 +9247,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
   // ib-split, since in that case the removal of aFrame might affect the
   // splitting of its parent.
   if (!IsFramePartOfIBSplit(parent)) {
     return false;
   }
 
   // If inFlowFrame is not the only in-flow child of |parent|, then removing
   // it will change nothing about the {ib} split.
-  if (inFlowFrame != parent->GetFirstPrincipalChild() ||
+  if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
       inFlowFrame->LastContinuation()->GetNextSibling()) {
     return false;
   }
 
   // If the parent is the first or last part of the {ib} split, then
   // removing one of its kids will have no effect on the splitting.
   // Get the first continuation up front so we don't have to do it twice.
   nsIFrame* parentFirstContinuation = parent->FirstContinuation();
@@ -10654,17 +10653,17 @@ nsCSSFrameConstructor::InsertFirstLineFr
 #if 0
   nsIFrame* parentFrame = *aParentFrame;
   nsIFrame* newFrame = aFrameItems.childList;
   bool isInline = IsInlineOutside(newFrame);
 
   if (!aPrevSibling) {
     // Insertion will become the first frame. Two cases: we either
     // already have a first-line frame or we don't.
-    nsIFrame* firstBlockKid = aBlockFrame->GetFirstPrincipalChild();
+    nsIFrame* firstBlockKid = aBlockFrame->PrincipalChildList().FirstChild();
     if (firstBlockKid->GetType() == nsGkAtoms::lineFrame) {
       // We already have a first-line frame
       nsIFrame* lineFrame = firstBlockKid;
 
       if (isInline) {
         // Easy case: the new inline frame will go into the lineFrame.
         ReparentFrame(this, lineFrame, newFrame);
         InsertFrames(lineFrame, kPrincipalList, nullptr, newFrame);
@@ -10754,17 +10753,17 @@ nsCSSFrameConstructor::InsertFirstLineFr
           }
 
           nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame;
           for (;;) {
             nextLineFrame = nextLineFrame->GetNextInFlow();
             if (!nextLineFrame) {
               break;
             }
-            nsIFrame* kids = nextLineFrame->GetFirstPrincipalChild();
+            nsIFrame* kids = nextLineFrame->PrincipalChildList().FirstChild();
           }
         }
         else {
           // We got lucky: aPrevSibling was the last inline frame in
           // the line-frame.
           ReparentFrame(this, aBlockFrame, newFrame);
           InsertFrames(aBlockFrame, kPrincipalList,
                        prevSiblingParent, newFrame);
@@ -11058,17 +11057,17 @@ nsCSSFrameConstructor::WrapFramesInFirst
         *aModifiedParent = aParentFrame;
         *aTextFrame = frame;
         *aPrevFrame = prevFrame;
         *aStopLooking = true;
         return;
       }
     }
     else if (IsInlineFrame(frame) && frameType != nsGkAtoms::brFrame) {
-      nsIFrame* kids = frame->GetFirstPrincipalChild();
+      nsIFrame* kids = frame->PrincipalChildList().FirstChild();
       WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
                                    static_cast<nsContainerFrame*>(frame),
                                    kids, aModifiedParent, aTextFrame,
                                    aPrevFrame, aLetterFrames, aStopLooking);
       if (*aStopLooking) {
         return;
       }
     }
@@ -11113,17 +11112,17 @@ nsCSSFrameConstructor::RemoveFloatingFir
       ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kPushedFloatsList);
     if (!floatFrame) {
       return NS_OK;
     }
   }
 
   // Take the text frame away from the letter frame (so it isn't
   // destroyed when we destroy the letter frame).
-  nsIFrame* textFrame = floatFrame->GetFirstPrincipalChild();
+  nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
   if (!textFrame) {
     return NS_OK;
   }
 
   // Discover the placeholder frame for the letter frame
   nsPlaceholderFrame* placeholderFrame = GetPlaceholderFrameFor(floatFrame);
   if (!placeholderFrame) {
     // Somethings really wrong
@@ -11192,22 +11191,22 @@ nsCSSFrameConstructor::RemoveFloatingFir
 
 nsresult
 nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell,
                                                nsContainerFrame* aFrame,
                                                nsContainerFrame* aBlockFrame,
                                                bool* aStopLooking)
 {
   nsIFrame* prevSibling = nullptr;
-  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
+  nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
 
   while (kid) {
     if (nsGkAtoms::letterFrame == kid->GetType()) {
       // Bingo. Found it. First steal away the text frame.
-      nsIFrame* textFrame = kid->GetFirstPrincipalChild();
+      nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
       if (!textFrame) {
         break;
       }
 
       // Create a new textframe
       nsStyleContext* parentSC = aFrame->StyleContext();
       if (!parentSC) {
         break;
@@ -11304,17 +11303,17 @@ nsCSSFrameConstructor::RecoverLetterFram
   nsIFrame* textFrame = nullptr;
   nsIFrame* prevFrame = nullptr;
   nsFrameItems letterFrames;
   bool stopLooking = false;
   do {
     // XXX shouldn't this bit be set already (bug 408493), assert instead?
     continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
     WrapFramesInFirstLetterFrame(aBlockFrame, continuation, continuation,
-                                 continuation->GetFirstPrincipalChild(),
+                                 continuation->PrincipalChildList().FirstChild(),
                                  &parentFrame, &textFrame, &prevFrame,
                                  letterFrames, &stopLooking);
     if (stopLooking) {
       break;
     }
     continuation =
       static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
   } while (continuation);
@@ -12020,17 +12019,17 @@ nsCSSFrameConstructor::WipeContainingBlo
           // Trailing whitespace.  How to handle this depeds on aIsAppend, our
           // next sibling and aFrame.  See the long comment above.
           okToDrop = aIsAppend && !nextSibling;
           if (!okToDrop) {
             if (!nextSibling) {
               // Try to find one after all
               nsIFrame* parentNextCont = aFrame->GetNextContinuation();
               while (parentNextCont) {
-                nextSibling = parentNextCont->GetFirstPrincipalChild();
+                nextSibling = parentNextCont->PrincipalChildList().FirstChild();
                 if (nextSibling) {
                   break;
                 }
                 parentNextCont = parentNextCont->GetNextContinuation();
               }
             }
 
             okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -3110,17 +3110,17 @@ nsCSSRendering::ComputeImageLayerPositio
       NS_ASSERTION(aLayer.mOrigin == NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
                    "unknown background-origin value");
     }
     *aAttachedToFrame = aForFrame;
     return bgPositioningArea;
   }
 
   if (MOZ_UNLIKELY(frameType == nsGkAtoms::canvasFrame)) {
-    geometryFrame = aForFrame->GetFirstPrincipalChild();
+    geometryFrame = aForFrame->PrincipalChildList().FirstChild();
     // geometryFrame might be null if this canvas is a page created
     // as an overflow container (e.g. the in-flow content has already
     // finished and this page only displays the continuations of
     // absolutely positioned content).
     if (geometryFrame) {
       bgPositioningArea = geometryFrame->GetRect();
     }
   } else {
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -57,17 +57,17 @@ CheckForTrailingTextFrameRecursive(nsIFr
 {
   if (aFrame == aStopAtFrame ||
       ((aFrame->GetType() == nsGkAtoms::textFrame &&
        (static_cast<nsTextFrame*>(aFrame))->IsAtEndOfLine())))
     return aFrame;
   if (!aFrame->IsFrameOfType(nsIFrame::eLineParticipant))
     return nullptr;
 
-  for (nsIFrame* f = aFrame->GetFirstPrincipalChild(); f; f = f->GetNextSibling())
+  for (nsIFrame* f : aFrame->PrincipalChildList())
   {
     nsIFrame* r = CheckForTrailingTextFrameRecursive(f, aStopAtFrame);
     if (r)
       return r;
   }
   return nullptr;
 }
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3790,28 +3790,26 @@ nsDocumentViewer::PrintPreviewNavigate(i
   // If it is "End" then just do a "goto" to the last page
   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) {
     aType    = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM;
     aPageNum = pageCount;
   }
 
   // Now, locate the current page we are on and
   // and the page of the page number
-  nsIFrame* pageFrame = seqFrame->GetFirstPrincipalChild();
-  while (pageFrame != nullptr) {
+  for (nsIFrame* pageFrame : seqFrame->PrincipalChildList()) {
     nsRect pageRect = pageFrame->GetRect();
     if (pageRect.Contains(pageRect.x, pt.y)) {
       currentPage = pageFrame;
     }
     if (pageNum == aPageNum) {
       fndPageFrame = pageFrame;
       break;
     }
     pageNum++;
-    pageFrame = pageFrame->GetNextSibling();
   }
 
   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) {
     if (currentPage) {
       fndPageFrame = currentPage->GetPrevInFlow();
       if (!fndPageFrame) {
         return NS_OK;
       }
--- a/layout/base/nsFrameTraversal.cpp
+++ b/layout/base/nsFrameTraversal.cpp
@@ -461,17 +461,17 @@ nsFrameIterator::GetPrevSibling(nsIFrame
   if (mFollowOOFs && IsPopupFrame(result))
     result = GetPrevSibling(result);
 
   return result;
 }
 
 nsIFrame*
 nsFrameIterator::GetFirstChildInner(nsIFrame* aFrame) {
-  return aFrame->GetFirstPrincipalChild();
+  return aFrame->PrincipalChildList().FirstChild();
 }
 
 nsIFrame*
 nsFrameIterator::GetLastChildInner(nsIFrame* aFrame) {
   return aFrame->PrincipalChildList().LastChild();
 }
 
 nsIFrame*
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1249,17 +1249,17 @@ nsLayoutUtils::HasCriticalDisplayPort(ns
   return GetCriticalDisplayPort(aContent, nullptr);
 }
 
 nsContainerFrame*
 nsLayoutUtils::LastContinuationWithChild(nsContainerFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
   nsIFrame* f = aFrame->LastContinuation();
-  while (!f->GetFirstPrincipalChild() && f->GetPrevContinuation()) {
+  while (!f->PrincipalChildList().FirstChild() && f->GetPrevContinuation()) {
     f = f->GetPrevContinuation();
   }
   return static_cast<nsContainerFrame*>(f);
 }
 
 //static
 FrameChildListID
 nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
@@ -1377,17 +1377,17 @@ nsLayoutUtils::GetBeforeFrameForContent(
           pseudos[i]->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) {
         return pseudos[i]->GetPrimaryFrame();
       }
     }
   }
   // If the first child frame is a pseudo-frame, then try that.
   // Note that the frame we create for the generated content is also a
   // pseudo-frame and so don't drill down in that case.
-  nsIFrame* childFrame = genConParentFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = genConParentFrame->PrincipalChildList().FirstChild();
   if (childFrame &&
       childFrame->IsPseudoFrame(aContent) &&
       !childFrame->IsGeneratedContentFrame()) {
     return GetBeforeFrameForContent(childFrame, aContent);
   }
   return nullptr;
 }
 
@@ -1461,17 +1461,17 @@ nsLayoutUtils::GetClosestFrameOfType(nsI
   return nullptr;
 }
 
 // static
 nsIFrame*
 nsLayoutUtils::GetStyleFrame(nsIFrame* aFrame)
 {
   if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
-    nsIFrame* inner = aFrame->GetFirstPrincipalChild();
+    nsIFrame* inner = aFrame->PrincipalChildList().FirstChild();
     NS_ASSERTION(inner, "Outer table must have an inner");
     return inner;
   }
 
   return aFrame;
 }
 
 nsIFrame*
@@ -3592,17 +3592,17 @@ nsLayoutUtils::BinarySearchForPosition(D
 
 static void
 AddBoxesForFrame(nsIFrame* aFrame,
                  nsLayoutUtils::BoxCallback* aCallback)
 {
   nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
 
   if (pseudoType == nsCSSAnonBoxes::tableOuter) {
-    AddBoxesForFrame(aFrame->GetFirstPrincipalChild(), aCallback);
+    AddBoxesForFrame(aFrame->PrincipalChildList().FirstChild(), aCallback);
     nsIFrame* kid = aFrame->GetChildList(nsIFrame::kCaptionList).FirstChild();
     if (kid) {
       AddBoxesForFrame(kid, aCallback);
     }
   } else if (pseudoType == nsCSSAnonBoxes::mozAnonymousBlock ||
              pseudoType == nsCSSAnonBoxes::mozAnonymousPositionedBlock ||
              pseudoType == nsCSSAnonBoxes::mozMathMLAnonymousBlock ||
              pseudoType == nsCSSAnonBoxes::mozXULAnonymousBlock) {
@@ -3625,17 +3625,17 @@ nsLayoutUtils::GetAllInFlowBoxes(nsIFram
 
 nsIFrame*
 nsLayoutUtils::GetFirstNonAnonymousFrame(nsIFrame* aFrame)
 {
   while (aFrame) {
     nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
 
     if (pseudoType == nsCSSAnonBoxes::tableOuter) {
-      nsIFrame* f = GetFirstNonAnonymousFrame(aFrame->GetFirstPrincipalChild());
+      nsIFrame* f = GetFirstNonAnonymousFrame(aFrame->PrincipalChildList().FirstChild());
       if (f) {
         return f;
       }
       nsIFrame* kid = aFrame->GetChildList(nsIFrame::kCaptionList).FirstChild();
       if (kid) {
         f = GetFirstNonAnonymousFrame(kid);
         if (f) {
           return f;
@@ -5854,17 +5854,17 @@ nsLayoutUtils::GetFirstLinePosition(Writ
           aFrame->GetLogicalUsedBorderAndPadding(aWM).BStart(aWM);
         return true;
       }
       return false;
     }
 
     if (fType == nsGkAtoms::fieldSetFrame) {
       LinePosition kidPosition;
-      nsIFrame* kid = aFrame->GetFirstPrincipalChild();
+      nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
       // kid might be a legend frame here, but that's ok.
       if (GetFirstLinePosition(aWM, kid, &kidPosition)) {
         *aResult = kidPosition +
           kid->GetLogicalNormalPosition(aWM, aFrame->GetSize()).B(aWM);
         return true;
       }
       return false;
     }
@@ -6753,17 +6753,17 @@ nsLayoutUtils::GetFrameTransparency(nsIF
     return transparency == nsITheme::eTransparent
          ? eTransparencyTransparent
          : eTransparencyOpaque;
 
   // We need an uninitialized window to be treated as opaque because
   // doing otherwise breaks window display effects on some platforms,
   // specifically Vista. (bug 450322)
   if (aBackgroundFrame->GetType() == nsGkAtoms::viewportFrame &&
-      !aBackgroundFrame->GetFirstPrincipalChild()) {
+      !aBackgroundFrame->PrincipalChildList().FirstChild()) {
     return eTransparencyOpaque;
   }
 
   nsStyleContext* bgSC;
   if (!nsCSSRendering::FindBackground(aBackgroundFrame, &bgSC)) {
     return eTransparencyTransparent;
   }
   const nsStyleBackground* bg = bgSC->StyleBackground();
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2271,17 +2271,17 @@ nsIPresShell::GetRootFrameExternal() con
 
 nsIFrame*
 nsIPresShell::GetRootScrollFrame() const
 {
   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
   // Ensure root frame is a viewport frame
   if (!rootFrame || nsGkAtoms::viewportFrame != rootFrame->GetType())
     return nullptr;
-  nsIFrame* theFrame = rootFrame->GetFirstPrincipalChild();
+  nsIFrame* theFrame = rootFrame->PrincipalChildList().FirstChild();
   if (!theFrame || nsGkAtoms::scrollFrame != theFrame->GetType())
     return nullptr;
   return theFrame;
 }
 
 nsIScrollableFrame*
 nsIPresShell::GetRootScrollFrameAsScrollable() const
 {
@@ -9586,23 +9586,21 @@ FindTopFrame(nsIFrame* aRoot)
       content->GetTag(tag);
       if (nullptr != tag) {
         NS_RELEASE(tag);
         return aRoot;
       }
     }
 
     // Try one of the children
-    nsIFrame* kid = aRoot->GetFirstPrincipalChild();
-    while (nullptr != kid) {
+    for (nsIFrame* kid : aRoot->PrincipalChildList()) {
       nsIFrame* result = FindTopFrame(kid);
       if (nullptr != result) {
         return result;
       }
-      kid = kid->GetNextSibling();
     }
   }
   return nullptr;
 }
 #endif
 
 
 #ifdef DEBUG
@@ -10172,20 +10170,18 @@ static void RecurseIndiTotals(nsPresCont
     char * name = ToNewCString(counter->mName);
     for (int32_t i=0;i<aLevel;i++) printf(" ");
     printf("%s - %p   [%d][", name, (void*)aParentFrame, counter->mCount);
     printf("%d", counter->mCounter.GetTotal());
     printf("]\n");
     free(name);
   }
 
-  nsIFrame* child = aParentFrame->GetFirstPrincipalChild();
-  while (child) {
+  for (nsIFrame* child : aParentFrame->PrincipalChildList()) {
     RecurseIndiTotals(aPresContext, aHT, child, aLevel+1);
-    child = child->GetNextSibling();
   }
 
 }
 
 //------------------------------------------------------------------
 int ReflowCountMgr::DoSingleIndi(PLHashEntry *he, int i, void *arg)
 {
   IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -76,17 +76,17 @@ public:
   virtual bool HonorPrintBackgroundSettings() override { return false; }
 
   // nsIFormControlFrame
   void SetFocus(bool aOn, bool aRepaint) override;
   virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
 
   // Inserted child content gets its frames parented by our child block
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -260,18 +260,17 @@ nsListControlFrame::AccessibleType()
   return a11y::eHTMLSelectListType;
 }
 #endif
 
 static nscoord
 GetMaxOptionBSize(nsIFrame* aContainer, WritingMode aWM)
 {
   nscoord result = 0;
-  for (nsIFrame* option = aContainer->GetFirstPrincipalChild();
-       option; option = option->GetNextSibling()) {
+  for (nsIFrame* option : aContainer->PrincipalChildList()) {
     nscoord optionBSize;
     if (nsCOMPtr<nsIDOMHTMLOptGroupElement>
         (do_QueryInterface(option->GetContent()))) {
       // An optgroup; drill through any scroll frame and recurse.  |frame| might
       // be null here though if |option| is an anonymous leaf frame of some sort.
       auto frame = option->GetContentInsertionFrame();
       optionBSize = frame ? GetMaxOptionBSize(frame, aWM) : 0;
     } else {
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -205,17 +205,17 @@ nsTextControlFrame::CalcIntrinsicSize(ns
   }
 
   // Set the height equal to total number of rows (times the height of each
   // line, of course)
   aIntrinsicSize.BSize(aWM) = lineHeight * GetRows();
 
   // Add in the size of the scrollbars for textarea
   if (IsTextArea()) {
-    nsIFrame* first = GetFirstPrincipalChild();
+    nsIFrame* first = PrincipalChildList().FirstChild();
 
     nsIScrollableFrame *scrollableFrame = do_QueryFrame(first);
     NS_ASSERTION(scrollableFrame, "Child must be scrollable");
 
     if (scrollableFrame) {
       LogicalMargin scrollbarSizes(aWM,
         scrollableFrame->GetDesiredScrollbarSizes(PresContext(),
                                                   aRenderingContext));
@@ -1226,17 +1226,17 @@ nsTextControlFrame::SetInitialChildList(
   nsContainerFrame::SetInitialChildList(aListID, aChildList);
   if (aListID != kPrincipalList) {
     return;
   }
 
   // Mark the scroll frame as being a reflow root. This will allow
   // incremental reflows to be initiated at the scroll frame, rather
   // than descending from the root frame of the frame hierarchy.
-  if (nsIFrame* first = GetFirstPrincipalChild()) {
+  if (nsIFrame* first = PrincipalChildList().FirstChild()) {
     first->AddStateBits(NS_FRAME_REFLOW_ROOT);
 
     nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
     NS_ASSERTION(txtCtrl, "Content not a text control element");
     txtCtrl->InitializeKeyboardEventListeners();
 
     nsPoint* contentScrollPos = Properties().Get(ContentScrollPos());
     if (contentScrollPos) {
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -35,17 +35,17 @@ public:
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ContentScrollPos, nsPoint)
 
   explicit nsTextControlFrame(nsStyleContext* aContext);
   virtual ~nsTextControlFrame();
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
 
   virtual nsIScrollableFrame* GetScrollTargetFrame() override {
-    return do_QueryFrame(GetFirstPrincipalChild());
+    return do_QueryFrame(PrincipalChildList().FirstChild());
   }
 
   virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
   virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
 
   virtual mozilla::LogicalSize
   ComputeAutoSize(nsRenderingContext *aRenderingContext,
                   mozilla::WritingMode aWritingMode,
--- a/layout/generic/RubyUtils.cpp
+++ b/layout/generic/RubyUtils.cpp
@@ -73,17 +73,17 @@ RubyColumn::Iterator::SkipUntilExistingF
     if (mColumn.mTextFrames[mIndex]) {
       break;
     }
   }
 }
 
 RubySegmentEnumerator::RubySegmentEnumerator(nsRubyFrame* aRubyFrame)
 {
-  nsIFrame* frame = aRubyFrame->GetFirstPrincipalChild();
+  nsIFrame* frame = aRubyFrame->PrincipalChildList().FirstChild();
   MOZ_ASSERT(!frame ||
              frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
   mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
 }
 
 void
 RubySegmentEnumerator::Next()
 {
@@ -98,25 +98,25 @@ RubySegmentEnumerator::Next()
 RubyColumnEnumerator::RubyColumnEnumerator(
   nsRubyBaseContainerFrame* aBaseContainer,
   const AutoRubyTextContainerArray& aTextContainers)
   : mAtIntraLevelWhitespace(false)
 {
   const uint32_t rtcCount = aTextContainers.Length();
   mFrames.SetCapacity(rtcCount + 1);
 
-  nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild();
+  nsIFrame* rbFrame = aBaseContainer->PrincipalChildList().FirstChild();
   MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
   mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* container = aTextContainers[i];
     // If the container is for span, leave a nullptr here.
     // Spans do not take part in pairing.
     nsIFrame* rtFrame = !container->IsSpanContainer() ?
-      container->GetFirstPrincipalChild() : nullptr;
+      container->PrincipalChildList().FirstChild() : nullptr;
     MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
     mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
   }
 
   // We have to init mAtIntraLevelWhitespace to be correct for the
   // first column. There are two ways we could end up with intra-level
   // whitespace in our first colum:
   // 1. The current segment itself is an inter-segment whitespace;
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -375,23 +375,21 @@ TextOverflow::ExamineFrameSubtree(nsIFra
                          aFoundVisibleTextOrAtomic,
                          aClippedMarkerEdges);
     }
   }
   if (isAtomic) {
     return;
   }
 
-  nsIFrame* child = aFrame->GetFirstPrincipalChild();
-  while (child) {
+  for (nsIFrame* child : aFrame->PrincipalChildList()) {
     ExamineFrameSubtree(child, aContentArea, aInsideMarkersArea,
                         aFramesToHide, aAlignmentEdges,
                         aFoundVisibleTextOrAtomic,
                         aClippedMarkerEdges);
-    child = child->GetNextSibling();
   }
 }
 
 void
 TextOverflow::AnalyzeMarkerEdges(nsIFrame*       aFrame,
                                  const nsIAtom*  aFrameType,
                                  const LogicalRect& aInsideMarkersArea,
                                  FrameHashtable* aFramesToHide,
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -2363,17 +2363,17 @@ nsBlockFrame::ReflowDirtyLines(nsBlockRe
       }
 
       needToRecoverState = true;
 
       if (reflowedPrevLine && !line->IsBlock() &&
           aState.mPresContext->HasPendingInterrupt()) {
         // Need to make sure to pull overflows from any prev-in-flows
         for (nsIFrame* inlineKid = line->mFirstChild; inlineKid;
-             inlineKid = inlineKid->GetFirstPrincipalChild()) {
+             inlineKid = inlineKid->PrincipalChildList().FirstChild()) {
           inlineKid->PullOverflowsFromPrevInFlow();
         }
       }
     }
 
     // Record if we need to clear floats before reflowing the next
     // line. Note that inlineFloatBreakType will be handled and
     // cleared before the next line is processed, so there is no
@@ -7195,17 +7195,17 @@ nsBlockFrame::DoCollectFloats(nsIFrame* 
         aList.AppendFrame(nullptr, outOfFlowFrame);
         outOfFlowFrame = outOfFlowFrame->GetNextInFlow();
         // FIXME: By not pulling floats whose parent is one of our
         // later siblings, are we risking the pushed floats getting
         // out-of-order?
         // XXXmats nsInlineFrame's lazy reparenting depends on NOT doing that.
       }
 
-      DoCollectFloats(aFrame->GetFirstPrincipalChild(), aList, true);
+      DoCollectFloats(aFrame->PrincipalChildList().FirstChild(), aList, true);
       DoCollectFloats(aFrame->GetChildList(kOverflowList).FirstChild(), aList, true);
     }
     if (!aCollectSiblings)
       break;
     aFrame = aFrame->GetNextSibling();
   }
 }
 
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -36,17 +36,17 @@ nsBlockReflowContext::nsBlockReflowConte
 {
 }
 
 static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
 {
   nsIAtom* type = aFrame->GetType();
   if (type == nsGkAtoms::columnSetFrame) {
     static_cast<nsColumnSetFrame*>(aFrame)->DrainOverflowColumns();
-    nsIFrame* child = aFrame->GetFirstPrincipalChild();
+    nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
     if (child) {
       return DescendIntoBlockLevelFrame(child);
     }
   }
   return aFrame;
 }
 
 bool
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -429,18 +429,17 @@ nsCanvasFrame::BuildDisplayList(nsDispla
     }
 
     if (needBlendContainer) {
       aLists.BorderBackground()->AppendNewToTop(
         new (aBuilder) nsDisplayBlendContainer(aBuilder, this, aLists.BorderBackground()));
     }
   }
 
-  nsIFrame* kid;
-  for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
+  for (nsIFrame* kid : PrincipalChildList()) {
     // Put our child into its own pseudo-stack.
     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
   }
 
 #ifdef DEBUG_CANVAS_FOCUS
   nsCOMPtr<nsIContent> focusContent;
   aPresContext->EventStateManager()->
     GetFocusedContent(getter_AddRefs(focusContent));
--- a/layout/generic/nsColumnSetFrame.h
+++ b/layout/generic/nsColumnSetFrame.h
@@ -40,17 +40,17 @@ public:
 
   /**
    * Retrieve the available height for content of this frame. The available content
    * height is the available height for the frame, minus borders and padding.
    */
   virtual nscoord GetAvailableContentBSize(const nsHTMLReflowState& aReflowState);
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    nsIFrame* frame = GetFirstPrincipalChild();
+    nsIFrame* frame = PrincipalChildList().FirstChild();
 
     // if no children return nullptr
     if (!frame)
       return nullptr;
 
     return frame->GetContentInsertionFrame();
   }
 
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -912,17 +912,17 @@ GetFirstNonAnonBoxDescendant(nsIFrame* a
       nsIFrame* colgroupDescendant =
         GetFirstNonAnonBoxDescendant(aFrame->GetChildList(kColGroupList).FirstChild());
       if (colgroupDescendant) {
         return colgroupDescendant;
       }
     }
 
     // USUAL CASE: Descend to the first child in principal list.
-    aFrame = aFrame->GetFirstPrincipalChild();
+    aFrame = aFrame->PrincipalChildList().FirstChild();
   }
   return aFrame;
 }
 
 /**
  * Sorting helper-function that compares two frames' "order" property-values,
  * and if they're equal, compares the DOM positions of their corresponding
  * content nodes. Returns true if aFrame1 is "less than or equal to" aFrame2
@@ -2018,17 +2018,17 @@ nsFlexContainerFrame::SanityCheckAnonymo
                "but it isn't");
     if (child->StyleContext()->GetPseudo() ==
         nsCSSAnonBoxes::anonymousFlexItem) {
       MOZ_ASSERT(!prevChildWasAnonFlexItem ||
                  HasAnyStateBits(NS_STATE_FLEX_CHILDREN_REORDERED),
                  "two anon flex items in a row (shouldn't happen, unless our "
                  "children have been reordered with the 'order' property)");
 
-      nsIFrame* firstWrappedChild = child->GetFirstPrincipalChild();
+      nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
       MOZ_ASSERT(firstWrappedChild,
                  "anonymous flex item is empty (shouldn't happen)");
       prevChildWasAnonFlexItem = true;
     } else {
       prevChildWasAnonFlexItem = false;
     }
   }
 }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -784,17 +784,17 @@ AddAndRemoveImageAssociations(nsFrame* a
 
 // Subclass hook for style post processing
 /* virtual */ void
 nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (IsSVGText()) {
     SVGTextFrame* svgTextFrame = static_cast<SVGTextFrame*>(
         nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::svgTextFrame));
-    nsIFrame* anonBlock = svgTextFrame->GetFirstPrincipalChild();
+    nsIFrame* anonBlock = svgTextFrame->PrincipalChildList().FirstChild();
     // Just as in SVGTextFrame::DidSetStyleContext, we need to ensure that
     // any non-display SVGTextFrames get reflowed when a child text frame
     // gets new style.
     //
     // Note that we must check NS_FRAME_FIRST_REFLOW on our SVGTextFrame's
     // anonymous block frame rather than our self, since NS_FRAME_FIRST_REFLOW
     // may be set on us if we're a new frame that has been inserted after the
     // document's first reflow. (In which case this DidSetStyleContext call may
@@ -3670,17 +3670,17 @@ static FrameTarget GetSelectionClosestFr
 // before the first child.  A click on a block whose first child is a block
 // should put the cursor in the child.  The cursor shouldn't be between the
 // blocks, because that's not where it's expected.
 // Note that this method is guaranteed to succeed.
 static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
                                              bool aEndFrame, uint32_t aFlags) {
   if (SelectionDescendToKids(aFrame)) {
     nsIFrame* result = nullptr;
-    nsIFrame *frame = aFrame->GetFirstPrincipalChild();
+    nsIFrame *frame = aFrame->PrincipalChildList().FirstChild();
     if (!aEndFrame) {
       while (frame && (!SelfIsSelectable(frame, aFlags) ||
                         frame->IsEmpty()))
         frame = frame->GetNextSibling();
       if (frame)
         result = frame;
     } else {
       // Because the frame tree is singly linked, to find the last frame,
@@ -3853,17 +3853,17 @@ static FrameTarget GetSelectionClosestFr
 {
   {
     // Handle blocks; if the frame isn't a block, the method fails
     FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint, aFlags);
     if (!target.IsNull())
       return target;
   }
 
-  nsIFrame *kid = aFrame->GetFirstPrincipalChild();
+  nsIFrame *kid = aFrame->PrincipalChildList().FirstChild();
 
   if (kid) {
     // Go through all the child frames to find the closest one
     nsIFrame::FrameWithDistance closest = { nullptr, nscoord_MAX, nscoord_MAX };
     for (; kid; kid = kid->GetNextSibling()) {
       if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty())
         continue;
 
@@ -6632,17 +6632,17 @@ FindBlockFrameOrBR(nsIFrame* aFrame, nsD
   // Iterate over children and call ourselves recursively
   if (aDirection == eDirPrevious) {
     nsIFrame* child = aFrame->GetChildList(nsIFrame::kPrincipalList).LastChild();
     while(child && !result.mContent) {
       result = FindBlockFrameOrBR(child, aDirection);
       child = child->GetPrevSibling();
     }
   } else { // eDirNext
-    nsIFrame* child = aFrame->GetFirstPrincipalChild();
+    nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
     while(child && !result.mContent) {
       result = FindBlockFrameOrBR(child, aDirection);
       child = child->GetNextSibling();
     }
   }
   return result;
 }
 
@@ -6945,30 +6945,30 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
   tables need to navigate also and the frame that supports it is nsTableRowGroupFrame which is INSIDE
   nsTableOuterFrame.  if we have stumbled onto an nsTableOuter we need to drill into nsTableRowGroup
   if we hit a header or footer that's ok just go into them,
 */
             bool searchTableBool = false;
             if (aPos->mResultFrame->GetType() == nsGkAtoms::tableOuterFrame ||
                 aPos->mResultFrame->GetType() == nsGkAtoms::tableCellFrame)
             {
-              nsIFrame *frame = aPos->mResultFrame->GetFirstPrincipalChild();
+              nsIFrame *frame = aPos->mResultFrame->PrincipalChildList().FirstChild();
               //got the table frame now
               while(frame) //ok time to drill down to find iterator
               {
                 iter = frame->GetLineIterator();
                 if (iter)
                 {
                   aPos->mResultFrame = frame;
                   searchTableBool = true;
                   result = NS_OK;
                   break; //while(frame)
                 }
                 result = NS_ERROR_FAILURE;
-                frame = frame->GetFirstPrincipalChild();
+                frame = frame->PrincipalChildList().FirstChild();
               }
             }
 
             if (!searchTableBool) {
               iter = aPos->mResultFrame->GetLineIterator();
               result = iter ? NS_OK : NS_ERROR_FAILURE;
             }
             if (NS_SUCCEEDED(result) && iter)//we've struck another block element!
@@ -7622,17 +7622,17 @@ ComputeAndIncludeOutlineArea(nsIFrame* a
   // actual contents of the anonymous blocks.
   nsIFrame *frameForArea = aFrame;
   do {
     nsIAtom *pseudoType = frameForArea->StyleContext()->GetPseudo();
     if (pseudoType != nsCSSAnonBoxes::mozAnonymousBlock &&
         pseudoType != nsCSSAnonBoxes::mozAnonymousPositionedBlock)
       break;
     // If we're done, we really want it and all its later siblings.
-    frameForArea = frameForArea->GetFirstPrincipalChild();
+    frameForArea = frameForArea->PrincipalChildList().FirstChild();
     NS_ASSERTION(frameForArea, "anonymous block with no children?");
   } while (frameForArea);
 
   // Find the union of the border boxes of all descendants, or in
   // the block-in-inline case, all descendants we care about.
   //
   // Note that the interesting perspective-related cases are taken
   // care of by the code that handles those issues for overflow
@@ -8060,28 +8060,28 @@ GetCorrectedParent(const nsIFrame* aFram
   nsIFrame* parent = aFrame->GetParent();
   if (!parent) {
     return nullptr;
   }
 
   // For a table caption we want the _inner_ table frame (unless it's anonymous)
   // as the style parent.
   if (aFrame->IsTableCaption()) {
-    nsIFrame* innerTable = parent->GetFirstPrincipalChild();
+    nsIFrame* innerTable = parent->PrincipalChildList().FirstChild();
     if (!innerTable->StyleContext()->GetPseudo()) {
       return innerTable;
     }
   }
 
   // Outer tables are always anon boxes; if we're in here for an outer
   // table, that actually means its the _inner_ table that wants to
   // know its parent.  So get the pseudo of the inner in that case.
   nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
   if (pseudo == nsCSSAnonBoxes::tableOuter) {
-    pseudo = aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo();
+    pseudo = aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo();
   }
   return nsFrame::CorrectStyleParentFrame(parent, pseudo);
 }
 
 /* static */
 nsIFrame*
 nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
                                  nsIAtom* aChildPseudo)
@@ -8209,17 +8209,17 @@ nsFrame::DoGetParentStyleContext(nsIFram
 void
 nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
   if (!aFrame || !*aFrame)
     return;
   nsIFrame *child = *aFrame;
   //if we are a block frame then go for the last line of 'this'
   while (1){
-    child = child->GetFirstPrincipalChild();
+    child = child->PrincipalChildList().FirstChild();
     if (!child)
       return;//nothing to do
     nsIFrame* siblingFrame;
     nsIContent* content;
     //ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
     //see bug 278197 comment #12 #13 for details
     while ((siblingFrame = child->GetNextSibling()) &&
            (content = siblingFrame->GetContent()) &&
@@ -8231,17 +8231,17 @@ nsFrame::GetLastLeaf(nsPresContext* aPre
 
 void
 nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
   if (!aFrame || !*aFrame)
     return;
   nsIFrame *child = *aFrame;
   while (1){
-    child = child->GetFirstPrincipalChild();
+    child = child->PrincipalChildList().FirstChild();
     if (!child)
       return;//nothing to do
     *aFrame = child;
   }
 }
 
 /* virtual */ bool
 nsIFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
--- a/layout/generic/nsFrameList.h
+++ b/layout/generic/nsFrameList.h
@@ -240,16 +240,21 @@ public:
   }
 
   bool NotEmpty() const {
     return nullptr != mFirstChild;
   }
 
   bool ContainsFrame(const nsIFrame* aFrame) const;
 
+  /**
+   * Get the number of frames in this list. Note that currently the
+   * implementation has O(n) time complexity. Do not call it repeatedly in hot
+   * code.
+   */
   int32_t GetLength() const;
 
   /**
    * If this frame list has only one frame, return that frame.
    * Otherwise, return null.
    */
   nsIFrame* OnlyChild() const {
     if (FirstChild() == LastChild()) {
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -597,17 +597,17 @@ nsHTMLScrollFrame::GuessVScrollbarNeeded
   }
 
   // If this is the initial reflow, guess false because usually
   // we have very little content by then.
   if (InInitialReflow())
     return false;
 
   if (mHelper.mIsRoot) {
-    nsIFrame *f = mHelper.mScrolledFrame->GetFirstPrincipalChild();
+    nsIFrame *f = mHelper.mScrolledFrame->PrincipalChildList().FirstChild();
     if (f && f->GetType() == nsGkAtoms::svgOuterSVGFrame &&
         static_cast<nsSVGOuterSVGFrame*>(f)->VerticalScrollbarNotNeeded()) {
       // Common SVG case - avoid a bad guess.
       return false;
     }
     // Assume that there will be a scrollbar; it seems to me
     // that 'most pages' do have a scrollbar, and anyway, it's cheaper
     // to do an extra reflow for the pages that *don't* need a
@@ -3908,18 +3908,17 @@ void
 ScrollFrameHelper::ReloadChildFrames()
 {
   mScrolledFrame = nullptr;
   mHScrollbarBox = nullptr;
   mVScrollbarBox = nullptr;
   mScrollCornerBox = nullptr;
   mResizerBox = nullptr;
 
-  nsIFrame* frame = mOuter->GetFirstPrincipalChild();
-  while (frame) {
+  for (nsIFrame* frame : mOuter->PrincipalChildList()) {
     nsIContent* content = frame->GetContent();
     if (content == mOuter->GetContent()) {
       NS_ASSERTION(!mScrolledFrame, "Already found the scrolled frame");
       mScrolledFrame = frame;
     } else {
       nsAutoString value;
       content->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, value);
       if (!value.IsEmpty()) {
@@ -3935,18 +3934,16 @@ ScrollFrameHelper::ReloadChildFrames()
         NS_ASSERTION(!mResizerBox, "Found multiple resizers");
         mResizerBox = frame;
       } else if (content->IsXULElement(nsGkAtoms::scrollcorner)) {
         // probably a scrollcorner
         NS_ASSERTION(!mScrollCornerBox, "Found multiple scrollcorners");
         mScrollCornerBox = frame;
       }
     }
-
-    frame = frame->GetNextSibling();
   }
 }
 
 nsresult
 ScrollFrameHelper::CreateAnonymousContent(
   nsTArray<nsIAnonymousContentCreator::ContentInfo>& aElements)
 {
   nsPresContext* presContext = mOuter->PresContext();
@@ -5332,17 +5329,17 @@ ScrollFrameHelper::GetScrolledRectIntern
                                                const nsSize& aScrollPortSize) const
 {
   uint8_t frameDir = IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
 
   // If the scrolled frame has unicode-bidi: plaintext, the paragraph
   // direction set by the text content overrides the direction of the frame
   if (mScrolledFrame->StyleTextReset()->mUnicodeBidi &
       NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
-    nsIFrame* childFrame = mScrolledFrame->GetFirstPrincipalChild();
+    nsIFrame* childFrame = mScrolledFrame->PrincipalChildList().FirstChild();
     if (childFrame) {
       frameDir =
         (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
           ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
     }
   }
 
   return nsLayoutUtils::GetScrolledRect(mScrolledFrame,
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -3580,17 +3580,17 @@ nsGridContainerFrame::SanityCheckAnonymo
   XXX haven't decided yet whether to reorder children or not.
   XXX If we do, we want this assertion instead of the one below.
         MOZ_ASSERT(!prevChildWasAnonGridItem ||
                    HasAnyStateBits(NS_STATE_GRID_CHILDREN_REORDERED),
                    "two anon grid items in a row (shouldn't happen, unless our "
                    "children have been reordered with the 'order' property)");
 */
         MOZ_ASSERT(!prevChildWasAnonGridItem, "two anon grid items in a row");
-        nsIFrame* firstWrappedChild = child->GetFirstPrincipalChild();
+        nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
         MOZ_ASSERT(firstWrappedChild,
                    "anonymous grid item is empty (shouldn't happen)");
         prevChildWasAnonGridItem = true;
       } else {
         prevChildWasAnonGridItem = false;
       }
     }
   }
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -90,17 +90,17 @@ public:
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   // Inserted child content gets its frames parented by our child block
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
 protected:
   virtual ~nsHTMLCanvasFrame();
 
   nscoord GetContinuationOffset(nscoord* aWidth = 0) const;
 
   mozilla::LogicalMargin mBorderPadding;
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -565,17 +565,17 @@ nsHTMLReflowState::InitResizeFlags(nsPre
       // FIXME: This isn't so great for the cases where
       // nsHTMLReflowState::SetComputedWidth is called, if the first time
       // we go through InitResizeFlags we set IsHResize() to true, and then
       // the second time we'd set it to false even without the
       // NS_FRAME_IS_DIRTY bit already set.
       if (frame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
         // Foreign object frames use dirty bits in a special way.
         frame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
-        nsIFrame *kid = frame->GetFirstPrincipalChild();
+        nsIFrame *kid = frame->PrincipalChildList().FirstChild();
         if (kid) {
           kid->AddStateBits(NS_FRAME_IS_DIRTY);
         }
       } else {
         frame->AddStateBits(NS_FRAME_IS_DIRTY);
       }
 
       // Mark intrinsic widths on all descendants dirty.  We need to do
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1074,29 +1074,25 @@ public:
   /**
    * Get the specified child list.
    *
    * @param   aListID identifies the requested child list.
    * @return  the child list.  If the requested list is unsupported by this
    *          frame type, an empty list will be returned.
    */
   virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
-  const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
+  const nsFrameList& PrincipalChildList() const { return GetChildList(kPrincipalList); }
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
 
   /**
    * Gets the child lists for this frame, including
    * ones belong to a child document.
    */
   void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
 
-  nsIFrame* GetFirstPrincipalChild() const {
-    return GetChildList(kPrincipalList).FirstChild();
-  }
-
   // The individual concrete child lists.
   static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
   static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
   static const ChildListID kBulletList = mozilla::layout::kBulletList;
   static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
   static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
   static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
   static const ChildListID kFixedList = mozilla::layout::kFixedList;
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -647,17 +647,17 @@ nsInlineFrame::ReflowFrames(nsPresContex
         }
         MOZ_ASSERT(!child || mFrames.ContainsFrame(child));
       } while (child);
 
       // Fix the parent pointer for ::first-letter child frame next-in-flows,
       // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042).
       nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame);
       if (realFrame->GetType() == nsGkAtoms::letterFrame) {
-        nsIFrame* child = realFrame->GetFirstPrincipalChild();
+        nsIFrame* child = realFrame->PrincipalChildList().FirstChild();
         if (child) {
           NS_ASSERTION(child->GetType() == nsGkAtoms::textFrame,
                        "unexpected frame type");
           nsIFrame* nextInFlow = child->GetNextInFlow();
           for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
             NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame,
                          "unexpected frame type");
             if (mFrames.ContainsFrame(nextInFlow)) {
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -460,17 +460,17 @@ GetNextPage(nsIFrame* aPageContentFrame)
   nsIFrame* pageFrame = aPageContentFrame->GetParent();
   NS_ASSERTION(pageFrame->GetType() == nsGkAtoms::pageFrame,
                "pageContentFrame has unexpected parent");
   nsIFrame* nextPageFrame = pageFrame->GetNextSibling();
   if (!nextPageFrame)
     return nullptr;
   NS_ASSERTION(nextPageFrame->GetType() == nsGkAtoms::pageFrame,
                "pageFrame's sibling is not a page frame...");
-  nsIFrame* f = nextPageFrame->GetFirstPrincipalChild();
+  nsIFrame* f = nextPageFrame->PrincipalChildList().FirstChild();
   NS_ASSERTION(f, "pageFrame has no page content frame!");
   NS_ASSERTION(f->GetType() == nsGkAtoms::pageContentFrame,
                "pageFrame's child is not page content!");
   return f;
 }
 
 static gfx::Matrix4x4 ComputePageTransform(nsIFrame* aFrame, float aAppUnitsPerPixel)
 {
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -1766,31 +1766,28 @@ nsPluginFrame::SetIsDocumentActive(bool 
     mInstanceOwner->UpdateDocumentActiveState(aIsActive);
   }
 }
 
 // static
 nsIObjectFrame *
 nsPluginFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
 {
-  nsIFrame* child = aRoot->GetFirstPrincipalChild();
-
-  while (child) {
+  for (nsIFrame* child : aRoot->PrincipalChildList()) {
     nsIObjectFrame* outFrame = do_QueryFrame(child);
     if (outFrame) {
       RefPtr<nsNPAPIPluginInstance> pi;
       outFrame->GetPluginInstance(getter_AddRefs(pi));  // make sure we have a REAL plugin
       if (pi)
         return outFrame;
     }
 
     outFrame = GetNextObjectFrame(aPresContext, child);
     if (outFrame)
       return outFrame;
-    child = child->GetNextSibling();
   }
 
   return nullptr;
 }
 
 /*static*/ void
 nsPluginFrame::BeginSwapDocShells(nsISupports* aSupports, void*)
 {
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -63,17 +63,17 @@ nsRubyBaseContainerFrame::GetFrameName(n
 
 static gfxBreakPriority
 LineBreakBefore(nsIFrame* aFrame,
                 DrawTarget* aDrawTarget,
                 nsIFrame* aLineContainerFrame,
                 const nsLineList::iterator* aLine)
 {
   for (nsIFrame* child = aFrame; child;
-       child = child->GetFirstPrincipalChild()) {
+       child = child->PrincipalChildList().FirstChild()) {
     if (!child->CanContinueTextRun()) {
       // It is not an inline element. We can break before it.
       return gfxBreakPriority::eNormalBreak;
     }
     if (child->GetType() != nsGkAtoms::textFrame) {
       continue;
     }
 
@@ -236,17 +236,17 @@ nsRubyBaseContainerFrame::AddInlinePrefI
     RubyColumnEnumerator enumerator(
       static_cast<nsRubyBaseContainerFrame*>(frame), textContainers);
     for (; !enumerator.AtEnd(); enumerator.Next()) {
       sum += CalculateColumnPrefISize(aRenderingContext, enumerator, aData);
     }
   }
   for (uint32_t i = 0, iend = textContainers.Length(); i < iend; i++) {
     if (textContainers[i]->IsSpanContainer()) {
-      nsIFrame* frame = textContainers[i]->GetFirstPrincipalChild();
+      nsIFrame* frame = textContainers[i]->PrincipalChildList().FirstChild();
       nsIFrame::InlinePrefISizeData data;
       frame->AddInlinePrefISize(aRenderingContext, &data);
       MOZ_ASSERT(data.prevLines == 0, "Shouldn't have prev lines");
       sum = std::max(sum, data.currentLine);
     }
   }
   aData->currentLine += sum;
 }
@@ -813,17 +813,17 @@ nsRubyBaseContainerFrame::ReflowSpans(co
   nscoord spanISize = 0;
   for (uint32_t i = 0, iend = aReflowState.mTextContainers.Length();
        i < iend; i++) {
     nsRubyTextContainerFrame* container = aReflowState.mTextContainers[i];
     if (!container->IsSpanContainer()) {
       continue;
     }
 
-    nsIFrame* rtFrame = container->GetFirstPrincipalChild();
+    nsIFrame* rtFrame = container->PrincipalChildList().FirstChild();
     nsReflowStatus reflowStatus;
     bool pushedFrame;
     nsLineLayout* lineLayout = aReflowState.mTextReflowStates[i]->mLineLayout;
     MOZ_ASSERT(lineLayout->GetCurrentICoord() == 0,
                "border/padding of rtc should have been suppressed");
     lineLayout->ReflowFrame(rtFrame, reflowStatus, nullptr, pushedFrame);
     MOZ_ASSERT(!NS_INLINE_IS_BREAK(reflowStatus) && !pushedFrame,
                "Any line break inside ruby box should has been suppressed");
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -515,17 +515,17 @@ GetPrintCanvasElementsInFrame(nsIFrame* 
         HTMLCanvasElement* canvas =
           HTMLCanvasElement::FromContentOrNull(canvasFrame->GetContent());
         if (canvas && canvas->GetMozPrintCallback()) {
           aArr->AppendElement(canvas);
           continue;
         }
       }
 
-      if (!child->GetFirstPrincipalChild()) {
+      if (!child->PrincipalChildList().FirstChild()) {
         nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(child);
         if (subdocumentFrame) {
           // Descend into the subdocument
           nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
           child = root;
         }
       }
       // The current child is not a nsHTMLCanvasFrame OR it is but there is
@@ -737,17 +737,17 @@ nsSimplePageSequenceFrame::PrintNextPage
     // I will soon improve this to work with IFrames 
     bool    continuePrinting = true;
     nscoord width, height;
     width = PresContext()->GetPageSize().width;
     height = PresContext()->GetPageSize().height;
     height -= mMargin.top + mMargin.bottom;
     width  -= mMargin.left + mMargin.right;
     nscoord selectionY = height;
-    nsIFrame* conFrame = currentPage->GetFirstPrincipalChild();
+    nsIFrame* conFrame = currentPage->PrincipalChildList().FirstChild();
     if (mSelectionHeight >= 0) {
       conFrame->SetPosition(conFrame->GetPosition() + nsPoint(0, -mYSelOffset));
       nsContainerFrame::PositionChildViews(conFrame);
     }
 
     // cast the frame to be a page frame
     nsPageFrame * pf = static_cast<nsPageFrame*>(currentPage);
     pf->SetPageNumInfo(mPageNum, mTotalPages);
@@ -832,17 +832,17 @@ nsSimplePageSequenceFrame::BuildDisplayL
   nsDisplayList content;
 
   {
     // Clear clip state while we construct the children of the
     // nsDisplayTransform, since they'll be in a different coordinate system.
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     clipState.Clear();
 
-    nsIFrame* child = GetFirstPrincipalChild();
+    nsIFrame* child = PrincipalChildList().FirstChild();
     nsRect dirty = aDirtyRect;
     dirty.ScaleInverseRoundOut(PresContext()->GetPrintPreviewScale());
 
     while (child) {
       if (child->GetVisualOverflowRectRelativeToParent().Intersects(dirty)) {
         child->BuildDisplayListForStackingContext(aBuilder,
             dirty - child->GetPosition(), &content);
         aBuilder->ResetMarkedFramesForDisplayList();
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -1265,17 +1265,17 @@ nsSubDocumentFrame::ObtainIntrinsicSizeF
     GetDocShell(getter_AddRefs(docShell));
     if (docShell) {
       nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
       if (presShell) {
         nsIScrollableFrame* scrollable = presShell->GetRootScrollFrameAsScrollable();
         if (scrollable) {
           nsIFrame* scrolled = scrollable->GetScrolledFrame();
           if (scrolled) {
-            subDocRoot = scrolled->GetFirstPrincipalChild();
+            subDocRoot = scrolled->PrincipalChildList().FirstChild();
           }
         }
       }
     }
 
     if (subDocRoot && subDocRoot->GetContent() &&
         subDocRoot->GetContent()->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
       return subDocRoot; // SVG documents have an intrinsic size
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -1140,17 +1140,17 @@ CanTextCrossFrameBoundary(nsIFrame* aFra
       result.mScanSiblings = false;
       result.mTextRunCanCrossFrameBoundary = false;
     } else {
       result.mFrameToScan = nullptr;
       result.mTextRunCanCrossFrameBoundary = true;
     }
   } else {
     if (continuesTextRun) {
-      result.mFrameToScan = aFrame->GetFirstPrincipalChild();
+      result.mFrameToScan = aFrame->PrincipalChildList().FirstChild();
       result.mOverflowFrameToScan =
         aFrame->GetChildList(nsIFrame::kOverflowList).FirstChild();
       NS_WARN_IF_FALSE(!result.mOverflowFrameToScan,
                        "Scanning overflow inline frames is something we should avoid");
       result.mScanSiblings = true;
       result.mTextRunCanCrossFrameBoundary = true;
       result.mLineBreakerCanCrossFrameBoundary = true;
     } else {
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -937,19 +937,17 @@ ComputeSizeFromParts(nsPresContext* aPre
                      nsGlyphCode* aGlyphs,
                      nscoord*     aSizes,
                      nscoord      aTargetSize)
 {
   enum {first, middle, last, glue};
   // Add the parts that cannot be left out.
   nscoord sum = 0;
   for (int32_t i = first; i <= last; i++) {
-    if (aGlyphs[i] != aGlyphs[glue]) {
-      sum += aSizes[i];
-    }
+    sum += aSizes[i];
   }
 
   // Determine how much is used in joins
   nscoord oneDevPixel = aPresContext->AppUnitsPerDevPixel();
   int32_t joins = aGlyphs[middle] == aGlyphs[glue] ? 1 : 2;
 
   // Pick a maximum size using a maximum number of glue glyphs that we are
   // prepared to draw for one character.
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -213,17 +213,17 @@ nsMathMLContainerFrame::GetPreferredStre
                  aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL,
                  "You must specify a direction in which to stretch");
     NS_ASSERTION(NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) ||
                  stretchAll,
                  "invalid call to GetPreferredStretchSize");
     bool firstTime = true;
     nsBoundingMetrics bm, bmChild;
     nsIFrame* childFrame =
-      stretchAll ? GetFirstPrincipalChild() : mPresentationData.baseFrame;
+      stretchAll ? PrincipalChildList().FirstChild() : mPresentationData.baseFrame;
     while (childFrame) {
       // initializations in case this child happens not to be a MathML frame
       nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
       if (mathMLFrame) {
         nsEmbellishData embellishData;
         nsPresentationData presentationData;
         mathMLFrame->GetEmbellishData(embellishData);
         mathMLFrame->GetPresentationData(presentationData);
@@ -477,17 +477,17 @@ nsMathMLContainerFrame::FinalizeReflow(D
   // Place() will call FinishReflowChild() when placeOrigin is true but if
   // it returns before reaching FinishReflowChild() due to errors we need
   // to fulfill the reflow protocol by calling DidReflow for the child frames
   // that still needs it here (or we may crash - bug 366012).
   // If placeOrigin is false we should reach Place() with aPlaceOrigin == true
   // through Stretch() eventually.
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
     GatherAndStoreOverflow(&aDesiredSize);
-    DidReflowChildren(GetFirstPrincipalChild());
+    DidReflowChildren(PrincipalChildList().FirstChild());
     return rv;
   }
 
   bool parentWillFireStretch = false;
   if (!placeOrigin) {
     // This means the rect.x and rect.y of our children were not set!!
     // Don't go without checking to see if our parent will later fire a Stretch() command
     // targeted at us. The Stretch() will cause the rect.x and rect.y to clear...
@@ -526,18 +526,17 @@ nsMathMLContainerFrame::FinalizeReflow(D
       // The stretch call will detect if this is incorrect and recalculate the size.
       nsBoundingMetrics defaultSize = aDesiredSize.mBoundingMetrics;
 
       Stretch(aDrawTarget, stretchDir, defaultSize, aDesiredSize);
 #ifdef DEBUG
       {
         // The Place() call above didn't request FinishReflowChild(),
         // so let's check that we eventually did through Stretch().
-        nsIFrame* childFrame = GetFirstPrincipalChild();
-        for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
+        for (nsIFrame* childFrame : PrincipalChildList()) {
           NS_ASSERTION(!(childFrame->GetStateBits() & NS_FRAME_IN_REFLOW),
                        "DidReflow() was never called");
         }
       }
 #endif
     }
   }
 
@@ -582,45 +581,41 @@ nsMathMLContainerFrame::PropagatePresent
                                         aFlagsToUpdate);
     // propagate using the base method to make sure that the control
     // is passed on to MathML frames that may be overloading the method
     mathMLFrame->UpdatePresentationDataFromChildAt(0, -1,
       aFlagsValues, aFlagsToUpdate);
   }
   else {
     // propagate down the subtrees
-    nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
-    while (childFrame) {
+    for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
       PropagatePresentationDataFor(childFrame,
         aFlagsValues, aFlagsToUpdate);
-      childFrame = childFrame->GetNextSibling();
     }
   }
 }
 
 /* static */ void
 nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame*       aParentFrame,
                                                              int32_t         aFirstChildIndex,
                                                              int32_t         aLastChildIndex,
                                                              uint32_t        aFlagsValues,
                                                              uint32_t        aFlagsToUpdate)
 {
   if (!aParentFrame || !aFlagsToUpdate)
     return;
   int32_t index = 0;
-  nsIFrame* childFrame = aParentFrame->GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : aParentFrame->PrincipalChildList()) {
     if ((index >= aFirstChildIndex) &&
         ((aLastChildIndex <= 0) || ((aLastChildIndex > 0) &&
          (index <= aLastChildIndex)))) {
       PropagatePresentationDataFor(childFrame,
         aFlagsValues, aFlagsToUpdate);
     }
     index++;
-    childFrame = childFrame->GetNextSibling();
   }
 }
 
 /* //////////////////
  * Frame construction
  * =============================================================================
  */
 
@@ -661,24 +656,22 @@ nsMathMLContainerFrame::BuildDisplayList
 // parent frame may do in its TransmitAutomaticData()).
 /* static */ void
 nsMathMLContainerFrame::RebuildAutomaticDataForChildren(nsIFrame* aParentFrame)
 {
   // 1. As we descend the tree, make each child frame inherit data from
   // the parent
   // 2. As we ascend the tree, transmit any specific change that we want
   // down the subtrees
-  nsIFrame* childFrame = aParentFrame->GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : aParentFrame->PrincipalChildList()) {
     nsIMathMLFrame* childMathMLFrame = do_QueryFrame(childFrame);
     if (childMathMLFrame) {
       childMathMLFrame->InheritAutomaticData(aParentFrame);
     }
     RebuildAutomaticDataForChildren(childFrame);
-    childFrame = childFrame->GetNextSibling();
   }
   nsIMathMLFrame* mathMLFrame = do_QueryFrame(aParentFrame);
   if (mathMLFrame) {
     mathMLFrame->TransmitAutomaticData();
   }
 }
 
 /* static */ nsresult
@@ -1370,17 +1363,17 @@ nsMathMLContainerFrame::SetIncrementScri
 // helpers to fix the inter-spacing when <math> is the only parent
 // e.g., it fixes <math> <mi>f</mi> <mo>q</mo> <mi>f</mi> <mo>I</mo> </math>
 
 static nscoord
 GetInterFrameSpacingFor(int32_t         aScriptLevel,
                         nsIFrame*       aParentFrame,
                         nsIFrame*       aChildFrame)
 {
-  nsIFrame* childFrame = aParentFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = aParentFrame->PrincipalChildList().FirstChild();
   if (!childFrame || aChildFrame == childFrame)
     return 0;
 
   int32_t carrySpace = 0;
   eMathMLFrameType fromFrameType = eMathMLFrameType_UNKNOWN;
   eMathMLFrameType prevFrameType = eMathMLFrameType_UNKNOWN;
   eMathMLFrameType childFrameType = nsMathMLFrame::GetMathMLFrameTypeFor(childFrame);
   childFrame = childFrame->GetNextSibling();
@@ -1458,17 +1451,17 @@ nsMathMLContainerFrame::DidReflowChildre
     return;
 
   for (nsIFrame* frame = aFirst;
        frame != aStop;
        frame = frame->GetNextSibling()) {
     NS_ASSERTION(frame, "aStop isn't a sibling");
     if (frame->GetStateBits() & NS_FRAME_IN_REFLOW) {
       // finish off principal descendants, too
-      nsIFrame* grandchild = frame->GetFirstPrincipalChild();
+      nsIFrame* grandchild = frame->PrincipalChildList().FirstChild();
       if (grandchild)
         DidReflowChildren(grandchild, nullptr);
 
       frame->DidReflow(frame->PresContext(), nullptr,
                        nsDidReflowStatus::FINISHED);
     }
   }
 }
@@ -1496,17 +1489,17 @@ nsMathMLContainerFrame::TransmitAutomati
   //     containing the same arguments would be an embellished operator;
   //   * an mrow whose arguments consist (in any order) of one embellished
   //     operator and zero or more space-like elements.
   //
   nsIFrame *childFrame, *baseFrame;
   bool embellishedOpFound = false;
   nsEmbellishData embellishData;
   
-  for (childFrame = GetFirstPrincipalChild();
+  for (childFrame = PrincipalChildList().FirstChild();
        childFrame;
        childFrame = childFrame->GetNextSibling()) {
     nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
     if (!mathMLFrame) break;
     if (!mathMLFrame->IsSpaceLike()) {
       if (embellishedOpFound) break;
       baseFrame = childFrame;
       GetEmbellishDataFrom(baseFrame, embellishData);
@@ -1550,20 +1543,18 @@ nsMathMLContainerFrame::TransmitAutomati
 /*static*/ void
 nsMathMLContainerFrame::PropagateFrameFlagFor(nsIFrame* aFrame,
                                               nsFrameState  aFlags)
 {
   if (!aFrame || !aFlags)
     return;
 
   aFrame->AddStateBits(aFlags);
-  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
     PropagateFrameFlagFor(childFrame, aFlags);
-    childFrame = childFrame->GetNextSibling();
   }
 }
 
 nsresult
 nsMathMLContainerFrame::ReportErrorToConsole(const char*       errorMsgId,
                                              const char16_t** aParams,
                                              uint32_t          aParamCount)
 {
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -59,19 +59,19 @@ nsMathMLTokenFrame::MarkTextFramesAsToke
 {
   nsIFrame* child = nullptr;
   uint32_t childCount = 0;
 
   // Set flags on child text frames
   // - to force them to trim their leading and trailing whitespaces.
   // - Indicate which frames are suitable for mathvariant
   // - flag single character <mi> frames for special italic treatment
-  for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
+  for (nsIFrame* childFrame = PrincipalChildList().FirstChild(); childFrame;
        childFrame = childFrame->GetNextSibling()) {
-    for (nsIFrame* childFrame2 = childFrame->GetFirstPrincipalChild();
+    for (nsIFrame* childFrame2 = childFrame->PrincipalChildList().FirstChild();
          childFrame2; childFrame2 = childFrame2->GetNextSibling()) {
       if (childFrame2->GetType() == nsGkAtoms::textFrame) {
         childFrame2->AddStateBits(TEXT_IS_IN_TOKEN_MATHML);
         child = childFrame2;
         childCount++;
       }
     }
   }
@@ -127,34 +127,31 @@ nsMathMLTokenFrame::Reflow(nsPresContext
   MarkInReflow();
   mPresentationData.flags &= ~NS_MATHML_ERROR;
 
   // initializations needed for empty markup like <mtag></mtag>
   aDesiredSize.ClearSize();
   aDesiredSize.SetBlockStartAscent(0);
   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
 
-  nsIFrame* childFrame = GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : PrincipalChildList()) {
     // ask our children to compute their bounding metrics
     nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(),
                                          aDesiredSize.mFlags
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowState.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     ReflowChild(childFrame, aPresContext, childDesiredSize,
                 childReflowState, aStatus);
     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
-
-    childFrame = childFrame->GetNextSibling();
   }
 
   // place and size children
   FinalizeReflow(aReflowState.rendContext->GetDrawTarget(), aDesiredSize);
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
 }
@@ -163,18 +160,17 @@ nsMathMLTokenFrame::Reflow(nsPresContext
 // pass, it is not computed here because our children may be text frames
 // that do not implement the GetBoundingMetrics() interface.
 /* virtual */ nsresult
 nsMathMLTokenFrame::Place(DrawTarget*          aDrawTarget,
                           bool                 aPlaceOrigin,
                           nsHTMLReflowMetrics& aDesiredSize)
 {
   mBoundingMetrics = nsBoundingMetrics();
-  for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
-       childFrame = childFrame->GetNextSibling()) {
+  for (nsIFrame* childFrame :PrincipalChildList()) {
     nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
     GetReflowAndBoundingMetricsFor(childFrame, childSize,
                                    childSize.mBoundingMetrics, nullptr);
     // compute and cache the bounding metrics
     mBoundingMetrics += childSize.mBoundingMetrics;
   }
 
   RefPtr<nsFontMetrics> fm;
@@ -187,18 +183,17 @@ nsMathMLTokenFrame::Place(DrawTarget*   
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   aDesiredSize.Width() = mBoundingMetrics.width;
   aDesiredSize.SetBlockStartAscent(std::max(mBoundingMetrics.ascent, ascent));
   aDesiredSize.Height() = aDesiredSize.BlockStartAscent() +
                         std::max(mBoundingMetrics.descent, descent);
 
   if (aPlaceOrigin) {
     nscoord dy, dx = 0;
-    for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
-         childFrame = childFrame->GetNextSibling()) {
+    for (nsIFrame* childFrame : PrincipalChildList()) {
       nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
       GetReflowAndBoundingMetricsFor(childFrame, childSize,
                                      childSize.mBoundingMetrics);
 
       // place and size the child; (dx,0) makes the caret happy - bug 188146
       dy = childSize.Height() == 0 ? 0 : aDesiredSize.BlockStartAscent() - childSize.BlockStartAscent();
       FinishReflowChild(childFrame, PresContext(), childSize, nullptr, dx, dy, 0);
       dx += childSize.Width();
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -322,17 +322,17 @@ nsMathMLmencloseFrame::PlaceInternal(Dra
   ///////////////
   // Measure the size of our content using the base class to format like an
   // inferred mrow.
   nsHTMLReflowMetrics baseSize(aDesiredSize.GetWritingMode());
   nsresult rv =
     nsMathMLContainerFrame::Place(aDrawTarget, false, baseSize);
 
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
-      DidReflowChildren(GetFirstPrincipalChild());
+      DidReflowChildren(PrincipalChildList().FirstChild());
       return rv;
     }
 
   nsBoundingMetrics bmBase = baseSize.mBoundingMetrics;
   nscoord dx_left = 0, dx_right = 0;
   nsBoundingMetrics bmLongdivChar, bmRadicalChar;
   nscoord radicalAscent = 0, radicalDescent = 0;
   nscoord longdivAscent = 0, longdivDescent = 0;
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -240,17 +240,17 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   // because we want to stretch our fences, separators and stretchy frames using
   // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base
   // method here, our stretchy frames will be stretched and placed, and we may
   // end up stretching our fences/separators with a different aDesiredSize.
   // XXX The above decision was revisited in bug 121748 and this code can be
   // refactored to use nsMathMLContainerFrame::Reflow() at some stage.
 
   nsReflowStatus childStatus;
-  nsIFrame* firstChild = GetFirstPrincipalChild();
+  nsIFrame* firstChild = PrincipalChildList().FirstChild();
   nsIFrame* childFrame = firstChild;
   nscoord ascent = 0, descent = 0;
   if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
     // We use the ASCII metrics to get our minimum height. This way,
     // if we have borders or a background, they will fit better with
     // other elements on the line.
     ascent = fm->MaxAscent();
     descent = fm->MaxDescent();
@@ -621,33 +621,30 @@ nsMathMLmfencedFrame::GetIntrinsicISizeM
   if (mOpenChar) {
     width +=
       GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
                       fontSizeInflation, mOpenChar,
                       NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
   }
 
   int32_t i = 0;
-  nsIFrame* childFrame = GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : PrincipalChildList()) {
     // XXX This includes margin while Reflow currently doesn't consider
     // margin, so we may end up with too much space, but, with stretchy
     // characters, this is an approximation anyway.
     width += nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
                                                   nsLayoutUtils::PREF_ISIZE);
 
     if (i < mSeparatorsCount) {
       width +=
         GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
                         fontSizeInflation, &mSeparatorsChar[i],
                         NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, em);
     }
     i++;
-
-    childFrame = childFrame->GetNextSibling();
   }
 
   if (mCloseChar) {
     width +=
       GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
                       fontSizeInflation, mCloseChar,
                       NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
   }
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -168,17 +168,17 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
 
   nscoord minShiftFromXHeight, subDrop, supDrop;
 
   ////////////////////////////////////////
   // Initialize super/sub shifts that
   // depend only on the current font
   ////////////////////////////////////////
 
-  nsIFrame* baseFrame = aFrame->GetFirstPrincipalChild();
+  nsIFrame* baseFrame = aFrame->PrincipalChildList().FirstChild();
 
   if (!baseFrame) {
     if (tag == nsGkAtoms::mmultiscripts_)
       aFrame->ReportErrorToConsole("NoBase");
     else
       aFrame->ReportChildCountError();
     return aFrame->ReflowError(aDrawTarget, aDesiredSize);
   }
@@ -325,17 +325,17 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
 
   int32_t count = 0;
   bool foundNoneTag = false;
 
   // Boolean to determine whether the current child is a subscript.
   // Note that only msup starts with a superscript.
   bool isSubScript = (tag != nsGkAtoms::msup_);
 
-  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
   while (childFrame) {
     if (childFrame->GetContent()->IsMathMLElement(nsGkAtoms::mprescripts_)) {
       if (tag != nsGkAtoms::mmultiscripts_) {
         if (aPlaceOrigin) {
           aFrame->ReportInvalidChildError(nsGkAtoms::mprescripts_);
         }
         return aFrame->ReflowError(aDrawTarget, aDesiredSize);
       }
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -321,17 +321,17 @@ nsMathMLmpaddedFrame::Reflow(nsPresConte
 /* virtual */ nsresult
 nsMathMLmpaddedFrame::Place(DrawTarget*          aDrawTarget,
                             bool                 aPlaceOrigin,
                             nsHTMLReflowMetrics& aDesiredSize)
 {
   nsresult rv =
     nsMathMLContainerFrame::Place(aDrawTarget, false, aDesiredSize);
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
-    DidReflowChildren(GetFirstPrincipalChild());
+    DidReflowChildren(PrincipalChildList().FirstChild());
     return rv;
   }
 
   nscoord height = aDesiredSize.BlockStartAscent();
   nscoord depth  = aDesiredSize.Height() - aDesiredSize.BlockStartAscent();
   // The REC says:
   //
   // "The lspace attribute ('leading' space) specifies the horizontal location
--- a/layout/mathml/nsMathMLmrowFrame.cpp
+++ b/layout/mathml/nsMathMLmrowFrame.cpp
@@ -38,17 +38,17 @@ nsMathMLmrowFrame::AttributeChanged(int3
                                     nsIAtom* aAttribute,
                                     int32_t  aModType)
 {
   // Special for <mtable>: In the frame construction code, we also use
   // this frame class as a wrapper for mtable. Hence, we should pass the
   // notification to the real mtable
   if (mContent->IsMathMLElement(nsGkAtoms::mtable_)) {
     nsIFrame* frame = mFrames.FirstChild();
-    for ( ; frame; frame = frame->GetFirstPrincipalChild()) {
+    for ( ; frame; frame = frame->PrincipalChildList().FirstChild()) {
       // drill down to the real mtable
       if (frame->GetType() == nsGkAtoms::tableOuterFrame)
         return frame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
     }
     NS_NOTREACHED("mtable wrapper without the real table frame");
   }
 
   return nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -572,31 +572,29 @@ MapAllAttributesIntoCSS(nsMathMLmtableFr
   // Map mtable columnalign & columnlines.
   ParseFrameAttribute(aTableFrame, nsGkAtoms::columnalign_, true);
   ParseFrameAttribute(aTableFrame, nsGkAtoms::columnlines_, true);
 
   // Map mtable rowspacing, columnspacing & framespacing
   ParseSpacingAttributes(aTableFrame);
 
   // mtable is simple and only has one (pseudo) row-group
-  nsIFrame* rgFrame = aTableFrame->GetFirstPrincipalChild();
+  nsIFrame* rgFrame = aTableFrame->PrincipalChildList().FirstChild();
   if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
     return;
 
-  nsIFrame* rowFrame = rgFrame->GetFirstPrincipalChild();
-  for ( ; rowFrame; rowFrame = rowFrame->GetNextSibling()) {
+  for (nsIFrame* rowFrame : rgFrame->PrincipalChildList()) {
     DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW);
     if (rowFrame->GetType() == nsGkAtoms::tableRowFrame) {
       // Map row rowalign.
       ParseFrameAttribute(rowFrame, nsGkAtoms::rowalign_, false);
       // Map row columnalign.
       ParseFrameAttribute(rowFrame, nsGkAtoms::columnalign_, true);
 
-      nsIFrame* cellFrame = rowFrame->GetFirstPrincipalChild();
-      for ( ; cellFrame; cellFrame = cellFrame->GetNextSibling()) {
+      for (nsIFrame* cellFrame : rowFrame->PrincipalChildList()) {
         DEBUG_VERIFY_THAT_FRAME_IS(cellFrame, TABLE_CELL);
         if (IS_TABLE_CELL(cellFrame->GetType())) {
           // Map cell rowalign.
           ParseFrameAttribute(cellFrame, nsGkAtoms::rowalign_, false);
           // Map row columnalign.
           ParseFrameAttribute(cellFrame, nsGkAtoms::columnalign_, false);
         }
       }
@@ -720,17 +718,17 @@ nsMathMLmtableOuterFrame::AttributeChang
   // columnalign   : here 
   // columnlines   : here 
   // columnspacing : here
 
   // mtable is simple and only has one (pseudo) row-group inside our inner-table
   nsIFrame* tableFrame = mFrames.FirstChild();
   NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
                "should always have an inner table frame");
-  nsIFrame* rgFrame = tableFrame->GetFirstPrincipalChild();
+  nsIFrame* rgFrame = tableFrame->PrincipalChildList().FirstChild();
   if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
     return NS_OK;
 
   // align - just need to issue a dirty (resize) reflow command
   if (aAttribute == nsGkAtoms::align) {
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     return NS_OK;
@@ -793,17 +791,17 @@ nsMathMLmtableOuterFrame::GetRowFrameAt(
     --aRowIndex;
   }
 
   // if our inner table says that the index is valid, find the row now
   if (0 <= aRowIndex && aRowIndex <= rowCount) {
     nsIFrame* tableFrame = mFrames.FirstChild();
     NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame,
                  "should always have an inner table frame");
-    nsIFrame* rgFrame = tableFrame->GetFirstPrincipalChild();
+    nsIFrame* rgFrame = tableFrame->PrincipalChildList().FirstChild();
     if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
       return nullptr;
     for (nsIFrame* rowFrame : rgFrame->PrincipalChildList()) {
       if (aRowIndex == 0) {
         DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW);
         if (rowFrame->GetType() != nsGkAtoms::tableRowFrame)
           return nullptr;
 
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2233,21 +2233,17 @@ nsPrintEngine::CalcNumPrintablePages(int
   // and printable pages
   for (uint32_t i=0; i<mPrt->mPrintDocList.Length(); i++) {
     nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
     NS_ASSERTION(po, "nsPrintObject can't be null!");
     if (po->mPresContext && po->mPresContext->IsRootPaginatedDocument()) {
       nsIPageSequenceFrame* pageSequence = po->mPresShell->GetPageSequenceFrame();
       nsIFrame * seqFrame = do_QueryFrame(pageSequence);
       if (seqFrame) {
-        nsIFrame* frame = seqFrame->GetFirstPrincipalChild();
-        while (frame) {
-          aNumPages++;
-          frame = frame->GetNextSibling();
-        }
+        aNumPages += seqFrame->PrincipalChildList().GetLength();
       }
     }
   }
 }
 
 //-----------------------------------------------------------------
 //-- Done: Reflow Methods
 //-----------------------------------------------------------------
@@ -2862,38 +2858,36 @@ nsPrintEngine::GetPageRangeForSelection(
 
 #ifdef DEBUG_rodsX
   printf("Start Page: %p\n", startPageFrame);
   printf("End Page:   %p\n", endPageFrame);
 
   // dump all the pages and their pointers
   {
   int32_t pageNum = 1;
-  nsIFrame* child = seqFrame->GetFirstPrincipalChild();
+  nsIFrame* child = seqFrame->PrincipalChildList().FirstChild();
   while (child != nullptr) {
     printf("Page: %d - %p\n", pageNum, child);
     pageNum++;
     child = child->GetNextSibling();
   }
   }
 #endif
 
   // Now that we have the page frames
   // find out what the page numbers are for each frame
   int32_t pageNum = 1;
-  nsIFrame* page = seqFrame->GetFirstPrincipalChild();
-  while (page != nullptr) {
+  for (nsIFrame* page : seqFrame->PrincipalChildList()) {
     if (page == startPageFrame) {
       aStartPageNum = pageNum;
     }
     if (page == endPageFrame) {
       aEndPageNum = pageNum;
     }
     pageNum++;
-    page = page->GetNextSibling();
   }
 
 #ifdef DEBUG_rodsX
   printf("Start Page No: %d\n", aStartPageNum);
   printf("End Page No:   %d\n", aEndPageNum);
 #endif
 
   *aStartFrame = startPageFrame;
@@ -3637,17 +3631,17 @@ static void DumpFrames(FILE*            
                        nsIFrame *            aFrame,
                        int32_t               aLevel)
 {
   NS_ASSERTION(out, "Pointer is null!");
   NS_ASSERTION(aPresContext, "Pointer is null!");
   NS_ASSERTION(aRendContext, "Pointer is null!");
   NS_ASSERTION(aFrame, "Pointer is null!");
 
-  nsIFrame* child = aFrame->GetFirstPrincipalChild();
+  nsIFrame* child = aFrame->PrincipalChildList().FirstChild();
   while (child != nullptr) {
     for (int32_t i=0;i<aLevel;i++) {
      fprintf(out, "  ");
     }
     nsAutoString tmp;
     child->GetFrameName(tmp);
     fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
     bool isSelected;
@@ -3778,17 +3772,17 @@ static void DumpPrintObjectsList(nsTArra
     nsIFrame* rootFrame = nullptr;
     if (po->mPresShell) {
       rootFrame = po->mPresShell->FrameManager()->GetRootFrame();
       while (rootFrame != nullptr) {
         nsIPageSequenceFrame * sqf = do_QueryFrame(rootFrame);
         if (sqf) {
           break;
         }
-        rootFrame = rootFrame->GetFirstPrincipalChild();
+        rootFrame = rootFrame->PrincipalChildList().FirstChild();
       }
     }
 
     PR_PL(("%s %d %d %d %p %p %p %p %p   %d   %d,%d,%d,%d\n", types[po->mFrameType],
             po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mDocShell.get(), po->mSeqFrame,
             po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height));
   }
 }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mo-glyph-size-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+</head>
+<body>
+<!-- Bug 1219068 -->
+
+<div id="hider"
+     style="position:absolute; top:0; left:0; background-color:green;
+            height:1em; width:100%; z-index:1; padding-top:5px;
+            padding-bottom:5px;" />
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mo-glyph-size.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="UTF-8">
+</head>
+<body>
+<!-- Bug 1219068 -->
+
+<math style="position:absolute; top: 0; font-size:1em;  z-index: 0;" display="block">
+<mrow>
+  <mo>|</mo>
+  <mrow>
+    <mi>f</mi>
+    <mrow>
+      <mn>(</mn>
+      <mi>x</mi>
+      <mn>)</mn>
+    </mrow>
+    <mn>-</mn>
+    <mrow>
+      <mi>f</mi>
+      <mrow>
+        <mn>(</mn>
+        <msub>
+          <mi>x</mi>
+          <mn>0</mn>
+        </msub>
+        <mn>)</mn>
+      </mrow>
+    </mrow>
+  </mrow>
+  <mo>|</mo>
+</mrow>
+</math>
+<div id="hider"
+     style="position:absolute; top:0; left:0; background-color:green;
+            height:1em; width:100%; z-index:1; padding-top:5px;
+            padding-bottom:5px; visibility:hidden" />
+  <script>
+    function obscureMathML() {
+      var hider = document.getElementById("hider");
+      hider.style.visibility="visible";
+      // The math should now be completely obscured
+
+      document.documentElement.removeAttribute("class");
+    }
+    window.addEventListener("MozReftestInvalidate", obscureMathML, false);
+  </script>
+</body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -185,16 +185,17 @@ fails-if(Mulet) == mpadded-7.html mpadde
 skip-if(B2G||Mulet) == maction-dynamic-1.html maction-dynamic-1-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == maction-dynamic-2.html maction-dynamic-2-ref.html
 == mo-lspace-rspace.html mo-lspace-rspace-ref.html
 == mo-lspace-rspace-2.html mo-lspace-rspace-2-ref.html
 == mo-lspace-rspace-3.html mo-lspace-rspace-3-ref.html
 == mo-lspace-rspace-4.html mo-lspace-rspace-4-ref.html
 == mo-invisibleoperators.html mo-invisibleoperators-ref.html
 == mo-invisibleoperators-2.html mo-invisibleoperators-2-ref.html
+== mo-glyph-size.html mo-glyph-size-ref.html
 skip-if(B2G||Mulet) == maction-dynamic-3.html maction-dynamic-3-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == whitespace-trim-1.html whitespace-trim-1-ref.html
 == whitespace-trim-2.html whitespace-trim-2-ref.html
 == whitespace-trim-3.html whitespace-trim-3-ref.html
 fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 787215
 == whitespace-trim-5.html whitespace-trim-5-ref.html
 random-if(winWidget&&!d2d) == opentype-stretchy.html opentype-stretchy-ref.html
 == opentype-fraction-dynamic-linethickness.html opentype-fraction-dynamic-linethickness-ref.html
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -668,17 +668,17 @@ nsComputedDOMStyle::UpdateCurrentStyleSo
       !mContent->IsHTMLElement(nsGkAtoms::area)) {
     mOuterFrame = mContent->GetPrimaryFrame();
     mInnerFrame = mOuterFrame;
     if (mOuterFrame) {
       nsIAtom* type = mOuterFrame->GetType();
       if (type == nsGkAtoms::tableOuterFrame) {
         // If the frame is an outer table frame then we should get the style
         // from the inner table frame.
-        mInnerFrame = mOuterFrame->GetFirstPrincipalChild();
+        mInnerFrame = mOuterFrame->PrincipalChildList().FirstChild();
         NS_ASSERTION(mInnerFrame, "Outer table must have an inner");
         NS_ASSERTION(!mInnerFrame->GetNextSibling(),
                      "Outer table frames should have just one child, "
                      "the inner table");
       }
 
       SetFrameStyleContext(mInnerFrame->StyleContext());
       NS_ASSERTION(mStyleContext, "Frame without style context?");
@@ -4886,17 +4886,17 @@ nsComputedDOMStyle::GetAbsoluteOffset(mo
 
   if (container->GetType() == nsGkAtoms::viewportFrame) {
     // For absolutely positioned frames scrollbars are taken into
     // account by virtue of getting a containing block that does
     // _not_ include the scrollbars.  For fixed positioned frames,
     // the containing block is the viewport, which _does_ include
     // scrollbars.  We have to do some extra work.
     // the first child in the default frame list is what we want
-    nsIFrame* scrollingChild = container->GetFirstPrincipalChild();
+    nsIFrame* scrollingChild = container->PrincipalChildList().FirstChild();
     nsIScrollableFrame *scrollFrame = do_QueryFrame(scrollingChild);
     if (scrollFrame) {
       scrollbarSizes = scrollFrame->GetActualScrollbarSizes();
     }
   }
 
   nscoord offset = 0;
   switch (aSide) {
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -434,17 +434,17 @@ TruncateTo(nsTArray<T>& aArrayToTruncate
  * since we sometimes need to call this function during reflow, after the
  * kid has been reflowed but before we have cleared the dirty bits on the
  * frame itself.
  */
 static SVGTextFrame*
 FrameIfAnonymousChildReflowed(SVGTextFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "aFrame must not be null");
-  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
+  nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   if (NS_SUBTREE_DIRTY(kid)) {
     MOZ_ASSERT(false, "should have already reflowed the anonymous block child");
     return nullptr;
   }
   return aFrame;
 }
 
 static double
@@ -1472,19 +1472,17 @@ TextNodeCorrespondenceRecorder::NextNode
 }
 
 void
 TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame)
 {
   // Recursively iterate over the frame tree, for frames that correspond
   // to text content elements.
   if (IsTextContentElement(aFrame->GetContent())) {
-    for (nsIFrame* f = aFrame->GetFirstPrincipalChild();
-         f;
-         f = f->GetNextSibling()) {
+    for (nsIFrame* f : aFrame->PrincipalChildList()) {
       TraverseAndRecord(f);
     }
     return;
   }
 
   nsTextFrame* frame;  // The current text frame.
   nsTextNode* node;    // The text node for the current text frame.
   if (!GetNonEmptyTextFrameAndNode(aFrame, frame, node)) {
@@ -1753,18 +1751,18 @@ private:
    * The iterator's current position relative to mSubtree.
    */
   SubtreePosition mSubtreePosition;
 };
 
 uint32_t
 TextFrameIterator::UndisplayedCharacters() const
 {
-  MOZ_ASSERT(!(mRootFrame->GetFirstPrincipalChild() &&
-               NS_SUBTREE_DIRTY(mRootFrame->GetFirstPrincipalChild())),
+  MOZ_ASSERT(!(mRootFrame->PrincipalChildList().FirstChild() &&
+               NS_SUBTREE_DIRTY(mRootFrame->PrincipalChildList().FirstChild())),
              "should have already reflowed the anonymous block child");
 
   if (!mCurrentFrame) {
     return mRootFrame->mTrailingUndisplayedCharacters;
   }
 
   nsTextFrame* frame = do_QueryFrame(mCurrentFrame);
   return GetUndisplayedCharactersBeforeFrame(frame);
@@ -1774,17 +1772,17 @@ nsTextFrame*
 TextFrameIterator::Next()
 {
   // Starting from mCurrentFrame, we do a non-recursive traversal to the next
   // nsTextFrame beneath mRoot, updating mSubtreePosition appropriately if we
   // encounter mSubtree.
   if (mCurrentFrame) {
     do {
       nsIFrame* next = IsTextContentElement(mCurrentFrame->GetContent()) ?
-                         mCurrentFrame->GetFirstPrincipalChild() :
+                         mCurrentFrame->PrincipalChildList().FirstChild() :
                          nullptr;
       if (next) {
         // Descend into this frame, and accumulate its position.
         mCurrentPosition += next->GetPosition();
         if (next->GetContent()->IsSVGElement(nsGkAtoms::textPath)) {
           // Record this <textPath> frame.
           mTextPathFrames.AppendElement(next);
         }
@@ -3662,17 +3660,17 @@ ShouldPaintCaret(const TextRenderedRun& 
 
 nsresult
 SVGTextFrame::PaintSVG(gfxContext& aContext,
                        const gfxMatrix& aTransform,
                        const nsIntRect *aDirtyRect)
 {
   DrawTarget& aDrawTarget = *aContext.GetDrawTarget();
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return NS_OK;
 
   nsPresContext* presContext = PresContext();
 
   gfxMatrix initialMatrix = aContext.CurrentMatrix();
 
   if (mState & NS_FRAME_IS_NONDISPLAY) {
@@ -3803,17 +3801,17 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
   }
 
   return NS_OK;
 }
 
 nsIFrame*
 SVGTextFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
-  NS_ASSERTION(GetFirstPrincipalChild(), "must have a child frame");
+  NS_ASSERTION(PrincipalChildList().FirstChild(), "must have a child frame");
 
   if (mState & NS_FRAME_IS_NONDISPLAY) {
     // Text frames inside <clipPath> will never have had ReflowSVG called on
     // them, so call UpdateGlyphPositioning to do this now.  (Text frames
     // inside <mask> and other non-display containers will never need to
     // be hit tested.)
     UpdateGlyphPositioning();
   } else {
@@ -3972,19 +3970,19 @@ TextRenderedRunFlagsForBBoxContribution(
   }
   return flags;
 }
 
 SVGBBox
 SVGTextFrame::GetBBoxContribution(const gfx::Matrix &aToBBoxUserspace,
                                   uint32_t aFlags)
 {
-  NS_ASSERTION(GetFirstPrincipalChild(), "must have a child frame");
+  NS_ASSERTION(PrincipalChildList().FirstChild(), "must have a child frame");
   SVGBBox bbox;
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (kid && NS_SUBTREE_DIRTY(kid)) {
     // Return an empty bbox if our kid's subtree is dirty. This may be called
     // in that situation, e.g. when we're building a display list after an
     // interrupted reflow. This can also be called during reflow before we've
     // been reflowed, e.g. if an earlier sibling is calling FinishAndStoreOverflow and
     // needs our parent's perspective matrix, which depends on the SVG bbox
     // contribution of this frame. In the latter situation, when all siblings have
     // been reflowed, the parent will compute its perspective and rerun
@@ -4832,17 +4830,17 @@ ShiftAnchoredChunk(nsTArray<mozilla::Cha
       }
     }
   }
 }
 
 void
 SVGTextFrame::AdjustChunksForLineBreaks()
 {
-  nsBlockFrame* block = nsLayoutUtils::GetAsBlock(GetFirstPrincipalChild());
+  nsBlockFrame* block = nsLayoutUtils::GetAsBlock(PrincipalChildList().FirstChild());
   NS_ASSERTION(block, "expected block frame");
 
   nsBlockFrame::line_iterator line = block->begin_lines();
 
   CharIterator it(this, CharIterator::eOriginal);
   while (!it.AtEnd() && line != block->end_lines()) {
     if (it.TextFrame() == line->mFirstChild) {
       mPositions[it.TextElementCharIndex()].mStartOfChunk = true;
@@ -5123,17 +5121,17 @@ SVGTextFrame::DoAnchoring()
 }
 
 void
 SVGTextFrame::DoGlyphPositioning()
 {
   mPositions.Clear();
   RemoveStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (kid && NS_SUBTREE_DIRTY(kid)) {
     MOZ_ASSERT(false, "should have already reflowed the kid");
     return;
   }
 
   // Determine the positions of each character in app units.
   nsTArray<nsPoint> charPositions;
   DetermineCharPositions(charPositions);
@@ -5192,18 +5190,18 @@ SVGTextFrame::DoGlyphPositioning()
     AppUnitsToFloatCSSPixels(presContext->AppUnitsPerDevPixel());
   double factor = cssPxPerDevPx / mFontSizeScaleFactor;
 
   // Determine how much to compress or expand glyph positions due to
   // textLength="" and lengthAdjust="".
   double adjustment = 0.0;
   mLengthAdjustScaleFactor = 1.0f;
   if (adjustingTextLength) {
-    nscoord frameLength = vertical ? GetFirstPrincipalChild()->GetRect().height
-                                   : GetFirstPrincipalChild()->GetRect().width;
+    nscoord frameLength = vertical ? PrincipalChildList().FirstChild()->GetRect().height
+                                   : PrincipalChildList().FirstChild()->GetRect().width;
     float actualTextLength =
       static_cast<float>(presContext->AppUnitsToGfxUnits(frameLength) * factor);
 
     RefPtr<SVGAnimatedEnumeration> lengthAdjustEnum = element->LengthAdjust();
     uint16_t lengthAdjust = lengthAdjustEnum->AnimVal();
     switch (lengthAdjust) {
       case SVG_LENGTHADJUST_SPACINGANDGLYPHS:
         // Scale the glyphs and their positions.
@@ -5325,30 +5323,30 @@ SVGTextFrame::NotifyGlyphMetricsChange()
     mContent->AsElement(), nsRestyleHint(0),
     nsChangeHint_InvalidateRenderingObservers);
   ScheduleReflowSVG();
 }
 
 void
 SVGTextFrame::UpdateGlyphPositioning()
 {
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid) {
     return;
   }
 
   if (mState & NS_STATE_SVG_POSITIONING_DIRTY) {
     DoGlyphPositioning();
   }
 }
 
 void
 SVGTextFrame::MaybeReflowAnonymousBlockChild()
 {
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return;
 
   NS_ASSERTION(!(kid->GetStateBits() & NS_FRAME_IN_REFLOW),
                "should not be in reflow when about to reflow again");
 
   if (NS_SUBTREE_DIRTY(this)) {
     if (mState & NS_FRAME_IS_DIRTY) {
@@ -5381,17 +5379,17 @@ SVGTextFrame::DoReflow()
     // our descendants invalidate as they reflow, which invalidates rendering
     // observers, which reschedules the frame that is currently painting by
     // referencing us to paint again. See bug 839958 comment 7. Hopefully we
     // will break that loop more convincingly at some point.
     mState &= ~(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
   }
 
   nsPresContext *presContext = PresContext();
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return;
 
   nsRenderingContext renderingContext(
     presContext->PresShell()->CreateReferenceRenderingContext());
 
   if (UpdateFontSizeScaleFactor()) {
     // If the font size scale factor changed, we need the block to report
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -286,17 +286,17 @@ public:
                     nsIFrame*         aPrevInFlow) override;
 
   virtual nsresult AttributeChanged(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override
   {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   /**
    * Get the "type" of the frame
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -335,18 +335,17 @@ nsSVGClipPathFrame::IsValid()
   }
 
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
 
     nsIAtom *type = kid->GetType();
 
     if (type == nsGkAtoms::svgUseFrame) {
-      for (nsIFrame* grandKid = kid->GetFirstPrincipalChild(); grandKid;
-           grandKid = grandKid->GetNextSibling()) {
+      for (nsIFrame* grandKid : kid->PrincipalChildList()) {
 
         nsIAtom *type = grandKid->GetType();
 
         if (type != nsGkAtoms::svgPathGeometryFrame &&
             type != nsGkAtoms::svgTextFrame) {
           return false;
         }
       }
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -107,18 +107,17 @@ nsSVGContainerFrame::UpdateOverflow()
 nsSVGContainerFrame::ReflowSVGNonDisplayText(nsIFrame* aContainer)
 {
   NS_ASSERTION(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY,
                "expected aContainer to be NS_FRAME_IS_DIRTY");
   NS_ASSERTION((aContainer->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
                !aContainer->IsFrameOfType(nsIFrame::eSVG),
                "it is wasteful to call ReflowSVGNonDisplayText on a container "
                "frame that is not NS_FRAME_IS_NONDISPLAY");
-  for (nsIFrame* kid = aContainer->GetFirstPrincipalChild(); kid;
-       kid = kid->GetNextSibling()) {
+  for (nsIFrame* kid : aContainer->PrincipalChildList()) {
     nsIAtom* type = kid->GetType();
     if (type == nsGkAtoms::svgTextFrame) {
       static_cast<SVGTextFrame*>(kid)->ReflowSVGNonDisplayText();
     } else {
       if (kid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
           type == nsGkAtoms::svgForeignObjectFrame ||
           !kid->IsFrameOfType(nsIFrame::eSVG)) {
         ReflowSVGNonDisplayText(kid);
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -206,17 +206,17 @@ nsSVGForeignObjectFrame::PaintSVG(gfxCon
   NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only painting of non-display "
                "SVG should take this code path");
 
   if (IsDisabled())
     return NS_OK;
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return NS_OK;
 
   if (aTransform.IsSingular()) {
     NS_WARNING("Can't render foreignObject element!");
     return NS_ERROR_FAILURE;
   }
 
@@ -289,17 +289,17 @@ nsSVGForeignObjectFrame::GetFrameForPoin
   NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
                (mState & NS_FRAME_IS_NONDISPLAY),
                "If display lists are enabled, only hit-testing of a "
                "clipPath's contents should take this code path");
 
   if (IsDisabled() || (GetStateBits() & NS_FRAME_IS_NONDISPLAY))
     return nullptr;
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return nullptr;
 
   float x, y, width, height;
   static_cast<nsSVGElement*>(mContent)->
     GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
 
   if (!gfxRect(x, y, width, height).Contains(aPoint) ||
@@ -355,17 +355,17 @@ nsSVGForeignObjectFrame::ReflowSVG()
   if (h < 0.0f) h = 0.0f;
 
   mRect = nsLayoutUtils::RoundGfxRectToAppRect(
                            gfxRect(x, y, w, h),
                            PresContext()->AppUnitsPerCSSPixel());
 
   // Fully mark our kid dirty so that it gets resized if necessary
   // (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case):
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   kid->AddStateBits(NS_FRAME_IS_DIRTY);
 
   // Make sure to not allow interrupts if we're not being reflown as a root:
   nsPresContext::InterruptPreventer noInterrupts(PresContext());
 
   DoReflow();
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
@@ -505,34 +505,34 @@ nsSVGForeignObjectFrame::GetCanvasTM()
 // Implementation helpers
 
 void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType)
 {
   if (GetStateBits() & NS_FRAME_FIRST_REFLOW)
     // If we haven't had a ReflowSVG() yet, nothing to do.
     return;
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return;
 
   PresContext()->PresShell()->FrameNeedsReflow(kid, aType, NS_FRAME_IS_DIRTY);
 }
 
 void
 nsSVGForeignObjectFrame::DoReflow()
 {
   MarkInReflow();
   // Skip reflow if we're zero-sized, unless this is our first reflow.
   if (IsDisabled() &&
       !(GetStateBits() & NS_FRAME_FIRST_REFLOW))
     return;
 
   nsPresContext *presContext = PresContext();
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (!kid)
     return;
 
   // initiate a synchronous reflow here and now:  
   nsRenderingContext renderingContext(
     presContext->PresShell()->CreateReferenceRenderingContext());
 
   mInReflow = true;
@@ -566,17 +566,17 @@ nsSVGForeignObjectFrame::DoReflow()
 }
 
 nsRect
 nsSVGForeignObjectFrame::GetInvalidRegion()
 {
   MOZ_ASSERT(!NS_SVGDisplayListPaintingEnabled(),
              "Only called by nsDisplayOuterSVG code");
 
-  nsIFrame* kid = GetFirstPrincipalChild();
+  nsIFrame* kid = PrincipalChildList().FirstChild();
   if (kid->HasInvalidFrameInSubtree()) {
     gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height);
     r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
     nsRect rect = nsSVGUtils::ToCanvasBounds(r, GetCanvasTM(), PresContext());
     rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
     return rect;
   }
   return nsRect();
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -34,17 +34,17 @@ public:
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       nsHTMLReflowMetrics&     aDesiredSize,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
--- a/layout/svg/nsSVGMarkerFrame.cpp
+++ b/layout/svg/nsSVGMarkerFrame.cpp
@@ -90,17 +90,17 @@ nsSVGMarkerFrame::GetCanvasTM()
   Matrix viewBoxTM = content->GetViewBoxTransform();
 
   return ThebesMatrix(viewBoxTM * markerTM) * markedTM;
 }
 
 static nsIFrame*
 GetAnonymousChildFrame(nsIFrame* aFrame)
 {
-  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
+  nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   MOZ_ASSERT(kid && kid->GetType() == nsGkAtoms::svgMarkerAnonChildFrame,
              "expected to find anonymous child of marker frame");
   return kid;
 }
 
 nsresult
 nsSVGMarkerFrame::PaintMark(gfxContext& aContext,
                             const gfxMatrix& aToMarkedFrameUserSpace,
--- a/layout/svg/nsSVGMarkerFrame.h
+++ b/layout/svg/nsSVGMarkerFrame.h
@@ -71,21 +71,21 @@ public:
   virtual nsresult GetFrameName(nsAString& aResult) const override
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGMarker"), aResult);
   }
 #endif
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     // Any children must be added to our single anonymous inner frame kid.
-    MOZ_ASSERT(GetFirstPrincipalChild() &&
-               GetFirstPrincipalChild()->GetType() ==
+    MOZ_ASSERT(PrincipalChildList().FirstChild() &&
+               PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgMarkerAnonChildFrame,
                "Where is our anonymous child?");
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   // nsSVGMarkerFrame methods:
   nsresult PaintMark(gfxContext& aContext,
                      const gfxMatrix& aToMarkedFrameUserSpace,
                      nsSVGPathGeometryFrame *aMarkedFrame,
                      nsSVGMark *aMark,
                      float aStrokeWidth);
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -379,17 +379,17 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext
   aDesiredSize.Height() = aReflowState.ComputedHeight() +
                           aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   NS_ASSERTION(!GetPrevInFlow(), "SVG can't currently be broken across pages.");
 
   SVGSVGElement *svgElem = static_cast<SVGSVGElement*>(mContent);
 
   nsSVGOuterSVGAnonChildFrame *anonKid =
-    static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
+    static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
     // Initialize
     svgElem->UpdateHasChildrenOnlyTransform();
   }
 
   // If our SVG viewport has changed, update our content and notify.
   // http://www.w3.org/TR/SVG11/coords.html#ViewportSpace
@@ -418,20 +418,19 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext
     // In the latter case, updating of overflow rects is handled for removal of
     // real viewBox (the viewBox attribute) in AttributeChanged. Synthetic
     // viewBox "removal" (e.g. a document references the same SVG via both an
     // <svg:image> and then as a CSS background image (a synthetic viewBox is
     // used when painting the former, but not when painting the latter)) is
     // handled in SVGSVGElement::FlushImageTransformInvalidation.
     //
     if (svgElem->HasViewBoxOrSyntheticViewBox()) {
-      nsIFrame* anonChild = GetFirstPrincipalChild();
+      nsIFrame* anonChild = PrincipalChildList().FirstChild();
       anonChild->AddStateBits(NS_FRAME_IS_DIRTY);
-      for (nsIFrame* child = anonChild->GetFirstPrincipalChild(); child;
-           child = child->GetNextSibling()) {
+      for (nsIFrame* child : anonChild->PrincipalChildList()) {
         child->AddStateBits(NS_FRAME_IS_DIRTY);
       }
     }
     changeBits |= COORD_CONTEXT_CHANGED;
     svgElem->SetViewportSize(newViewportSize);
   }
   if (mFullZoom != PresContext()->GetFullZoom()) {
     changeBits |= FULL_ZOOM_CHANGED;
@@ -523,17 +522,17 @@ nsSVGOuterSVGFrame::UpdateOverflow()
   // See the comments in Reflow above.
 
   // WARNING!! Keep this in sync with Reflow above!
 
   nsRect rect(nsPoint(0, 0), GetSize());
   nsOverflowAreas overflowAreas(rect, rect);
 
   if (!mIsRootContent) {
-    nsIFrame *anonKid = GetFirstPrincipalChild();
+    nsIFrame *anonKid = PrincipalChildList().FirstChild();
     overflowAreas.VisualOverflow().UnionRect(
       overflowAreas.VisualOverflow(),
       anonKid->GetVisualOverflowRect() + anonKid->GetPosition());
   }
 
   return FinishAndStoreOverflow(overflowAreas, GetSize());
 }
 
@@ -584,17 +583,17 @@ nsDisplayOuterSVG::HitTest(nsDisplayList
       refFrameToContentBox;
 
   gfxPoint svgViewportRelativePoint =
     gfxPoint(pointRelativeToContentBox.x, pointRelativeToContentBox.y) /
       outerSVGFrame->PresContext()->AppUnitsPerCSSPixel();
 
   nsSVGOuterSVGAnonChildFrame *anonKid =
     static_cast<nsSVGOuterSVGAnonChildFrame*>(
-      outerSVGFrame->GetFirstPrincipalChild());
+      outerSVGFrame->PrincipalChildList().FirstChild());
 
   nsIFrame* frame =
     nsSVGUtils::HitTestChildren(anonKid, svgViewportRelativePoint);
   if (frame) {
     aOutFrames->AppendElement(frame);
   }
 }
 
@@ -678,17 +677,17 @@ nsSVGOuterSVGFrame::AttributeChanged(int
       !(GetStateBits() & (NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_NONDISPLAY))) {
     if (aAttribute == nsGkAtoms::viewBox ||
         aAttribute == nsGkAtoms::preserveAspectRatio ||
         aAttribute == nsGkAtoms::transform) {
 
       // make sure our cached transform matrix gets (lazily) updated
       mCanvasTM = nullptr;
 
-      nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(),
+      nsSVGUtils::NotifyChildrenOfSVGChange(PrincipalChildList().FirstChild(),
                 aAttribute == nsGkAtoms::viewBox ?
                   TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED : TRANSFORM_CHANGED);
 
       if (aAttribute != nsGkAtoms::transform) {
         static_cast<SVGSVGElement*>(mContent)->ChildrenOnlyTransformChanged();
       }
 
     } else if (aAttribute == nsGkAtoms::width ||
@@ -820,48 +819,48 @@ nsSVGOuterSVGFrame::NotifyViewportOrTran
     if (haveNonFulLZoomTransformChange &&
         !(mState & NS_FRAME_IS_NONDISPLAY)) {
       uint32_t flags = (mState & NS_FRAME_IN_REFLOW) ?
                          SVGSVGElement::eDuringReflow : 0;
       content->ChildrenOnlyTransformChanged(flags);
     }
   }
 
-  nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(), aFlags);
+  nsSVGUtils::NotifyChildrenOfSVGChange(PrincipalChildList().FirstChild(), aFlags);
 }
 
 //----------------------------------------------------------------------
 // nsISVGChildFrame methods:
 
 nsresult
 nsSVGOuterSVGFrame::PaintSVG(gfxContext& aContext,
                              const gfxMatrix& aTransform,
                              const nsIntRect* aDirtyRect)
 {
-  NS_ASSERTION(GetFirstPrincipalChild()->GetType() ==
+  NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgOuterSVGAnonChildFrame &&
-               !GetFirstPrincipalChild()->GetNextSibling(),
+               !PrincipalChildList().FirstChild()->GetNextSibling(),
                "We should have a single, anonymous, child");
   nsSVGOuterSVGAnonChildFrame *anonKid =
-    static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
+    static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
   return anonKid->PaintSVG(aContext, aTransform, aDirtyRect);
 }
 
 SVGBBox
 nsSVGOuterSVGFrame::GetBBoxContribution(const gfx::Matrix &aToBBoxUserspace,
                                         uint32_t aFlags)
 {
-  NS_ASSERTION(GetFirstPrincipalChild()->GetType() ==
+  NS_ASSERTION(PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgOuterSVGAnonChildFrame &&
-               !GetFirstPrincipalChild()->GetNextSibling(),
+               !PrincipalChildList().FirstChild()->GetNextSibling(),
                "We should have a single, anonymous, child");
   // We must defer to our child so that we don't include our
   // content->PrependLocalTransformsTo() transforms.
   nsSVGOuterSVGAnonChildFrame *anonKid =
-    static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
+    static_cast<nsSVGOuterSVGAnonChildFrame*>(PrincipalChildList().FirstChild());
   return anonKid->GetBBoxContribution(aToBBoxUserspace, aFlags);
 }
 
 //----------------------------------------------------------------------
 // nsSVGContainerFrame methods:
 
 gfxMatrix
 nsSVGOuterSVGFrame::GetCanvasTM()
--- a/layout/svg/nsSVGOuterSVGFrame.h
+++ b/layout/svg/nsSVGOuterSVGFrame.h
@@ -91,29 +91,29 @@ public:
 #endif
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     // Any children must be added to our single anonymous inner frame kid.
-    MOZ_ASSERT(GetFirstPrincipalChild() &&
-               GetFirstPrincipalChild()->GetType() ==
+    MOZ_ASSERT(PrincipalChildList().FirstChild() &&
+               PrincipalChildList().FirstChild()->GetType() ==
                  nsGkAtoms::svgOuterSVGAnonChildFrame,
                "Where is our anonymous child?");
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual bool IsSVGTransformed(Matrix *aOwnTransform,
                                 Matrix *aFromParentTransform) const override {
     // Our anonymous wrapper performs the transforms. We simply
     // return whether we are transformed here but don't apply the transforms
     // themselves.
-    return GetFirstPrincipalChild()->IsSVGTransformed();
+    return PrincipalChildList().FirstChild()->IsSVGTransformed();
   }
 
   // nsISVGSVGFrame interface:
   virtual void NotifyViewportOrTransformChanged(uint32_t aFlags) override;
 
   // nsISVGChildFrame methods:
   virtual nsresult PaintSVG(gfxContext& aContext,
                             const gfxMatrix& aTransform,
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -427,32 +427,29 @@ nsSVGUtils::GetUserToCanvasTM(nsIFrame *
                     eUserSpaceToParent);
   }
   return tm;
 }
 
 void 
 nsSVGUtils::NotifyChildrenOfSVGChange(nsIFrame *aFrame, uint32_t aFlags)
 {
-  nsIFrame *kid = aFrame->GetFirstPrincipalChild();
-
-  while (kid) {
+  for (nsIFrame* kid : aFrame->PrincipalChildList()) {
     nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
     if (SVGFrame) {
       SVGFrame->NotifySVGChanged(aFlags); 
     } else {
       NS_ASSERTION(kid->IsFrameOfType(nsIFrame::eSVG) || kid->IsSVGText(),
                    "SVG frame expected");
       // recurse into the children of container frames e.g. <clipPath>, <mask>
       // in case they have child frames with transformation matrices
       if (kid->IsFrameOfType(nsIFrame::eSVG)) {
         NotifyChildrenOfSVGChange(kid, aFlags);
       }
     }
-    kid = kid->GetNextSibling();
   }
 }
 
 // ************************************************************
 
 class SVGPaintCallback : public nsSVGFilterPaintCallback
 {
 public:
--- a/layout/tables/nsCellMap.cpp
+++ b/layout/tables/nsCellMap.cpp
@@ -1564,27 +1564,25 @@ nsCellMap::AppendCell(nsTableCellMap&   
   return origData;
 }
 
 bool nsCellMap::CellsSpanOut(nsTArray<nsTableRowFrame*>& aRows) const
 {
   int32_t numNewRows = aRows.Length();
   for (int32_t rowX = 0; rowX < numNewRows; rowX++) {
     nsIFrame* rowFrame = (nsIFrame *) aRows.ElementAt(rowX);
-    nsIFrame* childFrame = rowFrame->GetFirstPrincipalChild();
-    while (childFrame) {
+    for (nsIFrame* childFrame : rowFrame->PrincipalChildList()) {
       nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
       if (cellFrame) {
         bool zeroSpan;
         int32_t rowSpan = GetRowSpanForNewCell(cellFrame, rowX, zeroSpan);
         if (zeroSpan || rowX + rowSpan > numNewRows) {
           return true;
         }
       }
-      childFrame = childFrame->GetNextSibling();
     }
   }
   return false;
 }
 
 // return true if any cells have rows spans into or out of the region
 // defined by the row and col indices or any cells have colspans into the region
 bool nsCellMap::CellsSpanInOrOut(int32_t aStartRowIndex,
@@ -1736,25 +1734,23 @@ nsCellMap::ExpandWithRows(nsTableCellMap
     return;
   }
 
 
   int32_t newRowIndex = 0;
   for (int32_t rowX = startRowIndex; rowX <= endRowIndex; rowX++) {
     nsTableRowFrame* rFrame = aRowFrames.ElementAt(newRowIndex);
     // append cells
-    nsIFrame* cFrame = rFrame->GetFirstPrincipalChild();
     int32_t colIndex = 0;
-    while (cFrame) {
+    for (nsIFrame* cFrame : rFrame->PrincipalChildList()) {
       nsTableCellFrame *cellFrame = do_QueryFrame(cFrame);
       if (cellFrame) {
         AppendCell(aMap, cellFrame, rowX, false, aRgFirstRowIndex, aDamageArea,
                    &colIndex);
       }
-      cFrame = cFrame->GetNextSibling();
     }
     newRowIndex++;
   }
   // mark all following rows damaged, they might contain a previously set
   // damage area which we can not shift.
   int32_t firstDamagedRow = aRgFirstRowIndex + startRowIndex;
   SetDamageArea(0, firstDamagedRow, aMap.GetColCount(),
                 aMap.GetRowCount() - firstDamagedRow, aDamageArea);
@@ -2181,23 +2177,21 @@ nsCellMap::RebuildConsideringRows(nsTabl
   // Now handle the new rows being inserted, if any.
   uint32_t copyStartRowIndex;
   rowX = aStartRowIndex;
   if (aRowsToInsert) {
     // add in the new cells and create rows if necessary
     int32_t numNewRows = aRowsToInsert->Length();
     for (int32_t newRowX = 0; newRowX < numNewRows; newRowX++) {
       nsTableRowFrame* rFrame = aRowsToInsert->ElementAt(newRowX);
-      nsIFrame* cFrame = rFrame->GetFirstPrincipalChild();
-      while (cFrame) {
+      for (nsIFrame* cFrame : rFrame->PrincipalChildList()) {
         nsTableCellFrame *cellFrame = do_QueryFrame(cFrame);
         if (cellFrame) {
           AppendCell(aMap, cellFrame, rowX, false, 0, damageArea);
         }
-        cFrame = cFrame->GetNextSibling();
       }
       rowX++;
     }
     copyStartRowIndex = aStartRowIndex;
   }
   else {
     copyStartRowIndex = aStartRowIndex + aNumRowsToRemove;
   }
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -694,34 +694,32 @@ nsTableCellFrame::CellHasVisibleContent(
                                         nsTableFrame* tableFrame,
                                         nsIFrame*     kidFrame)
 {
   // see  http://www.w3.org/TR/CSS21/tables.html#empty-cells
   if (height > 0)
     return true;
   if (tableFrame->IsBorderCollapse())
     return true;
-  nsIFrame* innerFrame = kidFrame->GetFirstPrincipalChild();
-  while(innerFrame) {
+  for (nsIFrame* innerFrame : kidFrame->PrincipalChildList()) {
     nsIAtom* frameType = innerFrame->GetType();
     if (nsGkAtoms::textFrame == frameType) {
        nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
        if (textFrame->HasNoncollapsedCharacters())
          return true;
     }
     else if (nsGkAtoms::placeholderFrame != frameType) {
       return true;
     }
     else {
       nsIFrame *floatFrame = nsLayoutUtils::GetFloatFromPlaceholder(innerFrame);
       if (floatFrame)
         return true;
     }
-    innerFrame = innerFrame->GetNextSibling();
-  }	
+  }
   return false;
 }
 
 nscoord
 nsTableCellFrame::GetCellBaseline() const
 {
   // Ignore the position of the inner frame relative to the cell frame
   // since we want the position as though the inner were top-aligned.
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -89,17 +89,17 @@ public:
   virtual void InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList) override;
   virtual void RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame) override;
 #endif
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
   virtual nsMargin GetUsedMargin() const override;
 
   virtual void NotifyPercentBSize(const nsHTMLReflowState& aReflowState) override;
 
   virtual bool NeedsToObserve(const nsHTMLReflowState& aReflowState) override;
 
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -49,17 +49,17 @@ void nsTableColGroupFrame::ResetColIndic
       // aFirstColIndex is smaller than the existing starting col index
       if ((colIndex != aFirstColIndex) ||
           (colIndex < colGroupFrame->GetStartColumnIndex()) ||
           !aStartColFrame) {
         colGroupFrame->SetStartColumnIndex(colIndex);
       }
       nsIFrame* colFrame = aStartColFrame; 
       if (!colFrame || (colIndex != aFirstColIndex)) {
-        colFrame = colGroupFrame->GetFirstPrincipalChild();
+        colFrame = colGroupFrame->PrincipalChildList().FirstChild();
       }
       while (colFrame) {
         if (nsGkAtoms::tableColFrame == colFrame->GetType()) {
           ((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
           colIndex++;
         }
         colFrame = colFrame->GetNextSibling();
       }
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -983,21 +983,19 @@ nsTableFrame::RemoveRows(nsTableRowFrame
 
 // collect the rows ancestors of aFrame
 int32_t
 nsTableFrame::CollectRows(nsIFrame*                   aFrame,
                           nsTArray<nsTableRowFrame*>& aCollection)
 {
   NS_PRECONDITION(aFrame, "null frame");
   int32_t numRows = 0;
-  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
-  while (childFrame) {
+  for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
     aCollection.AppendElement(static_cast<nsTableRowFrame*>(childFrame));
     numRows++;
-    childFrame = childFrame->GetNextSibling();
   }
   return numRows;
 }
 
 void
 nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
 {
 #ifdef DEBUG_TABLE_CELLMAP
@@ -1201,20 +1199,18 @@ nsTableFrame::GenericTraversal(nsDisplay
   // This is similar to what nsContainerFrame::BuildDisplayListForNonBlockChildren
   // does, except that we allow the children's background and borders to go
   // in our BorderBackground list. This doesn't really affect background
   // painting --- the children won't actually draw their own backgrounds
   // because the nsTableFrame already drew them, unless a child has its own
   // stacking context, in which case the child won't use its passed-in
   // BorderBackground list anyway. It does affect cell borders though; this
   // lets us get cell borders into the nsTableFrame's BorderBackground list.
-  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
-  while (kid) {
+  for (nsIFrame* kid : aFrame->PrincipalChildList()) {
     aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
-    kid = kid->GetNextSibling();
   }
 }
 
 /* static */ void
 nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
                                       nsFrame* aFrame,
                                       const nsRect& aDirtyRect,
                                       const nsDisplayListSet& aLists,
@@ -1499,31 +1495,29 @@ nsTableFrame::ProcessRowInserted(nscoord
 {
   SetRowInserted(false); // reset the bit that got us here
   nsTableFrame::RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
   // find the row group containing the inserted row
   for (uint32_t rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgIdx];
     NS_ASSERTION(rgFrame, "Must have rgFrame here");
-    nsIFrame* childFrame = rgFrame->GetFirstPrincipalChild();
     // find the row that was inserted first
-    while (childFrame) {
+    for (nsIFrame* childFrame : rgFrame->PrincipalChildList()) {
       nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
       if (rowFrame) {
         if (rowFrame->IsFirstInserted()) {
           rowFrame->SetFirstInserted(false);
           // damage the table from the 1st row inserted to the end of the table
           nsIFrame::InvalidateFrame();
           // XXXbz didn't we do this up front?  Why do we need to do it again?
           SetRowInserted(false);
           return; // found it, so leave
         }
       }
-      childFrame = childFrame->GetNextSibling();
     }
   }
 }
 
 /* virtual */ void
 nsTableFrame::MarkIntrinsicISizesDirty()
 {
   nsITableLayoutStrategy* tls = LayoutStrategy();
@@ -2434,17 +2428,17 @@ nsTableFrame::HomogenousInsertFrames(Chi
       // XXXbz Using content indices here means XBL will get screwed
       // over...  Oh, well.
       nsIFrame* pseudoFrame = aFrameList.FirstChild();
       nsIContent* parentContent = GetContent();
       nsIContent* content;
       aPrevFrame = nullptr;
       while (pseudoFrame  && (parentContent ==
                               (content = pseudoFrame->GetContent()))) {
-        pseudoFrame = pseudoFrame->GetFirstPrincipalChild();
+        pseudoFrame = pseudoFrame->PrincipalChildList().FirstChild();
       }
       nsCOMPtr<nsIContent> container = content->GetParent();
       if (MOZ_LIKELY(container)) { // XXX need this null-check, see bug 411823.
         int32_t newIndex = container->IndexOf(content);
         nsIFrame* kidFrame;
         nsTableColGroupFrame* lastColGroup;
         if (isColGroup) {
           kidFrame = mColGroups.FirstChild();
@@ -2460,17 +2454,17 @@ nsTableFrame::HomogenousInsertFrames(Chi
             if (kidFrame == lastColGroup) {
               aPrevFrame = kidFrame; // there is no real colgroup after this one
               break;
             }
           }
           pseudoFrame = kidFrame;
           while (pseudoFrame  && (parentContent ==
                                   (content = pseudoFrame->GetContent()))) {
-            pseudoFrame = pseudoFrame->GetFirstPrincipalChild();
+            pseudoFrame = pseudoFrame->PrincipalChildList().FirstChild();
           }
           int32_t index = container->IndexOf(content);
           if (index > lastIndex && index < newIndex) {
             lastIndex = index;
             aPrevFrame = kidFrame;
           }
           kidFrame = kidFrame->GetNextSibling();
         }
@@ -3918,55 +3912,51 @@ nsTableFrame::GetFrameAtOrBefore(nsIFram
   }
   if (aChildType == aPriorChildFrame->GetType()) {
     return aPriorChildFrame;
   }
 
   // aPriorChildFrame is not of type aChildType, so we need start from
   // the beginnng and find the closest one
   nsIFrame* lastMatchingFrame = nullptr;
-  nsIFrame* childFrame = aParentFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = aParentFrame->PrincipalChildList().FirstChild();
   while (childFrame && (childFrame != aPriorChildFrame)) {
     if (aChildType == childFrame->GetType()) {
       lastMatchingFrame = childFrame;
     }
     childFrame = childFrame->GetNextSibling();
   }
   return lastMatchingFrame;
 }
 
 #ifdef DEBUG
 void
 nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
 {
   if (!aKidFrame)
     return;
 
-  nsIFrame* cFrame = aKidFrame->GetFirstPrincipalChild();
-  while (cFrame) {
+  for (nsIFrame* cFrame : aKidFrame->PrincipalChildList()) {
     nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
     if (rowFrame) {
       printf("row(%d)=%p ", rowFrame->GetRowIndex(),
              static_cast<void*>(rowFrame));
-      nsIFrame* childFrame = cFrame->GetFirstPrincipalChild();
-      while (childFrame) {
+      for (nsIFrame* childFrame : cFrame->PrincipalChildList()) {
         nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
         if (cellFrame) {
           int32_t colIndex;
           cellFrame->GetColIndex(colIndex);
           printf("cell(%d)=%p ", colIndex, static_cast<void*>(childFrame));
         }
-        childFrame = childFrame->GetNextSibling();
       }
       printf("\n");
     }
     else {
       DumpRowGroup(rowFrame);
     }
-    cFrame = cFrame->GetNextSibling();
   }
 }
 
 void
 nsTableFrame::Dump(bool            aDumpRows,
                    bool            aDumpCols,
                    bool            aDumpCellMap)
 {
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -46,17 +46,17 @@ public:
                             nsFrameList&    aFrameList) override;
   virtual void InsertFrames(ChildListID     aListID,
                             nsIFrame*       aPrevFrame,
                             nsFrameList&    aFrameList) override;
   virtual void RemoveFrame(ChildListID     aListID,
                            nsIFrame*       aOldFrame) override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override {
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -430,17 +430,17 @@ nscoord nsTableRowFrame::GetRowBaseline(
   // bp              pb
   // bppppppppppppppppb
   // bbbbbbbbbbbbbbbbbb
 
   nscoord ascent = 0;
   nsSize containerSize = GetSize();
   for (nsIFrame* childFrame : mFrames) {
     if (IS_TABLE_CELL(childFrame->GetType())) {
-      nsIFrame* firstKid = childFrame->GetFirstPrincipalChild();
+      nsIFrame* firstKid = childFrame->PrincipalChildList().FirstChild();
       ascent = std::max(ascent,
                         LogicalRect(aWM, firstKid->GetNormalRect(),
                                     containerSize).BEnd(aWM));
     }
   }
   return ascent;
 }
 
@@ -541,17 +541,17 @@ nsTableRowFrame::CalcBSize(const nsHTMLR
     if (cellFrame) {
       MOZ_ASSERT(cellFrame->GetWritingMode() == wm);
       LogicalSize desSize = cellFrame->GetDesiredSize();
       if ((NS_UNCONSTRAINEDSIZE == aReflowState.AvailableBSize()) && !GetPrevInFlow()) {
         CalculateCellActualBSize(cellFrame, desSize.BSize(wm), wm);
       }
       // bsize may have changed, adjust descent to absorb any excess difference
       nscoord ascent;
-       if (!kidFrame->GetFirstPrincipalChild()->GetFirstPrincipalChild())
+       if (!kidFrame->PrincipalChildList().FirstChild()->PrincipalChildList().FirstChild())
          ascent = desSize.BSize(wm);
        else
          ascent = cellFrame->GetCellBaseline();
        nscoord descent = desSize.BSize(wm) - ascent;
        UpdateBSize(desSize.BSize(wm), ascent, descent, tableFrame, cellFrame);
     }
   }
   return GetInitialBSize();
@@ -956,17 +956,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
       if (NS_UNCONSTRAINEDSIZE == aReflowState.AvailableBSize()) {
         if (!GetPrevInFlow()) {
           // Calculate the cell's actual bsize given its pass2 bsize. This
           // function takes into account the specified bsize (in the style)
           CalculateCellActualBSize(cellFrame, desiredSize.BSize(wm), wm);
         }
         // bsize may have changed, adjust descent to absorb any excess difference
         nscoord ascent;
-        if (!kidFrame->GetFirstPrincipalChild()->GetFirstPrincipalChild()) {
+        if (!kidFrame->PrincipalChildList().FirstChild()->PrincipalChildList().FirstChild()) {
           ascent = desiredSize.BSize(wm);
         } else {
           ascent = ((nsTableCellFrame *)kidFrame)->GetCellBaseline();
         }
         nscoord descent = desiredSize.BSize(wm) - ascent;
         UpdateBSize(desiredSize.BSize(wm), ascent, descent, &aTableFrame, cellFrame);
       } else {
         cellMaxBSize = std::max(cellMaxBSize, desiredSize.BSize(wm));
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -192,17 +192,17 @@ DisplayRows(nsDisplayListBuilder* aBuild
       f->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
       kid = kid->GetNextSibling();
     }
     return;
   }
 
   // No cursor. Traverse children the hard way and build a cursor while we're at it
   nsTableRowGroupFrame::FrameCursorData* cursor = f->SetupRowCursor();
-  kid = f->GetFirstPrincipalChild();
+  kid = f->PrincipalChildList().FirstChild();
   while (kid) {
     f->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
 
     if (cursor) {
       if (!cursor->AppendFrame(kid)) {
         f->ClearRowCursor();
         return;
       }
@@ -1360,17 +1360,17 @@ nsTableRowGroupFrame::Reflow(nsPresConte
                   splitDueToPageBreak);
 
     ((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialBSizeReflow = specialReflow;
   }
 
   // XXXmats The following is just bogus.  We leave it here for now because
   // ReflowChildren should pull up rows from our next-in-flow before returning
   // a Complete status, but doesn't (bug 804888).
-  if (GetNextInFlow() && GetNextInFlow()->GetFirstPrincipalChild()) {
+  if (GetNextInFlow() && GetNextInFlow()->PrincipalChildList().FirstChild()) {
     NS_FRAME_SET_INCOMPLETE(aStatus);
   }
 
   SetHasStyleBSize((NS_UNCONSTRAINEDSIZE != aReflowState.ComputedBSize()) &&
                     (aReflowState.ComputedBSize() > 0));
 
   // Just set our isize to what was available.
   // The table will calculate the isize and not use our value.
--- a/layout/xul/BoxObject.cpp
+++ b/layout/xul/BoxObject.cpp
@@ -377,17 +377,17 @@ BoxObject::GetParentBox(nsIDOMElement * 
 }
 
 NS_IMETHODIMP
 BoxObject::GetFirstChild(nsIDOMElement * *aFirstVisibleChild)
 {
   *aFirstVisibleChild = nullptr;
   nsIFrame* frame = GetFrame(false);
   if (!frame) return NS_OK;
-  nsIFrame* firstFrame = frame->GetFirstPrincipalChild();
+  nsIFrame* firstFrame = frame->PrincipalChildList().FirstChild();
   if (!firstFrame) return NS_OK;
   // get the content for the box and query to a dom element
   nsCOMPtr<nsIDOMElement> el = do_QueryInterface(firstFrame->GetContent());
   el.swap(*aFirstVisibleChild);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -424,17 +424,17 @@ BoxObject::GetPreviousSibling(nsIDOMElem
   return GetPreviousSibling(parentFrame, frame, aPreviousOrdinalSibling);
 }
 
 nsresult
 BoxObject::GetPreviousSibling(nsIFrame* aParentFrame, nsIFrame* aFrame,
                               nsIDOMElement** aResult)
 {
   *aResult = nullptr;
-  nsIFrame* nextFrame = aParentFrame->GetFirstPrincipalChild();
+  nsIFrame* nextFrame = aParentFrame->PrincipalChildList().FirstChild();
   nsIFrame* prevFrame = nullptr;
   while (nextFrame) {
     if (nextFrame == aFrame)
       break;
     prevFrame = nextFrame;
     nextFrame = nextFrame->GetNextSibling();
   }
 
--- a/layout/xul/nsBox.cpp
+++ b/layout/xul/nsBox.cpp
@@ -921,17 +921,17 @@ nsBox::BoundsCheck(const nsSize& aMinSiz
                 BoundsCheck(aMinSize.height, aPrefSize.height, aMaxSize.height));
 }
 
 /*static*/ nsIFrame*
 nsBox::GetChildBox(const nsIFrame* aFrame)
 {
   // box layout ends at box-wrapped frames, so don't allow these frames
   // to report child boxes.
-  return aFrame->IsBoxFrame() ? aFrame->GetFirstPrincipalChild() : nullptr;
+  return aFrame->IsBoxFrame() ? aFrame->PrincipalChildList().FirstChild() : nullptr;
 }
 
 /*static*/ nsIFrame*
 nsBox::GetNextBox(const nsIFrame* aFrame)
 {
   return aFrame->GetParent() &&
     aFrame->GetParent()->IsBoxFrame() ? aFrame->GetNextSibling() : nullptr;
 }
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -1102,17 +1102,17 @@ nsBoxFrame::AppendFrames(ChildListID    
                         NS_FRAME_HAS_DIRTY_CHILDREN);
    }
 }
 
 /* virtual */ nsContainerFrame*
 nsBoxFrame::GetContentInsertionFrame()
 {
   if (GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK)
-    return GetFirstPrincipalChild()->GetContentInsertionFrame();
+    return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   return nsContainerFrame::GetContentInsertionFrame();
 }
 
 nsresult
 nsBoxFrame::AttributeChanged(int32_t aNameSpaceID,
                              nsIAtom* aAttribute,
                              int32_t aModType)
 {
--- a/layout/xul/nsMenuBarFrame.cpp
+++ b/layout/xul/nsMenuBarFrame.cpp
@@ -180,17 +180,17 @@ nsMenuBarFrame::FindMenuWithShortcut(nsI
     GetInsertionPoint(GetContent(), nullptr);
   nsContainerFrame* immediateParent = insertion.mParentFrame;
   if (!immediateParent)
     immediateParent = this;
 
   // Find a most preferred accesskey which should be returned.
   nsIFrame* foundMenu = nullptr;
   size_t foundIndex = accessKeys.NoIndex;
-  nsIFrame* currFrame = immediateParent->GetFirstPrincipalChild();
+  nsIFrame* currFrame = immediateParent->PrincipalChildList().FirstChild();
 
   while (currFrame) {
     nsIContent* current = currFrame->GetContent();
 
     // See if it's a menu item.
     if (nsXULPopupManager::IsValidMenuItem(current, false)) {
       // Get the shortcut attribute.
       nsAutoString shortcutKey;
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -1353,17 +1353,17 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutStat
       //  (2) there's enough room in the menu for the content and its
       //      border-padding
       //  (3) there's enough room in the popup for the content and its
       //      scrollbar
       nsMargin borderPadding;
       GetBorderAndPadding(borderPadding);
 
       // if there is a scroll frame, add the desired width of the scrollbar as well
-      nsIScrollableFrame* scrollFrame = do_QueryFrame(popupFrame->GetFirstPrincipalChild());
+      nsIScrollableFrame* scrollFrame = do_QueryFrame(popupFrame->PrincipalChildList().FirstChild());
       nscoord scrollbarWidth = 0;
       if (scrollFrame) {
         scrollbarWidth =
           scrollFrame->GetDesiredScrollbarSizes(&aState).LeftRight();
       }
 
       aSize.width =
         tmpSize.width + std::max(borderPadding.LeftRight(), scrollbarWidth);
@@ -1436,17 +1436,17 @@ nsMenuFrame::SetActiveChild(nsIDOMElemen
   return NS_OK;
 }
 
 nsIScrollableFrame* nsMenuFrame::GetScrollTargetFrame()
 {
   nsMenuPopupFrame* popupFrame = GetPopup();
   if (!popupFrame)
     return nullptr;
-  nsIFrame* childFrame = popupFrame->GetFirstPrincipalChild();
+  nsIFrame* childFrame = popupFrame->PrincipalChildList().FirstChild();
   if (childFrame)
     return popupFrame->GetScrollFrame(childFrame);
   return nullptr;
 }
 
 // nsMenuTimerMediator implementation.
 NS_IMPL_ISUPPORTS(nsMenuTimerMediator, nsITimerCallback)
 
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -231,17 +231,17 @@ nsMenuPopupFrame::PopupLevel(bool aIsNoA
   return sDefaultLevelIsTop ? ePopupLevelTop : ePopupLevelParent;
 }
 
 void
 nsMenuPopupFrame::EnsureWidget()
 {
   nsView* ourView = GetView();
   if (!ourView->HasWidget()) {
-    NS_ASSERTION(!mGeneratedChildren && !GetFirstPrincipalChild(),
+    NS_ASSERTION(!mGeneratedChildren && !PrincipalChildList().FirstChild(),
                  "Creating widget for MenuPopupFrame with children");
     CreateWidgetForView(ourView);
   }
 }
 
 nsresult
 nsMenuPopupFrame::CreateWidgetForView(nsView* aView)
 {
@@ -1679,17 +1679,17 @@ nsIScrollableFrame* nsMenuPopupFrame::Ge
     if (sf)
       return sf;
     currFrame = currFrame->GetNextSibling();
   } while (currFrame);
 
   // try children
   currFrame = aStart;
   do {
-    nsIFrame* childFrame = currFrame->GetFirstPrincipalChild();
+    nsIFrame* childFrame = currFrame->PrincipalChildList().FirstChild();
     nsIScrollableFrame* sf = GetScrollFrame(childFrame);
     if (sf)
       return sf;
     currFrame = currFrame->GetNextSibling();
   } while (currFrame);
 
   return nullptr;
 }
--- a/layout/xul/nsProgressMeterFrame.cpp
+++ b/layout/xul/nsProgressMeterFrame.cpp
@@ -130,17 +130,17 @@ nsProgressMeterFrame::AttributeChanged(i
   }
 
   // did the progress change?
   bool undetermined = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mode,
                                             nsGkAtoms::undetermined, eCaseMatters);
   if (nsGkAtoms::mode == aAttribute ||
       (!undetermined &&
        (nsGkAtoms::value == aAttribute || nsGkAtoms::max == aAttribute))) {
-    nsIFrame* barChild = GetFirstPrincipalChild();
+    nsIFrame* barChild = PrincipalChildList().FirstChild();
     if (!barChild) return NS_OK;
     nsIFrame* remainderChild = barChild->GetNextSibling();
     if (!remainderChild) return NS_OK;
     nsCOMPtr<nsIContent> remainderContent = remainderChild->GetContent();
     if (!remainderContent) return NS_OK;
 
     int32_t flex = 1, maxFlex = 1;
     if (!undetermined) {
--- a/layout/xul/nsRootBoxFrame.cpp
+++ b/layout/xul/nsRootBoxFrame.cpp
@@ -29,17 +29,17 @@ nsIRootBox::GetRootBox(nsIPresShell* aSh
     return nullptr;
   }
   nsIFrame* rootFrame = aShell->FrameManager()->GetRootFrame();
   if (!rootFrame) {
     return nullptr;
   }
 
   if (rootFrame) {
-    rootFrame = rootFrame->GetFirstPrincipalChild();
+    rootFrame = rootFrame->PrincipalChildList().FirstChild();
   }
 
   nsIRootBox* rootBox = do_QueryFrame(rootFrame);
   return rootBox;
 }
 
 class nsRootBoxFrame : public nsBoxFrame, public nsIRootBox {
 public:
--- a/layout/xul/nsScrollbarButtonFrame.cpp
+++ b/layout/xul/nsScrollbarButtonFrame.cpp
@@ -228,19 +228,18 @@ nsScrollbarButtonFrame::MouseClicked(Wid
   //MouseClicked();
 }
 
 nsresult
 nsScrollbarButtonFrame::GetChildWithTag(nsIAtom* atom, nsIFrame* start,
                                         nsIFrame*& result)
 {
   // recursively search our children
-  nsIFrame* childFrame = start->GetFirstPrincipalChild();
-  while (nullptr != childFrame) 
-  {    
+  for (nsIFrame* childFrame : start->PrincipalChildList())
+  {
     // get the content node
     nsIContent* child = childFrame->GetContent();
 
     if (child) {
       // see if it is the child
        if (child->IsXULElement(atom))
        {
          result = childFrame;
@@ -248,18 +247,16 @@ nsScrollbarButtonFrame::GetChildWithTag(
          return NS_OK;
        }
     }
 
      // recursive search the child
      GetChildWithTag(atom, childFrame, result);
      if (result != nullptr) 
        return NS_OK;
-
-    childFrame = childFrame->GetNextSibling();
   }
 
   result = nullptr;
   return NS_OK;
 }
 
 nsresult
 nsScrollbarButtonFrame::GetParentWithTag(nsIAtom* toFind, nsIFrame* start,
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -2328,46 +2328,46 @@ nsXULPopupManager::GetNextMenuItem(nsCon
   nsIFrame* currFrame = nullptr;
   if (aStart) {
     if (aStart->GetNextSibling())
       currFrame = aStart->GetNextSibling();
     else if (aStart->GetParent()->GetContent()->IsXULElement(nsGkAtoms::menugroup))
       currFrame = aStart->GetParent()->GetNextSibling();
   }
   else
-    currFrame = immediateParent->GetFirstPrincipalChild();
+    currFrame = immediateParent->PrincipalChildList().FirstChild();
 
   while (currFrame) {
     // See if it's a menu item.
     nsIContent* currFrameContent = currFrame->GetContent();
     if (IsValidMenuItem(currFrameContent, aIsPopup)) {
       return do_QueryFrame(currFrame);
     }
     if (currFrameContent->IsXULElement(nsGkAtoms::menugroup) &&
         currFrameContent->GetChildCount() > 0)
-      currFrame = currFrame->GetFirstPrincipalChild();
+      currFrame = currFrame->PrincipalChildList().FirstChild();
     else if (!currFrame->GetNextSibling() &&
              currFrame->GetParent()->GetContent()->IsXULElement(nsGkAtoms::menugroup))
       currFrame = currFrame->GetParent()->GetNextSibling();
     else
       currFrame = currFrame->GetNextSibling();
   }
 
-  currFrame = immediateParent->GetFirstPrincipalChild();
+  currFrame = immediateParent->PrincipalChildList().FirstChild();
 
   // Still don't have anything. Try cycling from the beginning.
   while (currFrame && currFrame != aStart) {
     // See if it's a menu item.
     nsIContent* currFrameContent = currFrame->GetContent();
     if (IsValidMenuItem(currFrameContent, aIsPopup)) {
       return do_QueryFrame(currFrame);
     }
     if (currFrameContent->IsXULElement(nsGkAtoms::menugroup) &&
         currFrameContent->GetChildCount() > 0)
-      currFrame = currFrame->GetFirstPrincipalChild();
+      currFrame = currFrame->PrincipalChildList().FirstChild();
     else if (!currFrame->GetNextSibling() &&
              currFrame->GetParent()->GetContent()->IsXULElement(nsGkAtoms::menugroup))
       currFrame = currFrame->GetParent()->GetNextSibling();
     else
       currFrame = currFrame->GetNextSibling();
   }
 
   // No luck. Just return our start value.
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -810,17 +810,17 @@ FindScrollParts(nsIFrame* aCurrFrame, ns
       if (!aResult->mHScrollbar) {
         aResult->mHScrollbar = sf;
       }
     }
     // don't bother searching inside a scrollbar
     return;
   }
   
-  nsIFrame* child = aCurrFrame->GetFirstPrincipalChild();
+  nsIFrame* child = aCurrFrame->PrincipalChildList().FirstChild();
   while (child &&
          !child->GetContent()->IsRootOfNativeAnonymousSubtree() &&
          (!aResult->mVScrollbar || !aResult->mHScrollbar ||
           !aResult->mColumnsScrollFrame)) {
     FindScrollParts(child, aResult);
     child = child->GetNextSibling();
   }
 }
--- a/layout/xul/tree/nsTreeColumns.cpp
+++ b/layout/xul/tree/nsTreeColumns.cpp
@@ -733,17 +733,17 @@ nsTreeColumns::EnsureColumns()
     nsIFrame* colFrame = colContent->GetPrimaryFrame();
     if (!colFrame)
       return;
 
     colFrame = colFrame->GetParent();
     if (!colFrame)
       return;
 
-    colFrame = colFrame->GetFirstPrincipalChild();
+    colFrame = colFrame->PrincipalChildList().FirstChild();
     if (!colFrame)
       return;
 
     // Now that we have the first visible column,
     // we can enumerate the columns in visible order
     nsTreeColumn* currCol = nullptr;
     while (colFrame) {
       nsIContent* colContent = colFrame->GetContent();
--- a/mobile/android/tests/browser/chrome/test_awsy_lite.html
+++ b/mobile/android/tests/browser/chrome/test_awsy_lite.html
@@ -149,17 +149,17 @@
   function openTab() {
     var urlIndex = gTabsOpened++;
     if (urlIndex >= kUrls.length) {
         checkpoint("After tabs");
         setTimeout(postOpening, 30000);
         return;
     }
 
-    dump("opening tab with url [" + kUrls[urlIndex] + "]");
+    info("opening tab with url [" + kUrls[urlIndex] + "]");
     gLastTab = BrowserApp.addTab(kUrls[urlIndex], { selected: true });
     setTimeout(waitForTab, 10000);
   }
 
   function waitForTab() {
     if (gLastTab.browser.contentDocument.readyState === "complete") {
         gLastTab = null;
         openTab();
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -43,17 +43,17 @@ static NS_DEFINE_CID(kZipReaderCID, NS_Z
 // own LOG macro below.)
 #ifdef LOG
 #undef LOG
 #endif
 
 //
 // set NSPR_LOG_MODULES=nsJarProtocol:5
 //
-static LazyLogModule gJarProtocolLog("nsJarProtocol");
+static PRLogModuleInfo *gJarProtocolLog = nullptr;
 
 #define LOG(args)     MOZ_LOG(gJarProtocolLog, mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() MOZ_LOG_TEST(gJarProtocolLog, mozilla::LogLevel::Debug)
 
 //-----------------------------------------------------------------------------
 // nsJARInputThunk
 //
 // this class allows us to do some extra work on the stream transport thread.
@@ -198,16 +198,19 @@ nsJARChannel::nsJARChannel()
     , mContentLength(-1)
     , mLoadFlags(LOAD_NORMAL)
     , mStatus(NS_OK)
     , mIsPending(false)
     , mIsUnsafe(true)
     , mOpeningRemote(false)
     , mBlockRemoteFiles(false)
 {
+    if (!gJarProtocolLog)
+        gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
+
     mBlockRemoteFiles = Preferences::GetBool("network.jar.block-remote-files", false);
 
     // hold an owning reference to the jar handler
     NS_ADDREF(gJarHandler);
 }
 
 nsJARChannel::~nsJARChannel()
 {
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -2659,17 +2659,18 @@ WebSocketChannel::SetupRequest()
 
   if (mLoadGroup) {
     rv = mHttpChannel->SetLoadGroup(mLoadGroup);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   rv = mHttpChannel->SetLoadFlags(nsIRequest::LOAD_BACKGROUND |
                                   nsIRequest::INHIBIT_CACHING |
-                                  nsIRequest::LOAD_BYPASS_CACHE);
+                                  nsIRequest::LOAD_BYPASS_CACHE |
+                                  nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // we never let websockets be blocked by head CSS/JS loads to avoid
   // potential deadlock where server generation of CSS/JS requires
   // an XHR signal.
   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
   if (cos) {
     cos->AddClassFlags(nsIClassOfService::Unblocked);
--- a/netwerk/test/browser/browser.ini
+++ b/netwerk/test/browser/browser.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 support-files =
   dummy.html
 
 [browser_NetUtil.js]
 [browser_child_resource.js]
+[browser_post_file.js]
 [browser_nsIFormPOSTActionChannel.js]
 skip-if = e10s # protocol handler and channel does not work in content process
new file mode 100644
--- /dev/null
+++ b/netwerk/test/browser/browser_post_file.js
@@ -0,0 +1,101 @@
+/*
+ * Tests for bug 1241100: Post to local file should not overwrite the file.
+ */
+
+Components.utils.import("resource://gre/modules/osfile.jsm");
+
+function* createTestFile(filename, content) {
+  let path = OS.Path.join(OS.Constants.Path.tmpDir, filename);
+  yield OS.File.writeAtomic(path, content);
+  return path;
+}
+
+function* readFile(path) {
+  var array = yield OS.File.read(path);
+  var decoder = new TextDecoder();
+  return decoder.decode(array);
+}
+
+function frameScript() {
+  addMessageListener("Test:WaitForIFrame", function() {
+    var check = function() {
+      if (content) {
+        var frame = content.document.getElementById("frame");
+        if (frame) {
+          var okBox = frame.contentDocument.getElementById("action_file_ok");
+          if (okBox) {
+            sendAsyncMessage("Test:IFrameLoaded");
+            return;
+          }
+        }
+      }
+
+      setTimeout(check, 100);
+    };
+
+    check();
+  });
+}
+
+add_task(function*() {
+  var postFilename = "post_file.html";
+  var actionFilename = "action_file.html";
+
+  var postFileContent = `
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>post file</title>
+</head>
+<body onload="document.getElementById('form').submit();">
+<form id="form" action="${actionFilename}" method="post" enctype="text/plain" target="frame">
+<input type="hidden" name="foo" value="bar">
+<input type="submit">
+</form>
+<iframe id="frame" name="frame"></iframe>
+</body>
+</html>
+`;
+
+  var actionFileContent = `
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>action file</title>
+</head>
+<body>
+<div id="action_file_ok">ok</div>
+</body>
+</html>
+`;
+
+  var postPath = yield* createTestFile(postFilename, postFileContent);
+  var actionPath = yield* createTestFile(actionFilename, actionFileContent);
+
+  var postURI = OS.Path.toFileURI(postPath);
+
+  gBrowser.selectedTab = gBrowser.addTab(postURI);
+  let browser = gBrowser.selectedBrowser;
+  browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
+  yield new Promise(resolve => {
+    let manager = browser.messageManager;
+
+    function listener() {
+      manager.removeMessageListener("Test:IFrameLoaded", listener);
+      resolve();
+    }
+
+    manager.addMessageListener("Test:IFrameLoaded", listener);
+    manager.sendAsyncMessage("Test:WaitForIFrame");
+  });
+
+  var actionFileContentAfter = yield* readFile(actionPath);
+  is(actionFileContentAfter, actionFileContent, "action file is not modified");
+
+  yield OS.File.remove(postPath);
+  yield OS.File.remove(actionPath);
+
+  gBrowser.removeCurrentTab();
+});
--- a/parser/htmlparser/nsExpatDriver.cpp
+++ b/parser/htmlparser/nsExpatDriver.cpp
@@ -35,17 +35,24 @@
 
 using mozilla::fallible;
 using mozilla::LogLevel;
 
 #define kExpatSeparatorChar 0xFFFF
 
 static const char16_t kUTF16[] = { 'U', 'T', 'F', '-', '1', '6', '\0' };
 
-static mozilla::LazyLogModule gExpatDriverLog("expatdriver");
+static PRLogModuleInfo *
+GetExpatDriverLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("expatdriver");
+  return sLog;
+}
 
 /***************************** EXPAT CALL BACKS ******************************/
 // The callback handlers that get called from the expat parser.
 
 static void
 Driver_HandleXMLDeclaration(void *aUserData,
                             const XML_Char *aVersion,
                             const XML_Char *aEncoding,
@@ -1047,17 +1054,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
   nsScannerIterator start = currentExpatPosition;
   start.advance(mExpatBuffered);
 
   // This is the end of the last buffer (at this point, more data could come in
   // later).
   nsScannerIterator end;
   aScanner.EndReading(end);
 
-  MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+  MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
           mExpatBuffered, Distance(start, end)));
 
   // We want to call Expat if we have more buffers, or if we know there won't
   // be more buffers (and so we want to flush the remaining data), or if we're
   // currently blocked and there's data in Expat's buffer.
   while (start != end || (mIsFinalChunk && !mMadeFinalCallToExpat) ||
          (BlockedOrInterrupted() && mExpatBuffered > 0)) {
@@ -1068,37 +1075,37 @@ nsExpatDriver::ConsumeToken(nsScanner& a
     uint32_t length;
     if (blocked || noMoreBuffers) {
       // If we're blocked we just resume Expat so we don't need a buffer, if
       // there aren't any more buffers we pass a null buffer to Expat.
       buffer = nullptr;
       length = 0;
 
       if (blocked) {
-        MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+        MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
                ("Resuming Expat, will parse data remaining in Expat's "
                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                       mExpatBuffered).get()));
       }
       else {
         NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end),
                      "Didn't pass all the data to Expat?");
-        MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+        MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
                ("Last call to Expat, will parse data remaining in Expat's "
                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                       mExpatBuffered).get()));
       }
     }
     else {
       buffer = start.get();
       length = uint32_t(start.size_forward());
 
-      MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+      MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
              ("Calling Expat, will parse data remaining in Expat's buffer and "
               "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew "
               "data:\n-----\n%s\n-----\n",
               NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                     mExpatBuffered).get(),
               NS_ConvertUTF16toUTF8(start.get(), length).get()));
     }
 
@@ -1128,17 +1135,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
         // data.
         AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
       }
     }
 
     mExpatBuffered += length - consumed;
 
     if (BlockedOrInterrupted()) {
-      MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+      MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
              ("Blocked or interrupted parser (probably for loading linked "
               "stylesheets or scripts)."));
 
       aScanner.SetPosition(currentExpatPosition, true);
       aScanner.Mark();
 
       return mInternalState;
     }
@@ -1189,17 +1196,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
     // (e.g. if we spun the event loop in an inline script). Reload end now
     // to compensate.
     aScanner.EndReading(end);
   }
 
   aScanner.SetPosition(currentExpatPosition, true);
   aScanner.Mark();
 
-  MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+  MOZ_LOG(GetExpatDriverLog(), LogLevel::Debug,
          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
           mExpatBuffered, Distance(currentExpatPosition, end)));
 
   return NS_SUCCEEDED(mInternalState) ? kEOF : NS_OK;
 }
 
 NS_IMETHODIMP
 nsExpatDriver::WillBuildModel(const CParserContext& aParserContext,
--- a/rdf/base/nsCompositeDataSource.cpp
+++ b/rdf/base/nsCompositeDataSource.cpp
@@ -40,17 +40,17 @@
 #include "rdf.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsEnumeratorUtils.h"
 
 #include "mozilla/Logging.h"
 #include "prprf.h"
 #include <stdio.h>
-mozilla::LazyLogModule nsRDFLog("RDF");
+PRLogModuleInfo* nsRDFLog = nullptr;
 
 //----------------------------------------------------------------------
 //
 // CompositeDataSourceImpl
 //
 
 class CompositeEnumeratorImpl;
 class CompositeArcsInOutEnumeratorImpl;
@@ -485,16 +485,18 @@ NS_NewRDFCompositeDataSource(nsIRDFCompo
 }
 
 
 CompositeDataSourceImpl::CompositeDataSourceImpl(void)
 	: mAllowNegativeAssertions(true),
 	  mCoalesceDuplicateArcs(true),
       mUpdateBatchNest(0)
 {
+    if (nsRDFLog == nullptr) 
+        nsRDFLog = PR_NewLogModule("RDF");
 }
 
 //----------------------------------------------------------------------
 //
 // nsISupports interface
 //
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(CompositeDataSourceImpl)
--- a/rdf/base/nsInMemoryDataSource.cpp
+++ b/rdf/base/nsInMemoryDataSource.cpp
@@ -347,20 +347,20 @@ public:
                  nsIRDFResource* asource,
                  nsIRDFResource* aProperty,
                  nsIRDFNode* aTarget,
                  bool aTruthValue = true);
 
     bool    mPropagateChanges;
 
 private:
-    static mozilla::LazyLogModule gLog;
+    static PRLogModuleInfo* gLog;
 };
 
-mozilla::LazyLogModule InMemoryDataSource::gLog("InMemoryDataSource");
+PRLogModuleInfo* InMemoryDataSource::gLog;
 
 //----------------------------------------------------------------------
 //
 // InMemoryAssertionEnumeratorImpl
 //
 
 /**
  * InMemoryAssertionEnumeratorImpl
@@ -738,16 +738,19 @@ InMemoryDataSource::InMemoryDataSource(n
     , mReverseArcs(PLDHashTable::StubOps(), sizeof(Entry))
     , mNumObservers(0)
     , mReadCount(0)
 {
     NS_INIT_AGGREGATED(aOuter);
 
     mPropagateChanges = true;
     MOZ_COUNT_CTOR(InMemoryDataSource);
+
+    if (! gLog)
+        gLog = PR_NewLogModule("InMemoryDataSource");
 }
 
 
 InMemoryDataSource::~InMemoryDataSource()
 {
 #ifdef DEBUG_REFS
     --gInstanceCount;
     fprintf(stdout, "%d - RDF: InMemoryDataSource\n", gInstanceCount);
--- a/rdf/base/nsRDFContentSink.cpp
+++ b/rdf/base/nsRDFContentSink.cpp
@@ -221,30 +221,30 @@ protected:
         RDFContentSinkParseMode  mParseMode;
     };
 
     nsAutoTArray<RDFContextStackElement, 8>* mContextStack;
 
     nsCOMPtr<nsIURI> mDocumentURL;
 
 private:
-    static mozilla::LazyLogModule gLog;
+    static PRLogModuleInfo* gLog;
 };
 
 int32_t         RDFContentSinkImpl::gRefCnt = 0;
 nsIRDFService*  RDFContentSinkImpl::gRDFService;
 nsIRDFContainerUtils* RDFContentSinkImpl::gRDFContainerUtils;
 nsIRDFResource* RDFContentSinkImpl::kRDF_type;
 nsIRDFResource* RDFContentSinkImpl::kRDF_instanceOf;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Alt;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Bag;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Seq;
 nsIRDFResource* RDFContentSinkImpl::kRDF_nextVal;
 
-mozilla::LazyLogModule RDFContentSinkImpl::gLog("nsRDFContentSink");
+PRLogModuleInfo* RDFContentSinkImpl::gLog;
 
 ////////////////////////////////////////////////////////////////////////
 
 #define RDF_ATOM(name_, value_) nsIAtom* RDFContentSinkImpl::name_;
 #include "nsRDFContentSinkAtomList.h"
 #undef RDF_ATOM
 
 #define RDF_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
@@ -285,16 +285,19 @@ RDFContentSinkImpl::RDFContentSinkImpl()
                                           &kRDF_nextVal);
         }
 
         NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
         rv = CallGetService(kRDFContainerUtilsCID, &gRDFContainerUtils);
 
         NS_RegisterStaticAtoms(rdf_atoms);
     }
+
+    if (! gLog)
+        gLog = PR_NewLogModule("nsRDFContentSink");
 }
 
 
 RDFContentSinkImpl::~RDFContentSinkImpl()
 {
 #ifdef DEBUG_REFS
     --gInstanceCount;
     fprintf(stdout, "%d - RDF: RDFContentSinkImpl\n", gInstanceCount);
--- a/rdf/base/nsRDFService.cpp
+++ b/rdf/base/nsRDFService.cpp
@@ -66,17 +66,17 @@ static NS_DEFINE_CID(kRDFXMLDataSourceCI
 static NS_DEFINE_CID(kRDFDefaultResourceCID,  NS_RDFDEFAULTRESOURCE_CID);
 
 static NS_DEFINE_IID(kIRDFLiteralIID,         NS_IRDFLITERAL_IID);
 static NS_DEFINE_IID(kIRDFDateIID,         NS_IRDFDATE_IID);
 static NS_DEFINE_IID(kIRDFIntIID,         NS_IRDFINT_IID);
 static NS_DEFINE_IID(kIRDFNodeIID,            NS_IRDFNODE_IID);
 static NS_DEFINE_IID(kISupportsIID,           NS_ISUPPORTS_IID);
 
-static LazyLogModule gLog("nsRDFService");
+static PRLogModuleInfo* gLog = nullptr;
 
 class BlobImpl;
 
 // These functions are copied from nsprpub/lib/ds/plhash.c, with one
 // change to free the key in DataSourceFreeEntry.
 // XXX sigh, why were DefaultAllocTable et. al. declared static, anyway?
 
 static void *
@@ -743,16 +743,19 @@ RDFServiceImpl::Init()
 
     if (! mNamedDataSources)
         return NS_ERROR_OUT_OF_MEMORY;
 
     mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
     if (NS_FAILED(rv)) return rv;
 
+    if (! gLog)
+        gLog = PR_NewLogModule("nsRDFService");
+
     return NS_OK;
 }
 
 
 RDFServiceImpl::~RDFServiceImpl()
 {
     if (mNamedDataSources) {
         PL_HashTableDestroy(mNamedDataSources);
--- a/rdf/base/nsRDFXMLDataSource.cpp
+++ b/rdf/base/nsRDFXMLDataSource.cpp
@@ -130,17 +130,17 @@ protected:
     nsCOMPtr<nsIURI>    mURL;
     nsCOMPtr<nsIStreamListener> mListener;
     nsNameSpaceMap      mNameSpaces;
 
     // pseudo-constants
     static int32_t gRefCnt;
     static nsIRDFService* gRDFService;
 
-    static mozilla::LazyLogModule gLog;
+    static PRLogModuleInfo* gLog;
 
     nsresult Init();
     RDFXMLDataSourceImpl(void);
     virtual ~RDFXMLDataSourceImpl(void);
     nsresult rdfXMLFlush(nsIURI *aURI);
 
     friend nsresult
     NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult);
@@ -354,17 +354,17 @@ public:
 protected:
     nsresult
     BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer);
 };
 
 int32_t         RDFXMLDataSourceImpl::gRefCnt = 0;
 nsIRDFService*  RDFXMLDataSourceImpl::gRDFService;
 
-mozilla::LazyLogModule RDFXMLDataSourceImpl::gLog("nsRDFXMLDataSource");
+PRLogModuleInfo* RDFXMLDataSourceImpl::gLog;
 
 static const char kFileURIPrefix[] = "file:";
 static const char kResourceURIPrefix[] = "resource:";
 
 
 //----------------------------------------------------------------------
 
 nsresult
@@ -392,16 +392,18 @@ NS_NewRDFXMLDataSource(nsIRDFDataSource*
 }
 
 
 RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
     : mIsWritable(true),
       mIsDirty(false),
       mLoadState(eLoadState_Unloaded)
 {
+    if (! gLog)
+        gLog = PR_NewLogModule("nsRDFXMLDataSource");
 }
 
 
 nsresult
 RDFXMLDataSourceImpl::Init()
 {
     nsresult rv;
     NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -35,17 +35,17 @@
 #include "pkix/pkixnss.h"
 #include "secmime.h"
 
 
 using namespace mozilla::pkix;
 using namespace mozilla;
 using namespace mozilla::psm;
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 namespace {
 
 // Reads a maximum of 1MB from a stream into the supplied buffer.
 // The reason for the 1MB limit is because this function is used to read
 // signature-related files and we want to avoid OOM. The uncompressed length of
 // an entry can be hundreds of times larger than the compressed version,
 // especially if someone has specifically crafted the entry to cause OOM or to
--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -32,17 +32,17 @@
 // Add-on signing Certificates
 #include "addons-public.inc"
 #include "addons-stage.inc"
 // Privileged Package Certificates
 #include "privileged-package-root.inc"
 
 using namespace mozilla::pkix;
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 static const unsigned int DEFAULT_MIN_RSA_BITS = 2048;
 static char kDevImportedDER[] =
   "network.http.signed-packages.developer-root";
 
 namespace mozilla { namespace psm {
 
 StaticMutex AppTrustDomain::sMutex;
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -17,17 +17,17 @@
 #include "pkix/pkixnss.h"
 #include "prerror.h"
 #include "secerr.h"
 #include "sslerr.h"
 
 using namespace mozilla::pkix;
 using namespace mozilla::psm;
 
-mozilla::LazyLogModule gCertVerifierLog("certverifier");
+PRLogModuleInfo* gCertVerifierLog = nullptr;
 
 namespace mozilla { namespace psm {
 
 const CertVerifier::Flags CertVerifier::FLAG_LOCAL_ONLY = 1;
 const CertVerifier::Flags CertVerifier::FLAG_MUST_BE_EV = 2;
 const CertVerifier::Flags CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST = 4;
 
 CertVerifier::CertVerifier(OcspDownloadConfig odc,
@@ -47,16 +47,19 @@ CertVerifier::CertVerifier(OcspDownloadC
 
 CertVerifier::~CertVerifier()
 {
 }
 
 void
 InitCertVerifierLog()
 {
+  if (!gCertVerifierLog) {
+    gCertVerifierLog = PR_NewLogModule("certverifier");
+  }
 }
 
 Result
 IsCertChainRootBuiltInRoot(CERTCertList* chain, bool& result)
 {
   if (!chain || CERT_LIST_EMPTY(chain)) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -11,17 +11,17 @@
 #include "base64.h"
 #include "hasht.h"
 #include "pkix/pkixtypes.h"
 #include "pk11pub.h"
 #include "secerr.h"
 #include "prerror.h"
 #include "prinit.h"
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 #define CONST_OID static const unsigned char
 #define OI(x) { siDEROID, (unsigned char*) x, sizeof x }
 
 struct nsMyTrustedEVInfo
 {
   const char* dotted_oid;
   const char* oid_name; // Set this to null to signal an invalid structure,
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -28,17 +28,17 @@
 #include "ScopedNSSTypes.h"
 #include "secerr.h"
 
 #include "CNNICHashWhitelist.inc"
 
 using namespace mozilla;
 using namespace mozilla::pkix;
 
-extern LazyLogModule gCertVerifierLog;
+extern PRLogModuleInfo* gCertVerifierLog;
 
 static const uint64_t ServerFailureDelaySeconds = 5 * 60;
 
 namespace mozilla { namespace psm {
 
 const char BUILTIN_ROOTS_MODULE_DEFAULT_NAME[] = "Builtin Roots Module";
 
 NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
--- a/security/certverifier/OCSPCache.cpp
+++ b/security/certverifier/OCSPCache.cpp
@@ -27,17 +27,17 @@
 #include <limits>
 
 #include "NSSCertDBTrustDomain.h"
 #include "pk11pub.h"
 #include "pkix/pkixnss.h"
 #include "ScopedNSSTypes.h"
 #include "secerr.h"
 
-extern mozilla::LazyLogModule gCertVerifierLog;
+extern PRLogModuleInfo* gCertVerifierLog;
 
 using namespace mozilla::pkix;
 
 namespace mozilla { namespace psm {
 
 // Let derIssuer be the DER encoding of the issuer of aCert.
 // Let derPublicKey be the DER encoding of the public key of aIssuerCert.
 // Let serialNumber be the bytes of the serial number of aCert.
--- a/security/certverifier/OCSPRequestor.cpp
+++ b/security/certverifier/OCSPRequestor.cpp
@@ -11,17 +11,17 @@
 #include "mozilla/Base64.h"
 #include "mozilla/Scoped.h"
 #include "nsIURLParser.h"
 #include "nsNSSCallbacks.h"
 #include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
 #include "secerr.h"
 
-extern mozilla::LazyLogModule gCertVerifierLog;
+extern PRLogModuleInfo* gCertVerifierLog;
 
 namespace mozilla {
 
 void
 ReleaseHttpServerSession(nsNSSHttpServerSession* httpServerSession)
 {
   delete httpServerSession;
 }
--- a/security/manager/ssl/CertBlocklist.cpp
+++ b/security/manager/ssl/CertBlocklist.cpp
@@ -29,17 +29,17 @@ NS_IMPL_ISUPPORTS(CertBlocklist, nsICert
 using namespace mozilla;
 using namespace mozilla::pkix;
 
 #define PREF_BACKGROUND_UPDATE_TIMER "app.update.lastUpdateTime.blocklist-background-update-timer"
 #define PREF_KINTO_ONECRL_CHECKED "services.kinto.onecrl.checked"
 #define PREF_MAX_STALENESS_IN_SECONDS "security.onecrl.maximum_staleness_in_seconds"
 #define PREF_ONECRL_VIA_AMO "security.onecrl.via.amo"
 
-static LazyLogModule gCertBlockPRLog("CertBlock");
+static PRLogModuleInfo* gCertBlockPRLog;
 
 uint32_t CertBlocklist::sLastBlocklistUpdate = 0U;
 uint32_t CertBlocklist::sLastKintoUpdate = 0U;
 uint32_t CertBlocklist::sMaxStaleness = 0U;
 bool CertBlocklist::sUseAMO = true;
 
 CertBlocklistItem::CertBlocklistItem(const uint8_t* DNData,
                                      size_t DNLength,
@@ -125,16 +125,19 @@ CertBlocklistItem::Hash() const
 }
 
 CertBlocklist::CertBlocklist()
   : mMutex("CertBlocklist::mMutex")
   , mModified(false)
   , mBackingFileIsInitialized(false)
   , mBackingFile(nullptr)
 {
+  if (!gCertBlockPRLog) {
+    gCertBlockPRLog = PR_NewLogModule("CertBlock");
+  }
 }
 
 CertBlocklist::~CertBlocklist()
 {
   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
                                   PREF_BACKGROUND_UPDATE_TIMER,
                                   this);
   Preferences::UnregisterCallback(CertBlocklist::PreferenceChanged,
--- a/security/manager/ssl/PSMContentListener.cpp
+++ b/security/manager/ssl/PSMContentListener.cpp
@@ -24,17 +24,17 @@
 #include "nsNetUtil.h"
 #include "nsIChannel.h"
 #include "nsIInputStream.h"
 #include "nsIURI.h"
 #include "nsNSSHelper.h"
 
 #include "mozilla/Logging.h"
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 namespace mozilla { namespace psm {
 
 namespace {
 
 const int32_t kDefaultCertAllocLength = 2048;
 
 enum {
--- a/security/manager/ssl/PublicKeyPinningService.cpp
+++ b/security/manager/ssl/PublicKeyPinningService.cpp
@@ -18,17 +18,18 @@
 #include "sechash.h"
 
 #include "StaticHPKPins.h" // autogenerated by genHPKPStaticpins.js
 
 using namespace mozilla;
 using namespace mozilla::pkix;
 using namespace mozilla::psm;
 
-LazyLogModule gPublicKeyPinningLog("PublicKeyPinningService");
+PRLogModuleInfo* gPublicKeyPinningLog =
+  PR_NewLogModule("PublicKeyPinningService");
 
 /**
  Computes in the location specified by base64Out the SHA256 digest
  of the DER Encoded subject Public Key Info for the given cert
 */
 static nsresult
 GetBase64HashSPKI(const CERTCertificate* cert, nsACString& hashSPKIDigest)
 {
--- a/security/manager/ssl/RootCertificateTelemetryUtils.cpp
+++ b/security/manager/ssl/RootCertificateTelemetryUtils.cpp
@@ -8,17 +8,18 @@
 
 #include "mozilla/Logging.h"
 #include "RootHashes.inc" // Note: Generated by genRootCAHashes.js
 #include "ScopedNSSTypes.h"
 #include "mozilla/ArrayUtils.h"
 
 namespace mozilla { namespace psm {
 
-mozilla::LazyLogModule gPublicKeyPinningTelemetryLog("PublicKeyPinningTelemetryService");
+PRLogModuleInfo* gPublicKeyPinningTelemetryLog =
+  PR_NewLogModule("PublicKeyPinningTelemetryService");
 
 // Used in the BinarySearch method, this does a memcmp between the pointer
 // provided to its construtor and whatever the binary search is looking for.
 //
 // This implementation assumes everything to be of HASH_LEN, so it should not
 // be used generically.
 class BinaryHashSearchArrayComparator
 {
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -128,17 +128,17 @@
 
 #include "ssl.h"
 #include "cert.h"
 #include "secerr.h"
 #include "secoidt.h"
 #include "secport.h"
 #include "sslerr.h"
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 using namespace mozilla::pkix;
 
 namespace mozilla { namespace psm {
 
 namespace {
 
 // do not use a nsCOMPtr to avoid static initializer/destructor
--- a/security/manager/ssl/nsCertTree.cpp
+++ b/security/manager/ssl/nsCertTree.cpp
@@ -21,17 +21,17 @@
 #include "nsXPCOMCID.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 
 #include "mozilla/Logging.h"
 
 using namespace mozilla;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID);
 
 // treeArrayElStr
 //
 // structure used to hold map of tree.  Each thread (an organization
 // field from a cert) has an element in the array.  The numChildren field
 // stores the number of certs corresponding to that thread.
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -23,17 +23,17 @@
 #include "nsNetUtil.h"
 #include "SharedSSLState.h"
 #include "ssl.h"
 #include "sslproto.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 static void AccumulateCipherSuite(Telemetry::ID probe,
                                   const SSLChannelInfo& channelInfo);
 
 namespace {
 
 // Bits in bit mask for SSL_REASONS_FOR_NOT_FALSE_STARTING telemetry probe
 // These bits are numbered so that the least subtle issues have higher values.
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -52,17 +52,17 @@
 
 #ifdef XP_WIN
 #include <winsock.h> // for htonl
 #endif
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 // This is being stored in an uint32_t that can otherwise
 // only take values from nsIX509Cert's list of cert types.
 // As nsIX509Cert is frozen, we choose a value not contained
 // in the list to mean not yet initialized.
 #define CERT_TYPE_NOT_YET_INITIALIZED (1 << 30)
 
 NS_IMPL_ISUPPORTS(nsNSSCertificate,
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -51,17 +51,17 @@
 #ifdef XP_WIN
 #include <winsock.h> // for ntohl
 #endif
 
 using namespace mozilla;
 using namespace mozilla::psm;
 using mozilla::psm::SharedSSLState;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 static nsresult
 attemptToLogInWithDefaultPassword()
 {
 #ifdef NSS_DISABLE_DBM
   // The SQL NSS DB requires the user to be authenticated to set certificate
   // trust settings, even if the user's password is empty. To maintain
   // compatibility with the DBM-based database, try to log in with the
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -50,17 +50,17 @@
 
 #ifdef XP_WIN
 #include "nsILocalFileWin.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
-LazyLogModule gPIPNSSLog("pipnss");
+PRLogModuleInfo* gPIPNSSLog = nullptr;
 
 int nsNSSComponent::mInstanceCount = 0;
 
 // This function can be called from chrome or content processes
 // to ensure that NSS is initialized.
 bool EnsureNSSInitializedChromeOrContent()
 {
   nsresult rv;
@@ -216,16 +216,18 @@ GetRevocationBehaviorFromPrefs(/*out*/ C
 nsNSSComponent::nsNSSComponent()
   :mutex("nsNSSComponent.mutex"),
    mNSSInitialized(false),
 #ifndef MOZ_NO_SMART_CARDS
    mThreadList(nullptr),
 #endif
    mCertVerificationThread(nullptr)
 {
+  if (!gPIPNSSLog)
+    gPIPNSSLog = PR_NewLogModule("pipnss");
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::ctor\n"));
 
   NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
   ++mInstanceCount;
   mShutdownObjectList = nsNSSShutDownList::construct();
 }
 
 void
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -77,17 +77,17 @@ typedef enum {ASK, AUTO} SSM_UserCertCho
 // order to false start, as a compatibility hack to work around
 // implementations that just stop responding during false start. However, now
 // false start is resricted to modern crypto (TLS 1.2 and AEAD cipher suites)
 // so it is less likely that requring NPN or ALPN is still necessary.
 static const bool FALSE_START_REQUIRE_NPN_DEFAULT = false;
 
 } // unnamed namespace
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
   : mFd(nullptr),
     mCertVerificationState(before_cert_verification),
     mSharedState(aState),
     mForSTARTTLS(false),
     mHandshakePending(true),
     mRememberClientAuthCertificate(false),
--- a/security/manager/ssl/nsNSSShutDown.cpp
+++ b/security/manager/ssl/nsNSSShutDown.cpp
@@ -2,17 +2,17 @@
  * 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 "nsNSSShutDown.h"
 #include "nsCOMPtr.h"
 
 using namespace mozilla;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 struct ObjectHashEntry : PLDHashEntryHdr {
   nsNSSShutDownObject *obj;
 };
 
 static bool
 ObjectSetMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                          const void *key)
--- a/security/manager/ssl/nsNTLMAuthModule.cpp
+++ b/security/manager/ssl/nsNTLMAuthModule.cpp
@@ -23,20 +23,28 @@
 #include "nsNetCID.h"
 #include "nsNSSShutDown.h"
 #include "nsUnicharUtils.h"
 #include "pk11pub.h"
 #include "mozilla/Logging.h"
 #include "prsystem.h"
 
 static bool sNTLMv1Forced = false;
-static mozilla::LazyLogModule sNTLMLog("NTLM");
 
-#define LOG(x) MOZ_LOG(sNTLMLog, mozilla::LogLevel::Debug, x)
-#define LOG_ENABLED() MOZ_LOG_TEST(sNTLMLog, mozilla::LogLevel::Debug)
+static PRLogModuleInfo *
+GetNTLMLog()
+{
+  static PRLogModuleInfo *sNTLMLog;
+  if (!sNTLMLog)
+    sNTLMLog = PR_NewLogModule("NTLM");
+  return sNTLMLog;
+}
+
+#define LOG(x) MOZ_LOG(GetNTLMLog(), mozilla::LogLevel::Debug, x)
+#define LOG_ENABLED() MOZ_LOG_TEST(GetNTLMLog(), mozilla::LogLevel::Debug)
 
 static void des_makekey(const uint8_t *raw, uint8_t *key);
 static void des_encrypt(const uint8_t *key, const uint8_t *src, uint8_t *hash);
 
 //-----------------------------------------------------------------------------
 // this file contains a cross-platform NTLM authentication implementation. it
 // is based on documentation from: http://davenport.sourceforge.net/ntlm.html
 //-----------------------------------------------------------------------------
--- a/security/manager/ssl/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/nsPK11TokenDB.cpp
@@ -9,17 +9,17 @@
 #include "prerror.h"
 #include "secerr.h"
 #include "nsReadableUtils.h"
 #include "nsNSSComponent.h"
 #include "nsServiceManagerUtils.h"
 
 #include "nsPK11TokenDB.h"
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
 
 nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return;
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -8,17 +8,17 @@
 #include "mozilla/Telemetry.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsArray.h"
 #include "nsPK11TokenDB.h"
 #include "secmod.h"
 
 using mozilla::LogLevel;
 
-extern mozilla::LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 NS_IMPL_ISUPPORTS(nsPKCS11Slot, nsIPKCS11Slot)
 
 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo *slot)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return;
--- a/security/manager/ssl/nsPKCS12Blob.cpp
+++ b/security/manager/ssl/nsPKCS12Blob.cpp
@@ -27,18 +27,19 @@
 #include "nsKeygenHandler.h" //For GetSlotWithMechanism
 #include "nsPK11TokenDB.h"
 #include "nsICertificateDialogs.h"
 #include "nsNSSShutDown.h"
 #include "nsCRT.h"
 
 #include "secerr.h"
 
+extern PRLogModuleInfo* gPIPNSSLog;
+
 using namespace mozilla;
-extern LazyLogModule gPIPNSSLog;
 
 #define PIP_PKCS12_TMPFILENAME   NS_LITERAL_CSTRING(".pip_p12tmp")
 #define PIP_PKCS12_BUFFER_SIZE   2048
 #define PIP_PKCS12_RESTORE_OK          1
 #define PIP_PKCS12_BACKUP_OK           2
 #define PIP_PKCS12_USER_CANCELED       3
 #define PIP_PKCS12_NOSMARTCARD_EXPORT  4
 #define PIP_PKCS12_RESTORE_FAILED      5
--- a/security/manager/ssl/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/ssl/nsSecureBrowserUIImpl.cpp
@@ -44,17 +44,17 @@ using namespace mozilla;
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=nsSecureBrowserUI:5
 //    set NSPR_LOG_FILE=nspr.log
 //
 // this enables LogLevel::Debug level information and places all output in
 // the file nspr.log
 //
-LazyLogModule gSecureDocLog("nsSecureBrowserUI");
+PRLogModuleInfo* gSecureDocLog = nullptr;
 
 struct RequestHashEntry : PLDHashEntryHdr {
     void *r;
 };
 
 static bool
 RequestMapMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                          const void *key)
@@ -112,16 +112,19 @@ nsSecureBrowserUIImpl::nsSecureBrowserUI
 #ifdef DEBUG
   , mOnStateLocationChangeReentranceDetection(0)
 #endif
   , mTransferringRequests(&gMapOps, sizeof(RequestHashEntry))
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ResetStateTracking();
+
+  if (!gSecureDocLog)
+    gSecureDocLog = PR_NewLogModule("nsSecureBrowserUI");
 }
 
 NS_IMPL_ISUPPORTS(nsSecureBrowserUIImpl,
                   nsISecureBrowserUI,
                   nsIWebProgressListener,
                   nsISupportsWeakReference,
                   nsISSLStatusProvider)
 
--- a/security/manager/ssl/nsSecurityHeaderParser.cpp
+++ b/security/manager/ssl/nsSecurityHeaderParser.cpp
@@ -41,19 +41,27 @@ IsQuotedTextSymbol(signed char chr) {
 }
 
 // The octet following the "\" in a quoted pair can be anything 0-127.
 bool
 IsQuotedPairSymbol(signed char chr) {
   return (chr >= 0);
 }
 
-static mozilla::LazyLogModule sSHParserLog("nsSecurityHeaderParser");
+static PRLogModuleInfo *
+GetSHParserLog()
+{
+  static PRLogModuleInfo *sSHParserLog;
+  if (!sSHParserLog) {
+    sSHParserLog = PR_NewLogModule("nsSecurityHeaderParser");
+  }
+  return sSHParserLog;
+}
 
-#define SHPARSERLOG(args) MOZ_LOG(sSHParserLog, mozilla::LogLevel::Debug, args)
+#define SHPARSERLOG(args) MOZ_LOG(GetSHParserLog(), mozilla::LogLevel::Debug, args)
 
 nsSecurityHeaderParser::nsSecurityHeaderParser(const char *aHeader)
   : mCursor(aHeader)
   , mError(false)
 {
 }
 
 nsSecurityHeaderParser::~nsSecurityHeaderParser() {
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -36,19 +36,26 @@
 // influence its HSTS status via include subdomains, however).
 // This prevents the preload list from overriding the site's current
 // desired HSTS status.
 #include "nsSTSPreloadList.inc"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
-static LazyLogModule gSSSLog("nsSSService");
+static PRLogModuleInfo *
+GetSSSLog()
+{
+  static PRLogModuleInfo *gSSSLog;
+  if (!gSSSLog)
+    gSSSLog = PR_NewLogModule("nsSSService");
+  return gSSSLog;
+}
 
-#define SSSLOG(args) MOZ_LOG(gSSSLog, mozilla::LogLevel::Debug, args)
+#define SSSLOG(args) MOZ_LOG(GetSSSLog(), mozilla::LogLevel::Debug, args)
 
 ////////////////////////////////////////////////////////////////////////////////
 
 SiteHSTSState::SiteHSTSState(nsCString& aStateString)
   : mHSTSExpireTime(0)
   , mHSTSState(SecurityPropertyUnset)
   , mHSTSIncludeSubdomains(false)
 {
--- a/security/manager/ssl/nsUsageArrayHelper.cpp
+++ b/security/manager/ssl/nsUsageArrayHelper.cpp
@@ -14,17 +14,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nspr.h"
 #include "pkix/pkixnss.h"
 #include "secerr.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
-extern LazyLogModule gPIPNSSLog;
+extern PRLogModuleInfo* gPIPNSSLog;
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); // XXX? needed?::
 
 nsUsageArrayHelper::nsUsageArrayHelper(CERTCertificate *aCert)
 :mCert(aCert)
 {
   nsNSSShutDownPreventionLock locker;
   defaultcertdb = CERT_GetDefaultCertDB();
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_22_BETA2
+NSS_3_22_RTM
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -28,22 +28,22 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION  "3.22" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION  "3.22" _NSS_ECC_STRING _NSS_CUSTOMIZED
 #define NSS_VMAJOR   3
 #define NSS_VMINOR   22
 #define NSS_VPATCH   0
 #define NSS_VBUILD   0
-#define NSS_BETA     PR_TRUE
+#define NSS_BETA     PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -20,16 +20,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION  "3.22" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION  "3.22" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR   3
 #define SOFTOKEN_VMINOR   22
 #define SOFTOKEN_VPATCH   0
 #define SOFTOKEN_VBUILD   0
-#define SOFTOKEN_BETA     PR_TRUE
+#define SOFTOKEN_BETA     PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,22 +14,22 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION  "3.22 Beta"
+#define NSSUTIL_VERSION  "3.22"
 #define NSSUTIL_VMAJOR   3
 #define NSSUTIL_VMINOR   22
 #define NSSUTIL_VPATCH   0
 #define NSSUTIL_VBUILD   0
-#define NSSUTIL_BETA     PR_TRUE
+#define NSSUTIL_BETA     PR_FALSE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);
 
--- a/services/cloudsync/tests/xpcshell/test_tabs.js
+++ b/services/cloudsync/tests/xpcshell/test_tabs.js
@@ -4,17 +4,17 @@
 "use strict";
 
 Cu.import("resource://gre/modules/CloudSync.jsm");
 
 function run_test () {
   run_next_test();
 }
 
-add_task(function test_get_remote_tabs () {
+add_task(function* test_get_remote_tabs () {
   let cloudSync = CloudSync();
   let clients = yield cloudSync.tabs.getRemoteTabs();
   equal(clients.length, 0);
 
   yield cloudSync.tabs.mergeRemoteTabs({
       id: "001",
       name: "FakeClient",
     },[
--- a/services/common/async.js
+++ b/services/common/async.js
@@ -1,20 +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/. */
 
-#ifndef MERGED_COMPARTMENT
-
 this.EXPORTED_SYMBOLS = ["Async"];
 
 var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
-#endif
-
 // Constants for makeSyncCallback, waitForSyncCallback.
 const CB_READY = {};
 const CB_COMPLETE = {};
 const CB_FAIL = {};
 
 const REASON_ERROR = Ci.mozIStorageStatementCallback.REASON_ERROR;
 
 Cu.import("resource://gre/modules/Services.jsm");
--- a/services/common/moz.build
+++ b/services/common/moz.build
@@ -9,39 +9,36 @@ with Files('**'):
 
 TEST_DIRS += ['tests']
 
 EXTRA_COMPONENTS += [
     'servicesComponents.manifest',
 ]
 
 EXTRA_JS_MODULES['services-common'] += [
+    'async.js',
     'logmanager.js',
     'moz-kinto-client.js',
+    'observers.js',
+    'rest.js',
     'stringbundle.js',
     'utils.js',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' or CONFIG['MOZ_B2GDROID']:
     EXTRA_JS_MODULES['services-common'] += [
         'hawkclient.js',
         'hawkrequest.js',
         'tokenserverclient.js',
     ]
 
     TESTING_JS_MODULES.services.common += [
         'modules-testing/storageserver.js',
     ]
 
-EXTRA_PP_JS_MODULES['services-common'] += [
-    'async.js',
-    'observers.js',
-    'rest.js',
-]
-
 TESTING_JS_MODULES.services.common += [
     'modules-testing/logging.js',
     'modules-testing/utils.js',
 ]
 
 JS_PREFERENCE_FILES += [
     'services-common.js',
 ]
--- a/services/common/observers.js
+++ b/services/common/observers.js
@@ -1,23 +1,19 @@
 /* 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/. */
 
-#ifndef MERGED_COMPARTMENT
-
 this.EXPORTED_SYMBOLS = ["Observers"];
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cr = Components.results;
 var Cu = Components.utils;
 
-#endif
-
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * A service for adding, removing and notifying observers of notifications.
  * Wraps the nsIObserverService interface.
  *
  * @version 0.2
  */
--- a/services/common/rest.js
+++ b/services/common/rest.js
@@ -1,24 +1,20 @@
 /* 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/. */
 
-#ifndef MERGED_COMPARTMENT
-
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 this.EXPORTED_SYMBOLS = [
   "RESTRequest",
   "RESTResponse",
   "TokenAuthenticatedRESTRequest",
 ];
 
-#endif
-
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/utils.js");
 
 XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils",
--- a/services/common/tests/unit/test_hawkclient.js
+++ b/services/common/tests/unit/test_hawkclient.js
@@ -39,17 +39,17 @@ add_task(function test_updateClockOffset
   // error, so checking strict equality will likely fail.
   //
   // localtimeOffsetMsec is how many milliseconds to add to the local clock so
   // that it agrees with the server.  We are one hour ahead of the server, so
   // our offset should be -1 hour.
   do_check_true(Math.abs(client.localtimeOffsetMsec + HOUR_MS) <= SECOND_MS);
 });
 
-add_task(function test_authenticated_get_request() {
+add_task(function* test_authenticated_get_request() {
   let message = "{\"msg\": \"Great Success!\"}";
   let method = "GET";
 
   let server = httpd_setup({"/foo": (request, response) => {
       do_check_true(request.hasHeader("Authorization"));
 
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.bodyOutputStream.write(message, message.length);
@@ -61,17 +61,17 @@ add_task(function test_authenticated_get
   let response = yield client.request("/foo", method, TEST_CREDS);
   let result = JSON.parse(response.body);
 
   do_check_eq("Great Success!", result.msg);
 
   yield deferredStop(server);
 });
 
-function check_authenticated_request(method) {
+function* check_authenticated_request(method) {
   let server = httpd_setup({"/foo": (request, response) => {
       do_check_true(request.hasHeader("Authorization"));
 
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.setHeader("Content-Type", "application/json");
       response.bodyOutputStream.writeFrom(request.bodyInputStream, request.bodyInputStream.available());
     }
   });
@@ -93,17 +93,17 @@ add_task(function test_authenticated_pos
 add_task(function test_authenticated_put_request() {
   check_authenticated_request("PUT");
 });
 
 add_task(function test_authenticated_patch_request() {
   check_authenticated_request("PATCH");
 });
 
-add_task(function test_credentials_optional() {
+add_task(function* test_credentials_optional() {
   let method = "GET";
   let server = httpd_setup({
     "/foo": (request, response) => {
       do_check_false(request.hasHeader("Authorization"));
 
       let message = JSON.stringify({msg: "you're in the friend zone"});
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.setHeader("Content-Type", "application/json");
@@ -113,17 +113,17 @@ add_task(function test_credentials_optio
 
   let client = new HawkClient(server.baseURI);
   let result = yield client.request("/foo", method); // credentials undefined
   do_check_eq(JSON.parse(result.body).msg, "you're in the friend zone");
 
   yield deferredStop(server);
 });
 
-add_task(function test_server_error() {
+add_task(function* test_server_error() {
   let message = "Ohai!";
   let method = "GET";
 
   let server = httpd_setup({"/foo": (request, response) => {
       response.setStatusLine(request.httpVersion, 418, "I am a Teapot");
       response.bodyOutputStream.write(message, message.length);
     }
   });
@@ -136,17 +136,17 @@ add_task(function test_server_error() {
   } catch(err) {
     do_check_eq(418, err.code);
     do_check_eq("I am a Teapot", err.message);
   }
 
   yield deferredStop(server);
 });
 
-add_task(function test_server_error_json() {
+add_task(function* test_server_error_json() {
   let message = JSON.stringify({error: "Cannot get ye flask."});
   let method = "GET";
 
   let server = httpd_setup({"/foo": (request, response) => {
       response.setStatusLine(request.httpVersion, 400, "What wouldst thou deau?");
       response.bodyOutputStream.write(message, message.length);
     }
   });
@@ -158,17 +158,17 @@ add_task(function test_server_error_json
     do_throw("Expected an error");
   } catch(err) {
     do_check_eq("Cannot get ye flask.", err.error);
   }
 
   yield deferredStop(server);
 });
 
-add_task(function test_offset_after_request() {
+add_task(function* test_offset_after_request() {
   let message = "Ohai!";
   let method = "GET";
 
   let server = httpd_setup({"/foo": (request, response) => {
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.bodyOutputStream.write(message, message.length);
     }
   });
@@ -181,17 +181,17 @@ add_task(function test_offset_after_requ
 
   let response = yield client.request("/foo", method, TEST_CREDS);
   // Should be about an hour off
   do_check_true(Math.abs(client.localtimeOffsetMsec + HOUR_MS) < SECOND_MS);
 
   yield deferredStop(server);
 });
 
-add_task(function test_offset_in_hawk_header() {
+add_task(function* test_offset_in_hawk_header() {
   let message = "Ohai!";
   let method = "GET";
 
   let server = httpd_setup({
     "/first": function(request, response) {
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.bodyOutputStream.write(message, message.length);
     },
@@ -228,17 +228,17 @@ add_task(function test_offset_in_hawk_he
   // After the first server response, our offset is updated to -12 hours.
   // We should be safely in the window, now.
   do_check_true(Math.abs(client.localtimeOffsetMsec + 12 * HOUR_MS) < MINUTE_MS);
   yield client.request("/second", method, TEST_CREDS);
 
   yield deferredStop(server);
 });
 
-add_task(function test_2xx_success() {
+add_task(function* test_2xx_success() {
   // Just to ensure that we're not biased toward 200 OK for success
   let credentials = {
     id: "eyJleHBpcmVzIjogMTM2NTAxMDg5OC4x",
     key: "qTZf4ZFpAMpMoeSsX3zVRjiqmNs=",
     algorithm: "sha256"
   };
   let method = "GET";
 
@@ -252,17 +252,17 @@ add_task(function test_2xx_success() {
   let response = yield client.request("/foo", method, credentials);
 
   // Shouldn't be any content in a 202
   do_check_eq(response.body, "");
 
   yield deferredStop(server);
 });
 
-add_task(function test_retry_request_on_fail() {
+add_task(function* test_retry_request_on_fail() {
   let attempts = 0;
   let credentials = {
     id: "eyJleHBpcmVzIjogMTM2NTAxMDg5OC4x",
     key: "qTZf4ZFpAMpMoeSsX3zVRjiqmNs=",
     algorithm: "sha256"
   };
   let method = "GET";
 
@@ -307,17 +307,17 @@ add_task(function test_retry_request_on_
 
   // Request will have bad timestamp; client will retry once
   let response = yield client.request("/maybe", method, credentials);
   do_check_eq(response.body, "i love you!!!");
 
   yield deferredStop(server);
 });
 
-add_task(function test_multiple_401_retry_once() {
+add_task(function* test_multiple_401_retry_once() {
   // Like test_retry_request_on_fail, but always return a 401
   // and ensure that the client only retries once.
   let attempts = 0;
   let credentials = {
     id: "eyJleHBpcmVzIjogMTM2NTAxMDg5OC4x",
     key: "qTZf4ZFpAMpMoeSsX3zVRjiqmNs=",
     algorithm: "sha256"
   };
@@ -356,17 +356,17 @@ add_task(function test_multiple_401_retr
   } catch (err) {
     do_check_eq(err.code, 401);
   }
   do_check_eq(attempts, 2);
 
   yield deferredStop(server);
 });
 
-add_task(function test_500_no_retry() {
+add_task(function* test_500_no_retry() {
   // If we get a 500 error, the client should not retry (as it would with a
   // 401)
   let credentials = {
     id: "eyJleHBpcmVzIjogMTM2NTAxMDg5OC4x",
     key: "qTZf4ZFpAMpMoeSsX3zVRjiqmNs=",
     algorithm: "sha256"
   };
   let method = "GET";
@@ -396,17 +396,17 @@ add_task(function test_500_no_retry() {
     do_throw("Expected an error");
   } catch(err) {
     do_check_eq(err.code, 500);
   }
 
   yield deferredStop(server);
 });
 
-add_task(function test_401_then_500() {
+add_task(function* test_401_then_500() {
   // Like test_multiple_401_retry_once, but return a 500 to the
   // second request, ensuring that the promise is properly rejected
   // in client.request.
   let attempts = 0;
   let credentials = {
     id: "eyJleHBpcmVzIjogMTM2NTAxMDg5OC4x",
     key: "qTZf4ZFpAMpMoeSsX3zVRjiqmNs=",
     algorithm: "sha256"
@@ -460,17 +460,17 @@ add_task(function test_401_then_500() {
   } catch(err) {
     do_check_eq(err.code, 500);
   }
   do_check_eq(attempts, 2);
 
   yield deferredStop(server);
 });
 
-add_task(function throw_if_not_json_body() {
+add_task(function* throw_if_not_json_body() {
   let client = new HawkClient("https://example.com");
   try {
     yield client.request("/bogus", "GET", {}, "I am not json");
     do_throw("Expected an error");
   } catch(err) {
     do_check_true(!!err.message);
   }
 });
--- a/services/crypto/modules/WeaveCrypto.js
+++ b/services/crypto/modules/WeaveCrypto.js
@@ -1,21 +1,20 @@
 /* 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/. */
 
 this.EXPORTED_SYMBOLS = ["WeaveCrypto"];
 
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cr = Components.results;
+var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import('resource://gre/modules/AppConstants.jsm');
 
 /**
  * Shortcuts for some algorithm SEC OIDs.  Full list available here:
  * http://lxr.mozilla.org/seamonkey/source/security/nss/lib/util/secoidt.h
  */
 const DES_EDE3_CBC = 156;
 const AES_128_CBC  = 184;
 const AES_192_CBC  = 186;
@@ -127,26 +126,26 @@ WeaveCrypto.prototype = {
         // implicitly initialize NSS.
         Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
 
         // Open the NSS library.
         let path = ctypes.libraryName("nss3");
 
         // XXX really want to be able to pass specific dlopen flags here.
         var nsslib;
-#ifdef MOZ_NATIVE_NSS
-        // Search platform-dependent library paths for system NSS.
-        this.log("Trying NSS library without path");
-        nsslib = ctypes.open(path);
-#else
-        let file = Services.dirsvc.get("GreBinD", Ci.nsILocalFile);
-        file.append(path);
-        this.log("Trying NSS library with path " + file.path);
-        nsslib = ctypes.open(file.path);
-#endif
+        if (AppConstants.MOZ_NATIVE_NSS) {
+            // Search platform-dependent library paths for system NSS.
+            this.log("Trying NSS library without path");
+            nsslib = ctypes.open(path);
+        } else {
+            let file = Services.dirsvc.get("GreBinD", Ci.nsILocalFile);
+            file.append(path);
+            this.log("Trying NSS library with path " + file.path);
+            nsslib = ctypes.open(file.path);
+        }
 
         this.log("Initializing NSS types and function declarations...");
 
         this.nss = {};
         this.nss_t = {};
 
         // nsprpub/pr/include/prtypes.h#435
         // typedef PRIntn PRBool; --> int
--- a/services/crypto/moz.build
+++ b/services/crypto/moz.build
@@ -8,20 +8,14 @@ with Files('**'):
     BUG_COMPONENT = ('Mozilla Services', 'Firefox Sync: Crypto')
 
 DIRS += ['component']
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 EXTRA_JS_MODULES['services-crypto'] += [
     'modules/utils.js',
-]
-
-EXTRA_PP_JS_MODULES['services-crypto'] += [
     'modules/WeaveCrypto.js',
 ]
 
 EXTRA_COMPONENTS += [
     'cryptoComponents.manifest',
 ]
-
-if CONFIG['MOZ_NATIVE_NSS']:
-    DEFINES['MOZ_NATIVE_NSS'] = 1
--- a/services/sync/modules-testing/utils.js
+++ b/services/sync/modules-testing/utils.js
@@ -311,25 +311,25 @@ this.encryptPayload = function encryptPa
 this.add_identity_test = function(test, testFunction) {
   function note(what) {
     let msg = "running test " + testFunction.name + " with " + what + " identity manager";
     test.do_print(msg);
   }
   let ns = {};
   Cu.import("resource://services-sync/service.js", ns);
   // one task for the "old" identity manager.
-  test.add_task(function() {
+  test.add_task(function* () {
     note("sync");
     let oldIdentity = Status._authManager;
     ensureLegacyIdentityManager();
     yield testFunction();
     Status.__authManager = ns.Service.identity = oldIdentity;
   });
   // another task for the FxAccounts identity manager.
-  test.add_task(function() {
+  test.add_task(function* () {
     note("FxAccounts");
     let oldIdentity = Status._authManager;
     Status.__authManager = ns.Service.identity = new BrowserIDManager();
     yield testFunction();
     Status.__authManager = ns.Service.identity = oldIdentity;
   });
 }
 
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -689,17 +689,20 @@ this.BrowserIDManager.prototype = {
     let cb = Async.makeSpinningCallback();
     this._ensureValidToken().then(cb, cb);
     // Note that in failure states we return null, causing the request to be
     // made without authorization headers, thereby presumably causing a 401,
     // which causes Sync to log out. If we throw, this may not happen as
     // expected.
     try {
       cb.wait();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.error("Failed to fetch a token for authentication", ex);
       return null;
     }
     if (!this._token) {
       return null;
     }
     let credentials = {algorithm: "sha256",
                        id: this._token.id,
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -296,22 +296,26 @@ Store.prototype = {
    * @param  records Array of records to apply
    * @return Array of record IDs which did not apply cleanly
    */
   applyIncomingBatch: function (records) {
     let failed = [];
     for (let record of records) {
       try {
         this.applyIncoming(record);
-      } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) {
-        // This kind of exception should have a 'cause' attribute, which is an
-        // originating exception.
-        // ex.cause will carry its stack with it when rethrown.
-        throw ex.cause;
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (ex.code == Engine.prototype.eEngineAbortApplyIncoming) {
+          // This kind of exception should have a 'cause' attribute, which is an
+          // originating exception.
+          // ex.cause will carry its stack with it when rethrown.
+          throw ex.cause;
+        }
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.warn("Failed to apply incoming record " + record.id, ex);
         this.engine._noteApplyFailure();
         failed.push(record.id);
       }
     };
     return failed;
   },
 
@@ -985,17 +989,20 @@ SyncEngine.prototype = {
     // methods to signal that they would like processing of incoming records to
     // cease.
     let aborting = undefined;
 
     function doApplyBatch() {
       this._tracker.ignoreAll = true;
       try {
         failed = failed.concat(this._store.applyIncomingBatch(applyBatch));
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         // Catch any error that escapes from applyIncomingBatch. At present
         // those will all be abort events.
         this._log.warn("Got exception, aborting processIncoming", ex);
         aborting = ex;
       }
       this._tracker.ignoreAll = false;
       applyBatch = [];
     }
@@ -1033,27 +1040,33 @@ SyncEngine.prototype = {
       item.collection = self.name;
 
       // Remember which records were processed
       handled.push(item.id);
 
       try {
         try {
           item.decrypt(key);
-        } catch (ex if Utils.isHMACMismatch(ex)) {
+        } catch (ex) {
+          if (!Utils.isHMACMismatch(ex)) {
+            throw ex;
+          }
           let strategy = self.handleHMACMismatch(item, true);
           if (strategy == SyncEngine.kRecoveryStrategy.retry) {
             // You only get one retry.
             try {
               // Try decrypting again, typically because we've got new keys.
               self._log.info("Trying decrypt again...");
               key = self.service.collectionKeys.keyForCollection(self.name);
               item.decrypt(key);
               strategy = null;
-            } catch (ex if Utils.isHMACMismatch(ex)) {
+            } catch (ex) {
+              if (!Utils.isHMACMismatch(ex)) {
+                throw ex;
+              }
               strategy = self.handleHMACMismatch(item, false);
             }
           }
 
           switch (strategy) {
             case null:
               // Retry succeeded! No further handling.
               break;
@@ -1076,26 +1089,30 @@ SyncEngine.prototype = {
         self._noteApplyFailure();
         failed.push(item.id);
         return;
       }
 
       let shouldApply;
       try {
         shouldApply = self._reconcile(item);
-      } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) {
-        self._log.warn("Reconciliation failed: aborting incoming processing.");
-        self._noteApplyFailure();
-        failed.push(item.id);
-        aborting = ex.cause;
-      } catch (ex if !Async.isShutdownException(ex)) {
-        self._log.warn("Failed to reconcile incoming record " + item.id, ex);
-        self._noteApplyFailure();
-        failed.push(item.id);
-        return;
+      } catch (ex) {
+        if (ex.code == Engine.prototype.eEngineAbortApplyIncoming) {
+          self._log.warn("Reconciliation failed: aborting incoming processing.");
+          self._noteApplyFailure();
+          failed.push(item.id);
+          aborting = ex.cause;
+        } else if (!Async.isShutdownException(ex)) {
+          self._log.warn("Failed to reconcile incoming record " + item.id, ex);
+          self._noteApplyFailure();
+          failed.push(item.id);
+          return;
+        } else {
+          throw ex;
+        }
       }
 
       if (shouldApply) {
         count.applied++;
         applyBatch.push(item);
       } else {
         count.reconciled++;
         self._log.trace("Skipping reconciled incoming item " + item.id);
@@ -1466,17 +1483,20 @@ SyncEngine.prototype = {
         let ok = false;
         try {
           out = this._createRecord(id);
           if (this._log.level <= Log.Level.Trace)
             this._log.trace("Outgoing: " + out);
 
           out.encrypt(this.service.collectionKeys.keyForCollection(this.name));
           ok = true;
-        } catch (ex if !Async.isShutdownException(ex)) {
+        } catch (ex) {
+          if (Async.isShutdownException(ex)) {
+            throw ex;
+          }
           this._log.warn("Error creating record", ex);
         }
         if (ok) {
           postQueue.enqueue(out);
         }
         this._store._sleep(0);
       }
       postQueue.flush();
@@ -1552,17 +1572,20 @@ SyncEngine.prototype = {
       record.decrypt(key);
       canDecrypt = true;
     }.bind(this);
 
     // Any failure fetching/decrypting will just result in false
     try {
       this._log.trace("Trying to decrypt a record from the server..");
       test.get();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.debug("Failed test decrypt", ex);
     }
 
     return canDecrypt;
   },
 
   _resetClient: function () {
     this.resetLastSync();
--- a/services/sync/modules/engines/bookmarks.js
+++ b/services/sync/modules/engines/bookmarks.js
@@ -251,17 +251,20 @@ BookmarksEngine.prototype = {
       let stmt = this._store._getStmt(`
             SELECT h.url
             FROM moz_places h
             JOIN moz_bookmarks b ON h.id = b.fk
             WHERE b.id = :id`);
       stmt.params.id = id;
       let rows = Async.querySpinningly(stmt, ["url"]);
       url = rows.length == 0 ? "<not found>" : rows[0].url;
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       if (ex instanceof Ci.mozIStorageError) {
         url = `<failed: Storage error: ${ex.message} (${ex.result})>`;
       } else {
         url = `<failed: ${ex.toString()}>`;
       }
     }
     return url;
   },
@@ -409,17 +412,17 @@ BookmarksEngine.prototype = {
     this._log.trace("No dupe found for key " + key + "/" + altKey + ".");
     return undefined;
   },
 
   _syncStartup: function _syncStart() {
     SyncEngine.prototype._syncStartup.call(this);
 
     let cb = Async.makeSpinningCallback();
-    Task.spawn(function() {
+    Task.spawn(function* () {
       // For first-syncs, make a backup for the user to restore
       if (this.lastSync == 0) {
         this._log.debug("Bookmarks backup starting.");
         yield PlacesBackups.create(null, true);
         this._log.debug("Bookmarks backup done.");
       }
     }.bind(this)).then(
       cb, ex => {
@@ -435,17 +438,20 @@ BookmarksEngine.prototype = {
 
     this.__defineGetter__("_guidMap", function() {
       // Create a mapping of folder titles and separator positions to GUID.
       // We do this lazily so that we don't do any work unless we reconcile
       // incoming items.
       let guidMap;
       try {
         guidMap = this._buildGUIDMap();
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.warn("Error while building GUID map, skipping all other incoming items", ex);
         throw {code: Engine.prototype.eEngineAbortApplyIncoming,
                cause: ex};
       }
       delete this._guidMap;
       return this._guidMap = guidMap;
     });
 
@@ -1362,17 +1368,17 @@ BookmarksStore.prototype = {
       if (guid != "places" && guid != "tags")
         this._getChildren(guid, items);
     }
     return items;
   },
 
   wipe: function BStore_wipe() {
     let cb = Async.makeSpinningCallback();
-    Task.spawn(function() {
+    Task.spawn(function* () {
       // Save a backup before clearing out all bookmarks.
       yield PlacesBackups.create(null, true);
       for (let guid of kSpecialIds.guids)
         if (guid != "places") {
           let id = kSpecialIds.specialIdForGUID(guid);
           if (id)
             PlacesUtils.bookmarks.removeFolderChildren(id);
         }
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -218,17 +218,20 @@ HistoryStore.prototype = {
         if (record.deleted) {
           // Consider using nsIBrowserHistory::removePages() here.
           this.remove(record);
           // No further processing needed. Remove it from the list.
           shouldApply = false;
         } else {
           shouldApply = this._recordToPlaceInfo(record);
         }
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         failed.push(record.id);
         shouldApply = false;
       }
 
       if (shouldApply) {
         k += 1;
       }
     }
--- a/services/sync/modules/engines/passwords.js
+++ b/services/sync/modules/engines/passwords.js
@@ -63,17 +63,20 @@ PasswordEngine.prototype = {
           }
         } else {
           this._log.debug("Didn't find any passwords to delete");
         }
         // If there were no ids to delete, or we succeeded, or got a 400,
         // record success.
         Svc.Prefs.set("deletePwdFxA", true);
         Svc.Prefs.reset("deletePwd"); // The old prefname we previously used.
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.debug("Password deletes failed", ex);
       }
     }
   },
 
   _findDupe: function (item) {
     let login = this._store._nsLoginInfoFromRecord(item);
     if (!login) {
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -441,17 +441,20 @@ IdentityManager.prototype = {
    * allows us to avoid a network request for when we actually need the
    * migration info.
    */
   prefetchMigrationSentinel: function(service) {
     // Try and fetch the migration sentinel - it will end up in the recordManager
     // cache.
     try {
       service.recordManager.get(service.storageURL + "meta/fxa_credentials");
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.warn("Failed to pre-fetch the migration sentinel", ex);
     }
   },
 
   /**
    * Obtains the array of basic logins from nsiPasswordManager.
    */
   _getLogins: function _getLogins(realm) {
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -234,17 +234,20 @@ SyncScheduler.prototype = {
          Services.prefs.savePrefFile(null);
          Svc.Idle.addIdleObserver(this, Svc.Prefs.get("scheduler.idleTime"));
          Svc.Obs.add("wake_notification", this);
          break;
       case "weave:service:start-over":
          this.setDefaults();
          try {
            Svc.Idle.removeIdleObserver(this, Svc.Prefs.get("scheduler.idleTime"));
-         } catch (ex if (ex.result == Cr.NS_ERROR_FAILURE)) {
+         } catch (ex) {
+           if (ex.result != Cr.NS_ERROR_FAILURE) {
+             throw ex;
+           }
            // In all likelihood we didn't have an idle observer registered yet.
            // It's all good.
          }
          break;
       case "idle":
         this._log.trace("We're idle.");
         this.idle = true;
         // Adjust the interval for future syncs. This won't actually have any
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -233,17 +233,20 @@ RecordManager.prototype = {
       // Don't parse and save the record on failure
       if (!this.response.success)
         return null;
 
       let record = new this._recordType(url);
       record.deserialize(this.response);
 
       return this.set(url, record);
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.debug("Failed to import record", ex);
       return null;
     }
   },
 
   get: function RecordMgr_get(url) {
     // Use a url string as the key to the hash
     let spec = url.spec ? url.spec : url;
--- a/services/sync/modules/resource.js
+++ b/services/sync/modules/resource.js
@@ -391,17 +391,20 @@ Resource.prototype = {
       else
         cb(ret);
     }
 
     // The channel listener might get a failure code
     try {
       this._doRequest(action, data, callback);
       return Async.waitForSyncCallback(cb);
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       // Combine the channel stack with this request stack.  Need to create
       // a new error object for that.
       let error = Error(ex.message);
       error.result = ex.result;
       let chanStack = [];
       if (ex.stack)
         chanStack = ex.stack.trim().split(/\n/).slice(1);
       let requestStack = error.stack.split(/\n/).slice(1);
@@ -544,17 +547,20 @@ ChannelListener.prototype = {
       this._data += siStream.read(count);
     } catch (ex) {
       this._log.warn("Exception thrown reading " + count + " bytes from " + siStream + ".");
       throw ex;
     }
 
     try {
       this._onProgress();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.warn("Got exception calling onProgress handler during fetch of "
                      + req.URI.spec, ex);
       this._log.trace("Rethrowing; expect a failure code from the HTTP channel.");
       throw ex;
     }
 
     this.delayAbort();
   },
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -331,21 +331,23 @@ this.Utils = {
     if (that._log) {
       that._log.trace("Loading json from disk: " + filePath);
     }
 
     let json;
 
     try {
       json = yield CommonUtils.readJSON(path);
-    } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) {
-      // Ignore non-existent files.
     } catch (e) {
-      if (that._log) {
-        that._log.debug("Failed to load json", e);
+      if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
+        // Ignore non-existent files.
+      } else {
+        if (that._log) {
+          that._log.debug("Failed to load json", e);
+        }
       }
     }
 
     callback.call(that, json);
   }),
 
   /**
    * Save a json-able object to disk in the profile directory.
--- a/services/sync/tests/unit/test_bookmark_engine.js
+++ b/services/sync/tests/unit/test_bookmark_engine.js
@@ -162,17 +162,17 @@ add_test(function test_processIncoming_e
   } finally {
     store.wipe();
     Svc.Prefs.resetBranch("");
     Service.recordManager.clearCache();
     server.stop(run_next_test);
   }
 });
 
-add_task(function test_restorePromptsReupload() {
+add_task(function* test_restorePromptsReupload() {
   _("Ensure that restoring from a backup will reupload all records.");
   let engine = new BookmarksEngine(Service);
   let store  = engine._store;
   let server = serverForFoo(engine);
   new SyncTestingInfrastructure(server.server);
 
   let collection = server.user("foo").collection("bookmarks");
 
--- a/services/sync/tests/unit/test_browserid_identity.js
+++ b/services/sync/tests/unit/test_browserid_identity.js
@@ -71,27 +71,27 @@ function run_test() {
 add_test(function test_initial_state() {
     _("Verify initial state");
     do_check_false(!!browseridManager._token);
     do_check_false(browseridManager.hasValidToken());
     run_next_test();
   }
 );
 
-add_task(function test_initialializeWithCurrentIdentity() {
+add_task(function* test_initialializeWithCurrentIdentity() {
     _("Verify start after initializeWithCurrentIdentity");
     browseridManager.initializeWithCurrentIdentity();
     yield browseridManager.whenReadyToAuthenticate.promise;
     do_check_true(!!browseridManager._token);
     do_check_true(browseridManager.hasValidToken());
     do_check_eq(browseridManager.account, identityConfig.fxaccount.user.email);
   }
 );
 
-add_task(function test_initialializeWithAuthErrorAndDeletedAccount() {
+add_task(function* test_initialializeWithAuthErrorAndDeletedAccount() {
     _("Verify sync unpair after initializeWithCurrentIdentity with auth error + account deleted");
 
     browseridManager._fxaService.internal.initialize();
 
     let fetchTokenForUserCalled = false;
     let accountStatusCalled = false;
 
     let MockFxAccountsClient = function() {
@@ -122,17 +122,17 @@ add_task(function test_initialializeWith
     do_check_true(accountStatusCalled);
     do_check_false(browseridManager.account);
     do_check_false(browseridManager._token);
     do_check_false(browseridManager.hasValidToken());
     do_check_false(browseridManager.account);
     browseridManager._fetchTokenForUser = oldFetchTokenForUser;
 });
 
-add_task(function test_initialializeWithNoKeys() {
+add_task(function* test_initialializeWithNoKeys() {
     _("Verify start after initializeWithCurrentIdentity without kA, kB or keyFetchToken");
     let identityConfig = makeIdentityConfig();
     delete identityConfig.fxaccount.user.kA;
     delete identityConfig.fxaccount.user.kB;
     // there's no keyFetchToken by default, so the initialize should fail.
     configureFxAccountIdentity(browseridManager, identityConfig);
 
     yield browseridManager.initializeWithCurrentIdentity();
@@ -291,17 +291,17 @@ add_test(function test_RESTResourceAuthe
   // window.
   do_check_eq(getTimestamp(authHeader), now - 12 * HOUR_MS);
   do_check_true(
       (getTimestampDelta(authHeader, now) - 12 * HOUR_MS) < 2 * MINUTE_MS);
 
   run_next_test();
 });
 
-add_task(function test_ensureLoggedIn() {
+add_task(function* test_ensureLoggedIn() {
   configureFxAccountIdentity(browseridManager);
   yield browseridManager.initializeWithCurrentIdentity();
   yield browseridManager.whenReadyToAuthenticate.promise;
   Assert.equal(Status.login, LOGIN_SUCCEEDED, "original initialize worked");
   yield browseridManager.ensureLoggedIn();
   Assert.equal(Status.login, LOGIN_SUCCEEDED, "original ensureLoggedIn worked");
   Assert.ok(browseridManager._shouldHaveSyncKeyBundle,
             "_shouldHaveSyncKeyBundle should always be true after ensureLogin completes.");
@@ -389,17 +389,17 @@ add_test(function test_computeXClientSta
 
   let bidUser = new BrowserIDManager();
   let header = bidUser._computeXClientState(kB);
 
   do_check_eq(header, "6ae94683571c7a7c54dab4700aa3995f");
   run_next_test();
 });
 
-add_task(function test_getTokenErrors() {
+add_task(function* test_getTokenErrors() {
   _("BrowserIDManager correctly handles various failures to get a token.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   initializeIdentityWithTokenServerResponse({
     status: 401,
     headers: {"content-type": "application/json"},
     body: JSON.stringify({}),
   });
@@ -428,17 +428,17 @@ add_task(function test_getTokenErrors() 
   yield Assert.rejects(browseridManager.whenReadyToAuthenticate.promise,
                        "should reject due to non-JSON response");
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login state is LOGIN_FAILED_NETWORK_ERROR");
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for invalid responses");
 });
 
-add_task(function test_getTokenErrorWithRetry() {
+add_task(function* test_getTokenErrorWithRetry() {
   _("tokenserver sends an observer notification on various backoff headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a Retry-After header.");
   initializeIdentityWithTokenServerResponse({
     status: 503,
@@ -476,17 +476,17 @@ add_task(function test_getTokenErrorWith
 
   // The observer should have fired - check it got the value in the response.
   Assert.ok(Status.backoffInterval >= 200000);
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503/backoff response from FxA");
 });
 
-add_task(function test_getKeysErrorWithBackoff() {
+add_task(function* test_getKeysErrorWithBackoff() {
   _("Auth server (via hawk) sends an observer notification on backoff headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a X-Backoff header.");
 
   let config = makeIdentityConfig();
@@ -513,17 +513,17 @@ add_task(function test_getKeysErrorWithB
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login was rejected");
   // Sync will have the value in ms with some slop - so check it is at least that.
   Assert.ok(Status.backoffInterval >= 100000);
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getKeysErrorWithRetry() {
+add_task(function* test_getKeysErrorWithRetry() {
   _("Auth server (via hawk) sends an observer notification on retry headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a Retry-After header.");
 
   let config = makeIdentityConfig();
@@ -550,17 +550,17 @@ add_task(function test_getKeysErrorWithR
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login was rejected");
   // Sync will have the value in ms with some slop - so check it is at least that.
   Assert.ok(Status.backoffInterval >= 100000);
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getHAWKErrors() {
+add_task(function* test_getHAWKErrors() {
   _("BrowserIDManager correctly handles various HAWK failures.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   let config = makeIdentityConfig();
   yield initializeIdentityWithHAWKResponseFactory(config, function(method, data, uri) {
     Assert.equal(method, "post");
     Assert.equal(uri, "http://mockedserver:9999/certificate/sign")
     return {
@@ -589,17 +589,17 @@ add_task(function test_getHAWKErrors() {
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login state is LOGIN_FAILED_NETWORK_ERROR");
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for invalid response from FxA");
 });
 
-add_task(function test_getGetKeysFailing401() {
+add_task(function* test_getGetKeysFailing401() {
   _("BrowserIDManager correctly handles 401 responses fetching keys.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   let config = makeIdentityConfig();
   // We want no kA or kB so we attempt to fetch them.
   delete config.fxaccount.user.kA;
   delete config.fxaccount.user.kB;
   config.fxaccount.user.keyFetchToken = "keyfetchtoken";
@@ -613,17 +613,17 @@ add_task(function test_getGetKeysFailing
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_LOGIN_REJECTED, "login was rejected");
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 1, "Should record key fetch errors for 401 from FxA");
 });
 
-add_task(function test_getGetKeysFailing503() {
+add_task(function* test_getGetKeysFailing503() {
   _("BrowserIDManager correctly handles 5XX responses fetching keys.");
 
   _("Arrange for a 503 - Sync should reflect a network error.");
   let config = makeIdentityConfig();
   // We want no kA or kB so we attempt to fetch them.
   delete config.fxaccount.user.kA;
   delete config.fxaccount.user.kB;
   config.fxaccount.user.keyFetchToken = "keyfetchtoken";
@@ -637,17 +637,17 @@ add_task(function test_getGetKeysFailing
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "state reflects network error");
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getKeysMissing() {
+add_task(function* test_getKeysMissing() {
   _("BrowserIDManager correctly handles getKeys succeeding but not returning keys.");
 
   let browseridManager = new BrowserIDManager();
   let identityConfig = makeIdentityConfig();
   // our mock identity config already has kA and kB - remove them or we never
   // try and fetch them.
   delete identityConfig.fxaccount.user.kA;
   delete identityConfig.fxaccount.user.kB;
--- a/services/sync/tests/unit/test_collections_recovery.js
+++ b/services/sync/tests/unit/test_collections_recovery.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Verify that we wipe the server if we have to regenerate keys.
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
-add_identity_test(this, function test_missing_crypto_collection() {
+add_identity_test(this, function* test_missing_crypto_collection() {
   let johnHelper = track_collections_helper();
   let johnU      = johnHelper.with_updated_collection;
   let johnColls  = johnHelper.collections;
 
   let empty = false;
   function maybe_empty(handler) {
     return function (request, response) {
       if (empty) {
--- a/services/sync/tests/unit/test_corrupt_keys.js
+++ b/services/sync/tests/unit/test_corrupt_keys.js
@@ -9,17 +9,17 @@ Cu.import("resource://services-sync/engi
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 Cu.import("resource://gre/modules/Promise.jsm");
 
-add_task(function test_locally_changed_keys() {
+add_task(function* test_locally_changed_keys() {
   let passphrase = "abcdeabcdeabcdeabcdeabcdea";
 
   let hmacErrorCount = 0;
   function counting(f) {
     return function() {
       hmacErrorCount++;
       return f.call(this);
     };
--- a/services/sync/tests/unit/test_errorhandler.js
+++ b/services/sync/tests/unit/test_errorhandler.js
@@ -156,17 +156,17 @@ function generateAndUploadKeys() {
 
 function clean() {
   Service.startOver();
   Status.resetSync();
   Status.resetBackoff();
   errorHandler.didReportProlongedError = false;
 }
 
-add_identity_test(this, function test_401_logout() {
+add_identity_test(this, function* test_401_logout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
 
@@ -201,17 +201,17 @@ add_identity_test(this, function test_40
   Service._updateCachedURLs();
 
   _("Starting first sync.");
   Service.sync();
   _("First sync done.");
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_credentials_changed_logout() {
+add_identity_test(this, function* test_credentials_changed_logout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
 
@@ -451,17 +451,17 @@ add_identity_test(this, function test_sh
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.login = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
   do_check_false(errorHandler.didReportProlongedError);
 });
 
-add_identity_test(this, function test_shouldReportError_master_password() {
+add_identity_test(this, function* test_shouldReportError_master_password() {
   _("Test error ignored due to locked master password");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Monkey patch Service.verifyLogin to imitate
   // master password being locked.
   Service._verifyLogin = Service.verifyLogin;
   Service.verifyLogin = function () {
@@ -496,17 +496,17 @@ add_identity_test(this, function test_sh
   // But any other status with a missing clusterURL is treated as a mid-sync
   // 401 (ie, should be treated as a node reassignment)
   Status.login = LOGIN_SUCCEEDED;
   do_check_false(errorHandler.shouldReportError());
 });
 
 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
 // an fxaccounts environment?
-add_task(function test_login_syncAndReportErrors_non_network_error() {
+add_task(function* test_login_syncAndReportErrors_non_network_error() {
   // Test non-network errors are reported
   // when calling syncAndReportErrors
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
@@ -517,17 +517,17 @@ add_task(function test_login_syncAndRepo
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_sync_syncAndReportErrors_non_network_error() {
+add_identity_test(this, function* test_sync_syncAndReportErrors_non_network_error() {
   // Test non-network errors are reported
   // when calling syncAndReportErrors
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
@@ -546,17 +546,17 @@ add_identity_test(this, function test_sy
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
 // an fxaccounts environment?
-add_task(function test_login_syncAndReportErrors_prolonged_non_network_error() {
+add_task(function* test_login_syncAndReportErrors_prolonged_non_network_error() {
   // Test prolonged, non-network errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
@@ -567,17 +567,17 @@ add_task(function test_login_syncAndRepo
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_sync_syncAndReportErrors_prolonged_non_network_error() {
+add_identity_test(this, function* test_sync_syncAndReportErrors_prolonged_non_network_error() {
   // Test prolonged, non-network errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
@@ -594,17 +594,17 @@ add_identity_test(this, function test_sy
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_syncAndReportErrors_network_error() {
+add_identity_test(this, function* test_login_syncAndReportErrors_network_error() {
   // Test network errors are reported when calling syncAndReportErrors.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -632,17 +632,17 @@ add_test(function test_sync_syncAndRepor
     clean();
     run_next_test();
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
 });
 
-add_identity_test(this, function test_login_syncAndReportErrors_prolonged_network_error() {
+add_identity_test(this, function* test_login_syncAndReportErrors_prolonged_network_error() {
   // Test prolonged, network errors are reported
   // when calling syncAndReportErrors.
   yield configureIdentity({username: "johndoe"});
 
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
@@ -672,17 +672,17 @@ add_test(function test_sync_syncAndRepor
     clean();
     run_next_test();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
 });
 
-add_task(function test_login_prolonged_non_network_error() {
+add_task(function* test_login_prolonged_non_network_error() {
   // Test prolonged, non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -693,17 +693,17 @@ add_task(function test_login_prolonged_n
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_prolonged_non_network_error() {
+add_task(function* test_sync_prolonged_non_network_error() {
   // Test prolonged, non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
@@ -720,17 +720,17 @@ add_task(function test_sync_prolonged_no
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_prolonged_network_error() {
+add_identity_test(this, function* test_login_prolonged_network_error() {
   // Test prolonged, network errors are reported
   yield configureIdentity({username: "johndoe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -759,17 +759,17 @@ add_test(function test_sync_prolonged_ne
     clean();
     run_next_test();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
 });
 
-add_task(function test_login_non_network_error() {
+add_task(function* test_login_non_network_error() {
   // Test non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -780,17 +780,17 @@ add_task(function test_login_non_network
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_non_network_error() {
+add_task(function* test_sync_non_network_error() {
   // Test non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
@@ -807,17 +807,17 @@ add_task(function test_sync_non_network_
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_network_error() {
+add_identity_test(this, function* test_login_network_error() {
   yield configureIdentity({username: "johndoe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   // Test network errors are not reported.
   Svc.Obs.add("weave:ui:clear-error", function onClearError() {
     Svc.Obs.remove("weave:ui:clear-error", onClearError);
@@ -848,17 +848,17 @@ add_test(function test_sync_network_erro
     clean();
     run_next_test();
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
 });
 
-add_identity_test(this, function test_sync_server_maintenance_error() {
+add_identity_test(this, function* test_sync_server_maintenance_error() {
   // Test server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 503,
@@ -884,17 +884,17 @@ add_identity_test(this, function test_sy
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_server_maintenance_error() {
   // Test info/collections server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   Service.username = "broken.info";
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -928,17 +928,17 @@ add_identity_test(this, function test_in
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_server_maintenance_error() {
   // Test meta/global server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -971,17 +971,17 @@ add_identity_test(this, function test_me
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_crypto_keys_login_server_maintenance_error() {
+add_identity_test(this, function* test_crypto_keys_login_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1017,17 +1017,17 @@ add_identity_test(this, function test_cr
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_prolonged_server_maintenance_error() {
+add_task(function* test_sync_prolonged_server_maintenance_error() {
   // Test prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 503,
@@ -1046,17 +1046,17 @@ add_task(function test_sync_prolonged_se
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_info_collections_login_prolonged_server_maintenance_error(){
   // Test info/collections prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1082,17 +1082,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_meta_global_login_prolonged_server_maintenance_error(){
   // Test meta/global prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1118,17 +1118,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_download_crypto_keys_login_prolonged_server_maintenance_error(){
   // Test crypto/keys prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
   // Force re-download of keys
@@ -1156,17 +1156,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
   // Test crypto/keys prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1192,17 +1192,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_wipeServer_login_prolonged_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping the server.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1229,17 +1229,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeRemote_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_wipeRemote_prolonged_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping all remote devices.
   let server = sync_httpd_setup();
 
   server.registerPathHandler("/1.1/broken.wipe/storage/catapult", service_unavailable);
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1273,17 +1273,17 @@ add_identity_test(this, function test_wi
   do_check_eq(Status.service, STATUS_OK);
 
   Svc.Prefs.set("firstSync", "wipeRemote");
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_syncAndReportErrors_server_maintenance_error() {
+add_task(function* test_sync_syncAndReportErrors_server_maintenance_error() {
   // Test server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
@@ -1303,17 +1303,17 @@ add_task(function test_sync_syncAndRepor
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
   // Test info/collections server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1340,17 +1340,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
   // Test meta/global server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1377,17 +1377,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1416,17 +1416,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1453,17 +1453,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1490,17 +1490,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
+add_identity_test(this, function* test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping all remote devices.
   let server = sync_httpd_setup();
 
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
   generateAndUploadKeys();
@@ -1533,17 +1533,17 @@ add_identity_test(this, function test_wi
   do_check_eq(Status.service, STATUS_OK);
 
   Svc.Prefs.set("firstSync", "wipeRemote");
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_task(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_task(function* test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test prolonged server maintenance errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
@@ -1565,17 +1565,17 @@ add_task(function test_sync_syncAndRepor
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test info/collections server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1604,17 +1604,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test meta/global server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1643,17 +1643,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1684,17 +1684,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1723,17 +1723,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1762,17 +1762,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_task(function test_sync_engine_generic_fail() {
+add_task(function* test_sync_engine_generic_fail() {
   let server = sync_httpd_setup();
 
   let engine = engine