Merge m-c to autoland. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 01 Sep 2016 12:17:16 -0400
changeset 312271 e6a877db45f0d686adcd8923f3b18e9ec4d344bf
parent 312270 91d164ff4285f37c6f0d2e1bdfebbdac43c68395 (current diff)
parent 312263 4dd14de3fa420bf5d750ca7c969ace2a9a9931ac (diff)
child 312272 c1d4822a21272acca445434dc6f74df492945b4f
push id30638
push userkwierso@gmail.com
push dateFri, 02 Sep 2016 00:01:21 +0000
treeherdermozilla-central@4bee81508989 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to autoland. a=merge
dom/svg/nsSVGFeaturesList.h
dom/svg/test/test_hasFeature.xhtml
dom/workers/test/closeOnGC_server.sjs
dom/workers/test/closeOnGC_worker.js
dom/workers/test/close_worker.js
dom/workers/test/test_close.html
dom/workers/test/test_closeOnGC.html
layout/reftests/svg/as-image/script100x100.svg
layout/reftests/svg/as-image/svg-image-script-1.svg
layout/reftests/svg/as-image/svg-image-script-2.svg
layout/reftests/svg/conditions-06.svg
toolkit/components/places/Bookmarks.jsm
toolkit/components/places/PlacesSyncUtils.jsm
toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js
--- a/accessible/tests/mochitest/name/a11y.ini
+++ b/accessible/tests/mochitest/name/a11y.ini
@@ -9,11 +9,12 @@ support-files =
 
 [test_browserui.xul]
 [test_counterstyle.html]
 [test_general.html]
 [test_general.xul]
 [test_link.html]
 [test_list.html]
 [test_markup.html]
+skip-if = (debug && os == 'win') # Bug 1296784
 [test_svg.html]
 [test_toolbaritem.xul]
 [test_tree.xul]
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -59,20 +59,18 @@ if (isGonk) {
     return libcutils;
   });
 }
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
                                   '@mozilla.org/toolkit/captive-detector;1',
                                   'nsICaptivePortalDetector');
 
-if (AppConstants.MOZ_SAFE_BROWSING) {
-  XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
-                "resource://gre/modules/SafeBrowsing.jsm");
-}
+XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
+              "resource://gre/modules/SafeBrowsing.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SafeMode",
                                   "resource://gre/modules/SafeMode.jsm");
 
 window.performance.measure('gecko-shell-jsm-loaded', 'gecko-shell-loadstart');
 
 function debug(str) {
   dump(' -*- Shell.js: ' + str + '\n');
@@ -429,21 +427,19 @@ var shell = {
     window.performance.mark('gecko-shell-system-frame-set');
 
     ppmm.addMessageListener("content-handler", this);
     ppmm.addMessageListener("dial-handler", this);
     ppmm.addMessageListener("sms-handler", this);
     ppmm.addMessageListener("mail-handler", this);
     ppmm.addMessageListener("file-picker", this);
 
-    if (AppConstants.MOZ_SAFE_BROWSING) {
-      setTimeout(function() {
-        SafeBrowsing.init();
-      }, 5000);
-    }
+    setTimeout(function() {
+      SafeBrowsing.init();
+    }, 5000);
   },
 
   stop: function shell_stop() {
     window.removeEventListener('unload', this);
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('sizemodechange', this);
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -12,18 +12,16 @@ MOZ_UA_OS_AGNOSTIC=1
 
 MOZ_B2G_VERSION=2.6.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
-MOZ_SAFE_BROWSING=1
-
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 MOZ_NO_EV_CERTS=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
 MOZ_AUDIO_CHANNEL_MANAGER=1
--- a/b2g/graphene/confvars.sh
+++ b/b2g/graphene/confvars.sh
@@ -19,17 +19,16 @@ MOZ_APP_UA_NAME=Firefox
 
 MOZ_B2G_VERSION=2.6.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
-MOZ_SAFE_BROWSING=1
 MOZ_CAPTIVEDETECT=1
 
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 NSS_NO_LIBPKIX=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -8,18 +8,16 @@
 <!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetMenu.dtd" >
 %charsetDTD;
 <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
 %textcontextDTD;
 <!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd">
   %customizeToolbarDTD;
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
-#ifdef MOZ_SAFE_BROWSING
 <!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
 %safebrowsingDTD;
-#endif
 <!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
 %aboutHomeDTD;
 <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
 %syncBrandDTD;
 ]>
 
--- a/browser/base/content/browser-safebrowsing.js
+++ b/browser/base/content/browser-safebrowsing.js
@@ -1,15 +1,12 @@
 /* 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/. */
 
-// Note: this file is not shipped (through jar.mn)
-// if MOZ_SAFE_BROWSING is not defined.
-
 var gSafeBrowsing = {
 
   setReportPhishingMenu: function() {
     // In order to detect whether or not we're at the phishing warning
     // page, we have to check the documentURI instead of the currentURI.
     // This is because when the DocShell loads an error page, the
     // currentURI stays at the original target, while the documentURI
     // will point to the internal error page we loaded instead.
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -758,17 +758,17 @@ html|*#fullscreen-exit-button {
 
 
 /* notification anchors should only be visible when their associated
    notifications are */
 .notification-anchor-icon {
   -moz-user-focus: normal;
 }
 
-.blocked-permission-icon:not([showing]),
+#blocked-permissions-container > .blocked-permission-icon:not([showing]),
 .notification-anchor-icon:not([showing]) {
   display: none;
 }
 
 #invalid-form-popup > description {
   max-width: 280px;
 }
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -52,20 +52,18 @@ Cu.import("resource://gre/modules/Notifi
   ["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
   ["Weave", "resource://services-sync/main.js"],
   ["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
   ["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
   ["gDevToolsBrowser", "resource://devtools/client/framework/gDevTools.jsm"],
   ["webrtcUI", "resource:///modules/webrtcUI.jsm", ]
 ].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
 
-if (AppConstants.MOZ_SAFE_BROWSING) {
-  XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
-    "resource://gre/modules/SafeBrowsing.jsm");
-}
+XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
+  "resource://gre/modules/SafeBrowsing.jsm");
 
 if (AppConstants.MOZ_CRASHREPORTER) {
   XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter",
     "resource:///modules/ContentCrashHandlers.jsm");
 }
 
 // lazy service getters
 [
@@ -1141,20 +1139,18 @@ var gBrowserInit = {
       }
       // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
       // Such callers expect that window.arguments[0] is handled as a single URI.
       else {
         loadOneOrMoreURIs(uriToLoad);
       }
     }
 
-    if (AppConstants.MOZ_SAFE_BROWSING) {
-      // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
-      setTimeout(function() { SafeBrowsing.init(); }, 2000);
-    }
+    // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
+    setTimeout(function() { SafeBrowsing.init(); }, 2000);
 
     Services.obs.addObserver(gIdentityHandler, "perm-changed", false);
     Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-origin-blocked", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
@@ -7372,17 +7368,17 @@ var gIdentityHandler = {
   _createPermissionItem: function (aPermission) {
     let container = document.createElement("hbox");
     container.setAttribute("class", "identity-popup-permission-item");
     container.setAttribute("align", "center");
 
     let img = document.createElement("image");
     let classes = "identity-popup-permission-icon " + aPermission.id + "-icon";
     if (aPermission.state == SitePermissions.BLOCK)
-      classes += " blocked";
+      classes += " blocked-permission-icon";
     if (aPermission.inUse)
       classes += " in-use";
     img.setAttribute("class", classes);
 
     let nameLabel = document.createElement("label");
     nameLabel.setAttribute("flex", "1");
     nameLabel.setAttribute("class", "identity-popup-permission-label");
     nameLabel.textContent = SitePermissions.getPermissionLabel(aPermission.id);
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -18,19 +18,17 @@
 <script type="application/javascript" src="chrome://browser/content/browser-feeds.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-fullScreenAndPointerLock.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-fullZoom.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-gestureSupport.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-media.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-plugins.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-refreshblocker.js"/>
-#ifdef MOZ_SAFE_BROWSING
 <script type="application/javascript" src="chrome://browser/content/browser-safebrowsing.js"/>
-#endif
 <script type="application/javascript" src="chrome://browser/content/browser-sidebar.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-social.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-syncui.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-tabsintitlebar.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-thumbnails.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser-trackingprotection.js"/>
 
 #ifdef MOZ_DATA_REPORTING
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -737,18 +737,19 @@ function openTourPage()
   let scope = {}
   Components.utils.import("resource:///modules/UITour.jsm", scope);
   openUILinkIn(scope.UITour.url, "tab");
 }
 
 function buildHelpMenu()
 {
   // Enable/disable the "Report Web Forgery" menu item.
-  if (typeof gSafeBrowsing != "undefined" && AppConstants.MOZ_SAFE_BROWSING)
+  if (typeof gSafeBrowsing != "undefined") {
     gSafeBrowsing.setReportPhishingMenu();
+  }
 }
 
 function isElementVisible(aElement)
 {
   if (!aElement)
     return false;
 
   // If aElement or a direct or indirect parent is hidden or collapsed,
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -82,19 +82,17 @@ browser.jar:
         content/browser/browser-fullScreenAndPointerLock.js  (content/browser-fullScreenAndPointerLock.js)
         content/browser/browser-fullZoom.js           (content/browser-fullZoom.js)
         content/browser/browser-fxaccounts.js         (content/browser-fxaccounts.js)
         content/browser/browser-gestureSupport.js     (content/browser-gestureSupport.js)
         content/browser/browser-media.js              (content/browser-media.js)
         content/browser/browser-places.js             (content/browser-places.js)
         content/browser/browser-plugins.js            (content/browser-plugins.js)
         content/browser/browser-refreshblocker.js     (content/browser-refreshblocker.js)
-#ifdef MOZ_SAFE_BROWSING
         content/browser/browser-safebrowsing.js       (content/browser-safebrowsing.js)
-#endif
         content/browser/browser-sidebar.js            (content/browser-sidebar.js)
         content/browser/browser-social.js             (content/browser-social.js)
         content/browser/browser-syncui.js             (content/browser-syncui.js)
 *       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
 #ifdef CAN_DRAW_IN_TITLEBAR
         content/browser/browser-tabsintitlebar.js       (content/browser-tabsintitlebar.js)
 #else
         content/browser/browser-tabsintitlebar.js       (content/browser-tabsintitlebar-stub.js)
@@ -186,15 +184,13 @@ browser.jar:
         content/browser/webrtcIndicator.js            (content/webrtcIndicator.js)
 #endif
 #ifdef XP_WIN
         content/browser/win6BrowserOverlay.xul        (content/win6BrowserOverlay.xul)
 #endif
 # the following files are browser-specific overrides
 *       content/browser/license.html                  (/toolkit/content/license.html)
 % override chrome://global/content/license.html chrome://browser/content/license.html
-#ifdef MOZ_SAFE_BROWSING
         content/browser/report-phishing-overlay.xul     (content/report-phishing-overlay.xul)
         content/browser/blockedSite.xhtml               (content/blockedSite.xhtml)
 % overlay chrome://browser/content/browser.xul chrome://browser/content/report-phishing-overlay.xul
-#endif
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/aboutNetError.xhtml
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -30,23 +30,21 @@ struct RedirEntry {
   Entries which do not have URI_SAFE_FOR_UNTRUSTED_CONTENT will run with chrome
   privileges. This is potentially dangerous. Please use
   URI_SAFE_FOR_UNTRUSTED_CONTENT in the third argument to each map item below
   unless your about: page really needs chrome privileges. Security review is
   required before adding new map entries without
   URI_SAFE_FOR_UNTRUSTED_CONTENT.
 */
 static RedirEntry kRedirMap[] = {
-#ifdef MOZ_SAFE_BROWSING
   { "blocked", "chrome://browser/content/blockedSite.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
-#endif
   { "certerror", "chrome://browser/content/aboutNetError.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "socialerror", "chrome://browser/content/aboutSocialError.xhtml",
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -80,19 +80,17 @@ static const mozilla::Module::CIDEntry k
 static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
     { NS_BROWSERDIRECTORYPROVIDER_CONTRACTID, &kNS_BROWSERDIRECTORYPROVIDER_CID },
 #if defined(XP_WIN)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #elif defined(MOZ_WIDGET_GTK)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #endif
     { NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
-#ifdef MOZ_SAFE_BROWSING
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
-#endif
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "socialerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "providerdirectory", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "tabcrashed", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "rights", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "robots", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -45,23 +45,21 @@ EXTRA_COMPONENTS += [
     'nsBrowserGlue.js',
 ]
 
 EXTRA_JS_MODULES += [
     'distribution.js',
 ]
 
 BROWSER_CHROME_MANIFESTS += [
+    'safebrowsing/content/test/browser.ini',
     'tests/browser/browser.ini'
 ]
 
 XPCSHELL_TESTS_MANIFESTS += [
     'tests/unit/xpcshell.ini'
 ]
 
-if CONFIG['MOZ_SAFE_BROWSING']:
-    BROWSER_CHROME_MANIFESTS += ['safebrowsing/content/test/browser.ini']
-
 with Files('safebrowsing/*'):
     BUG_COMPONENT = ('Toolkit', 'Phishing Protection')
 
 with Files('controlcenter/**'):
     BUG_COMPONENT = ('Firefox', 'General')
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -27,17 +27,16 @@ if test "$OS_ARCH" = "WINNT"; then
       fi
     fi
   fi
 fi
 
 # Enable building ./signmar and running libmar signature tests
 MOZ_ENABLE_SIGNMAR=1
 
-MOZ_SAFE_BROWSING=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_APP_VERSION_DISPLAY=$FIREFOX_VERSION_DISPLAY
 MOZ_EXTENSIONS_DEFAULT=" gio"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
 # specified. It should never point to the "official" branding directory.
 # For mozilla-beta, mozilla-release, or mozilla-central repositories, use
 # "unofficial" branding.
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -591,23 +591,21 @@
 @RESPATH@/components/extensions-toolkit.manifest
 @RESPATH@/browser/components/extensions-browser.manifest
 
 ; Modules
 @RESPATH@/browser/modules/*
 @RESPATH@/modules/*
 
 ; Safe Browsing
-#ifdef MOZ_URL_CLASSIFIER
 @RESPATH@/components/nsURLClassifier.manifest
 @RESPATH@/components/nsUrlClassifierHashCompleter.js
 @RESPATH@/components/nsUrlClassifierListManager.js
 @RESPATH@/components/nsUrlClassifierLib.js
 @RESPATH@/components/url-classifier.xpt
-#endif
 
 ; Private Browsing
 @RESPATH@/components/privatebrowsing.xpt
 @RESPATH@/components/PrivateBrowsing.manifest
 @RESPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js
 
 ; Security Reports
 @RESPATH@/components/SecurityReporter.manifest
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -48,20 +48,18 @@
     locale/browser/downloads/downloads.dtd         (%chrome/browser/downloads/downloads.dtd)
     locale/browser/downloads/downloads.properties  (%chrome/browser/downloads/downloads.properties)
     locale/browser/places/places.dtd               (%chrome/browser/places/places.dtd)
     locale/browser/places/places.properties        (%chrome/browser/places/places.properties)
     locale/browser/places/editBookmarkOverlay.dtd  (%chrome/browser/places/editBookmarkOverlay.dtd)
     locale/browser/places/bookmarkProperties.properties (%chrome/browser/places/bookmarkProperties.properties)
     locale/browser/preferences/selectBookmark.dtd  (%chrome/browser/preferences/selectBookmark.dtd)
     locale/browser/places/moveBookmarks.dtd        (%chrome/browser/places/moveBookmarks.dtd)
-#ifdef MOZ_SAFE_BROWSING
     locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
     locale/browser/safebrowsing/report-phishing.dtd                    (%chrome/browser/safebrowsing/report-phishing.dtd)
-#endif
     locale/browser/feeds/subscribe.dtd              (%chrome/browser/feeds/subscribe.dtd)
     locale/browser/feeds/subscribe.properties       (%chrome/browser/feeds/subscribe.properties)
     locale/browser/migration/migration.dtd         (%chrome/browser/migration/migration.dtd)
     locale/browser/migration/migration.properties  (%chrome/browser/migration/migration.properties)
     locale/browser/preferences/advanced.dtd           (%chrome/browser/preferences/advanced.dtd)
     locale/browser/preferences/applicationManager.dtd        (%chrome/browser/preferences/applicationManager.dtd)
     locale/browser/preferences/applicationManager.properties (%chrome/browser/preferences/applicationManager.properties)
     locale/browser/preferences/blocklists.dtd         (%chrome/browser/preferences/blocklists.dtd)
--- a/config/external/nss/Makefile.in
+++ b/config/external/nss/Makefile.in
@@ -236,16 +236,17 @@ endif
 ifneq (,$(NSS_EXTRA_LDFLAGS))
 DEFAULT_GMAKE_FLAGS += \
 	LDFLAGS='$(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
 	DSO_LDOPTS='$(DSO_LDOPTS) $(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
 	$(NULL)
 endif
 
 DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 $(FREEBL_LOWHASH_FLAG)
+DEFAULT_GMAKE_FLAGS += NSS_ALLOW_SSLKEYLOGFILE=1
 
 ifdef MOZ_NO_WLZDEFS
 DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG=
 endif
 ifdef MOZ_CFLAGS_NSS
 NSS_XCFLAGS += $(filter-out -W%,$(CFLAGS))
 DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS='-compatibility_version 1 -current_version 1 $(LDFLAGS)'
 endif
--- a/devtools/client/debugger/moz.build
+++ b/devtools/client/debugger/moz.build
@@ -8,9 +8,12 @@ DIRS += [
     'new'
 ]
 
 DevToolsModules(
     'debugger-commands.js',
     'panel.js'
 )
 
-BROWSER_CHROME_MANIFESTS += ['test/mochitest/browser.ini']
+BROWSER_CHROME_MANIFESTS += [
+  'new/test/mochitest/browser.ini',
+  'test/mochitest/browser.ini'
+]
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+tags = devtools
+subsuite = devtools
+
+[browser_dbg_stub.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg_stub.js
@@ -0,0 +1,7 @@
+
+add_task(function*() {
+  ok(true,
+     "This is a stub so that we can run the new debugger tests " +
+     "by copying them in here. This will go away once we land " +
+     "the initial suite of new tests");
+});
--- a/devtools/client/definitions.js
+++ b/devtools/client/definitions.js
@@ -177,24 +177,38 @@ Tools.jsdebugger = {
     return true;
   },
 
   build: function (iframeWindow, toolbox) {
     return new DebuggerPanel(iframeWindow, toolbox);
   }
 };
 
-if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
-  const NewDebuggerPanel = require("devtools/client/debugger/new/panel").DebuggerPanel;
+function switchDebugger() {
+  if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
+    const NewDebuggerPanel = require("devtools/client/debugger/new/panel").DebuggerPanel;
 
-  Tools.jsdebugger.url = "chrome://devtools/content/debugger/new/index.html";
-  Tools.jsdebugger.build = function (iframeWindow, toolbox) {
-    return new NewDebuggerPanel(iframeWindow, toolbox);
-  };
+    Tools.jsdebugger.url = "chrome://devtools/content/debugger/new/index.html";
+    Tools.jsdebugger.build = function (iframeWindow, toolbox) {
+      return new NewDebuggerPanel(iframeWindow, toolbox);
+    };
+  } else {
+    Tools.jsdebugger.url = "chrome://devtools/content/debugger/debugger.xul";
+    Tools.jsdebugger.build = function (iframeWindow, toolbox) {
+      return new DebuggerPanel(iframeWindow, toolbox);
+    };
+  }
 }
+switchDebugger();
+
+Services.prefs.addObserver(
+  "devtools.debugger.new-debugger-frontend",
+  { observe: switchDebugger },
+  false
+);
 
 Tools.styleEditor = {
   id: "styleeditor",
   key: l10n("open.commandkey", styleEditorStrings),
   ordinal: 4,
   visibilityswitch: "devtools.styleeditor.enabled",
   accesskey: l10n("open.accesskey", styleEditorStrings),
   modifiers: "shift",
--- a/devtools/shared/l10n.js
+++ b/devtools/shared/l10n.js
@@ -1,44 +1,55 @@
 /* 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/. */
 "use strict";
 
 const parsePropertiesFile = require("devtools/shared/node-properties/node-properties");
 const { sprintf } = require("devtools/shared/sprintfjs/sprintf");
 
+const propertiesMap = {};
+
+/**
+ * Memoized getter for properties files that ensures a given url is only required and
+ * parsed once.
+ *
+ * @param {String} url
+ *        The URL of the properties file to parse.
+ * @return {Object} parsed properties mapped in an object.
+ */
+function getProperties(url) {
+  if (!propertiesMap[url]) {
+    propertiesMap[url] = parsePropertiesFile(require(`raw!${url}`));
+  }
+
+  return propertiesMap[url];
+}
+
 /**
  * Localization convenience methods.
  *
  * @param string stringBundleName
  *        The desired string bundle's name.
  */
 function LocalizationHelper(stringBundleName) {
   this.stringBundleName = stringBundleName;
 }
 
 LocalizationHelper.prototype = {
-  get properties() {
-    if (!this._properties) {
-      this._properties = parsePropertiesFile(require(`raw!${this.stringBundleName}`));
-    }
-
-    return this._properties;
-  },
-
   /**
    * L10N shortcut function.
    *
    * @param string name
    * @return string
    */
   getStr: function (name) {
-    if (name in this.properties) {
-      return this.properties[name];
+    let properties = getProperties(this.stringBundleName);
+    if (name in properties) {
+      return properties[name];
     }
 
     throw new Error("No localization found for [" + name + "]");
   },
 
   /**
    * L10N shortcut function.
    *
@@ -98,16 +109,73 @@ LocalizationHelper.prototype = {
 
     return number.toLocaleString(undefined, {
       maximumFractionDigits: decimals,
       minimumFractionDigits: decimals
     });
   }
 };
 
+function getPropertiesForNode(node) {
+  let bundleEl = node.closest("[data-localization-bundle]");
+  if (!bundleEl) {
+    return null;
+  }
+
+  let propertiesUrl = bundleEl.getAttribute("data-localization-bundle");
+  return getProperties(propertiesUrl);
+}
+
+/**
+ * Translate existing markup annotated with data-localization attributes.
+ *
+ * How to use data-localization in markup:
+ *
+ *   <div data-localization="content=myContent;title=myTitle"/>
+ *
+ * The data-localization attribute identifies an element as being localizable.
+ * The content of the attribute is semi-colon separated list of descriptors.
+ * - "title=myTitle" means the "title" attribute should be replaced with the localized
+ *   string corresponding to the key "myTitle".
+ * - "content=myContent" means the text content of the node should be replaced by the
+ *   string corresponding to "myContent"
+ *
+ * How to define the localization bundle in markup:
+ *
+ *   <div data-localization-bundle="url/to/my.properties">
+ *     [...]
+ *       <div data-localization="content=myContent;title=myTitle"/>
+ *
+ * Set the data-localization-bundle on an ancestor of the nodes that should be localized.
+ *
+ * @param {Element} root
+ *        The root node to use for the localization
+ */
+function localizeMarkup(root) {
+  let elements = root.querySelectorAll("[data-localization]");
+  for (let element of elements) {
+    let properties = getPropertiesForNode(element);
+    if (!properties) {
+      continue;
+    }
+
+    let attributes = element.getAttribute("data-localization").split(";");
+    for (let attribute of attributes) {
+      let [name, value] = attribute.trim().split("=");
+      if (name === "content") {
+        element.textContent = properties[value];
+      } else {
+        element.setAttribute(name, properties[value]);
+      }
+    }
+
+    element.removeAttribute("data-localization");
+  }
+}
+
 const sharedL10N = new LocalizationHelper("devtools-shared/locale/shared.properties");
 const ELLIPSIS = sharedL10N.getStr("ellipsis");
 
 /**
  * A helper for having the same interface as LocalizationHelper, but for more
  * than one file. Useful for abstracting l10n string locations.
  */
 function MultiLocalizationHelper(...stringBundleNames) {
@@ -135,10 +203,11 @@ function MultiLocalizationHelper(...stri
           }
         }
         return null;
       };
     });
 }
 
 exports.LocalizationHelper = LocalizationHelper;
+exports.localizeMarkup = localizeMarkup;
 exports.MultiLocalizationHelper = MultiLocalizationHelper;
 exports.ELLIPSIS = ELLIPSIS;
--- a/devtools/shared/tests/browser/browser.ini
+++ b/devtools/shared/tests/browser/browser.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 tags = devtools
 subsuite = devtools
 support-files =
   ../../../server/tests/browser/head.js
 
 [browser_async_storage.js]
+[browser_l10n_localizeMarkup.js]
new file mode 100644
--- /dev/null
+++ b/devtools/shared/tests/browser/browser_l10n_localizeMarkup.js
@@ -0,0 +1,54 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the markup localization works properly.
+
+const { localizeMarkup, LocalizationHelper } = require("devtools/shared/l10n");
+
+add_task(function* () {
+  info("Check that the strings used for this test are still valid");
+  let INSPECTOR_L10N = new LocalizationHelper("devtools/locale/inspector.properties");
+  let TOOLBOX_L10N = new LocalizationHelper("devtools/locale/toolbox.properties");
+  let str1 = INSPECTOR_L10N.getStr("inspector.label");
+  let str2 = INSPECTOR_L10N.getStr("inspector.commandkey");
+  let str3 = TOOLBOX_L10N.getStr("toolbox.defaultTitle");
+  ok(str1 && str2 && str3, "If this failed, strings should be updated in the test");
+
+  info("Create the test markup");
+  let div = document.createElement("div");
+  div.innerHTML =
+  `<div data-localization-bundle="devtools/locale/inspector.properties">
+     <div id="d0" data-localization="content=inspector.someInvalidKey"></div>
+     <div id="d1" data-localization="content=inspector.label">Text will disappear</div>
+     <div id="d2" data-localization="content=inspector.label;title=inspector.commandkey">
+     </div>
+     <!-- keep the following data-localization on two separate lines -->
+     <div id="d3" data-localization="content=inspector.label;
+                                     title=inspector.commandkey"></div>
+     <div id="d4" data-localization="aria-label=inspector.label">Some content</div>
+     <div data-localization-bundle="devtools/locale/toolbox.properties">
+       <div id="d5" data-localization="content=toolbox.defaultTitle"></div>
+     </div>
+   </div>
+  `;
+
+  info("Use localization helper to localize the test markup");
+  localizeMarkup(div);
+
+  let div1 = div.querySelector("#d1");
+  let div2 = div.querySelector("#d2");
+  let div3 = div.querySelector("#d3");
+  let div4 = div.querySelector("#d4");
+  let div5 = div.querySelector("#d5");
+
+  is(div1.innerHTML, str1, "The content of #d1 is localized");
+  is(div2.innerHTML, str1, "The content of #d2 is localized");
+  is(div2.getAttribute("title"), str2, "The title of #d2 is localized");
+  is(div3.innerHTML, str1, "The content of #d3 is localized");
+  is(div3.getAttribute("title"), str2, "The title of #d3 is localized");
+  is(div4.innerHTML, "Some content", "The content of #d4 is not replaced");
+  is(div4.getAttribute("aria-label"), str1, "The aria-label of #d4 is localized");
+  is(div5.innerHTML, str3, "The content of #d5 is localized with another bundle");
+});
--- a/dom/base/DOMImplementation.cpp
+++ b/dom/base/DOMImplementation.cpp
@@ -31,31 +31,22 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMImple
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMImplementation)
 
 JSObject*
 DOMImplementation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DOMImplementationBinding::Wrap(aCx, this, aGivenProto);
 }
 
-bool
-DOMImplementation::HasFeature(const nsAString& aFeature,
-                              const nsAString& aVersion)
-{
-  return nsContentUtils::InternalIsSupported(
-           static_cast<nsIDOMDOMImplementation*>(this),
-           aFeature, aVersion);
-}
-
 NS_IMETHODIMP
 DOMImplementation::HasFeature(const nsAString& aFeature,
                               const nsAString& aVersion,
                               bool* aReturn)
 {
-  *aReturn = HasFeature(aFeature, aVersion);
+  *aReturn = true;
   return NS_OK;
 }
 
 already_AddRefed<DocumentType>
 DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName,
                                       const nsAString& aPublicId,
                                       const nsAString& aSystemId,
                                       ErrorResult& aRv)
--- a/dom/base/DOMImplementation.h
+++ b/dom/base/DOMImplementation.h
@@ -54,17 +54,20 @@ public:
     return mOwner;
   }
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIDOMDOMImplementation
   NS_DECL_NSIDOMDOMIMPLEMENTATION
 
-  bool HasFeature(const nsAString& aFeature, const nsAString& aVersion);
+  bool HasFeature()
+  {
+    return true;
+  }
 
   already_AddRefed<DocumentType>
   CreateDocumentType(const nsAString& aQualifiedName,
                      const nsAString& aPublicId,
                      const nsAString& aSystemId,
                      ErrorResult& aRv);
 
   already_AddRefed<nsIDocument>
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -118,17 +118,16 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
 #include "prprf.h"
 #include "nsDOMMutationObserver.h"
-#include "nsSVGFeatures.h"
 #include "nsWrapperCacheInlines.h"
 #include "xpcpublic.h"
 #include "nsIScriptError.h"
 #include "mozilla/Telemetry.h"
 
 #include "mozilla/CORSMode.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/NodeListBinding.h"
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -741,38 +741,26 @@ public:
   void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError)
   {
     bool activeState = false;
     if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
       aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
       return;
     }
     nsIPresShell::PointerCaptureInfo* pointerCaptureInfo = nullptr;
-    if (nsIPresShell::gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) && pointerCaptureInfo) {
-      // Call ReleasePointerCapture only on correct element
-      // (on element that have status pointer capture override
-      // or on element that have status pending pointer capture)
-      if (pointerCaptureInfo->mOverrideContent == this) {
-        nsIPresShell::ReleasePointerCapturingContent(aPointerId);
-      } else if (pointerCaptureInfo->mPendingContent == this) {
-        nsIPresShell::ReleasePointerCapturingContent(aPointerId);
-      }
+    if (nsIPresShell::gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
+        pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
+      nsIPresShell::ReleasePointerCapturingContent(aPointerId);
     }
   }
   bool HasPointerCapture(long aPointerId)
   {
-    bool activeState = false;
-    if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
-      return false;
-    }
     nsIPresShell::PointerCaptureInfo* pointerCaptureInfo = nullptr;
     if (nsIPresShell::gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
-        pointerCaptureInfo && !pointerCaptureInfo->mReleaseContent &&
-        (pointerCaptureInfo->mOverrideContent == this ||
-         pointerCaptureInfo->mPendingContent == this)) {
+        pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
       return true;
     }
     return false;
   }
   void SetCapture(bool aRetargetToElement)
   {
     // If there is already an active capture, ignore this request. This would
     // occur if a splitter, frame resizer, etc had already captured and we don't
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -181,17 +181,16 @@
 #include "nsParserConstants.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
 #include "nsReferencedElement.h"
 #include "nsSandboxFlags.h"
 #include "nsScriptSecurityManager.h"
 #include "nsStreamUtils.h"
-#include "nsSVGFeatures.h"
 #include "nsTextEditorState.h"
 #include "nsTextFragment.h"
 #include "nsTextNode.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsUnicodeProperties.h"
 #include "nsViewManager.h"
 #include "nsViewportInfo.h"
@@ -6988,38 +6987,16 @@ nsContentUtils::GetHTMLEditor(nsPresCont
     return nullptr;
 
   nsCOMPtr<nsIEditor> editor;
   docShell->GetEditor(getter_AddRefs(editor));
   return editor;
 }
 
 bool
-nsContentUtils::InternalIsSupported(nsISupports* aObject,
-                                    const nsAString& aFeature,
-                                    const nsAString& aVersion)
-{
-  // If it looks like an SVG feature string, forward to nsSVGFeatures
-  if (StringBeginsWith(aFeature,
-                       NS_LITERAL_STRING("http://www.w3.org/TR/SVG"),
-                       nsASCIICaseInsensitiveStringComparator()) ||
-      StringBeginsWith(aFeature, NS_LITERAL_STRING("org.w3c.dom.svg"),
-                       nsASCIICaseInsensitiveStringComparator()) ||
-      StringBeginsWith(aFeature, NS_LITERAL_STRING("org.w3c.svg"),
-                       nsASCIICaseInsensitiveStringComparator())) {
-    return (aVersion.IsEmpty() || aVersion.EqualsLiteral("1.0") ||
-            aVersion.EqualsLiteral("1.1")) &&
-           nsSVGFeatures::HasFeature(aObject, aFeature);
-  }
-
-  // Otherwise, we claim to support everything
-  return true;
-}
-
-bool
 nsContentUtils::IsContentInsertionPoint(const nsIContent* aContent)
 {
   // Check if the content is a XBL insertion point.
   if (aContent->IsActiveChildrenElement()) {
     return true;
   }
 
   // Check if the content is a web components content insertion point.
@@ -8095,16 +8072,17 @@ nsContentUtils::SendKeyEvent(nsIWidget* 
 }
 
 nsresult
 nsContentUtils::SendMouseEvent(nsCOMPtr<nsIPresShell> aPresShell,
                                const nsAString& aType,
                                float aX,
                                float aY,
                                int32_t aButton,
+                               int32_t aButtons,
                                int32_t aClickCount,
                                int32_t aModifiers,
                                bool aIgnoreRootScrollFrame,
                                float aPressure,
                                unsigned short aInputSourceArg,
                                bool aToWindow,
                                bool *aPreventDefault,
                                bool aIsDOMEventSynthesized,
@@ -8145,17 +8123,19 @@ nsContentUtils::SendMouseEvent(nsCOMPtr<
   WidgetMouseEvent event(true, msg, widget,
                          aIsWidgetEventSynthesized ?
                            WidgetMouseEvent::eSynthesized :
                            WidgetMouseEvent::eReal,
                          contextMenuKey ? WidgetMouseEvent::eContextMenuKey :
                                           WidgetMouseEvent::eNormal);
   event.mModifiers = GetWidgetModifiers(aModifiers);
   event.button = aButton;
-  event.buttons = GetButtonsFlagForButton(aButton);
+  event.buttons = aButtons != nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED ?
+                  aButtons :
+                  msg == eMouseUp ? 0 : GetButtonsFlagForButton(aButton);
   event.pressure = aPressure;
   event.inputSource = aInputSourceArg;
   event.mClickCount = aClickCount;
   event.mTime = PR_IntervalNow();
   event.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
 
   nsPresContext* presContext = aPresShell->GetPresContext();
   if (!presContext)
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2359,28 +2359,16 @@ public:
    * @see GetSelectionInTextControl for the original basis of this function.
    */
   static int32_t GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame,
                                                 int32_t aOffset);
 
   static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext);
 
   /**
-   * Check whether a spec feature/version is supported.
-   * @param aObject the object, which should support the feature,
-   *        for example nsIDOMNode or nsIDOMDOMImplementation
-   * @param aFeature the feature ("Views", "Core", "HTML", "Range" ...)
-   * @param aVersion the version ("1.0", "2.0", ...)
-   * @return whether the feature is supported or not
-   */
-  static bool InternalIsSupported(nsISupports* aObject,
-                                  const nsAString& aFeature,
-                                  const nsAString& aVersion);
-
-  /**
    * Returns true if the browser.dom.window.dump.enabled pref is set.
    */
   static bool DOMWindowDumpEnabled();
 
   /**
    * Returns true if the privacy.donottrackheader.enabled pref is set.
    */
   static bool DoNotTrackEnabled();
@@ -2549,16 +2537,17 @@ public:
    * Synthesize a mouse event to the given widget
    * (see nsIDOMWindowUtils.sendMouseEvent).
    */
   static nsresult SendMouseEvent(nsCOMPtr<nsIPresShell> aPresShell,
                                  const nsAString& aType,
                                  float aX,
                                  float aY,
                                  int32_t aButton,
+                                 int32_t aButtons,
                                  int32_t aClickCount,
                                  int32_t aModifiers,
                                  bool aIgnoreRootScrollFrame,
                                  float aPressure,
                                  unsigned short aInputSourceArg,
                                  bool aToWindow,
                                  bool *aPreventDefault,
                                  bool aIsDOMEventSynthesized,
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -645,72 +645,79 @@ nsDOMWindowUtils::SendMouseEvent(const n
                                  int32_t aButton,
                                  int32_t aClickCount,
                                  int32_t aModifiers,
                                  bool aIgnoreRootScrollFrame,
                                  float aPressure,
                                  unsigned short aInputSourceArg,
                                  bool aIsDOMEventSynthesized,
                                  bool aIsWidgetEventSynthesized,
+                                 int32_t aButtons,
                                  uint8_t aOptionalArgCount,
                                  bool *aPreventDefault)
 {
   return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
                               aIgnoreRootScrollFrame, aPressure,
                               aInputSourceArg, false, aPreventDefault,
                               aOptionalArgCount >= 4 ?
                                 aIsDOMEventSynthesized : true,
                               aOptionalArgCount >= 5 ?
-                                aIsWidgetEventSynthesized : false);
+                                aIsWidgetEventSynthesized : false,
+                              aOptionalArgCount >= 6 ?
+                              aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendMouseEventToWindow(const nsAString& aType,
                                          float aX,
                                          float aY,
                                          int32_t aButton,
                                          int32_t aClickCount,
                                          int32_t aModifiers,
                                          bool aIgnoreRootScrollFrame,
                                          float aPressure,
                                          unsigned short aInputSourceArg,
                                          bool aIsDOMEventSynthesized,
                                          bool aIsWidgetEventSynthesized,
+                                         int32_t aButtons,
                                          uint8_t aOptionalArgCount)
 {
   PROFILER_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow",
     js::ProfileEntry::Category::EVENTS);
 
   return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
                               aIgnoreRootScrollFrame, aPressure,
                               aInputSourceArg, true, nullptr,
                               aOptionalArgCount >= 4 ?
                                 aIsDOMEventSynthesized : true,
                               aOptionalArgCount >= 5 ?
-                                aIsWidgetEventSynthesized : false);
+                                aIsWidgetEventSynthesized : false,
+                              aOptionalArgCount >= 6 ?
+                              aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
                                        float aX,
                                        float aY,
                                        int32_t aButton,
                                        int32_t aClickCount,
                                        int32_t aModifiers,
                                        bool aIgnoreRootScrollFrame,
                                        float aPressure,
                                        unsigned short aInputSourceArg,
                                        bool aToWindow,
                                        bool *aPreventDefault,
                                        bool aIsDOMEventSynthesized,
-                                       bool aIsWidgetEventSynthesized)
+                                       bool aIsWidgetEventSynthesized,
+                                       int32_t aButtons)
 {
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   return nsContentUtils::SendMouseEvent(presShell, aType, aX, aY, aButton,
-      aClickCount, aModifiers, aIgnoreRootScrollFrame, aPressure,
+      aButtons, aClickCount, aModifiers, aIgnoreRootScrollFrame, aPressure,
       aInputSourceArg, aToWindow, aPreventDefault, aIsDOMEventSynthesized,
       aIsWidgetEventSynthesized);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendPointerEventCommon(const nsAString& aType,
                                          float aX,
                                          float aY,
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -89,17 +89,18 @@ protected:
                                   int32_t aClickCount,
                                   int32_t aModifiers,
                                   bool aIgnoreRootScrollFrame,
                                   float aPressure,
                                   unsigned short aInputSourceArg,
                                   bool aToWindow,
                                   bool *aPreventDefault,
                                   bool aIsDOMEventSynthesized,
-                                  bool aIsWidgetEventSynthesized);
+                                  bool aIsWidgetEventSynthesized,
+                                  int32_t aButtons);
 
   NS_IMETHOD SendPointerEventCommon(const nsAString& aType,
                                     float aX,
                                     float aY,
                                     int32_t aButton,
                                     int32_t aClickCount,
                                     int32_t aModifiers,
                                     bool aIgnoreRootScrollFrame,
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -81,17 +81,16 @@
 #include "nsNodeInfoManager.h"
 #include "nsNodeUtils.h"
 #include "nsPIBoxObject.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "nsRuleProcessorData.h"
 #include "nsString.h"
 #include "nsStyleConsts.h"
-#include "nsSVGFeatures.h"
 #include "nsSVGUtils.h"
 #include "nsTextNode.h"
 #include "nsUnicharUtils.h"
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "mozilla/Preferences.h"
 #include "prprf.h"
 #include "xpcpublic.h"
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5421,22 +5421,23 @@ CanvasRenderingContext2D::GetImageDataAr
 
   IntRect srcRect(0, 0, mWidth, mHeight);
   IntRect destRect(aX, aY, aWidth, aHeight);
   IntRect srcReadRect = srcRect.Intersect(destRect);
   RefPtr<DataSourceSurface> readback;
   DataSourceSurface::MappedSurface rawData;
   if (!srcReadRect.IsEmpty()) {
     RefPtr<SourceSurface> snapshot;
-    if (mTarget) {
-      snapshot = mTarget->Snapshot();
-    } else if (mBufferProvider) {
+    if (!mTarget && mBufferProvider) {
       snapshot = mBufferProvider->BorrowSnapshot();
     } else {
       EnsureTarget();
+      if (!IsTargetValid()) {
+        return NS_ERROR_FAILURE;
+      }
       snapshot = mTarget->Snapshot();
     }
 
     if (snapshot) {
       readback = snapshot->GetDataSurface();
     }
 
     if (!mTarget && mBufferProvider) {
--- a/dom/events/EventStates.h
+++ b/dom/events/EventStates.h
@@ -295,16 +295,18 @@ private:
 // Element is rtl (for :dir pseudo-class)
 #define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43)
 // Element is highlighted (devtools inspector)
 #define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45)
 // Element is an unresolved custom element candidate
 #define NS_EVENT_STATE_UNRESOLVED NS_DEFINE_EVENT_STATE_MACRO(46)
 // Element is transitioning for rules changed by style editor
 #define NS_EVENT_STATE_STYLEEDITOR_TRANSITIONING NS_DEFINE_EVENT_STATE_MACRO(47)
+// Content shows its placeholder
+#define NS_EVENT_STATE_PLACEHOLDERSHOWN NS_DEFINE_EVENT_STATE_MACRO(48)
 
 // Event state that is used for values that need to be parsed but do nothing.
 #define NS_EVENT_STATE_IGNORE NS_DEFINE_EVENT_STATE_MACRO(63)
 
 /**
  * NOTE: do not go over 63 without updating EventStates::InternalType!
  */
 
--- a/dom/events/test/pointerevents/mochitest.ini
+++ b/dom/events/test/pointerevents/mochitest.ini
@@ -16,16 +16,18 @@ support-files =
 [test_pointerevent_change-touch-action-onpointerdown_touch-manual.html]
   support-files = pointerevent_change-touch-action-onpointerdown_touch-manual.html
   disabled = disabled
 [test_pointerevent_constructor.html]
   support-files = pointerevent_constructor.html
   disabled = should be investigated
 [test_pointerevent_element_haspointercapture-manual.html]
   support-files = pointerevent_element_haspointercapture-manual.html
+[test_pointerevent_element_haspointercapture_release_pending_capture-manual.html]
+  support-files = pointerevent_element_haspointercapture_release_pending_capture-manual.html
 [test_pointerevent_gotpointercapture_before_first_pointerevent-manual.html]
   support-files = pointerevent_gotpointercapture_before_first_pointerevent-manual.html
 [test_pointerevent_lostpointercapture_for_disconnected_node-manual.html]
   support-files = pointerevent_lostpointercapture_for_disconnected_node-manual.html
 [test_pointerevent_lostpointercapture_is_first-manual.html]
   support-files = pointerevent_lostpointercapture_is_first-manual.html
 [test_pointerevent_multiple_primary_pointers_boundary_events-manual.html]
   support-files = pointerevent_multiple_primary_pointers_boundary_events-manual.html
@@ -64,17 +66,16 @@ support-files =
 [test_pointerevent_pointerleave_touch-manual.html]
   support-files = pointerevent_pointerleave_touch-manual.html
 [test_pointerevent_pointermove-manual.html]
   support-files = pointerevent_pointermove-manual.html
 [test_pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html]
   support-files = pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html
 [test_pointerevent_pointermove-on-chorded-mouse-button.html]
   support-files = pointerevent_pointermove-on-chorded-mouse-button.html
-  disabled = should be investigated
 [test_pointerevent_pointermove_pointertype-manual.html]
   support-files = pointerevent_pointermove_pointertype-manual.html
 [test_pointerevent_pointerout-manual.html]
   support-files = pointerevent_pointerout-manual.html
 [test_pointerevent_pointerout_after_pointercancel_touch-manual.html]
   support-files = pointerevent_pointerout_after_pointercancel_touch-manual.html
 [test_pointerevent_pointerout_after_pointerup_nohover-manual.html]
   support-files = pointerevent_pointerout_after_pointerup_nohover-manual.html
@@ -101,25 +102,31 @@ support-files =
 [test_pointerevent_releasepointercapture_events_to_original_target-manual.html]
   support-files = pointerevent_releasepointercapture_events_to_original_target-manual.html
 [test_pointerevent_releasepointercapture_invalid_pointerid-manual.html]
   support-files = pointerevent_releasepointercapture_invalid_pointerid-manual.html
 [test_pointerevent_releasepointercapture_onpointercancel_touch-manual.html]
   support-files = pointerevent_releasepointercapture_onpointercancel_touch-manual.html
 [test_pointerevent_releasepointercapture_onpointerup_mouse-manual.html]
   support-files = pointerevent_releasepointercapture_onpointerup_mouse-manual.html
+[test_pointerevent_releasepointercapture_release_right_after_capture-manual.html]
+  support-files = pointerevent_releasepointercapture_release_right_after_capture-manual.html
 [test_pointerevent_setpointercapture_disconnected-manual.html]
   support-files = pointerevent_setpointercapture_disconnected-manual.html
 [test_pointerevent_setpointercapture_inactive_button_mouse-manual.html]
   support-files = pointerevent_setpointercapture_inactive_button_mouse-manual.html
   disabled = should be investigated
 [test_pointerevent_setpointercapture_invalid_pointerid-manual.html]
   support-files = pointerevent_setpointercapture_invalid_pointerid-manual.html
+[test_pointerevent_setpointercapture_override_pending_capture_element-manual.html]
+  support-files = pointerevent_setpointercapture_override_pending_capture_element-manual.html
 [test_pointerevent_setpointercapture_relatedtarget-manual.html]
   support-files = pointerevent_setpointercapture_relatedtarget-manual.html
+[test_pointerevent_setpointercapture_to_same_element_twice-manual.html]
+  support-files = pointerevent_setpointercapture_to_same_element_twice-manual.html
 [test_pointerevent_suppress_compat_events_on_click.html]
   support-files = pointerevent_suppress_compat_events_on_click.html
   disabled = should be investigated
 [test_pointerevent_suppress_compat_events_on_drag_mouse.html]
   support-files = pointerevent_suppress_compat_events_on_drag_mouse.html
   disabled = should be investigated
 [test_touch_action.html]
   # Windows touch injection doesn't work in automation, but this test can be run locally on a windows touch device.
--- a/dom/events/test/pointerevents/mochitest_support_external.js
+++ b/dom/events/test/pointerevents/mochitest_support_external.js
@@ -67,16 +67,18 @@ function sendMouseEvent(int_win, elemId,
   var elem = int_win.document.getElementById(elemId);
   if(!!elem) {
     var rect = elem.getBoundingClientRect();
     var eventObj = {type: mouseEventType};
     if(params && "button" in params)
       eventObj.button = params.button;
     if(params && "inputSource" in params)
       eventObj.inputSource = params.inputSource;
+    if(params && "buttons" in params)
+      eventObj.buttons = params.buttons;
     console.log(elemId, eventObj);
     synthesizeMouse(elem, rect.width/4, rect.height/2, eventObj, int_win);
   } else {
     is(!!elem, true, "Document should have element with id: " + elemId);
   }
 }
 
 // Helper function to send TouchEvent with different parameters
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/pointerevent_element_haspointercapture_release_pending_capture-manual.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Element.hasPointerCapture test after the pending pointer capture element releases pointer capture</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <!--script src="/resources/testharnessreport.js"></script-->
+        <script type="text/javascript" src="pointerevent_support.js"></script>
+        <script type="text/javascript" src="mochitest_support_internal.js"></script>
+        <script>
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_pointerEvent = async_test("hasPointerCapture test after the pending pointer capture element releases pointer capture");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (e) {
+                    detected_pointertypes[e.pointerType] = true;
+                    target0.setPointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), true, "After target0.setPointerCapture, target0.hasPointerCapture should return true");
+                    });
+                });
+
+                on_event(target0, "gotpointercapture", function (e) {
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), true, "After target0 received gotpointercapture, target0.hasPointerCapture should return true");
+                    });
+                    target1.setPointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target1.setPointerCapture, target0.hasPointerCapture should return false");
+                        assert_equals(target1.hasPointerCapture(e.pointerId), true, "After target1.setPointerCapture, target1.hasPointerCapture should return true");
+                    });
+                    target1.releasePointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target1.releasePointerCapture, target0.hasPointerCapture should be false");
+                        assert_equals(target1.hasPointerCapture(e.pointerId), false, "After target1.releasePointerCapture, target1.hasPointerCapture should be false");
+                    });
+                });
+
+                on_event(target1, "gotpointercapture", function (e) {
+                    test_pointerEvent.step(function () {
+                        assert_true(false, "target1 should never receive gotpointercapture in this test");
+                    });
+                });
+
+                on_event(target0, "lostpointercapture", function (e) {
+                    test_pointerEvent.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Element.hasPointerCapture test after the pending pointer capture element releases pointer capture</h1>
+        <!--
+        <h4>
+            Test Description: This test checks if Element.hasPointerCapture returns value correctly after the pending pointer capture element releases pointer capture
+            <ol>
+                <li> Press black rectangle and do not release
+                <li> Move your pointer to purple rectangle
+                <li> Release the pointer
+            </ol>
+        </h4>
+        -->
+        <p>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Release pointer capture right after setpointercapture</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <!--script src="/resources/testharnessreport.js"></script-->
+        <script src="pointerevent_support.js"></script>
+        <script src="mochitest_support_internal.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("Release pointer capture right after setpointercapture");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                    target0.releasePointerCapture(event.pointerId);
+                    assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target0.releasePointerCapture, target0.hasPointerCapture should be false");
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_true(false, "target0 shouldn't receive gotpointercapture");
+                    });
+                });
+
+                on_event(target0, "lostpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_true(false, "target0 shouldn't receive lostpointercapture");
+                    });
+                });
+
+                on_event(target0, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Release pointer capture right after setpointercapture</h1>
+        <!--
+        <h4>Test Description:
+            When calling releasePointer right after setPointerCapture method is invoked, the pending pointer capture should be cleared and no element should receive gotpointercapture and lostpointercapture events
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        -->
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Test overriding the pending pointer capture element</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <!--script src="/resources/testharnessreport.js"></script-->
+        <script src="pointerevent_support.js"></script>
+        <script src="mochitest_support_internal.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("setPointerCapture: override the pending pointer capture element");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Set capture to target0, target0.hasPointerCapture should be true");
+                    });
+                    target1.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), false, "Set capture to target1, target0.hasPointerCapture should be false");
+                        assert_equals(target1.hasPointerCapture(event.pointerId), true, "Set capture to target1, target1.hasPointerCapture should be true");
+                    });
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    assert_true(false, "target0 shouldn't receive gotpointercapture");
+                });
+
+                on_event(target1, "gotpointercapture", function (event) {
+                    assert_true(true, "target1 should receive gotpointercapture");
+                });
+
+                on_event(target1, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Pointer Event: Test overriding the pending pointer capture element</h1>
+        <!--
+        <h4>Test Description:
+            After an element setPointerCapture, if another element also setPointerCapture and override it, the old pending pointer capture element shouldn't receive any gotpointercapture or lostpointercapture event
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        -->
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+    <head>
+        <title>setPointerCapture() to the element which already captured the pointer</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <!--script src="/resources/testharnessreport.js"></script-->
+        <script src="pointerevent_support.js"></script>
+        <script src="mochitest_support_internal.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("setPointerCapture: set to the element which already captured the pointer");
+            var got_pointer_capture = false;
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_equals(got_pointer_capture, false, "Target0 should receive gotpointercapture at the first time it captured the pointer");
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Target 0 received gotpointercapture, target0.hasPointerCapture should be true");
+                    });
+                    got_pointer_capture = true;
+
+                    target0.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Set capture to target0, target0.hasPointerCapture should be true");
+                        assert_equals(target1.hasPointerCapture(event.pointerId), false, "Set capture to target0, target1.hasPointerCapture should be false");
+                    });
+                });
+
+                on_event(target0, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Pointer Event: setPointerCapture to the element which already captured the pointer</h1>
+        <!--
+        <h4>Test Description:
+            When the setPointerCapture method is invoked, if the target element had already captured the pointer, it should not trigger any gotpointercapture or lostpointercapture event
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        -->
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointerevent_element_haspointercapture_release_pending_capture-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+  <head>
+    <meta charset="utf-8">
+    <title>Test for Bug 1000870</title>
+    <meta name="author" content="Maksim Lebedev" />
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script type="text/javascript" src="mochitest_support_external.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="text/javascript">
+      SimpleTest.waitForExplicitFinish();
+      function startTest() {
+        var iframe = document.getElementById("testFrame");
+        iframe.src = "pointerevent_element_haspointercapture_release_pending_capture-manual.html";
+      }
+      function executeTest(int_win) {
+        sendMouseEvent(int_win, "target0", "mousemove");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target1", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target1", "mouseup", {button:0});
+      }
+    </script>
+  </head>
+  <body>
+    <iframe id="testFrame" height="800" width="1000"></iframe>
+  </body>
+</html>
--- a/dom/events/test/pointerevents/test_pointerevent_lostpointercapture_is_first-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_lostpointercapture_is_first-manual.html
@@ -13,18 +13,18 @@ https://bugzilla.mozilla.org/show_bug.cg
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     <script type="text/javascript">
       SimpleTest.waitForExplicitFinish();
       function startTest() {
         var iframe = document.getElementById("testFrame");
         iframe.src = "pointerevent_lostpointercapture_is_first-manual.html";
       }
       function executeTest(int_win) {
-        sendMouseEvent(int_win, "btnCapture", "mousedown");
-        sendMouseEvent(int_win, "btnCapture", "mouseup");
+        sendMouseEvent(int_win, "btnCapture", "mousedown", {button:0});
+        sendMouseEvent(int_win, "btnCapture", "mouseup", {button:0});
         sendMouseEvent(int_win, "btnCapture", "mousemove");
       }
     </script>
   </head>
   <body>
     <iframe id="testFrame" height="800" width="1000"></iframe>
   </body>
 </html>
--- a/dom/events/test/pointerevents/test_pointerevent_pointermove-on-chorded-mouse-button.html
+++ b/dom/events/test/pointerevents/test_pointerevent_pointermove-on-chorded-mouse-button.html
@@ -12,18 +12,28 @@ https://bugzilla.mozilla.org/show_bug.cg
     <script type="text/javascript" src="mochitest_support_external.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     <script type="text/javascript">
       SimpleTest.waitForExplicitFinish();
       function startTest() {
         var iframe = document.getElementById("testFrame");
         iframe.src = "pointerevent_pointermove-on-chorded-mouse-button.html";
       }
+
       function executeTest(int_win) {
-        sendMouseEvent(int_win, "target0", "mousedown");
-        sendMouseEvent(int_win, "target0", "mouseup");
+        var utils = _getDOMWindowUtils(int_win);
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
+        sendMouseEvent(int_win, "target0", "mousedown", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
+                                                                           utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
+                                                                           utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
       }
     </script>
   </head>
   <body>
     <iframe id="testFrame" height="800" width="1000"></iframe>
   </body>
 </html>
--- a/dom/events/test/pointerevents/test_pointerevent_pointertype_mouse-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_pointertype_mouse-manual.html
@@ -13,17 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     <script type="text/javascript">
       SimpleTest.waitForExplicitFinish();
       function startTest() {
         var iframe = document.getElementById("testFrame");
         iframe.src = "pointerevent_pointertype_mouse-manual.html";
       }
       function executeTest(int_win) {
-        sendMouseEvent(int_win, "target0", "mousedown");
-        sendMouseEvent(int_win, "target0", "mouseup");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0});
       }
     </script>
   </head>
   <body>
     <iframe id="testFrame" height="800" width="1000"></iframe>
   </body>
 </html>
--- a/dom/events/test/pointerevents/test_pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html
+++ b/dom/events/test/pointerevents/test_pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html
@@ -13,17 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     <script type="text/javascript">
       SimpleTest.waitForExplicitFinish();
       function startTest() {
         var iframe = document.getElementById("testFrame");
         iframe.src = "pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html";
       }
       function executeTest(int_win) {
-        sendMouseEvent(int_win, "target0", "mousedown");
-        sendMouseEvent(int_win, "target0", "mouseup");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0});
       }
     </script>
   </head>
   <body>
     <iframe id="testFrame" height="800" width="1000"></iframe>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointerevent_releasepointercapture_release_right_after_capture-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+  <head>
+    <meta charset="utf-8">
+    <title>Test for Bug 1000870</title>
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script type="text/javascript" src="mochitest_support_external.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="text/javascript">
+      SimpleTest.waitForExplicitFinish();
+      function startTest() {
+        var iframe = document.getElementById("testFrame");
+        iframe.src = "pointerevent_releasepointercapture_release_right_after_capture-manual.html";
+      }
+      function executeTest(int_win) {
+        sendMouseEvent(int_win, "target0", "mousemove");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0});
+      }
+    </script>
+  </head>
+  <body>
+    <iframe id="testFrame" height="800" width="1000"></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointerevent_setpointercapture_override_pending_capture_element-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+  <head>
+    <meta charset="utf-8">
+    <title>Test for Bug 1000870</title>
+    <meta name="author" content="Maksim Lebedev" />
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script type="text/javascript" src="mochitest_support_external.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="text/javascript">
+      SimpleTest.waitForExplicitFinish();
+      function startTest() {
+        var iframe = document.getElementById("testFrame");
+        iframe.src = "pointerevent_setpointercapture_override_pending_capture_element-manual.html";
+      }
+      function executeTest(int_win) {
+        sendMouseEvent(int_win, "target0", "mousemove");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0});
+      }
+    </script>
+  </head>
+  <body>
+    <iframe id="testFrame" height="800" width="1000"></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/events/test/pointerevents/test_pointerevent_setpointercapture_to_same_element_twice-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
+-->
+  <head>
+    <meta charset="utf-8">
+    <title>Test for Bug 1000870</title>
+    <meta name="author" content="Maksim Lebedev" />
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script type="text/javascript" src="mochitest_support_external.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="text/javascript">
+      SimpleTest.waitForExplicitFinish();
+      function startTest() {
+        var iframe = document.getElementById("testFrame");
+        iframe.src = "pointerevent_setpointercapture_to_same_element_twice-manual.html";
+      }
+      function executeTest(int_win) {
+        sendMouseEvent(int_win, "target0", "mousemove");
+        sendMouseEvent(int_win, "target0", "mousedown", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mousemove", {button:0});
+        sendMouseEvent(int_win, "target0", "mouseup", {button:0});
+      }
+    </script>
+  </head>
+  <body>
+    <iframe id="testFrame" height="800" width="1000"></iframe>
+  </body>
+</html>
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3103,16 +3103,25 @@ HTMLInputElement::SetValueInternal(const
       if (mType == NS_FORM_INPUT_COLOR) {
         // Update color frame, to reflect color changes
         nsColorControlFrame* colorControlFrame = do_QueryFrame(GetPrimaryFrame());
         if (colorControlFrame) {
           colorControlFrame->UpdateColor();
         }
       }
 
+      // This call might be useless in some situations because if the element is
+      // a single line text control, nsTextEditorState::SetValue will call
+      // nsHTMLInputElement::OnValueChanged which is going to call UpdateState()
+      // if the element is focused. This bug 665547.
+      if (PlaceholderApplies() &&
+          HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
+        UpdateState(true);
+      }
+
       return NS_OK;
     }
 
     case VALUE_MODE_DEFAULT:
     case VALUE_MODE_DEFAULT_ON:
       // If the value of a hidden input was changed, we mark it changed so that we
       // will know we need to save / restore the value.  Yes, we are overloading
       // the meaning of ValueChanged just a teensy bit to save a measly byte of
@@ -6483,16 +6492,22 @@ HTMLInputElement::IntrinsicState() const
     if (mHasRange) {
       state |= (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) ||
                 GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW))
                  ? NS_EVENT_STATE_OUTOFRANGE
                  : NS_EVENT_STATE_INRANGE;
     }
   }
 
+  if (PlaceholderApplies() &&
+      HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
+      IsValueEmpty()) {
+    state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
+  }
+
   if (mForm && !mForm->GetValidity() && IsSubmitControl()) {
     state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
   }
 
   return state;
 }
 
 void
@@ -7913,16 +7928,23 @@ HTMLInputElement::OnValueChanged(bool aN
 {
   mLastValueChangeWasInteractive = aWasInteractiveUserChange;
 
   UpdateAllValidityStates(aNotify);
 
   if (HasDirAuto()) {
     SetDirectionIfAuto(true, aNotify);
   }
+
+  // :placeholder-shown pseudo-class may change when the value changes.
+  // However, we don't want to waste cycles if the state doesn't apply.
+  if (PlaceholderApplies() &&
+      HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
+    UpdateState(aNotify);
+  }
 }
 
 NS_IMETHODIMP_(bool)
 HTMLInputElement::HasCachedSelection()
 {
   bool isCached = false;
   nsTextEditorState* state = GetEditorState();
   if (state) {
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -1203,16 +1203,21 @@ HTMLTextAreaElement::IntrinsicState() co
     if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
         (mCanShowValidUI && ShouldShowValidityUI() &&
          (IsValid() || (state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
                         !mCanShowInvalidUI)))) {
       state |= NS_EVENT_STATE_MOZ_UI_VALID;
     }
   }
 
+  if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
+      IsValueEmpty()) {
+    state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
+  }
+
   return state;
 }
 
 nsresult
 HTMLTextAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers)
 {
@@ -1612,17 +1617,18 @@ HTMLTextAreaElement::OnValueChanged(bool
   mLastValueChangeWasInteractive = aWasInteractiveUserChange;
 
   // Update the validity state
   bool validBefore = IsValid();
   UpdateTooLongValidityState();
   UpdateTooShortValidityState();
   UpdateValueMissingValidityState();
 
-  if (validBefore != IsValid()) {
+  if (validBefore != IsValid() ||
+      HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
     UpdateState(aNotify);
   }
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTextAreaElement::HasCachedSelection()
 {
   return mState.IsSelectionCached();
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -326,17 +326,18 @@ interface nsIDOMWindowUtils : nsISupport
                          in float aY,
                          in long aButton,
                          in long aClickCount,
                          in long aModifiers,
                          [optional] in boolean aIgnoreRootScrollFrame,
                          [optional] in float aPressure,
                          [optional] in unsigned short aInputSourceArg,
                          [optional] in boolean aIsDOMEventSynthesized,
-                         [optional] in boolean aIsWidgetEventSynthesized);
+                         [optional] in boolean aIsWidgetEventSynthesized,
+                         [optional] in long aButtons);
 
 
   /** Synthesize a pointer event. The event types supported are:
    *    pointerdown, pointerup, pointermove, pointerover, pointerout
    *
    * Events are sent in coordinates offset by aX and aY from the window.
    *
    * Note that additional events may be fired as a result of this call. For
@@ -446,17 +447,18 @@ interface nsIDOMWindowUtils : nsISupport
                               in float aY,
                               in long aButton,
                               in long aClickCount,
                               in long aModifiers,
                               [optional] in boolean aIgnoreRootScrollFrame,
                               [optional] in float aPressure,
                               [optional] in unsigned short aInputSourceArg,
                               [optional] in boolean aIsDOMEventSynthesized,
-                              [optional] in boolean aIsWidgetEventSynthesized);
+                              [optional] in boolean aIsWidgetEventSynthesized,
+                              [optional] in long aButtons);
 
   /** The same as sendPointerEvent but ensures that the event
    *  is dispatched to this DOM window or one of its children.
    */
   [optional_argc]
   void sendPointerEventToWindow(in AString aType,
                                 in float aX,
                                 in float aY,
@@ -1945,16 +1947,29 @@ interface nsIDOMWindowUtils : nsISupport
    */
   void respectDisplayPortSuppression(in boolean aEnabled);
 
   /**
    * Set a flag that forces the next reflow interrupt check to return true. This
    * can be used by tests to force execution of the interrupted reflow codepaths.
    */
   void forceReflowInterrupt();
+
+  const long MOUSE_BUTTONS_NO_BUTTON = 0x00;
+  const long MOUSE_BUTTONS_LEFT_BUTTON = 0x01;
+  const long MOUSE_BUTTONS_RIGHT_BUTTON = 0x02;
+  const long MOUSE_BUTTONS_MIDDLE_BUTTON = 0x04;
+  // Typically, "back" button being left side of 5-button
+  // mice, see "buttons" attribute document of DOM3 Events.
+  const long MOUSE_BUTTONS_4TH_BUTTON = 0x08;
+  // Typically, "forward" button being right side of 5-button
+  // mice, see "buttons" attribute document of DOM3 Events.
+  const long MOUSE_BUTTONS_5TH_BUTTON = 0x10;
+  // Buttons are not specified, will be calculated from |aButton|.
+  const long MOUSE_BUTTONS_NOT_SPECIFIED = -1;
 };
 
 [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
 interface nsITranslationNodeList : nsISupports {
   readonly attribute unsigned long length;
   nsIDOMNode item(in unsigned long index);
 
   // A translation root is a block element, or an inline element
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2549,17 +2549,17 @@ TabParent::GetAuthPrompt(uint32_t aPromp
   // of the dialogs works as it should when using tabs.
   nsCOMPtr<nsISupports> prompt;
   rv = wwatch->GetPrompt(window, iid, getter_AddRefs(prompt));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoginManagerPrompter> prompter = do_QueryInterface(prompt);
   if (prompter) {
     nsCOMPtr<nsIDOMElement> browser = do_QueryInterface(mFrameElement);
-    prompter->SetE10sData(browser, nullptr);
+    prompter->SetBrowser(browser);
   }
 
   *aResult = prompt.forget().take();
   return NS_OK;
 }
 
 PColorPickerParent*
 TabParent::AllocPColorPickerParent(const nsString& aTitle,
--- a/dom/promise/tests/test_webassembly_compile.html
+++ b/dom/promise/tests/test_webassembly_compile.html
@@ -20,23 +20,25 @@ const fooModuleCode = wasmTextToBinary(`
 function checkFooModule(m) {
   ok(m instanceof WebAssembly.Module, "got a module");
   var i = new WebAssembly.Instance(m);
   ok(i instanceof WebAssembly.Instance, "got an instance");
   ok(i.exports.foo() === 42, "got 42");
 }
 
 function propertiesExist() {
+  if (!wasmIsSupported()) {
+    ok(!this["WebAssembly"], "If the device doesn't support, there will be no WebAssembly object");
+    SimpleTest.finish();
+    return;
+  }
+
   ok(WebAssembly, "WebAssembly object should exist");
   ok(WebAssembly.compile, "WebAssembly.compile function should exist");
-
-  if (!wasmIsSupported())
-    SimpleTest.finish();
-  else
-    runTest();
+  runTest();
 }
 
 function compileFail() {
   WebAssembly.compile().then(
     () => { ok(false, "should have failed"); runTest() }
   ).catch(
     err => { ok(err instanceof TypeError, "empty compile failed"); runTest() }
   );
--- a/dom/smil/test/test_smilConditionalProcessing.html
+++ b/dom/smil/test/test_smilConditionalProcessing.html
@@ -26,48 +26,46 @@ var svg = document.getElementById("svg")
 
 // Check initial state
 svg.setCurrentTime(50);
 is(a.getStartTime(), 0, "a has resolved start time at start");
 is(circle.cy.animVal.value, 100, "a is in effect at start");
 is(b.getStartTime(), 100, "b has resolved start time at start");
 
 // Add a failing conditional processing test
-a.setAttribute("requiredFeatures",
-               "http://www.w3.org/TR/SVGX/feature#SharksWithLasers");
+a.setAttribute("systemLanguage", "no-such-language");
 ok(hasUnresolvedStartTime(a),
    "a has unresolved start time with failing conditional processing test");
 is(circle.cy.animVal.value, 0,
    "a is not in effect with failing conditional processing test");
 ok(hasUnresolvedStartTime(b),
    "b has unresolved start time with failing conditional processing test on a");
 
 // Remove failing conditional processing test
-a.removeAttribute("requiredFeatures");
+a.removeAttribute("systemLanguage");
 is(a.getStartTime(), 0, "a has resolved start time after removing test");
 is(circle.cy.animVal.value, 100, "a is in effect after removing test");
 is(b.getStartTime(), 100, "b has resolved start time after removing test on a");
 
 // Add another failing conditional processing test
 // According to the spec, if a null string or empty string value is set for
-// the 'requiredFeatures' attribute, the attribute returns "false".
-a.setAttribute("requiredFeatures", "");
+// the 'systemLanguage' attribute, the attribute returns "false".
+a.setAttribute("systemLanguage", "");
 
 // Fast forward until |a| would have finished
 var endEventsReceived = 0;
 a.addEventListener("endEvent", function() { endEventsReceived++; });
 svg.setCurrentTime(150);
 is(endEventsReceived, 0,
    "a does not dispatch end events with failing condition processing test");
 is(circle.cx.animVal.value, 0,
    "b is not in effect with failing conditional processing test on a");
 
 // Make test pass
-a.setAttribute("requiredFeatures",
-               "http://www.w3.org/TR/SVG11/feature#Animation");
+a.setAttribute("systemLanguage", "en");
 is(circle.cx.animVal.value, 100,
    "b is in effect with passing conditional processing test on a");
 
 function hasUnresolvedStartTime(anim) {
   // getStartTime throws INVALID_STATE_ERR when there is no current interval
   try {
     anim.getStartTime();
     return false;
--- a/dom/svg/SVGTests.cpp
+++ b/dom/svg/SVGTests.cpp
@@ -107,31 +107,16 @@ SVGTests::GetBestLanguagePreferenceRank(
   return lowestRank;
 }
 
 const nsString * const SVGTests::kIgnoreSystemLanguage = (nsString *) 0x01;
 
 bool
 SVGTests::PassesConditionalProcessingTests(const nsString *aAcceptLangs) const
 {
-  // Required Features
-  if (mStringListAttributes[FEATURES].IsExplicitlySet()) {
-    if (mStringListAttributes[FEATURES].IsEmpty()) {
-      return false;
-    }
-    nsCOMPtr<nsIContent> content(
-      do_QueryInterface(const_cast<SVGTests*>(this)));
-
-    for (uint32_t i = 0; i < mStringListAttributes[FEATURES].Length(); i++) {
-      if (!nsSVGFeatures::HasFeature(content, mStringListAttributes[FEATURES][i])) {
-        return false;
-      }
-    }
-  }
-
   // Required Extensions
   //
   // The requiredExtensions  attribute defines a list of required language
   // extensions. Language extensions are capabilities within a user agent that
   // go beyond the feature set defined in the SVG specification.
   // Each extension is identified by a URI reference.
   // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
   if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) {
--- a/dom/svg/nsSVGFeatures.cpp
+++ b/dom/svg/nsSVGFeatures.cpp
@@ -16,38 +16,16 @@
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsNameSpaceManager.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /*static*/ bool
-nsSVGFeatures::HasFeature(nsISupports* aObject, const nsAString& aFeature)
-{
-  if (aFeature.EqualsLiteral("http://www.w3.org/TR/SVG11/feature#Script")) {
-    nsCOMPtr<nsIContent> content(do_QueryInterface(aObject));
-    if (content) {
-      nsIDocument* doc = content->GetUncomposedDoc();
-      if (doc && doc->IsResourceDoc()) {
-        // no scripting in SVG images or external resource documents
-        return false;
-      }
-    }
-    return Preferences::GetBool("javascript.enabled", false);
-  }
-#define SVG_SUPPORTED_FEATURE(str) if (aFeature.EqualsLiteral(str)) return true;
-#define SVG_UNSUPPORTED_FEATURE(str)
-#include "nsSVGFeaturesList.h"
-#undef SVG_SUPPORTED_FEATURE
-#undef SVG_UNSUPPORTED_FEATURE
-  return false;
-}
-
-/*static*/ bool
 nsSVGFeatures::HasExtension(const nsAString& aExtension, const bool aIsInChrome)
 {
 #define SVG_SUPPORTED_EXTENSION(str) if (aExtension.EqualsLiteral(str)) return true;
   SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
   nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
   if (aIsInChrome || !nameSpaceManager->mMathMLDisabled) {
     SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
   }
--- a/dom/svg/nsSVGFeatures.h
+++ b/dom/svg/nsSVGFeatures.h
@@ -8,27 +8,16 @@
 #define __NS_SVGFEATURES_H__
 
 #include "nsString.h"
 
 class nsSVGFeatures
 {
 public:
   /**
-   * Check whether we support the given feature string.
-   *
-   * @param aObject the object, which should support the feature,
-   *        for example nsIDOMNode or nsIDOMDOMImplementation
-   * @param aFeature one of the feature strings specified at
-   *    http://www.w3.org/TR/SVG11/feature.html
-   */
-  static bool
-  HasFeature(nsISupports* aObject, const nsAString& aFeature);
-
-  /**
    * Check whether we support the given extension string.
    *
    * @param aExtension the URI of an extension. Known extensions are
    *   "http://www.w3.org/1999/xhtml" and "http://www.w3.org/1998/Math/MathML"
    */
   static bool
   HasExtension(const nsAString& aExtension, const bool aIsInChrome);
 };
deleted file mode 100644
--- a/dom/svg/nsSVGFeaturesList.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//This file must not have include guards.
-
-// Features (SVG 1.1 style)
-
-// Static festures
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#CoreAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Structure")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ContainerAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ConditionalProcessing")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Image")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Style")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ViewportAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Shape")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Text")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#PaintAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#OpacityAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#GraphicsAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Marker")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ColorProfile")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Gradient")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Pattern")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Clip")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Mask")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Filter")
-
-// Basic features
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicStructure")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicText")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicClip")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicFilter")
-
-// Animation feature
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Animation")
-
-// Dynamic features
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#DocumentEventsAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#GraphicalEventsAttribute")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#AnimationEventsAttribute")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Cursor")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Hyperlinking")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#XlinkAttribute")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ExternalResourcesRequired")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#View")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Font")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#BasicFont")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Extensibility")
-
-// Feature groups (SVG 1.1 style)
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVG")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVGDOM")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVG-static")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVGDOM-static")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVG-animation")
-SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVGDOM-animation")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVG-dynamic")
-SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#SVGDOM-dynamic")
-
-// Features (SVG 1.0 style)
-SVG_UNSUPPORTED_FEATURE("org.w3c.svg")
-SVG_UNSUPPORTED_FEATURE("org.w3c.svg.all")
-SVG_UNSUPPORTED_FEATURE("org.w3c.svg.static")
-SVG_UNSUPPORTED_FEATURE("org.w3c.svg.animation")
-SVG_UNSUPPORTED_FEATURE("org.w3c.svg.dynamic")
-SVG_UNSUPPORTED_FEATURE("org.w3c.dom.svg")
-SVG_UNSUPPORTED_FEATURE("org.w3c.dom.svg.all")
-SVG_UNSUPPORTED_FEATURE("org.w3c.dom.svg.static")
-SVG_SUPPORTED_FEATURE("org.w3c.dom.svg.animation")
-SVG_UNSUPPORTED_FEATURE("org.w3c.dom.svg.dynamic")
--- a/dom/svg/test/mochitest.ini
+++ b/dom/svg/test/mochitest.ini
@@ -41,17 +41,16 @@ support-files =
 [test_bug872812.html]
 [test_getBBox-method.html]
 [test_dataTypes.html]
 [test_dataTypesModEvents.html]
 [test_fragments.html]
 [test_getCTM.html]
 [test_getElementById.xhtml]
 [test_getSubStringLength.xhtml]
-[test_hasFeature.xhtml]
 [test_lang.xhtml]
 skip-if = true # disabled-for-intermittent-failures--bug-701060
 [test_length.xhtml]
 [test_lengthParsing.html]
 [test_markerOrient.xhtml]
 [test_nonAnimStrings.xhtml]
 [test_non-scaling-stroke.html]
 [test_object-delayed-intrinsic-size.html]
deleted file mode 100644
--- a/dom/svg/test/test_hasFeature.xhtml
+++ /dev/null
@@ -1,159 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=519107
--->
-<head>
-  <title>Test for availability of svgElement::hasFeature</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=519107">Mozilla Bug 519107</a>
-<p id="display"></p>
-<div id="content" style="display: none;">
-  <svg id="svg" xmlns="http://www.w3.org/2000/svg">
-  </svg>
-</div>
-<pre id="test">
-<script type="application/javascript">
-<![CDATA[
-
-/** Test for Bug 519107 **/
-
-var features = [
-  // [feature, version, supported feature?]
-
-  // DOM Level 1
-  // http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-5CED94D7
-  ["HTML", "1.0", true],
-  ["XML",  "1.0", true],
-
-  // DOM Level 2
-  // http://www.w3.org/TR/DOM-Level-2-Core/introduction.html#ID-Conformance
-  ["Core", "2.0", true],
-  ["XML", "2.0", true],
-  ["HTML", "2.0", true],
-  ["XHTML", "2.0", true], // DOM Level 2 HTML
-  ["Views", "2.0", true],
-  ["StyleSheets", "2.0", true],
-  ["CSS", "2.0", true],
-  ["CSS2", "2.0", true],
-  ["Events", "2.0", true],
-  ["UIEvents", "2.0", true],
-  ["MouseEvents", "2.0", true],
-  ["MutationEvents", "2.0", true],
-  ["HTMLEvents", "2.0", true],
-  ["Range", "2.0", true],
-  ["Traversal", "2.0", true],
-
-  // DOM Level 3
-  // http://www.w3.org/TR/DOM-Level-3-Core/introduction.html#ID-Conformance
-  ["Core", "3.0", true],
-  ["XML", "3.0", true],
-  ["Events", "3.0", true],
-  ["UIEvents", "3.0", true],
-  ["MouseEvents", "3.0", true],
-  ["TextEvents", "3.0", true],
-  ["KeyboardEvents", "3.0", true],
-  ["MutationEvents", "3.0", true],
-  ["MutationNameEvents", "3.0", true],
-  ["HTMLEvents", "3.0", true],
-  ["LS", "3.0", true],
-  ["LS-Async", "3.0", true],
-  ["Validation", "3.0", true],
-  ["XPath", "3.0", "true"],
-
-  // current SVG feature string support status:
-  //   dom/svg/nsSVGFeaturesList.h
-  // SVG 1.1
-  // Static festures
-  ["http://www.w3.org/TR/SVG11/feature#CoreAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Structure", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#ContainerAttribute", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#ConditionalProcessing", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Image", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Style", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#ViewportAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Shape", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Text", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#PaintAttribute", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#OpacityAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#GraphicsAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Marker", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#ColorProfile", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#Gradient", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Pattern", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Clip", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Mask", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Filter", "1.1", false],
-
-  // Basic features
-  ["http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#BasicText", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#BasicClip", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#BasicFilter", "1.1", false],
-
-  // Animation feature
-  ["http://www.w3.org/TR/SVG11/feature#Animation", "1.1", true],
-
-  // Dynamic features
-  ["http://www.w3.org/TR/SVG11/feature#DocumentEventsAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#GraphicalEventsAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#AnimationEventsAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Cursor", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#Hyperlinking", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#XlinkAttribute", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#ExternalResourcesRequired", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#View", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#Script", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#Font", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#BasicFont", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#Extensibility", "1.1", true],
-
-  // Feature groups (SVG 1.1 style)
-  ["http://www.w3.org/TR/SVG11/feature#SVG", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVGDOM", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVG-static", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVGDOM-static", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVG-animation", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVGDOM-animation", "1.1", true],
-  ["http://www.w3.org/TR/SVG11/feature#SVG-dynamic", "1.1", false],
-  ["http://www.w3.org/TR/SVG11/feature#SVGDOM-dynamic", "1.1", false],
-
-  // Features (SVG 1.0 style)
-  ["org.w3c.svg", "1.0", false],
-  ["org.w3c.svg.all", "1.0", false],
-  ["org.w3c.svg.static", "1.0", false],
-  ["org.w3c.svg.animation", "1.0", false],
-  ["org.w3c.svg.dynamic", "1.0", false],
-  ["org.w3c.dom.svg", "1.0", false],
-  ["org.w3c.dom.svg.all", "1.0", false],
-  ["org.w3c.dom.svg.static", "1.0", false],
-  ["org.w3c.dom.svg.animation", "1.0", true],
-  ["org.w3c.dom.svg.dynamic", "1.0", false]
-];
-
-function testHasFeature() {
-  for (var [feature, version, accepted_result] of features) {
-    if (accepted_result) {
-      ok(document.implementation.hasFeature(feature, version), "hasFeature(" + feature + ", " + version + ") returned wrong value, Was it changed to unsupported feature?");
-    } else {
-      todo(document.implementation.hasFeature(feature, version), "hasFeature(" + feature + ", " + version + ") is unsupported feature string");
-    }
-  }
-}
-
-function main() {
-  testHasFeature();
-  SimpleTest.finish();
-}
-
-window.addEventListener("load", main, false);
-SimpleTest.waitForExplicitFinish();
-]]>
-</script>
-</pre>
-</body>
-</html>
--- a/dom/webidl/DOMImplementation.webidl
+++ b/dom/webidl/DOMImplementation.webidl
@@ -7,18 +7,17 @@
  * http://dom.spec.whatwg.org/#interface-domimplementation
  *
  * Copyright:
  * To the extent possible under law, the editors have waived all copyright and
  * related or neighboring rights to this work.
  */
 
 interface DOMImplementation {
-  boolean hasFeature(DOMString feature,
-                     [TreatNullAs=EmptyString] DOMString version);
+  boolean hasFeature();
 
   [Throws]
   DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId,
                                   DOMString systemId);
   [Throws]
   Document createDocument(DOMString? namespace,
                           [TreatNullAs=EmptyString] DOMString qualifiedName,
                           optional DocumentType? doctype = null);
--- a/dom/webidl/WorkerGlobalScope.webidl
+++ b/dom/webidl/WorkerGlobalScope.webidl
@@ -48,16 +48,15 @@ WorkerGlobalScope implements GlobalCrypt
 WorkerGlobalScope implements IDBEnvironment;
 WorkerGlobalScope implements ImageBitmapFactories;
 
 // Not implemented yet: bug 1072107.
 // WorkerGlobalScope implements FontFaceSource;
 
 // Mozilla extensions
 partial interface WorkerGlobalScope {
-  attribute EventHandler onclose;
 
   void dump(optional DOMString str);
 
   // XXXbz no spec for this yet, because the webperf WG is a bit dysfunctional
   [Constant, Cached]
   readonly attribute Performance performance;
 };
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -210,28 +210,16 @@ public:
   {
     AssertIsOnMainThread();
     sDefaultJSSettings.ApplyGCSetting(aKey, aValue);
   }
 
   void
   UpdateAllWorkerMemoryParameter(JSGCParamKey aKey, uint32_t aValue);
 
-  static uint32_t
-  GetContentCloseHandlerTimeoutSeconds()
-  {
-    return sDefaultJSSettings.content.maxScriptRuntime;
-  }
-
-  static uint32_t
-  GetChromeCloseHandlerTimeoutSeconds()
-  {
-    return sDefaultJSSettings.chrome.maxScriptRuntime;
-  }
-
 #ifdef JS_GC_ZEAL
   static void
   SetDefaultGCZeal(uint8_t aGCZeal, uint32_t aFrequency)
   {
     AssertIsOnMainThread();
     sDefaultJSSettings.gcZeal = aGCZeal;
     sDefaultJSSettings.gcZealFrequency = aFrequency;
   }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -598,74 +598,16 @@ private:
     if (rv.MaybeSetPendingException(aCx)) {
       return false;
     }
 
     return true;
   }
 };
 
-class CloseEventRunnable final : public WorkerRunnable
-{
-public:
-  explicit CloseEventRunnable(WorkerPrivate* aWorkerPrivate)
-  : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
-  { }
-
-private:
-  virtual bool
-  PreDispatch(WorkerPrivate* aWorkerPrivate) override
-  {
-    MOZ_CRASH("Don't call Dispatch() on CloseEventRunnable!");
-  }
-
-  virtual void
-  PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
-  {
-    MOZ_CRASH("Don't call Dispatch() on CloseEventRunnable!");
-  }
-
-  virtual bool
-  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
-  {
-    aWorkerPrivate->CloseHandlerStarted();
-
-    WorkerGlobalScope* globalScope = aWorkerPrivate->GlobalScope();
-
-    RefPtr<Event> event = NS_NewDOMEvent(globalScope, nullptr, nullptr);
-
-    event->InitEvent(NS_LITERAL_STRING("close"), false, false);
-    event->SetTrusted(true);
-
-    globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
-
-    return true;
-  }
-
-  nsresult Cancel() override
-  {
-    // We need to run regardless.
-    Run();
-    return WorkerRunnable::Cancel();
-  }
-
-  virtual void
-  PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
-          override
-  {
-    // Report errors.
-    WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
-
-    // Match the busy count increase from NotifyRunnable.
-    aWorkerPrivate->ModifyBusyCountFromWorker(false);
-
-    aWorkerPrivate->CloseHandlerFinished();
-  }
-};
-
 class MessageEventRunnable final : public WorkerRunnable
                                  , public StructuredCloneHolder
 {
   // This is only used for messages dispatched to a service worker.
   UniquePtr<ServiceWorkerClientInfo> mEventSource;
 
   RefPtr<PromiseNativeHandler> mHandler;
 
@@ -894,32 +836,38 @@ public:
                aStatus == Canceling || aStatus == Killing);
   }
 
 private:
   virtual bool
   PreDispatch(WorkerPrivate* aWorkerPrivate) override
   {
     aWorkerPrivate->AssertIsOnParentThread();
-    // Modify here, but not in PostRun! This busy count addition will be matched
-    // by the CloseEventRunnable.
     return aWorkerPrivate->ModifyBusyCount(true);
   }
 
   virtual void
   PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
   {
     aWorkerPrivate->AssertIsOnParentThread();
     if (!aDispatchResult) {
       // We couldn't dispatch to the worker, which means it's already dead.
       // Undo the busy count modification.
       aWorkerPrivate->ModifyBusyCount(false);
     }
   }
 
+  virtual void
+  PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
+          override
+  {
+    aWorkerPrivate->ModifyBusyCountFromWorker(false);
+    return;
+  }
+
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     bool ok = aWorkerPrivate->NotifyInternal(aCx, mStatus);
     MOZ_ASSERT(!JS_IsExceptionPending(aCx));
     return ok;
   }
 };
@@ -930,19 +878,17 @@ public:
   explicit CloseRunnable(WorkerPrivate* aWorkerPrivate)
   : WorkerControlRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
   { }
 
 private:
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
-    // This busy count will be matched by the CloseEventRunnable.
-    return aWorkerPrivate->ModifyBusyCount(true) &&
-           aWorkerPrivate->Close();
+    return aWorkerPrivate->Close();
   }
 };
 
 class FreezeRunnable final : public WorkerControlRunnable
 {
 public:
   explicit FreezeRunnable(WorkerPrivate* aWorkerPrivate)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
@@ -1351,121 +1297,16 @@ private:
 };
 
 void
 DummyCallback(nsITimer* aTimer, void* aClosure)
 {
   // Nothing!
 }
 
-class KillCloseEventRunnable final : public WorkerRunnable
-{
-  nsCOMPtr<nsITimer> mTimer;
-
-  class KillScriptRunnable final : public WorkerControlRunnable
-  {
-  public:
-    explicit KillScriptRunnable(WorkerPrivate* aWorkerPrivate)
-    : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
-    { }
-
-  private:
-    virtual bool
-    PreDispatch(WorkerPrivate* aWorkerPrivate) override
-    {
-      // Silence bad assertions, this is dispatched from the timer thread.
-      return true;
-    }
-
-    virtual void
-    PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
-    {
-      // Silence bad assertions, this is dispatched from the timer thread.
-    }
-
-    virtual bool
-    WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
-    {
-      // Kill running script.
-      return false;
-    }
-  };
-
-public:
-  explicit KillCloseEventRunnable(WorkerPrivate* aWorkerPrivate)
-  : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
-  { }
-
-  bool
-  SetTimeout(uint32_t aDelayMS)
-  {
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (!timer) {
-      return false;
-    }
-
-    RefPtr<KillScriptRunnable> runnable =
-      new KillScriptRunnable(mWorkerPrivate);
-
-    RefPtr<TimerThreadEventTarget> target =
-      new TimerThreadEventTarget(mWorkerPrivate, runnable);
-
-    if (NS_FAILED(timer->SetTarget(target))) {
-      return false;
-    }
-
-    if (NS_FAILED(timer->InitWithNamedFuncCallback(
-          DummyCallback, nullptr, aDelayMS, nsITimer::TYPE_ONE_SHOT,
-          "dom::workers::DummyCallback(1)"))) {
-      return false;
-    }
-
-    mTimer.swap(timer);
-    return true;
-  }
-
-private:
-  ~KillCloseEventRunnable()
-  {
-    if (mTimer) {
-      mTimer->Cancel();
-    }
-  }
-
-  virtual bool
-  PreDispatch(WorkerPrivate* aWorkerPrivate) override
-  {
-    MOZ_CRASH("Don't call Dispatch() on KillCloseEventRunnable!");
-  }
-
-  virtual void
-  PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
-  {
-    MOZ_CRASH("Don't call Dispatch() on KillCloseEventRunnable!");
-  }
-
-  virtual bool
-  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
-  {
-    if (mTimer) {
-      mTimer->Cancel();
-      mTimer = nullptr;
-    }
-
-    return true;
-  }
-
-  nsresult Cancel() override
-  {
-    // We need to run regardless.
-    Run();
-    return WorkerRunnable::Cancel();
-  }
-};
-
 class UpdateContextOptionsRunnable final : public WorkerControlRunnable
 {
   JS::ContextOptions mContextOptions;
 
 public:
   UpdateContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
                                const JS::ContextOptions& aContextOptions)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
@@ -4030,18 +3871,16 @@ WorkerPrivate::WorkerPrivate(WorkerPriva
   , mPRThread(nullptr)
   , mDebuggerEventLoopLevel(0)
   , mErrorHandlerRecursionCount(0)
   , mNextTimeoutId(1)
   , mStatus(Pending)
   , mFrozen(false)
   , mTimerRunning(false)
   , mRunningExpiredTimeouts(false)
-  , mCloseHandlerStarted(false)
-  , mCloseHandlerFinished(false)
   , mPendingEventQueueClearing(false)
   , mMemoryReporterRunning(false)
   , mBlockedForMemoryReporter(false)
   , mCancelAllPendingRunnables(false)
   , mPeriodicGCTimerRunning(false)
   , mIdleGCTimerRunning(false)
   , mWorkerScriptExecutedSuccessfully(false)
   , mOnLine(false)
@@ -4253,17 +4092,16 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
     // If the parent is going away give up now.
     Status parentStatus;
     {
       MutexAutoLock lock(aParent->mMutex);
       parentStatus = aParent->mStatus;
     }
 
     if (parentStatus > Running) {
-      NS_WARNING("Cannot create child workers from the close handler!");
       return NS_ERROR_FAILURE;
     }
 
     // StartAssignment() is used instead getter_AddRefs because, getter_AddRefs
     // does QI in debug build and, if this worker runs in a child process,
     // HttpChannelChild will crash because it's not thread-safe.
     rv = ChannelFromScriptURLWorkerThread(aCx, aParent, aScriptURL,
                                           loadInfo.mChannel.StartAssignment());
@@ -4531,22 +4369,23 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
 
   EnableMemoryReporter();
 
   InitializeGCTimers();
 
   Maybe<JSAutoCompartment> workerCompartment;
 
   for (;;) {
-    Status currentStatus;
+    Status currentStatus, previousStatus;
     bool debuggerRunnablesPending = false;
     bool normalRunnablesPending = false;
 
     {
       MutexAutoLock lock(mMutex);
+      previousStatus = mStatus;
 
       while (mControlQueue.IsEmpty() &&
              !(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
              !(normalRunnablesPending = NS_HasPendingEvents(mThread))) {
         WaitForWorkerEvents();
       }
 
       auto result = ProcessAllControlRunnablesLocked();
@@ -4557,20 +4396,21 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
         // The state of the world may have changed, recheck it.
         normalRunnablesPending = NS_HasPendingEvents(mThread);
         // The debugger queue doesn't get cleared, so we can ignore that.
       }
 
       currentStatus = mStatus;
     }
 
-    // If the close handler has finished and all holders are done then we can
-    // kill this thread.
+    // if all holders are done then we can kill this thread.
     if (currentStatus != Running && !HasActiveHolders()) {
-      if (mCloseHandlerFinished && currentStatus != Killing) {
+
+      // If we just changed status, we must schedule the current runnables.
+      if (previousStatus != Running && currentStatus != Killing) {
         NotifyInternal(aCx, Killing);
         MOZ_ASSERT(!JS_IsExceptionPending(aCx));
 
 #ifdef DEBUG
         {
           MutexAutoLock lock(mMutex);
           currentStatus = mStatus;
         }
@@ -4641,20 +4481,18 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
         WorkerDebuggerGlobalScope* globalScope = DebuggerGlobalScope();
         MOZ_ASSERT(globalScope);
 
         // Now *might* be a good time to GC. Let the JS engine make the decision.
         JSAutoCompartment ac(aCx, globalScope->GetGlobalJSObject());
         JS_MaybeGC(aCx);
       }
     } else if (normalRunnablesPending) {
-      MOZ_ASSERT(NS_HasPendingEvents(mThread));
-
       // Process a single runnable from the main queue.
-      MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(mThread, false));
+      NS_ProcessNextEvent(mThread, false);
 
       normalRunnablesPending = NS_HasPendingEvents(mThread);
       if (normalRunnablesPending && GlobalScope()) {
         // Now *might* be a good time to GC. Let the JS engine make the decision.
         JSAutoCompartment ac(aCx, GlobalScope()->GetGlobalJSObject());
         JS_MaybeGC(aCx);
       }
     }
@@ -4846,17 +4684,17 @@ WorkerPrivate::InterruptCallback(JSConte
     }
 
     while ((mayContinue = MayContinueRunning())) {
       MutexAutoLock lock(mMutex);
       if (!mControlQueue.IsEmpty()) {
         break;
       }
 
-      WaitForWorkerEvents(PR_MillisecondsToInterval(RemainingRunTimeMS()));
+      WaitForWorkerEvents(PR_MillisecondsToInterval(UINT32_MAX));
     }
   }
 
   if (!mayContinue) {
     // We want only uncatchable exceptions here.
     NS_ASSERTION(!JS_IsExceptionPending(aCx),
                  "Should not have an exception set here!");
     return false;
@@ -5148,27 +4986,16 @@ WorkerPrivate::ClearDebuggerEventQueue()
   while (!mDebuggerQueue.IsEmpty()) {
     WorkerRunnable* runnable;
     mDebuggerQueue.Pop(runnable);
     // It should be ok to simply release the runnable, without running it.
     runnable->Release();
   }
 }
 
-uint32_t
-WorkerPrivate::RemainingRunTimeMS() const
-{
-  if (mKillTime.IsNull()) {
-    return UINT32_MAX;
-  }
-  TimeDuration runtime = mKillTime - TimeStamp::Now();
-  double ms = runtime > TimeDuration(0) ? runtime.ToMilliseconds() : 0;
-  return ms > double(UINT32_MAX) ? UINT32_MAX : uint32_t(ms);
-}
-
 bool
 WorkerPrivate::FreezeInternal()
 {
   AssertIsOnWorkerThread();
 
   NS_ASSERTION(!mFrozen, "Already frozen!");
 
   mFrozen = true;
@@ -5797,121 +5624,57 @@ WorkerPrivate::NotifyInternal(JSContext*
     // mutex must be acquired *after* mCrossThreadDispatcher's mutex when
     // they're both held.
     mCrossThreadDispatcher->Forget();
     mCrossThreadDispatcher = nullptr;
   }
 
   MOZ_ASSERT(previousStatus != Pending);
 
-  MOZ_ASSERT(previousStatus >= Canceling || mKillTime.IsNull());
-
   // Let all our holders know the new status.
   NotifyHolders(aCx, aStatus);
   MOZ_ASSERT(!JS_IsExceptionPending(aCx));
 
   // If this is the first time our status has changed then we need to clear the
   // main event queue.
   if (previousStatus == Running) {
     // NB: If we're in a sync loop, we can't clear the queue immediately,
     // because this is the wrong queue. So we have to defer it until later.
     if (!mSyncLoopStack.IsEmpty()) {
       mPendingEventQueueClearing = true;
     } else {
       ClearMainEventQueue(WorkerRan);
     }
   }
 
-  // If we've run the close handler, we don't need to do anything else.
-  if (mCloseHandlerFinished) {
-    return true;
-  }
-
   // If the worker script never ran, or failed to compile, we don't need to do
-  // anything else, except pretend that we ran the close handler.
+  // anything else.
   if (!GlobalScope()) {
-    mCloseHandlerStarted = true;
-    mCloseHandlerFinished = true;
     return true;
   }
 
-  // If this is the first time our status has changed we also need to schedule
-  // the close handler unless we're being shut down.
-  if (previousStatus == Running && aStatus != Killing) {
-    MOZ_ASSERT(!mCloseHandlerStarted && !mCloseHandlerFinished);
-
-    RefPtr<CloseEventRunnable> closeRunnable = new CloseEventRunnable(this);
-    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(closeRunnable));
-  }
-
   if (aStatus == Closing) {
     // Notify parent to stop sending us messages and balance our busy count.
     RefPtr<CloseRunnable> runnable = new CloseRunnable(this);
     if (!runnable->Dispatch()) {
       return false;
     }
 
     // Don't abort the script.
     return true;
   }
 
-  if (aStatus == Terminating) {
-    // Only abort the script if we're not yet running the close handler.
-    return mCloseHandlerStarted;
-  }
-
-  if (aStatus == Canceling) {
-    // We need to enforce a timeout on the close handler.
-    MOZ_ASSERT(previousStatus >= Running && previousStatus <= Terminating);
-
-    uint32_t killSeconds = IsChromeWorker() ?
-      RuntimeService::GetChromeCloseHandlerTimeoutSeconds() :
-      RuntimeService::GetContentCloseHandlerTimeoutSeconds();
-
-    if (killSeconds) {
-      mKillTime = TimeStamp::Now() + TimeDuration::FromSeconds(killSeconds);
-
-      if (!mCloseHandlerFinished && !ScheduleKillCloseEventRunnable()) {
-        return false;
-      }
-    }
-
-    // Only abort the script if we're not yet running the close handler.
-    return mCloseHandlerStarted;
-  }
-
-  MOZ_ASSERT(aStatus == Killing);
-
-  mKillTime = TimeStamp::Now();
-
-  if (mCloseHandlerStarted && !mCloseHandlerFinished) {
-    ScheduleKillCloseEventRunnable();
-  }
+  MOZ_ASSERT(aStatus == Terminating ||
+             aStatus == Canceling ||
+             aStatus == Killing);
 
   // Always abort the script.
   return false;
 }
 
-bool
-WorkerPrivate::ScheduleKillCloseEventRunnable()
-{
-  AssertIsOnWorkerThread();
-  MOZ_ASSERT(!mKillTime.IsNull());
-
-  RefPtr<KillCloseEventRunnable> killCloseEventRunnable =
-    new KillCloseEventRunnable(this);
-  if (!killCloseEventRunnable->SetTimeout(RemainingRunTimeMS())) {
-    return false;
-  }
-
-  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(killCloseEventRunnable));
-
-  return true;
-}
-
 void
 WorkerPrivate::ReportError(JSContext* aCx, const char* aFallbackMessage,
                            JSErrorReport* aReport)
 {
   AssertIsOnWorkerThread();
 
   if (!MayContinueRunning() || mErrorHandlerRecursionCount == 2) {
     return;
@@ -5960,19 +5723,18 @@ WorkerPrivate::ReportError(JSContext* aC
       nsDependentCString truncatedFallbackMessage(aFallbackMessage, 1024);
       AppendUTF8toUTF16(truncatedFallbackMessage, message);
     }
   }
 
   mErrorHandlerRecursionCount++;
 
   // Don't want to run the scope's error handler if this is a recursive error or
-  // if there was an error in the close handler or if we ran out of memory.
+  // if we ran out of memory.
   bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
-                     !mCloseHandlerStarted &&
                      errorNumber != JSMSG_OUT_OF_MEMORY &&
                      JS::CurrentGlobalOrNull(aCx);
 
   ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
                                    filename, line, lineNumber,
                                    columnNumber, flags, errorNumber, exnType,
                                    mutedError, 0, exn);
 
@@ -6003,23 +5765,16 @@ WorkerPrivate::SetTimeout(JSContext* aCx
   const int32_t timerId = mNextTimeoutId++;
 
   Status currentStatus;
   {
     MutexAutoLock lock(mMutex);
     currentStatus = mStatus;
   }
 
-  // It's a script bug if setTimeout/setInterval are called from a close handler
-  // so throw an exception.
-  if (currentStatus == Closing) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return 0;
-  }
-
   // If the worker is trying to call setTimeout/setInterval and the parent
   // thread has initiated the close process then just silently fail.
   if (currentStatus >= Closing) {
     aRv.Throw(NS_ERROR_FAILURE);
     return 0;
   }
 
   nsAutoPtr<TimeoutInfo> newInfo(new TimeoutInfo());
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -945,18 +945,16 @@ class WorkerPrivate : public WorkerPriva
   JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
   TimeStamp mKillTime;
   uint32_t mErrorHandlerRecursionCount;
   uint32_t mNextTimeoutId;
   Status mStatus;
   bool mFrozen;
   bool mTimerRunning;
   bool mRunningExpiredTimeouts;
-  bool mCloseHandlerStarted;
-  bool mCloseHandlerFinished;
   bool mPendingEventQueueClearing;
   bool mMemoryReporterRunning;
   bool mBlockedForMemoryReporter;
   bool mCancelAllPendingRunnables;
   bool mPeriodicGCTimerRunning;
   bool mIdleGCTimerRunning;
   bool mWorkerScriptExecutedSuccessfully;
   bool mPreferences[WORKERPREF_COUNT];
@@ -1151,30 +1149,16 @@ public:
 
   bool
   RunExpiredTimeouts(JSContext* aCx);
 
   bool
   RescheduleTimeoutTimer(JSContext* aCx);
 
   void
-  CloseHandlerStarted()
-  {
-    AssertIsOnWorkerThread();
-    mCloseHandlerStarted = true;
-  }
-
-  void
-  CloseHandlerFinished()
-  {
-    AssertIsOnWorkerThread();
-    mCloseHandlerFinished = true;
-  }
-
-  void
   UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions);
 
   void
   UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
 
   void
   UpdatePreferenceInternal(WorkerPreference aPref, bool aValue);
 
@@ -1364,34 +1348,26 @@ private:
     AssertIsOnWorkerThread();
 
     Status status;
     {
       MutexAutoLock lock(mMutex);
       status = mStatus;
     }
 
-    if (status >= Killing) {
-      return false;
-    }
-    if (status >= Running) {
-      return mKillTime.IsNull() || RemainingRunTimeMS() > 0;
+    if (status < Terminating) {
+      return true;
     }
-    return true;
+
+    return false;
   }
 
-  uint32_t
-  RemainingRunTimeMS() const;
-
   void
   CancelAllTimeouts();
 
-  bool
-  ScheduleKillCloseEventRunnable();
-
   enum class ProcessAllControlRunnablesResult
   {
     // We did not process anything.
     Nothing,
     // We did process something, states may have changed, but we can keep
     // executing script.
     MayContinue,
     // We did process something, and should not continue executing script.
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -143,17 +143,16 @@ public:
 
   void
   Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const;
   void
   Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const;
 
   IMPL_EVENT_HANDLER(online)
   IMPL_EVENT_HANDLER(offline)
-  IMPL_EVENT_HANDLER(close)
 
   void
   Dump(const Optional<nsAString>& aString) const;
 
   Performance* GetPerformance();
 
   already_AddRefed<Promise>
   Fetch(const RequestOrUSVString& aInput, const RequestInit& aInit, ErrorResult& aRv);
deleted file mode 100644
--- a/dom/workers/test/closeOnGC_server.sjs
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-function handleRequest(request, response)
-{
-  response.setHeader("Content-Type", "text/plain", false);
-  response.setHeader("Cache-Control", "no-cache", false);
-
-  if (request.method == "POST") {
-    setState("seenPost" + request.queryString, "1");
-    return;
-  }
-
-  if (request.method == "GET") {
-    if (getState("seenPost" + request.queryString) == "1") {
-      response.write("closed");
-    }
-    return;
-  }
-
-  response.setStatusLine(request.httpVersion, 404, "Not found");
-}
deleted file mode 100644
--- a/dom/workers/test/closeOnGC_worker.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-onclose = function() {
-  var xhr = new XMLHttpRequest();
-  xhr.open("POST", "closeOnGC_server.sjs" + location.search, false);
-  xhr.send();
-};
-
-postMessage("ready");
deleted file mode 100644
--- a/dom/workers/test/close_worker.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-onclose = function() {
-  postMessage("closed");
-  // Try to open a new worker.
-  try {
-    var worker = new Worker("close_worker.js");
-    throw new Error("We shouldn't get here!");
-  } catch (e) {
-    // pass
-  }
-};
-
-setTimeout(function () {
-  setTimeout(function () {
-    throw new Error("I should never run!");
-  }, 1000);
-  close();
-}, 1000);
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -6,19 +6,16 @@ support-files =
   bug1014466_data1.txt
   bug1014466_data2.txt
   bug1014466_worker.js
   bug1020226_worker.js
   bug1020226_frame.html
   bug998474_worker.js
   bug1063538_worker.js
   clearTimeouts_worker.js
-  closeOnGC_server.sjs
-  closeOnGC_worker.js
-  close_worker.js
   content_worker.js
   console_worker.js
   consoleReplaceable_worker.js
   csp_worker.js
   csp_worker.js^headers^
   404_server.sjs
   errorPropagation_iframe.html
   errorPropagation_worker.js
@@ -141,18 +138,16 @@ support-files =
 [test_bug1062920.html]
 [test_bug1063538.html]
 [test_bug1104064.html]
 [test_bug1132395.html]
 skip-if = true # bug 1176225
 [test_bug1132924.html]
 [test_chromeWorker.html]
 [test_clearTimeouts.html]
-[test_close.html]
-[test_closeOnGC.html]
 [test_console.html]
 [test_consoleAndBlobs.html]
 [test_consoleReplaceable.html]
 [test_consoleSharedWorkers.html]
 [test_contentWorker.html]
 [test_csp.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_dataURLWorker.html]
--- a/dom/workers/test/terminate_worker.js
+++ b/dom/workers/test/terminate_worker.js
@@ -1,13 +1,9 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
-onclose = function() {
-  postMessage("Closed!");
-}
-
 onmessage = function(event) {
   throw "No messages should reach me!";
 }
 
 setInterval(function() { postMessage("Still alive!"); }, 100);
deleted file mode 100644
--- a/dom/workers/test/test_close.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for DOM Worker Threads</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-  var worker = new Worker("close_worker.js");
-  worker.onmessage = function(event) {
-    is(event.data, "closed");
-    SimpleTest.finish();
-  }
-
-  SimpleTest.waitForExplicitFinish();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/workers/test/test_closeOnGC.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for DOM Worker Threads</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-  var count = 0;
-
-  function testWorker(queryString) {
-    ++count;
-    var worker = new Worker("closeOnGC_worker.js?" + queryString);
-    worker.onmessage = function(event) {
-      is(event.data, "ready");
-      worker = null;
-    }
-
-    var interval = setInterval(function() {
-      var xhr = new XMLHttpRequest();
-      xhr.open("GET", "closeOnGC_server.sjs?" + queryString, false);
-      xhr.send();
-      if (xhr.responseText != "closed") {
-        SpecialPowers.gc();
-        return;
-      }
-      clearInterval(interval);
-      ok(true, "xhr correctly closed");
-      if (--count == 0) {
-        SimpleTest.finish();
-      }
-    }, 500);
-
-    return worker;
-  }
-
-  testWorker("white");
-  var worker = testWorker("gray");
-  worker.onerror = function() {};
-  worker.onerror.foo = worker;
-  worker = null;
-
-  SimpleTest.waitForExplicitFinish();
-
-</script>
-</pre>
-</body>
-</html>
--- a/dom/workers/test/test_terminate.html
+++ b/dom/workers/test/test_terminate.html
@@ -25,17 +25,17 @@ Tests of DOM Worker terminate feature
   var intervalCount = 0;
 
   var interval;
 
   var worker;
 
   function messageListener(event) {
     is(event.data, "Still alive!", "Correct message!");
-    if (messageCount++ == 20) {
+    if (++messageCount == 20) {
       ok(worker.onmessage === messageListener,
          "Correct listener before terminate");
 
       worker.terminate();
 
       var exception = false;
       try {
         worker.addEventListener("message", messageListener, false);
@@ -77,17 +77,17 @@ Tests of DOM Worker terminate feature
 
       worker.onmessage = function(event) { }
 
       interval = setInterval(testCount, 1000);
     }
   }
 
   function testCount() {
-    is(messageCount, 21, "Received another message after terminated!");
+    is(messageCount, 20, "Received another message after terminated!");
     if (intervalCount++ == 5) {
       clearInterval(interval);
       SimpleTest.finish();
     }
   }
 
   worker = new Worker("terminate_worker.js");
   worker.onmessage = messageListener;
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -18,16 +18,17 @@
 #include "nsContentUtils.h"
 #include "nsContainerFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
+#include "nsIDOMWindowUtils.h"
 #include "nsRefreshDriver.h"
 #include "nsString.h"
 #include "nsView.h"
 #include "Layers.h"
 
 #define APZCCH_LOG(...)
 // #define APZCCH_LOG(...) printf_stderr("APZCCH: " __VA_ARGS__)
 
@@ -509,19 +510,19 @@ APZCCallbackHelper::DispatchMouseEvent(c
                                        int32_t aModifiers,
                                        bool aIgnoreRootScrollFrame,
                                        unsigned short aInputSourceArg)
 {
   NS_ENSURE_TRUE(aPresShell, true);
 
   bool defaultPrevented = false;
   nsContentUtils::SendMouseEvent(aPresShell, aType, aPoint.x, aPoint.y,
-      aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame, 0,
-      aInputSourceArg, false, &defaultPrevented, false,
-      /* aIsWidgetEventSynthesized = */ false);
+      aButton, nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED, aClickCount,
+      aModifiers, aIgnoreRootScrollFrame, 0, aInputSourceArg, false,
+      &defaultPrevented, false, /* aIsWidgetEventSynthesized = */ false);
   return defaultPrevented;
 }
 
 
 void
 APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,
                                        Modifiers aModifiers,
                                        nsIWidget* aWidget)
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -216,20 +216,26 @@ TextureClientRecycleAllocator::Allocate(
 {
   return TextureClient::CreateForDrawing(mSurfaceAllocator, aFormat, aSize, aSelector,
                                          aTextureFlags, aAllocFlags);
 }
 
 void
 TextureClientRecycleAllocator::ShrinkToMinimumSize()
 {
-  MutexAutoLock lock(mLock);
-  while (!mPooledClients.empty()) {
-    mPooledClients.pop();
+  RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
+  std::map<TextureClient*, RefPtr<TextureClientHolder> > inUseClients;
+  {
+    MutexAutoLock lock(mLock);
+    while (!mPooledClients.empty()) {
+      mPooledClients.pop();
+    }
+    mInUseClients.swap(inUseClients);
   }
+  inUseClients.clear();
 }
 
 void
 TextureClientRecycleAllocator::Destroy()
 {
   MutexAutoLock lock(mLock);
   while (!mPooledClients.empty()) {
     mPooledClients.pop();
--- a/js/src/asmjs/WasmJS.cpp
+++ b/js/src/asmjs/WasmJS.cpp
@@ -51,30 +51,16 @@ wasm::HasCompilerSupport(ExclusiveContex
 
 #if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
     return false;
 #else
     return true;
 #endif
 }
 
-static bool
-CheckCompilerSupport(JSContext* cx)
-{
-    if (!HasCompilerSupport(cx)) {
-#ifdef JS_MORE_DETERMINISTIC
-        fprintf(stderr, "WebAssembly is not supported on the current device.\n");
-#endif
-        JS_ReportError(cx, "WebAssembly is not supported on the current device.");
-        return false;
-    }
-
-    return true;
-}
-
 // ============================================================================
 // (Temporary) Wasm class and static methods
 
 static bool
 Throw(JSContext* cx, const char* str)
 {
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_FAIL, str);
     return false;
@@ -218,19 +204,16 @@ DescribeScriptedCaller(JSContext* cx, Sc
 
     return true;
 }
 
 bool
 wasm::Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj,
            MutableHandleWasmInstanceObject instanceObj)
 {
-    if (!CheckCompilerSupport(cx))
-        return false;
-
     MutableBytes bytecode = cx->new_<ShareableBytes>();
     if (!bytecode)
         return false;
 
     if (!bytecode->append((uint8_t*)code->viewDataEither().unwrap(), code->byteLength())) {
         ReportOutOfMemory(cx);
         return false;
     }
@@ -313,16 +296,17 @@ static const JSFunctionSpec wasm_static_
 const Class js::WasmClass = {
     js_Wasm_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_Wasm)
 };
 
 JSObject*
 js::InitWasmClass(JSContext* cx, HandleObject global)
 {
+    MOZ_RELEASE_ASSERT(HasCompilerSupport(cx));
     MOZ_ASSERT(cx->options().wasm());
 
     RootedObject proto(cx, global->as<GlobalObject>().getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
 
     RootedObject Wasm(cx, NewObjectWithGivenProto(cx, &WasmClass, proto, SingletonObject));
     if (!Wasm)
@@ -424,18 +408,17 @@ GetCompileArgs(JSContext* cx, CallArgs c
     ScriptedCaller scriptedCaller;
     if (!DescribeScriptedCaller(cx, &scriptedCaller))
         return false;
 
     if (!compileArgs->initFromContext(cx, Move(scriptedCaller)))
         return false;
 
     compileArgs->assumptions.newFormat = true;
-
-    return CheckCompilerSupport(cx);
+    return true;
 }
 
 /* static */ bool
 WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs callArgs = CallArgsFromVp(argc, vp);
 
     if (!ThrowIfNotConstructing(cx, callArgs, "Module"))
@@ -1332,16 +1315,17 @@ InitConstructor(JSContext* cx, HandleObj
     RootedId id(cx, AtomToId(className));
     RootedValue ctorValue(cx, ObjectValue(*ctor));
     return DefineProperty(cx, wasm, id, ctorValue, nullptr, nullptr, 0);
 }
 
 JSObject*
 js::InitWebAssemblyClass(JSContext* cx, HandleObject obj)
 {
+    MOZ_RELEASE_ASSERT(HasCompilerSupport(cx));
     MOZ_ASSERT(cx->options().wasm());
 
     Handle<GlobalObject*> global = obj.as<GlobalObject>();
     MOZ_ASSERT(!global->isStandardClassResolved(JSProto_WebAssembly));
 
     RootedObject proto(cx, global->getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -128,40 +128,40 @@ static void
 uenum_close(UEnumeration* en)
 {
     MOZ_CRASH("uenum_close: Intl API disabled");
 }
 
 struct UCollator;
 
 enum UColAttribute {
-     UCOL_ALTERNATE_HANDLING,
-     UCOL_CASE_FIRST,
-     UCOL_CASE_LEVEL,
-     UCOL_NORMALIZATION_MODE,
-     UCOL_STRENGTH,
-     UCOL_NUMERIC_COLLATION,
+    UCOL_ALTERNATE_HANDLING,
+    UCOL_CASE_FIRST,
+    UCOL_CASE_LEVEL,
+    UCOL_NORMALIZATION_MODE,
+    UCOL_STRENGTH,
+    UCOL_NUMERIC_COLLATION,
 };
 
 enum UColAttributeValue {
-  UCOL_DEFAULT = -1,
-  UCOL_PRIMARY = 0,
-  UCOL_SECONDARY = 1,
-  UCOL_TERTIARY = 2,
-  UCOL_OFF = 16,
-  UCOL_ON = 17,
-  UCOL_SHIFTED = 20,
-  UCOL_LOWER_FIRST = 24,
-  UCOL_UPPER_FIRST = 25,
+    UCOL_DEFAULT = -1,
+    UCOL_PRIMARY = 0,
+    UCOL_SECONDARY = 1,
+    UCOL_TERTIARY = 2,
+    UCOL_OFF = 16,
+    UCOL_ON = 17,
+    UCOL_SHIFTED = 20,
+    UCOL_LOWER_FIRST = 24,
+    UCOL_UPPER_FIRST = 25,
 };
 
 enum UCollationResult {
-  UCOL_EQUAL = 0,
-  UCOL_GREATER = 1,
-  UCOL_LESS = -1
+    UCOL_EQUAL = 0,
+    UCOL_GREATER = 1,
+    UCOL_LESS = -1
 };
 
 static int32_t
 ucol_countAvailable()
 {
     MOZ_CRASH("ucol_countAvailable: Intl API disabled");
 }
 
@@ -216,28 +216,28 @@ enum UNumberFormatStyle {
     UNUM_CURRENCY_PLURAL,
 };
 
 enum UNumberFormatRoundingMode {
     UNUM_ROUND_HALFUP,
 };
 
 enum UNumberFormatAttribute {
-  UNUM_GROUPING_USED,
-  UNUM_MIN_INTEGER_DIGITS,
-  UNUM_MAX_FRACTION_DIGITS,
-  UNUM_MIN_FRACTION_DIGITS,
-  UNUM_ROUNDING_MODE,
-  UNUM_SIGNIFICANT_DIGITS_USED,
-  UNUM_MIN_SIGNIFICANT_DIGITS,
-  UNUM_MAX_SIGNIFICANT_DIGITS,
+    UNUM_GROUPING_USED,
+    UNUM_MIN_INTEGER_DIGITS,
+    UNUM_MAX_FRACTION_DIGITS,
+    UNUM_MIN_FRACTION_DIGITS,
+    UNUM_ROUNDING_MODE,
+    UNUM_SIGNIFICANT_DIGITS_USED,
+    UNUM_MIN_SIGNIFICANT_DIGITS,
+    UNUM_MAX_SIGNIFICANT_DIGITS,
 };
 
 enum UNumberFormatTextAttribute {
-  UNUM_CURRENCY_CODE,
+    UNUM_CURRENCY_CODE,
 };
 
 static int32_t
 unum_countAvailable()
 {
     MOZ_CRASH("unum_countAvailable: Intl API disabled");
 }
 
@@ -308,19 +308,41 @@ const char*
 NumberingSystem::getName()
 {
     MOZ_CRASH("NumberingSystem::getName: Intl API disabled");
 }
 
 typedef void* UCalendar;
 
 enum UCalendarType {
-  UCAL_TRADITIONAL,
-  UCAL_DEFAULT = UCAL_TRADITIONAL,
-  UCAL_GREGORIAN
+    UCAL_TRADITIONAL,
+    UCAL_DEFAULT = UCAL_TRADITIONAL,
+    UCAL_GREGORIAN
+};
+
+enum UCalendarAttribute {
+    UCAL_FIRST_DAY_OF_WEEK,
+    UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
+};
+
+enum UCalendarDaysOfWeek {
+    UCAL_SUNDAY,
+    UCAL_MONDAY,
+    UCAL_TUESDAY,
+    UCAL_WEDNESDAY,
+    UCAL_THURSDAY,
+    UCAL_FRIDAY,
+    UCAL_SATURDAY
+};
+
+enum UCalendarWeekdayType {
+    UCAL_WEEKDAY,
+    UCAL_WEEKEND,
+    UCAL_WEEKEND_ONSET,
+    UCAL_WEEKEND_CEASE
 };
 
 static UCalendar*
 ucal_open(const UChar* zoneID, int32_t len, const char* locale,
           UCalendarType type, UErrorCode* status)
 {
     MOZ_CRASH("ucal_open: Intl API disabled");
 }
@@ -339,16 +361,29 @@ ucal_getKeywordValuesForLocale(const cha
 }
 
 static void
 ucal_close(UCalendar* cal)
 {
     MOZ_CRASH("ucal_close: Intl API disabled");
 }
 
+static UCalendarWeekdayType
+ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status)
+{
+    MOZ_CRASH("ucal_getDayOfWeekType: Intl API disabled");
+}
+
+static int32_t
+ucal_getAttribute(const UCalendar*    cal,
+                  UCalendarAttribute  attr)
+{
+    MOZ_CRASH("ucal_getAttribute: Intl API disabled");
+}
+
 typedef void* UDateTimePatternGenerator;
 
 static UDateTimePatternGenerator*
 udatpg_open(const char* locale, UErrorCode* pErrorCode)
 {
     MOZ_CRASH("udatpg_open: Intl API disabled");
 }
 
@@ -365,53 +400,53 @@ udatpg_close(UDateTimePatternGenerator* 
 {
     MOZ_CRASH("udatpg_close: Intl API disabled");
 }
 
 typedef void* UCalendar;
 typedef void* UDateFormat;
 
 enum UDateFormatField {
-  UDAT_ERA_FIELD = 0,
-  UDAT_YEAR_FIELD = 1,
-  UDAT_MONTH_FIELD = 2,
-  UDAT_DATE_FIELD = 3,
-  UDAT_HOUR_OF_DAY1_FIELD = 4,
-  UDAT_HOUR_OF_DAY0_FIELD = 5,
-  UDAT_MINUTE_FIELD = 6,
-  UDAT_SECOND_FIELD = 7,
-  UDAT_FRACTIONAL_SECOND_FIELD = 8,
-  UDAT_DAY_OF_WEEK_FIELD = 9,
-  UDAT_DAY_OF_YEAR_FIELD = 10,
-  UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11,
-  UDAT_WEEK_OF_YEAR_FIELD = 12,
-  UDAT_WEEK_OF_MONTH_FIELD = 13,
-  UDAT_AM_PM_FIELD = 14,
-  UDAT_HOUR1_FIELD = 15,
-  UDAT_HOUR0_FIELD = 16,
-  UDAT_TIMEZONE_FIELD = 17,
-  UDAT_YEAR_WOY_FIELD = 18,
-  UDAT_DOW_LOCAL_FIELD = 19,
-  UDAT_EXTENDED_YEAR_FIELD = 20,
-  UDAT_JULIAN_DAY_FIELD = 21,
-  UDAT_MILLISECONDS_IN_DAY_FIELD = 22,
-  UDAT_TIMEZONE_RFC_FIELD = 23,
-  UDAT_TIMEZONE_GENERIC_FIELD = 24,
-  UDAT_STANDALONE_DAY_FIELD = 25,
-  UDAT_STANDALONE_MONTH_FIELD = 26,
-  UDAT_QUARTER_FIELD = 27,
-  UDAT_STANDALONE_QUARTER_FIELD = 28,
-  UDAT_TIMEZONE_SPECIAL_FIELD = 29,
-  UDAT_YEAR_NAME_FIELD = 30,
-  UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31,
-  UDAT_TIMEZONE_ISO_FIELD = 32,
-  UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33,
-  UDAT_RELATED_YEAR_FIELD = 34,
-  UDAT_TIME_SEPARATOR_FIELD = 35,
-  UDAT_FIELD_COUNT = 36 
+    UDAT_ERA_FIELD = 0,
+    UDAT_YEAR_FIELD = 1,
+    UDAT_MONTH_FIELD = 2,
+    UDAT_DATE_FIELD = 3,
+    UDAT_HOUR_OF_DAY1_FIELD = 4,
+    UDAT_HOUR_OF_DAY0_FIELD = 5,
+    UDAT_MINUTE_FIELD = 6,
+    UDAT_SECOND_FIELD = 7,
+    UDAT_FRACTIONAL_SECOND_FIELD = 8,
+    UDAT_DAY_OF_WEEK_FIELD = 9,
+    UDAT_DAY_OF_YEAR_FIELD = 10,
+    UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11,
+    UDAT_WEEK_OF_YEAR_FIELD = 12,
+    UDAT_WEEK_OF_MONTH_FIELD = 13,
+    UDAT_AM_PM_FIELD = 14,
+    UDAT_HOUR1_FIELD = 15,
+    UDAT_HOUR0_FIELD = 16,
+    UDAT_TIMEZONE_FIELD = 17,
+    UDAT_YEAR_WOY_FIELD = 18,
+    UDAT_DOW_LOCAL_FIELD = 19,
+    UDAT_EXTENDED_YEAR_FIELD = 20,
+    UDAT_JULIAN_DAY_FIELD = 21,
+    UDAT_MILLISECONDS_IN_DAY_FIELD = 22,
+    UDAT_TIMEZONE_RFC_FIELD = 23,
+    UDAT_TIMEZONE_GENERIC_FIELD = 24,
+    UDAT_STANDALONE_DAY_FIELD = 25,
+    UDAT_STANDALONE_MONTH_FIELD = 26,
+    UDAT_QUARTER_FIELD = 27,
+    UDAT_STANDALONE_QUARTER_FIELD = 28,
+    UDAT_TIMEZONE_SPECIAL_FIELD = 29,
+    UDAT_YEAR_NAME_FIELD = 30,
+    UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31,
+    UDAT_TIMEZONE_ISO_FIELD = 32,
+    UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33,
+    UDAT_RELATED_YEAR_FIELD = 34,
+    UDAT_TIME_SEPARATOR_FIELD = 35,
+    UDAT_FIELD_COUNT = 36
 };
 
 enum UDateFormatStyle {
     UDAT_PATTERN = -2,
     UDAT_IGNORE = UDAT_PATTERN
 };
 
 static int32_t
@@ -2339,16 +2374,106 @@ js::intl_FormatDateTime(JSContext* cx, u
     if (!isDateTimeFormatInstance)
         udat_close(df);
     if (!success)
         return false;
     args.rval().set(result);
     return true;
 }
 
+bool
+js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 1);
+
+    JSAutoByteString locale(cx, args[0].toString());
+    if (!locale)
+        return false;
+
+    UErrorCode status = U_ZERO_ERROR;
+    const UChar* uTimeZone = nullptr;
+    int32_t uTimeZoneLength = 0;
+    UCalendar* cal = ucal_open(uTimeZone, uTimeZoneLength, locale.ptr(), UCAL_DEFAULT, &status);
+    if (U_FAILURE(status)) {
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+        return false;
+    }
+    ScopedICUObject<UCalendar, ucal_close> toClose(cal);
+
+    RootedObject info(cx, NewBuiltinClassInstance<PlainObject>(cx));
+    if (!info)
+        return false;
+
+    RootedValue v(cx);
+    int32_t firstDayOfWeek = ucal_getAttribute(cal, UCAL_FIRST_DAY_OF_WEEK);
+    v.setInt32(firstDayOfWeek);
+
+    if (!DefineProperty(cx, info, cx->names().firstDayOfWeek, v))
+        return false;
+
+    int32_t minDays = ucal_getAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
+    v.setInt32(minDays);
+    if (!DefineProperty(cx, info, cx->names().minDays, v))
+        return false;
+
+    UCalendarWeekdayType prevDayType = ucal_getDayOfWeekType(cal, UCAL_SATURDAY, &status);
+    if (U_FAILURE(status)) {
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+        return false;
+    }
+
+    RootedValue weekendStart(cx), weekendEnd(cx);
+
+    for (int i = UCAL_SUNDAY; i <= UCAL_SATURDAY; i++) {
+        UCalendarDaysOfWeek dayOfWeek = static_cast<UCalendarDaysOfWeek>(i);
+        UCalendarWeekdayType type = ucal_getDayOfWeekType(cal, dayOfWeek, &status);
+        if (U_FAILURE(status)) {
+            JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+            return false;
+        }
+
+        if (prevDayType != type) {
+            switch (type) {
+              case UCAL_WEEKDAY:
+                // If the first Weekday after Weekend is Sunday (1),
+                // then the last Weekend day is Saturday (7).
+                // Otherwise we'll just take the previous days number.
+                weekendEnd.setInt32(i == 1 ? 7 : i - 1);
+                break;
+              case UCAL_WEEKEND:
+                weekendStart.setInt32(i);
+                break;
+              case UCAL_WEEKEND_ONSET:
+              case UCAL_WEEKEND_CEASE:
+                // At the time this code was added, ICU apparently never behaves this way,
+                // so just throw, so that users will report a bug and we can decide what to
+                // do.
+                JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+                return false;
+              default:
+                break;
+            }
+        }
+
+        prevDayType = type;
+    }
+
+    MOZ_ASSERT(weekendStart.isInt32());
+    MOZ_ASSERT(weekendEnd.isInt32());
+
+    if (!DefineProperty(cx, info, cx->names().weekendStart, weekendStart))
+        return false;
+
+    if (!DefineProperty(cx, info, cx->names().weekendEnd, weekendEnd))
+        return false;
+
+    args.rval().setObject(*info);
+    return true;
+}
 
 /******************** Intl ********************/
 
 const Class js::IntlClass = {
     js_Object_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_Intl)
 };
 
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -176,16 +176,42 @@ intl_patternForSkeleton(JSContext* cx, u
  *
  * Spec: ECMAScript Internationalization API Specification, 12.3.2.
  *
  * Usage: formatted = intl_FormatDateTime(dateTimeFormat, x)
  */
 extern MOZ_MUST_USE bool
 intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp);
 
+/**
+ * Returns a plain object with calendar information for a single valid locale
+ * (callers must perform this validation).  The object will have these
+ * properties:
+ *
+ *   firstDayOfWeek
+ *     an integer in the range 1=Sunday to 7=Saturday indicating the day
+ *     considered the first day of the week in calendars, e.g. 1 for en-US,
+ *     2 for en-GB, 1 for bn-IN
+ *   minDays
+ *     an integer in the range of 1 to 7 indicating the minimum number
+ *     of days required in the first week of the year, e.g. 1 for en-US, 4 for de
+ *   weekendStart
+ *     an integer in the range 1=Sunday to 7=Saturday indicating the day
+ *     considered the beginning of a weekend, e.g. 7 for en-US, 7 for en-GB,
+ *     1 for bn-IN
+ *   weekendEnd
+ *     an integer in the range 1=Sunday to 7=Saturday indicating the day
+ *     considered the end of a weekend, e.g. 1 for en-US, 1 for en-GB,
+ *     1 for bn-IN (note that "weekend" is *not* necessarily two days)
+ *
+ * NOTE: "calendar" and "locale" properties are *not* added to the object.
+ */
+extern MOZ_MUST_USE bool
+intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp);
+
 #if ENABLE_INTL_API
 /**
  * Cast char16_t* strings to UChar* strings used by ICU.
  */
 inline const UChar*
 Char16ToUChar(const char16_t* chars)
 {
   return reinterpret_cast<const UChar*>(chars);
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -2877,8 +2877,30 @@ function Intl_getCanonicalLocales(locale
   let k = 0;
 
   while (k < len) {
     _DefineDataProperty(result, k, codes[k]);
     k++;
   }
   return result;
 }
+
+function Intl_getCalendarInfo(locales) {
+  const requestedLocales = CanonicalizeLocaleList(locales);
+
+  const DateTimeFormat = dateTimeFormatInternalProperties;
+  const localeData = DateTimeFormat.localeData;
+
+  const localeOpt = new Record();
+  localeOpt.localeMatcher = "best fit";
+
+  const r = ResolveLocale(callFunction(DateTimeFormat.availableLocales, DateTimeFormat),
+                          requestedLocales,
+                          localeOpt,
+                          DateTimeFormat.relevantExtensionKeys,
+                          localeData);
+
+  const result = intl_GetCalendarInfo(r.locale);
+  result.calendar = r.ca;
+  result.locale = r.locale;
+
+  return result;
+}
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -504,17 +504,17 @@ IsProxy(JSContext* cx, unsigned argc, Va
     args.rval().setBoolean(args[0].toObject().is<ProxyObject>());
     return true;
 }
 
 static bool
 WasmIsSupported(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(wasm::HasCompilerSupport(cx) && cx->options().wasm());
+    args.rval().setBoolean(wasm::HasCompilerSupport(cx));
     return true;
 }
 
 static bool
 WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -4317,49 +4317,39 @@ Parser<ParseHandler>::declarationList(Yi
 
         if (!tokenStream.matchToken(&matched, TOK_COMMA))
             return null();
     } while (matched);
 
     return decl;
 }
 
-template <>
-ParseNode*
-Parser<FullParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, bool isConst)
-{
-    handler.disableSyntaxParser();
-
+template <typename ParseHandler>
+typename ParseHandler::Node
+Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, bool isConst)
+{
     /*
      * Parse body-level lets without a new block object. ES6 specs
      * that an execution environment's initial lexical environment
      * is the VariableEnvironment, i.e., body-level lets are in
      * the same environment record as vars.
      *
      * However, they cannot be parsed exactly as vars, as ES6
      * requires that uninitialized lets throw ReferenceError on use.
      *
      * See 8.1.1.1.6 and the note in 13.2.1.
      */
-    ParseNode* decl = declarationList(yieldHandling, isConst ? PNK_CONST : PNK_LET);
+    Node decl = declarationList(yieldHandling, isConst ? PNK_CONST : PNK_LET);
     if (!decl || !MatchOrInsertSemicolonAfterExpression(tokenStream))
         return null();
 
     return decl;
 }
 
 template <>
-SyntaxParseHandler::Node
-Parser<SyntaxParseHandler>::lexicalDeclaration(YieldHandling, bool)
-{
-    JS_ALWAYS_FALSE(abortIfSyntaxParser());
-    return SyntaxParseHandler::NodeFailure;
-}
-
-template <>
 bool
 Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
 {
     if (tt == TOK_LC) {
         TokenStream::Modifier modifier = TokenStream::KeywordIsName;
         while (true) {
             // Handle the forms |import {} from 'a'| and
             // |import { ..., } from 'a'| (where ... is non empty), by
@@ -5791,28 +5781,20 @@ Parser<ParseHandler>::yieldExpression(In
 
         return newYieldExpression(begin, exprNode);
       }
     }
 
     MOZ_CRASH("yieldExpr");
 }
 
-template <>
-ParseNode*
-Parser<FullParseHandler>::withStatement(YieldHandling yieldHandling)
-{
-    // test262/ch12/12.10/12.10-0-1.js fails if we try to parse with-statements
-    // in syntax-parse mode. See bug 892583.
-    if (handler.syntaxParser) {
-        handler.disableSyntaxParser();
-        abortedSyntaxParse = true;
-        return null();
-    }
-
+template <typename ParseHandler>
+typename ParseHandler::Node
+Parser<ParseHandler>::withStatement(YieldHandling yieldHandling)
+{
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH));
     uint32_t begin = pos().begin;
 
     // In most cases, we want the constructs forbidden in strict mode code to be
     // a subset of those that JSOPTION_EXTRA_WARNINGS warns about, and we should
     // use reportStrictModeError.  However, 'with' is the sole instance of a
     // construct that is forbidden in strict mode code, but doesn't even merit a
     // warning under JSOPTION_EXTRA_WARNINGS.  See
@@ -5836,24 +5818,16 @@ Parser<FullParseHandler>::withStatement(
             return null();
     }
 
     pc->sc()->setBindingsAccessedDynamically();
 
     return handler.newWithStatement(begin, objectExpr, innerBlock);
 }
 
-template <>
-SyntaxParseHandler::Node
-Parser<SyntaxParseHandler>::withStatement(YieldHandling yieldHandling)
-{
-    JS_ALWAYS_FALSE(abortIfSyntaxParser());
-    return null();
-}
-
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::labeledItem(YieldHandling yieldHandling)
 {
     TokenKind tt;
     if (!tokenStream.getToken(&tt, TokenStream::Operand))
         return null();
 
@@ -6894,18 +6868,16 @@ Parser<ParseHandler>::statementListItem(
         if (!abortIfSyntaxParser())
             return null();
         return classDefinition(yieldHandling, ClassStatement, NameRequired);
 
       //   LexicalDeclaration[In, ?Yield]
       //     LetOrConst BindingList[?In, ?Yield]
       case TOK_LET:
       case TOK_CONST:
-        if (!abortIfSyntaxParser())
-            return null();
         // [In] is the default behavior, because for-loops specially parse
         // their heads to handle |in| in this situation.
         return lexicalDeclaration(yieldHandling, /* isConst = */ tt == TOK_CONST);
 
       // ImportDeclaration (only inside modules)
       case TOK_IMPORT:
         return importDeclaration();
 
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -41,17 +41,18 @@ class SyntaxParseHandler
         NodeGeneric,
         NodeGetProp,
         NodeStringExprStatement,
         NodeReturn,
         NodeBreak,
         NodeThrow,
         NodeEmptyStatement,
 
-        NodeDeclaration,
+        NodeVarDeclaration,
+        NodeLexicalDeclaration,
 
         NodeFunctionDefinition,
 
         // This is needed for proper assignment-target handling.  ES6 formally
         // requires function calls *not* pass IsValidSimpleAssignmentTarget,
         // but at last check there were still sites with |f() = 5| and similar
         // in code not actually executed (or at least not executed enough to be
         // noticed).
@@ -291,16 +292,17 @@ class SyntaxParseHandler
     Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
     Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; }
     Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
     Node newSwitchStatement(uint32_t begin, Node discriminant, Node caseList) { return NodeGeneric; }
     Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
     Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
     Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; }
     Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; }
+    Node newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
 
     Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) {
         return NodeGeneric;
     }
 
     Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; }
     Node newTryStatement(uint32_t begin, Node body, Node catchList, Node finallyBlock) {
         return NodeGeneric;
@@ -371,32 +373,35 @@ class SyntaxParseHandler
     Node newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
         return newList(kind, op);
     }
     Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
         return newList(kind, op);
     }
 
     Node newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
-        return NodeDeclaration;
+        if (kind == PNK_VAR)
+            return NodeVarDeclaration;
+        MOZ_ASSERT(kind == PNK_LET || kind == PNK_CONST);
+        return NodeLexicalDeclaration;
     }
     Node newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
-        return NodeDeclaration;
+        return newDeclarationList(kind, op);
     }
 
     bool isDeclarationList(Node node) {
-        return node == NodeDeclaration;
+        return node == NodeVarDeclaration || node == NodeLexicalDeclaration;
     }
 
     Node singleBindingFromDeclaration(Node decl) {
         MOZ_ASSERT(isDeclarationList(decl));
 
-        // This is, unfortunately, very dodgy.  Obviously NodeDeclaration
-        // can store no info on the arbitrary number of bindings it could
-        // contain.
+        // This is, unfortunately, very dodgy.  Obviously NodeVarDeclaration
+        // and NodeLexicalDeclaration can store no info on the arbitrary
+        // number of bindings it could contain.
         //
         // But this method is called only for cloning for-in/of declarations
         // as initialization targets.  That context simplifies matters.  If the
         // binding is a single name, it'll always syntax-parse (or it would
         // already have been rejected as assigning/binding a forbidden name).
         // Otherwise the binding is a destructuring pattern.  But syntax
         // parsing would *already* have aborted when it saw a destructuring
         // pattern.  So we can just say any old thing here, because the only
@@ -414,17 +419,18 @@ class SyntaxParseHandler
         return NodeUnparenthesizedCommaExpr;
     }
 
     void addList(Node list, Node kid) {
         MOZ_ASSERT(list == NodeGeneric ||
                    list == NodeUnparenthesizedArray ||
                    list == NodeUnparenthesizedObject ||
                    list == NodeUnparenthesizedCommaExpr ||
-                   list == NodeDeclaration ||
+                   list == NodeVarDeclaration ||
+                   list == NodeLexicalDeclaration ||
                    list == NodeFunctionCall);
     }
 
     Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
         if (kind == PNK_ASSIGN)
             return NodeUnparenthesizedAssignment;
         return newBinary(kind, lhs, rhs, op);
     }
@@ -437,17 +443,17 @@ class SyntaxParseHandler
         return node == NodeUnparenthesizedAssignment;
     }
 
     bool isReturnStatement(Node node) {
         return node == NodeReturn;
     }
 
     bool isStatementPermittedAfterReturnStatement(Node pn) {
-        return pn == NodeFunctionDefinition || pn == NodeDeclaration ||
+        return pn == NodeFunctionDefinition || pn == NodeVarDeclaration ||
                pn == NodeBreak ||
                pn == NodeThrow ||
                pn == NodeEmptyStatement;
     }
 
     bool isSuperBase(Node pn) {
         return pn == NodeSuperBase;
     }
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1334,16 +1334,22 @@ class MacroAssembler : public MacroAssem
     void wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::CalleeDesc& callee);
 
     // This function takes care of loading the pointer to the current instance
     // as the implicit first argument. It preserves TLS and pinned registers.
     // (TLS & pinned regs are non-volatile registers in the system ABI).
     void wasmCallBuiltinInstanceMethod(const ABIArg& instanceArg,
                                        wasm::SymbolicAddress builtin);
 
+  public:
+    // ========================================================================
+    // Clamping functions.
+
+    inline void clampIntToUint8(Register reg) PER_SHARED_ARCH;
+
     //}}} check_macroassembler_style
   public:
 
     // Emits a test of a value against all types in a TypeSet. A scratch
     // register is required.
     template <typename Source>
     void guardTypeSet(const Source& address, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss);
 
--- a/js/src/jit/arm/MacroAssembler-arm-inl.h
+++ b/js/src/jit/arm/MacroAssembler-arm-inl.h
@@ -1952,16 +1952,30 @@ MacroAssembler::storeFloat32x3(FloatRegi
     MOZ_CRASH("NYI");
 }
 void
 MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest)
 {
     MOZ_CRASH("NYI");
 }
 
+// ===============================================================
+// Clamping functions.
+
+void
+MacroAssembler::clampIntToUint8(Register reg)
+{
+    // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
+    // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
+    ScratchRegisterScope scratch(*this);
+    as_mov(scratch, asr(reg, 8), SetCC);
+    ma_mov(Imm32(0xff), reg, NotEqual);
+    ma_mov(Imm32(0), reg, Signed);
+}
+
 //}}} check_macroassembler_style
 // ===============================================================
 
 void
 MacroAssemblerARMCompat::incrementInt32Value(const Address& addr)
 {
     asMasm().add32(Imm32(1), ToPayload(addr));
 }
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1309,25 +1309,16 @@ class MacroAssemblerARMCompat : public M
     template<typename T>
     void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register oldval, Register newval,
                                         Register temp, AnyRegister output);
 
     template<typename T>
     void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value,
                                        Register temp, AnyRegister output);
 
-    void clampIntToUint8(Register reg) {
-        // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
-        // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
-        ScratchRegisterScope scratch(asMasm());
-        as_mov(scratch, asr(reg, 8), SetCC);
-        ma_mov(Imm32(0xff), reg, NotEqual);
-        ma_mov(Imm32(0), reg, Signed);
-    }
-
     inline void incrementInt32Value(const Address& addr);
 
     void cmp32(Register lhs, Imm32 rhs);
     void cmp32(Register lhs, Register rhs);
     void cmp32(const Address& lhs, Imm32 rhs) {
         MOZ_CRASH("NYI");
     }
     void cmp32(const Address& lhs, Register rhs) {
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -1523,16 +1523,33 @@ MacroAssembler::storeFloat32x3(FloatRegi
     MOZ_CRASH("NYI");
 }
 void
 MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest)
 {
     MOZ_CRASH("NYI");
 }
 
+// ===============================================================
+// Clamping functions.
+
+void
+MacroAssembler::clampIntToUint8(Register reg)
+{
+    vixl::UseScratchRegisterScope temps(this);
+    const ARMRegister scratch32 = temps.AcquireW();
+    const ARMRegister reg32(reg, 32);
+    MOZ_ASSERT(!scratch32.Is(reg32));
+
+    Cmp(reg32, Operand(reg32, vixl::UXTB));
+    Csel(reg32, reg32, vixl::wzr, Assembler::GreaterThanOrEqual);
+    Mov(scratch32, Operand(0xff));
+    Csel(reg32, reg32, scratch32, Assembler::LessThanOrEqual);
+}
+
 //}}} check_macroassembler_style
 // ===============================================================
 
 template <typename T>
 void
 MacroAssemblerCompat::addToStackPtr(T t)
 {
     asMasm().addPtr(t, getStackPointer());
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -2238,27 +2238,16 @@ class MacroAssemblerCompat : public vixl
 
     void clampCheck(Register r, Label* handleNotAnInt) {
         MOZ_CRASH("clampCheck");
     }
 
     void stackCheck(ImmWord limitAddr, Label* label) {
         MOZ_CRASH("stackCheck");
     }
-    void clampIntToUint8(Register reg) {
-        vixl::UseScratchRegisterScope temps(this);
-        const ARMRegister scratch32 = temps.AcquireW();
-        const ARMRegister reg32(reg, 32);
-        MOZ_ASSERT(!scratch32.Is(reg32));
-
-        Cmp(reg32, Operand(reg32, vixl::UXTB));
-        Csel(reg32, reg32, vixl::wzr, Assembler::GreaterThanOrEqual);
-        Mov(scratch32, Operand(0xff));
-        Csel(reg32, reg32, scratch32, Assembler::LessThanOrEqual);
-    }
 
     void incrementInt32Value(const Address& addr) {
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch32 = temps.AcquireW();
         MOZ_ASSERT(scratch32.asUnsized() != addr.base);
 
         load32(addr, scratch32.asUnsized());
         Add(scratch32, scratch32, Operand(1));
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
@@ -960,15 +960,31 @@ MacroAssembler::storeFloat32x3(FloatRegi
     MOZ_CRASH("NYI");
 }
 void
 MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest)
 {
     MOZ_CRASH("NYI");
 }
 
+// ===============================================================
+// Clamping functions.
+
+void
+MacroAssembler::clampIntToUint8(Register reg)
+{
+    // If reg is < 0, then we want to clamp to 0.
+    as_slti(ScratchRegister, reg, 0);
+    as_movn(reg, zero, ScratchRegister);
+
+    // If reg is >= 255, then we want to clamp to 255.
+    ma_li(SecondScratchReg, Imm32(255));
+    as_slti(ScratchRegister, reg, 255);
+    as_movz(reg, SecondScratchReg, ScratchRegister);
+}
+
 //}}} check_macroassembler_style
 // ===============================================================
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips_shared_MacroAssembler_mips_shared_inl_h */
--- a/js/src/jit/mips-shared/MoveEmitter-mips-shared.h
+++ b/js/src/jit/mips-shared/MoveEmitter-mips-shared.h
@@ -50,19 +50,19 @@ class MoveEmitterMIPSShared
     virtual void completeCycle(const MoveOperand& from, const MoveOperand& to,
                        MoveOp::Type type, uint32_t slot) = 0;
     void emit(const MoveOp& move);
 
   public:
     MoveEmitterMIPSShared(MacroAssembler& masm)
       : inCycle_(0),
         masm(masm),
+        pushedAtStart_(masm.framePushed()),
         pushedAtCycle_(-1),
         pushedAtSpill_(-1),
-        pushedAtStart_(masm.framePushed()),
         spilledReg_(InvalidReg),
         spilledFloatReg_(InvalidFloatReg)
     { }
     ~MoveEmitterMIPSShared() {
         assertDone();
     }
     void emit(const MoveResolver& moves);
     void finish();
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -1059,29 +1059,16 @@ MacroAssemblerMIPSCompat::storePtr(Regis
 
 void
 MacroAssemblerMIPSCompat::storePtr(Register src, AbsoluteAddress dest)
 {
     movePtr(ImmPtr(dest.addr), ScratchRegister);
     storePtr(src, Address(ScratchRegister, 0));
 }
 
-void
-MacroAssemblerMIPSCompat::clampIntToUint8(Register reg)
-{
-    // If reg is < 0, then we want to clamp to 0.
-    as_slti(ScratchRegister, reg, 0);
-    as_movn(reg, zero, ScratchRegister);
-
-    // If reg is >= 255, then we want to clamp to 255.
-    ma_li(SecondScratchReg, Imm32(255));
-    as_slti(ScratchRegister, reg, 255);
-    as_movz(reg, SecondScratchReg, ScratchRegister);
-}
-
 // Note: this function clobbers the input register.
 void
 MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
 {
     MOZ_ASSERT(input != ScratchDoubleReg);
     Label positive, done;
 
     // <= 0 or NaN --> 0
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -934,18 +934,16 @@ class MacroAssemblerMIPSCompat : public 
         as_movd(dest, src);
     }
 
     void zeroDouble(FloatRegister reg) {
         moveToDoubleLo(zero, reg);
         moveToDoubleHi(zero, reg);
     }
 
-    void clampIntToUint8(Register reg);
-
     void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
 
     void breakpoint();
 
     void checkStackAlignment();
 
     void alignStackPointer();
     void restoreStackPointer();
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -201,39 +201,47 @@ MacroAssemblerMIPS64::ma_li(Register des
     BufferOffset bo = m_buffer.nextOffset();
     ma_liPatchable(dest, ImmWord(/* placeholder */ 0));
     label->bind(bo.getOffset());
 }
 
 void
 MacroAssemblerMIPS64::ma_li(Register dest, ImmWord imm)
 {
-    if ((int64_t)imm.value >= INT16_MIN  && (int64_t)imm.value <= INT16_MAX) {
-        as_addiu(dest, zero, imm.value);
+    int64_t value = imm.value;
+
+    if (value >= INT16_MIN && value <= INT16_MAX) {
+        as_addiu(dest, zero, value);
     } else if (imm.value <= UINT16_MAX) {
-        as_ori(dest, zero, Imm16::Lower(Imm32(imm.value)).encode());
-    } else if (0 == (imm.value & 0xffff) && 0 == (imm.value >> 32)) {
-        as_lui(dest, Imm16::Upper(Imm32(imm.value)).encode());
+        as_ori(dest, zero, Imm16::Lower(Imm32(value)).encode());
+    } else if (value >= INT32_MIN && value <= INT32_MAX) {
+        as_lui(dest, Imm16::Upper(Imm32(value)).encode());
+        if (value & 0xffff)
+            as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
     } else if (imm.value <= UINT32_MAX) {
-        as_lui(dest, Imm16::Upper(Imm32(imm.value)).encode());
-        as_ori(dest, dest, Imm16::Lower(Imm32(imm.value)).encode());
+        as_lui(dest, Imm16::Upper(Imm32(value)).encode());
+        if (value & 0xffff)
+            as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
+        as_dinsu(dest, zero, 32, 32);
     } else {
+        uint64_t high = imm.value >> 32;
+
         if (imm.value >> 48) {
-            as_lui(dest, Imm16::Upper(Imm32(imm.value >> 32)).encode());
-            if ((imm.value >> 32) & 0xffff)
-              as_ori(dest, dest, Imm16::Lower(Imm32(imm.value >> 32)).encode());
+            as_lui(dest, Imm16::Upper(Imm32(high)).encode());
+            if (high & 0xffff)
+                as_ori(dest, dest, Imm16::Lower(Imm32(high)).encode());
             as_dsll(dest, dest, 16);
         } else {
-            as_lui(dest, Imm16::Lower(Imm32(imm.value >> 32)).encode());
+            as_lui(dest, Imm16::Lower(Imm32(high)).encode());
         }
         if ((imm.value >> 16) & 0xffff)
-          as_ori(dest, dest, Imm16::Upper(Imm32(imm.value)).encode());
+            as_ori(dest, dest, Imm16::Upper(Imm32(value)).encode());
         as_dsll(dest, dest, 16);
-        if (imm.value & 0xffff)
-          as_ori(dest, dest, Imm16::Lower(Imm32(imm.value)).encode());
+        if (value & 0xffff)
+            as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
     }
 }
 
 // This method generates lui, dsll and ori instruction block that can be modified
 // by UpdateLoad64Value, either during compilation (eg. Assembler::bind), or
 // during execution (eg. jit::PatchJump).
 void
 MacroAssemblerMIPS64::ma_liPatchable(Register dest, ImmPtr imm)
@@ -1206,29 +1214,16 @@ MacroAssemblerMIPS64Compat::storePtr(Reg
 
 void
 MacroAssemblerMIPS64Compat::storePtr(Register src, AbsoluteAddress dest)
 {
     movePtr(ImmPtr(dest.addr), ScratchRegister);
     storePtr(src, Address(ScratchRegister, 0));
 }
 
-void
-MacroAssemblerMIPS64Compat::clampIntToUint8(Register reg)
-{
-    // If reg is < 0, then we want to clamp to 0.
-    as_slti(ScratchRegister, reg, 0);
-    as_movn(reg, zero, ScratchRegister);
-
-    // If reg is >= 255, then we want to clamp to 255.
-    ma_li(SecondScratchReg, Imm32(255));
-    as_slti(ScratchRegister, reg, 255);
-    as_movz(reg, SecondScratchReg, ScratchRegister);
-}
-
 // Note: this function clobbers the input register.
 void
 MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
 {
     MOZ_ASSERT(input != ScratchDoubleReg);
     Label positive, done;
 
     // <= 0 or NaN --> 0
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -939,18 +939,16 @@ class MacroAssemblerMIPS64Compat : publi
     void moveDouble(FloatRegister src, FloatRegister dest) {
         as_movd(dest, src);
     }
 
     void zeroDouble(FloatRegister reg) {
         moveToDouble(zero, reg);
     }
 
-    void clampIntToUint8(Register reg);
-
     void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
 
     void breakpoint();
 
     void checkStackAlignment();
 
     static void calculateAlignedStackPointer(void** stackPointer);
 
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -347,18 +347,16 @@ class MacroAssemblerNone : public Assemb
     template <typename T, typename S> void atomicFetchXor8ZeroExtend(const T& value, const S& mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor16SignExtend(const T& value, const S& mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor16ZeroExtend(const T& value, const S& mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor32(const T& value, const S& mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicXor8(const T& value, const S& mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicXor16(const T& value, const S& mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicXor32(const T& value, const S& mem) { MOZ_CRASH(); }
 
-    void clampIntToUint8(Register) { MOZ_CRASH(); }
-
     Register splitTagForTest(ValueOperand) { MOZ_CRASH(); }
 
     void boxDouble(FloatRegister, ValueOperand) { MOZ_CRASH(); }
     void boxNonDouble(JSValueType, Register, ValueOperand) { MOZ_CRASH(); }
     template <typename T> void unboxInt32(T, Register) { MOZ_CRASH(); }
     template <typename T> void unboxBoolean(T, Register) { MOZ_CRASH(); }
     template <typename T> void unboxString(T, Register) { MOZ_CRASH(); }
     template <typename T> void unboxSymbol(T, Register) { MOZ_CRASH(); }
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h
@@ -1235,28 +1235,31 @@ MacroAssembler::truncateDoubleToInt64(Ad
     fistp(Operand(dest));
 
     // Reset the conversion flag.
     fldcw(Operand(esp, 0));
 
     freeStack(2*sizeof(int32_t));
 }
 
-//}}} check_macroassembler_style
 // ===============================================================
+// Clamping functions.
 
 void
-MacroAssemblerX86Shared::clampIntToUint8(Register reg)
+MacroAssembler::clampIntToUint8(Register reg)
 {
     Label inRange;
-    asMasm().branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
+    branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
     {
         sarl(Imm32(31), reg);
         notl(reg);
         andl(Imm32(255), reg);
     }
     bind(&inRange);
 }
 
+//}}} check_macroassembler_style
+// ===============================================================
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_shared_MacroAssembler_x86_shared_inl_h */
--- a/js/src/jsapi-tests/testJitMoveEmitterCycles-mips32.cpp
+++ b/js/src/jsapi-tests/testJitMoveEmitterCycles-mips32.cpp
@@ -74,45 +74,46 @@ linkAndAllocate(JSContext* cx, js::jit::
 {
     using namespace js;
     using namespace js::jit;
     AutoFlushICache afc("test");
     Linker l(*masm);
     return l.newCode<CanGC>(cx, ION_CODE);
 }
 
+#define TRY(x) if (!(x)) return false;
+
 BEGIN_TEST(testJitMoveEmitterCycles_simple)
 {
     using namespace js;
     using namespace js::jit;
     LifoAlloc lifo(LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     TempAllocator alloc(&lifo);
     JitContext jc(cx, &alloc);
-    rt->getJitRuntime(cx);
     AutoFlushICache afc("test");
 
     MacroAssembler masm;
     MoveEmitter mover(masm);
     MoveResolver mr;
     mr.setAllocator(alloc);
     Simulator* sim = Simulator::Current();
-    mr.addMove(MoveOperand(double0), MoveOperand(double2), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double0), MoveOperand(double2), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double0.id(), 2.0);
-    mr.addMove(MoveOperand(double3), MoveOperand(double1), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double3), MoveOperand(double1), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double3.id(), 1.0);
-    mr.addMove(MoveOperand(single4), MoveOperand(single0), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single4), MoveOperand(single0), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single4.id(), 0.0f);
-    mr.addMove(MoveOperand(single5), MoveOperand(single6), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single5), MoveOperand(single6), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single5.id(), 6.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single1), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single1), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 1.0f);
-    mr.addMove(MoveOperand(single3), MoveOperand(single7), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single3), MoveOperand(single7), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single3.id(), 7.0f);
     // don't explode!
-    mr.resolve();
+    TRY(mr.resolve());
     mover.emit(mr);
     mover.finish();
     masm.abiret();
     JitCode* code = linkAndAllocate(cx, &masm);
     sim->call(code->raw(), 1, 1);
     CHECK(sim->getFpuRegisterDouble(double2.id()) == 2.0);
     CHECK(int(sim->getFpuRegisterDouble(double1.id())) == 1.0);
     CHECK(int(sim->getFpuRegisterFloat(single0.id())) == 0.0);
@@ -124,67 +125,66 @@ BEGIN_TEST(testJitMoveEmitterCycles_simp
 END_TEST(testJitMoveEmitterCycles_simple)
 BEGIN_TEST(testJitMoveEmitterCycles_autogen)
 {
     using namespace js;
     using namespace js::jit;
     LifoAlloc lifo(LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     TempAllocator alloc(&lifo);
     JitContext jc(cx, &alloc);
-    rt->getJitRuntime(cx);
     AutoFlushICache afc("test");
     MacroAssembler masm;
     MoveEmitter mover(masm);
     MoveResolver mr;
     mr.setAllocator(alloc);
     Simulator* sim = Simulator::Current();
     sim->setFpuRegisterDouble(double9.id(), 9.0);
-    mr.addMove(MoveOperand(single24), MoveOperand(single25), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single24), MoveOperand(single25), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single24.id(), 24.0f);
-    mr.addMove(MoveOperand(double3), MoveOperand(double0), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double3), MoveOperand(double0), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double3.id(), 3.0);
-    mr.addMove(MoveOperand(single10), MoveOperand(single31), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single10), MoveOperand(single31), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single10.id(), 10.0f);
-    mr.addMove(MoveOperand(double1), MoveOperand(double10), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double1), MoveOperand(double10), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double1.id(), 1.0);
-    mr.addMove(MoveOperand(single8), MoveOperand(single10), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single8), MoveOperand(single10), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single8.id(), 8.0f);
-    mr.addMove(MoveOperand(double2), MoveOperand(double7), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double2), MoveOperand(double7), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double2.id(), 2.0);
-    mr.addMove(MoveOperand(single1), MoveOperand(single3), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single1), MoveOperand(single3), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single1.id(), 1.0f);
-    mr.addMove(MoveOperand(single17), MoveOperand(single11), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single17), MoveOperand(single11), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single17.id(), 17.0f);
-    mr.addMove(MoveOperand(single22), MoveOperand(single30), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single22), MoveOperand(single30), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single22.id(), 22.0f);
-    mr.addMove(MoveOperand(single31), MoveOperand(single7), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single31), MoveOperand(single7), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single31.id(), 31.0f);
-    mr.addMove(MoveOperand(double3), MoveOperand(double13), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double3), MoveOperand(double13), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double3.id(), 3.0);
-    mr.addMove(MoveOperand(single31), MoveOperand(single23), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single31), MoveOperand(single23), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single31.id(), 31.0f);
-    mr.addMove(MoveOperand(single13), MoveOperand(single8), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single13), MoveOperand(single8), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single13.id(), 13.0f);
-    mr.addMove(MoveOperand(single28), MoveOperand(single5), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single28), MoveOperand(single5), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single28.id(), 28.0f);
-    mr.addMove(MoveOperand(single20), MoveOperand(single6), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single20), MoveOperand(single6), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single20.id(), 20.0f);
-    mr.addMove(MoveOperand(single0), MoveOperand(single2), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single0), MoveOperand(single2), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single0.id(), 0.0f);
-    mr.addMove(MoveOperand(double7), MoveOperand(double6), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double7), MoveOperand(double6), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double7.id(), 7.0);
-    mr.addMove(MoveOperand(single13), MoveOperand(single9), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single13), MoveOperand(single9), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single13.id(), 13.0f);
-    mr.addMove(MoveOperand(single1), MoveOperand(single4), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single1), MoveOperand(single4), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single1.id(), 1.0f);
-    mr.addMove(MoveOperand(single29), MoveOperand(single22), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single29), MoveOperand(single22), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single29.id(), 29.0f);
-    mr.addMove(MoveOperand(single25), MoveOperand(single24), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single25), MoveOperand(single24), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single25.id(), 25.0f);
-    mr.resolve();
+    TRY(mr.resolve());
     mover.emit(mr);
     mover.finish();
     masm.abiret();
     JitCode* code = linkAndAllocate(cx, &masm);
     sim->call(code->raw(), 1, 1);
     CHECK(int(sim->getFpuRegisterFloat(single25.id())) == 24.0);
     CHECK(int(sim->getFpuRegisterDouble(double0.id())) == 3.0);
     CHECK(int(sim->getFpuRegisterFloat(single31.id())) == 10.0);
@@ -212,74 +212,73 @@ END_TEST(testJitMoveEmitterCycles_autoge
 
 BEGIN_TEST(testJitMoveEmitterCycles_autogen2)
 {
     using namespace js;
     using namespace js::jit;
     LifoAlloc lifo(LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     TempAllocator alloc(&lifo);
     JitContext jc(cx, &alloc);
-    rt->getJitRuntime(cx);
     AutoFlushICache afc("test");
     MacroAssembler masm;
     MoveEmitter mover(masm);
     MoveResolver mr;
     mr.setAllocator(alloc);
     Simulator* sim = Simulator::Current();
-    mr.addMove(MoveOperand(double10), MoveOperand(double0), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double10), MoveOperand(double0), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double10.id(), 10.0);
-    mr.addMove(MoveOperand(single15), MoveOperand(single3), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single15), MoveOperand(single3), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single15.id(), 15.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single28), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single28), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single30), MoveOperand(single25), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single30), MoveOperand(single25), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single30.id(), 30.0f);
-    mr.addMove(MoveOperand(single16), MoveOperand(single2), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single16), MoveOperand(single2), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single16.id(), 16.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single29), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single29), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single17), MoveOperand(single10), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single17), MoveOperand(single10), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single17.id(), 17.0f);
-    mr.addMove(MoveOperand(single9), MoveOperand(single26), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single9), MoveOperand(single26), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single9.id(), 9.0f);
-    mr.addMove(MoveOperand(single1), MoveOperand(single23), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single1), MoveOperand(single23), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single1.id(), 1.0f);
-    mr.addMove(MoveOperand(single8), MoveOperand(single6), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single8), MoveOperand(single6), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single8.id(), 8.0f);
-    mr.addMove(MoveOperand(single24), MoveOperand(single16), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single24), MoveOperand(single16), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single24.id(), 24.0f);
-    mr.addMove(MoveOperand(double5), MoveOperand(double6), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double5), MoveOperand(double6), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double5.id(), 5.0f);
-    mr.addMove(MoveOperand(single23), MoveOperand(single30), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single23), MoveOperand(single30), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single23.id(), 23.0f);
-    mr.addMove(MoveOperand(single27), MoveOperand(single17), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single27), MoveOperand(single17), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single27.id(), 27.0f);
-    mr.addMove(MoveOperand(double3), MoveOperand(double4), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double3), MoveOperand(double4), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double3.id(), 3.0f);
-    mr.addMove(MoveOperand(single14), MoveOperand(single27), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single14), MoveOperand(single27), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single14.id(), 14.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single31), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single31), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single24), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single24), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single31), MoveOperand(single11), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single31), MoveOperand(single11), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single31.id(), 31.0f);
-    mr.addMove(MoveOperand(single24), MoveOperand(single7), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single24), MoveOperand(single7), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single24.id(), 24.0f);
-    mr.addMove(MoveOperand(single0), MoveOperand(single21), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single0), MoveOperand(single21), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single0.id(), 0.0f);
-    mr.addMove(MoveOperand(single27), MoveOperand(single20), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single27), MoveOperand(single20), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single27.id(), 27.0f);
-    mr.addMove(MoveOperand(single14), MoveOperand(single5), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single14), MoveOperand(single5), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single14.id(), 14.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single14), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single14), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single12), MoveOperand(single22), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single12), MoveOperand(single22), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single12.id(), 12.0f);
-    mr.resolve();
+    TRY(mr.resolve());
     mover.emit(mr);
     mover.finish();
     masm.abiret();
     JitCode* code = linkAndAllocate(cx, &masm);
     sim->call(code->raw(), 1, 1);
     CHECK(int(sim->getFpuRegisterDouble(double0.id())) == 10);
     CHECK(int(sim->getFpuRegisterFloat(single3.id())) == 15);
     CHECK(int(sim->getFpuRegisterFloat(single28.id())) == 2);
@@ -312,76 +311,75 @@ END_TEST(testJitMoveEmitterCycles_autoge
 
 BEGIN_TEST(testJitMoveEmitterCycles_autogen3)
 {
     using namespace js;
     using namespace js::jit;
     LifoAlloc lifo(LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     TempAllocator alloc(&lifo);
     JitContext jc(cx, &alloc);
-    rt->getJitRuntime(cx);
     AutoFlushICache afc("test");
     MacroAssembler masm;
     MoveEmitter mover(masm);
     MoveResolver mr;
     mr.setAllocator(alloc);
     Simulator* sim = Simulator::Current();
-    mr.addMove(MoveOperand(single0), MoveOperand(single21), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single0), MoveOperand(single21), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single0.id(), 0.0f);
-    mr.addMove(MoveOperand(single2), MoveOperand(single26), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single2), MoveOperand(single26), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single2.id(), 2.0f);
-    mr.addMove(MoveOperand(single4), MoveOperand(single24), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single4), MoveOperand(single24), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single4.id(), 4.0f);
-    mr.addMove(MoveOperand(single22), MoveOperand(single9), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single22), MoveOperand(single9), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single22.id(), 22.0f);
-    mr.addMove(MoveOperand(single5), MoveOperand(single28), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single5), MoveOperand(single28), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single5.id(), 5.0f);
-    mr.addMove(MoveOperand(single15), MoveOperand(single7), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single15), MoveOperand(single7), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single15.id(), 15.0f);
-    mr.addMove(MoveOperand(single26), MoveOperand(single14), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single26), MoveOperand(single14), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single26.id(), 26.0f);
-    mr.addMove(MoveOperand(single13), MoveOperand(single30), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single13), MoveOperand(single30), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single13.id(), 13.0f);
-    mr.addMove(MoveOperand(single26), MoveOperand(single22), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single26), MoveOperand(single22), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single26.id(), 26.0f);
-    mr.addMove(MoveOperand(single21), MoveOperand(single6), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single21), MoveOperand(single6), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single21.id(), 21.0f);
-    mr.addMove(MoveOperand(single23), MoveOperand(single31), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single23), MoveOperand(single31), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single23.id(), 23.0f);
-    mr.addMove(MoveOperand(single7), MoveOperand(single12), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single7), MoveOperand(single12), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single7.id(), 7.0f);
-    mr.addMove(MoveOperand(single14), MoveOperand(single10), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single14), MoveOperand(single10), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single14.id(), 14.0f);
-    mr.addMove(MoveOperand(double12), MoveOperand(double8), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double12), MoveOperand(double8), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double12.id(), 12.0);
-    mr.addMove(MoveOperand(single5), MoveOperand(single1), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single5), MoveOperand(single1), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single5.id(), 5.0f);
-    mr.addMove(MoveOperand(double12), MoveOperand(double2), MoveOp::DOUBLE);
+    TRY(mr.addMove(MoveOperand(double12), MoveOperand(double2), MoveOp::DOUBLE));
     sim->setFpuRegisterDouble(double12.id(), 12.0);
-    mr.addMove(MoveOperand(single3), MoveOperand(single8), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single3), MoveOperand(single8), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single3.id(), 3.0f);
-    mr.addMove(MoveOperand(single14), MoveOperand(single0), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single14), MoveOperand(single0), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single14.id(), 14.0f);
-    mr.addMove(MoveOperand(single28), MoveOperand(single29), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single28), MoveOperand(single29), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single28.id(), 28.0f);
-    mr.addMove(MoveOperand(single29), MoveOperand(single2), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single29), MoveOperand(single2), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single29.id(), 29.0f);
-    mr.addMove(MoveOperand(single22), MoveOperand(single27), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single22), MoveOperand(single27), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single22.id(), 22.0f);
-    mr.addMove(MoveOperand(single21), MoveOperand(single11), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single21), MoveOperand(single11), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single21.id(), 21.0f);
-    mr.addMove(MoveOperand(single22), MoveOperand(single13), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single22), MoveOperand(single13), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single22.id(), 22.0f);
-    mr.addMove(MoveOperand(single29), MoveOperand(single25), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single29), MoveOperand(single25), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single29.id(), 29.0f);
-    mr.addMove(MoveOperand(single29), MoveOperand(single15), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single29), MoveOperand(single15), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single29.id(), 29.0f);
-    mr.addMove(MoveOperand(single16), MoveOperand(single23), MoveOp::FLOAT32);
+    TRY(mr.addMove(MoveOperand(single16), MoveOperand(single23), MoveOp::FLOAT32));
     sim->setFpuRegisterFloat(single16.id(), 16.0f);
-    mr.resolve();
+    TRY(mr.resolve());
     mover.emit(mr);
     mover.finish();
     masm.abiret();
     JitCode* code = linkAndAllocate(cx, &masm);
     sim->call(code->raw(), 1, 1);
     CHECK(int(sim->getFpuRegisterFloat(single21.id())) == 0);
     CHECK(int(sim->getFpuRegisterFloat(single26.id())) == 2);
     CHECK(int(sim->getFpuRegisterFloat(single24.id())) == 4);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -873,16 +873,40 @@ SetPromiseRejectionTrackerCallback(JSCon
     GetShellContext(cx)->promiseRejectionTrackerCallback = args[0];
     JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback);
 
 #endif // SPIDERMONKEY_PROMISE
     args.rval().setUndefined();
     return true;
 }
 
+#ifdef ENABLE_INTL_API
+static bool
+AddIntlExtras(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!args.get(0).isObject()) {
+        JS_ReportError(cx, "addIntlExtras must be passed an object");
+        return false;
+    }
+    JS::RootedObject intl(cx, &args[0].toObject());
+
+    static const JSFunctionSpec funcs[] = {
+        JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
+        JS_FS_END
+    };
+
+    if (!JS_DefineFunctions(cx, intl, funcs))
+        return false;
+
+    args.rval().setUndefined();
+    return true;
+}
+#endif // ENABLE_INTL_API
+
 static bool
 EvalAndPrint(JSContext* cx, const char* bytes, size_t length,
              int lineno, bool compileOnly)
 {
     // Eval.
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell interactive")
            .setUTF8(true)
@@ -5795,16 +5819,26 @@ static const JSFunctionSpecWithHelp shel
 "Take jobs from the shell's job queue in FIFO order and run them until the\n"
 "queue is empty.\n"),
 
     JS_FN_HELP("setPromiseRejectionTrackerCallback", SetPromiseRejectionTrackerCallback, 1, 0,
 "setPromiseRejectionTrackerCallback()",
 "Sets the callback to be invoked whenever a Promise rejection is unhandled\n"
 "or a previously-unhandled rejection becomes handled."),
 
+#ifdef ENABLE_INTL_API
+    JS_FN_HELP("addIntlExtras", AddIntlExtras, 1, 0,
+"addIntlExtras(obj)",
+"Adds various not-yet-standardized Intl functions as properties on the\n"
+"provided object (this should generally be Intl itself).  The added\n"
+"functions and their behavior are experimental: don't depend upon them\n"
+"unless you're willing to update your code if these experimental APIs change\n"
+"underneath you."),
+#endif // ENABLE_INTL_API
+
     JS_FS_HELP_END
 };
 
 static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
     JS_FN_HELP("clone", Clone, 1, 0,
 "clone(fun[, scope])",
 "  Clone function object."),
 
new file mode 100644
--- /dev/null
+++ b/js/src/tests/Intl/getCalendarInfo.js
@@ -0,0 +1,83 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras"))
+/* 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/. */
+
+// Tests the getCalendarInfo function with a diverse set of arguments.
+
+function checkCalendarInfo(info, expected)
+{
+  assertEq(Object.getPrototypeOf(info), Object.prototype);
+
+  assertEq(info.firstDayOfWeek, expected.firstDayOfWeek);
+  assertEq(info.minDays, expected.minDays);
+  assertEq(info.weekendStart, expected.weekendStart);
+  assertEq(info.weekendEnd, expected.weekendEnd);
+  assertEq(info.calendar, expected.calendar);
+  assertEq(info.locale, expected.locale);
+}
+
+addIntlExtras(Intl);
+
+let gCI = Intl.getCalendarInfo;
+
+assertEq(gCI.length, 1);
+
+checkCalendarInfo(gCI('en-US'), {
+  firstDayOfWeek: 1,
+  minDays: 1,
+  weekendStart: 7,
+  weekendEnd: 1,
+  calendar: "gregory",
+  locale: "en-US"
+});
+
+checkCalendarInfo(gCI('en-IL'), {
+  firstDayOfWeek: 1,
+  minDays: 1,
+  weekendStart: 6,
+  weekendEnd: 7,
+  calendar: "gregory",
+  locale: "en-IL"
+});
+
+
+checkCalendarInfo(gCI('en-GB'), {
+  firstDayOfWeek: 2,
+  minDays: 4,
+  weekendStart: 7,
+  weekendEnd: 1,
+  calendar: "gregory",
+  locale: "en-GB"
+});
+
+
+checkCalendarInfo(gCI('pl'), {
+  firstDayOfWeek: 2,
+  minDays: 4,
+  weekendStart: 7,
+  weekendEnd: 1,
+  calendar: "gregory",
+  locale: "pl"
+});
+
+checkCalendarInfo(gCI('ar-IQ'), {
+  firstDayOfWeek: 7,
+  minDays: 1,
+  weekendStart: 6,
+  weekendEnd: 7,
+  calendar: "gregory",
+  locale: "ar-IQ"
+});
+
+checkCalendarInfo(gCI('fa-IR'), {
+  firstDayOfWeek: 7,
+  minDays: 1,
+  weekendStart: 6,
+  weekendEnd: 6,
+  calendar: "persian",
+  locale: "fa-IR"
+});
+
+if (typeof reportCompare === 'function')
+    reportCompare(0, 0);
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -101,16 +101,17 @@
     macro(exec, exec, "exec") \
     macro(false, false_, "false") \
     macro(fieldOffsets, fieldOffsets, "fieldOffsets") \
     macro(fieldTypes, fieldTypes, "fieldTypes") \
     macro(fileName, fileName, "fileName") \
     macro(fill, fill, "fill") \
     macro(find, find, "find") \
     macro(findIndex, findIndex, "findIndex") \
+    macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
     macro(fix, fix, "fix") \
     macro(flags, flags, "flags") \
     macro(float32, float32, "float32") \
     macro(Float32x4, Float32x4, "Float32x4") \
     macro(float64, float64, "float64") \
     macro(Float64x2, Float64x2, "Float64x2") \
     macro(forceInterpreter, forceInterpreter, "forceInterpreter") \
     macro(forEach, forEach, "forEach") \
@@ -176,16 +177,17 @@
     macro(loc, loc, "loc") \
     macro(locale, locale, "locale") \
     macro(lookupGetter, lookupGetter, "__lookupGetter__") \
     macro(lookupSetter, lookupSetter, "__lookupSetter__") \
     macro(MapIterator, MapIterator, "Map Iterator") \
     macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
     macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
     macro(message, message, "message") \
+    macro(minDays, minDays, "minDays") \
     macro(minimumFractionDigits, minimumFractionDigits, "minimumFractionDigits") \
     macro(minimumIntegerDigits, minimumIntegerDigits, "minimumIntegerDigits") \
     macro(minimumSignificantDigits, minimumSignificantDigits, "minimumSignificantDigits") \
     macro(minute, minute, "minute") \
     macro(missingArguments, missingArguments, "missingArguments") \
     macro(module, module, "module") \
     macro(ModuleDeclarationInstantiation, ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation") \
     macro(ModuleEvaluation, ModuleEvaluation, "ModuleEvaluation") \
@@ -316,16 +318,18 @@
     macro(WeakSet_add, WeakSet_add, "WeakSet_add") \
     macro(RegExp_prototype_Exec, RegExp_prototype_Exec, "RegExp_prototype_Exec") \
     macro(UnwrapAndCallRegExpBuiltinExec, UnwrapAndCallRegExpBuiltinExec, "UnwrapAndCallRegExpBuiltinExec") \
     macro(RegExpBuiltinExec, RegExpBuiltinExec, "RegExpBuiltinExec") \
     macro(RegExpMatcher, RegExpMatcher, "RegExpMatcher") \
     macro(RegExpSearcher, RegExpSearcher, "RegExpSearcher") \
     macro(RegExpTester, RegExpTester, "RegExpTester") \
     macro(weekday, weekday, "weekday") \
+    macro(weekendEnd, weekendEnd, "weekendEnd") \
+    macro(weekendStart, weekendStart, "weekendStart") \
     macro(writable, writable, "writable") \
     macro(year, year, "year") \
     macro(yield, yield, "yield") \
     macro(raw, raw, "raw") \
     /* Type names must be contiguous and ordered; see js::TypeName. */ \
     macro(undefined, undefined, "undefined") \
     macro(object, object, "object") \
     macro(function, function, "function") \
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -94,17 +94,17 @@ js::GlobalObject::getTypedObjectModule()
     MOZ_ASSERT(v.isObject());
     return v.toObject().as<TypedObjectModuleObject>();
 }
 
 /* static */ bool
 GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key)
 {
     if (key == JSProto_Wasm || key == JSProto_WebAssembly)
-        return !cx->options().wasm();
+        return !cx->options().wasm() || !wasm::HasCompilerSupport(cx);
 
 #ifdef ENABLE_SHARED_ARRAY_BUFFER
     // Return true if the given constructor has been disabled at run-time.
     switch (key) {
       case JSProto_Atomics:
       case JSProto_SharedArrayBuffer:
         return !cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled();
       default:
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2501,16 +2501,17 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("intl_availableCollations", intl_availableCollations, 1,0),
     JS_FN("intl_Collator", intl_Collator, 2,0),
     JS_FN("intl_Collator_availableLocales", intl_Collator_availableLocales, 0,0),
     JS_FN("intl_CompareStrings", intl_CompareStrings, 3,0),
     JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2,0),
     JS_FN("intl_DateTimeFormat_availableLocales", intl_DateTimeFormat_availableLocales, 0,0),
     JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2,0),
     JS_FN("intl_FormatNumber", intl_FormatNumber, 2,0),
+    JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1,0),
     JS_FN("intl_NumberFormat", intl_NumberFormat, 2,0),
     JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),
     JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
     JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
 
     JS_INLINABLE_FN("IsRegExpObject",
                     intrinsic_IsInstanceOfBuiltin<RegExpObject>, 1,0,
                     IsRegExpObject),
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1260,21 +1260,20 @@ public:
 
   // mouse capturing
   static CapturingContentInfo gCaptureInfo;
 
   struct PointerCaptureInfo
   {
     nsCOMPtr<nsIContent> mPendingContent;
     nsCOMPtr<nsIContent> mOverrideContent;
-    bool                 mReleaseContent;
     bool                 mPrimaryState;
 
     explicit PointerCaptureInfo(nsIContent* aPendingContent, bool aPrimaryState) :
-      mPendingContent(aPendingContent), mReleaseContent(false), mPrimaryState(aPrimaryState)
+      mPendingContent(aPendingContent), mPrimaryState(aPrimaryState)
     {
       MOZ_COUNT_CTOR(PointerCaptureInfo);
     }
     ~PointerCaptureInfo()
     {
       MOZ_COUNT_DTOR(PointerCaptureInfo);
     }
 
@@ -1306,18 +1305,17 @@ public:
                                                    uint16_t aPointerType,
                                                    bool aIsPrimary,
                                                    nsIContent* aCaptureTarget);
   static void SetPointerCapturingContent(uint32_t aPointerId, nsIContent* aContent);
   static void ReleasePointerCapturingContent(uint32_t aPointerId);
   static nsIContent* GetPointerCapturingContent(uint32_t aPointerId);
 
   // CheckPointerCaptureState checks cases, when got/lostpointercapture events should be fired.
-  // Function returns true, if any of events was fired; false, if no one event was fired.
-  static bool CheckPointerCaptureState(uint32_t aPointerId,
+  static void CheckPointerCaptureState(uint32_t aPointerId,
                                        uint16_t aPointerType, bool aIsPrimary);
 
   // GetPointerInfo returns true if pointer with aPointerId is situated in device, false otherwise.
   // aActiveState is additional information, which shows state of pointer like button state for mouse.
   static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState);
 
   // GetPointerType returns pointer type like mouse, pen or touch for pointer event with pointerId
   static uint16_t GetPointerType(uint32_t aPointerId);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4427,19 +4427,18 @@ PresShell::ContentRemoved(nsIDocument *a
       mPointerEventTarget = aMaybeContainer;
     }
   }
 
   // We should check that aChild does not contain pointer capturing elements.
   // If it does we should release the pointer capture for the elements.
   for (auto iter = gPointerCaptureList->Iter(); !iter.Done(); iter.Next()) {
     nsIPresShell::PointerCaptureInfo* data = iter.UserData();
-    if (data && data->mOverrideContent &&
-        nsContentUtils::ContentIsDescendantOf(data->mOverrideContent,
-                                              aChild)) {
+    if (data && data->mPendingContent &&
+        nsContentUtils::ContentIsDescendantOf(data->mPendingContent, aChild)) {
       nsIPresShell::ReleasePointerCapturingContent(iter.Key());
     }
   }
 
   bool didReconstruct;
   mFrameConstructor->ContentRemoved(aMaybeContainer, aChild, oldNextSibling,
                                     nsCSSFrameConstructor::REMOVE_CONTENT,
                                     &didReconstruct);
@@ -6691,100 +6690,80 @@ nsIPresShell::SetCapturingContent(nsICon
     gCaptureInfo.mPointerLock = (aFlags & CAPTURE_POINTERLOCK) != 0;
   }
 }
 
 /* static */ void
 nsIPresShell::SetPointerCapturingContent(uint32_t aPointerId, nsIContent* aContent)
 {
   PointerCaptureInfo* pointerCaptureInfo = nullptr;
-  gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo);
-  nsIContent* content = pointerCaptureInfo ?
-    pointerCaptureInfo->mOverrideContent.get() : nullptr;
-
-  if (!content && (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId))) {
+  MOZ_ASSERT(aContent != nullptr);
+
+  if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
     SetCapturingContent(aContent, CAPTURE_PREVENTDRAG);
   }
 
-  if (pointerCaptureInfo) {
+  if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
+      pointerCaptureInfo) {
     pointerCaptureInfo->mPendingContent = aContent;
-    pointerCaptureInfo->mReleaseContent = false;
   } else {
     gPointerCaptureList->Put(aPointerId,
                              new PointerCaptureInfo(aContent, GetPointerPrimaryState(aPointerId)));
   }
 }
 
 /* static */ void
 nsIPresShell::ReleasePointerCapturingContent(uint32_t aPointerId)
 {
-  if (gActivePointersIds->Get(aPointerId)) {
+  if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) {
     SetCapturingContent(nullptr, CAPTURE_PREVENTDRAG);
   }
 
   PointerCaptureInfo* pointerCaptureInfo = nullptr;
-  if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) && pointerCaptureInfo) {
-    // Set flag to asyncronously release capture for given pointer.
-    pointerCaptureInfo->mReleaseContent = true;
+  if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
+      pointerCaptureInfo) {
+    pointerCaptureInfo->mPendingContent = nullptr;
   }
 }
 
 /* static */ nsIContent*
 nsIPresShell::GetPointerCapturingContent(uint32_t aPointerId)
 {
   PointerCaptureInfo* pointerCaptureInfo = nullptr;
   if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) && pointerCaptureInfo) {
     return pointerCaptureInfo->mOverrideContent;
   }
   return nullptr;
 }
 
-/* static */ bool
+/* static */ void
 nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId,
                                        uint16_t aPointerType, bool aIsPrimary)
 {
-  bool didDispatchEvent = false;
-  PointerCaptureInfo* pointerCaptureInfo = nullptr;
-  if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) && pointerCaptureInfo) {
-    // If pendingContent exist or anybody calls element.releasePointerCapture
-    // we should dispatch lostpointercapture event to overrideContent if it exist
-    if (pointerCaptureInfo->mPendingContent || pointerCaptureInfo->mReleaseContent) {
-      if (pointerCaptureInfo->mOverrideContent) {
-        nsCOMPtr<nsIContent> content;
-        pointerCaptureInfo->mOverrideContent.swap(content);
-        if (pointerCaptureInfo->mReleaseContent) {
-          pointerCaptureInfo->mPendingContent = nullptr;
-        }
-        if (pointerCaptureInfo->Empty()) {
-          gPointerCaptureList->Remove(aPointerId);
-        }
-        DispatchGotOrLostPointerCaptureEvent(false, aPointerId, aPointerType,
-                                             aIsPrimary, content);
-        didDispatchEvent = true;
-      } else if (pointerCaptureInfo->mPendingContent && pointerCaptureInfo->mReleaseContent) {
-        // If anybody calls element.releasePointerCapture
-        // We should clear overrideContent and pendingContent
-        pointerCaptureInfo->mPendingContent = nullptr;
-        pointerCaptureInfo->mReleaseContent = false;
-      }
-    }
-  }
-  if (gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) && pointerCaptureInfo) {
-    // If pendingContent exist we should dispatch gotpointercapture event to it
-    if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent) {
-      pointerCaptureInfo->mOverrideContent = pointerCaptureInfo->mPendingContent;
-      pointerCaptureInfo->mPendingContent = nullptr;
-      pointerCaptureInfo->mReleaseContent = false;
-      DispatchGotOrLostPointerCaptureEvent(true, aPointerId, aPointerType,
-                                           aIsPrimary,
-                                           pointerCaptureInfo->mOverrideContent);
-      didDispatchEvent = true;
-    }
-  }
-  return didDispatchEvent;
+  PointerCaptureInfo* captureInfo = nullptr;
+  if (gPointerCaptureList->Get(aPointerId, &captureInfo) && captureInfo &&
+      captureInfo->mPendingContent != captureInfo->mOverrideContent) {
+    // cache captureInfo->mPendingContent since it may be changed in the pointer
+    // event listener
+    nsIContent* pendingContent = captureInfo->mPendingContent.get();
+    if (captureInfo->mOverrideContent) {
+      DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false,
+                                           aPointerId, aPointerType, aIsPrimary,
+                                           captureInfo->mOverrideContent);
+    }
+    if (pendingContent) {
+      DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aPointerId,
+                                           aPointerType, aIsPrimary,
+                                           pendingContent);
+    }
+    captureInfo->mOverrideContent = pendingContent;
+    if (captureInfo->Empty()) {
+      gPointerCaptureList->Remove(aPointerId);
+    }
+  }
 }
 
 /* static */ uint16_t
 nsIPresShell::GetPointerType(uint32_t aPointerId)
 {
   PointerInfo* pointerInfo = nullptr;
   if (gActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
     return pointerInfo->mPointerType;
@@ -7135,34 +7114,35 @@ DispatchPointerFromMouseOrTouch(PresShel
     //    dispatched to DOM.
     if (!mouseEvent->convertToPointer ||
         !aEvent->IsAllowedToDispatchDOMEvent()) {
       return NS_OK;
     }
     int16_t button = mouseEvent->button;
     switch (mouseEvent->mMessage) {
     case eMouseMove:
-      if (mouseEvent->buttons == 0) {
-        button = -1;
-      }
+      button = -1;
       pointerMessage = ePointerMove;
       break;
     case eMouseUp:
-      pointerMessage = ePointerUp;
+      pointerMessage = mouseEvent->buttons ? ePointerMove : ePointerUp;
       break;
     case eMouseDown:
-      pointerMessage = ePointerDown;
+      pointerMessage =
+        mouseEvent->buttons & ~nsContentUtils::GetButtonsFlagForButton(button) ?
+        ePointerMove : ePointerDown;
       break;
     default:
       return NS_OK;
     }
 
     WidgetPointerEvent event(*mouseEvent);
     event.mMessage = pointerMessage;
     event.button = button;
+    event.buttons = mouseEvent->buttons;
     event.pressure = event.buttons ?
                      mouseEvent->pressure ? mouseEvent->pressure : 0.5f :
                      0.0f;
     event.convertToPointer = mouseEvent->convertToPointer = false;
     aShell->HandleEvent(aFrame, &event, aDontRetargetEvents, aStatus, aTargetContent);
   } else if (aEvent->mClass == eTouchEventClass) {
     WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
     // loop over all touches and dispatch pointer events on each touch
--- a/layout/base/tests/bug977003_inner_4.html
+++ b/layout/base/tests/bug977003_inner_4.html
@@ -15,17 +15,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   </style>
   <script type="application/javascript">
     var target = undefined;
     var mediator = undefined;
     var listener = undefined;
     var test_down_got = false;
     var test_mediator_got = false;
     var test_mediator_lost = false;
-    var test_listener = false;
+    var test_listener_got = false;
+    var test_listener_lost = false;
 
     function TargetDownHandler(event) {
       logger("Target receive event: " + event.type);
       logger("Send pointerCapture to Mediator");
       mediator.setPointerCapture(event.pointerId);
       logger("setPointerCapture was executed");
       test_down_got = true;
     }
@@ -36,19 +37,21 @@ https://bugzilla.mozilla.org/show_bug.cg
       logger("Try send releasePointerCapture from Mediator");
       mediator.releasePointerCapture(event.pointerId);
       test_mediator_got = true;
     }
     function MediatorLostPCHandler(event) {
       logger("Mediator receive event: " + event.type);
       test_mediator_lost = true;
     }
-    function ListenerHandler(event) {
-      logger("Receive event on Listener: " + event.type);
-      test_listener = true;
+    function ListenerGotHandler(event) {
+      test_listener_got = true;
+    }
+    function ListenerLostHandler(event) {
+      test_listener_lost = true;
     }
     function logger(message) {
       console.log(message);
       var log = document.getElementById('log');
       log.innerHTML = message + "<br>" + log.innerHTML;
     }
 
     function prepareTest() {
@@ -58,29 +61,31 @@ https://bugzilla.mozilla.org/show_bug.cg
     {
       logger("executeTest");
       target = document.getElementById("target");
       mediator = document.getElementById("mediator");
       listener = document.getElementById("listener");
       target.addEventListener("pointerdown",          TargetDownHandler,      false);
       mediator.addEventListener("gotpointercapture",  MediatorGotPCHandler,   false);
       mediator.addEventListener("lostpointercapture", MediatorLostPCHandler,  false);
-      listener.addEventListener("gotpointercapture",  ListenerHandler, false);
-      listener.addEventListener("lostpointercapture", ListenerHandler, false);
+      listener.addEventListener("gotpointercapture",  ListenerGotHandler,     false);
+      listener.addEventListener("lostpointercapture", ListenerLostHandler,    false);
       var rect = target.getBoundingClientRect();
       synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
       synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
       synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
+      synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointerup"});
       finishTest();
     }
     function finishTest() {
       parent.is(test_down_got,      true,  "Part 4: pointerdown event should be received");
       parent.is(test_mediator_got,  true,  "Part 4: gotpointercapture event should be received by Mediator");
       parent.is(test_mediator_lost, true,  "Part 4: lostpointercapture event should be received by Mediator");
-      parent.is(test_listener,      false, "Part 4: listener should not receive any events");
+      parent.is(test_listener_got,  true,  "Part 4: gotpointercapture event should be received by listener");
+      parent.is(test_listener_lost, true,  "Part 4: lostpointercapture event should be received by listener");
       logger("finishTest");
       parent.finishTest();
     }
   </script>
 </head>
 <body onload="prepareTest()">
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 4</a>
   <p id="display"></p>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/input/placeholdershown-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style-shown.css'>
+  <body>
+    <input class='shown-ref' value='foo'>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/input/placeholdershown.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style-shown.css'>
+  <body>
+    <input class='shown' placeholder='foo'>
+  </body>
+</html>
--- a/layout/reftests/css-placeholder/input/reftest.list
+++ b/layout/reftests/css-placeholder/input/reftest.list
@@ -15,13 +15,14 @@ needs-focus == placeholder-blur.html pla
 == placeholder-empty-string.html placeholder-empty-string-ref.html
 == placeholder-add.html placeholder-simple-ref.html
 == placeholder-removal.html input-ref.html
 == placeholder-value-set.html placeholder-value-ref.html
 == placeholder-value-unset.html placeholder-simple-ref.html
 == placeholder-value-reset.html placeholder-simple-ref.html
 == placeholder-type-change-1.html placeholder-simple-ref.html
 == placeholder-type-change-2.html placeholder-button-ref.html
+== placeholdershown.html placeholdershown-ref.html
 == css-display.html placeholder-simple-ref.html
 # We can't check except by verifying that the output is different.
 # Same reasons as focus issues explained above.
 != css-opacity.html placeholder-simple-ref.html
 != css-text-align.html placeholder-simple-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/input/style-shown.css
@@ -0,0 +1,21 @@
+input::-moz-placeholder {
+  color: green;
+  opacity: 1.0;
+}
+
+input:placeholder-shown {
+  -moz-appearance: none;
+  color: -moz-FieldText;
+  background-color: red;
+}
+
+input:placeholder-shown.shown,
+input.shown-ref {
+  -moz-appearance: none;
+  color: green;
+  background-color: #c7c7c7;
+  font-style: italic;
+  border: 2px solid green;
+  height: 200px;
+  width: 200px;
+}
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/textarea/placeholdershown-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style-shown.css'>
+  <body>
+    <textarea class='shown-ref'>foo</textarea>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/textarea/placeholdershown.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <link rel='stylesheet' type='text/css' href='style-shown.css'>
+  <body>
+    <textarea class='shown' placeholder='foo'></textarea>
+  </body>
+</html>
--- a/layout/reftests/css-placeholder/textarea/reftest.list
+++ b/layout/reftests/css-placeholder/textarea/reftest.list
@@ -13,13 +13,14 @@
 needs-focus == placeholder-blur.html placeholder-simple-ref.html
 == placeholder-value.html placeholder-value-ref.html
 == placeholder-empty-string.html placeholder-empty-string-ref.html
 == placeholder-add.html placeholder-simple-ref.html
 == placeholder-removal.html textarea-ref.html
 == placeholder-value-set.html placeholder-value-ref.html
 == placeholder-value-unset.html placeholder-simple-ref.html
 == placeholder-value-reset.html placeholder-simple-ref.html
+== placeholdershown.html placeholdershown-ref.html
 == css-resize.html css-resize-ref.html
 == css-display.html placeholder-simple-ref.html
 # We can't check except by verifying that the output is different.
 # Same reasons as focus issues explained above.
 != css-opacity.html placeholder-simple-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-placeholder/textarea/style-shown.css
@@ -0,0 +1,22 @@
+textarea::-moz-placeholder {
+  color: green;
+  opacity: 1.0;
+}
+
+textarea:placeholder-shown {
+  -moz-appearance: none;
+  color: -moz-FieldText;
+  background-color: red;
+}
+
+textarea:placeholder-shown.shown,
+textarea.shown-ref {
+  -moz-appearance: none;
+  color: green;
+  background-color: #c7c7c7;
+  font-style: italic;
+  border: 2px solid green;
+  height: 200px;
+  width: 200px;
+}
+
--- a/layout/reftests/svg/as-image/reftest.list
+++ b/layout/reftests/svg/as-image/reftest.list
@@ -132,20 +132,16 @@ fuzzy-if(B2G,68,4) == list-simple-1.html
 == svg-image-simple-3.svg lime100x100.svg
 
 # tests for <svg> files that include themselves as an <image>
 == svg-image-recursive-1a.svg  svg-image-recursive-1-ref.svg
 == svg-image-recursive-1b.svg  svg-image-recursive-1-ref.svg
 == svg-image-recursive-2a.svg  svg-image-recursive-2-ref.svg
 == svg-image-recursive-2b.html svg-image-recursive-2-ref.svg
 
-# test that scripting feature is not supported in images or referenced documents
-skip-if(B2G||Mulet) == svg-image-script-1.svg lime100x100.svg # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-== svg-image-script-2.svg lime100x100.svg
-
 # tests for external resources vs. data URIs in SVG as an image
 == svg-image-datauri-1.html            lime100x100.svg
 HTTP == svg-image-datauri-1.html       lime100x100.svg
 == svg-image-external-1.html           blue100x100.svg
 HTTP == svg-image-external-1.html      blue100x100.svg
 == svg-stylesheet-datauri-1.html       lime100x100.svg
 HTTP == svg-stylesheet-datauri-1.html  lime100x100.svg
 == svg-stylesheet-external-1.html      blue100x100.svg
deleted file mode 100644
--- a/layout/reftests/svg/as-image/script100x100.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
-     width="100" height="100">
-  <defs>
-    <!-- So that other documents can svg:use this one and force it to
-         load before onload -->
-    <g id="empty" />
-
-    <pattern id="p1" patternUnits="userSpaceOnUse" width="100%" height="100%">
-      <rect width="100%" height="100%" fill="lime"/>
-      <rect id="r1" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Script" width="100%" height="100%" fill="orange"/>
-    </pattern>
-  </defs>
-  <rect width="100%" height="100%" fill="lime"/>
-  <rect requiredFeatures="http://www.w3.org/TR/SVG11/feature#Script" width="100%" height="100%" fill="blue"/>
-</svg>
deleted file mode 100644
--- a/layout/reftests/svg/as-image/svg-image-script-1.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg"
-     xmlns:xlink="http://www.w3.org/1999/xlink"
-     width="100" height="100">
-  <rect  width="100%" height="100%" fill="red"/>
-  <image width="100%" height="100%" xlink:href="script100x100.svg"/>
-</svg>
deleted file mode 100644
--- a/layout/reftests/svg/as-image/svg-image-script-2.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg"
-     xmlns:xlink="http://www.w3.org/1999/xlink"
-     width="100" height="100" class="reftest-wait">
-
-  <!-- This <use> just forces our resources file to load before onload fires -->
-  <use xlink:href="script100x100.svg#empty" />
-
-  <rect width="100%" height="100%" fill="red"/>
-  <rect width="100%" height="100%" fill="url(script100x100.svg#p1)"/>
-  <rect id="r1" width="100%" height="100%" fill="transparent"/>
-  <script type="application/javascript">
-    document.addEventListener("MozReftestInvalidate", doTest, false);
-    setTimeout(doTest, 4000); // fallback for running outside reftest
-
-    function doTest() {
-      // force a repaint
-      var r1 = document.getElementById("r1");
-      document.documentElement.removeChild(r1);
-      document.documentElement.removeAttribute('class');
-    }
-  </script>
-</svg>
--- a/layout/reftests/svg/conditions-01.svg
+++ b/layout/reftests/svg/conditions-01.svg
@@ -9,12 +9,10 @@
 
 	<rect width="100%" height="100%" fill="lime"/>
 	
 	<rect systemLanguage="foo" x="50" y="100" width="50" height="50" fill="red"/>
 
 	<rect x="200" y="100" width="50" height="50" fill="red"/>
 	<rect requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient" x="200" y="100" width="50" height="50" fill="lime"/>
 
-	<rect requiredFeatures="foo" x="50" y="200" width="50" height="50" fill="red"/>
-
 	<rect requiredExtensions="foo" x="200" y="200" width="50" height="50" fill="red"/>
 </svg>
--- a/layout/reftests/svg/conditions-04.svg
+++ b/layout/reftests/svg/conditions-04.svg
@@ -4,12 +4,12 @@
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Test that 'use'ing an element with a failing conditional fails</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=614265 -->
 
   <rect id="r1" width="100%" height="100%" fill="lime"/>
-  <rect requiredExtensions="http://example.org/hypothetical" id="r2" width="100%" height="100%" fill="red"/>
+  <rect systemLanguage="x" id="r2" width="100%" height="100%" fill="red"/>
   <use xlink:href="#r1"/>
   <use xlink:href="#r2"/>
 </svg>
--- a/layout/reftests/svg/conditions-05.svg
+++ b/layout/reftests/svg/conditions-05.svg
@@ -1,11 +1,11 @@
 <?xml version="1.0"?>
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<svg xmlns="http://www.w3.org/2000/svg" requiredExtensions="x">
+<svg xmlns="http://www.w3.org/2000/svg" systemLanguage="x">
   <title>Test that conditional processing attributes on outer 'svg' elements are honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <rect width="100%" height="100%" fill="red"/>
 </svg>
deleted file mode 100644
--- a/layout/reftests/svg/conditions-06.svg
+++ /dev/null
@@ -1,69 +0,0 @@
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<svg id="svg-root" width="100%" height="100%"
-  xmlns="http://www.w3.org/2000/svg"
-  xmlns:xlink="http://www.w3.org/1999/xlink" onload="runtest()">
-  <title>Test conditional processing DOM interface</title>
-  <defs>
-    <script>
-      function runtest() {
-        try {
-          var r1 = document.getElementById("r1");
-          var r2 = document.getElementById("r2");
-          var r3 = document.getElementById("r3");
-          var i0 = r1.requiredFeatures.getItem(0);
-          var i1 = r1.requiredFeatures.getItem(1);
-
-          if(i0 != "http://www.w3.org/TR/SVG11/feature#Shape") {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-          if(i1 != "this.is.a.bogus.feature.string") {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-          if(r1.requiredFeatures.numberOfItems != 2) {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-          r2.requiredFeatures.appendItem(i1);
-          if(r1.requiredFeatures.numberOfItems != 2) {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-          if(r2.requiredFeatures.numberOfItems != 1) {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-          r3.requiredFeatures.insertItemBefore(i0,0);
-          if(r3.requiredFeatures.numberOfItems != 2) {
-            r3.setAttribute("fill", "red");
-            return;
-          }
-          if(r1.requiredFeatures.numberOfItems != 2) {
-            r1.removeAttribute("requiredFeatures");
-            return;
-          }
-        } catch(e) {
-          var f = document.getElementById("fail");
-          f.setAttribute("fill", "red");
-        }
-      }
-    </script>
-  </defs>
-
-  <rect width="100%" height="100%" fill="lime"/>
-  <!-- background images -->
-  <rect x="100" y="100" width="100" height="100" fill="lime"/>
-  <rect x="190" y="100" width="100" height="100" fill="lime"/>
-  <rect x="300" y="100" width="100" height="100" fill="red"/>
-
-  <!-- tests -->
-  <rect id="r1" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Shape this.is.a.bogus.feature.string" x="100" y="100" width="100" height="100" fill="red"/>
-  <rect id="r2" x="190" y="100" width="100" height="100" fill="red"/>
-  <rect id="r3" x="300" y="100" width="100" height="100" fill="lime" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Shape"/>
-
-  <rect id="fail" width="100%" height="100%" fill="none"/>
-</svg>
--- a/layout/reftests/svg/conditions-07.svg
+++ b/layout/reftests/svg/conditions-07.svg
@@ -6,35 +6,35 @@
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink" onload="runtest()">
   <title>Test conditional processing DOM interface for foreignObject</title>
   <defs>
     <script>
       function runtest() {
         try {
           var f1 = document.getElementById("f1");
-          var i0 = f1.requiredFeatures.getItem(0);
+          var i0 = f1.systemLanguage.getItem(0);
 
-          if(i0 != "this.is.a.bogus.feature.string") {
+          if(i0 != "x") {
             return;
           }
-          f1.removeAttribute("requiredFeatures");
+          f1.removeAttribute("systemLanguage");
           
         } catch(e) {
           var f = document.getElementById("fail");
           f.setAttribute("fill", "red");
         }
       }
     </script>
   </defs>
 
   <rect width="100%" height="100%" fill="lime"/>
   <!-- background images -->
   <rect x="100" y="100" width="100" height="100" fill="red"/>
 
   <!-- tests -->
-  <foreignObject id="f1" x="100" y="100" width="100" height="100" requiredFeatures="this.is.a.bogus.feature.string">
+  <foreignObject id="f1" x="100" y="100" width="100" height="100" systemLanguage="x">
     <svg>
       <rect width="100%" height="100%" fill="lime"/>
     </svg>
   </foreignObject>
   <rect id="fail" width="100%" height="100%" fill="none"/>
 </svg>
--- a/layout/reftests/svg/dynamic-conditions-01.svg
+++ b/layout/reftests/svg/dynamic-conditions-01.svg
@@ -13,26 +13,21 @@
 
 		var rect1 = document.getElementById("rect1");
 		rect1.setAttribute("systemLanguage", "foo");
 
 		var rect2 = document.getElementById("rect2");
 		rect2.setAttribute("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Gradient");
 
 		var rect3 = document.getElementById("rect3");
-		rect3.setAttribute("requiredFeatures", "foo");
-
-		var rect4 = document.getElementById("rect4");
-		rect4.setAttribute("requiredExtensions", "foo");
+		rect3.setAttribute("requiredExtensions", "foo");
 		}
 	</script>
 
 	<rect width="100%" height="100%" fill="lime"/>
 	
 	<rect id="rect1" x="50" y="100" width="50" height="50" fill="red"/>
 
 	<rect x="200" y="100" width="50" height="50" fill="red"/>
 	<rect id="rect2" x="200" y="100" width="50" height="50" fill="lime"/>
 
 	<rect id="rect3" x="50" y="200" width="50" height="50" fill="red"/>
-
-	<rect id="rect4" x="200" y="200" width="50" height="50" fill="red"/>
 </svg>
--- a/layout/reftests/svg/dynamic-conditions-02.svg
+++ b/layout/reftests/svg/dynamic-conditions-02.svg
@@ -1,11 +1,11 @@
 <?xml version="1.0"?>
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<svg xmlns="http://www.w3.org/2000/svg" onload="this.setAttribute('requiredExtensions', 'x')">
+<svg xmlns="http://www.w3.org/2000/svg" onload="this.setAttribute('systemLanguage', 'x')">
   <title>Test that dynamically changed conditional processing attributes on outer 'svg' elements are honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <rect width="100%" height="100%" fill="red"/>
 </svg>
--- a/layout/reftests/svg/dynamic-conditions-04.svg
+++ b/layout/reftests/svg/dynamic-conditions-04.svg
@@ -1,11 +1,12 @@
 <?xml version="1.0"?>
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<svg xmlns="http://www.w3.org/2000/svg" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient" onload="this.setAttribute('requiredFeatures', 'x')">
+<svg xmlns="http://www.w3.org/2000/svg" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient"
+onload="this.setAttribute('systemLanguage', 'x')">
   <title>Test that dynamically changed conditional processing attributes on outer 'svg' elements are honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <rect width="100%" height="100%" fill="red"/>
 </svg>
--- a/layout/reftests/svg/dynamic-conditions-06.svg
+++ b/layout/reftests/svg/dynamic-conditions-06.svg
@@ -7,17 +7,17 @@
   <title>Test that changing conditional processing attributes dynamically on outer 'svg' elements while redraw is suspended is honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <script>
     function f() {
       var svg = document.documentElement;
       svg.suspendRedraw(10000);
       setTimeout(function() {
-        svg.setAttribute("requiredFeatures", "x");
+        svg.setAttribute("systemLanguage", "x");
         svg.unsuspendRedrawAll();
         setTimeout(function() {
           svg.removeAttribute("class");
         }, 1);
       }, 1);
     }
   </script>
   <rect width="100%" height="100%" fill="red"/>
--- a/layout/reftests/svg/dynamic-conditions-09.svg
+++ b/layout/reftests/svg/dynamic-conditions-09.svg
@@ -1,23 +1,24 @@
 <?xml version="1.0"?>
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient">
+<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()"
+systemLanguage="en">
   <title>Test that changing conditional processing attributes dynamically on outer 'svg' elements while redraw is suspended is honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <script>
     function f() {
       var svg = document.documentElement;
       svg.suspendRedraw(10000);
       setTimeout(function() {
-        svg.setAttribute("requiredFeatures", "x");
+        svg.setAttribute("systemLanguage", "x");
         svg.unsuspendRedrawAll();
         setTimeout(function() {
           svg.removeAttribute("class");
         }, 1);
       }, 1);
     }
   </script>
   <rect width="100%" height="100%" fill="red"/>
--- a/layout/reftests/svg/dynamic-conditions-10.svg
+++ b/layout/reftests/svg/dynamic-conditions-10.svg
@@ -7,17 +7,17 @@
   <title>Test that changing conditional processing attributes dynamically while redraw is suspended is honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <script>
     function f() {
       var svg = document.documentElement;
       svg.suspendRedraw(10000);
       setTimeout(function() {
-        document.getElementById("r").setAttribute("requiredFeatures", "x");
+        document.getElementById("r").setAttribute("systemLanguage", "x");
         svg.unsuspendRedrawAll();
         setTimeout(function() {
           svg.removeAttribute("class");
         }, 1);
       }, 1);
     }
   </script>
   <rect id="r" width="100%" height="100%" fill="red"/>
--- a/layout/reftests/svg/dynamic-conditions-13.svg
+++ b/layout/reftests/svg/dynamic-conditions-13.svg
@@ -7,18 +7,18 @@
   <title>Test that changing conditional processing attributes dynamically elements while redraw is suspended is honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
 
   <script>
     function f() {
       var svg = document.documentElement;
       svg.suspendRedraw(10000);
       setTimeout(function() {
-        document.getElementById("r").setAttribute("requiredFeatures", "x");
+        document.getElementById("r").setAttribute("systemLanguage", "x");
         svg.unsuspendRedrawAll();
         setTimeout(function() {
           svg.removeAttribute("class");
         }, 1);
       }, 1);
     }
   </script>
-  <rect id="r" width="100%" height="100%" fill="red" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient"/>
+  <rect id="r" width="100%" height="100%" fill="red" systemLanguage="en"/>
 </svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -43,17 +43,16 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(
 == clipPath-basic-07.svg pass.svg
 == clipPath-winding-01.svg pass.svg
 == clip-surface-clone-01.svg clip-surface-clone-01-ref.svg
 == conditions-01.svg pass.svg
 == conditions-02.svg pass.svg
 == conditions-03.svg pass.svg
 == conditions-04.svg pass.svg
 random-if(Mulet) == conditions-05.svg about:blank # bug 1178062
-== conditions-06.svg pass.svg
 == conditions-07.svg pass.svg
 fuzzy-if(skiaContent,1,320) == conditions-08.svg conditions-08-ref.svg
 == conditions-09.svg conditions-09-ref.svg
 == currentColor-01.svg pass.svg
 == currentColor-02.svg pass.svg
 == currentColor-03.svg pass.svg
 == data-uri-with-filter-01.xhtml data-uri-with-filter-01-ref.svg
 == data-uri-with-gradient-01.xhtml data-uri-with-gradient-01-ref.svg
--- a/layout/reftests/svg/svg-integration/conditions-outer-svg-01.xhtml
+++ b/layout/reftests/svg/svg-integration/conditions-outer-svg-01.xhtml
@@ -7,12 +7,12 @@
 <head>
   <title>Test that conditional processing attributes on outer 'svg' elements are honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
   <style>svg { position: absolute; top: 0; left: 0; height: 100%; width: 100% }</style>
 </head>
 <body>
 
 <svg:svg><svg:rect width="100%" height="100%" fill="lime"/></svg:svg>
-<svg:svg requiredExtensions="x"><svg:rect width="100%" height="100%" fill="red"/></svg:svg>
+<svg:svg systemLanguage="x"><svg:rect width="100%" height="100%" fill="red"/></svg:svg>
 
 </body>
 </html>
--- a/layout/reftests/svg/svg-integration/dynamic-conditions-outer-svg-03.xhtml
+++ b/layout/reftests/svg/svg-integration/dynamic-conditions-outer-svg-03.xhtml
@@ -4,15 +4,15 @@
 -->
 <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:svg="http://www.w3.org/2000/svg">
 <head>
   <title>Test that conditional processing attributes on outer 'svg' elements are honored</title>
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
   <style>svg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</style>
 </head>
-<body onload="document.getElementById('a').setAttribute('requiredFeatures', 'x')">
+<body onload="document.getElementById('a').setAttribute('systemLanguage', 'x')">
 
 <svg:svg><svg:rect width="100%" height="100%" fill="lime"/></svg:svg>
 <svg:svg id="a" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Gradient"><svg:rect width="100%" height="100%" fill="red"/></svg:svg>
 
 </body>
 </html>
--- a/layout/reftests/svg/switch-01.svg
+++ b/layout/reftests/svg/switch-01.svg
@@ -39,24 +39,18 @@
 	<switch>
 		<!-- test matching required features -->
 		<rect requiredFeatures="http://www.w3.org/TR/SVG11/feature#CoreAttribute  http://www.w3.org/TR/SVG11/feature#Gradient"
 			  x="50" y="200" width="50" height="50" fill="lime"/>
 		<rect x="50" y="200" width="50" height="50" fill="red"/>
 		<rect x="50" y="200" width="50" height="50" fill="red"/>
 	</switch>
 
-	<rect x="200" y="200" width="50" height="50" fill="red"/>
-	<switch>
-		<!-- test non-matching required features -->
-		<rect requiredFeatures="foo" x="200" y="200" width="50" height="50" fill="red"/>
-		<rect x="200" y="200" width="50" height="50" fill="lime"/>
-		<rect x="200" y="200" width="50" height="50" fill="red"/>
-		<rect x="200" y="200" width="50" height="50" fill="red"/>
-	</switch>
+	<!-- this rectangle intentionally left green -->
+	<rect x="200" y="200" width="50" height="50" fill="lime"/>
 
 	<rect x="50" y="300" width="50" height="50" fill="red"/>
 	<switch>
 		<!-- test non-matching required extensions -->
 		<rect requiredExtensions="foo" x="50" y="300" width="50" height="50" fill="red"/>
 		<rect x="50" y="300" width="50" height="50" fill="lime"/>
 		<rect x="50" y="300" width="50" height="50" fill="red"/>
 		<rect x="50" y="300" width="50" height="50" fill="red"/>
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -220,16 +220,18 @@ CSS_STATE_PSEUDO_CLASS(mozMathIncrementS
 // http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
 CSS_STATE_PSEUDO_CLASS(required, ":required", 0, "", NS_EVENT_STATE_REQUIRED)
 CSS_STATE_PSEUDO_CLASS(optional, ":optional", 0, "", NS_EVENT_STATE_OPTIONAL)
 CSS_STATE_PSEUDO_CLASS(valid, ":valid", 0, "", NS_EVENT_STATE_VALID)
 CSS_STATE_PSEUDO_CLASS(invalid, ":invalid", 0, "", NS_EVENT_STATE_INVALID)
 CSS_STATE_PSEUDO_CLASS(inRange, ":in-range", 0, "", NS_EVENT_STATE_INRANGE)
 CSS_STATE_PSEUDO_CLASS(outOfRange, ":out-of-range", 0, "", NS_EVENT_STATE_OUTOFRANGE)
 CSS_STATE_PSEUDO_CLASS(defaultPseudo, ":default", 0, "", NS_EVENT_STATE_DEFAULT)
+CSS_STATE_PSEUDO_CLASS(placeholderShown, ":placeholder-shown", 0, "",
+                       NS_EVENT_STATE_PLACEHOLDERSHOWN)
 CSS_STATE_PSEUDO_CLASS(mozReadOnly, ":-moz-read-only", 0, "",
                        NS_EVENT_STATE_MOZ_READONLY)
 CSS_STATE_PSEUDO_CLASS(mozReadWrite, ":-moz-read-write", 0, "",
                        NS_EVENT_STATE_MOZ_READWRITE)
 CSS_STATE_PSEUDO_CLASS(mozSubmitInvalid, ":-moz-submit-invalid", 0, "",
                        NS_EVENT_STATE_MOZ_SUBMITINVALID)
 CSS_STATE_PSEUDO_CLASS(mozUIInvalid, ":-moz-ui-invalid", 0, "",
                        NS_EVENT_STATE_MOZ_UI_INVALID)
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2872,22 +2872,26 @@ nsCSSValueFloatColor::operator==(nsCSSVa
          mAlpha == aOther.mAlpha;
 }
 
 nscolor
 nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
 {
   MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
 
+  // We should clamp each component value since eCSSUnit_PercentageRGBColor
+  // and eCSSUnit_PercentageRGBAColor may store values greater than 1.0.
   if (aUnit == eCSSUnit_PercentageRGBColor ||
       aUnit == eCSSUnit_PercentageRGBAColor) {
-    return NS_RGBA(NSToIntRound(mComponent1 * 255.0f),
-                   NSToIntRound(mComponent2 * 255.0f),
-                   NSToIntRound(mComponent3 * 255.0f),
-                   NSToIntRound(mAlpha * 255.0f));
+    return NS_RGBA(
+      // We need to clamp before multiplying by 255.0f to avoid overflow.
+      NSToIntRound(mozilla::clamped(mComponent1, 0.0f, 1.0f) * 255.0f),
+      NSToIntRound(mozilla::clamped(mComponent2, 0.0f, 1.0f) * 255.0f),
+      NSToIntRound(mozilla::clamped(mComponent3, 0.0f, 1.0f) * 255.0f),
+      NSToIntRound(mozilla::clamped(mAlpha, 0.0f, 1.0f) * 255.0f));
   }
 
   // HSL color
   MOZ_ASSERT(aUnit == eCSSUnit_HSLColor ||
              aUnit == eCSSUnit_HSLAColor);
   nscolor hsl = NS_HSL2RGB(mComponent1, mComponent2, mComponent3);
   return NS_RGBA(NS_GET_R(hsl),
                  NS_GET_G(hsl),
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -373,18 +373,24 @@ enum nsCSSUnit {
 
   eCSSUnit_EnumColor           = 80,   // (int) enumerated color (kColorKTable)
   eCSSUnit_RGBColor            = 81,   // (nscolor) an opaque RGBA value specified as rgb()
   eCSSUnit_RGBAColor           = 82,   // (nscolor) an RGBA value specified as rgba()
   eCSSUnit_HexColor            = 83,   // (nscolor) an opaque RGBA value specified as #rrggbb
   eCSSUnit_ShortHexColor       = 84,   // (nscolor) an opaque RGBA value specified as #rgb
   eCSSUnit_HexColorAlpha       = 85,   // (nscolor) an opaque RGBA value specified as #rrggbbaa
   eCSSUnit_ShortHexColorAlpha  = 86,   // (nscolor) an opaque RGBA value specified as #rgba
-  eCSSUnit_PercentageRGBColor  = 87,   // (nsCSSValueFloatColor*)
-  eCSSUnit_PercentageRGBAColor = 88,   // (nsCSSValueFloatColor*)
+  eCSSUnit_PercentageRGBColor  = 87,   // (nsCSSValueFloatColor*) an opaque
+                                       // RGBA value specified as rgb() with
+                                       // percentage components. Values over
+                                       // 100% are allowed.
+  eCSSUnit_PercentageRGBAColor = 88,   // (nsCSSValueFloatColor*) an RGBA value
+                                       // specified as rgba() with percentage
+                                       // components. Values over 100% are
+                                       // allowed.
   eCSSUnit_HSLColor            = 89,   // (nsCSSValueFloatColor*)
   eCSSUnit_HSLAColor           = 90,   // (nsCSSValueFloatColor*)
 
   eCSSUnit_Percent      = 100,     // (float) 1.0 == 100%) value is percentage of something
   eCSSUnit_Number       = 101,     // (float) value is numeric (usually multiplier, different behavior than percent)
 
   // Physical length units
   eCSSUnit_PhysicalMillimeter = 200,   // (float) 1/25.4 inch
@@ -722,16 +728,22 @@ public:
   // Not making this inline because that would force us to include
   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
   // all over.
   imgRequestProxy* GetImageValue(nsIDocument* aDocument) const;
 
   nscoord GetFixedLength(nsPresContext* aPresContext) const;
   nscoord GetPixelLength() const;
 
+  nsCSSValueFloatColor* GetFloatColorValue() const
+  {
+    MOZ_ASSERT(IsFloatColorUnit(), "not a float color value");
+    return mValue.mFloatColor;
+  }
+
   void Reset()  // sets to null
   {
     if (mUnit != eCSSUnit_Null)
       DoReset();
   }
 private:
   void DoReset();
 
@@ -1682,30 +1694,43 @@ private:
   {
     MOZ_COUNT_DTOR(nsCSSValueFloatColor);
   }
 
 public:
   bool operator==(nsCSSValueFloatColor& aOther) const;
 
   nscolor GetColorValue(nsCSSUnit aUnit) const;
+  float Comp1() const { return mComponent1; }
+  float Comp2() const { return mComponent2; }
+  float Comp3() const { return mComponent3; }
+  float Alpha() const { return mAlpha; }
   bool IsNonTransparentColor() const;
 
   void AppendToString(nsCSSUnit aUnit, nsAString& aResult) const;
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   NS_INLINE_DECL_REFCOUNTING(nsCSSValueFloatColor)
 
 private:
-  // FIXME: We should not be clamping specified RGB color components.
-  float mComponent1;  // 0..1 for RGB, 0..360 for HSL
-  float mComponent2;  // 0..1
-  float mComponent3;  // 0..1
-  float mAlpha;       // 0..1
+  // The range of each component is.
+  // [0, 1] for HSLColor and HSLAColor. mComponent1 for hue, mComponent2 for
+  //                                    saturation, mComponent3 for lightness.
+  //                                    [0, 1] for saturation and lightness
+  //                                    represents [0%, 100%].
+  //                                    [0, 1] for hue represents
+  //                                    [0deg, 360deg].
+  //
+  // [-float::max(), float::max()] for PercentageRGBColor, PercentageRGBAColor.
+  //                               1.0 means 100%.
+  float mComponent1;
+  float mComponent2;
+  float mComponent3;
+  float mAlpha;
 
   nsCSSValueFloatColor(const nsCSSValueFloatColor& aOther) = delete;
   nsCSSValueFloatColor& operator=(const nsCSSValueFloatColor& aOther)
                                                                    = delete;
 };
 
 struct nsCSSCornerSizes {
   nsCSSCornerSizes(void);
--- a/mobile/android/chrome/content/browser.css
+++ b/mobile/android/chrome/content/browser.css
@@ -1,17 +1,7 @@
 /* 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/. */
 
-/**
- * Optimization for tabs that are restored lazily. We can save a good amount of
- * memory that to-be-restored tabs would otherwise consume simply by setting
- * their browsers to 'display: none' as that will prevent them from having to
- * create a presentation and the like.
- */
-browser[pending] {
-  display: none;
-}
-
 browser[remote="true"] {
   -moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
 }
\ No newline at end of file
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -52,20 +52,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/LoginManagerContent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
                                   "resource://gre/modules/LoginManagerParent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
 
-if (AppConstants.MOZ_SAFE_BROWSING) {
-  XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
-                                    "resource://gre/modules/SafeBrowsing.jsm");
-}
+XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
+                                  "resource://gre/modules/SafeBrowsing.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
                                   "resource://gre/modules/BrowserUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Sanitizer",
@@ -544,20 +542,18 @@ var BrowserApp = {
       });
 
       InitLater(() => LightWeightThemeWebInstaller.init());
       InitLater(() => SpatialNavigation.init(BrowserApp.deck, null), window, "SpatialNavigation");
       InitLater(() => CastingApps.init(), window, "CastingApps");
       InitLater(() => Services.search.init(), Services, "search");
       InitLater(() => DownloadNotifications.init(), window, "DownloadNotifications");
 
-      if (AppConstants.MOZ_SAFE_BROWSING) {
-        // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
-        InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing");
-      }
+      // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
+      InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing");
 
       InitLater(() => Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager));
       InitLater(() => LoginManagerParent.init(), window, "LoginManagerParent");
 
     }, false);
 
     // Pass caret StateChanged events to ActionBarHandler.
     window.addEventListener("mozcaretstatechanged", e => {
--- a/mobile/android/components/LoginManagerPrompter.js
+++ b/mobile/android/components/LoginManagerPrompter.js
@@ -100,28 +100,33 @@ LoginManagerPrompter.prototype = {
 
   /* ---------- nsILoginManagerPrompter prompts ---------- */
 
   /*
    * init
    *
    */
   init : function (aWindow, aFactory) {
-    this._window = aWindow;
+    this._chromeWindow = this._getChromeWindow(aWindow).wrappedJSObject;
     this._factory = aFactory || null;
+    this._browser = null;
 
     var prefBranch = Services.prefs.getBranch("signon.");
     this._debug = prefBranch.getBoolPref("debug");
     this.log("===== initialized =====");
   },
 
-  setE10sData : function (aBrowser, aOpener) {
-    throw new Error("This should be filled in when Android is multiprocess");
+  set browser(aBrowser) {
+    this._browser = aBrowser;
   },
 
+  // setting this attribute is ignored because Android does not consider
+  // opener windows when displaying login notifications
+  set opener(aOpener) { },
+
   /*
    * promptToSavePassword
    *
    */
   promptToSavePassword : function (aLogin) {
     this._showSaveLoginNotification(aLogin);
       Services.telemetry.getHistogramById("PWMGR_PROMPT_REMEMBER_ACTION").add(PROMPT_DISPLAYED);
   },
@@ -135,20 +140,17 @@ LoginManagerPrompter.prototype = {
    * @param aButtons
    *        Buttons to display with the doorhanger
    * @param aUsername
    *        Username string used in creating a doorhanger action
    * @param aPassword
    *        Password string used in creating a doorhanger action
    */
   _showLoginNotification : function (aBody, aButtons, aUsername, aPassword) {
-    let notifyWin = this._window.top;
-    let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
-    let browser = chromeWin.BrowserApp.getBrowserForWindow(notifyWin);
-    let tabID = chromeWin.BrowserApp.getTabForBrowser(browser).id;
+    let tabID = this._chromeWindow.BrowserApp.getTabForBrowser(this._browser).id;
 
     let actionText = {
       text: aUsername,
       type: "EDIT",
       bundle: { username: aUsername,
       password: aPassword }
     };
 
@@ -329,34 +331,35 @@ LoginManagerPrompter.prototype = {
   },
 
   /*
    * _getChromeWindow
    *
    * Given a content DOM window, returns the chrome window it's in.
    */
   _getChromeWindow: function (aWindow) {
+    if (aWindow instanceof Ci.nsIDOMChromeWindow)
+      return aWindow;
     var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebNavigation)
       .QueryInterface(Ci.nsIDocShell)
       .chromeEventHandler.ownerDocument.defaultView;
     return chromeWin;
   },
 
   /*
    * _getNativeWindow
    *
    * Returns the NativeWindow to this prompter, or null if there isn't
    * a NativeWindow available (w/ error sent to logcat).
    */
   _getNativeWindow : function () {
     let nativeWindow = null;
     try {
-      let notifyWin = this._window.top;
-      let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
+      let chromeWin = this._chromeWindow;
       if (chromeWin.NativeWindow) {
         nativeWindow = chromeWin.NativeWindow;
       } else {
         Cu.reportError("NativeWindow not available on window");
       }
 
     } catch (e) {
       // If any errors happen, just assume no native window helper.
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -9,19 +9,17 @@ contract @mozilla.org/network/protocol/a
 contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=downloads {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=reader {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=feedback {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=privatebrowsing {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 #ifdef MOZ_SERVICES_HEALTHREPORT
 contract @mozilla.org/network/protocol/about;1?what=healthreport {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 #endif
-#ifdef MOZ_SAFE_BROWSING
 contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9}
-#endif
 contract @mozilla.org/network/protocol/about;1?what=accounts {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 contract @mozilla.org/network/protocol/about;1?what=logins {322ba47e-7047-4f71-aebf-cb7d69325cd9}
 
 # DirectoryProvider.js
 component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js
 contract @mozilla.org/browser/directory-provider;1 {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b}
 category xpcom-directory-providers browser-directory-provider @mozilla.org/browser/directory-provider;1
 
--- a/mobile/android/confvars.sh
+++ b/mobile/android/confvars.sh
@@ -18,18 +18,16 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/a
 MOZ_ANDROID_MIN_SDK_VERSION=15
 
 # There are several entry points into the Firefox application.  These are the names of some of the classes that are
 # listed in the Android manifest.  They are specified in here to avoid hard-coding them in source code files.
 MOZ_ANDROID_APPLICATION_CLASS=org.mozilla.gecko.GeckoApplication
 MOZ_ANDROID_BROWSER_INTENT_CLASS=org.mozilla.gecko.BrowserApp
 MOZ_ANDROID_SEARCH_INTENT_CLASS=org.mozilla.search.SearchActivity
 
-MOZ_SAFE_BROWSING=1
-
 MOZ_NO_SMART_CARDS=1
 
 MOZ_XULRUNNER=
 
 MOZ_CAPTURE=1
 MOZ_RAW=1
 
 # use custom widget for html:select
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -417,24 +417,22 @@
 @BINPATH@/components/PACGenerator.manifest
 
 @BINPATH@/components/TVSimulatorService.js
 @BINPATH@/components/TVSimulatorService.manifest
 
 ; Modules
 @BINPATH@/modules/*
 
-#ifdef MOZ_SAFE_BROWSING
 ; Safe Browsing
 @BINPATH@/components/nsURLClassifier.manifest
 @BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
 @BINPATH@/components/nsUrlClassifierLib.js
 @BINPATH@/components/url-classifier.xpt
-#endif
 
 ; Private Browsing
 @BINPATH@/components/privatebrowsing.xpt
 @BINPATH@/components/PrivateBrowsing.manifest
 @BINPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js
 
 ; Security Reports
 @BINPATH@/components/SecurityReporter.manifest
--- a/old-configure.in
+++ b/old-configure.in
@@ -2334,17 +2334,16 @@ VPX_USE_YASM=
 VPX_ASFLAGS=
 VPX_AS_CONVERSION=
 VPX_X86_ASM=
 VPX_ARM_ASM=
 LIBJPEG_TURBO_AS=
 LIBJPEG_TURBO_ASFLAGS=
 MOZ_PREF_EXTENSIONS=1
 MOZ_REFLOW_PERF=
-MOZ_SAFE_BROWSING=
 MOZ_SPELLCHECK=1
 MOZ_TOOLKIT_SEARCH=1
 MOZ_UI_LOCALE=en-US
 MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 MOZ_NO_SMART_CARDS=
@@ -4300,34 +4299,18 @@ then
 fi
 
 if test -n "$MOZ_SYSTEM_SQLITE"; then
     AC_DEFINE(MOZ_SYSTEM_SQLITE)
 fi
 AC_SUBST(MOZ_SYSTEM_SQLITE)
 
 dnl ========================================================
-dnl = Enable safe browsing (anti-phishing)
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(safe-browsing,
-[  --enable-safe-browsing  Enable safe browsing (anti-phishing) implementation],
-    MOZ_SAFE_BROWSING=1,
-    MOZ_SAFE_BROWSING= )
-if test -n "$MOZ_SAFE_BROWSING"; then
-    AC_DEFINE(MOZ_SAFE_BROWSING)
-fi
-AC_SUBST(MOZ_SAFE_BROWSING)
-
-dnl ========================================================
 dnl = Enable url-classifier
 dnl ========================================================
-dnl Implicitly enabled by default if building with safe-browsing
-if test -n "$MOZ_SAFE_BROWSING"; then
-    MOZ_URL_CLASSIFIER=1
-fi
 MOZ_ARG_ENABLE_BOOL(url-classifier,
 [  --enable-url-classifier Enable url classifier module],
     MOZ_URL_CLASSIFIER=1,
     MOZ_URL_CLASSIFIER= )
 if test -n "$MOZ_URL_CLASSIFIER"; then
     AC_DEFINE(MOZ_URL_CLASSIFIER)
 fi
 AC_SUBST(MOZ_URL_CLASSIFIER)
--- a/services/sync/modules-testing/fakeservices.js
+++ b/services/sync/modules-testing/fakeservices.js
@@ -17,16 +17,30 @@ Cu.import("resource://services-sync/reco
 Cu.import("resource://services-sync/util.js");
 
 var btoa = Cu.import("resource://gre/modules/Log.jsm").btoa;
 
 this.FakeFilesystemService = function FakeFilesystemService(contents) {
   this.fakeContents = contents;
   let self = this;
 
+  // Save away the unmocked versions of the functions we replace here for tests
+  // that really want the originals. As this may be called many times per test,
+  // we must be careful to not replace them with ones we previously replaced.
+  // (And WTF are we bothering with these mocks in the first place? Is the
+  // performance of the filesystem *really* such that it outweighs the downside
+  // of not running our real JSON functions in the tests? Eg, these mocks don't
+  // always throw exceptions when the real ones do. Anyway...)
+  for (let name of ["jsonSave", "jsonLoad", "jsonMove", "jsonRemove"]) {
+    let origName = "_real_" + name;
+    if (!Utils[origName]) {
+      Utils[origName] = Utils[name];
+    }
+  }
+
   Utils.jsonSave = function jsonSave(filePath, that, obj, callback) {
     let json = typeof obj == "function" ? obj.call(that) : obj;
     self.fakeContents["weave/" + filePath + ".json"] = JSON.stringify(json);
     callback.call(that);
   };
 
   Utils.jsonLoad = function jsonLoad(filePath, that, cb) {
     let obj;
--- a/services/sync/modules/telemetry.js
+++ b/services/sync/modules/telemetry.js
@@ -13,16 +13,17 @@ Cu.import("resource://services-sync/main
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-common/observers.js");
 Cu.import("resource://services-common/async.js");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://gre/modules/TelemetryController.jsm");
 Cu.import("resource://gre/modules/FxAccounts.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/osfile.jsm", this);
 
 let constants = {};
 Cu.import("resource://services-sync/constants.js", constants);
 
 var fxAccountsCommon = {};
 Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
 
 XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
@@ -45,16 +46,24 @@ const TOPICS = [
 ];
 
 const PING_FORMAT_VERSION = 1;
 
 // The set of engines we record telemetry for - any other engines are ignored.
 const ENGINES = new Set(["addons", "bookmarks", "clients", "forms", "history",
                          "passwords", "prefs", "tabs"]);
 
+// A regex we can use to replace the profile dir in error messages. We use a
+// regexp so we can simply replace all case-insensitive occurences.
+// This escaping function is from:
+// https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
+const reProfileDir = new RegExp(
+        OS.Constants.Path.profileDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
+        "gi");
+
 // is it a wrapped auth error from browserid_identity?
 function isBrowerIdAuthError(error) {
   // I can't think of what could throw on String conversion
   // but we have absolutely no clue about the type, and
   // there's probably some things out there that would
   try {
     if (String(error).startsWith("AuthenticationError")) {
       return true;
@@ -68,17 +77,19 @@ function transformError(error, engineNam
     return { name: "shutdownerror" };
   }
 
   if (typeof error === "string") {
     if (error.startsWith("error.")) {
       // This is hacky, but I can't imagine that it's not also accurate.
       return { name: "othererror", error };
     }
-
+    // There's a chance the profiledir is in the error string which is PII we
+    // want to avoid including in the ping.
+    error = error.replace(reProfileDir, "[profileDir]");
     return { name: "unexpectederror", error };
   }
 
   if (error.failureCode) {
     return { name: "othererror", error: error.failureCode };
   }
 
   if (error instanceof AuthenticationError) {
@@ -94,17 +105,18 @@ function transformError(error, engineNam
   }
 
   if (error.result) {
     return { name: "nserror", code: error.result };
   }
 
   return {
     name: "unexpectederror",
-    error: String(error),
+    // as above, remove the profile dir value.
+    error: String(error).replace(reProfileDir, "[profileDir]")
   }
 }
 
 function tryGetMonotonicTimestamp() {
   try {
     return Telemetry.msSinceProcessStart();
   } catch (e) {
     log.warn("Unable to get a monotonic timestamp!");
--- a/services/sync/tests/unit/test_telemetry.js
+++ b/services/sync/tests/unit/test_telemetry.js
@@ -8,16 +8,17 @@ Cu.import("resource://services-sync/reco
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/engines/clients.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 Cu.import("resource://testing-common/services/sync/fxa_utils.js");
 Cu.import("resource://testing-common/services/sync/rotaryengine.js");
+Cu.import("resource://gre/modules/osfile.jsm", this);
 
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 Cu.import("resource://services-sync/util.js");
 
 initTestLogging("Trace");
 
 function SteamStore(engine) {
   Store.call(this, "Steam", engine);
@@ -337,16 +338,52 @@ add_task(function* test_generic_engine_f
       error: String(e)
     });
   } finally {
     Service.engineManager.unregister(engine);
     yield cleanAndGo(server);
   }
 });
 
+add_task(function* test_engine_fail_ioerror() {
+  Service.engineManager.register(SteamEngine);
+  let engine = Service.engineManager.get("steam");
+  engine.enabled = true;
+  let store  = engine._store;
+  let server = serverForUsers({"foo": "password"}, {
+    meta: {global: {engines: {steam: {version: engine.version,
+                                      syncID: engine.syncID}}}},
+    steam: {}
+  });
+  new SyncTestingInfrastructure(server.server);
+  // create an IOError to re-throw as part of Sync.
+  try {
+    // (Note that fakeservices.js has replaced Utils.jsonMove etc, but for
+    // this test we need the real one so we get real exceptions from the
+    // filesystem.)
+    yield Utils._real_jsonMove("file-does-not-exist", "anything", {});
+  } catch (ex) {
+    engine._errToThrow = ex;
+  }
+  ok(engine._errToThrow, "expecting exception");
+
+  try {
+    let ping = yield sync_and_validate_telem(true);
+    equal(ping.status.service, SYNC_FAILED_PARTIAL);
+    let failureReason = ping.engines.find(e => e.name === "steam").failureReason;
+    equal(failureReason.name, "unexpectederror");
+    // ensure the profile dir in the exception message has been stripped.
+    ok(!failureReason.error.includes(OS.Constants.Path.profileDir), failureReason.error);
+    ok(failureReason.error.includes("[profileDir]"), failureReason.error);
+  } finally {
+    Service.engineManager.unregister(engine);
+    yield cleanAndGo(server);
+  }
+});
+
 add_task(function* test_initial_sync_engines() {
   Service.engineManager.register(SteamEngine);
   let engine = Service.engineManager.get("steam");
   engine.enabled = true;
   let store  = engine._store;
   let engines = {};
   // These are the only ones who actually have things to sync at startup.
   let engineNames = ["clients", "bookmarks", "prefs", "tabs"];
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -360,31 +360,33 @@ function synthesizeMouseAtPoint(left, to
     var clickCount = aEvent.clickCount || 1;
     var modifiers = _parseModifiers(aEvent, aWindow);
     var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0;
     var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0;
     var isDOMEventSynthesized =
       ("isSynthesized" in aEvent) ? aEvent.isSynthesized : true;
     var isWidgetEventSynthesized =
       ("isWidgetEventSynthesized" in aEvent) ? aEvent.isWidgetEventSynthesized : false;
-
+    var buttons = ("buttons" in aEvent) ? aEvent.buttons :
+                                          utils.MOUSE_BUTTONS_NOT_SPECIFIED;
     if (("type" in aEvent) && aEvent.type) {
       defaultPrevented = utils.sendMouseEvent(aEvent.type, left, top, button,
                                               clickCount, modifiers, false,
                                               pressure, inputSource,
                                               isDOMEventSynthesized,
-                                              isWidgetEventSynthesized);
+                                              isWidgetEventSynthesized,
+                                              buttons);
     }
     else {
       utils.sendMouseEvent("mousedown", left, top, button, clickCount, modifiers,
                            false, pressure, inputSource, isDOMEventSynthesized,
-                           isWidgetEventSynthesized);
+                           isWidgetEventSynthesized, buttons);
       utils.sendMouseEvent("mouseup", left, top, button, clickCount, modifiers,
                            false, pressure, inputSource, isDOMEventSynthesized,
-                           isWidgetEventSynthesized);
+                           isWidgetEventSynthesized, buttons);
     }
   }
 
   return defaultPrevented;
 }
 
 function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window)
 {
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -37594,16 +37594,40 @@
     "deleted_reftests": {},
     "items": {
       "manual": {
         "pointerevents/pointerevent_element_haspointercapture-manual.html": [
           {
             "path": "pointerevents/pointerevent_element_haspointercapture-manual.html",
             "url": "/pointerevents/pointerevent_element_haspointercapture-manual.html"
           }
+        ],
+        "pointerevents/pointerevent_element_haspointercapture_release_pending_capture-manual.html": [
+          {
+            "path": "pointerevents/pointerevent_element_haspointercapture_release_pending_capture-manual.html",
+            "url": "/pointerevents/pointerevent_element_haspointercapture_release_pending_capture-manual.html"
+          }
+        ],
+        "pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html": [
+          {
+            "path": "pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html",
+            "url": "/pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html"
+          }
+        ],
+        "pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html": [
+          {
+            "path": "pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html",
+            "url": "/pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html"
+          }
+        ],
+        "pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html": [
+          {
+            "path": "pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html",
+            "url": "/pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html"
+          }
         ]
       },
       "reftest": {
         "html/semantics/grouping-content/the-ol-element/reversed-1a.html": [
           {
             "path": "html/semantics/grouping-content/the-ol-element/reversed-1a.html",
             "references": [
               [
--- a/testing/web-platform/meta/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/dom/interfaces.html.ini
@@ -23,19 +23,16 @@
     expected: FAIL
 
   [Document interface: xmlDoc must inherit property "queryAll" with the proper type (35)]
     expected: FAIL
 
   [Document interface: calling queryAll(DOMString) on xmlDoc with too few arguments must throw TypeError]
     expected: FAIL
 
-  [DOMImplementation interface: operation hasFeature()]
-    expected: FAIL
-
   [DocumentFragment interface: operation query(DOMString)]
     expected: FAIL
 
   [DocumentFragment interface: operation queryAll(DOMString)]
     expected: FAIL
 
   [DocumentFragment interface: document.createDocumentFragment() must inherit property "query" with the proper type (7)]
     expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/pointerevents/pointerevent_element_haspointercapture_release_pending_capture-manual.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Element.hasPointerCapture test after the pending pointer capture element releases pointer capture</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script type="text/javascript" src="pointerevent_support.js"></script>
+        <script>
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_pointerEvent = async_test("hasPointerCapture test after the pending pointer capture element releases pointer capture");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (e) {
+                    detected_pointertypes[e.pointerType] = true;
+                    target0.setPointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), true, "After target0.setPointerCapture, target0.hasPointerCapture should return true");
+                    });
+                });
+
+                on_event(target0, "gotpointercapture", function (e) {
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), true, "After target0 received gotpointercapture, target0.hasPointerCapture should return true");
+                    });
+                    target1.setPointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target1.setPointerCapture, target0.hasPointerCapture should return false");
+                        assert_equals(target1.hasPointerCapture(e.pointerId), true, "After target1.setPointerCapture, target1.hasPointerCapture should return true");
+                    });
+                    target1.releasePointerCapture(e.pointerId);
+                    test_pointerEvent.step(function () {
+                        assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target1.releasePointerCapture, target0.hasPointerCapture should be false");
+                        assert_equals(target1.hasPointerCapture(e.pointerId), false, "After target1.releasePointerCapture, target1.hasPointerCapture should be false");
+                    });
+                });
+
+                on_event(target1, "gotpointercapture", function (e) {
+                    test_pointerEvent.step(function () {
+                        assert_true(false, "target1 should never receive gotpointercapture in this test");
+                    });
+                });
+
+                on_event(target0, "lostpointercapture", function (e) {
+                    test_pointerEvent.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Element.hasPointerCapture test after the pending pointer capture element releases pointer capture</h1>
+        <h4>
+            Test Description: This test checks if Element.hasPointerCapture returns value correctly after the pending pointer capture element releases pointer capture
+            <ol>
+                <li> Press black rectangle and do not release
+                <li> Move your pointer to purple rectangle
+                <li> Release the pointer
+            </ol>
+        </h4>
+        <p>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Release pointer capture right after setpointercapture</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="pointerevent_support.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("Release pointer capture right after setpointercapture");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                    target0.releasePointerCapture(event.pointerId);
+                    assert_equals(target0.hasPointerCapture(e.pointerId), false, "After target0.releasePointerCapture, target0.hasPointerCapture should be false");
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_true(false, "target0 shouldn't receive gotpointercapture");
+                    });
+                });
+
+                on_event(target0, "lostpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_true(false, "target0 shouldn't receive lostpointercapture");
+                    });
+                });
+
+                on_event(target0, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Release pointer capture right after setpointercapture</h1>
+        <h4>Test Description:
+            When calling releasePointer right after setPointerCapture method is invoked, the pending pointer capture should be cleared and no element should receive gotpointercapture and lostpointercapture events
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Test overriding the pending pointer capture element</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="pointerevent_support.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("setPointerCapture: override the pending pointer capture element");
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Set capture to target0, target0.hasPointerCapture should be true");
+                    });
+                    target1.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), false, "Set capture to target1, target0.hasPointerCapture should be false");
+                        assert_equals(target1.hasPointerCapture(event.pointerId), true, "Set capture to target1, target1.hasPointerCapture should be true");
+                    });
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    assert_true(false, "target0 shouldn't receive gotpointercapture");
+                });
+
+                on_event(target1, "gotpointercapture", function (event) {
+                    assert_true(true, "target1 should receive gotpointercapture");
+                });
+
+                on_event(target1, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Pointer Event: Test overriding the pending pointer capture element</h1>
+        <h4>Test Description:
+            After an element setPointerCapture, if another element also setPointerCapture and override it, the old pending pointer capture element shouldn't receive any gotpointercapture or lostpointercapture event
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+    <head>
+        <title>setPointerCapture() to the element which already captured the pointer</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="pointerevent_support.js"></script>
+        <script type="text/javascript">
+            var detected_pointertypes = {};
+            add_completion_callback(showPointerTypes);
+            var test_setPointerCapture = async_test("setPointerCapture: set to the element which already captured the pointer");
+            var got_pointer_capture = false;
+
+            function run() {
+                var target0 = document.getElementById("target0");
+                var target1 = document.getElementById("target1");
+
+                on_event(target0, "pointerdown", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    target0.setPointerCapture(event.pointerId);
+                });
+
+                on_event(target0, "gotpointercapture", function (event) {
+                    test_setPointerCapture.step(function () {
+                        assert_equals(got_pointer_capture, false, "Target0 should receive gotpointercapture at the first time it captured the pointer");
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Target 0 received gotpointercapture, target0.hasPointerCapture should be true");
+                    });
+                    got_pointer_capture = true;
+
+                    target0.setPointerCapture(event.pointerId);
+                    test_setPointerCapture.step(function () {
+                        assert_equals(target0.hasPointerCapture(event.pointerId), true, "Set capture to target0, target0.hasPointerCapture should be true");
+                        assert_equals(target1.hasPointerCapture(event.pointerId), false, "Set capture to target0, target1.hasPointerCapture should be false");
+                    });
+                });
+
+                on_event(target0, "pointerup", function (event) {
+                    test_setPointerCapture.done();
+                });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <h1>Pointer Event: setPointerCapture to the element which already captured the pointer</h1>
+        <h4>Test Description:
+            When the setPointerCapture method is invoked, if the target element had already captured the pointer, it should not trigger any gotpointercapture or lostpointercapture event
+            <ol>
+                <li>Press and hold left mouse button over black box
+                <li>Move mouse and release mouse button
+            </ol>
+        </h4>
+        <br>
+        <div id="target0" touch-action:none></div>
+        <div id="target1" touch-action:none></div>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -21,23 +21,21 @@
 
 #include "nsDownloadManager.h"
 #include "DownloadPlatform.h"
 #include "nsDownloadProxy.h"
 #include "rdf.h"
 
 #include "nsTypeAheadFind.h"
 
-#ifdef MOZ_URL_CLASSIFIER
 #include "ApplicationReputation.h"
 #include "nsUrlClassifierDBService.h"
 #include "nsUrlClassifierStreamUpdater.h"
 #include "nsUrlClassifierUtils.h"
 #include "nsUrlClassifierPrefixSet.h"
-#endif
 
 #include "nsBrowserStatusFilter.h"
 #include "mozilla/FinalizationWitnessService.h"
 #include "mozilla/NativeOSFileInternals.h"
 #include "mozilla/AddonContentPolicy.h"
 #include "mozilla/AddonPathService.h"
 
 #if defined(XP_WIN)
@@ -86,17 +84,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsS
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager,
                                          nsDownloadManager::GetSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DownloadPlatform)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTypeAheadFind)
 
-#ifdef MOZ_URL_CLASSIFIER
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ApplicationReputationService,
                                          ApplicationReputationService::GetSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierPrefixSet)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierStreamUpdater)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUrlClassifierUtils, Init)
 
 static nsresult
 nsUrlClassifierDBServiceConstructor(nsISupports *aOuter, REFNSIID aIID,
@@ -111,17 +108,16 @@ nsUrlClassifierDBServiceConstructor(nsIS
         return rv;
     }
     /* NS_ADDREF(inst); */
     rv = inst->QueryInterface(aIID, aResult);
     NS_RELEASE(inst);
 
     return rv;
 }
-#endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUpdateProcessor)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(FinalizationWitnessService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(NativeOSFileInternalsService)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NativeFileWatcherService, Init)
@@ -143,23 +139,21 @@ NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID
 #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
 NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_DOWNLOADMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_DOWNLOADPLATFORM_CID);
 NS_DEFINE_NAMED_CID(NS_DOWNLOAD_CID);
 NS_DEFINE_NAMED_CID(NS_FIND_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_TYPEAHEADFIND_CID);
-#ifdef MOZ_URL_CLASSIFIER
 NS_DEFINE_NAMED_CID(NS_APPLICATION_REPUTATION_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERPREFIXSET_CID);
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERDBSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERSTREAMUPDATER_CID);
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERUTILS_CID);
-#endif
 NS_DEFINE_NAMED_CID(NS_BROWSERSTATUSFILTER_CID);
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
 NS_DEFINE_NAMED_CID(NS_UPDATEPROCESSOR_CID);
 #endif
 NS_DEFINE_NAMED_CID(FINALIZATIONWITNESSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NATIVE_OSFILE_INTERNALS_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_ADDONCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_ADDON_PATH_SERVICE_CID);
@@ -179,23 +173,21 @@ static const Module::CIDEntry kToolkitCI
 #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
   { &kNS_PARENTALCONTROLSSERVICE_CID, false, nullptr, nsParentalControlsServiceConstructor },
 #endif
   { &kNS_DOWNLOADMANAGER_CID, false, nullptr, nsDownloadManagerConstructor },
   { &kNS_DOWNLOADPLATFORM_CID, false, nullptr, DownloadPlatformConstructor },
   { &kNS_DOWNLOAD_CID, false, nullptr, nsDownloadProxyConstructor },
   { &kNS_FIND_SERVICE_CID, false, nullptr, nsFindServiceConstructor },
   { &kNS_TYPEAHEADFIND_CID, false, nullptr, nsTypeAheadFindConstructor },
-#ifdef MOZ_URL_CLASSIFIER
   { &kNS_APPLICATION_REPUTATION_SERVICE_CID, false, nullptr, ApplicationReputationServiceConstructor },
   { &kNS_URLCLASSIFIERPREFIXSET_CID, false, nullptr, nsUrlClassifierPrefixSetConstructor },
   { &kNS_URLCLASSIFIERDBSERVICE_CID, false, nullptr, nsUrlClassifierDBServiceConstructor },
   { &kNS_URLCLASSIFIERSTREAMUPDATER_CID, false, nullptr, nsUrlClassifierStreamUpdaterConstructor },
   { &kNS_URLCLASSIFIERUTILS_CID, false, nullptr, nsUrlClassifierUtilsConstructor },
-#endif
   { &kNS_BROWSERSTATUSFILTER_CID, false, nullptr, nsBrowserStatusFilterConstructor },
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
   { &kNS_UPDATEPROCESSOR_CID, false, nullptr, nsUpdateProcessorConstructor },
 #endif
   { &kFINALIZATIONWITNESSSERVICE_CID, false, nullptr, FinalizationWitnessServiceConstructor },
   { &kNATIVE_OSFILE_INTERNALS_SERVICE_CID, false, nullptr, NativeOSFileInternalsServiceConstructor },
   { &kNS_ADDONCONTENTPOLICY_CID, false, nullptr, AddonContentPolicyConstructor },
   { &kNS_ADDON_PATH_SERVICE_CID, false, nullptr, AddonPathServiceConstructor },
@@ -216,24 +208,22 @@ static const Module::ContractIDEntry kTo
   { NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
 #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
   { NS_PARENTALCONTROLSSERVICE_CONTRACTID, &kNS_PARENTALCONTROLSSERVICE_CID },
 #endif
   { NS_DOWNLOADMANAGER_CONTRACTID, &kNS_DOWNLOADMANAGER_CID },
   { NS_DOWNLOADPLATFORM_CONTRACTID, &kNS_DOWNLOADPLATFORM_CID },
   { NS_FIND_SERVICE_CONTRACTID, &kNS_FIND_SERVICE_CID },
   { NS_TYPEAHEADFIND_CONTRACTID, &kNS_TYPEAHEADFIND_CID },
-#ifdef MOZ_URL_CLASSIFIER
   { NS_APPLICATION_REPUTATION_SERVICE_CONTRACTID, &kNS_APPLICATION_REPUTATION_SERVICE_CID },
   { NS_URLCLASSIFIERPREFIXSET_CONTRACTID, &kNS_URLCLASSIFIERPREFIXSET_CID },
   { NS_URLCLASSIFIERDBSERVICE_CONTRACTID, &kNS_URLCLASSIFIERDBSERVICE_CID },
   { NS_URICLASSIFIERSERVICE_CONTRACTID, &kNS_URLCLASSIFIERDBSERVICE_CID },
   { NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID, &kNS_URLCLASSIFIERSTREAMUPDATER_CID },
   { NS_URLCLASSIFIERUTILS_CONTRACTID, &kNS_URLCLASSIFIERUTILS_CID },
-#endif
   { NS_BROWSERSTATUSFILTER_CONTRACTID, &kNS_BROWSERSTATUSFILTER_CID },
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
   { NS_UPDATEPROCESSOR_CONTRACTID, &kNS_UPDATEPROCESSOR_CID },
 #endif
   { FINALIZATIONWITNESSSERVICE_CONTRACTID, &kFINALIZATIONWITNESSSERVICE_CID },
   { NATIVE_OSFILE_INTERNALS_SERVICE_CONTRACTID, &kNATIVE_OSFILE_INTERNALS_SERVICE_CID },
   { NS_ADDONCONTENTPOLICY_CONTRACTID, &kNS_ADDONCONTENTPOLICY_CID },
   { NS_ADDONPATHSERVICE_CONTRACTID, &kNS_ADDON_PATH_SERVICE_CID },
--- a/toolkit/components/downloads/moz.build
+++ b/toolkit/components/downloads/moz.build
@@ -27,30 +27,26 @@ XPIDL_SOURCES += [
     'nsIDownloadManager.idl',
     'nsIDownloadManagerUI.idl',
     'nsIDownloadProgressListener.idl',
 ]
 
 XPIDL_MODULE = 'downloads'
 
 UNIFIED_SOURCES += [
-    'nsDownloadManager.cpp',
+    'ApplicationReputation.cpp',
+    'chromium/chrome/common/safe_browsing/csd.pb.cc',
+    'nsDownloadManager.cpp'
 ]
 
 # SQLFunctions.cpp cannot be built in unified mode because of Windows headers.
 SOURCES += [
     'SQLFunctions.cpp',
 ]
 
-if CONFIG['MOZ_URL_CLASSIFIER']:
-    UNIFIED_SOURCES += [
-        'ApplicationReputation.cpp',
-        'chromium/chrome/common/safe_browsing/csd.pb.cc'
-    ]
-
 if CONFIG['OS_ARCH'] == 'WINNT':
     # Can't build unified because we need CreateEvent which some IPC code
     # included in LoadContext ends up undefining.
     SOURCES += [
         'nsDownloadScanner.cpp',
     ]
 
 # XXX - Until Suite builds off XULRunner we can't guarantee our implementation
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -516,22 +516,16 @@ this.DownloadIntegration = {
    *           {
    *             shouldBlock: Whether the download should be blocked.
    *             verdict: Detailed reason for the block, according to the
    *                      "Downloads.Error.BLOCK_VERDICT_" constants, or empty
    *                      string if the reason is unknown.
    *           }
    */
   shouldBlockForReputationCheck(aDownload) {
-#ifndef MOZ_URL_CLASSIFIER
-    return Promise.resolve({
-      shouldBlock: false,
-      verdict: "",
-    });
-#else
     let hash;
     let sigInfo;
     let channelRedirects;
     try {
       hash = aDownload.saver.getSha256Hash();
       sigInfo = aDownload.saver.getSignatureInfo();
       channelRedirects = aDownload.saver.getRedirects();
     } catch (ex) {
@@ -562,17 +556,16 @@ this.DownloadIntegration = {
       redirects: channelRedirects },
       function onComplete(aShouldBlock, aRv, aVerdict) {
         deferred.resolve({
           shouldBlock: aShouldBlock,
           verdict: (aShouldBlock && kVerdictMap[aVerdict]) || "",
         });
       });
     return deferred.promise;
-#endif
   },
 
 #ifdef XP_WIN
   /**
    * Checks whether downloaded files should be marked as coming from
    * Internet Zone.
    *
    * @return true if files should be marked
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -55,16 +55,17 @@ DIRS += [
     'startup',
     'statusfilter',
     'telemetry',
     'thumbnails',
     'timermanager',
     'tooltiptext',
     'typeaheadfind',
     'utils',
+    'url-classifier',
     'urlformatter',
     'viewconfig',
     'workerloader',
     'xulstore'
 ]
 
 if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
     DIRS += ['narrate', 'viewsource'];
@@ -82,19 +83,16 @@ if CONFIG['MOZ_FEEDS']:
     DIRS += ['feeds']
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['autocomplete', 'satchel']
 
 if CONFIG['MOZ_TOOLKIT_SEARCH']:
     DIRS += ['search']
 
-if CONFIG['MOZ_URL_CLASSIFIER']:
-    DIRS += ['url-classifier']
-
 DIRS += ['captivedetect']
 
 if CONFIG['OS_TARGET'] != 'Android':
     DIRS += ['terminator']
 
 DIRS += ['build']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -913,25 +913,25 @@ var LoginManagerContent = {
     let mockPassword = { name: newPasswordField.name,
                          value: newPasswordField.value };
     let mockOldPassword = oldPasswordField ?
                             { name: oldPasswordField.name,
                               value: oldPasswordField.value } :
                             null;
 
     // Make sure to pass the opener's top in case it was in a frame.
-    let opener = win.opener ? win.opener.top : null;
+    let openerTopWindow = win.opener ? win.opener.top : null;
 
     messageManager.sendAsyncMessage("RemoteLogins:onFormSubmit",
                                     { hostname: hostname,
                                       formSubmitURL: formSubmitURL,
                                       usernameField: mockUsername,
                                       newPasswordField: mockPassword,
                                       oldPasswordField: mockOldPassword },
-                                    { openerWin: opener });
+                                    { openerTopWindow });
   },
 
   /**
    * Attempt to find the username and password fields in a form, and fill them
    * in using the provided logins and recipes.
    *
    * @param {HTMLFormElement} form
    * @param {bool} autofillForm denotes if we should fill the form in automatically
--- a/toolkit/components/passwordmgr/LoginManagerParent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerParent.jsm
@@ -79,17 +79,17 @@ var LoginManagerParent = {
 
       case "RemoteLogins:onFormSubmit": {
         // TODO Verify msg.target's principals against the formOrigin?
         this.onFormSubmit(data.hostname,
                           data.formSubmitURL,
                           data.usernameField,
                           data.newPasswordField,
                           data.oldPasswordField,
-                          msg.objects.openerWin,
+                          msg.objects.openerTopWindow,
                           msg.target);
         break;
       }
 
       case "RemoteLogins:updateLoginFormPresence": {
         this.updateLoginFormPresence(msg.target, data);
         break;
       }
@@ -282,31 +282,24 @@ var LoginManagerParent = {
     target.messageManager.sendAsyncMessage("RemoteLogins:loginsAutoCompleted", {
       requestId: requestId,
       logins: jsLogins,
     });
   },
 
   onFormSubmit: function(hostname, formSubmitURL,
                          usernameField, newPasswordField,
-                         oldPasswordField, opener,
+                         oldPasswordField, openerTopWindow,
                          target) {
     function getPrompter() {
       var prompterSvc = Cc["@mozilla.org/login-manager/prompter;1"].
                         createInstance(Ci.nsILoginManagerPrompter);
-      // XXX For E10S, we don't want to use the browser's contentWindow
-      // because it's in another process, so we use our chrome window as
-      // the window parent (the content process is responsible for
-      // making sure that its window is not in private browsing mode).
-      // In the same-process case, we can simply use the content window.
-      prompterSvc.init(target.isRemoteBrowser ?
-                          target.ownerDocument.defaultView :
-                          target.contentWindow);
-      if (target.isRemoteBrowser)
-        prompterSvc.setE10sData(target, opener);
+      prompterSvc.init(target.ownerDocument.defaultView);
+      prompterSvc.browser = target;
+      prompterSvc.opener = openerTopWindow;
       return prompterSvc;
     }
 
     function recordLoginUse(login) {
       // Update the lastUsed timestamp and increment the use count.
       let propBag = Cc["@mozilla.org/hash-property-bag;1"].
                     createInstance(Ci.nsIWritablePropertyBag);
       propBag.setProperty("timeLastUsed", Date.now());
--- a/toolkit/components/passwordmgr/nsILoginManagerPrompter.idl
+++ b/toolkit/components/passwordmgr/nsILoginManagerPrompter.idl
@@ -14,28 +14,36 @@ interface nsILoginManagerPrompter : nsIS
   /**
    * Initialize the prompter. Must be called before using other interfaces.
    *
    * @param aWindow
    *        The in which the user is doing some login-related action that's
    *        resulting in a need to prompt them for something. The prompt
    *        will be associated with this window (or, if a notification bar
    *        is being used, topmost opener in some cases).
+   *
+   *        If this window is a content window, the corresponding window and browser
+   *        elements will be calculated. If this window is a chrome window, the
+   *        corresponding browser element needs to be set using setBrowser.
    */
   void init(in nsIDOMWindow aWindow);
 
   /**
-   * If the caller knows which browser this prompter is being created for,
-   * they can call this function to avoid having to calculate it from the
-   * window passed to init.
-   *
-   * @param aBrowser the <browser> to use for this prompter.
-   * @param aOpener the opener to use for this prompter.
+   * The browser this prompter is being created for.
+   * This is required if the init function received a chrome window as argument.
    */
-  void setE10sData(in nsIDOMElement aBrowser, in nsIDOMWindow aOpener);
+  attribute nsIDOMElement browser;
+
+  /**
+   * The opener that was used to open the window passed to init.
+   * The opener can be used to determine in which window the prompt
+   * should be shown. Must be a content window that is not a frame window,
+   * make sure to pass the top window using e.g. window.top.
+   */
+  attribute nsIDOMWindow opener;
 
   /**
    * Ask the user if they want to save a login (Yes, Never, Not Now)
    *
    * @param aLogin
    *        The login to be saved.
    */
   void promptToSavePassword(in nsILoginInfo aLogin);
--- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
@@ -252,18 +252,18 @@ LoginManagerPrompter.prototype = {
       } catch (e) { }
     }
     return this.__ellipsis;
   },
 
 
   // Whether we are in private browsing mode
   get _inPrivateBrowsing() {
-    if (this._window) {
-      return PrivateBrowsingUtils.isContentWindowPrivate(this._window);
+    if (this._chromeWindow) {
+      return PrivateBrowsingUtils.isWindowPrivate(this._chromeWindow);
     }
     // If we don't that we're in private browsing mode if the caller did
     // not provide a window.  The callers which really care about this
     // will indeed pass down a window to us, and for those who don't,
     // we can just assume that we don't want to save the entered login
     // information.
     return true;
   },
@@ -285,17 +285,17 @@ LoginManagerPrompter.prototype = {
                                      Cr.NS_ERROR_NOT_IMPLEMENTED);
 
     this.log("===== prompt() called =====");
 
     if (aDefaultText) {
       aResult.value = aDefaultText;
     }
 
-    return this._promptService.prompt(this._window,
+    return this._promptService.prompt(this._chromeWindow,
            aDialogTitle, aText, aResult, null, {});
   },
 
 
   /**
    * Looks up a username and password in the database. Will prompt the user
    * with a dialog, even if a username and password are found.
    */
@@ -347,17 +347,17 @@ LoginManagerPrompter.prototype = {
           aUsername.value = selectedLogin.username;
           // If the caller provided a password, prefer it.
           if (!aPassword.value)
             aPassword.value = selectedLogin.password;
         }
       }
     }
 
-    var ok = this._promptService.promptUsernameAndPassword(this._window,
+    var ok = this._promptService.promptUsernameAndPassword(this._chromeWindow,
                 aDialogTitle, aText, aUsername, aPassword,
                 checkBoxLabel, checkBox);
 
     if (!ok || !checkBox.value || !hostname)
       return ok;
 
     if (!aPassword.value) {
       this.log("No password entered, so won't offer to save.");
@@ -438,17 +438,17 @@ LoginManagerPrompter.prototype = {
             aPassword.value = foundLogins[i].password;
             // wallet returned straight away, so this mimics that code
             return true;
           }
         }
       }
     }
 
-    var ok = this._promptService.promptPassword(this._window, aDialogTitle,
+    var ok = this._promptService.promptPassword(this._chromeWindow, aDialogTitle,
                                                 aText, aPassword,
                                                 checkBoxLabel, checkBox);
 
     if (ok && checkBox.value && hostname && aPassword.value) {
       var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
                      createInstance(Ci.nsILoginInfo);
       newLogin.init(hostname, null, realm, username,
                     aPassword.value, "", "");
@@ -558,19 +558,19 @@ LoginManagerPrompter.prototype = {
       // Ignore any errors and display the prompt anyway.
       epicfail = true;
       Components.utils.reportError("LoginManagerPrompter: " +
           "Epic fail in promptAuth: " + e + "\n");
     }
 
     var ok = canAutologin;
     if (!ok) {
-      if (this._window)
-        PromptUtils.fireDialogEvent(this._window, "DOMWillOpenModalDialog", this._browser);
-      ok = this._promptService.promptAuth(this._window,
+      if (this._chromeWindow)
+        PromptUtils.fireDialogEvent(this._chromeWindow, "DOMWillOpenModalDialog", this._browser);
+      ok = this._promptService.promptAuth(this._chromeWindow,
                                           aChannel, aLevel, aAuthInfo,
                                           checkboxLabel, checkbox);
     }
 
     // If there's a notification box, use it to allow the user to
     // determine if the login should be saved. If there isn't a
     // notification box, only save the login if the user set the
     // checkbox to do so.
@@ -674,30 +674,37 @@ LoginManagerPrompter.prototype = {
   },
 
 
 
 
   /* ---------- nsILoginManagerPrompter prompts ---------- */
 
 
-
   init : function (aWindow, aFactory) {
-    this._window = aWindow;
+    if (aWindow instanceof Ci.nsIDOMChromeWindow) {
+      this._chromeWindow = aWindow;
+      // needs to be set explicitly using setBrowser
+      this._browser = null;
+    } else {
+      let {win, browser} = this._getChromeWindow(aWindow);
+      this._chromeWindow = win;
+      this._browser = browser;
+    }
+    this._opener = null;
     this._factory = aFactory || null;
-    this._browser = null;
-    this._opener = null;
 
     this.log("===== initialized =====");
   },
 
-  setE10sData : function (aBrowser, aOpener) {
-    if (!(this._window instanceof Ci.nsIDOMChromeWindow))
-      throw new Error("Unexpected call");
+  set browser(aBrowser) {
     this._browser = aBrowser;
+  },
+
+  set opener(aOpener) {
     this._opener = aOpener;
   },
 
   promptToSavePassword : function (aLogin) {
     this.log("promptToSavePassword");
     var notifyObj = this._getPopupNote() || this._getNotifyBox();
     if (notifyObj)
       this._showSaveLoginNotification(notifyObj, aLogin);
@@ -1116,17 +1123,17 @@ LoginManagerPrompter.prototype = {
     var neverButtonText    = this._getLocalizedString(
                                     "neverForSiteButtonText");
     var rememberButtonText = this._getLocalizedString(
                                     "rememberButtonText");
     var notNowButtonText   = this._getLocalizedString(
                                     "notNowButtonText");
 
     this.log("Prompting user to save/ignore login");
-    var userChoice = this._promptService.confirmEx(this._window,
+    var userChoice = this._promptService.confirmEx(this._chromeWindow,
                                         dialogTitle, dialogText,
                                         buttonFlags, rememberButtonText,
                                         notNowButtonText, neverButtonText,
                                         null, {});
     //  Returns:
     //   0 - Save the login
     //   1 - Ignore the login this time
     //   2 - Never save logins for this site
@@ -1248,17 +1255,17 @@ LoginManagerPrompter.prototype = {
     else
       dialogText  = this._getLocalizedString(
                               "updatePasswordMsgNoUser");
 
     var dialogTitle = this._getLocalizedString(
                                 "passwordChangeTitle");
 
     // returns 0 for yes, 1 for no.
-    var ok = !this._promptService.confirmEx(this._window,
+    var ok = !this._promptService.confirmEx(this._chromeWindow,
                             dialogTitle, dialogText, buttonFlags,
                             null, null, null,
                             null, {});
     if (ok) {
       this.log("Updating password for user " + aOldLogin.username);
       this._updateLogin(aOldLogin, aNewLogin);
     }
   },
@@ -1281,17 +1288,17 @@ LoginManagerPrompter.prototype = {
 
     var usernames = logins.map(l => l.username);
     var dialogText  = this._getLocalizedString("userSelectText");
     var dialogTitle = this._getLocalizedString("passwordChangeTitle");
     var selectedIndex = { value: null };
 
     // If user selects ok, outparam.value is set to the index
     // of the selected username.
-    var ok = this._promptService.select(this._window,
+    var ok = this._promptService.select(this._chromeWindow,
                             dialogTitle, dialogText,
                             usernames.length, usernames,
                             selectedIndex);
     if (ok) {
       // Now that we know which login to use, modify its password.
       var selectedLogin = logins[selectedIndex.value];
       this.log("Updating password for user " + selectedLogin.username);
       var newLoginWithUsername = Cc["@mozilla.org/login-manager/loginInfo;1"].
@@ -1326,135 +1333,83 @@ LoginManagerPrompter.prototype = {
       // value as timeLastUsed.
       propBag.setProperty("timePasswordChanged", now);
     }
     propBag.setProperty("timeLastUsed", now);
     propBag.setProperty("timesUsedIncrement", 1);
     this._pwmgr.modifyLogin(login, propBag);
   },
 
-
   /**
-   * Given a content DOM window, returns the chrome window it's in.
+   * Given a content DOM window, returns the chrome window and browser it's in.
    */
   _getChromeWindow: function (aWindow) {
-    // In e10s, aWindow may already be a chrome window.
-    if (aWindow instanceof Ci.nsIDOMChromeWindow)
-      return aWindow;
-    var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIWebNavigation)
-                           .QueryInterface(Ci.nsIDocShell)
-                           .chromeEventHandler.ownerDocument.defaultView;
-    return chromeWin;
+    let windows = Services.wm.getEnumerator(null);
+    while (windows.hasMoreElements()) {
+      let win = windows.getNext();
+      let browser = win.gBrowser.getBrowserForContentWindow(aWindow);
+      if (browser) {
+        return { win, browser };
+      }
+    }
+    return null;
   },
 
-
   _getNotifyWindow: function () {
-
-    try {
-      // Get topmost window, in case we're in a frame.
-      var notifyWin = this._window.top;
-      var isE10s = (notifyWin instanceof Ci.nsIDOMChromeWindow);
-      var useOpener = false;
-
-      // Some sites pop up a temporary login window, which disappears
-      // upon submission of credentials. We want to put the notification
-      // bar in the opener window if this seems to be happening.
-      if (notifyWin.opener) {
-        var chromeDoc = this._getChromeWindow(notifyWin).
-                             document.documentElement;
-
-        var hasHistory;
-        if (isE10s) {
-          if (!this._browser)
-            throw new Error("Expected a browser in e10s");
-          hasHistory = this._browser.canGoBack;
-        } else {
-          var webnav = notifyWin.
-                       QueryInterface(Ci.nsIInterfaceRequestor).
-                       getInterface(Ci.nsIWebNavigation);
-          hasHistory = webnav.sessionHistory.count > 1;
-        }
+    // Some sites pop up a temporary login window, which disappears
+    // upon submission of credentials. We want to put the notification
+    // bar in the opener window if this seems to be happening.
+    if (this._opener) {
+      let chromeDoc = this._chromeWindow.document.documentElement;
 
-        // Check to see if the current window was opened with chrome
-        // disabled, and if so use the opener window. But if the window
-        // has been used to visit other pages (ie, has a history),
-        // assume it'll stick around and *don't* use the opener.
-        if (chromeDoc.getAttribute("chromehidden") && !hasHistory) {
-          this.log("Using opener window for notification bar.");
-          notifyWin = notifyWin.opener;
-          useOpener = true;
-        }
+      // Check to see if the current window was opened with chrome
+      // disabled, and if so use the opener window. But if the window
+      // has been used to visit other pages (ie, has a history),
+      // assume it'll stick around and *don't* use the opener.
+      if (chromeDoc.getAttribute("chromehidden") && !this._browser.canGoBack) {
+        this.log("Using opener window for notification bar.");
+        return this._getChromeWindow(this._opener);
       }
-
-      let browser;
-      if (useOpener && this._opener && isE10s) {
-        // In e10s, we have to reconstruct the opener browser from
-        // the CPOW passed in the message (and then passed to us in
-        // setE10sData).
-        // NB: notifyWin is now the chrome window for the opening
-        // window.
+    }
 
-        browser = notifyWin.gBrowser.getBrowserForContentWindow(this._opener);
-      } else if (isE10s) {
-        browser = this._browser;
-      } else {
-        var chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
-        browser = chromeWin.gBrowser
-                           .getBrowserForDocument(notifyWin.top.document);
-      }
-
-      return { notifyWin: notifyWin, browser: browser };
-
-    } catch (e) {
-      // If any errors happen, just assume no notification box.
-      this.log("Unable to get notify window: " + e.fileName + ":" + e.lineNumber + ": " + e.message);
-      return null;
-    }
+    return { win: this._chromeWindow, browser: this._browser };
   },
 
-
   /**
    * Returns the popup notification to this prompter,
    * or null if there isn't one available.
    */
   _getPopupNote : function () {
     let popupNote = null;
 
     try {
-      let { notifyWin } = this._getNotifyWindow();
+      let { win: notifyWin } = this._getNotifyWindow();
 
-      // Get the chrome window for the content window we're using.
       // .wrappedJSObject needed here -- see bug 422974 comment 5.
-      let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
-
-      popupNote = chromeWin.PopupNotifications;
+      popupNote = notifyWin.wrappedJSObject.PopupNotifications;
     } catch (e) {
       this.log("Popup notifications not available on window");
     }
 
     return popupNote;
   },
 
 
   /**
    * Returns the notification box to this prompter, or null if there isn't
    * a notification box available.
    */
   _getNotifyBox : function () {
     let notifyBox = null;
 
     try {
-      let { notifyWin } = this._getNotifyWindow();
+      let { win: notifyWin } = this._getNotifyWindow();
 
-      // Get the chrome window for the content window we're using.
       // .wrappedJSObject needed here -- see bug 422974 comment 5.
-      let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
-
-      notifyBox = chromeWin.getNotificationBox(notifyWin);
+      notifyBox = notifyWin.wrappedJSObject.getNotificationBox(notifyWin);
     } catch (e) {
       this.log("Notification bars not available on window");
     }
 
     return notifyBox;
   },
 
 
--- a/toolkit/components/passwordmgr/test/browser/browser.ini
+++ b/toolkit/components/passwordmgr/test/browser/browser.ini
@@ -25,17 +25,16 @@ support-files =
   subtst_notifications_4.html
   subtst_notifications_5.html
   subtst_notifications_6.html
   subtst_notifications_8.html
   subtst_notifications_9.html
   subtst_notifications_10.html
   subtst_notifications_change_p.html
 [browser_capture_doorhanger_window_open.js]
-skip-if = e10s # Bug 1266836 - Prompt code is broken with popups in e10s
 support-files =
   subtst_notifications_11.html
   subtst_notifications_11_popup.html
 [browser_username_select_dialog.js]
 support-files =
   subtst_notifications_change_p.html
 [browser_DOMFormHasPassword.js]
 [browser_DOMInputPasswordAdded.js]
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -93,18 +93,16 @@ static NS_DEFINE_CID(kPlacesInitComplete
 static NS_DEFINE_CID(kSessionStoreWindowRestoredCID,
   NS_SESSION_STORE_WINDOW_RESTORED_EVENT_CID);
 static NS_DEFINE_CID(kXPCOMShutdownCID,
   NS_XPCOM_SHUTDOWN_EVENT_CID);  
 #endif //defined(XP_WIN)
 
 using namespace mozilla;
 
-uint32_t gRestartMode = 0;
-
 class nsAppExitEvent : public mozilla::Runnable {
 private:
   RefPtr<nsAppStartup> mService;
 
 public:
   explicit nsAppExitEvent(nsAppStartup *service) : mService(service) {}
 
   NS_IMETHOD Run() override {
@@ -383,22 +381,20 @@ nsAppStartup::Quit(uint32_t aMode)
       }
     }
 
     PROFILER_MARKER("Shutdown start");
     mozilla::RecordShutdownStartTimeStamp();
     mShuttingDown = true;
     if (!mRestart) {
       mRestart = (aMode & eRestart) != 0;
-      gRestartMode = (aMode & 0xF0);
     }
 
     if (!mRestartNotSameProfile) {
       mRestartNotSameProfile = (aMode & eRestartNotSameProfile) != 0;
-      gRestartMode = (aMode & 0xF0);
     }
 
     if (mRestart || mRestartNotSameProfile) {
       // Mark the next startup as a restart.
       PR_SetEnv("MOZ_APP_RESTART=1");
 
       /* Firefox-restarts reuse the process so regular process start-time isn't
          a useful indicator of startup time anymore. */
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10191,10 +10191,17 @@
   },
   "FENNEC_SESSIONSTORE_RESTORING_FROM_BACKUP": {
     "alert_emails": ["jh+bugzilla@buttercookie.de"],
     "expires_in_version": "56",
     "kind": "flag",
     "bug_numbers": [1190627],
     "description": "When restoring tabs on startup, reading from sessionstore.js failed, but sessionstore.bak was read successfully.",
     "cpp_guard": "ANDROID"
+  },
+  "NUMBER_OF_PROFILES": {
+    "alert_emails": ["amarchesini@mozilla.com"],
+    "expires_in_version": "58",
+    "bug_numbers": [1296606],
+    "kind": "count",
+    "description": "Number of named profiles."
   }
 }
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -172,16 +172,17 @@ const DEFAULT_ENVIRONMENT_PREFS = new Ma
   ["network.proxy.ssl", {what: RECORD_PREF_STATE}],
   ["pdfjs.disabled", {what: RECORD_PREF_VALUE}],
   ["places.history.enabled", {what: RECORD_PREF_VALUE}],
   ["privacy.trackingprotection.enabled", {what: RECORD_PREF_VALUE}],
   ["privacy.donottrackheader.enabled", {what: RECORD_PREF_VALUE}],
   ["services.sync.serverURL", {what: RECORD_PREF_STATE}],
   ["security.mixed_content.block_active_content", {what: RECORD_PREF_VALUE}],
   ["security.mixed_content.block_display_content", {what: RECORD_PREF_VALUE}],
+  ["security.sandbox.content.level", {what: RECORD_PREF_VALUE}],
   ["xpinstall.signatures.required", {what: RECORD_PREF_VALUE}],
 ]);
 
 const LOGGER_NAME = "Toolkit.Telemetry";
 
 const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
 const PREF_DISTRIBUTION_ID = "distribution.id";
 const PREF_DISTRIBUTION_VERSION = "distribution.version";
--- a/toolkit/components/telemetry/docs/data/environment.rst
+++ b/toolkit/components/telemetry/docs/data/environment.rst
@@ -311,16 +311,18 @@ The following is a partial list of colle
 - ``browser.search.suggest.enabled``: The "master switch" for search suggestions everywhere in Firefox (search bar, urlbar, etc.). Defaults to true.
 
 - ``browser.urlbar.suggest.searches``: True if search suggestions are enabled in the urlbar. Defaults to false.
 
 - ``browser.urlbar.userMadeSearchSuggestionsChoice``: True if the user has clicked Yes or No in the urlbar's opt-in notification. Defaults to false.
 
 - ``browser.zoom.full``: True if zoom is enabled for both text and images, that is if "Zoom Text Only" is not enabled. Defaults to true. Collection of this preference has been enabled in Firefox 50 and will be disabled again in Firefox 53 (`Bug 979323 <https://bugzilla.mozilla.org/show_bug.cgi?id=979323>`_).
 
+- ``security.sandbox.content.level``: The meanings of the values are OS dependent, but 0 means not sandboxed for all OS. Details of the meanings can be found in the `Firefox prefs file <http://hg.mozilla.org/mozilla-central/file/tip/browser/app/profile/firefox.js>`_.
+
 partner
 -------
 
 If the user is using a partner repack, this contains information identifying the repack being used, otherwise "partnerNames" will be an empty array and other entries will be null. The information may be missing when the profile just becomes available. In Firefox for desktop, the information along with other customizations defined in distribution.ini are processed later in the startup phase, and will be fully applied when "distribution-customization-complete" notification is sent.
 
 Distributions are most reliably identified by the ``distributionId`` field. Partner information can be found in the `partner repacks <https://github.com/mozilla-partners>`_ (`the old one <http://hg.mozilla.org/build/partner-repacks/>`_ is deprecated): it contains one private repository per partner.
 Important values for ``distributionId`` include:
 
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -69,23 +69,16 @@ this.AppConstants = Object.freeze({
 
   MOZ_DATA_REPORTING:
 #ifdef MOZ_DATA_REPORTING
   true,
 #else
   false,
 #endif
 
-  MOZ_SAFE_BROWSING:
-#ifdef MOZ_SAFE_BROWSING
-  true,
-#else
-  false,
-#endif
-
   MOZ_SANDBOX:
 #ifdef MOZ_SANDBOX
   true,
 #else
   false,
 #endif
 
   MOZ_CONTENT_SANDBOX:
--- a/toolkit/modules/subprocess/subprocess_worker_common.js
+++ b/toolkit/modules/subprocess/subprocess_worker_common.js
@@ -222,14 +222,8 @@ onmessage = event => {
 
     self.postMessage({
       msg: "failure",
       msgId,
       error: {},
     });
   });
 };
-
-onclose = event => {
-  io.shutdown();
-
-  self.postMessage({msg: "close"});
-};
--- a/toolkit/modules/subprocess/subprocess_worker_unix.js
+++ b/toolkit/modules/subprocess/subprocess_worker_unix.js
@@ -495,16 +495,17 @@ io = {
 
   shutdown() {
     if (this.running) {
       this.running = false;
 
       this.signal.cleanup();
       this.signal = null;
 
+      self.postMessage({msg: "close"});
       self.close();
     }
   },
 
   getPipe(pipeId) {
     let pipe = this.pipes.get(pipeId);
 
     if (!pipe) {
--- a/toolkit/modules/subprocess/subprocess_worker_win.js
+++ b/toolkit/modules/subprocess/subprocess_worker_win.js
@@ -594,16 +594,17 @@ io = {
 
   shutdown() {
     if (this.running) {
       this.running = false;
 
       this.signal.cleanup();
       this.signal = null;
 
+      self.postMessage({msg: "close"});
       self.close();
     }
   },
 
   getPipe(pipeId) {
     let pipe = this.pipes.get(pipeId);
 
     if (!pipe) {
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -6487,18 +6487,18 @@ AddonInstall.prototype = {
       let win = this.window;
       if (!win && this.browser)
         win = this.browser.ownerDocument.defaultView;
 
       let factory = Cc["@mozilla.org/prompter;1"].
                     getService(Ci.nsIPromptFactory);
       let prompt = factory.getPrompt(win, Ci.nsIAuthPrompt2);
 
-      if (this.browser && this.browser.isRemoteBrowser && prompt instanceof Ci.nsILoginManagerPrompter)
-        prompt.setE10sData(this.browser, null);
+      if (this.browser && prompt instanceof Ci.nsILoginManagerPrompter)
+        prompt.browser = this.browser;
 
       return prompt;
     }
     else if (iid.equals(Ci.nsIChannelEventSink)) {
       return this;
     }
 
     return this.badCertHandler.getInterface(iid);
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -1026,66 +1026,16 @@ function isServiceInstalled() {
     installed = installed == 1;  // convert to bool
     LOG("isServiceInstalled = " + installed);
     return installed;
   }
   return false;
 }
 
 /**
- * Removes the MozUpdater directory that is created when replacing an install
- * with a staged update and leftover MozUpdater-i folders in the tmp directory.
- */
-function cleanUpMozUpdaterDirs() {
-  try {
-    // Remove the MozUpdater directory in the updates/0 directory.
-    var mozUpdaterDir = getUpdatesDir();
-    mozUpdaterDir.append("MozUpdater");
-    if (mozUpdaterDir.exists()) {
-      LOG("cleanUpMozUpdaterDirs - removing MozUpdater directory");
-      mozUpdaterDir.remove(true);
-    }
-  } catch (e) {
-    LOG("cleanUpMozUpdaterDirs - Exception: " + e);
-  }
-
-  try {
-    var tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
-
-    // We used to store MozUpdater-i directories in the temp directory.
-    // We need to remove these directories if we detect that they still exist.
-    // To check if they still exist, we simply check for MozUpdater-1.
-    var mozUpdaterDir1 = tmpDir.clone();
-    mozUpdaterDir1.append("MozUpdater-1");
-    // Only try to delete the left over directories in "$Temp/MozUpdater-i/*" if
-    // MozUpdater-1 exists.
-    if (mozUpdaterDir1.exists()) {
-      LOG("cleanUpMozUpdaterDirs - Removing top level tmp MozUpdater-i " +
-          "directories");
-      let i = 0;
-      let dirEntries = tmpDir.directoryEntries;
-      while (dirEntries.hasMoreElements() && i < 10) {
-        let file = dirEntries.getNext().QueryInterface(Ci.nsILocalFile);
-        if (file.leafName.startsWith("MozUpdater-") && file.leafName != "MozUpdater-1") {
-          file.remove(true);
-          i++;
-        }
-      }
-      // If you enumerate the whole temp directory and the count of deleted
-      // items is less than 10, then delete MozUpdate-1.
-      if (i < 10) {
-        mozUpdaterDir1.remove(true);
-      }
-    }
-  } catch (e) {
-    LOG("cleanUpMozUpdaterDirs - Exception: " + e);
-  }
-}
-
-/**
  * Removes the contents of the updates patch directory and rotates the update
  * logs when present. If the update.log exists in the patch directory this will
  * move the last-update.log if it exists to backup-update.log in the parent
  * directory of the patch directory and then move the update.log in the patch
  * directory to last-update.log in the parent directory of the patch directory.
  *
  * @param aRemovePatchFiles (optional, defaults to true)
  *        When true the update's patch directory contents are removed.
@@ -1134,17 +1084,18 @@ function cleanUpUpdatesDir(aRemovePatchF
           if (linkedFile && linkedFile.exists()) {
             linkedFile.remove(false);
           }
         }
       }
 
       // Now, recursively remove this file.  The recursive removal is needed for
       // Mac OSX because this directory will contain a copy of updater.app,
-      // which is itself a directory.
+      // which is itself a directory and the MozUpdater directory on platforms
+      // other than Windows.
       try {
         f.remove(true);
       } catch (e) {
         LOG("cleanUpUpdatesDir - failed to remove file " + f.path);
       }
     }
   }
   if (AppConstants.platform == "gonk") {
@@ -2145,20 +2096,16 @@ UpdateService.prototype = {
       }
 
       // Something went wrong with the patch application process.
       handleFallbackToCompleteUpdate(update, false);
       let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                      createInstance(Ci.nsIUpdatePrompt);
       prompter.showUpdateError(update);
     }
-
-    // Now trash the MozUpdater directory created when replacing an install with
-    // a staged update.
-    cleanUpMozUpdaterDirs();
   },
 
   /**
    * Register an observer when the network comes online, so we can short-circuit
    * the app.update.interval when there isn't connectivity
    */
   _registerOnlineObserver: function AUS__registerOnlineObserver() {
     if (this._registeredOnlineObserver) {
--- a/toolkit/mozapps/update/updater/launchchild_osx.mm
+++ b/toolkit/mozapps/update/updater/launchchild_osx.mm
@@ -29,24 +29,24 @@ private:
 };
 
 void LaunchChild(int argc, const char** argv)
 {
   MacAutoreleasePool pool;
 
   @try {
     NSString* launchPath = [NSString stringWithUTF8String:argv[0]];
-    NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc];
+    NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc - 1];
     for (int i = 1; i < argc; i++) {
       [arguments addObject:[NSString stringWithUTF8String:argv[i]]];
     }
     [NSTask launchedTaskWithLaunchPath:launchPath
                              arguments:arguments];
   } @catch (NSException* e) {
-    // Ignore any exception.
+    NSLog(@"%@: %@", e.name, e.reason);
   }
 }
 
 void
 LaunchMacPostProcess(const char* aAppBundle)
 {
   MacAutoreleasePool pool;
 
--- a/toolkit/xre/MacLaunchHelper.h
+++ b/toolkit/xre/MacLaunchHelper.h
@@ -6,15 +6,18 @@
 #ifndef MacLaunchHelper_h_
 #define MacLaunchHelper_h_
 
 #include <stdint.h>
 
 #include <unistd.h>
 
 extern "C" {
-  void LaunchChildMac(int aArgc, char** aArgv, uint32_t aRestartType = 0,
-                      pid_t *pid = 0);
-  bool LaunchElevatedUpdate(int argc, char** argv, uint32_t aRestartType = 0,
-                            pid_t* pid = 0);
+  /**
+   * Passing an aPid parameter to LaunchChildMac will wait for the launched
+   * process to terminate. When the process terminates, aPid will be set to the
+   * pid of the terminated process to confirm that it executed successfully.
+   */
+  void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid = 0);
+  bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid = 0);
 }
 
 #endif
--- a/toolkit/xre/MacLaunchHelper.mm
+++ b/toolkit/xre/MacLaunchHelper.mm
@@ -14,87 +14,37 @@
 #include <crt_externs.h>
 #include <ServiceManagement/ServiceManagement.h>
 #include <Security/Authorization.h>
 #include <spawn.h>
 #include <stdio.h>
 
 using namespace mozilla;
 
-namespace {
-cpu_type_t pref_cpu_types[2] = {
-#if defined(__i386__)
-                                 CPU_TYPE_X86,
-#elif defined(__x86_64__)
-                                 CPU_TYPE_X86_64,
-#elif defined(__ppc__)
-                                 CPU_TYPE_POWERPC,
-#endif
-                                 CPU_TYPE_ANY };
-
-cpu_type_t cpu_i386_types[2] = {
-                                 CPU_TYPE_X86,
-                                 CPU_TYPE_ANY };
-
-cpu_type_t cpu_x64_86_types[2] = {
-                                 CPU_TYPE_X86_64,
-                                 CPU_TYPE_ANY };
-} // namespace
-
-void LaunchChildMac(int aArgc, char** aArgv,
-                    uint32_t aRestartType, pid_t *pid)
+void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid)
 {
-  // "posix_spawnp" uses null termination for arguments rather than a count.
-  // Note that we are not duplicating the argument strings themselves.
-  auto argv_copy = MakeUnique<char*[]>(aArgc + 1);
-  for (int i = 0; i < aArgc; i++) {
-    argv_copy[i] = aArgv[i];
-  }
-  argv_copy[aArgc] = NULL;
+  MacAutoreleasePool pool;
 
-  // Initialize spawn attributes.
-  posix_spawnattr_t spawnattr;
-  if (posix_spawnattr_init(&spawnattr) != 0) {
-    printf("Failed to init posix spawn attribute.");
-    return;
-  }
-
-  cpu_type_t *wanted_type = pref_cpu_types;
-  size_t attr_count = ArrayLength(pref_cpu_types);
-
-  if (aRestartType & nsIAppStartup::eRestarti386) {
-    wanted_type = cpu_i386_types;
-    attr_count = ArrayLength(cpu_i386_types);
-  } else if (aRestartType & nsIAppStartup::eRestartx86_64) {
-    wanted_type = cpu_x64_86_types;
-    attr_count = ArrayLength(cpu_x64_86_types);
-  }
-
-  // Set spawn attributes.
-  size_t attr_ocount = 0;
-  if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, wanted_type, &attr_ocount) != 0 ||
-      attr_ocount != attr_count) {
-    printf("Failed to set binary preference on posix spawn attribute.");
-    posix_spawnattr_destroy(&spawnattr);
-    return;
-  }
-
-  // Pass along our environment.
-  char** envp = NULL;
-  char*** cocoaEnvironment = _NSGetEnviron();
-  if (cocoaEnvironment) {
-    envp = *cocoaEnvironment;
-  }
-
-  int result = posix_spawnp(pid, argv_copy[0], NULL, &spawnattr, argv_copy.get(), envp);
-
-  posix_spawnattr_destroy(&spawnattr);
-
-  if (result != 0) {
-    printf("Process spawn failed with code %d!", result);
+  @try {
+    NSString* launchPath = [NSString stringWithUTF8String:aArgv[0]];
+    NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:aArgc - 1];
+    for (int i = 1; i < aArgc; i++) {
+      [arguments addObject:[NSString stringWithUTF8String:aArgv[i]]];
+    }
+    NSTask* child = [NSTask launchedTaskWithLaunchPath:launchPath
+                                             arguments:arguments];
+    if (aPid) {
+      *aPid = [child processIdentifier];
+      // We used to use waitpid to wait for the process to terminate. This is
+      // incompatible with NSTask and we wait for the process to exit here
+      // instead.
+      [child waitUntilExit];
+    }
+  } @catch (NSException* e) {
+    NSLog(@"%@: %@", e.name, e.reason);
   }
 }
 
 BOOL InstallPrivilegedHelper()
 {
   AuthorizationRef authRef = NULL;
   OSStatus status = AuthorizationCreate(NULL,
                                         kAuthorizationEmptyEnvironment,
@@ -171,18 +121,17 @@ void AbortElevatedUpdate()
       NSLog(@"Encountered exception, retrying: %@: %@", e.name, e.reason);
       sleep(1); // Wait 1 second.
       currTry++;
     }
   }
   NSLog(@"Unable to clean up updater.");
 }
 
-bool LaunchElevatedUpdate(int argc, char** argv, uint32_t aRestartType,
-                          pid_t* pid)
+bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid)
 {
-  LaunchChildMac(argc, argv, aRestartType, pid);
+  LaunchChildMac(aArgc, aArgv, aPid);
   bool didSucceed = InstallPrivilegedHelper();
   if (!didSucceed) {
     AbortElevatedUpdate();
   }
   return didSucceed;
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1744,19 +1744,17 @@ static nsresult LaunchChild(nsINativeApp
 
   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
 
 #if defined(MOZ_WIDGET_ANDROID)
   java::GeckoAppShell::ScheduleRestart();
 #else
 #if defined(XP_MACOSX)
   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
-  uint32_t restartMode = 0;
-  restartMode = gRestartMode;
-  LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
+  LaunchChildMac(gRestartArgc, gRestartArgv);
 #else
   nsCOMPtr<nsIFile> lf;
   nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
   if (NS_FAILED(rv))
     return rv;
 
 #if defined(XP_WIN)
   nsAutoString exePath;
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -634,19 +634,16 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIF
 #elif defined(XP_WIN)
   // Switch the application using updater.exe
   if (!WinLaunchChild(updaterPathW.get(), argc, argv)) {
     return;
   }
   _exit(0);
 #elif defined(XP_MACOSX)
   CommandLineServiceMac::SetupMacCommandLine(argc, argv, true);
-  // LaunchChildMac uses posix_spawnp and prefers the current
-  // architecture when launching. It doesn't require a
-  // null-terminated string but it doesn't matter if we pass one.
   LaunchChildMac(argc, argv);
   exit(0);
 #else
   PR_CreateProcessDetached(updaterPath.get(), argv, nullptr, nullptr);
   exit(0);
 #endif
 }
 
@@ -959,26 +956,27 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
     _exit(0);
   }
 #elif defined(XP_MACOSX)
   CommandLineServiceMac::SetupMacCommandLine(argc, argv, restart);
   // We need to detect whether elevation is required for this update. This can
   // occur when an admin user installs the application, but another admin
   // user attempts to update (see bug 394984).
   if (restart && !IsRecursivelyWritable(installDirPath.get())) {
-    if (!LaunchElevatedUpdate(argc, argv, 0, outpid)) {
+    if (!LaunchElevatedUpdate(argc, argv, outpid)) {
       LOG(("Failed to launch elevated update!"));
       exit(1);
     }
     exit(0);
   } else {
-    LaunchChildMac(argc, argv, 0, outpid);
     if (restart) {
+      LaunchChildMac(argc, argv);
       exit(0);
     }
+    LaunchChildMac(argc, argv, outpid);
   }
 #else
   *outpid = PR_CreateProcess(updaterPath.get(), argv, nullptr, nullptr);
   if (restart) {
     exit(0);
   }
 #endif
 }
@@ -990,16 +988,19 @@ static bool
 ProcessHasTerminated(ProcessType pt)
 {
 #if defined(XP_WIN)
   if (WaitForSingleObject(pt, 1000)) {
     return false;
   }
   CloseHandle(pt);
   return true;
+#elif defined(XP_MACOSX)
+  // We're waiting for the process to terminate in LaunchChildMac.
+  return true;
 #elif defined(XP_UNIX)
   int exitStatus;
   bool exited = waitpid(pt, &exitStatus, WNOHANG) > 0;
   if (!exited) {
     sleep(1);
   } else if (WIFEXITED(exitStatus) && (WEXITSTATUS(exitStatus) != 0)) {
     LOG(("Error while running the updater process, check update.log"));
   }
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -13,16 +13,17 @@
 #include "nsIAddonInterposition.h"
 #include "nsIAppStartup.h"
 #include "nsIDirectoryEnumerator.h"
 #include "nsIFile.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIToolkitChromeRegistry.h"
+#include "nsIToolkitProfileService.h"
 #include "nsIXULRuntime.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsCategoryManagerUtils.h"
 
@@ -1180,16 +1181,36 @@ nsXREDirProvider::DoStartup()
     if (gSafeMode) {
       if (safeModeNecessary)
         mode = 3;
       else
         mode = 2;
     }
     mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
 
+    // Telemetry about number of profiles.
+    nsCOMPtr<nsIToolkitProfileService> profileService =
+      do_GetService("@mozilla.org/toolkit/profile-service;1");
+    if (profileService) {
+      nsCOMPtr<nsISimpleEnumerator> profiles;
+      rv = profileService->GetProfiles(getter_AddRefs(profiles));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      uint32_t count = 0;
+      nsCOMPtr<nsISupports> profile;
+      while (NS_SUCCEEDED(profiles->GetNext(getter_AddRefs(profile)))) {
+        ++count;
+      }
+
+      mozilla::Telemetry::Accumulate(mozilla::Telemetry::NUMBER_OF_PROFILES,
+                                     count);
+    }
+
     obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
 
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
     // The parent is responsible for creating the sandbox temp dir
     if (XRE_IsParentProcess()) {
       mContentProcessSandboxTempDir = CreateContentProcessSandboxTempDir();
       mContentTempDir = mContentProcessSandboxTempDir;
     }