merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 16 Feb 2016 11:51:26 +0100
changeset 331237 6ea654cad929c9bedd8a4161a182b6189fbeae6a
parent 331224 fb7ceaf4b009243423cdaf1077adbb6c609b22e5 (current diff)
parent 331236 53029769feefdb9e01b239c9c9e7bb3b089b1019 (diff)
child 331238 c9b53332083e78246c1a836bf9ade76a4a0bd040
child 331239 03e86899b4abb489994d920e622e5fab8aac94b1
child 331243 86f41b2e13e30d42c51503d454782478c56d0dbf
child 331244 2fa4f637edb1937846cffcc650a0751db679166e
child 331245 8179c9b0c39c099920dd4441e116db300cd8d99e
child 331247 68f6b26b986d14c8e20b870487b98cd2c9d8e1b6
child 331267 236914496758842d722c005a4effb39399889f29
child 331268 a219ac6092a872d979ed0bb0543f4df7c62eed4b
child 331269 06655cf94beb42d31827089224d92a6880d0aaad
child 331273 cf16002d74e4a8ae9a8c5e7ef2de7e9876c61f3f
child 331286 d73b4d5f5d259b9015d7af8f7bfaae81d33529ec
child 331334 3999ad4438ab1cc3ee66c4b31b43b390368950ce
child 331335 f6ddd16dfeba55b0b882c2f88d5f543a3b56ab18
child 331362 b028097b6fa4a25f7e93bb90bc027f30e2c68248
child 331368 6bc3e07168dac8d3449265d85f9d1485175fd2ac
child 331371 38e46b3cb4ea346a4d6382c627fc926ba33933ab
child 331379 bc83b76bf6eea5e2e450eca4aacee5685373aed7
child 331386 7347aab8183d20a9c79da4eb4b1e9a0eb03f596e
child 331439 8d714ee220fd68840d09d3c4efff9d80b9304666
child 331442 87f7483ba44872a642962978f887abfed90f4155
child 331461 0759778b48ecd8e6602f63cbb50184a6d95300f6
child 331462 bf2d24f1565441dd47b6556f262d597d054e5c0b
child 331463 20d5f91e4ec56185dfc72039708af79564d7386a
child 331464 35ca91f3ab19d33ee60579f5e3e309830c89e8df
child 331465 26bb76809c0aa928f6e444540be6c100742e1756
child 331549 c9ff6f1553205b7bcbce17179a2b7931941c7a38
child 331551 44d7669d7a66d75b5cd40bf6e93584ec8b135f04
child 331557 7d085c252a36dd7fe05d1452fae8619fa14da0f5
child 331682 f9acfe711678f232e60beb2452a69218484dc013
child 331871 0c6861b50d13f449a95f03b77ff4f889cacfc6c7
child 331877 4f2fc07e4f89cfa37c4530a6454196f2e776ff2f
child 331969 dcdd07cfe92236a462f3ce473e2de6de56cca547
child 332002 5f61ab1398e23b63ff776082dcfb80f3a46887ec
child 332858 5687493a78a3b4560ebb470ab16f3f1bfa1ecdd9
child 332859 67e71c7e4e016752f2afbb99edaeceb84f6fc184
child 333268 cd230a5396c04a384e320d9b514882432231f829
child 333270 165de4c7316e7fe64b81efab894c5113a183ca58
child 334040 2492d7793b54634232d97732226c7204ac720922
child 334419 aff5b5e4732ce76267e119b4e104cd53f2d3d0f0
child 334428 1a563c36d05b0fdb7e1de613025164224f8ada3a
child 334545 47b21673d8db45262b4d50610b54309fc6d9f2eb
child 334789 d4bbb19fa26c0af335eee717484c8ec508474956
child 334791 43e4794b05ab487ec9088dfa6d1e9d9539b9917b
child 336458 e901b566c3dc4bb4b1ace430b8a185d4ed2d6a1c
child 336461 a92e61d926477cd18a42eadf43154cf328054d5f
child 336465 8cfe961786c16bc6a5b6a932637ec891f6ee6f80
child 336474 897e99d19c9547efb7e555bcf160f1f7092eaecc
child 336480 0be160c74dabd0662bb82a2aeaefcc81dd0e8aed
child 337305 06286ad1fd7ab0c402bfafcfb53baa07b84d0ad7
child 338514 9bc9bd6cc7079ce4ee47ddc7b5a9fe4a0327fca0
child 338526 6af103a97ccdfa439912bf8d014991bda5584f18
child 338535 e71fbdbd931e900f4c350467a0f4221e5c988ee7
child 338574 b223bf55cf87981cc36af14afa375a47f86fd548
child 339877 3e198559c20a7018018171060900dbe9ba842a0b
child 339892 154369a68f68fd81fb2981819b4188a514e94913
child 351941 6f632662a9cf1ddb5a24b4de3bb086d091905dfd
push id10938
push userBogdan.Postelnicu@softvision.ro
push dateTue, 16 Feb 2016 15:52:05 +0000
reviewersmerge
milestone47.0a1
merge mozilla-inbound to mozilla-central a=merge
browser/base/content/browser.js
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -74,16 +74,20 @@ const TAP_MAX_RADIUS = 0.2;
 // consequent pointer move lines.
 const DIRECTNESS_COEFF = 1.44;
 // The virtual touch ID generated by a mouse event.
 const MOUSE_ID = 'mouse';
 // Amount in inches from the edges of the screen for it to be an edge swipe
 const EDGE = 0.1;
 // Multiply timeouts by this constant, x2 works great too for slower users.
 const TIMEOUT_MULTIPLIER = 1;
+// A single pointer down/up sequence periodically precedes the tripple swipe
+// gesture on Android. This delay acounts for that.
+const IS_ANDROID = Utils.MozBuildApp === 'mobile/android' &&
+  Utils.AndroidSdkVersion >= 14;
 
 /**
  * A point object containing distance travelled data.
  * @param {Object} aPoint A point object that looks like: {
  *   x: x coordinate in pixels,
  *   y: y coordinate in pixels
  * }
  */
@@ -197,23 +201,23 @@ this.GestureTracker = { // jshint ignore
 
   /**
    * Create a new gesture object and attach resolution handler to it as well as
    * handle the incoming pointer event.
    * @param  {Object} aDetail A new pointer event detail.
    * @param  {Number} aTimeStamp A new pointer event timeStamp.
    * @param  {Function} aGesture A gesture constructor (default: Tap).
    */
-  _init: function GestureTracker__init(aDetail, aTimeStamp, aGesture = Tap) {
+  _init: function GestureTracker__init(aDetail, aTimeStamp, aGesture) {
     // Only create a new gesture on |pointerdown| event.
     if (aDetail.type !== 'pointerdown') {
       return;
     }
     let points = aDetail.points;
-    let GestureConstructor = aGesture;
+    let GestureConstructor = aGesture || (IS_ANDROID ? DoubleTap : Tap);
     this._create(GestureConstructor);
     this._update(aDetail, aTimeStamp);
   },
 
   /**
    * Handle the incoming pointer event with the existing gesture object(if
    * present) or with the newly created one.
    * @param  {Object} aDetail A new pointer event detail.
--- a/addon-sdk/source/lib/sdk/io/fs.js
+++ b/addon-sdk/source/lib/sdk/io/fs.js
@@ -116,18 +116,18 @@ function remove(path, recursive) {
   else {
     throw FSError("remove", "ENOENT", 34, path);
   }
 }
 
 /**
  * Utility function to convert either an octal number or string
  * into an octal number
- * 0777 => 0777
- * "0644" => 0644
+ * 0777 => 0o777
+ * "0644" => 0o644
  */
 function Mode(mode, fallback) {
   return isString(mode) ? parseInt(mode, 8) : mode || fallback;
 }
 function Flags(flag) {
   return !isString(flag) ? flag :
          FLAGS[flag] || Error("Unknown file open flag: " + flag);
 }
--- a/b2g/components/HelperAppDialog.js
+++ b/b2g/components/HelperAppDialog.js
@@ -84,28 +84,28 @@ HelperAppLauncherDialog.prototype = {
           else
             aLocalFile.leafName = aLocalFile.leafName.replace(/(\.[^\.]*)?$/, "(2)$&");
         }
         else {
           // replace the last (n) in the filename with (n+1)
           aLocalFile.leafName = aLocalFile.leafName.replace(/^(.*\()\d+\)/, "$1" + (collisionCount+1) + ")");
         }
       }
-      aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+      aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     }
     catch (e) {
       dump("*** exception in makeFileUnique: " + e + "\n");
 
       if (e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED)
         throw e;
 
       if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) {
         aLocalFile.append("unnamed");
         if (aLocalFile.exists())
-          aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+          aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
       }
     }
   },
 
   isUsableDirectory: function(aDirectory) {
     return aDirectory.exists() &&
            aDirectory.isDirectory() &&
            aDirectory.isWritable();
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -319,19 +319,17 @@
 @RESPATH@/components/storage.xpt
 @RESPATH@/components/telemetry.xpt
 @RESPATH@/components/toolkit_asyncshutdown.xpt
 @RESPATH@/components/toolkit_filewatcher.xpt
 @RESPATH@/components/toolkit_finalizationwitness.xpt
 @RESPATH@/components/toolkit_formautofill.xpt
 @RESPATH@/components/toolkit_osfile.xpt
 @RESPATH@/components/toolkit_securityreporter.xpt
-#ifdef NIGHTLY_BUILD
 @RESPATH@/components/toolkit_perfmonitoring.xpt
-#endif
 @RESPATH@/components/toolkit_xulstore.xpt
 @RESPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @RESPATH@/components/toolkitremote.xpt
 #endif
 @RESPATH@/components/txtsvc.xpt
 @RESPATH@/components/txmgr.xpt
 #ifdef MOZ_USE_NATIVE_UCONV
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -56,16 +56,18 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "gAboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
   return Services.strings.createBundle('chrome://browser/locale/browser.properties');
 });
+XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
+                                  "resource://gre/modules/AddonWatcher.jsm");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
 var gLastBrowserCharset = null;
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
 var gContextMenu = null; // nsContextMenu instance
 var gMultiProcessBrowser =
@@ -1343,16 +1345,19 @@ var gBrowserInit = {
         return;
       }
 
       // Enable the Restore Last Session command if needed
       RestoreLastSessionObserver.init();
 
       SocialUI.init();
 
+      // Start monitoring slow add-ons
+      AddonWatcher.init();
+
       // Telemetry for master-password - we do this after 5 seconds as it
       // can cause IO if NSS/PSM has not already initialized.
       setTimeout(() => {
         if (window.closed) {
           return;
         }
         let secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"]
                        .getService(Ci.nsIPKCS11ModuleDB);
@@ -3975,17 +3980,17 @@ function updateEditUIVisibility()
  * living on the tab's docShell.
  *
  * @param event
  *        A click event on a userContext File Menu option
  */
 function openNewUserContextTab(event)
 {
   openUILinkIn(BROWSER_NEW_TAB_URL, "tab", {
-    userContextId: event.target.getAttribute('usercontextid'),
+    userContextId: parseInt(event.target.getAttribute('usercontextid')),
   });
 }
 
 /**
  * Updates File Menu User Context UI visibility depending on
  * privacy.userContext.enabled pref state.
  */
 function updateUserContextUIVisibility()
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -978,17 +978,17 @@ nsContextMenu.prototype = {
         sm.checkSameOriginURI(referrerURI, targetURI, false);
         persistAllowMixedContentInChildTab = true;
       }
       catch (e) { }
     }
 
     let params = this._openLinkInParameters({
       allowMixedContent: persistAllowMixedContentInChildTab,
-      userContextId: event.target.getAttribute('usercontextid'),
+      userContextId: parseInt(event.target.getAttribute('usercontextid')),
     });
     openLinkIn(this.linkURL, "tab", params);
   },
 
   // open URL in current tab
   openLinkInCurrent: function() {
     urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "current", this._openLinkInParameters());
--- a/browser/base/content/sync/utils.js
+++ b/browser/base/content/sync/utils.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-// Equivalent to 0600 permissions; used for saved Sync Recovery Key.
+// Equivalent to 0o600 permissions; used for saved Sync Recovery Key.
 // This constant can be replaced when the equivalent values are available to
 // chrome JS; see Bug 433295 and Bug 757351.
 const PERMISSIONS_RWUSR = 0x180;
 
 // Weave should always exist before before this file gets included.
 var gSyncUtils = {
   get bundle() {
     delete this.bundle;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1721,18 +1721,19 @@
             let b = document.createElementNS(NS_XUL, "browser");
             b.permanentKey = {};
             b.setAttribute("type", "content-targetable");
             b.setAttribute("message", "true");
             b.setAttribute("messagemanagergroup", "browsers");
             b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
             b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
 
-            if (userContextId)
+            if (userContextId) {
               b.setAttribute("usercontextid", userContextId);
+            }
 
             if (remote)
               b.setAttribute("remote", "true");
 
             if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
               b.setAttribute("showresizer", "true");
             }
 
@@ -6267,18 +6268,23 @@
         ]]>
         </body>
       </method>
 
       <method name="setUserContextId">
         <parameter name="aUserContextId"/>
         <body>
         <![CDATA[
-          this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
-          this.setAttribute("usercontextid", aUserContextId);
+          if (aUserContextId) {
+            this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
+            this.setAttribute("usercontextid", aUserContextId);
+          } else {
+            this.linkedBrowser.removeAttribute("usercontextid");
+            this.removeAttribute("usercontextid");
+          }
         ]]>
         </body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="mouseover"><![CDATA[
         let anonid = event.originalTarget.getAttribute("anonid");
--- a/browser/base/content/test/general/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_link-perwindowpb.js
@@ -195,13 +195,13 @@ Cc["@mozilla.org/moz/jssubscript-loader;
 
 function createTemporarySaveDirectory() {
   var saveDir = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIProperties)
                   .get("TmpD", Ci.nsIFile);
   saveDir.append("testsavedir");
   if (!saveDir.exists()) {
     info("create testsavedir!");
-    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   }
   info("return from createTempSaveDir: " + saveDir.path);
   return saveDir;
 }
--- a/browser/base/content/test/general/browser_save_link_when_window_navigates.js
+++ b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
@@ -15,17 +15,17 @@ Cc["@mozilla.org/moz/jssubscript-loader;
 
 function createTemporarySaveDirectory() {
   var saveDir = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIProperties)
                   .get("TmpD", Ci.nsIFile);
   saveDir.append("testsavedir");
   if (!saveDir.exists()) {
     info("create testsavedir!");
-    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   }
   info("return from createTempSaveDir: " + saveDir.path);
   return saveDir;
 }
 
 function triggerSave(aWindow, aCallback) {
   info("started triggerSave, persite downloads: " + (Services.prefs.getBoolPref(SAVE_PER_SITE_PREF) ? "on" : "off"));
   var fileName;
--- a/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
@@ -48,17 +48,17 @@ function test() {
   }
 
   function createTemporarySaveDirectory() {
     var saveDir = Cc["@mozilla.org/file/directory_service;1"]
                     .getService(Ci.nsIProperties)
                     .get("TmpD", Ci.nsIFile);
     saveDir.append("testsavedir");
     if (!saveDir.exists())
-      saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+      saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
     return saveDir;
   }
 
   function doTest(aIsPrivateMode, aWindow, aCallback) {
     function contextMenuOpened(event) {
       cache.clear();
 
       aWindow.document.removeEventListener("popupshown", contextMenuOpened);
--- a/browser/base/content/test/general/browser_save_video.js
+++ b/browser/base/content/test/general/browser_save_video.js
@@ -77,11 +77,11 @@ Cc["@mozilla.org/moz/jssubscript-loader;
                  this);
 
 function createTemporarySaveDirectory() {
   var saveDir = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIProperties)
                   .get("TmpD", Ci.nsIFile);
   saveDir.append("testsavedir");
   if (!saveDir.exists())
-    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   return saveDir;
 }
--- a/browser/base/content/test/general/browser_save_video_frame.js
+++ b/browser/base/content/test/general/browser_save_video_frame.js
@@ -19,17 +19,17 @@ Cc["@mozilla.org/moz/jssubscript-loader;
  * @return nsIFile
  */
 function createTemporarySaveDirectory() {
   let saveDir = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIProperties)
                   .get("TmpD", Ci.nsIFile);
   saveDir.append("testsavedir");
   if (!saveDir.exists())
-    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   return saveDir;
 }
 /**
  * MockTransfer exposes a "mockTransferCallback" global which
  * allows us to define a callback to be called once the mock file
  * selector has selected where to save the file.
  */
 function waitForTransferComplete() {
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -538,17 +538,16 @@ BrowserGlue.prototype = {
     }
     os.addObserver(this, "browser-search-engine-modified", false);
     os.addObserver(this, "restart-in-safe-mode", false);
     os.addObserver(this, "flash-plugin-hang", false);
     os.addObserver(this, "xpi-signature-changed", false);
     os.addObserver(this, "autocomplete-did-enter-text", false);
 
     if (AppConstants.NIGHTLY_BUILD) {
-      AddonWatcher.init();
       os.addObserver(this, AddonWatcher.TOPIC_SLOW_ADDON_DETECTED, false);
     }
 
     ExtensionManagement.registerScript("chrome://browser/content/ext-utils.js");
     ExtensionManagement.registerScript("chrome://browser/content/ext-browserAction.js");
     ExtensionManagement.registerScript("chrome://browser/content/ext-pageAction.js");
     ExtensionManagement.registerScript("chrome://browser/content/ext-contextMenus.js");
     ExtensionManagement.registerScript("chrome://browser/content/ext-desktop-runtime.js");
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
@@ -25,17 +25,17 @@ function test() {
   // initialization
   waitForExplicitFinish();
   let ds = Cc["@mozilla.org/file/directory_service;1"].
            getService(Ci.nsIProperties);
   let dir1 = ds.get("ProfD", Ci.nsIFile);
   let dir2 = ds.get("TmpD", Ci.nsIFile);
   let file = dir2.clone();
   file.append("pbtest.file");
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   const kPrefName = "browser.open.lastDir";
 
   function setupCleanSlate(win) {
     win.gLastOpenDirectory.reset();
     gPrefService.clearUserPref(kPrefName);
   }
 
--- a/browser/components/sessionstore/test/browser_backup_recovery.js
+++ b/browser/components/sessionstore/test/browser_backup_recovery.js
@@ -136,17 +136,17 @@ add_task(function* test_recovery_inacces
   yield File.makeDir(Paths.backups);
   yield File.writeAtomic(Paths.recoveryBackup, SOURCE);
 
   // Write a valid recovery file but make it inaccessible.
   yield File.writeAtomic(Paths.recovery, SOURCE_RECOVERY);
   yield File.setPermissions(Paths.recovery, { unixMode: 0 });
 
   is((yield SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file");
-  yield File.setPermissions(Paths.recovery, { unixMode: 0644 });
+  yield File.setPermissions(Paths.recovery, { unixMode: 0o644 });
 });
 
 add_task(function* test_clean() {
   yield SessionFile.wipe();
   let SOURCE = yield promiseSource("Paths.clean");
   yield File.writeAtomic(Paths.clean, SOURCE);
   yield SessionFile.read();
   yield SessionSaver.run();
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -313,19 +313,17 @@
 @RESPATH@/components/spellchecker.xpt
 @RESPATH@/components/storage.xpt
 @RESPATH@/components/toolkit_asyncshutdown.xpt
 @RESPATH@/components/toolkit_filewatcher.xpt
 @RESPATH@/components/toolkit_finalizationwitness.xpt
 @RESPATH@/components/toolkit_formautofill.xpt
 @RESPATH@/components/toolkit_osfile.xpt
 @RESPATH@/components/toolkit_securityreporter.xpt
-#ifdef NIGHTLY_BUILD
 @RESPATH@/components/toolkit_perfmonitoring.xpt
-#endif
 @RESPATH@/components/toolkit_xulstore.xpt
 @RESPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @RESPATH@/components/toolkitremote.xpt
 #endif
 @RESPATH@/components/txtsvc.xpt
 @RESPATH@/components/txmgr.xpt
 @RESPATH@/components/uconv.xpt
--- a/config/config.mk
+++ b/config/config.mk
@@ -25,20 +25,16 @@ endif
 
 ifndef INCLUDED_AUTOCONF_MK
 include $(DEPTH)/config/autoconf.mk
 endif
 
 -include $(DEPTH)/.mozconfig.mk
 
 ifndef EXTERNALLY_MANAGED_MAKE_FILE
-# Using $(firstword) may not be perfect. But it should be good enough for most
-# scenarios.
-_current_makefile = $(CURDIR)/$(firstword $(MAKEFILE_LIST))
-
 # Import the automatically generated backend file. If this file doesn't exist,
 # the backend hasn't been properly configured. We want this to be a fatal
 # error, hence not using "-include".
 ifndef STANDALONE_MAKEFILE
 GLOBAL_DEPS += backend.mk
 include backend.mk
 endif
 
--- a/config/external/nspr/pr/moz.build
+++ b/config/external/nspr/pr/moz.build
@@ -24,16 +24,23 @@ if CONFIG['OS_ARCH'] == 'Linux':
     SOURCES += ['/nsprpub/pr/src/md/unix/linux.c']
     if CONFIG['CPU_ARCH'] == 'x86_64':
         SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_x86_64.s']
     elif CONFIG['CPU_ARCH'] == 'x86':
         DEFINES['i386'] = True
         SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_x86.s']
     elif CONFIG['CPU_ARCH'] == 'ppc':
         SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_ppc.s']
+elif CONFIG['OS_TARGET'] in ('FreeBSD', 'OpenBSD', 'NetBSD'):
+    DEFINES.update(
+        HAVE_BSD_FLOCK=True,
+        HAVE_SOCKLEN_T=True,
+    )
+    DEFINES[CONFIG['OS_TARGET'].upper()] = True
+    SOURCES += ['/nsprpub/pr/src/md/unix/%s.c' % CONFIG['OS_TARGET'].lower()]
 elif CONFIG['OS_TARGET'] == 'Darwin':
     DEFINES.update(
         DARWIN=True,
         HAVE_BSD_FLOCK=True,
         HAVE_SOCKLEN_T=True,
     )
     SOURCES += [
         '/nsprpub/pr/src/md/unix/darwin.c',
@@ -205,17 +212,20 @@ EXPORTS.nspr += [
     '/nsprpub/pr/include/prtrace.h',
     '/nsprpub/pr/include/prtypes.h',
     '/nsprpub/pr/include/prvrsion.h',
     '/nsprpub/pr/include/prwin16.h',
 ]
 
 EXPORTS.nspr.md += [
     '/nsprpub/pr/include/md/_darwin.cfg',
+    '/nsprpub/pr/include/md/_freebsd.cfg',
     '/nsprpub/pr/include/md/_linux.cfg',
+    '/nsprpub/pr/include/md/_netbsd.cfg',
+    '/nsprpub/pr/include/md/_openbsd.cfg',
     '/nsprpub/pr/include/md/_win95.cfg',
 ]
 
 EXPORTS.nspr.private += [
     '/nsprpub/pr/include/private/pprio.h',
     '/nsprpub/pr/include/private/pprthred.h',
     '/nsprpub/pr/include/private/prpriv.h',
 ]
--- a/config/external/nspr/prcpucfg.h
+++ b/config/external/nspr/prcpucfg.h
@@ -9,15 +9,21 @@
 /*
  * Need to support conditionals that are defined in both the top-level build
  * system as well as NSS' build system for now.
  */
 #if defined(XP_DARWIN) || defined(DARWIN)
 #include "md/_darwin.cfg"
 #elif defined(XP_WIN) || defined(_WINDOWS)
 #include "md/_win95.cfg"
+#elif defined(__FreeBSD__)
+#include "md/_freebsd.cfg"
+#elif defined(__NetBSD__)
+#include "md/_netbsd.cfg"
+#elif defined(__OpenBSD__)
+#include "md/_openbsd.cfg"
 #elif defined(__linux__)
 #include "md/_linux.cfg"
 #else
 #error "Unsupported platform!"
 #endif
 
 #endif /* NSPR_PRCPUCFG_H_ */
--- a/configure.in
+++ b/configure.in
@@ -71,16 +71,17 @@ GTK3_VERSION=3.4.0
 GDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_4
 WINDRES_VERSION=2.14.90
 W32API_VERSION=3.14
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
 SQLITE_VERSION=3.10.2
+FONTCONFIG_VERSION=2.7.0
 
 MSMANIFEST_TOOL=
 
 dnl Set various checks
 dnl ========================================================
 MISSING_X=
 AC_PROG_AWK
 
@@ -8073,17 +8074,17 @@ if test "$USE_FC_FREETYPE"; then
         CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
         MOZ_CHECK_HEADERS([fontconfig/fcfreetype.h], ,
             [AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)], [#include <fontconfig/fontconfig.h>])
         CPPFLAGS="$_SAVE_CPPFLAGS"
     else
         AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H)
     fi
 
-    PKG_CHECK_MODULES(_FONTCONFIG, fontconfig,
+    PKG_CHECK_MODULES(_FONTCONFIG, fontconfig >= $FONTCONFIG_VERSION,
     [
         if test "$MOZ_PANGO"; then
             MOZ_PANGO_CFLAGS="$MOZ_PANGO_CFLAGS $_FONTCONFIG_CFLAGS"
             MOZ_PANGO_LIBS="$MOZ_PANGO_LIBS $_FONTCONFIG_LIBS"
         else
             FT2_CFLAGS="$FT2_CFLAGS $_FONTCONFIG_CFLAGS"
             FT2_LIBS="$FT2_LIBS $_FONTCONFIG_LIBS"
         fi
--- a/devtools/client/projecteditor/test/head.js
+++ b/devtools/client/projecteditor/test/head.js
@@ -229,17 +229,17 @@ function writeToFile(file, data) {
 // You should typically use the async version of this, writeToFile.
 // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#More
 function writeToFileSync(file, data) {
   // file is nsIFile, data is a string
   var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
                  createInstance(Components.interfaces.nsIFileOutputStream);
 
   // use 0x02 | 0x10 to open file for appending.
-  foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
+  foStream.init(file, 0x02 | 0x08 | 0x20, 0o666, 0);
   // write, create, truncate
   // In a c file operation, we have no need to set file mode with or operation,
   // directly using "r" or "w" usually.
 
   // if you are sure there will never ever be any non-ascii text in data you can
   // also call foStream.write(data, data.length) directly
   var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
                   createInstance(Components.interfaces.nsIConverterOutputStream);
--- a/devtools/client/scratchpad/test/browser_scratchpad_confirm_close.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_confirm_close.js
@@ -187,27 +187,27 @@ function cleanup()
   Services.prompt = oldPrompt;
   gFile.remove(false);
   gFile = null;
 }
 
 function createTempFile(name)
 {
   let file = FileUtils.getFile("TmpD", [name]);
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
   file.QueryInterface(Ci.nsILocalFile)
   return file;
 }
 
 function writeFile(file, content, callback)
 {
   let fout = Cc["@mozilla.org/network/file-output-stream;1"].
              createInstance(Ci.nsIFileOutputStream);
   fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
-            0644, fout.DEFER_OPEN);
+            0o644, fout.DEFER_OPEN);
 
   let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
                   createInstance(Ci.nsIScriptableUnicodeConverter);
   converter.charset = "UTF-8";
   let fileContentStream = converter.convertToInputStream(content);
 
   NetUtil.asyncCopy(fileContentStream, fout, callback);
 }
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -205,16 +205,19 @@ RootActor.prototype = {
       this._parameters.tabList.onListChanged = null;
     }
     if (this._parameters.addonList) {
       this._parameters.addonList.onListChanged = null;
     }
     if (this._parameters.workerList) {
       this._parameters.workerList.onListChanged = null;
     }
+    if (this._parameters.serviceWorkerRegistrationList) {
+      this._parameters.serviceWorkerRegistrationList.onListChanged = null;
+    }
     if (typeof this._parameters.onShutdown === 'function') {
       this._parameters.onShutdown();
     }
     this._extraActors = null;
     this.conn = null;
     this._tabActorPool = null;
     this._globalActorPool = null;
     this._parameters = null;
--- a/devtools/shared/apps/tests/debugger-protocol-helper.js
+++ b/devtools/shared/apps/tests/debugger-protocol-helper.js
@@ -91,17 +91,17 @@ function downloadURL(url, file) {
   let istream = channel.open2();
   let bstream = Cc["@mozilla.org/binaryinputstream;1"]
                   .createInstance(Ci.nsIBinaryInputStream);
   bstream.setInputStream(istream);
   let data = bstream.readBytes(bstream.available());
 
   let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
                   .createInstance(Ci.nsIFileOutputStream);
-  ostream.init(file, 0x04 | 0x08 | 0x20, 0600, 0);
+  ostream.init(file, 0x04 | 0x08 | 0x20, 0o600, 0);
   ostream.write(data, data.length);
   ostream.QueryInterface(Ci.nsISafeOutputStream).finish();
 }
 
 // Install a test packaged webapp from data folder
 addMessageListener("install", function (aMessage) {
   let url = aMessage.url;
   let appId = aMessage.appId;
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -90,22 +90,20 @@ static RedirEntry kRedirMap[] = {
     "networking", "chrome://global/content/aboutNetworking.xhtml",
     nsIAboutModule::ALLOW_SCRIPT
   },
   {
     "newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
     nsIAboutModule::ALLOW_SCRIPT |
       nsIAboutModule::HIDE_FROM_ABOUTABOUT
   },
-#ifdef NIGHTLY_BUILD
   {
     "performance", "chrome://global/content/aboutPerformance.xhtml",
     nsIAboutModule::ALLOW_SCRIPT
   },
-#endif
   {
     "plugins", "chrome://global/content/plugins.html",
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD
   },
   {
     "serviceworkers", "chrome://global/content/aboutServiceWorkers.xhtml",
     nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
--- a/dom/animation/CSSPseudoElement.cpp
+++ b/dom/animation/CSSPseudoElement.cpp
@@ -31,16 +31,22 @@ CSSPseudoElement::~CSSPseudoElement()
 {
   // Element might have been unlinked already, so we have to do null check.
   if (mParentElement) {
     mParentElement->DeleteProperty(
       GetCSSPseudoElementPropertyAtom(mPseudoType));
   }
 }
 
+ParentObject
+CSSPseudoElement::GetParentObject() const
+{
+  return mParentElement->GetParentObject();
+}
+
 JSObject*
 CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return CSSPseudoElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 CSSPseudoElement::GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal)
--- a/dom/animation/CSSPseudoElement.h
+++ b/dom/animation/CSSPseudoElement.h
@@ -27,20 +27,17 @@ class CSSPseudoElement final : public ns
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CSSPseudoElement)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CSSPseudoElement)
 
 protected:
   virtual ~CSSPseudoElement();
 
 public:
-  ParentObject GetParentObject() const
-  {
-    return mParentElement->GetParentObject();
-  }
+  ParentObject GetParentObject() const;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   nsCSSPseudoElements::Type GetType() const { return mPseudoType; }
   void GetType(nsString& aRetVal) const
   {
     MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType),
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -154,17 +154,17 @@ PostMessageEvent::Run()
   // window if it can get a reference to it.
 
   nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell();
   RefPtr<nsPresContext> presContext;
   if (shell)
     presContext = shell->GetPresContext();
 
   event->SetTrusted(mTrustedCaller);
-  WidgetEvent* internalEvent = event->GetInternalNSEvent();
+  WidgetEvent* internalEvent = event->WidgetEventPtr();
 
   nsEventStatus status = nsEventStatus_eIgnore;
   EventDispatcher::Dispatch(window,
                             presContext,
                             internalEvent,
                             static_cast<dom::Event*>(event.get()),
                             &status);
   return NS_OK;
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -339,17 +339,17 @@ TextInputProcessor::PrepareKeyboardEvent
                       uint32_t& aKeyFlags,
                       uint8_t aOptionalArgc,
                       WidgetKeyboardEvent*& aKeyboardEvent)
 {
   aKeyboardEvent = nullptr;
 
   aKeyboardEvent =
     aOptionalArgc && aDOMKeyEvent ?
-      aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent() : nullptr;
+      aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent() : nullptr;
   if (!aKeyboardEvent || aOptionalArgc < 2) {
     aKeyFlags = 0;
   }
 
   if (!aKeyboardEvent) {
     return NS_OK;
   }
 
@@ -764,17 +764,17 @@ TextInputProcessor::Keydown(nsIDOMKeyEve
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   if (!aOptionalArgc) {
     aKeyFlags = 0;
   }
   if (NS_WARN_IF(!aDOMKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   WidgetKeyboardEvent* originalKeyEvent =
-    aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   if (NS_WARN_IF(!originalKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
 }
 
 TextEventDispatcher::DispatchTo
 TextInputProcessor::GetDispatchTo() const
@@ -870,17 +870,17 @@ TextInputProcessor::Keyup(nsIDOMKeyEvent
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   if (!aOptionalArgc) {
     aKeyFlags = 0;
   }
   if (NS_WARN_IF(!aDOMKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   WidgetKeyboardEvent* originalKeyEvent =
-    aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   if (NS_WARN_IF(!originalKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   return KeyupInternal(*originalKeyEvent, aKeyFlags, *aDoDefault);
 }
 
 nsresult
 TextInputProcessor::KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3778,17 +3778,17 @@ nsContentUtils::DispatchEvent(nsIDocumen
                               bool aOnlyChromeDispatch)
 {
   nsCOMPtr<nsIDOMEvent> event;
   nsCOMPtr<EventTarget> target;
   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
                                   aCancelable, aTrusted, getter_AddRefs(event),
                                   getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = aOnlyChromeDispatch;
 
   bool dummy;
   return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
 }
 
 nsresult
 nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
                                     nsISupports *aTarget,
@@ -4942,17 +4942,17 @@ nsContentUtils::GetAccelKeyCandidates(ns
 
   nsAutoString eventType;
   aDOMKeyEvent->AsEvent()->GetType(eventType);
   // Don't process if aDOMKeyEvent is not a keypress event.
   if (!eventType.EqualsLiteral("keypress"))
     return;
 
   WidgetKeyboardEvent* nativeKeyEvent =
-    aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   if (nativeKeyEvent) {
     NS_ASSERTION(nativeKeyEvent->mClass == eKeyboardEventClass,
                  "wrong type of native event");
     // nsShortcutCandidate::mCharCode is a candidate charCode.
     // nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
     // execute a command with/without shift key state. If this is TRUE, the
     // shifted key state should be ignored. Otherwise, don't ignore the state.
     // the priority of the charCodes are (shift key is not pressed):
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1768,17 +1768,17 @@ nsDOMWindowUtils::GetFullZoom(float* aFu
 NS_IMETHODIMP
 nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget,
                                                nsIDOMEvent* aEvent,
                                                bool aTrusted,
                                                bool* aRetVal)
 {
   NS_ENSURE_STATE(aEvent);
   aEvent->SetTrusted(aTrusted);
-  WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
+  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
   NS_ENSURE_STATE(internalEvent);
   nsCOMPtr<nsIContent> content = do_QueryInterface(aTarget);
   NS_ENSURE_STATE(content);
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   if (content->OwnerDoc()->GetWindow() != window) {
     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
   }
   nsCOMPtr<nsIDocument> targetDoc = content->GetCurrentDoc();
@@ -3451,17 +3451,17 @@ nsDOMWindowUtils::GetPaintFlashing(bool*
 
 NS_IMETHODIMP
 nsDOMWindowUtils::DispatchEventToChromeOnly(nsIDOMEventTarget* aTarget,
                                             nsIDOMEvent* aEvent,
                                             bool* aRetVal)
 {
   *aRetVal = false;
   NS_ENSURE_STATE(aTarget && aEvent);
-  aEvent->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  aEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   aTarget->DispatchEvent(aEvent, aRetVal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RequestCompositorProperty(const nsAString& property,
                                             float* aResult)
 {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5090,17 +5090,17 @@ nsDocument::DispatchContentLoadedEvents(
         event->SetTrusted(true);
 
         // To dispatch this event we must manually call
         // EventDispatcher::Dispatch() on the ancestor document since the
         // target is not in the same document, so the event would never reach
         // the ancestor document if we used the normal event
         // dispatching code.
 
-        WidgetEvent* innerEvent = event->GetInternalNSEvent();
+        WidgetEvent* innerEvent = event->WidgetEventPtr();
         if (innerEvent) {
           nsEventStatus status = nsEventStatus_eIgnore;
 
           nsIPresShell *shell = parent->GetShell();
           if (shell) {
             RefPtr<nsPresContext> context = shell->GetPresContext();
 
             if (context) {
@@ -8108,17 +8108,17 @@ nsIDocument::CreateEvent(const nsAString
   // Create event even without presContext.
   RefPtr<Event> ev =
     EventDispatcher::CreateEvent(const_cast<nsIDocument*>(this), presContext,
                                  nullptr, aEventType);
   if (!ev) {
     rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return nullptr;
   }
-  WidgetEvent* e = ev->GetInternalNSEvent();
+  WidgetEvent* e = ev->WidgetEventPtr();
   e->mFlags.mBubbles = false;
   e->mFlags.mCancelable = false;
   return ev.forget();
 }
 
 void
 nsDocument::FlushPendingNotifications(mozFlushType aType)
 {
@@ -9195,17 +9195,17 @@ NotifyPageHide(nsIDocument* aDocument, v
 static void
 DispatchCustomEventWithFlush(nsINode* aTarget, const nsAString& aEventType,
                              bool aBubbles, bool aOnlyChromeDispatch)
 {
   RefPtr<Event> event = NS_NewDOMEvent(aTarget, nullptr, nullptr);
   event->InitEvent(aEventType, aBubbles, false);
   event->SetTrusted(true);
   if (aOnlyChromeDispatch) {
-    event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+    event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   }
   if (nsIPresShell* shell = aTarget->OwnerDoc()->GetShell()) {
     shell->GetPresContext()->
       RefreshDriver()->ScheduleEventDispatch(aTarget, event);
   }
 }
 
 static void
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5060,19 +5060,17 @@ nsGlobalWindow::GetScreenXY(ErrorResult&
   // placed to the right of a lo-dpi screen on Windows. (Instead, there
   // may be "gaps" in the resulting CSS px coordinates in some cases.)
   nsDeviceContext *dc = presContext->DeviceContext();
   nsRect screenRect;
   dc->GetRect(screenRect);
   LayoutDeviceRect screenRectDev =
     LayoutDevicePixel::FromAppUnits(screenRect, dc->AppUnitsPerDevPixel());
 
-  nsCOMPtr<nsIWidget> widget = GetMainWidget();
-  DesktopToLayoutDeviceScale scale = widget ? widget->GetDesktopToDeviceScale()
-                                            : DesktopToLayoutDeviceScale(1.0);
+  DesktopToLayoutDeviceScale scale = dc->GetDesktopToDeviceScale();
   DesktopRect screenRectDesk = screenRectDev / scale;
 
   CSSPoint cssPt =
     LayoutDevicePoint(x - screenRectDev.x, y - screenRectDev.y) /
     presContext->CSSToDevPixelScale();
   cssPt.x += screenRectDesk.x;
   cssPt.y += screenRectDesk.y;
 
@@ -5698,17 +5696,17 @@ nsGlobalWindow::DispatchResizeEvent(cons
                                /* cancelable = */ true,
                                detailValue,
                                res);
   if (res.Failed()) {
     return false;
   }
 
   domEvent->SetTrusted(true);
-  domEvent->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   nsCOMPtr<EventTarget> target = do_QueryInterface(GetOuterWindow());
   domEvent->SetTarget(target);
 
   bool defaultActionEnabled = true;
   target->DispatchEvent(domEvent, &defaultActionEnabled);
 
   return defaultActionEnabled;
@@ -8493,17 +8491,17 @@ nsGlobalWindow::LeaveModalState()
   nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal();
   if (inner)
     inner->mLastDialogQuitTime = TimeStamp::Now();
 
   if (topWin->mModalStateDepth == 0) {
     RefPtr<Event> event = NS_NewDOMEvent(inner, nullptr, nullptr);
     event->InitEvent(NS_LITERAL_STRING("endmodalstate"), true, false);
     event->SetTrusted(true);
-    event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+    event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
     bool dummy;
     topWin->DispatchEvent(event, &dummy);
   }
 }
 
 bool
 nsGlobalWindow::IsInModalState()
 {
@@ -11107,17 +11105,17 @@ nsGlobalWindow::Observe(nsISupports* aSu
                                                         event, error);
     if (error.Failed()) {
       return error.StealNSResult();
     }
 
     newEvent->SetTrusted(true);
 
     if (fireMozStorageChanged) {
-      WidgetEvent* internalEvent = newEvent->GetInternalNSEvent();
+      WidgetEvent* internalEvent = newEvent->WidgetEventPtr();
       internalEvent->mFlags.mOnlyChromeDispatch = true;
     }
 
     if (IsFrozen()) {
       // This window is frozen, rather than firing the events here,
       // store the domain in which the change happened and fire the
       // events if we're ever thawed.
 
@@ -13240,17 +13238,17 @@ nsGlobalWindow::BeginWindowMove(Event& a
   }
 #endif
 
   if (!widget) {
     return;
   }
 
   WidgetMouseEvent* mouseEvent =
-    aMouseDownEvent.GetInternalNSEvent()->AsMouseEvent();
+    aMouseDownEvent.WidgetEventPtr()->AsMouseEvent();
   if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   aError = widget->BeginMoveDrag(mouseEvent);
 }
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -348,17 +348,17 @@ nsPluginCrashedEvent::Run()
   init.mSubmittedCrashReport = mSubmittedCrashReport;
   init.mBubbles = true;
   init.mCancelable = true;
 
   RefPtr<PluginCrashedEvent> event =
     PluginCrashedEvent::Constructor(doc, NS_LITERAL_STRING("PluginCrashed"), init);
 
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   EventDispatcher::DispatchDOMEvent(mContent, nullptr, event, nullptr, nullptr);
   return NS_OK;
 }
 
 class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
 {
 public:
--- a/dom/base/test/bug578096LoadChromeScript.js
+++ b/dom/base/test/bug578096LoadChromeScript.js
@@ -1,16 +1,16 @@
 var file;
 Components.utils.importGlobalProperties(["File"]);
 
 addMessageListener("file.create", function (message) {
   file = Components.classes["@mozilla.org/file/directory_service;1"]
              .getService(Components.interfaces.nsIProperties)
              .get("TmpD", Components.interfaces.nsIFile);
   file.append("foo.txt");
-  file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
+  file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
   sendAsyncMessage("file.created", new File(file));
 });
 
 addMessageListener("file.remove", function (message) {
   file.remove(false);
   sendAsyncMessage("file.removed", {});
 });
--- a/dom/base/test/file_bug1198095.js
+++ b/dom/base/test/file_bug1198095.js
@@ -3,17 +3,17 @@ Cu.importGlobalProperties(["File"]);
 
 function createFileWithData(message) {
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
   var testFile = dirSvc.get("ProfD", Ci.nsIFile);
   testFile.append("fileAPItestfileBug1198095");
 
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
-                 0666, 0);
+                 0o666, 0);
 
   outStream.write(message, message.length);
   outStream.close();
 
   var domFile = new File(testFile);
   return domFile;
 }
 
--- a/dom/base/test/fileapi_chromeScript.js
+++ b/dom/base/test/fileapi_chromeScript.js
@@ -6,17 +6,17 @@ var fileNum = 1;
 function createFileWithData(fileData) {
   var willDelete = fileData === null;
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
   var testFile = dirSvc.get("ProfD", Ci.nsIFile);
   testFile.append("fileAPItestfile" + fileNum);
   fileNum++;
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
-                 0666, 0);
+                 0o666, 0);
   if (willDelete) {
     fileData = "some irrelevant test data\n";
   }
   outStream.write(fileData, fileData.length);
   outStream.close();
   var domFile = new File(testFile);
   if (willDelete) {
     testFile.remove(/* recursive: */ false);
--- a/dom/base/test/unit/head_xml.js
+++ b/dom/base/test/unit/head_xml.js
@@ -41,17 +41,17 @@ function ParseFile(file) {
     file = fileObj;
   }
 
   do_check_eq(file instanceof nsILocalFile, true);
 
   var fileStr = C["@mozilla.org/network/file-input-stream;1"]
                  .createInstance(nsIFileInputStream);
   // Init for readonly reading
-  fileStr.init(file,  0x01, 0400, nsIFileInputStream.CLOSE_ON_EOF);
+  fileStr.init(file,  0x01, 0o400, nsIFileInputStream.CLOSE_ON_EOF);
   return ParseXML(fileStr);
 }
 
 function ParseXML(data) {
   if (typeof(data) == "string") {
     return DOMParser().parseFromString(data, "application/xml");
   }
 
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -40,17 +40,17 @@ AsyncEventDispatcher::Run()
   RefPtr<Event> event = mEvent ? mEvent->InternalDOMEvent() : nullptr;
   if (!event) {
     event = NS_NewDOMEvent(mTarget, nullptr, nullptr);
     event->InitEvent(mEventType, mBubbles, false);
     event->SetTrusted(true);
   }
   if (mOnlyChromeDispatch) {
     MOZ_ASSERT(event->IsTrusted());
-    event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+    event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   }
   bool dummy;
   mTarget->DispatchEvent(event, &dummy);
   return NS_OK;
 }
 
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -624,17 +624,17 @@ Event::SetTarget(nsIDOMEventTarget* aTar
 
 NS_IMETHODIMP_(bool)
 Event::IsDispatchStopped()
 {
   return mEvent->mFlags.mPropagationStopped;
 }
 
 NS_IMETHODIMP_(WidgetEvent*)
-Event::GetInternalNSEvent()
+Event::WidgetEventPtr()
 {
   return mEvent;
 }
 
 NS_IMETHODIMP_(Event*)
 Event::InternalDOMEvent()
 {
   return this;
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -354,17 +354,17 @@ private:
   NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) override { return _to GetDefaultPrevented(aDefaultPrevented); } \
   NS_IMETHOD StopImmediatePropagation(void) override { return _to StopImmediatePropagation(); } \
   NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) override { return _to GetOriginalTarget(aOriginalTarget); } \
   NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) override { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \
   NS_IMETHOD GetPreventDefault(bool* aRetval) override { return _to GetPreventDefault(aRetval); } \
   NS_IMETHOD GetIsTrusted(bool* aIsTrusted) override { return _to GetIsTrusted(aIsTrusted); } \
   NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) override { return _to SetTarget(aTarget); } \
   NS_IMETHOD_(bool) IsDispatchStopped(void) override { return _to IsDispatchStopped(); } \
-  NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) override { return _to GetInternalNSEvent(); } \
+  NS_IMETHOD_(WidgetEvent*) WidgetEventPtr(void) override { return _to WidgetEventPtr(); } \
   NS_IMETHOD_(void) SetTrusted(bool aTrusted) override { _to SetTrusted(aTrusted); } \
   NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) override { _to SetOwner(aOwner); } \
   NS_IMETHOD_(Event*) InternalDOMEvent() override { return _to InternalDOMEvent(); }
 
 #define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \
   NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) \
   virtual void PreventDefault(JSContext* aCx) override { Event::PreventDefault(aCx); }
 
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -504,17 +504,17 @@ EventDispatcher::Dispatch(nsISupports* a
         NS_WARNING("Fix the caller!");
       } else {
         NS_ERROR("This is unsafe! Fix the caller!");
       }
     }
   }
 
   if (aDOMEvent) {
-    WidgetEvent* innerEvent = aDOMEvent->GetInternalNSEvent();
+    WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
     NS_ASSERTION(innerEvent == aEvent,
                   "The inner event of aDOMEvent is not the same as aEvent!");
   }
 #endif
 
   nsresult rv = NS_OK;
   bool externalDOMEvent = !!(aDOMEvent);
 
@@ -693,17 +693,17 @@ EventDispatcher::Dispatch(nsISupports* a
 /* static */ nsresult
 EventDispatcher::DispatchDOMEvent(nsISupports* aTarget,
                                   WidgetEvent* aEvent,
                                   nsIDOMEvent* aDOMEvent,
                                   nsPresContext* aPresContext,
                                   nsEventStatus* aEventStatus)
 {
   if (aDOMEvent) {
-    WidgetEvent* innerEvent = aDOMEvent->GetInternalNSEvent();
+    WidgetEvent* innerEvent = aDOMEvent->WidgetEventPtr();
     NS_ENSURE_TRUE(innerEvent, NS_ERROR_ILLEGAL_VALUE);
 
     bool dontResetTrusted = false;
     if (innerEvent->mFlags.mDispatchedAtLeastOnce) {
       innerEvent->target = nullptr;
       innerEvent->originalTarget = nullptr;
     } else {
       aDOMEvent->GetIsTrusted(&dontResetTrusted);
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -579,17 +579,17 @@ IMEStateManager::OnMouseButtonEventInEdi
   if (!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
     MOZ_LOG(sISMLog, LogLevel::Debug,
       ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
        "the active IMEContentObserver isn't managing the editor"));
     return false;
   }
 
   WidgetMouseEvent* internalEvent =
-    aMouseEvent->AsEvent()->GetInternalNSEvent()->AsMouseEvent();
+    aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
   if (NS_WARN_IF(!internalEvent)) {
     MOZ_LOG(sISMLog, LogLevel::Debug,
       ("ISM:   IMEStateManager::OnMouseButtonEventInEditor(), "
        "the internal event of aMouseEvent isn't WidgetMouseEvent"));
     return false;
   }
 
   bool consumed =
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -867,17 +867,17 @@ nsTextInputListener::HandleEvent(nsIDOME
   bool isTrusted = false;
   rv = aEvent->GetIsTrusted(&isTrusted);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!isTrusted) {
     return NS_OK;
   }
 
   WidgetKeyboardEvent* keyEvent =
-    aEvent->GetInternalNSEvent()->AsKeyboardEvent();
+    aEvent->WidgetEventPtr()->AsKeyboardEvent();
   if (!keyEvent) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (keyEvent->mMessage != eKeyPress) {
     return NS_OK;
   }
 
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -738,17 +738,17 @@ DispatchErrorEvent(IDBRequest* aRequest,
   nsresult rv = request->DispatchEvent(aEvent, &doDefault);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MOZ_ASSERT(!transaction || transaction->IsOpen() || transaction->IsAborted());
 
   if (transaction && transaction->IsOpen()) {
-    WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
+    WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
     MOZ_ASSERT(internalEvent);
 
     if (internalEvent->mFlags.mExceptionHasBeenRisen) {
       transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     } else if (doDefault) {
       transaction->Abort(request);
     }
   }
@@ -811,17 +811,17 @@ DispatchSuccessEvent(ResultHelper* aResu
   nsresult rv = request->DispatchEvent(aEvent, &dummy);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MOZ_ASSERT_IF(transaction,
                 transaction->IsOpen() || transaction->IsAborted());
 
-  WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
+  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
   MOZ_ASSERT(internalEvent);
 
   if (transaction &&
       transaction->IsOpen() &&
       internalEvent->mFlags.mExceptionHasBeenRisen) {
     transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
   }
 }
--- a/dom/indexedDB/test/unit/test_blob_file_backed.js
+++ b/dom/indexedDB/test/unit/test_blob_file_backed.js
@@ -7,17 +7,17 @@ var disableWorkerTest = "This test uses 
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const fileIOFlags = 0x02 | // PR_WRONLY
                       0x08 | // PR_CREATEFILE
                       0x20;  // PR_TRUNCATE
-  const filePerms = 0664;
+  const filePerms = 0o664;
   const fileData = "abcdefghijklmnopqrstuvwxyz";
   const fileType = "text/plain";
 
   const databaseName =
     ("window" in this) ? window.location.pathname : "Test";
   const objectStoreName = "foo";
   const objectStoreKey = "10";
 
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIDOMEventTarget;
 
-[ptr] native WidgetEventPtr(mozilla::WidgetEvent);
+[ptr] native WidgetEvent(mozilla::WidgetEvent);
 [ptr] native DOMEventPtr(mozilla::dom::Event);
 [ptr] native IPCMessagePtr(IPC::Message);
 [ptr] native ConstIPCMessagePtr(const IPC::Message);
 [ptr] native EventTargetPtr(mozilla::dom::EventTarget);
 %{C++
 #ifdef ERROR
 #undef ERROR
 #endif
@@ -202,17 +202,17 @@ interface nsIDOMEvent : nsISupports
    */
   boolean                   getPreventDefault();
 
   readonly attribute boolean isTrusted;
 
   [noscript] void duplicatePrivateData();
   [noscript] void setTarget(in nsIDOMEventTarget aTarget);
   [notxpcom] boolean IsDispatchStopped();
-  [notxpcom] WidgetEventPtr GetInternalNSEvent();
+  [notxpcom] WidgetEvent WidgetEventPtr();
   [noscript,notxpcom] void SetTrusted(in boolean aTrusted);
   [notxpcom] void Serialize(in IPCMessagePtr aMsg,
                             in boolean aSerializeInterfaceType);
   [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter);
   [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner);
   [notxpcom] DOMEventPtr InternalDOMEvent();
   [noscript] void stopCrossProcessForwarding();
 };
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3096,17 +3096,17 @@ TabParent::LayerTreeUpdate(bool aActive)
 
   RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
   if (aActive) {
     event->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false);
   } else {
     event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false);
   }
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   bool dummy;
   mFrameElement->DispatchEvent(event, &dummy);
   return true;
 }
 
 void
 TabParent::SwapLayerTreeObservers(TabParent* aOther)
 {
@@ -3131,17 +3131,17 @@ TabParent::RecvRemotePaintIsReady()
   if (!target) {
     NS_WARNING("Could not locate target for MozAfterRemotePaint message.");
     return true;
   }
 
   RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
   event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false);
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   bool dummy;
   mFrameElement->DispatchEvent(event, &dummy);
   return true;
 }
 
 mozilla::plugins::PPluginWidgetParent*
 TabParent::AllocPPluginWidgetParent()
 {
--- a/dom/json/test/unit/test_encode.js
+++ b/dom/json/test/unit/test_encode.js
@@ -7,17 +7,17 @@ var dirSvc = Cc["@mozilla.org/file/direc
 var workingDir = dirSvc.get("TmpD", Ci.nsIFile);
 
 var outputName = "json-test-output";
 var outputDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
 outputDir.initWithFile(workingDir);
 outputDir.append(outputName);
 
 if (!outputDir.exists()) {
-  outputDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
+  outputDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777);
 } else if (!outputDir.isDirectory()) {
   do_throw(outputName + " is not a directory?")
 }
 
 function testStringEncode()
 {
   var obj1 = {a:1};
   var obj2 = {foo:"bar"};
@@ -78,20 +78,20 @@ function testThrowingToJSON() {
   }
 }
 
 function testOutputStreams() {
   function writeToFile(obj, charset, writeBOM) {
     var jsonFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
     jsonFile.initWithFile(outputDir);
     jsonFile.append("test.json");
-    jsonFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+    jsonFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
     try {
-      stream.init(jsonFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate
+      stream.init(jsonFile, 0x04 | 0x08 | 0x20, 0o600, 0); // write, create, truncate
       nativeJSON.encodeToStream(stream, charset, writeBOM, obj);
     } finally {
       stream.close();
     }
     return jsonFile;
   }
 
   var pairs = [
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -200,17 +200,17 @@ GeckoMediaPluginService::GMPCrashCallbac
   nsCOMPtr<nsIDocument> document;
   if (!GetParentWindowAndDocumentIfValid(parentWindow, document)) {
     return;
   }
 
   RefPtr<dom::PluginCrashedEvent> event =
     dom::PluginCrashedEvent::Constructor(document, NS_LITERAL_STRING("PluginCrashed"), init);
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   EventDispatcher::DispatchDOMEvent(parentWindow, nullptr, event, nullptr, nullptr);
 }
 
 bool
 GeckoMediaPluginService::GMPCrashCallback::IsStillValid()
 {
   nsCOMPtr<nsPIDOMWindowInner> parentWindow;
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -14,16 +14,25 @@
 #include "MediaStreamGraph.h"
 #include "OutputStreamManager.h"
 #include "SharedBuffer.h"
 #include "VideoSegment.h"
 #include "VideoUtils.h"
 
 namespace mozilla {
 
+/*
+ * A container class to make it easier to pass the playback info all the
+ * way to DecodedStreamGraphListener from DecodedStream.
+ */
+struct PlaybackInfoInit {
+  int64_t mStartTime;
+  MediaInfo mInfo;
+};
+
 class DecodedStreamGraphListener : public MediaStreamListener {
   typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent;
 public:
   DecodedStreamGraphListener(MediaStream* aStream,
                              MozPromiseHolder<GenericPromise>&& aPromise)
     : mMutex("DecodedStreamGraphListener::mMutex")
     , mStream(aStream)
     , mLastOutputTime(aStream->StreamTimeToMicroseconds(aStream->GetCurrentTime()))
@@ -102,17 +111,18 @@ UpdateStreamSuspended(MediaStream* aStre
  * We have at most one DecodedStreamDaata per MediaDecoder. Its stream
  * is used as the input for each ProcessedMediaStream created by calls to
  * captureStream(UntilEnded). Seeking creates a new source stream, as does
  * replaying after the input as ended. In the latter case, the new source is
  * not connected to streams created by captureStreamUntilEnded.
  */
 class DecodedStreamData {
 public:
-  DecodedStreamData(SourceMediaStream* aStream,
+  DecodedStreamData(OutputStreamManager* aOutputStreamManager,
+                    PlaybackInfoInit&& aInit,
                     MozPromiseHolder<GenericPromise>&& aPromise);
   ~DecodedStreamData();
   int64_t GetPosition() const;
   void SetPlaying(bool aPlaying);
 
   /* The following group of fields are protected by the decoder's monitor
    * and can be read or written on any thread.
    */
@@ -122,55 +132,66 @@ public:
   // Therefore video packets starting at or after this time need to be copied
   // to the output stream.
   int64_t mNextVideoTime; // microseconds
   int64_t mNextAudioTime; // microseconds
   // The last video image sent to the stream. Useful if we need to replicate
   // the image.
   RefPtr<layers::Image> mLastVideoImage;
   gfx::IntSize mLastVideoImageDisplaySize;
-  // This is set to true when the stream is initialized (audio and
-  // video tracks added).
-  bool mStreamInitialized;
   bool mHaveSentFinish;
   bool mHaveSentFinishAudio;
   bool mHaveSentFinishVideo;
 
   // The decoder is responsible for calling Destroy() on this stream.
   const RefPtr<SourceMediaStream> mStream;
-  RefPtr<DecodedStreamGraphListener> mListener;
+  const RefPtr<DecodedStreamGraphListener> mListener;
   bool mPlaying;
   // True if we need to send a compensation video frame to ensure the
   // StreamTime going forward.
   bool mEOSVideoCompensation;
+
+  const RefPtr<OutputStreamManager> mOutputStreamManager;
 };
 
-DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream,
+DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
+                                     PlaybackInfoInit&& aInit,
                                      MozPromiseHolder<GenericPromise>&& aPromise)
   : mAudioFramesWritten(0)
-  , mNextVideoTime(-1)
-  , mNextAudioTime(-1)
-  , mStreamInitialized(false)
+  , mNextVideoTime(aInit.mStartTime)
+  , mNextAudioTime(aInit.mStartTime)
   , mHaveSentFinish(false)
   , mHaveSentFinishAudio(false)
   , mHaveSentFinishVideo(false)
-  , mStream(aStream)
+  , mStream(aOutputStreamManager->Graph()->CreateSourceStream(nullptr))
+  // DecodedStreamGraphListener will resolve this promise.
+  , mListener(new DecodedStreamGraphListener(mStream, Move(aPromise)))
+  // mPlaying is initially true because MDSM won't start playback until playing
+  // becomes true. This is consistent with the settings of AudioSink.
   , mPlaying(true)
   , mEOSVideoCompensation(false)
+  , mOutputStreamManager(aOutputStreamManager)
 {
-  // DecodedStreamGraphListener will resolve this promise.
-  mListener = new DecodedStreamGraphListener(mStream, Move(aPromise));
   mStream->AddListener(mListener);
+  mOutputStreamManager->Connect(mStream);
 
-  // mPlaying is initially true because MDSM won't start playback until playing
-  // becomes true. This is consistent with the settings of AudioSink.
+  // Initialize tracks.
+  if (aInit.mInfo.HasAudio()) {
+    mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId,
+                           aInit.mInfo.mAudio.mRate,
+                           0, new AudioSegment());
+  }
+  if (aInit.mInfo.HasVideo()) {
+    mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment());
+  }
 }
 
 DecodedStreamData::~DecodedStreamData()
 {
+  mOutputStreamManager->Disconnect();
   mListener->Forget();
   mStream->Destroy();
 }
 
 int64_t
 DecodedStreamData::GetPosition() const
 {
   return mListener->GetLastOutputTime();
@@ -243,37 +264,41 @@ DecodedStream::Start(int64_t aStartTime,
 
   mStartTime.emplace(aStartTime);
   mInfo = aInfo;
   mPlaying = true;
   ConnectListener();
 
   class R : public nsRunnable {
     typedef MozPromiseHolder<GenericPromise> Promise;
-    typedef void(DecodedStream::*Method)(Promise&&);
+    typedef decltype(&DecodedStream::CreateData) Method;
   public:
-    R(DecodedStream* aThis, Method aMethod, Promise&& aPromise)
-      : mThis(aThis), mMethod(aMethod)
+    R(DecodedStream* aThis, Method aMethod, PlaybackInfoInit&& aInit, Promise&& aPromise)
+      : mThis(aThis), mMethod(aMethod), mInit(Move(aInit))
     {
       mPromise = Move(aPromise);
     }
     NS_IMETHOD Run() override
     {
-      (mThis->*mMethod)(Move(mPromise));
+      (mThis->*mMethod)(Move(mInit), Move(mPromise));
       return NS_OK;
     }
   private:
     RefPtr<DecodedStream> mThis;
     Method mMethod;
+    PlaybackInfoInit mInit;
     Promise mPromise;
   };
 
   MozPromiseHolder<GenericPromise> promise;
   mFinishPromise = promise.Ensure(__func__);
-  nsCOMPtr<nsIRunnable> r = new R(this, &DecodedStream::CreateData, Move(promise));
+  PlaybackInfoInit init {
+    aStartTime, aInfo
+  };
+  nsCOMPtr<nsIRunnable> r = new R(this, &DecodedStream::CreateData, Move(init), Move(promise));
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
 void
 DecodedStream::Stop()
 {
   AssertOwnerThread();
   MOZ_ASSERT(mStartTime.isSome(), "playback not started.");
@@ -306,40 +331,36 @@ DecodedStream::DestroyData(UniquePtr<Dec
 {
   AssertOwnerThread();
 
   if (!aData) {
     return;
   }
 
   DecodedStreamData* data = aData.release();
-  RefPtr<DecodedStream> self = this;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-    self->mOutputStreamManager->Disconnect();
     delete data;
   });
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
 void
-DecodedStream::CreateData(MozPromiseHolder<GenericPromise>&& aPromise)
+DecodedStream::CreateData(PlaybackInfoInit&& aInit, MozPromiseHolder<GenericPromise>&& aPromise)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // No need to create a source stream when there are no output streams. This
   // happens when RemoveOutput() is called immediately after StartPlayback().
   if (!mOutputStreamManager->Graph()) {
     // Resolve the promise to indicate the end of playback.
     aPromise.Resolve(true, __func__);
     return;
   }
 
-  auto source = mOutputStreamManager->Graph()->CreateSourceStream(nullptr);
-  auto data = new DecodedStreamData(source, Move(aPromise));
-  mOutputStreamManager->Connect(data->mStream);
+  auto data = new DecodedStreamData(mOutputStreamManager, Move(aInit), Move(aPromise));
 
   class R : public nsRunnable {
     typedef void(DecodedStream::*Method)(UniquePtr<DecodedStreamData>);
   public:
     R(DecodedStream* aThis, Method aMethod, DecodedStreamData* aData)
       : mThis(aThis), mMethod(aMethod), mData(aData) {}
     NS_IMETHOD Run() override
     {
@@ -349,19 +370,17 @@ DecodedStream::CreateData(MozPromiseHold
   private:
     virtual ~R()
     {
       // mData is not transferred when dispatch fails and Run() is not called.
       // We need to dispatch a task to ensure DecodedStreamData is destroyed
       // properly on the main thread.
       if (mData) {
         DecodedStreamData* data = mData.release();
-        RefPtr<DecodedStream> self = mThis.forget();
         nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-          self->mOutputStreamManager->Disconnect();
           delete data;
         });
         // We are in tail dispatching phase. Don't call
         // AbstractThread::MainThread()->Dispatch() to avoid reentrant
         // AutoTaskDispatcher.
         NS_DispatchToMainThread(r.forget());
       }
     }
@@ -426,47 +445,16 @@ DecodedStream::SetPlaybackRate(double aP
 
 void
 DecodedStream::SetPreservesPitch(bool aPreservesPitch)
 {
   AssertOwnerThread();
   mParams.mPreservesPitch = aPreservesPitch;
 }
 
-void
-DecodedStream::InitTracks()
-{
-  AssertOwnerThread();
-
-  if (mData->mStreamInitialized) {
-    return;
-  }
-
-  SourceMediaStream* sourceStream = mData->mStream;
-
-  if (mInfo.HasAudio()) {
-    TrackID audioTrackId = mInfo.mAudio.mTrackId;
-    AudioSegment* audio = new AudioSegment();
-    sourceStream->AddAudioTrack(audioTrackId, mInfo.mAudio.mRate, 0, audio,
-                                SourceMediaStream::ADDTRACK_QUEUED);
-    mData->mNextAudioTime = mStartTime.ref();
-  }
-
-  if (mInfo.HasVideo()) {
-    TrackID videoTrackId = mInfo.mVideo.mTrackId;
-    VideoSegment* video = new VideoSegment();
-    sourceStream->AddTrack(videoTrackId, 0, video,
-                           SourceMediaStream::ADDTRACK_QUEUED);
-    mData->mNextVideoTime = mStartTime.ref();
-  }
-
-  sourceStream->FinishAddTracks();
-  mData->mStreamInitialized = true;
-}
-
 static void
 SendStreamAudio(DecodedStreamData* aStream, int64_t aStartTime,
                 MediaData* aData, AudioSegment* aOutput,
                 uint32_t aRate, double aVolume)
 {
   // The amount of audio frames that is used to fuzz rounding errors.
   static const int64_t AUDIO_FUZZ_FRAMES = 1;
 
@@ -689,17 +677,16 @@ DecodedStream::SendData()
     return;
   }
 
   // Nothing to do when the stream is finished.
   if (mData->mHaveSentFinish) {
     return;
   }
 
-  InitTracks();
   SendAudio(mParams.mVolume, mSameOrigin);
   SendVideo(mSameOrigin);
   AdvanceTracks();
 
   bool finished = (!mInfo.HasAudio() || mAudioQueue.IsFinished()) &&
                   (!mInfo.HasVideo() || mVideoQueue.IsFinished());
 
   if (finished && !mData->mHaveSentFinish) {
--- a/dom/media/mediasink/DecodedStream.h
+++ b/dom/media/mediasink/DecodedStream.h
@@ -18,16 +18,17 @@
 #include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 
 class DecodedStreamData;
 class MediaData;
 class MediaStream;
 class OutputStreamManager;
+struct PlaybackInfoInit;
 class ProcessedMediaStream;
 class TimeStamp;
 
 template <class T> class MediaQueue;
 
 class DecodedStream : public media::MediaSink {
   using media::MediaSink::PlaybackParams;
 
@@ -60,20 +61,19 @@ public:
   void Stop() override;
   bool IsStarted() const override;
   bool IsPlaying() const override;
 
 protected:
   virtual ~DecodedStream();
 
 private:
-  void CreateData(MozPromiseHolder<GenericPromise>&& aPromise);
+  void CreateData(PlaybackInfoInit&& aInit, MozPromiseHolder<GenericPromise>&& aPromise);
   void DestroyData(UniquePtr<DecodedStreamData> aData);
   void OnDataCreated(UniquePtr<DecodedStreamData> aData);
-  void InitTracks();
   void AdvanceTracks();
   void SendAudio(double aVolume, bool aIsSameOrigin);
   void SendVideo(bool aIsSameOrigin);
   void SendData();
 
   void AssertOwnerThread() const {
     MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   }
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
@@ -42,19 +42,21 @@ ChoosePixelFormat(AVCodecContext* aCodec
 {
   FFMPEG_LOG("Choosing FFmpeg pixel format for video decoding.");
   for (; *aFormats > -1; aFormats++) {
     switch (*aFormats) {
       case AV_PIX_FMT_YUV444P:
         FFMPEG_LOG("Requesting pixel format YUV444P.");
         return AV_PIX_FMT_YUV444P;
       case AV_PIX_FMT_YUV420P:
-      case AV_PIX_FMT_YUVJ420P:
         FFMPEG_LOG("Requesting pixel format YUV420P.");
         return AV_PIX_FMT_YUV420P;
+      case AV_PIX_FMT_YUVJ420P:
+        FFMPEG_LOG("Requesting pixel format YUVJ420P.");
+        return AV_PIX_FMT_YUVJ420P;
       default:
         break;
     }
   }
 
   NS_WARNING("FFmpeg does not share any supported pixel formats.");
   return AV_PIX_FMT_NONE;
 }
--- a/dom/media/test/external/README.md
+++ b/dom/media/test/external/README.md
@@ -1,17 +1,33 @@
 external-media-tests
 ===================
 
 [Marionette Python tests][marionette-python-tests] for media playback in Mozilla Firefox. MediaTestCase uses [Firefox Puppeteer][ff-puppeteer-docs] library.
 
 Setup
 -----
 
-Normally, you get this source by cloning a firefox repo such as mozilla-central. The path to these tests would be in <mozilla-central>/dom/media/test/external, and these instuctions refer to this path as '$PROJECT_HOME'.
+Normally, you get this source by cloning a firefox repo such as mozilla-central. The path to these tests would be in <mozilla-central>/dom/media/test/external, and these instructions refer to this path as '$PROJECT_HOME'.
+
+Running from a build
+--------------------
+
+If you have built Firefox using ./mach build from a source tree such as mozilla-central, you can run the following command:
+
+    '''sh
+    $ ./mach external-media-tests
+    '''
+
+You can pass any of the test options on this command line. They are listed below.
+
+Running with an installer and a tests payload
+---------------------------------------------
+
+If you are testing a version of Firefox that you have not built, you must setup a virtualenv to run tests from. You will need a path to the installer or binary of Firefox.
 
 * Create a virtualenv called `foo`.
 
    ```sh
    $ virtualenv foo
    $ source foo/bin/activate #or `foo\Scripts\activate` on Windows
    ```
 
@@ -22,56 +38,81 @@ Normally, you get this source by cloning
    ```
 
 Now `external-media-tests` should be a recognized command. Try `external-media-tests --help` to see if it works.
 
 
 Running the Tests
 -----------------
 
-In the examples below, `$FF_PATH` is a path to a recent Firefox binary.
+In the examples below, `$FF_PATH` is a path to a recent Firefox binary. If you are running from a source build, the commands below should be invoked with:
+
+    '''sh
+    ./mach external-media-tests
+    '''
+
+If you are running with a virtualenv, you will need to run like this:
+
+    '''sh
+    external-media-tests --binary $FF_PATH
+    '''
+
+or
+
+    '''sh
+    external-media-tests --installer $FF_INSTALLER_PATH
+    '''
+
+or
+
+    '''sh
+    external-media-tests --installer-url <url to installer package>
+    '''
+
+The following examples assume that you will use of these command lines instead of $EXTERNAL-MEDIA-TESTS.
+
 
 This runs all the tests listed in `$PROJECT_HOME/external_media_tests/manifest.ini`:
 
    ```sh
-   $ external-media-tests --binary $FF_PATH
+   $ $EXTERNAL-MEDIA-TESTS
    ```
 
 You can also run all the tests at a particular path:
 
    ```sh
-   $ external-media-tests --binary $FF_PATH some/path/foo
+   $ $EXTERNAL-MEDIA-TESTS some/path/foo
    ```
 
 Or you can run the tests that are listed in a manifest file of your choice.
 
    ```sh
-   $ external-media-tests --binary $FF_PATH some/other/path/manifest.ini
+   $ $EXTERNAL-MEDIA-TESTS some/other/path/manifest.ini
    ```
 
 By default, the urls listed in `external_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
 
    ```sh
-   $ external-media-tests --binary $FF_PATH --urls some/other/path/my_urls.ini
+   $ $EXTERNAL-MEDIA-TESTS --urls some/other/path/my_urls.ini
    ```
 
 ### Running EME tests
 
 In order to run EME tests, you must use a Firefox profile that has a signed plugin-container.exe and voucher.bin. With Netflix, this will be created when you log in and save the credentials. You must also use a custom .ini file for urls to the provider's content and indicate which test to run, like above. Ex:
 
    ```sh
-   $ external-media-tests --binary $FF_PATH some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
+   $ $EXTERNAL-MEDIA-TESTS some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
    ```
 
 
 ### Running tests in a way that provides information about a crash
 
 What if Firefox crashes during a test run? You want to know why! To report useful crash data, the test runner needs access to a "minidump_stackwalk" binary and a "symbols.zip" file.
 
-1. Download a `minidump_stackwalk` binary for your platform (save it whereever). Get it from http://hg.mozilla.org/build/tools/file/tip/breakpad/.
+1. Download a `minidump_stackwalk` binary for your platform (save it wherever). Get it from http://hg.mozilla.org/build/tools/file/tip/breakpad/.
 2. Make `minidump_stackwalk` executable
 
    ```sh
    $ chmod +x path/to/minidump_stackwalk
    ```
 
 3. Create an environment variable called `MINIDUMP_STACKWALK` that points to that local path
 
@@ -79,17 +120,17 @@ 3. Create an environment variable called
    $ export MINIDUMP_STACKWALK=path/to/minidump_stackwalk
    ```
 
 4. Download the `crashreporter-symbols.zip` file for the Firefox build you are testing and extract it. Example: ftp://ftp.mozilla.org/pub/firefox/tinderbox-builds/mozilla-aurora-win32/1427442016/firefox-38.0a2.en-US.win32.crashreporter-symbols.zip
 
 5. Run the tests with a `--symbols-path` flag
 
   ```sh
-   $ external-media-tests --binary $FF_PATH --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
+   $ $EXTERNAL-MEDIA-TESTS --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
   ```
 
 To check whether the above setup is working for you, trigger a (silly) Firefox crash while the tests are running. One way to do this is with the [crashme add-on](https://github.com/luser/crashme) -- you can add it to Firefox even while the tests are running. Another way on Linux and Mac OS systems:
 
 1. Find the process id (PID) of the Firefox process being used by the tests.
 
   ```sh
    $ ps x | grep 'Firefox'
@@ -119,27 +160,25 @@ Crash reason:  EXC_SOFTWARE / SIGABRT
 Crash address: 0x104616900
 ...
 ```
 
 ### Setting up for network shaping tests (browsermobproxy)
 
 1. Download the browsermob proxy zip file from http://bmp.lightbody.net/. The most current version as of this writing is browsermob-proxy-2.1.0-beta-2-bin.zip.
 2. Unpack the .zip file.
-3. Verify that you can launch browsermobproxy on your machine by running \<browsermob\>/bin/browsermob-proxy on your machine. I had to do a lot of work to install and use a java that browsermobproxy would like.
+3. Verify that you can launch browsermobproxy on your machine by running \<browsermob\>/bin/browsermob-proxy (or browsermob-proxy.bat on Windows) on your machine. I had to do a lot of work to install and use a java that browsermobproxy would like.
 4. Import the certificate into your Firefox profile. Select Preferences->Advanced->Certificates->View Certificates->Import... Navigate to <browsermob>/ssl-support and select cybervilliansCA.cer. Select all of the checkboxes.
-5. Tell marionette where browsermobproxy is and what port to start it on. Add the following command-line parameters to your firefox-media-tests command line:
+5. Tell marionette where browsermobproxy is and what port to start it on. Add the following command-line parameters to your external-media-tests command line:
 
 <pre><code>
 --browsermob-script <browsermob>/bin/browsermob-proxy --browsermob-port 999 --profile <your saved profile>
 </code></pre>
 
-On Windows, use browsermob-proxy.bat.
-
-You can then call browsermob to shape the network. You can find an example in firefox_media_tests/playback/test_playback_limiting_bandwidth.py. Another example can be found at https://dxr.mozilla.org/mozilla-central/source/testing/marionette/client/marionette/tests/unit/test_browsermobproxy.py.
+You can then call browsermob to shape the network. You can find an example in external_media_tests/playback/test_playback_limiting_bandwidth.py. Another example can be found at https://dxr.mozilla.org/mozilla-central/source/testing/marionette/client/marionette/tests/unit/test_browsermobproxy.py.
 
 ### A warning about video URLs
 The ini files in `external_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
 
 Writing a test
 --------------
 Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/external_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
 
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1660,17 +1660,17 @@ nsresult nsPluginInstanceOwner::Dispatch
 
 #ifndef XP_MACOSX
   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) {
     // continue only for cases without child window
     return aFocusEvent->PreventDefault(); // consume event
   }
 #endif
 
-  WidgetEvent* theEvent = aFocusEvent->GetInternalNSEvent();
+  WidgetEvent* theEvent = aFocusEvent->WidgetEventPtr();
   if (theEvent) {
     WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->mMessage,
                               nullptr);
     nsEventStatus rv = ProcessEvent(focusEvent);
     if (nsEventStatus_eConsumeNoDefault == rv) {
       aFocusEvent->PreventDefault();
       aFocusEvent->StopPropagation();
     }
@@ -1702,17 +1702,17 @@ nsresult nsPluginInstanceOwner::Dispatch
 #if !defined(XP_MACOSX)
   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
     return aKeyEvent->PreventDefault(); // consume event
   // continue only for cases without child window
 #endif
 
   if (mInstance) {
     WidgetKeyboardEvent* keyEvent =
-      aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+      aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
     if (keyEvent && keyEvent->mClass == eKeyboardEventClass) {
       nsEventStatus rv = ProcessEvent(*keyEvent);
       if (nsEventStatus_eConsumeNoDefault == rv) {
         aKeyEvent->PreventDefault();
         aKeyEvent->StopPropagation();
       }
     }
   }
@@ -1737,17 +1737,17 @@ nsPluginInstanceOwner::ProcessMouseDown(
     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     if (fm) {
       nsCOMPtr<nsIDOMElement> elem = do_QueryReferent(mContent);
       fm->SetFocus(elem, 0);
     }
   }
 
   WidgetMouseEvent* mouseEvent =
-    aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
+    aMouseEvent->WidgetEventPtr()->AsMouseEvent();
   if (mouseEvent && mouseEvent->mClass == eMouseEventClass) {
     mLastMouseDownButtonType = mouseEvent->button;
     nsEventStatus rv = ProcessEvent(*mouseEvent);
     if (nsEventStatus_eConsumeNoDefault == rv) {
       return aMouseEvent->PreventDefault(); // consume event
     }
   }
 
@@ -1762,17 +1762,17 @@ nsresult nsPluginInstanceOwner::Dispatch
     return aMouseEvent->PreventDefault(); // consume event
   // continue only for cases without child window
 #endif
   // don't send mouse events if we are hidden
   if (!mWidgetVisible)
     return NS_OK;
 
   WidgetMouseEvent* mouseEvent =
-    aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
+    aMouseEvent->WidgetEventPtr()->AsMouseEvent();
   if (mouseEvent && mouseEvent->mClass == eMouseEventClass) {
     nsEventStatus rv = ProcessEvent(*mouseEvent);
     if (nsEventStatus_eConsumeNoDefault == rv) {
       aMouseEvent->PreventDefault();
       if (!aAllowPropagate) {
         aMouseEvent->StopPropagation();
       }
     }
@@ -1877,17 +1877,17 @@ nsPluginInstanceOwner::DispatchCompositi
 {
 #ifdef XP_WIN
   if (!mPluginWindow) {
     // CompositionEvent isn't cancellable.  So it is unnecessary to call
     // PreventDefaults() to consume event
     return NS_OK;
   }
   WidgetCompositionEvent* compositionEvent =
-    aEvent->GetInternalNSEvent()->AsCompositionEvent();
+    aEvent->WidgetEventPtr()->AsCompositionEvent();
   if (NS_WARN_IF(!compositionEvent)) {
       return NS_ERROR_INVALID_ARG;
   }
 
   if (compositionEvent->mMessage == eCompositionChange) {
     RefPtr<TextComposition> composition = GetTextComposition();
     if (NS_WARN_IF(!composition)) {
       return NS_ERROR_FAILURE;
@@ -2020,17 +2020,17 @@ nsPluginInstanceOwner::HandleEvent(nsIDO
   if (eventType.EqualsLiteral("compositionstart") ||
       eventType.EqualsLiteral("compositionend") ||
       eventType.EqualsLiteral("text")) {
     return DispatchCompositionToPlugin(aEvent);
   }
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
   if (dragEvent && mInstance) {
-    WidgetEvent* ievent = aEvent->GetInternalNSEvent();
+    WidgetEvent* ievent = aEvent->WidgetEventPtr();
     if (ievent && ievent->mFlags.mIsTrusted &&
         ievent->mMessage != eDragEnter && ievent->mMessage != eDragOver) {
       aEvent->PreventDefault();
     }
 
     // Let the plugin handle drag events.
     aEvent->StopPropagation();
   }
--- a/dom/plugins/test/unit/test_bug455213.js
+++ b/dom/plugins/test/unit/test_bug455213.js
@@ -17,17 +17,17 @@ function write_registry(version, info) {
   header += "Version" + DELIM + version + DELIM + "$\n\n";
   header += "[PLUGINS]\n";
 
   var registry = gProfD.clone();
   registry.append("pluginreg.dat");
   var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                            .createInstance(Components.interfaces.nsIFileOutputStream);
   // write, create, truncate
-  foStream.init(registry, 0x02 | 0x08 | 0x20, 0666, 0);
+  foStream.init(registry, 0x02 | 0x08 | 0x20, 0o666, 0);
 
   var charset = "UTF-8"; // Can be any character encoding name that Mozilla supports
   var os = Cc["@mozilla.org/intl/converter-output-stream;1"].
            createInstance(Ci.nsIConverterOutputStream);
   os.init(foStream, charset, 0, 0x0000);
 
   os.writeString(header);
   os.writeString(info);
--- a/dom/plugins/test/unit/test_bug813245.js
+++ b/dom/plugins/test/unit/test_bug813245.js
@@ -21,17 +21,17 @@ function write_registry(version, info) {
   header += "\n";
   header += "[PLUGINS]\n";
 
   var registry = gProfD.clone();
   registry.append("pluginreg.dat");
   var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                            .createInstance(Components.interfaces.nsIFileOutputStream);
   // write, create, truncate
-  foStream.init(registry, 0x02 | 0x08 | 0x20, 0666, 0);
+  foStream.init(registry, 0x02 | 0x08 | 0x20, 0o666, 0);
 
   var charset = "UTF-8"; // Can be any character encoding name that Mozilla supports
   var os = Cc["@mozilla.org/intl/converter-output-stream;1"].
            createInstance(Ci.nsIConverterOutputStream);
   os.init(foStream, charset, 0, 0x0000);
 
   os.writeString(header);
   os.writeString(info);
--- a/dom/plugins/test/unit/test_persist_in_prefs.js
+++ b/dom/plugins/test/unit/test_persist_in_prefs.js
@@ -21,17 +21,17 @@ function write_registry(version, info) {
   header += "\n";
   header += "[PLUGINS]\n";
 
   let registry = gProfD.clone();
   registry.append("pluginreg.dat");
   let foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                            .createInstance(Components.interfaces.nsIFileOutputStream);
   // write, create, truncate
-  foStream.init(registry, 0x02 | 0x08 | 0x20, 0666, 0);
+  foStream.init(registry, 0x02 | 0x08 | 0x20, 0o666, 0);
 
   let charset = "UTF-8"; // Can be any character encoding name that Mozilla supports
   let os = Cc["@mozilla.org/intl/converter-output-stream;1"].
            createInstance(Ci.nsIConverterOutputStream);
   os.init(foStream, charset, 0, 0x0000);
 
   os.writeString(header);
   os.writeString(info);
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -259,17 +259,17 @@ public:
   DispatchExtendableEventOnWorkerScope(JSContext* aCx,
                                        WorkerGlobalScope* aWorkerScope,
                                        ExtendableEvent* aEvent,
                                        Promise** aWaitUntilPromise)
   {
     MOZ_ASSERT(aWorkerScope);
     MOZ_ASSERT(aEvent);
     nsCOMPtr<nsIGlobalObject> sgo = aWorkerScope;
-    WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
+    WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
 
     ErrorResult result;
     result = aWorkerScope->DispatchDOMEvent(nullptr, aEvent, nullptr, nullptr);
     if (NS_WARN_IF(result.Failed()) || internalEvent->mFlags.mExceptionHasBeenRisen) {
       result.SuppressException();
       return;
     }
 
@@ -1218,17 +1218,17 @@ private:
     event->SetTrusted(true);
 
     RefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
     nsresult rv2 = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) {
       nsCOMPtr<nsIRunnable> runnable;
       if (event->DefaultPrevented(aCx)) {
         event->ReportCanceled();
-      } else if (event->GetInternalNSEvent()->mFlags.mExceptionHasBeenRisen) {
+      } else if (event->WidgetEventPtr()->mFlags.mExceptionHasBeenRisen) {
         // Exception logged via the WorkerPrivate ErrorReporter
       } else {
         runnable = new ResumeRequest(mInterceptedChannel);
       }
 
       if (!runnable) {
         nsCOMPtr<nsIRunnable> updateRunnable =
           new RegistrationUpdateRunnable(mRegistration, false /* time check */);
--- a/dom/workers/ServiceWorkerRegistrar.cpp
+++ b/dom/workers/ServiceWorkerRegistrar.cpp
@@ -136,51 +136,59 @@ ServiceWorkerRegistrar::GetRegistrations
   if (firstTime) {
     firstTime = false;
     Telemetry::AccumulateTimeDelta(
       Telemetry::SERVICE_WORKER_REGISTRATION_LOADING,
       startTime);
   }
 }
 
+namespace {
+
+bool Equivalent(const ServiceWorkerRegistrationData& aLeft,
+                const ServiceWorkerRegistrationData& aRight)
+{
+  MOZ_ASSERT(aLeft.principal().type() ==
+             mozilla::ipc::PrincipalInfo::TContentPrincipalInfo);
+  MOZ_ASSERT(aRight.principal().type() ==
+             mozilla::ipc::PrincipalInfo::TContentPrincipalInfo);
+
+  const auto& leftPrincipal = aLeft.principal().get_ContentPrincipalInfo();
+  const auto& rightPrincipal = aRight.principal().get_ContentPrincipalInfo();
+
+  // Only compare the attributes, not the spec part of the principal.
+  // The scope comparison above already covers the origin and codebase
+  // principals include the full path in their spec which is not what
+  // we want here.
+  return aLeft.scope() == aRight.scope() &&
+         leftPrincipal.attrs() == rightPrincipal.attrs();
+}
+
+} // anonymous namespace
+
 void
 ServiceWorkerRegistrar::RegisterServiceWorker(
                                      const ServiceWorkerRegistrationData& aData)
 {
   AssertIsOnBackgroundThread();
 
   if (mShuttingDown) {
     NS_WARNING("Failed to register a serviceWorker during shutting down.");
     return;
   }
 
   {
     MonitorAutoLock lock(mMonitor);
     MOZ_ASSERT(mDataLoaded);
 
-    const mozilla::ipc::PrincipalInfo& newPrincipalInfo = aData.principal();
-    MOZ_ASSERT(newPrincipalInfo.type() ==
-               mozilla::ipc::PrincipalInfo::TContentPrincipalInfo);
-
-    const mozilla::ipc::ContentPrincipalInfo& newContentPrincipalInfo =
-      newPrincipalInfo.get_ContentPrincipalInfo();
-
     bool found = false;
     for (uint32_t i = 0, len = mData.Length(); i < len; ++i) {
-      if (mData[i].scope() == aData.scope()) {
-        const mozilla::ipc::PrincipalInfo& existingPrincipalInfo =
-          mData[i].principal();
-        const mozilla::ipc::ContentPrincipalInfo& existingContentPrincipalInfo =
-          existingPrincipalInfo.get_ContentPrincipalInfo();
-
-        if (newContentPrincipalInfo == existingContentPrincipalInfo) {
-          mData[i] = aData;
-          found = true;
-          break;
-        }
+      if (Equivalent(aData, mData[i])) {
+        found = true;
+        break;
       }
     }
 
     if (!found) {
       mData.AppendElement(aData);
     }
   }
 
@@ -200,19 +208,22 @@ ServiceWorkerRegistrar::UnregisterServic
   }
 
   bool deleted = false;
 
   {
     MonitorAutoLock lock(mMonitor);
     MOZ_ASSERT(mDataLoaded);
 
+    ServiceWorkerRegistrationData tmp;
+    tmp.principal() = aPrincipalInfo;
+    tmp.scope() = aScope;
+
     for (uint32_t i = 0; i < mData.Length(); ++i) {
-      if (mData[i].principal() == aPrincipalInfo &&
-          mData[i].scope() == aScope) {
+      if (Equivalent(tmp, mData[i])) {
         mData.RemoveElementAt(i);
         deleted = true;
         break;
       }
     }
   }
 
   if (deleted) {
@@ -310,19 +321,21 @@ ServiceWorkerRegistrar::ReadData()
   }
 
   if (!IsSupportedVersion(version)) {
     nsContentUtils::LogMessageToConsole(nsPrintfCString(
       "Unsupported service worker registrar version: %s", version.get()).get());
     return NS_ERROR_FAILURE;
   }
 
+  nsTArray<ServiceWorkerRegistrationData> tmpData;
+
   bool overwrite = false;
   while (hasMoreLines) {
-    ServiceWorkerRegistrationData* entry = mData.AppendElement();
+    ServiceWorkerRegistrationData* entry = tmpData.AppendElement();
 
 #define GET_LINE(x)                                   \
     rv = lineInputStream->ReadLine(x, &hasMoreLines); \
     if (NS_WARN_IF(NS_FAILED(rv))) {                  \
       return rv;                                      \
     }                                                 \
     if (NS_WARN_IF(!hasMoreLines)) {                  \
       return NS_ERROR_FAILURE;                        \
@@ -390,16 +403,38 @@ ServiceWorkerRegistrar::ReadData()
 
     if (!line.EqualsLiteral(SERVICEWORKERREGISTRAR_TERMINATOR)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   stream->Close();
 
+  // Dedupe data in file.  Old profiles had many duplicates.  In theory
+  // we can remove this in the future. (Bug 1248449)
+  for (uint32_t i = 0; i < tmpData.Length(); ++i) {
+    bool match = false;
+    for (uint32_t j = 0; j < mData.Length(); ++j) {
+      // Use same comparison as RegisterServiceWorker. Scope contains
+      // basic origin information.  Combine with any principal attributes.
+      if (Equivalent(tmpData[i], mData[j])) {
+        // Last match wins, just like legacy loading used to do in
+        // the ServiceWorkerManager.
+        mData[j] = tmpData[i];
+        // Dupe found, so overwrite file with reduced list.
+        overwrite = true;
+        match = true;
+        break;
+      }
+    }
+    if (!match) {
+      mData.AppendElement(tmpData[i]);
+    }
+  }
+
   // Overwrite previous version.
   // Cannot call SaveData directly because gtest uses main-thread.
   if (overwrite && NS_FAILED(WriteData())) {
     NS_WARNING("Failed to write data for the ServiceWorker Registations.");
     DeleteData();
   }
 
   return NS_OK;
--- a/dom/workers/test/fileapi_chromeScript.js
+++ b/dom/workers/test/fileapi_chromeScript.js
@@ -6,17 +6,17 @@ var fileNum = 1;
 function createFileWithData(fileData) {
   var willDelete = fileData === null;
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
   var testFile = dirSvc.get("ProfD", Ci.nsIFile);
   testFile.append("fileAPItestfile" + fileNum);
   fileNum++;
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
-                 0666, 0);
+                 0o666, 0);
   if (willDelete) {
     fileData = "some irrelevant test data\n";
   }
   outStream.write(fileData, fileData.length);
   outStream.close();
   var domFile = new File(testFile);
   if (willDelete) {
     testFile.remove(/* recursive: */ false);
--- a/dom/workers/test/gtest/TestReadWrite.cpp
+++ b/dom/workers/test/gtest/TestReadWrite.cpp
@@ -152,17 +152,17 @@ TEST(ServiceWorkerRegistrar, TestReadDat
   ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
 
   RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
 
   nsresult rv = swr->TestReadData();
   ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
 
   const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
-  ASSERT_EQ((uint32_t)2, data.Length()) << "4 entries should be found";
+  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
 
   const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
   ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
   const mozilla::ipc::ContentPrincipalInfo& cInfo0 = data[0].principal();
 
   nsAutoCString suffix0;
   cInfo0.attrs().CreateSuffix(suffix0);
 
@@ -307,14 +307,77 @@ TEST(ServiceWorkerRegistrar, TestVersion
 
   ASSERT_STREQ("", suffix1.get());
   ASSERT_STREQ("spec 1", cInfo1.spec().get());
   ASSERT_STREQ("scope 1", data[1].scope().get());
   ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
   ASSERT_STREQ("activeCache 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
 }
 
+TEST(ServiceWorkerRegistrar, TestDedupe)
+{
+  nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n");
+
+  // unique entries
+  buffer.Append("^appId=123&inBrowser=1\n");
+  buffer.Append("spec 0\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
+  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
+
+  buffer.Append("\n");
+  buffer.Append("spec 1\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
+  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
+
+  // dupe entries
+  buffer.Append("^appId=123&inBrowser=1\n");
+  buffer.Append("spec 1\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
+  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
+
+  buffer.Append("^appId=123&inBrowser=1\n");
+  buffer.Append("spec 2\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
+  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
+
+  buffer.Append("\n");
+  buffer.Append("spec 3\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
+  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
+
+  ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
+
+  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
+
+  nsresult rv = swr->TestReadData();
+  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
+
+  const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
+  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
+
+  const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
+  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
+  const mozilla::ipc::ContentPrincipalInfo& cInfo0 = data[0].principal();
+
+  nsAutoCString suffix0;
+  cInfo0.attrs().CreateSuffix(suffix0);
+
+  ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
+  ASSERT_STREQ("spec 2", cInfo0.spec().get());
+  ASSERT_STREQ("scope 0", data[0].scope().get());
+  ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
+  ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
+
+  const mozilla::ipc::PrincipalInfo& info1 = data[1].principal();
+  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
+  const mozilla::ipc::ContentPrincipalInfo& cInfo1 = data[1].principal();
+
+  nsAutoCString suffix1;
+  cInfo1.attrs().CreateSuffix(suffix1);
+
+  ASSERT_STREQ("", suffix1.get());
+  ASSERT_STREQ("spec 3", cInfo1.spec().get());
+  ASSERT_STREQ("scope 1", data[1].scope().get());
+  ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
+  ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
+}
+
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
 
   int rv = RUN_ALL_TESTS();
   return rv;
 }
--- a/dom/xbl/nsXBLEventHandler.cpp
+++ b/dom/xbl/nsXBLEventHandler.cpp
@@ -85,17 +85,17 @@ nsXBLKeyEventHandler::~nsXBLKeyEventHand
 NS_IMPL_ISUPPORTS(nsXBLKeyEventHandler, nsIDOMEventListener)
 
 bool
 nsXBLKeyEventHandler::ExecuteMatchedHandlers(
                         nsIDOMKeyEvent* aKeyEvent,
                         uint32_t aCharCode,
                         const IgnoreModifierState& aIgnoreModifierState)
 {
-  WidgetEvent* event = aKeyEvent->AsEvent()->GetInternalNSEvent();
+  WidgetEvent* event = aKeyEvent->AsEvent()->WidgetEventPtr();
   nsCOMPtr<EventTarget> target = aKeyEvent->AsEvent()->InternalDOMEvent()->GetCurrentTarget();
 
   bool executed = false;
   for (uint32_t i = 0; i < mProtoHandlers.Length(); ++i) {
     nsXBLPrototypeHandler* handler = mProtoHandlers[i];
     bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
     if ((event->mFlags.mIsTrusted ||
         (hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -900,17 +900,17 @@ nsXBLPrototypeHandler::ReportKeyConflict
                                   nullptr, EmptyString(), mLineNumber);
 }
 
 bool
 nsXBLPrototypeHandler::ModifiersMatchMask(
                          nsIDOMUIEvent* aEvent,
                          const IgnoreModifierState& aIgnoreModifierState)
 {
-  WidgetInputEvent* inputEvent = aEvent->AsEvent()->GetInternalNSEvent()->AsInputEvent();
+  WidgetInputEvent* inputEvent = aEvent->AsEvent()->WidgetEventPtr()->AsInputEvent();
   NS_ENSURE_TRUE(inputEvent, false);
 
   if (mKeyMask & cMetaMask) {
     if (inputEvent->IsMeta() != ((mKeyMask & cMeta) != 0)) {
       return false;
     }
   }
 
--- a/dom/xbl/nsXBLWindowKeyHandler.cpp
+++ b/dom/xbl/nsXBLWindowKeyHandler.cpp
@@ -317,24 +317,24 @@ nsXBLWindowKeyHandler::HandleEvent(nsIDO
 
   return WalkHandlers(keyEvent, eventTypeAtom);
 }
 
 void
 nsXBLWindowKeyHandler::HandleEventOnCapture(nsIDOMKeyEvent* aEvent)
 {
   WidgetKeyboardEvent* widgetEvent =
-    aEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
 
   if (widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding) {
     return;
   }
 
   nsCOMPtr<mozilla::dom::Element> originalTarget =
-    do_QueryInterface(aEvent->AsEvent()->GetInternalNSEvent()->originalTarget);
+    do_QueryInterface(aEvent->AsEvent()->WidgetEventPtr()->originalTarget);
   if (!EventStateManager::IsRemoteTarget(originalTarget)) {
     return;
   }
 
   bool aReservedForChrome = false;
   if (!HasHandlerForEvent(aEvent, &aReservedForChrome)) {
     return;
   }
@@ -560,17 +560,17 @@ nsXBLWindowKeyHandler::WalkHandlersAndEx
 
 #ifdef XP_WIN
   // Windows native applications ignore Windows-Logo key state when checking
   // shortcut keys even if the key is pressed.  Therefore, if there is no
   // shortcut key which exactly matches current modifier state, we should
   // retry to look for a shortcut key without the Windows-Logo key press.
   if (!aIgnoreModifierState.mOS) {
     WidgetKeyboardEvent* keyEvent =
-      aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+      aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
     if (keyEvent && keyEvent->IsOS()) {
       IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
       ignoreModifierState.mOS = true;
       return WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler, aCharCode,
                                     ignoreModifierState, aExecute);
     }
   }
 #endif
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -4611,17 +4611,17 @@ nsEditor::HandleKeyPressEvent(nsIDOMKeyE
   // NOTE: When you change this method, you should also change:
   //   * editor/libeditor/tests/test_texteditor_keyevent_handling.html
   //   * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
   //
   // And also when you add new key handling, you need to change the subclass's
   // HandleKeyPressEvent()'s switch statement.
 
   WidgetKeyboardEvent* nativeKeyEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
                "HandleKeyPressEvent gets non-keypress event");
 
   // if we are readonly or disabled, then do nothing.
   if (IsReadonly() || IsDisabled()) {
     // consume backspace for disabled and readonly textfields, to prevent
     // back in history, which could be confusing to users
@@ -5048,17 +5048,17 @@ nsEditor::IsActiveInDOMWindow()
 }
 
 bool
 nsEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
 {
   // If the event is trusted, the event should always cause input.
   NS_ENSURE_TRUE(aEvent, false);
 
-  WidgetEvent* widgetEvent = aEvent->GetInternalNSEvent();
+  WidgetEvent* widgetEvent = aEvent->WidgetEventPtr();
   if (NS_WARN_IF(!widgetEvent)) {
     return false;
   }
 
   // If this is dispatched by using cordinates but this editor doesn't have
   // focus, we shouldn't handle it.
   if (widgetEvent->IsUsingCoordinates()) {
     nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
@@ -5081,17 +5081,17 @@ nsEditor::IsAcceptableInputEvent(nsIDOME
       return false;
     case eCompositionStart:
     case eCompositionEnd:
     case eCompositionUpdate:
     case eCompositionChange:
     case eCompositionCommitAsIs:
       // Don't allow composition events whose internal event are not
       // WidgetCompositionEvent.
-      widgetGUIEvent = aEvent->GetInternalNSEvent()->AsCompositionEvent();
+      widgetGUIEvent = aEvent->WidgetEventPtr()->AsCompositionEvent();
       needsWidget = true;
       break;
     default:
       break;
   }
   if (needsWidget &&
       (!widgetGUIEvent || !widgetGUIEvent->widget)) {
     return false;
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -352,17 +352,17 @@ NS_IMPL_ISUPPORTS(nsEditorEventListener,
 
 NS_IMETHODIMP
 nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   NS_ENSURE_TRUE(mEditor, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIEditor> kungFuDeathGrip = mEditor;
 
-  WidgetEvent* internalEvent = aEvent->GetInternalNSEvent();
+  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
 
   // Let's handle each event with the message of the internal event of the
   // coming event.  If the DOM event was created with improper interface,
   // e.g., keydown event is created with |new MouseEvent("keydown", {});|,
   // its message is always 0.  Therefore, we can ban such strange event easy.
   // However, we need to handle strange "focus" and "blur" event.  See the
   // following code of this switch statement.
   // NOTE: Each event handler may require specific event interface.  Before
@@ -636,17 +636,17 @@ nsEditorEventListener::KeyPress(nsIDOMKe
   }
 
   if (!ShouldHandleNativeKeyBindings(aKeyEvent)) {
     return NS_OK;
   }
 
   // Now, ask the native key bindings to handle the event.
   WidgetKeyboardEvent* keyEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   MOZ_ASSERT(keyEvent,
              "DOM key event's internal event must be WidgetKeyboardEvent");
   nsIWidget* widget = keyEvent->widget;
   // If the event is created by chrome script, the widget is always nullptr.
   if (!widget) {
     nsCOMPtr<nsIPresShell> ps = GetPresShell();
     nsPresContext* pc = ps ? ps->GetPresContext() : nullptr;
     widget = pc ? pc->GetNearestWidget() : nullptr;
@@ -1042,17 +1042,17 @@ nsEditorEventListener::CanDrop(nsIDOMDra
 
 nsresult
 nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
 {
   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     return NS_OK;
   }
   WidgetCompositionEvent* compositionStart =
-    aCompositionEvent->GetInternalNSEvent()->AsCompositionEvent();
+    aCompositionEvent->WidgetEventPtr()->AsCompositionEvent();
   return mEditor->BeginIMEComposition(compositionStart);
 }
 
 void
 nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
 {
   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     return;
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -612,17 +612,17 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOM
 
   if (IsReadonly() || IsDisabled()) {
     // When we're not editable, the events are handled on nsEditor, so, we can
     // bypass nsPlaintextEditor.
     return nsEditor::HandleKeyPressEvent(aKeyEvent);
   }
 
   WidgetKeyboardEvent* nativeKeyEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
     case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
@@ -5177,17 +5177,17 @@ nsHTMLEditor::IsAcceptableInputEvent(nsI
 {
   if (!nsEditor::IsAcceptableInputEvent(aEvent)) {
     return false;
   }
 
   // While there is composition, all composition events in its top level window
   // are always fired on the composing editor.  Therefore, if this editor has
   // composition, the composition events should be handled in this editor.
-  if (mComposition && aEvent->GetInternalNSEvent()->AsCompositionEvent()) {
+  if (mComposition && aEvent->WidgetEventPtr()->AsCompositionEvent()) {
     return true;
   }
 
   NS_ENSURE_TRUE(mDocWeak, false);
 
   nsCOMPtr<nsIDOMEventTarget> target;
   aEvent->GetTarget(getter_AddRefs(target));
   NS_ENSURE_TRUE(target, false);
--- a/editor/libeditor/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/nsPlaintextDataTransfer.cpp
@@ -179,17 +179,17 @@ nsresult nsPlaintextEditor::InsertFromDr
 
   nsCOMPtr<nsIDOMDocument> srcdomdoc;
   if (sourceNode) {
     sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
     NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
   }
 
   if (nsContentUtils::CheckForSubFrameDrop(dragSession,
-        aDropEvent->GetInternalNSEvent()->AsDragEvent())) {
+        aDropEvent->WidgetEventPtr()->AsDragEvent())) {
     // Don't allow drags from subframe documents with different origins than
     // the drop destination.
     if (srcdomdoc && !IsSafeToInsertData(srcdomdoc))
       return NS_OK;
   }
 
   // Current doc is destination
   nsCOMPtr<nsIDOMDocument> destdomdoc = GetDOMDocument();
--- a/editor/libeditor/nsPlaintextEditor.cpp
+++ b/editor/libeditor/nsPlaintextEditor.cpp
@@ -357,17 +357,17 @@ nsPlaintextEditor::HandleKeyPressEvent(n
   // HandleKeyPressEvent()'s switch statement.
 
   if (IsReadonly() || IsDisabled()) {
     // When we're not editable, the events handled on nsEditor.
     return nsEditor::HandleKeyPressEvent(aKeyEvent);
   }
 
   WidgetKeyboardEvent* nativeKeyEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
   NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
                "HandleKeyPressEvent gets non-keypress event");
 
   switch (nativeKeyEvent->keyCode) {
     case nsIDOMKeyEvent::DOM_VK_META:
     case nsIDOMKeyEvent::DOM_VK_WIN:
     case nsIDOMKeyEvent::DOM_VK_SHIFT:
@@ -843,17 +843,17 @@ nsPlaintextEditor::BeginIMEComposition(W
 }
 
 nsresult
 nsPlaintextEditor::UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent)
 {
   MOZ_ASSERT(aDOMTextEvent, "aDOMTextEvent must not be nullptr");
 
   WidgetCompositionEvent* compositionChangeEvent =
-    aDOMTextEvent->GetInternalNSEvent()->AsCompositionEvent();
+    aDOMTextEvent->WidgetEventPtr()->AsCompositionEvent();
   NS_ENSURE_TRUE(compositionChangeEvent, NS_ERROR_INVALID_ARG);
   MOZ_ASSERT(compositionChangeEvent->mMessage == eCompositionChange,
              "The internal event should be eCompositionChange");
 
   EnsureComposition(compositionChangeEvent);
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
--- a/embedding/components/windowwatcher/nsAutoWindowStateHelper.cpp
+++ b/embedding/components/windowwatcher/nsAutoWindowStateHelper.cpp
@@ -58,15 +58,15 @@ nsAutoWindowStateHelper::DispatchEventTo
 
   ErrorResult rv;
   RefPtr<Event> event = doc->CreateEvent(NS_LITERAL_STRING("Events"), rv);
   if (rv.Failed()) {
     return false;
   }
   event->InitEvent(NS_ConvertASCIItoUTF16(aEventName), true, true);
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   nsCOMPtr<EventTarget> target = do_QueryInterface(mWindow);
   bool defaultActionEnabled;
   target->DispatchEvent(event, &defaultActionEnabled);
   return defaultActionEnabled;
 }
--- a/extensions/cookie/test/unit/test_permmanager_defaults.js
+++ b/extensions/cookie/test/unit/test_permmanager_defaults.js
@@ -25,17 +25,17 @@ add_task(function* do_test() {
 
   // create a file in the temp directory with the defaults.
   let file = do_get_tempdir();
   file.append("test_default_permissions");
 
   // write our test data to it.
   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                 createInstance(Ci.nsIFileOutputStream);
-  ostream.init(file, -1, 0666, 0);
+  ostream.init(file, -1, 0o666, 0);
   let conv = Cc["@mozilla.org/intl/converter-output-stream;1"].
              createInstance(Ci.nsIConverterOutputStream);
   conv.init(ostream, "UTF-8", 0, 0);
 
   conv.writeString("# this is a comment\n");
   conv.writeString("\n"); // a blank line!
   conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN.host + "\n");
   conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_2.host + "\n");
--- a/extensions/cookie/test/unit/test_permmanager_removeall.js
+++ b/extensions/cookie/test/unit/test_permmanager_removeall.js
@@ -12,25 +12,25 @@ function run_test() {
   // get the db file
   var file = dir.clone();
   file.append("permissions.sqlite");
   do_check_true(file.exists());
 
   // corrupt the file
   var ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                 createInstance(Ci.nsIFileOutputStream);
-  ostream.init(file, 0x02, 0666, 0);
+  ostream.init(file, 0x02, 0o666, 0);
   var conv = Cc["@mozilla.org/intl/converter-output-stream;1"].
              createInstance(Ci.nsIConverterOutputStream);
   conv.init(ostream, "UTF-8", 0, 0);
   for (var i = 0; i < file.fileSize; ++i)
     conv.writeString("a");
   conv.close();
 
   // prepare an empty hostperm.1 file so that it can be used for importing
   var hostperm = dir.clone();
   hostperm.append("hostperm.1");
-  ostream.init(hostperm, 0x02 | 0x08, 0666, 0);
+  ostream.init(hostperm, 0x02 | 0x08, 0o666, 0);
   ostream.close();
 
   // remove all should not throw
   pm.removeAll();
 }
--- a/extensions/spellcheck/hunspell/tests/unit/test_hunspell.js
+++ b/extensions/spellcheck/hunspell/tests/unit/test_hunspell.js
@@ -125,17 +125,17 @@ const tests = [
 ];
 
 function do_get_file_by_line(file, charset) {
   dump("getting file by line for file " + file.path + "\n");
   dump("using charset " + charset +"\n");
   let fis = Cc["@mozilla.org/network/file-input-stream;1"].
               createInstance(Ci.nsIFileInputStream);
   fis.init(file, 0x1 /* READONLY */,
-           0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
+           0o444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
 
   let lis = Cc["@mozilla.org/intl/converter-input-stream;1"].
               createInstance(Ci.nsIConverterInputStream);
   lis.init(fis, charset, 1024, 0);
   lis.QueryInterface(Ci.nsIUnicharLineInputStream);
 
   var val = {};
   while (lis.readLine(val)) {
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -62,16 +62,17 @@ struct DeviceAttachmentsD3D11
 {
   DeviceAttachmentsD3D11(ID3D11Device* device)
    : mSyncHandle(0),
      mDevice(device),
      mInitOkay(true)
   {}
 
   bool CreateShaders();
+  bool InitBlendShaders();
   bool InitSyncObject();
 
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
           VertexShaderArray;
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
           PixelShaderArray;
 
   RefPtr<ID3D11InputLayout> mInputLayout;
@@ -966,17 +967,19 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
     // If the blend operation needs to read from the backdrop, copy the
     // current render target into a new texture and bind it now.
     if (BlendOpIsMixBlendMode(blendMode)) {
       gfx::Matrix4x4 backdropTransform;
       gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect, aTransform, &backdropTransform);
 
       RefPtr<ID3D11ShaderResourceView> srv;
-      if (CopyBackdrop(rect, &mixBlendBackdrop, &srv)) {
+      if (CopyBackdrop(rect, &mixBlendBackdrop, &srv) &&
+          mAttachments->InitBlendShaders())
+      {
         vertexShader = mAttachments->mVSQuadBlendShader[maskType];
         pixelShader = mAttachments->mBlendShader[MaskType::MaskNone];
 
         ID3D11ShaderResourceView* srView = srv.get();
         mContext->PSSetShaderResources(TexSlot::Backdrop, 1, &srView);
 
         memcpy(&mVSConstants.backdropTransform, &backdropTransform._11, 64);
 
@@ -1487,35 +1490,45 @@ DeviceAttachmentsD3D11::InitSyncObject()
     }));
     return false;
   }
 
   return true;
 }
 
 bool
+DeviceAttachmentsD3D11::InitBlendShaders()
+{
+  if (!mVSQuadBlendShader[MaskType::MaskNone]) {
+    InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
+    InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d);
+    InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d);
+  }
+  if (!mBlendShader[MaskType::MaskNone]) {
+    InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
+  }
+  return mInitOkay;
+}
+
+bool
 DeviceAttachmentsD3D11::CreateShaders()
 {
   InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone);
   InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask2d);
   InitVertexShader(sLayerQuadMask3DVS, mVSQuadShader, MaskType::Mask3d);
-  InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
-  InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d);
-  InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d);
 
   InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone);
   InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask2d);
   InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone);
   InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask2d);
   InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone);
   InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask2d);
   InitPixelShader(sRGBAShaderMask3D, mRGBAShader, MaskType::Mask3d);
   InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone);
   InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask2d);
-  InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
   if (gfxPrefs::ComponentAlphaEnabled()) {
     InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone);
     InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask2d);
   }
 
   InitVertexShader(sOculus050VRDistortionVS, getter_AddRefs(mVRDistortionVS[VRHMDType::Oculus050]));
   InitPixelShader(sOculus050VRDistortionPS, getter_AddRefs(mVRDistortionPS[VRHMDType::Oculus050]));
 
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -2963,20 +2963,21 @@ void gfxFontGroup::ComputeRanges(nsTArra
         }
 
         if (lastRangeIndex == -1) {
             // first char ==> make a new range
             aRanges.AppendElement(gfxTextRange(0, 1, font, matchType, orient));
             lastRangeIndex++;
             prevFont = font;
         } else {
-            // if font has changed, make a new range
+            // if font or orientation has changed, make a new range...
+            // unless ch is a variation selector (bug 1248248)
             gfxTextRange& prevRange = aRanges[lastRangeIndex];
             if (prevRange.font != font || prevRange.matchType != matchType ||
-                prevRange.orientation != orient) {
+                (prevRange.orientation != orient && !IsClusterExtender(ch))) {
                 // close out the previous range
                 prevRange.end = origI;
                 aRanges.AppendElement(gfxTextRange(origI, i + 1,
                                                    font, matchType, orient));
                 lastRangeIndex++;
 
                 // update prevFont for the next match, *unless* we switched
                 // fonts on a ZWJ, in which case propagating the changed font
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -197,19 +197,19 @@ GetFilterOffsetAndLength(UniquePtr<skia:
 {
   MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
   aFilter->FilterForValue(aOutputImagePosition,
                           aFilterOffsetOut,
                           aFilterLengthOut);
 }
 
 void
-Downscaler::ClearRow(uint32_t aStartingAtCol)
+Downscaler::ClearRestOfRow(uint32_t aStartingAtCol)
 {
-  MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
+  MOZ_ASSERT(int64_t(aStartingAtCol) <= int64_t(mOriginalSize.width));
   uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
                         * sizeof(uint32_t);
   memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
          0, bytesToClear);
 }
 
 void
 Downscaler::CommitRow()
--- a/image/Downscaler.h
+++ b/image/Downscaler.h
@@ -87,18 +87,21 @@ public:
   bool IsFrameComplete() const { return mCurrentInLine >= mOriginalSize.height; }
 
   /// Retrieves the buffer into which the Decoder should write each row.
   uint8_t* RowBuffer()
   {
     return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
   }
 
-  /// Clears the current row buffer (optionally starting at @aStartingAtCol).
-  void ClearRow(uint32_t aStartingAtCol = 0);
+  /// Clears the current row buffer.
+  void ClearRow() { ClearRestOfRow(0); }
+
+  /// Clears the current row buffer starting at @aStartingAtCol.
+  void ClearRestOfRow(uint32_t aStartingAtCol);
 
   /// Signals that the decoder has finished writing a row into the row buffer.
   void CommitRow();
 
   /// Returns true if there is a non-empty invalid rect available.
   bool HasInvalidation() const;
 
   /// Takes the Downscaler's current invalid rect and resets it.
@@ -161,17 +164,18 @@ public:
 
   nsresult BeginFrame(const nsIntSize&, const Maybe<nsIntRect>&, uint8_t*, bool, bool = false)
   {
     return NS_ERROR_FAILURE;
   }
 
   bool IsFrameComplete() const { return false; }
   uint8_t* RowBuffer() { return nullptr; }
-  void ClearRow(uint32_t = 0) { }
+  void ClearRow() { }
+  void ClearRestOfRow(uint32_t) { }
   void CommitRow() { }
   bool HasInvalidation() const { return false; }
   DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }
   void ResetForNextProgressivePass() { }
   const nsIntSize FrameSize() const { return nsIntSize(0, 0); }
 };
 
 #endif // MOZ_ENABLE_SKIA
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -989,17 +989,17 @@ nsBMPDecoder::ReadRLEDelta(const char* a
   // Delta encoding makes it possible to skip pixels making part of the image
   // transparent.
   MOZ_ASSERT(mMayHaveTransparency);
   mDoesHaveTransparency = true;
 
   if (mDownscaler) {
     // Clear the skipped pixels. (This clears to the end of the row,
     // which is perfect if there's a Y delta and harmless if not).
-    mDownscaler->ClearRow(/* aStartingAtCol = */ mCurrentPos);
+    mDownscaler->ClearRestOfRow(/* aStartingAtCol = */ mCurrentPos);
   }
 
   // Handle the XDelta.
   mCurrentPos += uint8_t(aData[0]);
   if (mCurrentPos > mH.mWidth) {
     mCurrentPos = mH.mWidth;
   }
 
new file mode 100644
--- /dev/null
+++ b/image/test/crashtests/1242093-1.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset='UTF-8'>
+<meta http-equiv='Cache-control' content='no-cache'>
+</head>
+<body>
+<img id='m1' src='data:image/bmp;base64,Qk1mDgAAAAAAAHYAAAAoAAAAQAEAAPAAAAABAAQAAgAAAPANAADoAwAA6AMAABAAAAAAAAAA/wD/AAAAAAAAAP8AAP8AAP8AAAD///8AzMzMAMzMzADMzMwAzMzMAMzMzADMzMwAzMzMAMzMzADMzMwAzMzMAAACAAEAAgABAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAAAAAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRCAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBpRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAIAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICADgRMCIAAmoAakQAAAACAgA4ETAiAAJqAGpEAAAAAgIABhEBVQURA1UDEQFVCREEVQIRBFUCEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVCREBVQURAVUFEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVCREBVQURAVUFEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQRVBhEBVQURA1UDEQNVBhEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVAxEBVQURAVUFEQFVBREBVQgRAVUGETAiAAJqAGpEAAAAAgIABhEBVQQRAVUDEQFVAhEBVQMRAVUFEQFVBREBVQURAVUIEQFVBhEwIgACagBqRAAAAAICAAMRB1UCEQNVAxEEVQYRAVUFEQRVAhEEVQIRB1UDETAiAAJqAGpEAAAAAgIAOBEwIgACagBqRAAAAAICADgRMCIAAmoAakQAAAACAAEAAgABAAE='>
+<img id='m2' height='2' width='2'>
+<canvas id='c1'></canvas>
+<script>
+  var im1=document.getElementById('m1');
+  var im2=document.getElementById('m2');
+  im2.src=im1.src;
+  window.onload=function(){
+    var ctx=document.getElementById('c1').getContext('2d');
+    ctx.drawImage(im1, 0, 0); // sync docoder call
+    ctx.drawImage(im2, 0, 0); // sync downscaler call
+  }
+</script>
+</body>
+</html>
\ No newline at end of file
--- a/image/test/crashtests/crashtests.list
+++ b/image/test/crashtests/crashtests.list
@@ -12,16 +12,17 @@ load 732319-1.html
 load 844403-1.html
 load 856616.gif
 skip-if(B2G) load 944353.jpg
 load 1205923-1.html
 load 1212954-1.svg
 load 1235605.gif
 load 1241728-1.html
 load 1241729-1.html
+load 1242093-1.html
 load 1242778-1.png
 load colormap-range.gif
 HTTP load delayedframe.sjs # A 3-frame animated GIF with an inordinate delay between the second and third frame
 
 # Animated gifs with a very large canvas, but tiny actual content.
 skip-if(B2G) load delaytest.html?523528-1.gif
 skip-if(B2G) load delaytest.html?523528-2.gif
 
--- a/image/test/unit/test_imgtools.js
+++ b/image/test/unit/test_imgtools.js
@@ -14,17 +14,17 @@ var Cc = Components.classes;
  */
 function dumpToFile(aData) {
     var outputFile = do_get_tempdir();
     outputFile.append("testdump.png");
 
     var outputStream = Cc["@mozilla.org/network/file-output-stream;1"].
                        createInstance(Ci.nsIFileOutputStream);
     // WR_ONLY|CREAT|TRUNC
-    outputStream.init(outputFile, 0x02 | 0x08 | 0x20, 0644, null);
+    outputStream.init(outputFile, 0x02 | 0x08 | 0x20, 0o644, null);
 
     var bos = Cc["@mozilla.org/binaryoutputstream;1"].
               createInstance(Ci.nsIBinaryOutputStream);
     bos.setOutputStream(outputStream);
 
     bos.writeByteArray(aData, aData.length);
 
     outputStream.close();
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -788,16 +788,17 @@ class GCRuntime
 
     uint64_t majorGCCount() const { return majorGCNumber; }
     void incMajorGcNumber() { ++majorGCNumber; ++number; }
 
     int64_t defaultSliceBudget() const { return defaultTimeBudget_; }
 
     bool isIncrementalGc() const { return isIncremental; }
     bool isFullGc() const { return isFull; }
+    bool isCompactingGc() const { return isCompacting; }
 
     bool shouldCleanUpEverything() { return cleanUpEverything; }
 
     bool areGrayBitsValid() const { return grayBitsValid; }
     void setGrayBitsInvalid() { grayBitsValid = false; }
 
     bool minorGCRequested() const { return minorGCTriggerReason != JS::gcreason::NO_REASON; }
     bool majorGCRequested() const { return majorGCTriggerReason != JS::gcreason::NO_REASON; }
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -928,16 +928,17 @@ Statistics::endGC()
 
     runtime->addTelemetry(JS_TELEMETRY_GC_IS_COMPARTMENTAL, !zoneStats.isCollectingAllZones());
     runtime->addTelemetry(JS_TELEMETRY_GC_MS, t(total));
     runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
     int64_t markTotal = SumPhase(PHASE_MARK, phaseTimes);
     int64_t markRootsTotal = SumPhase(PHASE_MARK_ROOTS, phaseTimes);
     runtime->addTelemetry(JS_TELEMETRY_GC_MARK_MS, t(markTotal));
     runtime->addTelemetry(JS_TELEMETRY_GC_SWEEP_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_SWEEP]));
+    runtime->addTelemetry(JS_TELEMETRY_GC_COMPACT_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_COMPACT]));
     runtime->addTelemetry(JS_TELEMETRY_GC_MARK_ROOTS_MS, t(markRootsTotal));
     runtime->addTelemetry(JS_TELEMETRY_GC_MARK_GRAY_MS, t(phaseTimes[PHASE_DAG_NONE][PHASE_SWEEP_MARK_GRAY]));
     runtime->addTelemetry(JS_TELEMETRY_GC_NON_INCREMENTAL, !!nonincrementalReason_);
     runtime->addTelemetry(JS_TELEMETRY_GC_INCREMENTAL_DISABLED, !runtime->gc.isIncrementalGCAllowed());
     runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal));
     runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
 
     if (!aborted) {
--- a/js/src/jit-test/lib/bullet.js
+++ b/js/src/jit-test/lib/bullet.js
@@ -1264,17 +1264,17 @@ function copyTempDouble(ptr) {
         }}};
   var MEMFS={CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,ensureFlexible:function (node) {
         if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
           var contents = node.contents;
           node.contents = Array.prototype.slice.call(contents);
           node.contentMode = MEMFS.CONTENT_FLEXIBLE;
         }
       },mount:function (mount) {
-        return MEMFS.create_node(null, '/', 0040000 | 0777, 0);
+        return MEMFS.create_node(null, '/', 0o040000 | 0o777, 0);
       },create_node:function (parent, name, mode, dev) {
         if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
           // no supported
           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
         }
         var node = FS.createNode(parent, name, mode, dev);
         if (FS.isDir(node.mode)) {
           node.node_ops = {
@@ -1402,17 +1402,17 @@ function copyTempDouble(ptr) {
           for (var key in node.contents) {
             if (!node.contents.hasOwnProperty(key)) {
               continue;
             }
             entries.push(key);
           }
           return entries;
         },symlink:function (parent, newname, oldpath) {
-          var node = MEMFS.create_node(parent, newname, 0777 | 0120000, 0);
+          var node = MEMFS.create_node(parent, newname, 0o777 | 0o120000, 0);
           node.link = oldpath;
           return node;
         },readlink:function (node) {
           if (!FS.isLink(node.mode)) {
             throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
           }
           return node.link;
         }},stream_ops:{read:function (stream, buffer, offset, length, position) {
@@ -1652,29 +1652,29 @@ function copyTempDouble(ptr) {
         return node;
       },destroyNode:function (node) {
         FS.hashRemoveNode(node);
       },isRoot:function (node) {
         return node === node.parent;
       },isMountpoint:function (node) {
         return node.mounted;
       },isFile:function (mode) {
-        return (mode & 0170000) === 0100000;
+        return (mode & 0o170000) === 0o100000;
       },isDir:function (mode) {
-        return (mode & 0170000) === 0040000;
+        return (mode & 0o170000) === 0o040000;
       },isLink:function (mode) {
-        return (mode & 0170000) === 0120000;
+        return (mode & 0o170000) === 0o120000;
       },isChrdev:function (mode) {
-        return (mode & 0170000) === 0020000;
+        return (mode & 0o170000) === 0o020000;
       },isBlkdev:function (mode) {
-        return (mode & 0170000) === 0060000;
+        return (mode & 0o170000) === 0o060000;
       },isFIFO:function (mode) {
-        return (mode & 0170000) === 0010000;
+        return (mode & 0o170000) === 0o010000;
       },isSocket:function (mode) {
-        return (mode & 0140000) === 0140000;
+        return (mode & 0o140000) === 0o140000;
       },flagModes:{"r":0,"rs":8192,"r+":2,"w":1537,"wx":3585,"xw":3585,"w+":1538,"wx+":3586,"xw+":3586,"a":521,"ax":2569,"xa":2569,"a+":522,"ax+":2570,"xa+":2570},modeStringToFlags:function (str) {
         var flags = FS.flagModes[str];
         if (typeof flags === 'undefined') {
           throw new Error('Unknown file open mode: ' + str);
         }
         return flags;
       },flagsToPermissionString:function (flag) {
         var accmode = flag & 3;
@@ -1831,31 +1831,31 @@ function copyTempDouble(ptr) {
         if (err) {
           throw new FS.ErrnoError(err);
         }
         if (!parent.node_ops.mknod) {
           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
         }
         return parent.node_ops.mknod(parent, name, mode, dev);
       },create:function (path, mode) {
-        mode = mode !== undefined ? mode : 0666;
+        mode = mode !== undefined ? mode : 0o666;
         mode &= 4095;
-        mode |= 0100000;
+        mode |= 0o100000;
         return FS.mknod(path, mode, 0);
       },mkdir:function (path, mode) {
-        mode = mode !== undefined ? mode : 0777;
-        mode &= 511 | 0001000;
-        mode |= 0040000;
+        mode = mode !== undefined ? mode : 0o777;
+        mode &= 511 | 0o001000;
+        mode |= 0o040000;
         return FS.mknod(path, mode, 0);
       },mkdev:function (path, mode, dev) {
         if (typeof(dev) === 'undefined') {
           dev = mode;
-          mode = 0666;
-        }
-        mode |= 0020000;
+          mode = 0o666;
+        }
+        mode |= 0o020000;
         return FS.mknod(path, mode, dev);
       },symlink:function (oldpath, newpath) {
         var lookup = FS.lookupPath(newpath, { parent: true });
         var parent = lookup.node;
         var newname = PATH.basename(newpath);
         var err = FS.mayCreate(parent, newname);
         if (err) {
           throw new FS.ErrnoError(err);
@@ -2091,26 +2091,26 @@ function copyTempDouble(ptr) {
         var lookup = FS.lookupPath(path, { follow: true });
         var node = lookup.node;
         node.node_ops.setattr(node, {
           timestamp: Math.max(atime, mtime)
         });
       },open:function (path, flags, mode, fd_start, fd_end) {
         path = PATH.normalize(path);
         flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
-        mode = typeof mode === 'undefined' ? 0666 : mode;
+        mode = typeof mode === 'undefined' ? 0o666 : mode;
         if ((flags & 512)) {
-          mode = (mode & 4095) | 0100000;
+          mode = (mode & 4095) | 0o100000;
         } else {
           mode = 0;
         }
         var node;
         try {
           var lookup = FS.lookupPath(path, {
-            follow: !(flags & 0200000)
+            follow: !(flags & 0o200000)
           });
           node = lookup.node;
           path = lookup.path;
         } catch (e) {
           // ignore
         }
         // perhaps we need to create the node
         if ((flags & 512)) {
@@ -2340,17 +2340,17 @@ function copyTempDouble(ptr) {
         var stdout = FS.open('/dev/stdout', 'w');
         HEAP32[((_stdout)>>2)]=stdout.fd;
         assert(stdout.fd === 2, 'invalid handle for stdout (' + stdout.fd + ')');
         var stderr = FS.open('/dev/stderr', 'w');
         HEAP32[((_stderr)>>2)]=stderr.fd;
         assert(stderr.fd === 3, 'invalid handle for stderr (' + stderr.fd + ')');
       },staticInit:function () {
         FS.nameTable = new Array(4096);
-        FS.root = FS.createNode(null, '/', 0040000 | 0777, 0);
+        FS.root = FS.createNode(null, '/', 0o040000 | 0o777, 0);
         FS.mount(MEMFS, {}, '/');
         FS.createDefaultDirectories();
         FS.createDefaultDevices();
       },init:function (input, output, error) {
         assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
         FS.init.initialized = true;
         // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
         Module['stdin'] = input || Module['stdin'];
@@ -2762,17 +2762,17 @@ function copyTempDouble(ptr) {
             };
             getRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
           });
           transaction.onerror = onerror;
         };
         openRequest.onerror = onerror;
       }};
   var SOCKFS={mount:function (mount) {
-        return FS.createNode(null, '/', 0040000 | 0777, 0);
+        return FS.createNode(null, '/', 0o040000 | 0o777, 0);
       },nextname:function () {
         if (!SOCKFS.nextname.current) {
           SOCKFS.nextname.current = 0;
         }
         return 'socket[' + (SOCKFS.nextname.current++) + ']';
       },createSocket:function (family, type, protocol) {
         var streaming = type == 1;
         if (protocol) {
@@ -2786,17 +2786,17 @@ function copyTempDouble(ptr) {
           server: null,
           peers: {},
           pending: [],
           recv_queue: [],
           sock_ops: SOCKFS.websocket_sock_ops
         };
         // create the filesystem node to store the socket structure
         var name = SOCKFS.nextname();
-        var node = FS.createNode(SOCKFS.root, name, 0140000, 0);
+        var node = FS.createNode(SOCKFS.root, name, 0o140000, 0);
         node.sock = sock;
         // and the wrapping stream that enables library functions such
         // as read and write to indirectly interact with the socket
         var stream = FS.createStream({
           path: name,
           node: node,
           flags: FS.modeStringToFlags('r+'),
           seekable: false,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -911,63 +911,64 @@ JS_TransplantObject(JSContext* cx, Handl
     AssertHeapIsIdle(cx);
     MOZ_ASSERT(origobj != target);
     MOZ_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
     MOZ_ASSERT(!target->is<CrossCompartmentWrapperObject>());
 
     RootedValue origv(cx, ObjectValue(*origobj));
     RootedObject newIdentity(cx);
 
-    {
-        AutoDisableProxyCheck adpc(cx->runtime());
-
-        JSCompartment* destination = target->compartment();
-
-        if (origobj->compartment() == destination) {
-            // If the original object is in the same compartment as the
-            // destination, then we know that we won't find a wrapper in the
-            // destination's cross compartment map and that the same
-            // object will continue to work.
-            if (!JSObject::swap(cx, origobj, target))
-                MOZ_CRASH();
-            newIdentity = origobj;
-        } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
-            // There might already be a wrapper for the original object in
-            // the new compartment. If there is, we use its identity and swap
-            // in the contents of |target|.
-            newIdentity = &p->value().get().toObject();
-
-            // When we remove origv from the wrapper map, its wrapper, newIdentity,
-            // must immediately cease to be a cross-compartment wrapper. Nuke it.
-            destination->removeWrapper(p);
-            NukeCrossCompartmentWrapper(cx, newIdentity);
-
-            if (!JSObject::swap(cx, newIdentity, target))
-                MOZ_CRASH();
-        } else {
-            // Otherwise, we use |target| for the new identity object.
-            newIdentity = target;
-        }
-
-        // Now, iterate through other scopes looking for references to the
-        // old object, and update the relevant cross-compartment wrappers.
-        if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
+    // Don't allow a compacting GC to observe any intermediate state.
+    AutoDisableCompactingGC nocgc(cx->runtime());
+
+    AutoDisableProxyCheck adpc(cx->runtime());
+
+    JSCompartment* destination = target->compartment();
+
+    if (origobj->compartment() == destination) {
+        // If the original object is in the same compartment as the
+        // destination, then we know that we won't find a wrapper in the
+        // destination's cross compartment map and that the same
+        // object will continue to work.
+        if (!JSObject::swap(cx, origobj, target))
             MOZ_CRASH();
-
-        // Lastly, update the original object to point to the new one.
-        if (origobj->compartment() != destination) {
-            RootedObject newIdentityWrapper(cx, newIdentity);
-            AutoCompartment ac(cx, origobj);
-            if (!JS_WrapObject(cx, &newIdentityWrapper))
-                MOZ_CRASH();
-            MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
-            if (!JSObject::swap(cx, origobj, newIdentityWrapper))
-                MOZ_CRASH();
-            origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
-        }
+        newIdentity = origobj;
+    } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
+        // There might already be a wrapper for the original object in
+        // the new compartment. If there is, we use its identity and swap
+        // in the contents of |target|.
+        newIdentity = &p->value().get().toObject();
+
+        // When we remove origv from the wrapper map, its wrapper, newIdentity,
+        // must immediately cease to be a cross-compartment wrapper. Nuke it.
+        destination->removeWrapper(p);
+        NukeCrossCompartmentWrapper(cx, newIdentity);
+
+        if (!JSObject::swap(cx, newIdentity, target))
+            MOZ_CRASH();
+    } else {
+        // Otherwise, we use |target| for the new identity object.
+        newIdentity = target;
+    }
+
+    // Now, iterate through other scopes looking for references to the
+    // old object, and update the relevant cross-compartment wrappers.
+    if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
+        MOZ_CRASH();
+
+    // Lastly, update the original object to point to the new one.
+    if (origobj->compartment() != destination) {
+        RootedObject newIdentityWrapper(cx, newIdentity);
+        AutoCompartment ac(cx, origobj);
+        if (!JS_WrapObject(cx, &newIdentityWrapper))
+            MOZ_CRASH();
+        MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
+        if (!JSObject::swap(cx, origobj, newIdentityWrapper))
+            MOZ_CRASH();
+        origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
     }
 
     // The new identity object might be one of several things. Return it to avoid
     // ambiguity.
     return newIdentity;
 }
 
 /*
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -110,16 +110,17 @@ enum {
     JS_TELEMETRY_GC_REASON,
     JS_TELEMETRY_GC_IS_COMPARTMENTAL,
     JS_TELEMETRY_GC_MS,
     JS_TELEMETRY_GC_BUDGET_MS,
     JS_TELEMETRY_GC_ANIMATION_MS,
     JS_TELEMETRY_GC_MAX_PAUSE_MS,
     JS_TELEMETRY_GC_MARK_MS,
     JS_TELEMETRY_GC_SWEEP_MS,
+    JS_TELEMETRY_GC_COMPACT_MS,
     JS_TELEMETRY_GC_MARK_ROOTS_MS,
     JS_TELEMETRY_GC_MARK_GRAY_MS,
     JS_TELEMETRY_GC_SLICE_MS,
     JS_TELEMETRY_GC_SLOW_PHASE,
     JS_TELEMETRY_GC_MMU_50,
     JS_TELEMETRY_GC_RESET,
     JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
     JS_TELEMETRY_GC_NON_INCREMENTAL,
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2000,16 +2000,18 @@ GCRuntime::isCompactingGCEnabled() const
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
     return compactingEnabled && compactingDisabledCount == 0;
 }
 
 AutoDisableCompactingGC::AutoDisableCompactingGC(JSRuntime* rt)
   : gc(rt->gc)
 {
     gc.disableCompactingGC();
+    if (gc.isIncrementalGCInProgress() && gc.isCompactingGc())
+        AutoFinishGC finishGC(rt);
 }
 
 AutoDisableCompactingGC::~AutoDisableCompactingGC()
 {
     gc.enableCompactingGC();
 }
 
 static bool
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -295,17 +295,17 @@ JS_FRIEND_API(JSObject*)
 UnwrapOneChecked(JSObject* obj, bool stopAtWindowProxy = true);
 
 JS_FRIEND_API(bool)
 IsCrossCompartmentWrapper(JSObject* obj);
 
 void
 NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
 
-bool
+void
 RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
 
 JS_FRIEND_API(bool)
 RemapAllWrappersForObject(JSContext* cx, JSObject* oldTarget,
                           JSObject* newTarget);
 
 // API to recompute all cross-compartment wrappers whose source and target
 // match the given filters.
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -489,17 +489,19 @@ js::NukeCrossCompartmentWrappers(JSConte
     }
 
     return true;
 }
 
 // Given a cross-compartment wrapper |wobj|, update it to point to
 // |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
 // useful even if wrapper already points to newTarget.
-bool
+// This operation crashes on failure rather than leaving the heap in an
+// inconsistent state.
+void
 js::RemapWrapper(JSContext* cx, JSObject* wobjArg, JSObject* newTargetArg)
 {
     RootedObject wobj(cx, wobjArg);
     RootedObject newTarget(cx, newTargetArg);
     MOZ_ASSERT(wobj->is<CrossCompartmentWrapperObject>());
     MOZ_ASSERT(!newTarget->is<CrossCompartmentWrapperObject>());
     JSObject* origTarget = Wrapper::wrappedObject(wobj);
     MOZ_ASSERT(origTarget);
@@ -546,18 +548,18 @@ js::RemapWrapper(JSContext* cx, JSObject
 
     // Before swapping, this wrapper came out of wrap(), which enforces the
     // invariant that the wrapper in the map points directly to the key.
     MOZ_ASSERT(Wrapper::wrappedObject(wobj) == newTarget);
 
     // Update the entry in the compartment's wrapper map to point to the old
     // wrapper, which has now been updated (via reuse or swap).
     MOZ_ASSERT(wobj->is<WrapperObject>());
-    wcompartment->putWrapper(cx, CrossCompartmentKey(newTarget), ObjectValue(*wobj));
-    return true;
+    if (!wcompartment->putWrapper(cx, CrossCompartmentKey(newTarget), ObjectValue(*wobj)))
+        MOZ_CRASH();
 }
 
 // Remap all cross-compartment wrappers pointing to |oldTarget| to point to
 // |newTarget|. All wrappers are recomputed.
 JS_FRIEND_API(bool)
 js::RemapAllWrappersForObject(JSContext* cx, JSObject* oldTargetArg,
                               JSObject* newTargetArg)
 {
@@ -570,20 +572,18 @@ js::RemapAllWrappersForObject(JSContext*
 
     for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
         if (WrapperMap::Ptr wp = c->lookupWrapper(origv)) {
             // We found a wrapper. Remember and root it.
             toTransplant.infallibleAppend(wp);
         }
     }
 
-    for (const Value& v : toTransplant) {
-        if (!RemapWrapper(cx, &v.toObject(), newTarget))
-            MOZ_CRASH();
-    }
+    for (const Value& v : toTransplant)
+        RemapWrapper(cx, &v.toObject(), newTarget);
 
     return true;
 }
 
 JS_FRIEND_API(bool)
 js::RecomputeWrappers(JSContext* cx, const CompartmentFilter& sourceFilter,
                       const CompartmentFilter& targetFilter)
 {
@@ -610,14 +610,13 @@ js::RecomputeWrappers(JSContext* cx, con
                 return false;
         }
     }
 
     // Recompute all the wrappers in the list.
     for (const Value& v : toRecompute) {
         JSObject* wrapper = &v.toObject();
         JSObject* wrapped = Wrapper::wrappedObject(wrapper);
-        if (!RemapWrapper(cx, wrapper, wrapped))
-            MOZ_CRASH();
+        RemapWrapper(cx, wrapper, wrapped);
     }
 
     return true;
 }
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -384,19 +384,19 @@ ExecuteState::pushInterpreterFrame(JSCon
 #ifdef _MSC_VER
 # pragma optimize("g", off)
 #endif
 bool
 js::RunScript(JSContext* cx, RunState& state)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-#if defined(NIGHTLY_BUILD) && defined(MOZ_HAVE_RDTSC)
+#if defined(MOZ_HAVE_RDTSC)
     js::AutoStopwatch stopwatch(cx);
-#endif // defined(NIGHTLY_BUILD) && defined(MOZ_HAVE_RDTSC)
+#endif // defined(MOZ_HAVE_RDTSC)
 
     SPSEntryMarker marker(cx->runtime(), state.script());
 
     state.script()->ensureNonLazyCanonicalFunction(cx);
 
     if (jit::IsIonEnabled(cx)) {
         jit::MethodStatus status = jit::CanEnter(cx, state);
         if (status == jit::Method_Error)
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -153,16 +153,20 @@ struct SavedFrame::Lookup {
         principals(principals),
         framePtr(framePtr),
         pc(pc),
         activation(activation)
     {
         MOZ_ASSERT(source);
         MOZ_ASSERT_IF(framePtr.isSome(), pc);
         MOZ_ASSERT_IF(framePtr.isSome(), activation);
+
+#ifdef JS_MORE_DETERMINISTIC
+        column = 0;
+#endif
     }
 
     explicit Lookup(SavedFrame& savedFrame)
       : source(savedFrame.getSource()),
         line(savedFrame.getLine()),
         column(savedFrame.getColumn()),
         functionDisplayName(savedFrame.getFunctionDisplayName()),
         asyncCause(savedFrame.getAsyncCause()),
@@ -419,16 +423,19 @@ void
 SavedFrame::initLine(uint32_t line)
 {
     initReservedSlot(JSSLOT_LINE, PrivateUint32Value(line));
 }
 
 void
 SavedFrame::initColumn(uint32_t column)
 {
+#ifdef JS_MORE_DETERMINISTIC
+    column = 0;
+#endif
     initReservedSlot(JSSLOT_COLUMN, PrivateUint32Value(column));
 }
 
 void
 SavedFrame::initPrincipals(JSPrincipals* principals)
 {
     if (principals)
         JS_HoldPrincipals(principals);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3143,16 +3143,19 @@ AccumulateTelemetryCallback(int id, uint
         Telemetry::Accumulate(Telemetry::GC_MAX_PAUSE_MS, sample);
         break;
       case JS_TELEMETRY_GC_MARK_MS:
         Telemetry::Accumulate(Telemetry::GC_MARK_MS, sample);
         break;
       case JS_TELEMETRY_GC_SWEEP_MS:
         Telemetry::Accumulate(Telemetry::GC_SWEEP_MS, sample);
         break;
+      case JS_TELEMETRY_GC_COMPACT_MS:
+        Telemetry::Accumulate(Telemetry::GC_COMPACT_MS, sample);
+        break;
       case JS_TELEMETRY_GC_MARK_ROOTS_MS:
         Telemetry::Accumulate(Telemetry::GC_MARK_ROOTS_MS, sample);
         break;
       case JS_TELEMETRY_GC_MARK_GRAY_MS:
         Telemetry::Accumulate(Telemetry::GC_MARK_GRAY_MS, sample);
         break;
       case JS_TELEMETRY_GC_SLICE_MS:
         Telemetry::Accumulate(Telemetry::GC_SLICE_MS, sample);
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -1204,17 +1204,17 @@ AccessibleCaretManager::DispatchCaretSta
   init.mCaretVisuallyVisible = mFirstCaret->IsVisuallyVisible() ||
                                 mSecondCaret->IsVisuallyVisible();
   sel->Stringify(init.mSelectedTextContent);
 
   RefPtr<CaretStateChangedEvent> event =
     CaretStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozcaretstatechanged"), init);
 
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   AC_LOG("%s: reason %d, collapsed %d, caretVisible %d", __FUNCTION__,
          init.mReason, init.mCollapsed, init.mCaretVisible);
 
   (new AsyncEventDispatcher(doc, event))->RunDOMEventWhenSafe();
 }
 
 } // namespace mozilla
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3514,17 +3514,17 @@ ContainerState::NewPaintedLayerData(nsDi
                                     bool aShouldFixToViewport)
 {
   PaintedLayerData data;
   data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
   data.mScrollClip = aScrollClip;
   data.mAnimatedGeometryRootOffset = aTopLeft;
   data.mReferenceFrame = aItem->ReferenceFrame();
   data.mSingleItemFixedToViewport = aShouldFixToViewport;
-  data.mBackfaceHidden = aItem->Frame()->BackfaceIsHidden();
+  data.mBackfaceHidden = aItem->Frame()->In3DContextAndBackfaceIsHidden();
   data.mIsCaret = aItem->GetType() == nsDisplayItem::TYPE_CARET;
 
   data.mNewChildLayersIndex = mNewChildLayers.Length();
   NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
   newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
   newLayerEntry->mScrollClip = aScrollClip;
   newLayerEntry->mIsCaret = data.mIsCaret;
   // newLayerEntry->mOpaqueRegion is filled in later from
@@ -4133,17 +4133,17 @@ ContainerState::ProcessDisplayItems(nsDi
        * part of a PaintedLayer.
        */
       mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nullptr);
     } else {
       bool avoidCreatingLayer = (maxLayers != -1 && layerCount >= maxLayers);
       PaintedLayerData* paintedLayerData =
         mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, agrScrollClip,
                                                   itemVisibleRect, false,
-                                                  item->Frame()->BackfaceIsHidden(),
+                                                  item->Frame()->In3DContextAndBackfaceIsHidden(),
                                                   avoidCreatingLayer,
                                                   [&]() {
           layerCount++;
           return NewPaintedLayerData(item, animatedGeometryRoot, agrScrollClip,
                                      topLeft, shouldFixToViewport);
         });
 
       if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1136,17 +1136,17 @@ nsDocumentViewer::PermitUnloadInternal(b
   nsCOMPtr<nsIDocShell> docShell(mContainer);
   nsAutoString text;
   beforeUnload->GetReturnValue(text);
 
   // NB: we nullcheck mDocument because it might now be dead as a result of
   // the event being dispatched.
   if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled && mDocument &&
       (!sBeforeUnloadRequiresInteraction || mDocument->UserHasInteracted()) &&
-      (event->GetInternalNSEvent()->mFlags.mDefaultPrevented ||
+      (event->WidgetEventPtr()->mFlags.mDefaultPrevented ||
        !text.IsEmpty())) {
     // Ask the user if it's ok to unload the current page
 
     nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell);
 
     if (prompt) {
       nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
       if (promptBag) {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2049,17 +2049,17 @@ nsLayoutUtils::HasPseudoStyle(nsIContent
   return pseudoContext != nullptr;
 }
 
 nsPoint
 nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(nsIDOMEvent* aDOMEvent, nsIFrame* aFrame)
 {
   if (!aDOMEvent)
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
-  WidgetEvent* event = aDOMEvent->GetInternalNSEvent();
+  WidgetEvent* event = aDOMEvent->WidgetEventPtr();
   if (!event)
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
   return GetEventCoordinatesRelativeTo(event, aFrame);
 }
 
 nsPoint
 nsLayoutUtils::GetEventCoordinatesRelativeTo(const WidgetEvent* aEvent,
                                              nsIFrame* aFrame)
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -1638,17 +1638,17 @@ nsListControlFrame::MouseUp(nsIDOMEvent*
     // And then NOT get an "onclick" event when when you click down on the select
     // and then up outside of the select
     // the EventStateManager tracks the content of the mouse down and the mouse up
     // to make sure they are the same, and the onclick is sent in the PostHandleEvent
     // depeneding on whether the clickCount is non-zero.
     // So we cheat here by either setting or unsetting the clcikCount in the native event
     // so the right thing happens for the onclick event
     WidgetMouseEvent* mouseEvent =
-      aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
+      aMouseEvent->WidgetEventPtr()->AsMouseEvent();
 
     int32_t selectedIndex;
     if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
       // If it's disabled, disallow the click and leave.
       bool isDisabled = false;
       IsOptionDisabled(selectedIndex, isDisabled);
       if (isDisabled) {
         aMouseEvent->PreventDefault();
@@ -2092,17 +2092,17 @@ nsListControlFrame::KeyDown(nsIDOMEvent*
 
   // Don't check defaultPrevented value because other browsers don't prevent
   // the key navigation of list control even if preventDefault() is called.
   // XXXmats 2015-04-16: the above is not true anymore, Chrome prevents all
   // XXXmats keyboard events, even tabbing, when preventDefault() is called
   // XXXmats in onkeydown. That seems sub-optimal though.
 
   const WidgetKeyboardEvent* keyEvent =
-    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
   MOZ_ASSERT(keyEvent,
     "DOM event must have WidgetKeyboardEvent for its internal event");
 
   if (keyEvent->IsAlt()) {
     if (keyEvent->keyCode == NS_VK_UP || keyEvent->keyCode == NS_VK_DOWN) {
       DropDownToggleKey(aKeyEvent);
     }
     return NS_OK;
@@ -2245,17 +2245,17 @@ nsListControlFrame::KeyPress(nsIDOMEvent
   EventStates eventStates = mContent->AsElement()->State();
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return NS_OK;
   }
 
   AutoIncrementalSearchResetter incrementalSearchResetter;
 
   const WidgetKeyboardEvent* keyEvent =
-    aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
   MOZ_ASSERT(keyEvent,
     "DOM event must have WidgetKeyboardEvent for its internal event");
 
   // Select option with this as the first character
   // XXX Not I18N compliant
 
   // Don't do incremental search if the key event has already consumed.
   if (keyEvent->mFlags.mDefaultPrevented) {
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1160,16 +1160,22 @@ nsIFrame::Combines3DTransformWithAncesto
 {
   if (!GetParent() || !GetParent()->Extend3DContext()) {
     return false;
   }
   return StyleDisplay()->HasTransform(this) || StyleDisplay()->BackfaceIsHidden();
 }
 
 bool
+nsIFrame::In3DContextAndBackfaceIsHidden() const
+{
+  return Combines3DTransformWithAncestors() && StyleDisplay()->BackfaceIsHidden();
+}
+
+bool
 nsIFrame::HasPerspective() const
 {
   if (!IsTransformed()) {
     return false;
   }
   nsIFrame* containingBlock = GetContainingBlock(SKIP_SCROLLED_FRAME);
   if (!containingBlock) {
     return false;
@@ -2101,18 +2107,16 @@ nsIFrame::BuildDisplayListForStackingCon
 
   mozilla::gfx::VRDeviceProxy* vrHMDInfo = nullptr;
   if ((GetStateBits() & NS_FRAME_HAS_VR_CONTENT)) {
     vrHMDInfo = static_cast<mozilla::gfx::VRDeviceProxy*>(mContent->GetProperty(nsGkAtoms::vr_state));
   }
 
   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
-  nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex perspectiveIndex(aBuilder, this);
-
   if (isTransformed || useBlendMode || usingSVGEffects || useFixedPosition || useStickyPosition) {
     // We don't need to pass ancestor clipping down to our children;
     // everything goes inside a display item's child list, and the display
     // item itself will be clipped.
     // For transforms we also need to clear ancestor clipping because it's
     // relative to the wrong display item reference frame anyway.
     // We clear both regular and scroll clips here. Our content needs to be
     // able to walk up the complete cross stacking context scroll clip chain,
@@ -2121,16 +2125,19 @@ nsIFrame::BuildDisplayListForStackingCon
     clipState.ClearForStackingContextContents();
   }
 
   nsDisplayListCollection set;
   {
     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
     nsDisplayListBuilder::AutoInTransformSetter
       inTransformSetter(aBuilder, inTransform);
+    nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex
+      perspectiveIndex(aBuilder, this);
+
     CheckForApzAwareEventHandlers(aBuilder, this);
 
     nsRect clipPropClip;
     if (ApplyClipPropClipping(aBuilder, this, disp, &clipPropClip,
                               nestedClipState)) {
       dirtyRect.IntersectRect(dirtyRect, clipPropClip);
     }
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1271,16 +1271,23 @@ public:
 
   /**
    * Returns whether this frame has a parent that Extend3DContext() and has
    * its own transform (or hidden backface) to be combined with the parent's
    * transform.
    */
   bool Combines3DTransformWithAncestors() const;
 
+  /**
+   * Returns whether this frame has a hidden backface and has a parent that
+   * Extend3DContext(). This is useful because in some cases the hidden
+   * backface can safely be ignored if it could not be visible anyway.
+   */
+  bool In3DContextAndBackfaceIsHidden() const;
+
   bool IsPreserve3DLeaf() const {
     return Combines3DTransformWithAncestors() && !Extend3DContext();
   }
 
   bool HasPerspective() const;
 
   bool ChildrenHavePerspective() const;
 
--- a/layout/printing/nsPrintPreviewListener.cpp
+++ b/layout/printing/nsPrintPreviewListener.cpp
@@ -107,17 +107,17 @@ enum eEventAction {
   eEventAction_Propagate, eEventAction_Suppress,
   eEventAction_StopPropagation
 };
 
 static eEventAction
 GetActionForEvent(nsIDOMEvent* aEvent)
 {
   WidgetKeyboardEvent* keyEvent =
-    aEvent->GetInternalNSEvent()->AsKeyboardEvent();
+    aEvent->WidgetEventPtr()->AsKeyboardEvent();
   if (!keyEvent) {
     return eEventAction_Suppress;
   }
 
   if (keyEvent->mFlags.mInSystemGroup) {
     NS_ASSERTION(keyEvent->mMessage == eKeyDown,
       "Assuming we're listening only keydown event in system group");
     return eEventAction_StopPropagation;
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -350,16 +350,19 @@ include transform/reftest.list
 # 3d transforms
 include transform-3d/reftest.list
 
 # unicode/ (verify that we don't do expend effort doing unicode-aware case checks)
 include unicode/reftest.list
 
 include view-source/reftest.list
 
+# web-animations
+include web-animations/reftest.list
+
 # webcomponents/
 include webcomponents/reftest.list
 
 # widget/
 include ../../widget/reftests/reftest.list
 
 # xml-stylesheet/
 include ../../dom/tests/reftest/xml-stylesheet/reftest.list
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/1245450-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style type="text/css">
+  .scene {
+    perspective: 1000px;
+    transform-style: preserve-3d;
+    transform: rotateY(0deg);
+  }
+
+  .card {
+    perspective: 1000px;
+    transform-style: preserve-3d;
+    backface-visibility: hidden;
+    width: 100px;
+    height: 100px;
+  }
+
+  .front {
+    transform: rotateY(0deg);
+    background-color: #00FF00;
+  }
+
+  .back {
+    transform: rotateY(180deg);
+    background-color: #FF0000;
+  }
+</style>
+</head>
+<body>
+  <div class="scene">
+    <div class="card front"></div>
+    <div class="card back"></div>
+  </div>
+</body>
+</html>
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -66,8 +66,9 @@ fuzzy(3,99) fuzzy-if(/^Windows\x20NT\x20
 != animate-cube-radians-ref.html animate-cube-radians-zoom-ref.html
 fuzzy(3,99) == animate-cube-degrees.html animate-cube-degrees-ref.html # subpixel AA
 == animate-cube-degrees-zoom.html animate-cube-degrees-zoom-ref.html
 != animate-cube-degrees-ref.html animate-cube-degrees-zoom-ref.html
 fuzzy-if(B2G||Android||OSX==1010,143,100) fuzzy-if(winWidget||OSX<1010,141,100) fuzzy-if(gtkWidget,128,100) == preserves3d-nested.html preserves3d-nested-ref.html
 fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
 fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
 == animate-backface-hidden.html about:blank
+== 1245450-1.html green-rect.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/web-animations/1246046-1.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html class="reftest-wait">
+  <head>
+    <meta charset=utf-8>
+    <title>Bug 1246046</title>
+    <style>
+      div {
+        width: 0px;
+        height: 100px;
+        background: green;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+    <script>
+      var target = document.querySelector("div");
+      var anim = target.animate(
+        [ { width: "0px" }, { width: "200px" } ], 2000);
+      anim.pause();
+      anim.currentTime = 1000;
+      document.documentElement.removeAttribute("class");
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/web-animations/green-box.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset=utf-8>
+    <title>Reference green box</title>
+    <style>
+      div {
+        width: 100px;
+        height: 100px;
+        background: green;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/web-animations/reftest.list
@@ -0,0 +1,1 @@
+== 1246046-1.html green-box.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1248248-1-orientation-break-glyphrun-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url('../fonts/gw1270797.ttf') format("truetype");
+}
+html {
+  font-size: 72pt;
+  font-family: test, sans-serif;
+  writing-mode: vertical-rl;
+  text-orientation: mixed;
+}
+</style>
+</head>
+<body>
+&#xFA19;&#xFA19;&#xFA19;&#xFA19;
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1248248-1-orientation-break-glyphrun.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url('../fonts/gw1270797.ttf') format("truetype");
+}
+html {
+  font-size: 72pt;
+  font-family: test, sans-serif;
+  writing-mode: vertical-rl;
+  text-orientation: mixed;
+}
+</style>
+</head>
+<body>
+&#xFA19;&#x795E;&#xE0100;&#x795E;&#xE0103;&#x795E;&#xFE00;
+</body>
+</html>
--- a/layout/reftests/writing-mode/reftest.list
+++ b/layout/reftests/writing-mode/reftest.list
@@ -164,14 +164,16 @@ fuzzy-if(gtkWidget||B2G,255,6) fuzzy-if(
 == 1196887-1-computed-display-inline-block.html 1196887-1-computed-display-inline-block-ref.html
 == 1205787-legacy-svg-values-1.html 1205787-legacy-svg-values-1-ref.html
 
 == 1216747-1.html 1216747-1-ref.html
 != 1216747-1.html 1216747-1-notref.html
 
 == 1243125-1-floats-overflowing.html 1243125-1-floats-overflowing-ref.html
 
+HTTP(..) == 1248248-1-orientation-break-glyphrun.html 1248248-1-orientation-break-glyphrun-ref.html
+
 # Suite of tests from Gérard Talbot in bug 1079151
 # Frequent Windows 7 load failed: timed out waiting for test to complete (waiting for onload scripts to complete), bug 1167155 and friends
 skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) include abspos/reftest.list
 
 # Tests for tables with vertical writing modes
 include tables/reftest.list
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -296,56 +296,56 @@ CSSAnimation::ElapsedTimeToTimeStamp(con
 
 ////////////////////////// nsAnimationManager ////////////////////////////
 
 NS_IMPL_CYCLE_COLLECTION(nsAnimationManager, mEventDispatcher)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsAnimationManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsAnimationManager, Release)
 
-nsIStyleRule*
-nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
-                                       mozilla::dom::Element* aElement)
+void
+nsAnimationManager::UpdateAnimations(nsStyleContext* aStyleContext,
+                                     mozilla::dom::Element* aElement)
 {
-  // Ignore animations for print or print preview, and for elements
-  // that are not attached to the document tree.
-  if (!mPresContext->IsDynamic() || !aElement->IsInComposedDoc()) {
-    return nullptr;
-  }
+  MOZ_ASSERT(mPresContext->IsDynamic(),
+             "Should not update animations for print or print preview");
+  MOZ_ASSERT(aElement->IsInComposedDoc(),
+             "Should not update animations that are not attached to the "
+             "document tree");
 
   // Everything that causes our animation data to change triggers a
   // style change, which in turn triggers a non-animation restyle.
   // Likewise, when we initially construct frames, we're not in a
   // style change, but also not in an animation restyle.
 
   const nsStyleDisplay* disp = aStyleContext->StyleDisplay();
   AnimationCollection* collection =
     GetAnimationCollection(aElement,
                            aStyleContext->GetPseudoType(),
                            false /* aCreateIfNeeded */);
   if (!collection &&
       disp->mAnimationNameCount == 1 &&
       disp->mAnimations[0].GetName().IsEmpty()) {
-    return nullptr;
+    return;
   }
 
   nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
 
   // build the animations list
   dom::DocumentTimeline* timeline = aElement->OwnerDoc()->Timeline();
   AnimationPtrArray newAnimations;
   if (!aStyleContext->IsInDisplayNoneSubtree()) {
     BuildAnimations(aStyleContext, aElement, timeline, newAnimations);
   }
 
   if (newAnimations.IsEmpty()) {
     if (collection) {
       collection->Destroy();
     }
-    return nullptr;
+    return;
   }
 
   if (collection) {
     EffectSet* effectSet =
       EffectSet::GetEffectSet(aElement, aStyleContext->GetPseudoType());
     if (effectSet) {
       effectSet->UpdateAnimationGeneration(mPresContext);
     }
@@ -466,35 +466,28 @@ nsAnimationManager::CheckAnimationRule(n
   for (size_t newAnimIdx = newAnimations.Length(); newAnimIdx-- != 0; ) {
     newAnimations[newAnimIdx]->CancelFromStyle();
   }
 
   EffectCompositor::UpdateCascadeResults(aElement,
                                          aStyleContext->GetPseudoType(),
                                          aStyleContext);
 
-  EffectCompositor::CascadeLevel cascadeLevel =
-    EffectCompositor::CascadeLevel::Animations;
-  mPresContext->EffectCompositor()
-              ->MaybeUpdateAnimationRule(aElement,
-                                         aStyleContext->GetPseudoType(),
-                                         cascadeLevel);
+  mPresContext->EffectCompositor()->
+    MaybeUpdateAnimationRule(aElement,
+                             aStyleContext->GetPseudoType(),
+                             EffectCompositor::CascadeLevel::Animations);
 
   // We don't actually dispatch the pending events now.  We'll either
   // dispatch them the next time we get a refresh driver notification
   // or the next time somebody calls
   // nsPresShell::FlushPendingNotifications.
   if (mEventDispatcher.HasQueuedEvents()) {
     mPresContext->Document()->SetNeedStyleFlush();
   }
-
-  return mPresContext->EffectCompositor()
-                     ->GetAnimationRule(aElement,
-                                        aStyleContext->GetPseudoType(),
-                                        cascadeLevel);
 }
 
 void
 nsAnimationManager::StopAnimationsForElement(
   mozilla::dom::Element* aElement,
   nsCSSPseudoElements::Type aPseudoType)
 {
   MOZ_ASSERT(aElement);
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -279,28 +279,25 @@ public:
     : mozilla::CommonAnimationManager(aPresContext)
   {
   }
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsAnimationManager)
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsAnimationManager)
 
   /**
-   * Return the style rule that RulesMatching should add for
-   * aStyleContext.  This might be different from what RulesMatching
-   * actually added during aStyleContext's construction because the
-   * element's animation-name may have changed.  (However, this does
-   * return null during the non-animation restyling phase, as
-   * RulesMatching does.)
+   * Update the set of animations on |aElement| based on |aStyleContext|.
+   * If necessary, this will notify the corresponding EffectCompositor so
+   * that it can update its animation rule.
    *
    * aStyleContext may be a style context for aElement or for its
    * :before or :after pseudo-element.
    */
-  nsIStyleRule* CheckAnimationRule(nsStyleContext* aStyleContext,
-                                   mozilla::dom::Element* aElement);
+  void UpdateAnimations(nsStyleContext* aStyleContext,
+                        mozilla::dom::Element* aElement);
 
   /**
    * Add a pending event.
    */
   void QueueEvent(mozilla::AnimationEventInfo&& aEventInfo)
   {
     mEventDispatcher.QueueEvent(
       mozilla::Forward<mozilla::AnimationEventInfo>(aEventInfo));
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -965,23 +965,34 @@ nsStyleSet::GetContext(nsStyleContext* a
     }
   }
   else {
     NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type");
     NS_ASSERTION(result->GetPseudo() == aPseudoTag, "Unexpected pseudo");
   }
 
   if (aFlags & eDoAnimation) {
-    // Normally the animation manager has already added the correct
-    // style rule.  However, if the animation-name just changed, it
-    // might have been wrong.  So ask it to double-check based on the
-    // resulting style context.
+
     nsIStyleRule *oldAnimRule = GetAnimationRule(aRuleNode);
-    nsIStyleRule *animRule = PresContext()->AnimationManager()->
-      CheckAnimationRule(result, aElementForAnimation);
+    nsIStyleRule *animRule = nullptr;
+
+    // Ignore animations for print or print preview, and for elements
+    // that are not attached to the document tree.
+    if (PresContext()->IsDynamic() &&
+        aElementForAnimation->IsInComposedDoc()) {
+      // Update CSS animations in case the animation-name has just changed.
+      PresContext()->AnimationManager()->UpdateAnimations(result,
+                                                          aElementForAnimation);
+
+      animRule = PresContext()->EffectCompositor()->
+                   GetAnimationRule(aElementForAnimation,
+                                    result->GetPseudoType(),
+                                    EffectCompositor::CascadeLevel::Animations);
+    }
+
     MOZ_ASSERT(result->RuleNode() == aRuleNode,
                "unexpected rule node");
     MOZ_ASSERT(!result->GetStyleIfVisited() == !aVisitedRuleNode,
                "unexpected visited rule node");
     MOZ_ASSERT(!aVisitedRuleNode ||
                result->GetStyleIfVisited()->RuleNode() == aVisitedRuleNode,
                "unexpected visited rule node");
     MOZ_ASSERT(!aVisitedRuleNode ||
--- a/layout/tools/layout-debug/ui/content/layoutdebug.js
+++ b/layout/tools/layout-debug/ui/content/layoutdebug.js
@@ -377,17 +377,17 @@ RTestURLList.prototype = {
   doneURL : function()
   {
     var basename =
       String(this.mCurrentURL.relurl).replace(/[:=&.\/?]/g, "_") + ".rgd";
 
     var data = this.mCurrentURL.dir.clone();
     data.append( this.mIsBaseline ? "baseline" : "verify");
     if (!data.exists())
-      data.create(nsIFile.DIRECTORY_TYPE, 0777)
+      data.create(nsIFile.DIRECTORY_TYPE, 0o777)
     data.append(basename);
 
     dump("Writing regression data to " +
          data.QueryInterface(nsILocalFile).persistentDescriptor + "\n");
     if (this.mIsPrinting) {
       this.mRegressionTester.dumpFrameModel(gBrowser.contentWindow, data,
         nsILayoutRegressionTester.DUMP_FLAGS_MASK_PRINT_MODE);
     }
--- a/layout/xul/nsMenuBarFrame.cpp
+++ b/layout/xul/nsMenuBarFrame.cpp
@@ -161,17 +161,17 @@ nsMenuBarFrame::ToggleMenuActiveState()
 nsMenuFrame*
 nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
 {
   uint32_t charCode;
   aKeyEvent->GetCharCode(&charCode);
 
   AutoTArray<uint32_t, 10> accessKeys;
   WidgetKeyboardEvent* nativeKeyEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   if (nativeKeyEvent)
     nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, accessKeys);
   if (accessKeys.IsEmpty() && charCode)
     accessKeys.AppendElement(charCode);
 
   if (accessKeys.IsEmpty())
     return nullptr; // no character was pressed so just return
 
--- a/layout/xul/nsMenuBarListener.cpp
+++ b/layout/xul/nsMenuBarListener.cpp
@@ -214,17 +214,17 @@ nsMenuBarListener::KeyPress(nsIDOMEvent*
       nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
       uint32_t keyCode, charCode;
       keyEvent->GetKeyCode(&keyCode);
       keyEvent->GetCharCode(&charCode);
 
       bool hasAccessKeyCandidates = charCode != 0;
       if (!hasAccessKeyCandidates) {
         WidgetKeyboardEvent* nativeKeyEvent =
-          aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
+          aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
         if (nativeKeyEvent) {
           AutoTArray<uint32_t, 10> keys;
           nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, keys);
           hasAccessKeyCandidates = !keys.IsEmpty();
         }
       }
 
       // Cancel the access key flag unless we are pressing the access key.
@@ -289,17 +289,17 @@ nsMenuBarListener::IsAccessKeyPressed(ns
           (modifiers & mAccessKeyMask) &&
           (modifiers & ~(mAccessKeyMask | MODIFIER_SHIFT)) == 0);
 }
 
 Modifiers
 nsMenuBarListener::GetModifiersForAccessKey(nsIDOMKeyEvent* aKeyEvent)
 {
   WidgetInputEvent* inputEvent =
-    aKeyEvent->AsEvent()->GetInternalNSEvent()->AsInputEvent();
+    aKeyEvent->AsEvent()->WidgetEventPtr()->AsInputEvent();
   MOZ_ASSERT(inputEvent);
 
   static const Modifiers kPossibleModifiersForAccessKey =
     (MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT | MODIFIER_META |
      MODIFIER_OS);
   return (inputEvent->modifiers & kPossibleModifiersForAccessKey);
 }
 
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -961,17 +961,17 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aE
 {
 #ifdef DEBUG_SLIDER
   printf("Begin dragging\n");
 #endif
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
                             nsGkAtoms::_true, eCaseMatters))
     return NS_OK;
 
-  WidgetGUIEvent* event = aEvent->GetInternalNSEvent()->AsGUIEvent();
+  WidgetGUIEvent* event = aEvent->WidgetEventPtr()->AsGUIEvent();
 
   if (!ShouldScrollForEvent(event)) {
     return NS_OK;
   }
 
   nsPoint pt;
   if (!GetEventPoint(event, pt)) {
     return NS_OK;
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -592,17 +592,17 @@ nsXULPopupManager::InitTriggerEvent(nsID
   nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aEvent);
   if (uiEvent) {
     uiEvent->GetRangeParent(getter_AddRefs(mRangeParent));
     uiEvent->GetRangeOffset(&mRangeOffset);
 
     // get the event coordinates relative to the root frame of the document
     // containing the popup.
     NS_ASSERTION(aPopup, "Expected a popup node");
-    WidgetEvent* event = aEvent->GetInternalNSEvent();
+    WidgetEvent* event = aEvent->WidgetEventPtr();
     if (event) {
       WidgetInputEvent* inputEvent = event->AsInputEvent();
       if (inputEvent) {
         mCachedModifiers = inputEvent->modifiers;
       }
       nsIDocument* doc = aPopup->GetCurrentDoc();
       if (doc) {
         nsIPresShell* presShell = doc->GetShell();
@@ -2053,33 +2053,33 @@ nsXULPopupManager::CancelMenuTimer(nsMen
 }
 
 bool
 nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
                                             nsMenuPopupFrame* aFrame)
 {
   // On Windows, don't check shortcuts when the accelerator key is down.
 #ifdef XP_WIN
-  WidgetInputEvent* evt = aKeyEvent->AsEvent()->GetInternalNSEvent()->AsInputEvent();
+  WidgetInputEvent* evt = aKeyEvent->AsEvent()->WidgetEventPtr()->AsInputEvent();
   if (evt && evt->IsAccel()) {
     return false;
   }
 #endif
 
   nsMenuChainItem* item = GetTopVisibleMenu();
   if (!aFrame && item)
     aFrame = item->Frame();
 
   if (aFrame) {
     bool action;
     nsMenuFrame* result = aFrame->FindMenuWithShortcut(aKeyEvent, action);
     if (result) {
       aFrame->ChangeMenuItem(result, false, true);
       if (action) {
-        WidgetGUIEvent* evt = aKeyEvent->AsEvent()->GetInternalNSEvent()->AsGUIEvent();
+        WidgetGUIEvent* evt = aKeyEvent->AsEvent()->WidgetEventPtr()->AsGUIEvent();
         nsMenuFrame* menuToOpen = result->Enter(evt);
         if (menuToOpen) {
           nsCOMPtr<nsIContent> content = menuToOpen->GetContent();
           ShowMenu(content, true, false);
         }
       }
       return true;
     }
@@ -2316,17 +2316,17 @@ nsXULPopupManager::HandleKeyboardEventWi
       MOZ_FALLTHROUGH;
 
     case nsIDOMKeyEvent::DOM_VK_RETURN: {
       // If there is a popup open, check if the current item needs to be opened.
       // Otherwise, tell the active menubar, if any, to activate the menu. The
       // Enter method will return a menu if one needs to be opened as a result.
       nsMenuFrame* menuToOpen = nullptr;
       WidgetGUIEvent* GUIEvent = aKeyEvent->AsEvent()->
-        GetInternalNSEvent()->AsGUIEvent();
+        WidgetEventPtr()->AsGUIEvent();
 
       if (aTopVisibleMenuItem) {
         menuToOpen = aTopVisibleMenuItem->Frame()->Enter(GUIEvent);
       } else if (mActiveMenuBar) {
         menuToOpen = mActiveMenuBar->Enter(GUIEvent);
       }
       if (menuToOpen) {
         nsCOMPtr<nsIContent> content = menuToOpen->GetContent();
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -1844,16 +1844,23 @@ JsepSessionImpl::ValidateRemoteDescripti
   for (size_t i = 0;
        i < mCurrentRemoteDescription->GetMediaSectionCount();
        ++i) {
     if (mSdpHelper.MsectionIsDisabled(description.GetMediaSection(i)) ||
         mSdpHelper.MsectionIsDisabled(mCurrentRemoteDescription->GetMediaSection(i))) {
       continue;
     }
 
+    if (mCurrentRemoteDescription->GetMediaSection(i).GetMediaType() !=
+        description.GetMediaSection(i).GetMediaType()) {
+      JSEP_SET_ERROR("Remote description changes the media type of m-line "
+                     << i);
+      return NS_ERROR_INVALID_ARG;
+    }
+
     const SdpAttributeList& newAttrs(
         description.GetMediaSection(i).GetAttributeList());
     const SdpAttributeList& oldAttrs(
         mCurrentRemoteDescription->GetMediaSection(i).GetAttributeList());
 
     if ((newAttrs.GetIceUfrag() != oldAttrs.GetIceUfrag()) ||
         (newAttrs.GetIcePwd() != oldAttrs.GetIcePwd())) {
       JSEP_SET_ERROR("ICE restart is unsupported at this time "
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2623,17 +2623,17 @@ PeerConnectionImpl::PluginCrash(uint32_t
   init.mGmpPlugin = true;
   init.mBubbles = true;
   init.mCancelable = true;
 
   RefPtr<PluginCrashedEvent> event =
     PluginCrashedEvent::Constructor(doc, NS_LITERAL_STRING("PluginCrashed"), init);
 
   event->SetTrusted(true);
-  event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
 
   EventDispatcher::DispatchDOMEvent(mWindow, nullptr, event, nullptr, nullptr);
 #endif
 
   return true;
 }
 
 void
--- a/media/webrtc/trunk/webrtc/tools/rtcbot/test.js
+++ b/media/webrtc/trunk/webrtc/tools/rtcbot/test.js
@@ -135,17 +135,17 @@ StatisticsReport.prototype = {
     };
   },
 
   finish: function (doneCallback) {
     fs.exists("test/reports/", function (exists) {
       if(exists) {
         writeFile.bind(this)();
       } else {
-        fs.mkdir("test/reports/", 0777, writeFile.bind(this));
+        fs.mkdir("test/reports/", 0o777, writeFile.bind(this));
       }
     }.bind(this));
 
     function writeFile () {
       fs.writeFile("test/reports/" + this.outputFileName_ + "_" +
         (new Date()).getTime() +".json", JSON.stringify(this.output_),
         doneCallback);
     }
--- a/mobile/android/b2gdroid/installer/package-manifest.in
+++ b/mobile/android/b2gdroid/installer/package-manifest.in
@@ -247,19 +247,17 @@
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkit_asyncshutdown.xpt
 @BINPATH@/components/toolkit_filewatcher.xpt
 @BINPATH@/components/toolkit_finalizationwitness.xpt
 @BINPATH@/components/toolkit_formautofill.xpt
 @BINPATH@/components/toolkit_osfile.xpt
 @BINPATH@/components/toolkit_securityreporter.xpt
-#ifdef NIGHTLY_BUILD
 @BINPATH@/components/toolkit_perfmonitoring.xpt
-#endif
 @BINPATH@/components/toolkit_xulstore.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
 @BINPATH@/components/uconv.xpt
--- a/mobile/android/base/AdjustConstants.java.in
+++ b/mobile/android/base/AdjustConstants.java.in
@@ -1,9 +1,10 @@
 //#filter substitution
+//#include @OBJDIR@/adjust_sdk_app_token
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.adjust.AdjustHelperInterface;
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -328,35 +328,16 @@ PP_TARGETS += manifest
 # need to write AppConstants.java.in to
 # generated/preprocessed/org/mozilla/gecko.
 preprocessed := $(addsuffix .in,$(subst generated/preprocessed/org/mozilla/gecko/,,$(filter generated/preprocessed/org/mozilla/gecko/%,$(constants_PP_JAVAFILES))))
 
 preprocessed_PATH := generated/preprocessed/org/mozilla/gecko
 preprocessed_KEEP_PATH := 1
 preprocessed_FLAGS := --marker='//\\\#'
 
-ifdef MOZ_INSTALL_TRACKING
-ifdef MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN
-# The value of MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN is sensitive: we don't
-# want to expose it in build logs.  Following the model set by
-# toolkit/components/urlformatter/Makefile.in, we expose it to AppConstants.java
-# quietly here.  Be aware that the included line's marker needs to agree with
-# --marker above.
-
-adjust_sdk_app_token:
-	@echo '//#define MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN $(MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN)' > $@
-
-export:: adjust_sdk_app_token
-
-preprocessed_FLAGS += -I adjust_sdk_app_token
-endif # MOZ_INSTALL_TRACKING
-endif # MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN
-
-GARBAGE += adjust_sdk_app_token
-
 PP_TARGETS += preprocessed
 
 include $(topsrcdir)/config/rules.mk
 
 not_android_res_files := \
   *.mkdir.done* \
   *.DS_Store* \
   *\#* \
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/adjust_sdk_app_token.in
@@ -0,0 +1,3 @@
+//#ifdef MOZ_INSTALL_TRACKING
+//#define MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN @MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN@
+//#endif
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -1,16 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['locales']
 
+CONFIGURE_SUBST_FILES += ['adjust_sdk_app_token']
+
 include('android-services.mozbuild')
 
 thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/'
 
 constants_jar = add_java_jar('constants')
 constants_jar.sources = ['java/org/mozilla/gecko/' + x for x in [
     'adjust/AdjustHelperInterface.java',
     'annotation/JNITarget.java',
@@ -980,9 +982,10 @@ if CONFIG['MOZ_ANDROID_SEARCH_ACTIVITY']
         'gecko-browser.jar',
         'gecko-mozglue.jar',
         'gecko-thirdparty.jar',
         'gecko-util.jar'
     ]
 
 FINAL_TARGET_PP_FILES += ['package-name.txt.in']
 
+DEFINES['OBJDIR'] = OBJDIR
 DEFINES['TOPOBJDIR'] = TOPOBJDIR
--- a/mobile/android/components/HelperAppDialog.js
+++ b/mobile/android/components/HelperAppDialog.js
@@ -284,28 +284,28 @@ HelperAppLauncherDialog.prototype = {
           else
             aLocalFile.leafName = aLocalFile.leafName.replace(/(\.[^\.]*)?$/, "(2)$&");
         }
         else {
           // replace the last (n) in the filename with (n+1)
           aLocalFile.leafName = aLocalFile.leafName.replace(/^(.*\()\d+\)/, "$1" + (collisionCount+1) + ")");
         }
       }
-      aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+      aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     }
     catch (e) {
       dump("*** exception in validateLeafName: " + e + "\n");
 
       if (e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED)
         throw e;
 
       if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) {
         aLocalFile.append("unnamed");
         if (aLocalFile.exists())
-          aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+          aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
       }
     }
   },
 
   isUsableDirectory: function hald_isUsableDirectory(aDirectory) {
     return aDirectory.exists() && aDirectory.isDirectory() && aDirectory.isWritable();
   },
 };
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -676,17 +676,17 @@ SessionStore.prototype = {
     // Use async file writer and just return it's promise
     if (aAsync) {
       return OS.File.writeAtomic(aFile.path, aBuffer, { tmpPath: aFile.path + ".tmp" });
     }
 
     // Convert buffer to an encoded string and sync write to disk
     let bytes = String.fromCharCode.apply(null, new Uint16Array(aBuffer));
     let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
-    stream.init(aFile, 0x02 | 0x08 | 0x20, 0666, 0);
+    stream.init(aFile, 0x02 | 0x08 | 0x20, 0o666, 0);
     stream.write(bytes, bytes.length);
     stream.close();
 
     // Return a resolved promise to make the caller happy
     return Promise.resolve();
   },
 
   _updateCrashReportURL: function ss_updateCrashReportURL(aWindow) {
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -1,8 +1,9 @@
+
 ; 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/.
 
 ; Package file for the Fennec build.
 ;
 ; File format:
 ;
@@ -223,19 +224,17 @@
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkit_asyncshutdown.xpt
 @BINPATH@/components/toolkit_filewatcher.xpt
 @BINPATH@/components/toolkit_finalizationwitness.xpt
 @BINPATH@/components/toolkit_formautofill.xpt
 @BINPATH@/components/toolkit_osfile.xpt
 @BINPATH@/components/toolkit_securityreporter.xpt
-#ifdef NIGHTLY_BUILD
 @BINPATH@/components/toolkit_perfmonitoring.xpt
-#endif
 @BINPATH@/components/toolkit_xulstore.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
 @BINPATH@/components/uconv.xpt
--- a/modules/libjar/test/unit/test_umlaute.js
+++ b/modules/libjar/test/unit/test_umlaute.js
@@ -22,17 +22,17 @@ function run_test() {
 
   var entryName = entries.getNext();
   do_check_eq(entryName, "test_\u00FC.txt");
 
   do_check_true(zipreader.hasEntry(entryName));
 
   var target = tmpDir.clone();
   target.append(entryName);
-  target.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 6 * 64 + 4 * 8 + 0); // 0640
+  target.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0o640); // 0640
 
   zipreader.extract(entryName, target);
 
   var entry = zipreader.getEntry(entryName);
   do_check_true(entry != null);
 
   zipreader.test(entryName);
 
--- a/modules/libjar/zipwriter/test/unit/test_zippermissions.js
+++ b/modules/libjar/zipwriter/test/unit/test_zippermissions.js
@@ -27,17 +27,17 @@ function build_tests() {
 function run_test() {
   build_tests();
 
   var foStream = Cc["@mozilla.org/network/file-output-stream;1"].
                  createInstance(Ci.nsIFileOutputStream);
 
   var tmp = tmpDir.clone();
   tmp.append("temp-permissions");
-  tmp.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE, 0755);
+  tmp.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE, 0o755);
 
   var file = tmp.clone();
   file.append("tempfile");
 
   zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
   for (let i = 0; i < TESTS.length; i++) {
     // Open the file with the permissions to match how the zipreader extracts
     // This obeys the umask
--- a/modules/libmar/tests/unit/head_libmar.js
+++ b/modules/libmar/tests/unit/head_libmar.js
@@ -97,23 +97,23 @@ function createMAR(outMAR, dataDir, file
   let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
   // Make sure the signmar binary exists and is an executable.
   do_check_true(signmarBin.exists());
   do_check_true(signmarBin.isExecutable());
 
   // Ensure on non Windows platforms we encode the same permissions
   // as the refernence MARs contain.  On Windows this is also safe.
-  // The reference MAR files have permissions of 0664, so in case
+  // The reference MAR files have permissions of 0o664, so in case
   // someone is running these tests locally with another permission
-  // (perhaps 0777), make sure that we encode them as 0664.
+  // (perhaps 0o777), make sure that we encode them as 0o664.
   for (filePath of files) {
     let f = dataDir.clone();
     f.append(filePath);
-    f.permissions = 0664;
+    f.permissions = 0o664;
   }
 
   // Setup the command line arguments to create the MAR.
   let args = ["-C", dataDir.path, "-H", "\@MAR_CHANNEL_ID\@", 
               "-V", "13.0a1", "-c", outMAR.path];
   args = args.concat(files);
 
   do_print('Running: ' + signmarBin.path);
--- a/modules/libmar/tests/unit/test_extract.js
+++ b/modules/libmar/tests/unit/test_extract.js
@@ -12,17 +12,17 @@ function run_test() {
   function run_one_test(marFileName, files) { 
     // Get the MAR file that we will be extracting
     let mar = do_get_file("data/" + marFileName);
 
     // Get the path that we will extract to
     let outDir = tempDir.clone();
     outDir.append("out");
     do_check_false(outDir.exists());
-    outDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
+    outDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777);
 
     // Get the ref files and the files that will be extracted.
     let outFiles = [];
     let refFiles = [];
     for (let i = 0; i < files.length; i++) {
       let outFile = outDir.clone();
       outFile.append(files[i]);
       do_check_false(outFile.exists());
--- a/modules/libpref/test/unit/test_libPrefs.js
+++ b/modules/libpref/test/unit/test_libPrefs.js
@@ -306,17 +306,17 @@ function run_test() {
   ps.setCharPref("ReadPref.char", "hello");
 
   // save those prefs in a file
   let savePrefFile = do_get_cwd();
   savePrefFile.append("data");
   savePrefFile.append("savePref.js");
   if (savePrefFile.exists())
     savePrefFile.remove(false);
-  savePrefFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  savePrefFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
   ps.savePrefFile(savePrefFile);
   ps.resetPrefs();
 
   // load a preexisting pref file
   let prefFile = do_get_file("data/testPref.js");
   ps.readUserPrefs(prefFile);
 
   // former prefs should have been replaced/lost
--- a/netwerk/cache2/CacheObserver.cpp
+++ b/netwerk/cache2/CacheObserver.cpp
@@ -498,37 +498,33 @@ CacheObserver::Observe(nsISupports* aSub
   }
 
   if (!strcmp(aTopic, "browser-delayed-startup-finished")) {
     uint32_t activeVersion = UseNewCache() ? 1 : 0;
     CacheStorageService::CleaupCacheDirectories(sAutoDeleteCacheVersion, activeVersion);
     return NS_OK;
   }
 
-  if (!strcmp(aTopic, "profile-before-change")) {
+  if (!strcmp(aTopic, "profile-change-net-teardown") ||
+      !strcmp(aTopic, "profile-before-change") ||
+      !strcmp(aTopic, "xpcom-shutdown")) {
     RefPtr<CacheStorageService> service = CacheStorageService::Self();
-    if (service)
+    if (service) {
       service->Shutdown();
-
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, "xpcom-shutdown")) {
-    RefPtr<CacheStorageService> service = CacheStorageService::Self();
-    if (service)
-      service->Shutdown();
+    }
 
     CacheFileIOManager::Shutdown();
     return NS_OK;
   }
 
   if (!strcmp(aTopic, "last-pb-context-exited")) {
     RefPtr<CacheStorageService> service = CacheStorageService::Self();
-    if (service)
+    if (service) {
       service->DropPrivateBrowsingEntries();
+    }
 
     return NS_OK;
   }
 
   if (!strcmp(aTopic, "clear-origin-data")) {
     NeckoOriginAttributes oa;
     if (!oa.Init(nsDependentString(aData))) {
       NS_ERROR("Could not parse NeckoOriginAttributes JSON in clear-origin-data notification");
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -2992,39 +2992,18 @@ WebSocketChannel::AsyncOnChannelRedirect
   bool newuriIsHttps = false;
   rv = newuri->SchemeIs("https", &newuriIsHttps);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!mAutoFollowRedirects) {
     // Even if redirects configured off, still allow them for HTTP Strict
     // Transport Security (from ws://FOO to https://FOO (mapped to wss://FOO)
 
-    nsCOMPtr<nsIURI> clonedNewURI;
-    rv = newuri->Clone(getter_AddRefs(clonedNewURI));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = clonedNewURI->SetScheme(NS_LITERAL_CSTRING("ws"));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIURI> currentURI;
-    rv = GetURI(getter_AddRefs(currentURI));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // currentURI is expected to be ws or wss
-    bool currentIsHttps = false;
-    rv = currentURI->SchemeIs("wss", &currentIsHttps);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    bool uriEqual = false;
-    rv = clonedNewURI->Equals(currentURI, &uriEqual);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // It's only a HSTS redirect if we started with non-secure, are going to
-    // secure, and the new URI is otherwise the same as the old one.
-    if (!(!currentIsHttps && newuriIsHttps && uriEqual)) {
+    if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL |
+                   nsIChannelEventSink::REDIRECT_STS_UPGRADE))) {
       nsAutoCString newSpec;
       rv = newuri->GetSpec(newSpec);
       NS_ENSURE_SUCCESS(rv, rv);
 
       LOG(("WebSocketChannel: Redirect to %s denied by configuration\n",
            newSpec.get()));
       return NS_ERROR_FAILURE;
     }
--- a/netwerk/test/httpserver/test/head_utils.js
+++ b/netwerk/test/httpserver/test/head_utils.js
@@ -54,17 +54,17 @@ function makeBIS(stream)
  * @param file : nsILocalFile
  *   the file whose contents are to be read
  * @returns string
  *   the contents of the file
  */
 function fileContents(file)
 {
   const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(file, PR_RDONLY, 0444,
+  var fis = new FileInputStream(file, PR_RDONLY, 0o444,
                                 Ci.nsIFileInputStream.CLOSE_ON_EOF);
   var sis = new ScriptableInputStream(fis);
   var contents = sis.read(file.fileSize);
   sis.close();
   return contents;
 }
 
 /**
--- a/netwerk/test/httpserver/test/test_default_index_handler.js
+++ b/netwerk/test/httpserver/test/test_default_index_handler.js
@@ -37,17 +37,17 @@ function run_test()
 }
 
 function createTestDirectory()
 {
   dir = Cc["@mozilla.org/file/directory_service;1"]
           .getService(Ci.nsIProperties)
           .get("TmpD", Ci.nsIFile);
   dir.append("index_handler_test_" + Math.random());
-  dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0744);
+  dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o744);
 
   // populate with test directories, files, etc.
   // Files must be in expected order of display on the index page!
 
   var files = [];
 
   makeFile("aa_directory", true, dir, files);
   makeFile("Ba_directory", true, dir, files);
@@ -244,17 +244,17 @@ function dataCheck(bytes, uri, path, dir
 function makeFile(name, isDirectory, parentDir, lst)
 {
   var type = Ci.nsIFile[isDirectory ? "DIRECTORY_TYPE" : "NORMAL_FILE_TYPE"];
   var file = parentDir.clone();
 
   try
   {
     file.append(name);
-    file.create(type, 0755);
+    file.create(type, 0o755);
     lst.push({name: name, isDirectory: isDirectory});
   }
   catch (e) { /* OS probably doesn't like file name, skip */ }
 }
 
 /*********
  * TESTS *
  *********/
--- a/netwerk/test/unit/test_NetUtil.js
+++ b/netwerk/test/unit/test_NetUtil.js
@@ -63,17 +63,17 @@ function async_write_file(aContractId, a
 {
   do_test_pending();
 
   // First, we need an output file to write to.
   let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append("NetUtil-async-test-file.tmp");
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   // Then, we need an output stream to our output file.
   let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
   ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
 
   // Finally, we need an input stream to take data from.
   const TEST_DATA = "this is a test string";
   let istream = Cc["@mozilla.org/io/string-input-stream;1"].
@@ -118,17 +118,17 @@ function test_async_copy()
       return istream;
     }
 
     // File input streams are not buffered, so let's create a file
     let file = Cc["@mozilla.org/file/directory_service;1"].
       getService(Ci.nsIProperties).
       get("ProfD", Ci.nsIFile);
     file.append("NetUtil-asyncFetch-test-file.tmp");
-    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
     let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
       createInstance(Ci.nsIFileOutputStream);
     ostream.init(file, -1, -1, 0);
     ostream.write(data, data.length);
     ostream.close();
 
     let istream = Cc["@mozilla.org/network/file-input-stream;1"].
@@ -139,17 +139,17 @@ function test_async_copy()
   }
 
   // Create an output buffer holding some data
   function make_output(isBuffered) {
     let file = Cc["@mozilla.org/file/directory_service;1"].
       getService(Ci.nsIProperties).
       get("ProfD", Ci.nsIFile);
     file.append("NetUtil-asyncFetch-test-file.tmp");
-    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
     let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
       createInstance(Ci.nsIFileOutputStream);
     ostream.init(file, -1, -1, 0);
 
     if (!isBuffered) {
       return {file: file, sink: ostream};
     }
@@ -404,17 +404,17 @@ function test_asyncFetch_with_nsIFile()
 {
   const TEST_DATA = "this is a test string";
 
   // First we need a file to read from.
   let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append("NetUtil-asyncFetch-test-file.tmp");
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   // Write the test data to the file.
   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                 createInstance(Ci.nsIFileOutputStream);
   ostream.init(file, -1, -1, 0);
   ostream.write(TEST_DATA, TEST_DATA.length);
 
   // Sanity check to make sure the data was written.
--- a/netwerk/test/unit/test_bug414122.js
+++ b/netwerk/test/unit/test_bug414122.js
@@ -5,17 +5,17 @@ var etld = Cc["@mozilla.org/network/effe
 var idn = Cc["@mozilla.org/network/idn-service;1"]
              .getService(Ci.nsIIDNService);
 
 function run_test()
 {
   var fis = Cc["@mozilla.org/network/file-input-stream;1"]
               .createInstance(Ci.nsIFileInputStream);
   fis.init(do_get_file("effective_tld_names.dat"),
-           PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
+           PR_RDONLY, 0o444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
 
   var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
               .createInstance(Ci.nsIConverterInputStream);
   lis.init(fis, "UTF-8", 1024, 0);
   lis.QueryInterface(Ci.nsIUnicharLineInputStream);
 
   var out = { value: "" };
   do
--- a/netwerk/test/unit/test_file_partial_inputstream.js
+++ b/netwerk/test/unit/test_file_partial_inputstream.js
@@ -113,17 +113,17 @@ function run_test()
   tempInputStream = new_partial_file_input_stream(tempFile, 5, 10,
                                                   Ci.nsIFileInputStream.CLOSE_ON_EOF |
                                                   Ci.nsIFileInputStream.REOPEN_ON_REWIND);
   tempInputStream.QueryInterface(Ci.nsILineInputStream);
   do_check_eq(read_line_stream(tempInputStream)[1], "5678901234");
   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                 createInstance(Ci.nsIFileOutputStream);
   ostream.init(tempFile, 0x02 | 0x08 | 0x20, // write, create, truncate
-               0666, 0);
+               0o666, 0);
   let newData = "abcdefghijklmnopqrstuvwxyz";
   ostream.write(newData, newData.length);
   ostream.close();
   tempInputStream.QueryInterface(Ci.nsISeekableStream);
   tempInputStream.seek(SET, 1);
   do_check_eq(read_line_stream(tempInputStream)[1], newData.substr(6,9));
 
   // Test auto-delete and auto-close together
@@ -494,19 +494,19 @@ function new_partial_file_input_stream(f
   return stream.QueryInterface(Ci.nsIInputStream);
 }
 
 function create_temp_file(data) {
   let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append("fileinputstream-test-file.tmp");
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                 createInstance(Ci.nsIFileOutputStream);
   ostream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
-               0666, 0);
+               0o666, 0);
   do_check_eq(ostream.write(data, data.length), data.length);
   ostream.close();
 
   return file;
 }
--- a/netwerk/test/unit/test_file_protocol.js
+++ b/netwerk/test/unit/test_file_protocol.js
@@ -175,17 +175,17 @@ function test_read_dir_2() {
 }
 
 function test_upload_file() {
   dump("*** test_upload_file\n");
 
   var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload
   var dest = do_get_tempdir();      // file upload destination
   dest.append("junk.dat");
-  dest.createUnique(dest.NORMAL_FILE_TYPE, 0600);
+  dest.createUnique(dest.NORMAL_FILE_TYPE, 0o600);
 
   var uploadstream = new_file_input_stream(file, true);
 
   var chan = new_file_channel(dest);
   chan.QueryInterface(Ci.nsIUploadChannel);
   chan.setUploadStream(uploadstream, "", file.fileSize);
 
   function on_upload_complete(data) {
--- a/netwerk/test/unit/test_filestreams.js
+++ b/netwerk/test/unit/test_filestreams.js
@@ -123,17 +123,17 @@ function sync_operations(aDeferOpen)
 {
   const TEST_DATA = "this is a test string";
   const LEAF_NAME = "filestreams-test-file.tmp";
 
   let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append(LEAF_NAME);
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let ostream = Cc[OUTPUT_STREAM_CONTRACT_ID].
                 createInstance(Ci.nsIFileOutputStream);
   ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
 
   ostream.write(TEST_DATA, TEST_DATA.length);
   ostream.close();
 
@@ -210,17 +210,17 @@ function do_test_zero_size_buffered(disa
 {
   const LEAF_NAME = "filestreams-test-file.tmp";
   const BUFFERSIZE = 4096;
 
   let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append(LEAF_NAME);
-  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
                 createInstance(Ci.nsIFileInputStream);
   fstream.init(file, -1, 0,
                Ci.nsIFileInputStream.CLOSE_ON_EOF |
                Ci.nsIFileInputStream.REOPEN_ON_REWIND);
 
   var buffered = Cc["@mozilla.org/network/buffered-input-stream;1"].
--- a/security/manager/pki/resources/content/pippki.js
+++ b/security/manager/pki/resources/content/pippki.js
@@ -129,17 +129,17 @@ function exportToFile(parent, cert)
   var written = 0;
   try {
     var file = Components.classes["@mozilla.org/file/local;1"].
                createInstance(Components.interfaces.nsILocalFile);
     file.initWithPath(fp.file.path);
     var fos = Components.classes["@mozilla.org/network/file-output-stream;1"].
               createInstance(Components.interfaces.nsIFileOutputStream);
     // flags: PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
-    fos.init(file, 0x02 | 0x08 | 0x20, 00644, 0);
+    fos.init(file, 0x02 | 0x08 | 0x20, 0o0644, 0);
     written = fos.write(content, content.length);
     fos.close();
   }
   catch(e) {
     switch (e.result) {
       case Components.results.NS_ERROR_FILE_ACCESS_DENIED:
         msg = bundle.getString("writeFileAccessDenied");
         break;
--- a/security/manager/ssl/tests/unit/test_sss_readstate_empty.js
+++ b/security/manager/ssl/tests/unit/test_sss_readstate_empty.js
@@ -23,17 +23,17 @@ function checkStateRead(aSubject, aTopic
 
 function run_test() {
   let profileDir = do_get_profile();
   let stateFile = profileDir.clone();
   stateFile.append(SSS_STATE_FILE_NAME);
   // Assuming we're working with a clean slate, the file shouldn't exist
   // until we create it.
   ok(!stateFile.exists());
-  stateFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0x1a4); // 0x1a4 == 0644
+  stateFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0x1a4); // 0x1a4 == 0o644
   ok(stateFile.exists());
   // Initialize nsISiteSecurityService after do_get_profile() so it
   // can read the state file.
   Services.obs.addObserver(checkStateRead, "data-storage-ready", false);
   do_test_pending();
   gSSService = Cc["@mozilla.org/ssservice;1"]
                  .getService(Ci.nsISiteSecurityService);
   notEqual(gSSService, null);
--- a/security/manager/tools/makeCNNICHashes.js
+++ b/security/manager/tools/makeCNNICHashes.js
@@ -247,15 +247,15 @@ for (let cert of invalidCerts) {
 }
 
 // Sort the key hashes to allow for binary search.
 certs.sort(compareCertificatesByHash);
 
 // Write the output file.
 var outFile = relativePathToFile("CNNICHashWhitelist.inc");
 if (!outFile.exists()) {
-  outFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
+  outFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
 }
 var outStream = Cc["@mozilla.org/network/file-output-stream;1"]
                   .createInstance(Ci.nsIFileOutputStream);
 outStream.init(outFile, -1, 0, 0);
 writeHashes(certs, lastValidTime, outStream);
 outStream.close();
--- a/services/sync/tests/unit/test_bookmark_engine.js
+++ b/services/sync/tests/unit/test_bookmark_engine.js
@@ -199,17 +199,17 @@ add_task(function* test_restorePromptsRe
       .getService(Ci.nsIProperties);
 
     let backupFile = dirSvc.get("TmpD", Ci.nsILocalFile);
 
     _("Make a backup.");
     backupFile.append("t_b_e_" + Date.now() + ".json");
 
     _("Backing up to file " + backupFile.path);
-    backupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
+    backupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0o600);
     yield BookmarkJSONUtils.exportToFile(backupFile);
 
     _("Create a different record and sync.");
     let bmk2_id = PlacesUtils.bookmarks.insertBookmark(
       folder1_id, tburi, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Thunderbird!");
     let bmk2_guid = store.GUIDForId(bmk2_id);
     _("Get Thunderbird!: " + bmk2_id + ", " + bmk2_guid);
 
--- a/testing/talos/talos/pageloader/chrome/MozillaFileLogger.js
+++ b/testing/talos/talos/pageloader/chrome/MozillaFileLogger.js
@@ -47,17 +47,17 @@ const PR_EXCL         = 0x80;
 var MozillaFileLogger = {};
 
 
 MozillaFileLogger.init = function(path) {
   MozillaFileLogger._file = Cc[LF_CID].createInstance(Ci.nsILocalFile);
   MozillaFileLogger._file.initWithPath(path);
   MozillaFileLogger._foStream = Cc[FOSTREAM_CID].createInstance(Ci.nsIFileOutputStream);
   MozillaFileLogger._foStream.init(this._file, PR_WRITE_ONLY | PR_CREATE_FILE | PR_APPEND,
-                                   0664, 0);
+                                   0o664, 0);
 }
 
 MozillaFileLogger.getLogCallback = function() {
   return function (msg) {
     var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
     if (MozillaFileLogger._foStream)
       MozillaFileLogger._foStream.write(data, data.length);
 
--- a/testing/talos/talos/scripts/MozillaFileLogger.js
+++ b/testing/talos/talos/scripts/MozillaFileLogger.js
@@ -74,17 +74,17 @@ var MozFileLogger = {};
 
 MozFileLogger.init = function(path) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   MozFileLogger._file = Cc[LF_CID].createInstance(Ci.nsILocalFile);
   MozFileLogger._file.initWithPath(path);
   MozFileLogger._foStream = Cc[FOSTREAM_CID].createInstance(Ci.nsIFileOutputStream);
   MozFileLogger._foStream.init(this._file, PR_WRITE_ONLY | PR_CREATE_FILE | PR_APPEND,
-                                   0664, 0);
+                                   0o664, 0);
 }
 
 MozFileLogger.getLogCallback = function() {
   return function (msg) {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
     var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
     if (MozFileLogger._foStream)
--- a/testing/tools/fileid/win_fileid.cpp
+++ b/testing/tools/fileid/win_fileid.cpp
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdio.h>
 #include <stdint.h>
-#include <Windows.h>
+#include <windows.h>
 #include <dbghelp.h>
 
 const DWORD CV_SIGNATURE_RSDS = 0x53445352; // 'SDSR'
 
 struct CV_INFO_PDB70 {
   DWORD      CvSignature;
   GUID       Signature;
   DWORD      Age;
--- a/toolkit/components/jsdownloads/test/unit/test_PrivateTemp.js
+++ b/toolkit/components/jsdownloads/test/unit/test_PrivateTemp.js
@@ -14,11 +14,11 @@ add_task(function* test_private_temp() {
   let download = yield promiseStartExternalHelperAppServiceDownload(
                                                          httpUrl("empty.txt"));
 
   yield promiseDownloadStopped(download);
 
   var targetFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
   targetFile.initWithPath(download.target.path);
 
-  // 488 is the decimal value of 0700.
+  // 488 is the decimal value of 0o700.
   equal(targetFile.parent.permissions, 448);
 });
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -7,16 +7,17 @@
 # These component dirs are built for all apps (including suite)
 if CONFIG['MOZ_ENABLE_XREMOTE']:
     DIRS += ['remote']
 
 DIRS += [
     'aboutcache',
     'aboutcheckerboard',
     'aboutmemory',
+    'aboutperformance',
     'addoncompat',
     'alerts',
     'apppicker',
     'asyncshutdown',
     'commandlines',
     'console',
     'contentprefs',
     'cookie',
@@ -34,16 +35,17 @@ DIRS += [
     'jsdownloads',
     'lz4',
     'mediasniffer',
     'microformats',
     'osfile',
     'parentalcontrols',
     'passwordmgr',
     'perf',
+    'perfmonitoring',
     'places',
     'privatebrowsing',
     'processsingleton',
     'promiseworker',
     'prompts',
     'protobuf',
     'reader',
     'remotebrowserutils',
@@ -93,21 +95,15 @@ if CONFIG['MOZ_TOOLKIT_SEARCH']:
 if CONFIG['MOZ_URL_CLASSIFIER']:
     DIRS += ['url-classifier']
 
 DIRS += ['captivedetect']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk" and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
     DIRS += ['terminator']
 
-if CONFIG['NIGHTLY_BUILD']: # Bug 1136927 - Performance Monitoring is not ready for prime-time yet
-    DIRS += [
-      'aboutperformance',
-      'perfmonitoring',
-    ]
-
 DIRS += ['build']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
     EXTRA_COMPONENTS += [
         'nsDefaultCLH.js',
         'nsDefaultCLH.manifest',
     ]
--- a/toolkit/components/osfile/tests/xpcshell/test_osfile_async_setPermissions.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_osfile_async_setPermissions.js
@@ -9,17 +9,17 @@
  * (see bug 1001849)
  * These functions are currently Unix-specific.  The manifest skips
  * the test on Windows.
  */
 
 /**
  * Helper function for test logging: prints a POSIX file permission mode as an
  * octal number, with a leading '0' per C (not JS) convention.  When the
- * numeric value is 0777 or lower, it is padded on the left with zeroes to
+ * numeric value is 0o777 or lower, it is padded on the left with zeroes to
  * four digits wide.
  * Sample outputs:  0022, 0644, 04755.
  */
 function format_mode(mode) {
   if (mode <= 0o777) {
     return ("0000" + mode.toString(8)).slice(-4);
   } else {
     return "0" + mode.toString(8);
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -359,16 +359,24 @@
   "GC_SWEEP_MS": {
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 50,
     "description": "Time spent running JS GC sweep phase (ms)"
   },
+  "GC_COMPACT_MS": {
+    "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": "10000",
+    "n_buckets": 50,
+    "description": "Time spent running JS GC compact phase (ms)"
+  },
   "GC_MARK_ROOTS_MS": {
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
     "expires_in_version": "never",
     "kind": "linear",
     "high": "200",
     "n_buckets": 50,
     "description": "Time spent marking GC roots (ms)"
   },
--- a/uriloader/exthandler/tests/unit/test_handlerService.js
+++ b/uriloader/exthandler/tests/unit/test_handlerService.js
@@ -63,17 +63,17 @@ function run_test() {
   // only that it has a path and exists.  Since we don't know any executable
   // that exists on all platforms (except possibly the application being
   // tested, but there doesn't seem to be a way to get a reference to that
   // from the directory service), we use the temporary directory itself.
   var executable = HandlerServiceTest._dirSvc.get("TmpD", Ci.nsIFile);
   // XXX We could, of course, create an actual executable in the directory:
   //executable.append("localhandler");
   //if (!executable.exists())
-  //  executable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0755);
+  //  executable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o755);
 
   var localHandler = {
     name: "Local Handler",
     executable: executable,
     interfaces: [Ci.nsIHandlerApp, Ci.nsILocalHandlerApp, Ci.nsISupports],
     QueryInterface: function(iid) {
       if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
         throw Cr.NS_ERROR_NO_INTERFACE;
--- a/xpcom/ds/nsINIProcessor.js
+++ b/xpcom/ds/nsINIProcessor.js
@@ -139,17 +139,17 @@ INIProcessor.prototype = {
         }
 
         if (!aFile)
             aFile = this._iniFile;
 
         let safeStream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
                          createInstance(Ci.nsIFileOutputStream);
         safeStream.init(aFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE,
-                        0600, null);
+                        0o600, null);
 
         var outputStream = Cc["@mozilla.org/network/buffered-output-stream;1"].
                            createInstance(Ci.nsIBufferedOutputStream);
         outputStream.init(safeStream, 8192);
         outputStream.QueryInterface(Ci.nsISafeOutputStream); // for .finish()
 
         if (Ci.nsIINIParserWriter.WRITE_UTF16 == aFlags
          && 'nsIWindowsRegKey' in Ci) {
--- a/xpcom/tests/unit/test_bug364285-1.js
+++ b/xpcom/tests/unit/test_bug364285-1.js
@@ -17,21 +17,21 @@ function getTempDir()
 	.getService(Ci.nsIProperties);
     return dirService.get("TmpD", Ci.nsILocalFile);
 }
 
 function create_file(fileName)
 {
     var outFile = getTempDir();
     outFile.append(fileName);
-    outFile.createUnique(outFile.NORMAL_FILE_TYPE, 0600);
+    outFile.createUnique(outFile.NORMAL_FILE_TYPE, 0o600);
 
     var stream = Cc["@mozilla.org/network/file-output-stream;1"]
 	.createInstance(Ci.nsIFileOutputStream);
-    stream.init(outFile, 0x02 | 0x08 | 0x20, 0600, 0);
+    stream.init(outFile, 0x02 | 0x08 | 0x20, 0o600, 0);
     stream.write("foo", 3);
     stream.close();
 
     do_check_eq(outFile.leafName.substr(0, fileName.length), fileName);
 
     return outFile;
 }
 
--- a/xpcom/tests/unit/test_bug476919.js
+++ b/xpcom/tests/unit/test_bug476919.js
@@ -4,17 +4,17 @@ var Ci = Components.interfaces;
 function run_test() {
   // skip this test on Windows
   if (mozinfo.os != "win") {
     var testDir = __LOCATION__.parent;
     // create a test file, then symlink it, then check that we think it's a symlink
     var targetFile = testDir.clone();
     targetFile.append("target.txt");
     if (!targetFile.exists())
-      targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
+      targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
 
     var link = testDir.clone();
     link.append("link");
     if (link.exists())
       link.remove(false);
 
     var ln = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
     ln.initWithPath("/bin/ln");
--- a/xpcom/tests/unit/test_file_createUnique.js
+++ b/xpcom/tests/unit/test_file_createUnique.js
@@ -14,16 +14,16 @@ function run_test()
 
   // Generate the path for a file located in a directory with a long name.
   var tempFile = Cc["@mozilla.org/file/directory_service;1"].
                  getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
   tempFile.append(longLeafName);
   tempFile.append("test.txt");
 
   try {
-    tempFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
+    tempFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     do_throw("Creating an item in a folder with a very long name should throw");
   }
   catch (e if (e instanceof Ci.nsIException &&
                e.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH)) {
     // We expect the function not to crash but to raise this exception.
   }
 }
--- a/xpcom/tests/unit/test_hidden_files.js
+++ b/xpcom/tests/unit/test_hidden_files.js
@@ -8,17 +8,17 @@ var hiddenUnixFile;
 function createUNIXHiddenFile() {
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
   var tmpDir = dirSvc.get(NS_OS_TEMP_DIR, Ci.nsIFile);
   hiddenUnixFile = tmpDir.clone();
   hiddenUnixFile.append(".foo");
   // we don't care if this already exists because we don't care
   // about the file's contents (just the name)
   if (!hiddenUnixFile.exists())
-    hiddenUnixFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+    hiddenUnixFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
   return hiddenUnixFile.exists();
 }
 
 function run_test() {
   // Skip this test on Windows
   if (mozinfo.os == "win")
     return;
 
--- a/xpcom/tests/unit/test_localfile.js
+++ b/xpcom/tests/unit/test_localfile.js
@@ -63,17 +63,17 @@ function test_file_modification_time()
   var file = do_get_profile();
   file.append("testfile");
 
   // Should never happen but get rid of it anyway
   if (file.exists())
     file.remove(true);
 
   var now = Date.now();
-  file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
+  file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
   do_check_true(file.exists());
 
   // Modification time may be out by up to 2 seconds on FAT filesystems. Test
   // with a bit of leeway, close enough probably means it is correct.
   var diff = Math.abs(file.lastModifiedTime - now);
   do_check_true(diff < MAX_TIME_DIFFERENCE);
 
   var yesterday = now - MILLIS_PER_DAY;
@@ -103,17 +103,17 @@ function test_directory_modification_tim
   var dir = do_get_profile();
   dir.append("testdir");
 
   // Should never happen but get rid of it anyway
   if (dir.exists())
     dir.remove(true);
 
   var now = Date.now();
-  dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+  dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   do_check_true(dir.exists());
 
   // Modification time may be out by up to 2 seconds on FAT filesystems. Test
   // with a bit of leeway, close enough probably means it is correct.
   var diff = Math.abs(dir.lastModifiedTime - now);
   do_check_true(diff < MAX_TIME_DIFFERENCE);
 
   var yesterday = now - MILLIS_PER_DAY;
@@ -137,15 +137,15 @@ function test_diskSpaceAvailable()
   file.QueryInterface(Ci.nsILocalFile);
 
   let bytes = file.diskSpaceAvailable;
   do_check_true(bytes > 0);
 
   file.append("testfile");
   if (file.exists())
     file.remove(true);
-  file.create(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("644", 8));
+  file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
 
   bytes = file.diskSpaceAvailable;
   do_check_true(bytes > 0);
 
   file.remove(true);
 }
--- a/xpcom/tests/unit/test_symlinks.js
+++ b/xpcom/tests/unit/test_symlinks.js
@@ -64,23 +64,23 @@ function setupTestDir(testDir, relative)
   var targetDir = testDir.clone();
   targetDir.append(DIR_TARGET);
 
   if (testDir.exists()) {
     testDir.remove(true);
   }
   do_check_true(!testDir.exists());
 
-  testDir.create(nsIFile.DIRECTORY_TYPE, 0777);
+  testDir.create(nsIFile.DIRECTORY_TYPE, 0o777);
 
-  targetDir.create(nsIFile.DIRECTORY_TYPE, 0777);
+  targetDir.create(nsIFile.DIRECTORY_TYPE, 0o777);
 
   var targetFile = testDir.clone();
   targetFile.append(FILE_TARGET);
-  targetFile.create(nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.create(nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   var imaginary = testDir.clone();
   imaginary.append(DOES_NOT_EXIST);
 
   var loop = testDir.clone();
   loop.append(LOOP_LINK);
 
   var dirLink  = makeSymLink(targetDir, DIR_LINK, relative);
--- a/xpcom/tests/unit/test_windows_shortcut.js
+++ b/xpcom/tests/unit/test_windows_shortcut.js
@@ -18,17 +18,17 @@ Cu.import("resource://gre/modules/Servic
 function run_test()
 {
   // This test makes sense only on Windows, so skip it on other platforms
   if ("nsILocalFileWin" in Ci
    && do_get_cwd() instanceof Ci.nsILocalFileWin) {
 
     let tempDir = Services.dirsvc.get("TmpD", Ci.nsILocalFile);
     tempDir.append("shortcutTesting");
-    tempDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0666);
+    tempDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o666);
 
     test_create_noargs(tempDir);
     test_create_notarget(tempDir);
     test_create_targetonly(tempDir);
     test_create_normal(tempDir);
     test_create_unicode(tempDir);
 
     test_update_noargs(tempDir);
@@ -38,17 +38,17 @@ function run_test()
     test_update_unicode(tempDir);
   }
 }
 
 function test_create_noargs(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("shouldNeverExist.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   try
   {
     win.setShortcut();
     do_throw("Creating a shortcut with no args (no target) should throw");
   }
@@ -58,17 +58,17 @@ function test_create_noargs(tempDir)
 
   }
 }
 
 function test_create_notarget(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("shouldNeverExist2.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   try
   {
     win.setShortcut(null,
                     do_get_cwd(),
                     "arg1 arg2",
@@ -81,81 +81,81 @@ function test_create_notarget(tempDir)
 
   }
 }
 
 function test_create_targetonly(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile);
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(targetFile));
 }
 
 function test_create_normal(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "Ordinary shortcut");
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(targetFile))
 }
 
 function test_create_unicode(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("ṩhогТϾừ†Target.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(), // XXX: This should probably be a unicode dir
                   "ᾶṟǵ1 ᾶṟǵ2",
                   "ῧṋіḉѻₑ");
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(targetFile))
 }
 
 function test_update_noargs(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "A sample shortcut");
 
@@ -164,21 +164,21 @@ function test_update_noargs(tempDir)
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(targetFile))
 }
 
 function test_update_notarget(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "A sample shortcut");
 
@@ -190,89 +190,89 @@ function test_update_notarget(tempDir)
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(targetFile))
 }
 
 function test_update_targetonly(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "A sample shortcut");
 
   let newTargetFile = tempDir.clone();
   newTargetFile.append("shortcutTarget.exe");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   win.setShortcut(newTargetFile);
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(newTargetFile))
 }
 
 function test_update_normal(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "A sample shortcut");
 
   let newTargetFile = tempDir.clone();
   newTargetFile.append("shortcutTarget.exe");
-  newTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  newTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   win.setShortcut(newTargetFile,
                   do_get_profile(),
                   "arg3 arg4",
                   "An UPDATED shortcut");
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(newTargetFile))
 }
 
 function test_update_unicode(tempDir)
 {
   let shortcutFile = tempDir.clone();
   shortcutFile.append("createdShortcut.lnk");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let targetFile = tempDir.clone();
   targetFile.append("shortcutTarget.exe");
-  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  targetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   let win = shortcutFile.QueryInterface(Ci.nsILocalFileWin);
 
   win.setShortcut(targetFile,
                   do_get_cwd(),
                   "arg1 arg2",
                   "A sample shortcut");
 
   let newTargetFile = tempDir.clone();
   newTargetFile.append("ṩhогТϾừ†Target.exe");
-  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  shortcutFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
 
   win.setShortcut(newTargetFile,
                   do_get_profile(), // XXX: This should probably be unicode
                   "ᾶṟǵ3 ᾶṟǵ4",
                   "A ῧṋіḉѻₑ shortcut");
 
   let shortcutTarget = LocalFile(shortcutFile.target);
   do_check_true(shortcutTarget.equals(newTargetFile))