diff --git a/.lldbinit b/.lldbinit
index 8564681b0f2af41cac8b135e12c7c271236f8508..df68ee16b257a40e81bb846287df549a929161f2 100644
--- a/.lldbinit
+++ b/.lldbinit
@@ -14,3 +14,9 @@ settings set target.prefer-dynamic-value run-target
 # than do any kind of searching, this assumes that you are running lldb from
 # the top level source directory.
 script sys.path.append('python/lldbutils'); import lldbutils; lldbutils.init()
+
+# Show the string value in atoms.
+type summary add nsIAtom --summary-string "${var.mString}"
+
+# Show the value of text nodes.
+type summary add nsTextNode --summary-string "${var.mText}"
diff --git a/accessible/src/windows/msaa/moz.build b/accessible/src/windows/msaa/moz.build
index cb3ff5affb00ae237a6dde5d23f0467f09843e63..cffb30b4a241007eb3740f0c0baa550d2690bdfc 100644
--- a/accessible/src/windows/msaa/moz.build
+++ b/accessible/src/windows/msaa/moz.build
@@ -46,7 +46,7 @@ if CONFIG['MOZ_XUL']:
 
 LOCAL_INCLUDES += [
     '../../../../content/base/src',
-    '../../../../content/events/src',
+    '../../../../dom/events',
     '../../base',
     '../../generic',
     '../../html',
diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js
index bad179d2037bd07ec2257a9de284230189580e96..adc94b5d48f2626f422f0358be848134a8de02fc 100644
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -683,6 +683,10 @@ Services.obs.addObserver(function onBluetoothVolumeChange(subject, topic, data)
   });
 }, 'bluetooth-volume-change', false);
 
+Services.obs.addObserver(function(subject, topic, data) {
+  shell.sendCustomEvent('mozmemorypressure');
+}, 'memory-pressure', false);
+
 var CustomEventManager = {
   init: function custevt_init() {
     window.addEventListener("ContentStart", (function(evt) {
diff --git a/b2g/config/emulator-jb/config.json b/b2g/config/emulator-jb/config.json
index 27be0502e76b7607836e43a4df653ce0ca2b6cc6..0490be0f04ccb630cc76ff1ac91e9cfdb838ca50 100644
--- a/b2g/config/emulator-jb/config.json
+++ b/b2g/config/emulator-jb/config.json
@@ -12,6 +12,12 @@
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{workdir}/sources.xml"
     ],
+    "public_upload_files": [
+        "{workdir}/out/target/product/generic/*.tar.bz2",
+        "{workdir}/out/target/product/generic/tests/*.zip",
+        "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+        "{workdir}/sources.xml"
+    ],
     "upload_platform": "emulator-jb",
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
diff --git a/b2g/config/emulator/config.json b/b2g/config/emulator/config.json
index be81fc03281d062352479914d4ed079c7f96db96..8998984207dc89cc5c5dd23c3572589af21446fc 100644
--- a/b2g/config/emulator/config.json
+++ b/b2g/config/emulator/config.json
@@ -12,6 +12,12 @@
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{workdir}/sources.xml"
     ],
+    "public_upload_files": [
+        "{workdir}/out/target/product/generic/*.tar.bz2",
+        "{workdir}/out/target/product/generic/tests/*.zip",
+        "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+        "{workdir}/sources.xml"
+    ],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index bd66f90ad221528433438f66d3b83c8238b3f905..73b4dca10f211b6b6d1a423e17ceee2d99d43b25 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "5fed274e799a9f111cdf6476ec53c9328c55c7b9", 
+    "revision": "25a3b96e9c5ff89b69b29007462bfd056ad5bf53", 
     "repo_path": "/integration/gaia-central"
 }
diff --git a/b2g/config/hamachi/config.json b/b2g/config/hamachi/config.json
index 9a36545016d7aa355c2a68ae3032f562e90a12a5..187c23590b5d45f949eb417a0b088d1e1a4f40fa 100644
--- a/b2g/config/hamachi/config.json
+++ b/b2g/config/hamachi/config.json
@@ -10,6 +10,11 @@
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml"
     ],
+    "public_upload_files": [
+        "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+        "{objdir}/dist/b2g-*.tar.gz",
+        "{workdir}/sources.xml"
+    ],
     "zip_files": [
         ["{workdir}/out/target/product/hamachi/*.img", "out/target/product/hamachi/"],
         ["{workdir}/boot.img", "out/target/product/hamachi/"],
diff --git a/b2g/config/inari/config.json b/b2g/config/inari/config.json
index 2f42f53326c8b3a15bb5521f69e6c79bc90ab511..9613ed514af4e5f4b043dd5adbd21bb370daffc2 100644
--- a/b2g/config/inari/config.json
+++ b/b2g/config/inari/config.json
@@ -10,6 +10,11 @@
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml"
     ],
+    "public_upload_files": [
+        "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+        "{objdir}/dist/b2g-*.tar.gz",
+        "{workdir}/sources.xml"
+    ],
     "zip_files": [
         ["{workdir}/out/target/product/inari/*.img", "out/target/product/inari/"],
         ["{workdir}/boot.img", "out/target/product/inari/"],
diff --git a/b2g/config/mako/config.json b/b2g/config/mako/config.json
index 8e655fae1e7dcf64eff0d26b9d61da472ac5a74b..000a61263c4a943fb7dc0649b67fbfd1b31175f8 100644
--- a/b2g/config/mako/config.json
+++ b/b2g/config/mako/config.json
@@ -10,6 +10,11 @@
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml"
     ],
+    "public_upload_files": [
+        "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
+        "{objdir}/dist/b2g-*.tar.gz",
+        "{workdir}/sources.xml"
+    ],
     "zip_files": [
         ["{workdir}/out/target/product/mako/*.img", "out/target/product/mako/"],
         ["{workdir}/boot.img", "out/target/product/mako/"],
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index cd1c101463229e2ddc9a82e1601907dfd58e1415..5510431842e27ea476050d4c3b953e2a5063cf85 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1337,7 +1337,7 @@ pref("browser.uiCustomization.debug", false);
 
 // The URL where remote content that composes the UI for Firefox Accounts should
 // be fetched. Must use HTTPS.
-pref("firefox.accounts.remoteUrl", "https://accounts.dev.lcip.org/flow?moar_native=true");
+pref("firefox.accounts.remoteUrl", "https://accounts.dev.lcip.org/?service=sync");
 
 // The URL of the Firefox Accounts auth server backend
 pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
diff --git a/browser/config/mozconfigs/linux64/debug b/browser/config/mozconfigs/linux64/debug
index 631cc91c6cc0557d09aa9bdb88a00cb38b81ba29..3c8d80220806d10ff2573e5eba5b8de7889b06c8 100644
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -2,8 +2,6 @@ ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 
-ac_add_options --disable-unified-compilation
-
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Needed to enable breakpad in application.ini
diff --git a/browser/config/mozconfigs/linux64/debug-nonunified b/browser/config/mozconfigs/linux64/debug-nonunified
new file mode 100644
index 0000000000000000000000000000000000000000..2e7b433c6a432a167fb8847963a0da8efacb6f44
--- /dev/null
+++ b/browser/config/mozconfigs/linux64/debug-nonunified
@@ -0,0 +1,3 @@
+. "$topsrcdir/browser/config/mozconfigs/linux64/debug"
+
+ac_add_options --disable-unified-compilation
diff --git a/browser/config/mozconfigs/linux64/nightly-nonunified b/browser/config/mozconfigs/linux64/nightly-nonunified
new file mode 100644
index 0000000000000000000000000000000000000000..2dccd17f3ce9b88fa9e00a4d3e65b52e87cab731
--- /dev/null
+++ b/browser/config/mozconfigs/linux64/nightly-nonunified
@@ -0,0 +1,3 @@
+. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
+
+ac_add_options --disable-unified-compilation
diff --git a/content/base/src/moz.build b/content/base/src/moz.build
index b0191e3019800b14b7d025df57dac5abb3a6c34c..4165eb470a2f51df4c181d2545e4387fbbec7b6e 100644
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -194,7 +194,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/caps/include',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/xml/content/src',
@@ -203,6 +202,7 @@ LOCAL_INCLUDES += [
     '/content/xul/document/src',
     '/docshell/base',
     '/dom/base',
+    '/dom/events',
     '/dom/ipc',
     '/dom/workers',
     '/dom/xbl',
diff --git a/content/events/moz.build b/content/events/moz.build
deleted file mode 100644
index ff2c29c66e04207f59825a57e61d21e3d95297bd..0000000000000000000000000000000000000000
--- a/content/events/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-PARALLEL_DIRS += ['public', 'src']
-
-MOCHITEST_MANIFESTS += ['test/mochitest.ini']
-MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
diff --git a/content/events/public/moz.build b/content/events/public/moz.build
deleted file mode 100644
index d17aa7044f1608099cde97c50f78650e1b5670f9..0000000000000000000000000000000000000000
--- a/content/events/public/moz.build
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
-    'nsIEventListenerService.idl',
-]
-
-XPIDL_MODULE = 'content_events'
-
-EXPORTS += [
-    'nsAsyncDOMEvent.h',
-    'nsDOMKeyNameList.h',
-    'nsEventDispatcher.h',
-    'nsEventNameList.h',
-    'nsEventStates.h',
-    'nsIPrivateTextEvent.h',
-    'nsIPrivateTextRange.h',
-    'nsVKList.h',
-]
-
-EXPORTS.mozilla += [
-    'MutationEvent.h',
-]
-
-EXPORTS.mozilla.dom += [
-    'EventTarget.h',
-]
-
diff --git a/content/html/content/public/HTMLCanvasElement.h b/content/html/content/public/HTMLCanvasElement.h
index d5e32f51d5cfd82dced91da5e7b2e88c4ab210dd..c6968002ee4190e7e90ad61b6ec0fa76b312b989 100644
--- a/content/html/content/public/HTMLCanvasElement.h
+++ b/content/html/content/public/HTMLCanvasElement.h
@@ -86,9 +86,9 @@ public:
                  const Optional<JS::Handle<JS::Value> >& aParams,
                  nsAString& aDataURL, ErrorResult& aRv)
   {
-    JS::Value params = aParams.WasPassed()
-                     ? aParams.Value()
-                     : JS::UndefinedValue();
+    JS::Handle<JS::Value> params = aParams.WasPassed()
+                                 ? aParams.Value()
+                                 : JS::UndefinedHandleValue;
     aRv = ToDataURL(aType, params, aCx, aDataURL);
   }
   void ToBlob(JSContext* aCx,
diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp
index 4177279bbd14a0b8f8bbcd2bd9036e86413db6c0..0a027845a23122533b727fc8d0238907a7c2a960 100644
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3395,27 +3395,26 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
     }
     if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
         aVisitor.mEvent->message == NS_BLUR_CONTENT) {
-      nsIFrame* frame = GetPrimaryFrame();
-      if (frame) {
-        if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
-          // Tell our frame it's getting focus so that it can make sure focus
-          // is moved to our anonymous text control.
-          nsNumberControlFrame* numberControlFrame =
-            do_QueryFrame(GetPrimaryFrame());
-          if (numberControlFrame) {
-            numberControlFrame->HandleFocusEvent(aVisitor.mEvent);
-          }
-        }
-        if (frame->IsThemed()) {
-          // Our frame's nested <input type=text> will be invalidated when it
-          // loses focus, but since we are also native themed we need to make
-          // sure that our entire area is repainted since any focus highlight
-          // from the theme should be removed from us (the repainting of the
-          // sub-area occupied by the anon text control is not enough to do
-          // that).
-          frame->InvalidateFrame();
+      if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
+        // Tell our frame it's getting focus so that it can make sure focus
+        // is moved to our anonymous text control.
+        nsNumberControlFrame* numberControlFrame =
+          do_QueryFrame(GetPrimaryFrame());
+        if (numberControlFrame) {
+          // This could kill the frame!
+          numberControlFrame->HandleFocusEvent(aVisitor.mEvent);
         }
       }
+      nsIFrame* frame = GetPrimaryFrame();
+      if (frame && frame->IsThemed()) {
+        // Our frame's nested <input type=text> will be invalidated when it
+        // loses focus, but since we are also native themed we need to make
+        // sure that our entire area is repainted since any focus highlight
+        // from the theme should be removed from us (the repainting of the
+        // sub-area occupied by the anon text control is not enough to do
+        // that).
+        frame->InvalidateFrame();
+      }
     } else if (aVisitor.mEvent->message == NS_KEY_UP) {
       WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
       if ((keyEvent->keyCode == NS_VK_UP || keyEvent->keyCode == NS_VK_DOWN) &&
@@ -3453,8 +3452,11 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
         numberControlFrame->HandlingInputEvent(true);
         nsAutoString value;
         textControl->GetValue(value);
+        nsWeakFrame weakNumberControlFrame(numberControlFrame);
         SetValueInternal(value, false, true);
-        numberControlFrame->HandlingInputEvent(false);
+        if (weakNumberControlFrame.IsAlive()) {
+          numberControlFrame->HandlingInputEvent(false);
+        }
       }
       else if (aVisitor.mEvent->message == NS_FORM_CHANGE) {
         // We cancel the DOM 'change' event that is fired for any change to our
diff --git a/content/html/content/src/moz.build b/content/html/content/src/moz.build
index da328edc9fb3cf0f62c87d35318a53a19792c8fc..4105e0fa9bdc9b4797dd18b14298b22ab835771c 100644
--- a/content/html/content/src/moz.build
+++ b/content/html/content/src/moz.build
@@ -168,11 +168,11 @@ FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/canvas/src',
-    '/content/events/src',
     '/content/html/document/src',
     '/content/media/',
     '/content/xul/content/src',
     '/dom/base',
+    '/dom/events',
     '/dom/xbl',
     '/editor/libeditor/base',
     '/editor/libeditor/text',
diff --git a/content/html/content/test/enableTestPlugin.js b/content/html/content/test/enableTestPlugin.js
new file mode 100644
index 0000000000000000000000000000000000000000..63c481807e0e1b8298148d16acc28444075933a7
--- /dev/null
+++ b/content/html/content/test/enableTestPlugin.js
@@ -0,0 +1,25 @@
+// this automatically sets the test plugin to be enabled (not e.g. click-to-play)
+// and resets this afterwards
+
+(function() {
+  function getTestPlugin(aPluginName) {
+    var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"]
+                          .getService(SpecialPowers.Ci.nsIPluginHost);
+    var tags = ph.getPluginTags();
+    for (var tag of tags) {
+      if (tag.name == aPluginName) {
+       return tag;
+      }
+    }
+
+    ok(false, "Could not find plugin tag with plugin name '" + name + "'");
+    return null;
+  }
+
+  var plugin = getTestPlugin("Test Plug-in");
+  var oldEnabledState = plugin.enabledState;
+  plugin.enabledState = SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED;
+  SimpleTest.registerCleanupFunction(function() {
+    getTestPlugin("Test Plug-in").enabledState = oldEnabledState;
+  });
+})();
diff --git a/content/html/content/test/test_object_plugin_nav.html b/content/html/content/test/test_object_plugin_nav.html
index 7d6f021ef949edbe06f743ad4df58fe3f2a8c312..0b5c4984bb4322657d9b50879f8f3b8502c4b448 100644
--- a/content/html/content/test/test_object_plugin_nav.html
+++ b/content/html/content/test/test_object_plugin_nav.html
@@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=720130
   <title>Test for Bug 720130</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript" src="enableTestPlugin.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
@@ -55,7 +56,7 @@ function checkFocus() {
 
 SimpleTest.waitForExplicitFinish();
 
-SimpleTest.waitForFocus(function() {
+function doTest() {
   is(document.activeElement, document.body);
 
   // Preliminary check: tabindex should be -1 on the object.
@@ -82,6 +83,11 @@ SimpleTest.waitForFocus(function() {
   }, true);
 
   synthesizeKey("VK_TAB", {});
+}
+
+SimpleTest.waitForFocus(function () {
+  // Set the focus model so that links are focusable by the tab key even on Mac
+  SpecialPowers.pushPrefEnv({'set': [['accessibility.tabfocus', 7]]}, doTest);
 });
 
 </script>
diff --git a/content/html/document/src/moz.build b/content/html/document/src/moz.build
index d11996ce4c483da4b7ad9dad33025a508ad2535d..2291ca70a2e8168eaf5bfcefcaa1e26f48f200e3 100644
--- a/content/html/document/src/moz.build
+++ b/content/html/document/src/moz.build
@@ -31,9 +31,9 @@ LOCAL_INCLUDES += [
     '../../content/src',
     '/caps/include',
     '/content/base/src',
-    '/content/events/src',
     '/docshell/base',
     '/dom/base',
+    '/dom/events',
     '/layout/style',
     '/xpcom/ds',
 ]
diff --git a/content/media/fmp4/BlankDecoderModule.cpp b/content/media/fmp4/BlankDecoderModule.cpp
index b578ebcc6fe8e9f561b0f9227b38322821a32024..30b65ef91784ab5a762a6ad9436333f5f56861c6 100644
--- a/content/media/fmp4/BlankDecoderModule.cpp
+++ b/content/media/fmp4/BlankDecoderModule.cpp
@@ -11,6 +11,8 @@
 #include "mozilla/CheckedInt.h"
 #include "VideoUtils.h"
 #include "ImageContainer.h"
+#include "mp4_demuxer/mp4_demuxer.h"
+#include "mp4_demuxer/audio_decoder_config.h"
 
 namespace mozilla {
 
@@ -22,33 +24,36 @@ public:
 
   BlankMediaDataDecoder(BlankMediaDataCreator* aCreator)
     : mCreator(aCreator),
-      mNextDTS(-1),
+      mNextTimeStamp(-1),
       mNextOffset(-1)
   {
   }
 
+  virtual nsresult Init() MOZ_OVERRIDE {
+    return NS_OK;
+  }
+
   virtual nsresult Shutdown() MOZ_OVERRIDE {
     return NS_OK;
   }
 
-  virtual DecoderStatus Input(const uint8_t* aData,
-                              uint32_t aLength,
-                              Microseconds aDTS,
-                              Microseconds aPTS,
-                              int64_t aOffsetInStream) MOZ_OVERRIDE
+  virtual DecoderStatus Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample) MOZ_OVERRIDE
   {
     // Accepts input, and outputs on the second input, using the difference
     // in DTS as the duration.
     if (mOutput) {
       return DECODE_STATUS_NOT_ACCEPTING;
     }
-    if (mNextDTS != -1 && mNextOffset != -1) {
-      Microseconds duration = aDTS - mNextDTS;
-      mOutput = mCreator->Create(mNextDTS, duration, mNextOffset);
+
+    Microseconds timestamp = aSample->composition_timestamp;
+    if (mNextTimeStamp != -1 && mNextOffset != -1) {
+      Microseconds duration = timestamp - mNextTimeStamp;
+      mOutput = mCreator->Create(mNextTimeStamp, duration, mNextOffset);
     }
 
-    mNextDTS = aDTS;
-    mNextOffset = aOffsetInStream;
+    mNextTimeStamp = timestamp;
+    mNextOffset = aSample->byte_offset;
+
     return DECODE_STATUS_OK;
   }
 
@@ -66,7 +71,7 @@ public:
   }
 private:
   nsAutoPtr<BlankMediaDataCreator> mCreator;
-  Microseconds mNextDTS;
+  Microseconds mNextTimeStamp;
   int64_t mNextOffset;
   nsAutoPtr<MediaData> mOutput;
   bool mHasInput;
@@ -198,21 +203,19 @@ public:
   }
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateH264Decoder(layers::LayersBackend aLayersBackend,
+  virtual MediaDataDecoder* CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                                              layers::LayersBackend aLayersBackend,
                                               layers::ImageContainer* aImageContainer) MOZ_OVERRIDE {
     BlankVideoDataCreator* decoder = new BlankVideoDataCreator(aImageContainer);
     return new BlankMediaDataDecoder<BlankVideoDataCreator>(decoder);
   }
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
-                                             uint32_t aSampleRate,
-                                             uint16_t aBitsPerSample,
-                                             const uint8_t* aUserData,
-                                             uint32_t aUserDataLength) MOZ_OVERRIDE {
-    BlankAudioDataCreator* decoder = new BlankAudioDataCreator(aChannelCount,
-                                                               aSampleRate,
-                                                               aBitsPerSample);
+  virtual MediaDataDecoder* CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig) MOZ_OVERRIDE {
+    BlankAudioDataCreator* decoder =
+      new BlankAudioDataCreator(ChannelLayoutToChannelCount(aConfig.channel_layout()),
+                                aConfig.samples_per_second(),
+                                aConfig.bits_per_channel());
     return new BlankMediaDataDecoder<BlankAudioDataCreator>(decoder);
   }
 };
diff --git a/content/media/fmp4/MP4Reader.cpp b/content/media/fmp4/MP4Reader.cpp
index 82358465b237aa77ba1e70b9eac8f6fe93ef1fb8..9ac386ce2abf871c5609815215b641b400e1cb16 100644
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -123,12 +123,10 @@ nsresult
 MP4Reader::Init(MediaDecoderReader* aCloneDonor)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+  PlatformDecoderModule::Init();
   mMP4Stream = new MP4Stream(mDecoder->GetResource());
   mDemuxer = new MP4Demuxer(mMP4Stream);
 
-  mPlatform = PlatformDecoderModule::Create();
-  NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE);
-
   InitLayersBackendType();
 
   return NS_OK;
@@ -157,25 +155,28 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
     return NS_ERROR_FAILURE;
   }
 
+  mPlatform = PlatformDecoderModule::Create();
+  NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE);
+
   if (mHasAudio) {
     mInfo.mAudio.mRate = audio.samples_per_second();
     mInfo.mAudio.mChannels = ChannelLayoutToChannelCount(audio.channel_layout());
-    mAudioDecoder = mPlatform->CreateAACDecoder(mInfo.mAudio.mChannels,
-                                                mInfo.mAudio.mRate,
-                                                audio.bits_per_channel(),
-                                                audio.extra_data(),
-                                                audio.extra_data_size());
+    mAudioDecoder = mPlatform->CreateAACDecoder(audio);
     NS_ENSURE_TRUE(mAudioDecoder != nullptr, NS_ERROR_FAILURE);
+    nsresult rv = mAudioDecoder->Init();
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mInfo.mVideo.mHasVideo = mHasVideo = mDemuxer->HasVideo();
   if (mHasVideo) {
-    const VideoDecoderConfig& config = mDemuxer->VideoConfig();
-    IntSize sz = config.natural_size();
+    IntSize sz = video.natural_size();
     mInfo.mVideo.mDisplay = nsIntSize(sz.width(), sz.height());
-    mVideoDecoder = mPlatform->CreateH264Decoder(mLayersBackendType,
+    mVideoDecoder = mPlatform->CreateH264Decoder(video,
+                                                 mLayersBackendType,
                                                  mDecoder->GetImageContainer());
     NS_ENSURE_TRUE(mVideoDecoder != nullptr, NS_ERROR_FAILURE);
+    nsresult rv = mVideoDecoder->Init();
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Get the duration, and report it to the decoder if we have it.
@@ -282,16 +283,15 @@ MP4Reader::Decode(TrackType aTrack, nsAutoPtr<MediaData>& aOutData)
           // frames coming.
           return false;
         }
-        const std::vector<uint8_t>* data = compressed->data;
-        status = decoder->Input(&data->front(),
-                                data->size(),
-                                compressed->decode_timestamp,
-                                compressed->composition_timestamp,
-                                compressed->byte_offset);
+        status = decoder->Input(compressed);
       } while (status == DECODE_STATUS_OK);
       if (status == DECODE_STATUS_NOT_ACCEPTING) {
         // Decoder should now be able to produce an output.
-        SampleQueue(aTrack).push_front(compressed.forget());
+        if (compressed != nullptr) {
+          // Decoder didn't consume data, attempt to decode the same
+          // sample next time.
+          SampleQueue(aTrack).push_front(compressed.forget());
+        }
         continue;
       }
       LOG("MP4Reader decode failure. track=%d status=%d\n", aTrack, status);
@@ -401,8 +401,9 @@ MP4Reader::OnDecodeThreadStart()
 {
   MOZ_ASSERT(!NS_IsMainThread(), "Must not be on main thread.");
   MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
-  MOZ_ASSERT(mPlatform);
-  mPlatform->OnDecodeThreadStart();
+  if (mPlatform) {
+    mPlatform->OnDecodeThreadStart();
+  }
 }
 
 void
@@ -410,8 +411,9 @@ MP4Reader::OnDecodeThreadFinish()
 {
   MOZ_ASSERT(!NS_IsMainThread(), "Must not be on main thread.");
   MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
-  MOZ_ASSERT(mPlatform);
-  mPlatform->OnDecodeThreadFinish();
+  if (mPlatform) {
+    mPlatform->OnDecodeThreadFinish();
+  }
 }
 
 } // namespace mozilla
diff --git a/content/media/fmp4/MP4Reader.h b/content/media/fmp4/MP4Reader.h
index 2a17340998a73f8120194ca60f223c7106bf4626..fe40be90497931765b847a87c689871f03ac32c3 100644
--- a/content/media/fmp4/MP4Reader.h
+++ b/content/media/fmp4/MP4Reader.h
@@ -14,6 +14,7 @@
 #include "mp4_demuxer/box_definitions.h"
 
 #include <deque>
+#include "mozilla/Monitor.h"
 
 namespace mozilla {
 
@@ -82,7 +83,6 @@ private:
 
   bool mHasAudio;
   bool mHasVideo;
-
 };
 
 } // namespace mozilla
diff --git a/content/media/fmp4/PlatformDecoderModule.cpp b/content/media/fmp4/PlatformDecoderModule.cpp
index ed51a6842e7d1d717d2751d5d0a879e770012fcc..3e8a3f1754cd796ab5916d5b562e540113a6ce76 100644
--- a/content/media/fmp4/PlatformDecoderModule.cpp
+++ b/content/media/fmp4/PlatformDecoderModule.cpp
@@ -14,16 +14,34 @@ namespace mozilla {
 
 extern PlatformDecoderModule* CreateBlankDecoderModule();
 
+bool PlatformDecoderModule::sUseBlankDecoder = false;
+
+/* static */
+void
+PlatformDecoderModule::Init()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  static bool alreadyInitialized = false;
+  if (alreadyInitialized) {
+    return;
+  }
+  alreadyInitialized = true;
+  sUseBlankDecoder = Preferences::GetBool("media.fragmented-mp4.use-blank-decoder");
+#ifdef XP_WIN
+  WMFDecoderModule::Init();
+#endif
+}
+
 /* static */
 PlatformDecoderModule*
 PlatformDecoderModule::Create()
 {
-  if (Preferences::GetBool("media.fragmented-mp4.use-blank-decoder")) {
+  if (sUseBlankDecoder) {
     return CreateBlankDecoderModule();
   }
 #ifdef XP_WIN
   nsAutoPtr<WMFDecoderModule> m(new WMFDecoderModule());
-  if (NS_SUCCEEDED(m->Init())) {
+  if (NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
 #endif
diff --git a/content/media/fmp4/PlatformDecoderModule.h b/content/media/fmp4/PlatformDecoderModule.h
index 94674acbefd7c8911fc5995d5843716f129bb176..2c11bca11ab5e320618e2acbe1bf4383cbd3c218 100644
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -9,6 +9,13 @@
 
 #include "MediaDecoderReader.h"
 #include "mozilla/layers/LayersTypes.h"
+#include "nsTArray.h"
+
+namespace mp4_demuxer {
+class VideoDecoderConfig;
+class AudioDecoderConfig;
+struct MP4Sample;
+}
 
 namespace mozilla {
 
@@ -35,6 +42,9 @@ typedef int64_t Microseconds;
 // "media.fragmented-mp4.use-blank-decoder" is true.
 class PlatformDecoderModule {
 public:
+  // Call on the main thread to initialize the static state
+  // needed by Create().
+  static void Init();
 
   // Factory method that creates the appropriate PlatformDecoderModule for
   // the platform we're running on. Caller is responsible for deleting this
@@ -56,7 +66,8 @@ public:
   // decoding can be used. Returns nullptr if the decoder can't be
   // initialized.
   // Called on decode thread.
-  virtual MediaDataDecoder* CreateH264Decoder(layers::LayersBackend aLayersBackend,
+  virtual MediaDataDecoder* CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                                              layers::LayersBackend aLayersBackend,
                                               layers::ImageContainer* aImageContainer) = 0;
 
   // Creates and initializes an AAC decoder with the specified properties.
@@ -65,11 +76,7 @@ public:
   // so it must be copied if it is to be retained by the decoder.
   // Returns nullptr if the decoder can't be initialized.
   // Called on decode thread.
-  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
-                                             uint32_t aSampleRate,
-                                             uint16_t aBitsPerSample,
-                                             const uint8_t* aAACConfig,
-                                             uint32_t aAACConfigLength) = 0;
+  virtual MediaDataDecoder* CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig) = 0;
 
   // Called when a decode thread is started. Called on decode thread.
   virtual void OnDecodeThreadStart() {}
@@ -80,6 +87,8 @@ public:
   virtual ~PlatformDecoderModule() {}
 protected:
   PlatformDecoderModule() {}
+  // Caches pref media.fragmented-mp4.use-blank-decoder
+  static bool sUseBlankDecoder;
 };
 
 // Return value of the MediaDataDecoder functions.
@@ -102,10 +111,29 @@ class MediaDataDecoder {
 public:
   virtual ~MediaDataDecoder() {};
 
+  // Initialize the decoder. The decoder should be ready to decode after
+  // this returns. The decoder should do any initialization here, rather
+  // than in its constructor, so that if the MP4Reader needs to Shutdown()
+  // during initialization it can call Shutdown() to cancel this.
+  // Any initialization that requires blocking the calling thread *must*
+  // be done here so that it can be canceled by calling Shutdown()!
+  virtual nsresult Init() = 0;
+
   // Inserts aData into the decoding pipeline. Decoding may begin
-  // asynchronously. The caller owns aData, so it may need to be copied.
-  // The MP4Reader calls Input() with new input in a loop until Input()
-  // stops returning DECODE_STATUS_OK.
+  // asynchronously.
+  //
+  // If the decoder needs to assume ownership of the sample it may do so by
+  // calling forget() on aSample.
+  //
+  // If Input() returns DECODE_STATUS_NOT_ACCEPTING without forget()ing
+  // aSample, then the next call will have the same aSample. Otherwise
+  // the caller will delete aSample after Input() returns.
+  //
+  // The MP4Reader calls Input() in a loop until Input() stops returning
+  // DECODE_STATUS_OK. Input() should return DECODE_STATUS_NOT_ACCEPTING
+  // once the underlying decoder should have enough data to output decoded
+  // data.
+  //
   // Called on the media decode thread.
   // Returns:
   //  - DECODE_STATUS_OK if input was successfully inserted into
@@ -114,15 +142,13 @@ public:
   //    at this time. The MP4Reader will assume that the decoder can now
   //    produce one or more output samples, and call the Output() function.
   //    The MP4Reader will call Input() again with the same data later,
-  //    after the decoder's Output() function has stopped producing output.
+  //    after the decoder's Output() function has stopped producing output,
+  //    except if Input() called forget() on aSample, whereupon a new sample
+  //    will come in next call.
   //  - DECODE_STATUS_ERROR if the decoder has been shutdown, or some
   //    unspecified error.
   // This function should not return DECODE_STATUS_NEED_MORE_INPUT.
-  virtual DecoderStatus Input(const uint8_t* aData,
-                              uint32_t aLength,
-                              Microseconds aDTS,
-                              Microseconds aPTS,
-                              int64_t aOffsetInStream) = 0;
+  virtual DecoderStatus Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample) = 0;
 
   // Blocks until a decoded sample is produced by the deoder. The MP4Reader
   // calls this until it stops returning DECODE_STATUS_OK.
diff --git a/content/media/fmp4/wmf/WMFAudioDecoder.cpp b/content/media/fmp4/wmf/WMFAudioDecoder.cpp
index 1dda4eb08835bb0a0c9a05c398fee040b05f094c..23ec1f9897b67becd384541c43491cf37654b724 100644
--- a/content/media/fmp4/wmf/WMFAudioDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFAudioDecoder.cpp
@@ -21,17 +21,6 @@ PRLogModuleInfo* GetDemuxerLog();
 
 namespace mozilla {
 
-WMFAudioDecoder::WMFAudioDecoder()
-  : mAudioChannels(0),
-    mAudioBytesPerSample(0),
-    mAudioRate(0),
-    mLastStreamOffset(0),
-    mAudioFrameOffset(0),
-    mAudioFrameSum(0),
-    mMustRecaptureAudioPosition(true)
-{
-}
-
 static void
 AACAudioSpecificConfigToUserData(const uint8_t* aAudioSpecConfig,
                                  uint32_t aConfigLength,
@@ -77,12 +66,26 @@ AACAudioSpecificConfigToUserData(const uint8_t* aAudioSpecConfig,
   aOutUserData.AppendElements(aAudioSpecConfig, aConfigLength);
 }
 
+WMFAudioDecoder::WMFAudioDecoder(uint32_t aChannelCount,
+                                 uint32_t aSampleRate,
+                                 uint16_t aBitsPerSample,
+                                 const uint8_t* aAudioSpecConfig,
+                                 uint32_t aConfigLength)
+  : mAudioChannels(aChannelCount),
+    mAudioBytesPerSample(aBitsPerSample / 8),
+    mAudioRate(aSampleRate),
+    mLastStreamOffset(0),
+    mAudioFrameOffset(0),
+    mAudioFrameSum(0),
+    mMustRecaptureAudioPosition(true)
+{
+  AACAudioSpecificConfigToUserData(aAudioSpecConfig,
+                                   aConfigLength,
+                                   mUserData);
+}
+
 nsresult
-WMFAudioDecoder::Init(uint32_t aChannelCount,
-                      uint32_t aSampleRate,
-                      uint16_t aBitsPerSample,
-                      const uint8_t* aAudioSpecConfig,
-                      uint32_t aConfigLength)
+WMFAudioDecoder::Init()
 {
   mDecoder = new MFTDecoder();
 
@@ -101,31 +104,23 @@ WMFAudioDecoder::Init(uint32_t aChannelCount,
   hr = type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
-  hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, aSampleRate);
+  hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mAudioRate);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
-  hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, aChannelCount);
+  hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mAudioChannels);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   hr = type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x1); // ADTS
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
-  nsTArray<BYTE> userData;
-  AACAudioSpecificConfigToUserData(aAudioSpecConfig,
-                                   aConfigLength,
-                                   userData);
-
   hr = type->SetBlob(MF_MT_USER_DATA,
-                     userData.Elements(),
-                     userData.Length());
+                     mUserData.Elements(),
+                     mUserData.Length());
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   hr = mDecoder->SetMediaTypes(type, MFAudioFormat_PCM);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
-  mAudioChannels = aChannelCount;
-  mAudioBytesPerSample = aBitsPerSample / 8;
-  mAudioRate = aSampleRate;
   return NS_OK;
 }
 
@@ -136,14 +131,12 @@ WMFAudioDecoder::Shutdown()
 }
 
 DecoderStatus
-WMFAudioDecoder::Input(const uint8_t* aData,
-                       uint32_t aLength,
-                       Microseconds aDTS,
-                       Microseconds aPTS,
-                       int64_t aOffsetInStream)
+WMFAudioDecoder::Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample)
 {
-  mLastStreamOffset = aOffsetInStream;
-  HRESULT hr = mDecoder->Input(aData, aLength, aPTS);
+  mLastStreamOffset = aSample->byte_offset;
+  const uint8_t* data = &aSample->data->front();
+  uint32_t length = aSample->data->size();
+  HRESULT hr = mDecoder->Input(data, length, aSample->composition_timestamp);
   if (hr == MF_E_NOTACCEPTING) {
     return DECODE_STATUS_NOT_ACCEPTING;
   }
diff --git a/content/media/fmp4/wmf/WMFAudioDecoder.h b/content/media/fmp4/wmf/WMFAudioDecoder.h
index cc8d6b1b24409cae7d8022190206b568359a75c7..a4246881d37a0ea7c31cea5fabe2748dd09e31db 100644
--- a/content/media/fmp4/wmf/WMFAudioDecoder.h
+++ b/content/media/fmp4/wmf/WMFAudioDecoder.h
@@ -15,22 +15,18 @@ namespace mozilla {
 
 class WMFAudioDecoder : public MediaDataDecoder {
 public:
-  WMFAudioDecoder();
+  WMFAudioDecoder(uint32_t aChannelCount,
+                  uint32_t aSampleRate,
+                  uint16_t aBitsPerSample,
+                  const uint8_t* aUserData,
+                  uint32_t aUserDataLength);
 
-  nsresult Init(uint32_t aChannelCount,
-                uint32_t aSampleRate,
-                uint16_t aBitsPerSample,
-                const uint8_t* aUserData,
-                uint32_t aUserDataLength);
+  virtual nsresult Init() MOZ_OVERRIDE;
 
   virtual nsresult Shutdown() MOZ_OVERRIDE;
 
   // Inserts data into the decoder's pipeline.
-  virtual DecoderStatus Input(const uint8_t* aData,
-                              uint32_t aLength,
-                              Microseconds aDTS,
-                              Microseconds aPTS,
-                              int64_t aOffsetInStream);
+  virtual DecoderStatus Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample);
 
   // Blocks until a decoded sample is produced by the decoder.
   virtual DecoderStatus Output(nsAutoPtr<MediaData>& aOutData);
@@ -53,6 +49,7 @@ private:
   uint32_t mAudioChannels;
   uint32_t mAudioBytesPerSample;
   uint32_t mAudioRate;
+  nsTArray<BYTE> mUserData;
 
   // The last offset into the media resource that was passed into Input().
   // This is used to approximate the decoder's position in the media resource.
diff --git a/content/media/fmp4/wmf/WMFDecoderModule.cpp b/content/media/fmp4/wmf/WMFDecoderModule.cpp
index 7d428bbe5d2b2c46cc55727a4ae1e136bdb14e4b..c534f5a72556989041578298decc5b2f848eeabe 100644
--- a/content/media/fmp4/wmf/WMFDecoderModule.cpp
+++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp
@@ -11,36 +11,46 @@
 #include "WMFAudioDecoder.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/DebugOnly.h"
+#include "mp4_demuxer/audio_decoder_config.h"
 
 namespace mozilla {
 
+bool WMFDecoderModule::sIsWMFEnabled = false;
+bool WMFDecoderModule::sDXVAEnabled = false;
+
 WMFDecoderModule::WMFDecoderModule()
-  : mDXVAEnabled(Preferences::GetBool("media.windows-media-foundation.use-dxva", false))
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 }
 
 WMFDecoderModule::~WMFDecoderModule()
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 }
 
-nsresult
+/* static */
+void
 WMFDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
-  if (!Preferences::GetBool("media.windows-media-foundation.enabled", false)) {
-    return NS_ERROR_FAILURE;
+  sIsWMFEnabled = Preferences::GetBool("media.windows-media-foundation.enabled", false);
+  if (!sIsWMFEnabled) {
+    return;
   }
+  if (NS_FAILED(WMFDecoder::LoadDLLs())) {
+    sIsWMFEnabled = false;
+  }
+  sDXVAEnabled = Preferences::GetBool("media.windows-media-foundation.use-dxva", false);
+}
 
-  nsresult rv = WMFDecoder::LoadDLLs();
-  NS_ENSURE_SUCCESS(rv, rv);
-
+nsresult
+WMFDecoderModule::Startup()
+{
+  if (!sIsWMFEnabled) {
+    return NS_ERROR_FAILURE;
+  }
   if (FAILED(wmf::MFStartup())) {
     NS_WARNING("Failed to initialize Windows Media Foundation");
     return NS_ERROR_FAILURE;
   }
-
   return NS_OK;
 }
 
@@ -56,30 +66,23 @@ WMFDecoderModule::Shutdown()
 }
 
 MediaDataDecoder*
-WMFDecoderModule::CreateH264Decoder(mozilla::layers::LayersBackend aLayersBackend,
+WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                                    mozilla::layers::LayersBackend aLayersBackend,
                                     mozilla::layers::ImageContainer* aImageContainer)
 {
-  nsAutoPtr<WMFVideoDecoder> decoder(new WMFVideoDecoder(mDXVAEnabled));
-  nsresult rv = decoder->Init(aLayersBackend, aImageContainer);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-  return decoder.forget();
+  return new WMFVideoDecoder(aLayersBackend,
+                             aImageContainer,
+                             sDXVAEnabled);
 }
 
 MediaDataDecoder*
-WMFDecoderModule::CreateAACDecoder(uint32_t aChannelCount,
-                                   uint32_t aSampleRate,
-                                   uint16_t aBitsPerSample,
-                                   const uint8_t* aUserData,
-                                   uint32_t aUserDataLength)
+WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig)
 {
-  nsAutoPtr<WMFAudioDecoder> decoder(new WMFAudioDecoder());
-  nsresult rv = decoder->Init(aChannelCount,
-                              aSampleRate,
-                              aBitsPerSample,
-                              aUserData,
-                              aUserDataLength);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-  return decoder.forget();
+  return new WMFAudioDecoder(ChannelLayoutToChannelCount(aConfig.channel_layout()),
+                             aConfig.samples_per_second(),
+                             aConfig.bits_per_channel(),
+                             aConfig.extra_data(),
+                             aConfig.extra_data_size());
 }
 
 void
diff --git a/content/media/fmp4/wmf/WMFDecoderModule.h b/content/media/fmp4/wmf/WMFDecoderModule.h
index 34371cde22de7633af8d7e2b10ddaa26ae64850b..039f268aeffc9a6c8d42911d767768718c54f1b7 100644
--- a/content/media/fmp4/wmf/WMFDecoderModule.h
+++ b/content/media/fmp4/wmf/WMFDecoderModule.h
@@ -18,7 +18,7 @@ public:
 
   // Initializes the module, loads required dynamic libraries, etc.
   // Main thread only.
-  nsresult Init();
+  nsresult Startup();
 
   // Called when the decoders have shutdown. Main thread only.
   // Does this really need to be main thread only????
@@ -26,21 +26,22 @@ public:
 
   // Decode thread.
   virtual MediaDataDecoder*
-  CreateH264Decoder(mozilla::layers::LayersBackend aLayersBackend,
+  CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                    mozilla::layers::LayersBackend aLayersBackend,
                     mozilla::layers::ImageContainer* aImageContainer) MOZ_OVERRIDE;
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
-                                             uint32_t aSampleRate,
-                                             uint16_t aBitsPerSample,
-                                             const uint8_t* aUserData,
-                                             uint32_t aUserDataLength) MOZ_OVERRIDE;
+  virtual MediaDataDecoder* CreateAACDecoder(
+    const mp4_demuxer::AudioDecoderConfig& aConfig) MOZ_OVERRIDE;
 
   // Platform decoders can override these. Base implementation does nothing.
   virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
   virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
+
+  static void Init();
 private:
-  const bool mDXVAEnabled;
+  static bool sIsWMFEnabled;
+  static bool sDXVAEnabled;
 };
 
 } // namespace mozilla
diff --git a/content/media/fmp4/wmf/WMFVideoDecoder.cpp b/content/media/fmp4/wmf/WMFVideoDecoder.cpp
index 8fd284506113f4d6d1813f63ddb6fca54317e5cf..58e11b74ecd0b01ef586fce1f5da263c4da7926d 100644
--- a/content/media/fmp4/wmf/WMFVideoDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFVideoDecoder.cpp
@@ -28,15 +28,20 @@ using mozilla::layers::LayersBackend;
 
 namespace mozilla {
 
-WMFVideoDecoder::WMFVideoDecoder(bool aDXVAEnabled)
+WMFVideoDecoder::WMFVideoDecoder(mozilla::layers::LayersBackend aLayersBackend,
+                                 mozilla::layers::ImageContainer* aImageContainer,
+                                 bool aDXVAEnabled)
   : mVideoStride(0),
     mVideoWidth(0),
     mVideoHeight(0),
     mLastStreamOffset(0),
+    mImageContainer(aImageContainer),
     mDXVAEnabled(aDXVAEnabled),
+    mLayersBackend(aLayersBackend),
     mUseHwAccel(false)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Must be on main thread.");
+  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
+  MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(WMFVideoDecoder);
 }
 
@@ -56,14 +61,14 @@ public:
 };
 
 bool
-WMFVideoDecoder::InitializeDXVA(mozilla::layers::LayersBackend aLayersBackend)
+WMFVideoDecoder::InitializeDXVA()
 {
   // If we use DXVA but aren't running with a D3D layer manager then the
   // readback of decoded video frames from GPU to CPU memory grinds painting
   // to a halt, and makes playback performance *worse*.
   if (!mDXVAEnabled ||
-      (aLayersBackend != LayersBackend::LAYERS_D3D9 &&
-       aLayersBackend != LayersBackend::LAYERS_D3D10)) {
+      (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
+       mLayersBackend != LayersBackend::LAYERS_D3D10)) {
     return false;
   }
 
@@ -76,12 +81,9 @@ WMFVideoDecoder::InitializeDXVA(mozilla::layers::LayersBackend aLayersBackend)
 }
 
 nsresult
-WMFVideoDecoder::Init(mozilla::layers::LayersBackend aLayersBackend,
-                      mozilla::layers::ImageContainer* aImageContainer)
+WMFVideoDecoder::Init()
 {
-  NS_ENSURE_ARG_POINTER(aImageContainer);
-
-  bool useDxva= InitializeDXVA(aLayersBackend);
+  bool useDxva = InitializeDXVA();
 
   mDecoder = new MFTDecoder();
 
@@ -126,8 +128,6 @@ WMFVideoDecoder::Init(mozilla::layers::LayersBackend aLayersBackend,
   hr = mDecoder->SetMediaTypes(type, outputType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
-  mImageContainer = aImageContainer;
-
   LOG("Video Decoder initialized, Using DXVA: %s", (mUseHwAccel ? "Yes" : "No"));
 
   return NS_OK;
@@ -202,14 +202,12 @@ WMFVideoDecoder::Shutdown()
 
 // Inserts data into the decoder's pipeline.
 DecoderStatus
-WMFVideoDecoder::Input(const uint8_t* aData,
-                       uint32_t aLength,
-                       Microseconds aDTS,
-                       Microseconds aPTS,
-                       int64_t aOffsetInStream)
+WMFVideoDecoder::Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample)
 {
-  mLastStreamOffset = aOffsetInStream;
-  HRESULT hr = mDecoder->Input(aData, aLength, aPTS);
+  mLastStreamOffset = aSample->byte_offset;
+  const uint8_t* data = &aSample->data->front();
+  uint32_t length = aSample->data->size();
+  HRESULT hr = mDecoder->Input(data, length, aSample->composition_timestamp);
   if (hr == MF_E_NOTACCEPTING) {
     return DECODE_STATUS_NOT_ACCEPTING;
   }
diff --git a/content/media/fmp4/wmf/WMFVideoDecoder.h b/content/media/fmp4/wmf/WMFVideoDecoder.h
index 91bb09fe9b00c36c477552b4e7693c459a876836..154e7a3512fb1b6e0267defb2c1453af02958ad2 100644
--- a/content/media/fmp4/wmf/WMFVideoDecoder.h
+++ b/content/media/fmp4/wmf/WMFVideoDecoder.h
@@ -20,21 +20,18 @@ class DXVA2Manager;
 
 class WMFVideoDecoder : public MediaDataDecoder {
 public:
-  WMFVideoDecoder(bool aDXVAEnabled);
+  WMFVideoDecoder(mozilla::layers::LayersBackend aLayersBackend,
+                  mozilla::layers::ImageContainer* aImageContainer,
+                  bool aDXVAEnabled);
   ~WMFVideoDecoder();
 
   // Decode thread.
-  nsresult Init(mozilla::layers::LayersBackend aLayersBackend,
-                mozilla::layers::ImageContainer* aImageContainer);
+  virtual nsresult Init() MOZ_OVERRIDE;
 
   virtual nsresult Shutdown() MOZ_OVERRIDE;
 
   // Inserts data into the decoder's pipeline.
-  virtual DecoderStatus Input(const uint8_t* aData,
-                              uint32_t aLength,
-                              Microseconds aDTS,
-                              Microseconds aPTS,
-                              int64_t aOffsetInStream) MOZ_OVERRIDE;
+  virtual DecoderStatus Input(nsAutoPtr<mp4_demuxer::MP4Sample>& aSample) MOZ_OVERRIDE;
 
   // Blocks until a decoded sample is produced by the decoder.
   virtual DecoderStatus Output(nsAutoPtr<MediaData>& aOutData) MOZ_OVERRIDE;
@@ -43,7 +40,7 @@ public:
 
 private:
 
-  bool InitializeDXVA(mozilla::layers::LayersBackend aLayersBackend);
+  bool InitializeDXVA();
 
   HRESULT ConfigureVideoFrameGeometry();
 
@@ -68,6 +65,7 @@ private:
   nsAutoPtr<DXVA2Manager> mDXVA2Manager;
 
   const bool mDXVAEnabled;
+  const layers::LayersBackend mLayersBackend;
   bool mUseHwAccel;
 };
 
diff --git a/content/moz.build b/content/moz.build
index 5acef5396ab7fe4f683e21d3b6401d808b9e3ccb..6c174ed42c03f628a9a456e8e7f49514984ab688 100644
--- a/content/moz.build
+++ b/content/moz.build
@@ -7,7 +7,6 @@
 PARALLEL_DIRS += [
     'base',
     'canvas',
-    'events',
     'html',
     'mathml/content/src',
     'media',
diff --git a/content/svg/content/src/moz.build b/content/svg/content/src/moz.build
index e6c261bb18645aebf23cba7975df29367c57f693..5d98a1de8cd0432cffa1543fb4083b27eef72083 100644
--- a/content/svg/content/src/moz.build
+++ b/content/svg/content/src/moz.build
@@ -250,10 +250,10 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/xml/content/src',
     '/dom',
+    '/dom/events',
     '/dom/smil',
     '/dom/xbl',
     '/layout/generic',
diff --git a/content/svg/document/src/moz.build b/content/svg/document/src/moz.build
index 37ee55efe59820f9ba6fe8e5d0dffac95c0cc273..e36ece87b985e606d3ca956aa979e57a1be0f3cf 100644
--- a/content/svg/document/src/moz.build
+++ b/content/svg/document/src/moz.build
@@ -16,10 +16,10 @@ FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/content/html/document/src',
     '/content/svg/content/src',
     '/content/xml/document/src',
+    '/dom/events',
     '/layout/style',
     '/xpcom/ds',
 ]
diff --git a/content/xml/document/src/moz.build b/content/xml/document/src/moz.build
index 824c6144f1acf517de723a58613712a5c9c13e78..f1aa5a54ad64b1db6a0ae5094ed9a2bb7c1ae9f2 100644
--- a/content/xml/document/src/moz.build
+++ b/content/xml/document/src/moz.build
@@ -22,10 +22,10 @@ MSVC_ENABLE_PGO = True
 LOCAL_INCLUDES += [
     '/caps/include',
     '/content/base/src',
-    '/content/events/src',
     '/content/html/document/src',
     '/content/xul/content/src',
     '/dom/base',
+    '/dom/events',
     '/layout/style',
     '/xpcom/ds',
     ]
diff --git a/content/xul/content/src/moz.build b/content/xul/content/src/moz.build
index 36586a1675d4eaa3f155ce82f81cf34f3b557562..2f7bba5ef85b04fc3923cc3e80ec71738f6972fc 100644
--- a/content/xul/content/src/moz.build
+++ b/content/xul/content/src/moz.build
@@ -19,10 +19,10 @@ LOCAL_INCLUDES += [
     '../../document/src',
     '../../templates/src',
     '/content/base/src',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/xml/content/src',
     '/content/xml/document/src',
+    '/dom/events',
     '/dom/xbl',
     '/layout/generic',
     '/layout/style',
diff --git a/content/xul/document/src/moz.build b/content/xul/document/src/moz.build
index d84f473b00fc8309ff89688b05d273d647d1c3c5..96ab4c5e960cc4cd9c1d5f3b20b6c3dfc448f61c 100644
--- a/content/xul/document/src/moz.build
+++ b/content/xul/document/src/moz.build
@@ -23,12 +23,12 @@ MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/templates/src',
     '/docshell/base',
     '/dom/base',
+    '/dom/events',
     '/dom/xbl',
     '/layout/base',
     '/layout/generic',
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index f7f9a4d0e98bca9944172c2fdd36c05d48eda7db..ce97ad23ae6a019c919a838cc376a78b17681518 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1815,8 +1815,15 @@ Navigator::HasNfcSupport(JSContext* /* unused */, JSObject* aGlobal)
   return win && (CheckPermission(win, "nfc-read") ||
                  CheckPermission(win, "nfc-write"));
 }
-#endif // MOZ_NFC
 
+/* static */
+bool
+Navigator::HasNfcPeerSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return win && CheckPermission(win, "nfc-write");
+}
+#endif // MOZ_NFC
 
 #ifdef MOZ_TIME_MANAGER
 /* static */
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
index 9a05a7cf29ae993f25d548dfd8cbb6d44772a3b5..534d3c615be110c757a65f23a9e4a336ebc21097 100644
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -273,6 +273,7 @@ public:
 #endif // MOZ_B2G_FM
 #ifdef MOZ_NFC
   static bool HasNfcSupport(JSContext* /* unused */, JSObject* aGlobal);
+  static bool HasNfcPeerSupport(JSContext* /* unused */, JSObject* aGlobal);
 #endif // MOZ_NFC
 #ifdef MOZ_TIME_MANAGER
   static bool HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal);
diff --git a/dom/base/moz.build b/dom/base/moz.build
index 8291326a3e76ad08173f68cda314cf875e0c21bc..2e15493ab83a06f8419d2590c83b0f7689f86dde 100644
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -29,7 +29,6 @@ EXPORTS += [
     'nsIDOMClassInfo.h',
     'nsIDOMScriptObjectFactory.h',
     'nsIGlobalObject.h',
-    'nsIJSEventListener.h',
     'nsIJSNativeInitializer.h',
     'nsIScriptContext.h',
     'nsIScriptExternalNameSet.h',
@@ -138,6 +137,7 @@ MSVC_ENABLE_PGO = True
 LOCAL_INCLUDES += [
     '../battery',
     '../bluetooth',
+    '../events',
     '../media',
     '../network/src',
     '../src/geolocation',
@@ -145,7 +145,6 @@ LOCAL_INCLUDES += [
     '../time',
     '../xbl',
     '/content/base/src',
-    '/content/events/src',
     '/content/html/document/src',
     '/content/xul/document/src',
     '/layout/generic',
diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp
index b4f6b65805eaeb95c0e3499d5d9df17010090e18..2ddf19e9fe1b595483536d11d8f20e535b8d8e34 100644
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -171,6 +171,46 @@ MOZ_DEFINE_MALLOC_SIZE_OF(WindowsMallocSizeOf)
 // The key is the window ID.
 typedef nsDataHashtable<nsUint64HashKey, nsCString> WindowPaths;
 
+static nsresult
+ReportAmount(const nsCString& aBasePath, const char* aPathTail,
+             size_t aAmount, const nsCString& aDescription,
+             uint32_t aKind, uint32_t aUnits,
+             nsIMemoryReporterCallback* aCb,
+             nsISupports* aClosure)
+{
+  if (aAmount == 0) {
+    return NS_OK;
+  }
+
+  nsAutoCString path(aBasePath);
+  path += aPathTail;
+
+  return aCb->Callback(EmptyCString(), path, aKind, aUnits,
+                       aAmount, aDescription, aClosure);
+}
+
+static nsresult
+ReportSize(const nsCString& aBasePath, const char* aPathTail,
+           size_t aAmount, const nsCString& aDescription,
+           nsIMemoryReporterCallback* aCb,
+           nsISupports* aClosure)
+{
+  return ReportAmount(aBasePath, aPathTail, aAmount, aDescription,
+                      nsIMemoryReporter::KIND_HEAP,
+                      nsIMemoryReporter::UNITS_BYTES, aCb, aClosure);
+}
+
+static nsresult
+ReportCount(const nsCString& aBasePath, const char* aPathTail,
+            size_t aAmount, const nsCString& aDescription,
+            nsIMemoryReporterCallback* aCb,
+            nsISupports* aClosure)
+{
+  return ReportAmount(aBasePath, aPathTail, aAmount, aDescription,
+                      nsIMemoryReporter::KIND_OTHER,
+                      nsIMemoryReporter::UNITS_COUNT, aCb, aClosure);
+}
+
 static nsresult
 CollectWindowReports(nsGlobalWindow *aWindow,
                      amIAddonManager *addonManager,
@@ -242,28 +282,16 @@ CollectWindowReports(nsGlobalWindow *aWindow,
 
 #define REPORT_SIZE(_pathTail, _amount, _desc)                                \
   do {                                                                        \
-    if (_amount > 0) {                                                        \
-      nsAutoCString path(windowPath);                                         \
-      path += _pathTail;                                                      \
-      nsresult rv;                                                            \
-      rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,  \
-                    nsIMemoryReporter::UNITS_BYTES, _amount,                  \
-                    NS_LITERAL_CSTRING(_desc), aClosure);                     \
-      NS_ENSURE_SUCCESS(rv, rv);                                              \
-    }                                                                         \
+    nsresult rv = ReportSize(windowPath, _pathTail, _amount,                  \
+                             NS_LITERAL_CSTRING(_desc), aCb, aClosure);       \
+    NS_ENSURE_SUCCESS(rv, rv);                                                \
   } while (0)
 
 #define REPORT_COUNT(_pathTail, _amount, _desc)                               \
   do {                                                                        \
-    if (_amount > 0) {                                                        \
-      nsAutoCString path(censusWindowPath);                                   \
-      path += _pathTail;                                                      \
-      nsresult rv;                                                            \
-      rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_OTHER, \
-                    nsIMemoryReporter::UNITS_COUNT, _amount,                  \
-                    NS_LITERAL_CSTRING(_desc), aClosure);                     \
-      NS_ENSURE_SUCCESS(rv, rv);                                              \
-    }                                                                         \
+    nsresult rv = ReportCount(censusWindowPath, _pathTail, _amount,           \
+                              NS_LITERAL_CSTRING(_desc), aCb, aClosure);      \
+    NS_ENSURE_SUCCESS(rv, rv);                                                \
   } while (0)
 
   nsWindowSizes windowSizes(WindowsMallocSizeOf);
diff --git a/dom/battery/moz.build b/dom/battery/moz.build
index 830d2d97835b9a0121833a482065cab286b5dd02..9ed898a353391b71d209e6382f7625d8e0e427b0 100644
--- a/dom/battery/moz.build
+++ b/dom/battery/moz.build
@@ -21,6 +21,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
 ]
 
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 753831aad8562610b51951a9a48e2bcefc80e505..941ad5f2dbb7c3edbe9db65362a71872024f2c43 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4079,7 +4079,7 @@ def instantiateJSToNativeConversion(info, replacements, checkForValue=False):
 
 def convertConstIDLValueToJSVal(value):
     if isinstance(value, IDLNullValue):
-        return "JSVAL_NULL"
+        return "JS::NullValue()"
     tag = value.type.tag()
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
@@ -4265,7 +4265,34 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
     # if body.
     exceptionCodeIndented = CGIndenter(CGGeneric(exceptionCode))
 
-    def setValue(value, wrapAsType=None):
+    def setUndefined():
+        return _setValue("", setter="setUndefined")
+
+    def setNull():
+        return _setValue("", setter="setNull")
+
+    def setInt32(value):
+        return _setValue(value, setter="setInt32")
+
+    def setString(value):
+        return _setValue(value, setter="setString")
+
+    def setObject(value, wrapAsType=None):
+        return _setValue(value, wrapAsType=wrapAsType, setter="setObject")
+
+    def setObjectOrNull(value, wrapAsType=None):
+        return _setValue(value, wrapAsType=wrapAsType, setter="setObjectOrNull")
+
+    def setUint32(value):
+        return _setValue(value, setter="setNumber")
+
+    def setDouble(value):
+        return _setValue("JS_NumberValue(%s)" % value)
+
+    def setBoolean(value):
+        return _setValue(value, setter="setBoolean")
+
+    def _setValue(value, wrapAsType=None, setter="set"):
         """
         Returns the code to set the jsval to value.
 
@@ -4281,8 +4308,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
                                exceptionCodeIndented.define())) +
                     "}\n" +
                     successCode)
-        return ("${jsvalRef}.set(%s);\n" +
-                tail) % (value)
+        return ("${jsvalRef}.%s(%s);\n" +
+                tail) % (setter, value)
 
     def wrapAndSetPtr(wrapCall, failureCode=None):
         """
@@ -4298,7 +4325,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
         return str
 
     if type is None or type.isVoid():
-        return (setValue("JSVAL_VOID"), True)
+        return (setUndefined(), True)
 
     if type.isArray():
         raise TypeError("Can't handle array return values yet")
@@ -4314,7 +4341,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
 if (%s.IsNull()) {
 %s
 }
-%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), recTemplate), recInfall)
+%s""" % (result, CGIndenter(CGGeneric(setNull())).define(), recTemplate), recInfall)
 
         # Now do non-nullable sequences.  Our success code is just to break to
         # where we set the element in the array.  Note that we bump the
@@ -4361,13 +4388,13 @@ if (!returnArray) {
           index, index, index,
           innerTemplate, index,
           CGIndenter(exceptionCodeIndented, 4).define())) +
-                setValue("JS::ObjectValue(*returnArray)"), False)
+                setObject("*returnArray"), False)
 
     if type.isGeckoInterface() and not type.isCallbackInterface():
         descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
         if type.nullable():
             wrappingCode = ("if (!%s) {\n" % (result) +
-                            CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
+                            CGIndenter(CGGeneric(setNull())).define() + "\n" +
                             "}\n")
         else:
             wrappingCode = ""
@@ -4434,26 +4461,26 @@ if (!returnArray) {
 """ % { "result" : resultLoc,
         "strings" : type.unroll().inner.identifier.name + "Values::" + ENUM_ENTRY_VARIABLE_NAME,
         "exceptionCode" : CGIndenter(exceptionCodeIndented).define() } +
-        CGIndenter(CGGeneric(setValue("JS::StringValue(resultStr)"))).define() +
+        CGIndenter(CGGeneric(setString("resultStr"))).define() +
                       "\n}")
 
         if type.nullable():
             conversion = CGIfElseWrapper(
                 "%s.IsNull()" % result,
-                CGGeneric(setValue("JS::NullValue()")),
+                CGGeneric(setNull()),
                 CGGeneric(conversion)).define()
         return conversion, False
 
     if type.isCallback() or type.isCallbackInterface():
-        wrapCode = setValue(
-            "JS::ObjectValue(*GetCallbackFromCallbackObject(%(result)s))",
+        wrapCode = setObject(
+            "*GetCallbackFromCallbackObject(%(result)s)",
             wrapAsType=type)
         if type.nullable():
             wrapCode = (
                 "if (%(result)s) {\n" +
                 CGIndenter(CGGeneric(wrapCode)).define() + "\n"
                 "} else {\n" +
-                CGIndenter(CGGeneric(setValue("JS::NullValue()"))).define() + "\n"
+                CGIndenter(CGGeneric(setNull())).define() + "\n"
                 "}")
         wrapCode = wrapCode % { "result": result }
         return wrapCode, False
@@ -4461,19 +4488,21 @@ if (!returnArray) {
     if type.isAny():
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
-        # NB: setValue(..., type-that-is-any) calls JS_WrapValue(), so is fallible
-        return (setValue(result, wrapAsType=type), False)
+        # NB: _setValue(..., type-that-is-any) calls JS_WrapValue(), so is fallible
+        return (_setValue(result, wrapAsType=type), False)
 
     if (type.isObject() or (type.isSpiderMonkeyInterface() and
                             not typedArraysAreStructs)):
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
         if type.nullable():
-            toValue = "JS::ObjectOrNullValue(%s)"
+            toValue = "%s"
+            setter = setObjectOrNull
         else:
-            toValue = "JS::ObjectValue(*%s)"
-        # NB: setValue(..., some-object-type) calls JS_WrapValue(), so is fallible
-        return (setValue(toValue % result, wrapAsType=type), False)
+            toValue = "*%s"
+            setter = setObject
+        # NB: setObject{,OrNull}(..., some-object-type) calls JS_WrapValue(), so is fallible
+        return (setter(toValue % result, wrapAsType=type), False)
 
     if not (type.isUnion() or type.isPrimitive() or type.isDictionary() or
             type.isDate() or
@@ -4486,16 +4515,16 @@ if (!returnArray) {
                                                          returnsNewObject, exceptionCode,
                                                          typedArraysAreStructs)
         return ("if (%s.IsNull()) {\n" % result +
-                CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
+                CGIndenter(CGGeneric(setNull())).define() + "\n" +
                 "}\n" + recTemplate, recInfal)
 
     if type.isSpiderMonkeyInterface():
         assert typedArraysAreStructs
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
-        # NB: setValue(..., some-object-type) calls JS_WrapValue(), so is fallible
-        return (setValue("JS::ObjectValue(*%s.Obj())" % result,
-                         wrapAsType=type), False)
+        # NB: setObject(..., some-object-type) calls JS_WrapValue(), so is fallible
+        return (setObject("*%s.Obj()" % result,
+                          wrapAsType=type), False)
 
     if type.isUnion():
         return (wrapAndSetPtr("%s.ToJSVal(cx, ${obj}, ${jsvalHandle})" % result),
@@ -4513,20 +4542,20 @@ if (!returnArray) {
 
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
-        return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
+        return (setInt32("int32_t(%s)" % result), True)
 
     elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64,
                  IDLType.Tags.unrestricted_float, IDLType.Tags.float,
                  IDLType.Tags.unrestricted_double, IDLType.Tags.double]:
         # XXXbz will cast to double do the "even significand" thing that webidl
         # calls for for 64-bit ints?  Do we care?
-        return (setValue("JS_NumberValue(double(%s))" % result), True)
+        return (setDouble("double(%s)" % result), True)
 
     elif tag == IDLType.Tags.uint32:
-        return (setValue("UINT_TO_JSVAL(%s)" % result), True)
+        return (setUint32(result), True)
 
     elif tag == IDLType.Tags.bool:
-        return (setValue("BOOLEAN_TO_JSVAL(%s)" % result), True)
+        return (setBoolean(result), True)
 
     else:
         raise TypeError("Need to learn to wrap primitive: %s" % type)
@@ -5042,7 +5071,7 @@ class CGPerSignatureCall(CGThing):
             if setter:
                 lenientFloatCode = "return true;"
             elif idlNode.isMethod():
-                lenientFloatCode = ("args.rval().set(JSVAL_VOID);\n"
+                lenientFloatCode = ("args.rval().setUndefined();\n"
                                     "return true;")
 
         argsPre = []
@@ -8660,6 +8689,10 @@ class CGDescriptor(CGThing):
                     else:
                         hasMethod = True
             elif m.isAttr():
+                if m.stringifier:
+                    raise TypeError("Stringifier attributes not supported yet. "
+                                    "See bug 824857.\n"
+                                    "%s" % m.location);
                 if m.isStatic():
                     assert descriptor.interface.hasInterfaceObject
                     cgThings.append(CGStaticGetter(descriptor, m))
@@ -8672,6 +8705,12 @@ class CGDescriptor(CGThing):
                     else:
                         hasGetter = True
                 if not m.readonly:
+                    for extAttr in ["PutForwards", "Replaceable"]:
+                        if m.getExtendedAttribute(extAttr):
+                            raise TypeError("Writable attributes should not "
+                                            "have %s specified.\n"
+                                            "%s" %
+                                            (extAttr, m.location))
                     if m.isStatic():
                         assert descriptor.interface.hasInterfaceObject
                         cgThings.append(CGStaticSetter(descriptor, m))
diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build
index ae08ee53c90c7d22401b3466a1d3906192809048..594f13a9c8ae786d8dc63d6704f0d1ae5dcb84e8 100644
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -40,7 +40,6 @@ MSVC_ENABLE_PGO = True
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/canvas/src',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/media/webaudio',
@@ -53,6 +52,7 @@ LOCAL_INCLUDES += [
     '/dom/battery',
     '/dom/bluetooth',
     '/dom/camera',
+    '/dom/events',
     '/dom/file',
     '/dom/indexedDB',
     '/dom/src/geolocation',
diff --git a/dom/devicestorage/moz.build b/dom/devicestorage/moz.build
index 8a3d2df082fa1dc7008045120c9a68b1e181ba61..d1fa4ebda155d642f2d395a2cf80976cfc08b0fa 100644
--- a/dom/devicestorage/moz.build
+++ b/dom/devicestorage/moz.build
@@ -33,8 +33,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/dom/base',
+    '/dom/events',
     '/dom/ipc',
 ]
 
diff --git a/content/events/src/DOMWheelEvent.cpp b/dom/events/DOMWheelEvent.cpp
similarity index 100%
rename from content/events/src/DOMWheelEvent.cpp
rename to dom/events/DOMWheelEvent.cpp
diff --git a/content/events/src/DOMWheelEvent.h b/dom/events/DOMWheelEvent.h
similarity index 100%
rename from content/events/src/DOMWheelEvent.h
rename to dom/events/DOMWheelEvent.h
diff --git a/content/events/src/EventTarget.cpp b/dom/events/EventTarget.cpp
similarity index 100%
rename from content/events/src/EventTarget.cpp
rename to dom/events/EventTarget.cpp
diff --git a/content/events/public/EventTarget.h b/dom/events/EventTarget.h
similarity index 100%
rename from content/events/public/EventTarget.h
rename to dom/events/EventTarget.h
diff --git a/content/events/public/MutationEvent.h b/dom/events/MutationEvent.h
similarity index 100%
rename from content/events/public/MutationEvent.h
rename to dom/events/MutationEvent.h
diff --git a/content/events/src/PointerEvent.cpp b/dom/events/PointerEvent.cpp
similarity index 100%
rename from content/events/src/PointerEvent.cpp
rename to dom/events/PointerEvent.cpp
diff --git a/content/events/src/PointerEvent.h b/dom/events/PointerEvent.h
similarity index 100%
rename from content/events/src/PointerEvent.h
rename to dom/events/PointerEvent.h
diff --git a/content/events/src/SpeechRecognitionError.cpp b/dom/events/SpeechRecognitionError.cpp
similarity index 100%
rename from content/events/src/SpeechRecognitionError.cpp
rename to dom/events/SpeechRecognitionError.cpp
diff --git a/content/events/src/SpeechRecognitionError.h b/dom/events/SpeechRecognitionError.h
similarity index 100%
rename from content/events/src/SpeechRecognitionError.h
rename to dom/events/SpeechRecognitionError.h
diff --git a/content/events/src/TextComposition.cpp b/dom/events/TextComposition.cpp
similarity index 100%
rename from content/events/src/TextComposition.cpp
rename to dom/events/TextComposition.cpp
diff --git a/content/events/src/TextComposition.h b/dom/events/TextComposition.h
similarity index 100%
rename from content/events/src/TextComposition.h
rename to dom/events/TextComposition.h
diff --git a/content/events/src/Touch.cpp b/dom/events/Touch.cpp
similarity index 100%
rename from content/events/src/Touch.cpp
rename to dom/events/Touch.cpp
diff --git a/content/events/src/Touch.h b/dom/events/Touch.h
similarity index 100%
rename from content/events/src/Touch.h
rename to dom/events/Touch.h
diff --git a/content/events/crashtests/104310-1.html b/dom/events/crashtests/104310-1.html
similarity index 100%
rename from content/events/crashtests/104310-1.html
rename to dom/events/crashtests/104310-1.html
diff --git a/content/events/crashtests/116206-1.html b/dom/events/crashtests/116206-1.html
similarity index 100%
rename from content/events/crashtests/116206-1.html
rename to dom/events/crashtests/116206-1.html
diff --git a/content/events/crashtests/135345-1.html b/dom/events/crashtests/135345-1.html
similarity index 100%
rename from content/events/crashtests/135345-1.html
rename to dom/events/crashtests/135345-1.html
diff --git a/content/events/crashtests/422009-1.xhtml b/dom/events/crashtests/422009-1.xhtml
similarity index 100%
rename from content/events/crashtests/422009-1.xhtml
rename to dom/events/crashtests/422009-1.xhtml
diff --git a/content/events/crashtests/457776-1.html b/dom/events/crashtests/457776-1.html
similarity index 100%
rename from content/events/crashtests/457776-1.html
rename to dom/events/crashtests/457776-1.html
diff --git a/content/events/crashtests/496308-1.html b/dom/events/crashtests/496308-1.html
similarity index 100%
rename from content/events/crashtests/496308-1.html
rename to dom/events/crashtests/496308-1.html
diff --git a/content/events/crashtests/682637-1.html b/dom/events/crashtests/682637-1.html
similarity index 100%
rename from content/events/crashtests/682637-1.html
rename to dom/events/crashtests/682637-1.html
diff --git a/content/events/crashtests/crashtests.list b/dom/events/crashtests/crashtests.list
similarity index 100%
rename from content/events/crashtests/crashtests.list
rename to dom/events/crashtests/crashtests.list
diff --git a/content/events/crashtests/eventctor-nulldictionary.html b/dom/events/crashtests/eventctor-nulldictionary.html
similarity index 100%
rename from content/events/crashtests/eventctor-nulldictionary.html
rename to dom/events/crashtests/eventctor-nulldictionary.html
diff --git a/content/events/crashtests/eventctor-nullstorage.html b/dom/events/crashtests/eventctor-nullstorage.html
similarity index 100%
rename from content/events/crashtests/eventctor-nullstorage.html
rename to dom/events/crashtests/eventctor-nullstorage.html
diff --git a/content/events/crashtests/recursive-DOMNodeInserted.html b/dom/events/crashtests/recursive-DOMNodeInserted.html
similarity index 100%
rename from content/events/crashtests/recursive-DOMNodeInserted.html
rename to dom/events/crashtests/recursive-DOMNodeInserted.html
diff --git a/content/events/crashtests/recursive-onload.html b/dom/events/crashtests/recursive-onload.html
similarity index 100%
rename from content/events/crashtests/recursive-onload.html
rename to dom/events/crashtests/recursive-onload.html
diff --git a/content/events/src/moz.build b/dom/events/moz.build
similarity index 83%
rename from content/events/src/moz.build
rename to dom/events/moz.build
index 285a66459832c9dccadcb8ce72219f217c63f5c3..516babeb4e947b56cfd24c700d45b08c81876291 100644
--- a/content/events/src/moz.build
+++ b/dom/events/moz.build
@@ -4,16 +4,39 @@
 # 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/.
 
+MOCHITEST_MANIFESTS += ['test/mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
+
+XPIDL_SOURCES += [
+    'nsIEventListenerService.idl',
+]
+
+XPIDL_MODULE = 'content_events'
+
 EXPORTS += [
+    'nsAsyncDOMEvent.h',
     'nsDOMEvent.h',
     'nsDOMEventTargetHelper.h',
+    'nsDOMKeyNameList.h',
     'nsDOMTouchEvent.h',
     'nsDOMUIEvent.h',
+    'nsEventDispatcher.h',
     'nsEventListenerManager.h',
+    'nsEventNameList.h',
     'nsEventStateManager.h',
+    'nsEventStates.h',
+    'nsIJSEventListener.h',
+    'nsIPrivateTextEvent.h',
+    'nsIPrivateTextRange.h',
+    'nsVKList.h',
+]
+
+EXPORTS.mozilla += [
+    'MutationEvent.h',
 ]
 
 EXPORTS.mozilla.dom += [
+    'EventTarget.h',
     'PointerEvent.h',
     'Touch.h',
 ]
@@ -56,6 +79,7 @@ UNIFIED_SOURCES += [
     'nsEventListenerManager.cpp',
     'nsEventListenerService.cpp',
     'nsIMEStateManager.cpp',
+    'nsJSEventListener.cpp',
     'nsPaintRequest.cpp',
     'nsPrivateTextRange.cpp',
     'PointerEvent.cpp',
diff --git a/content/events/src/nsAsyncDOMEvent.cpp b/dom/events/nsAsyncDOMEvent.cpp
similarity index 100%
rename from content/events/src/nsAsyncDOMEvent.cpp
rename to dom/events/nsAsyncDOMEvent.cpp
diff --git a/content/events/public/nsAsyncDOMEvent.h b/dom/events/nsAsyncDOMEvent.h
similarity index 100%
rename from content/events/public/nsAsyncDOMEvent.h
rename to dom/events/nsAsyncDOMEvent.h
diff --git a/content/events/src/nsContentEventHandler.cpp b/dom/events/nsContentEventHandler.cpp
similarity index 100%
rename from content/events/src/nsContentEventHandler.cpp
rename to dom/events/nsContentEventHandler.cpp
diff --git a/content/events/src/nsContentEventHandler.h b/dom/events/nsContentEventHandler.h
similarity index 100%
rename from content/events/src/nsContentEventHandler.h
rename to dom/events/nsContentEventHandler.h
diff --git a/content/events/src/nsDOMAnimationEvent.cpp b/dom/events/nsDOMAnimationEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMAnimationEvent.cpp
rename to dom/events/nsDOMAnimationEvent.cpp
diff --git a/content/events/src/nsDOMAnimationEvent.h b/dom/events/nsDOMAnimationEvent.h
similarity index 100%
rename from content/events/src/nsDOMAnimationEvent.h
rename to dom/events/nsDOMAnimationEvent.h
diff --git a/content/events/src/nsDOMBeforeUnloadEvent.cpp b/dom/events/nsDOMBeforeUnloadEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMBeforeUnloadEvent.cpp
rename to dom/events/nsDOMBeforeUnloadEvent.cpp
diff --git a/content/events/src/nsDOMBeforeUnloadEvent.h b/dom/events/nsDOMBeforeUnloadEvent.h
similarity index 100%
rename from content/events/src/nsDOMBeforeUnloadEvent.h
rename to dom/events/nsDOMBeforeUnloadEvent.h
diff --git a/content/events/src/nsDOMClipboardEvent.cpp b/dom/events/nsDOMClipboardEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMClipboardEvent.cpp
rename to dom/events/nsDOMClipboardEvent.cpp
diff --git a/content/events/src/nsDOMClipboardEvent.h b/dom/events/nsDOMClipboardEvent.h
similarity index 100%
rename from content/events/src/nsDOMClipboardEvent.h
rename to dom/events/nsDOMClipboardEvent.h
diff --git a/content/events/src/nsDOMCommandEvent.cpp b/dom/events/nsDOMCommandEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMCommandEvent.cpp
rename to dom/events/nsDOMCommandEvent.cpp
diff --git a/content/events/src/nsDOMCommandEvent.h b/dom/events/nsDOMCommandEvent.h
similarity index 100%
rename from content/events/src/nsDOMCommandEvent.h
rename to dom/events/nsDOMCommandEvent.h
diff --git a/content/events/src/nsDOMCompositionEvent.cpp b/dom/events/nsDOMCompositionEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMCompositionEvent.cpp
rename to dom/events/nsDOMCompositionEvent.cpp
diff --git a/content/events/src/nsDOMCompositionEvent.h b/dom/events/nsDOMCompositionEvent.h
similarity index 100%
rename from content/events/src/nsDOMCompositionEvent.h
rename to dom/events/nsDOMCompositionEvent.h
diff --git a/content/events/src/nsDOMDataContainerEvent.cpp b/dom/events/nsDOMDataContainerEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMDataContainerEvent.cpp
rename to dom/events/nsDOMDataContainerEvent.cpp
diff --git a/content/events/src/nsDOMDataContainerEvent.h b/dom/events/nsDOMDataContainerEvent.h
similarity index 100%
rename from content/events/src/nsDOMDataContainerEvent.h
rename to dom/events/nsDOMDataContainerEvent.h
diff --git a/content/events/src/nsDOMDataTransfer.cpp b/dom/events/nsDOMDataTransfer.cpp
similarity index 100%
rename from content/events/src/nsDOMDataTransfer.cpp
rename to dom/events/nsDOMDataTransfer.cpp
diff --git a/content/events/src/nsDOMDataTransfer.h b/dom/events/nsDOMDataTransfer.h
similarity index 100%
rename from content/events/src/nsDOMDataTransfer.h
rename to dom/events/nsDOMDataTransfer.h
diff --git a/content/events/src/nsDOMDeviceMotionEvent.cpp b/dom/events/nsDOMDeviceMotionEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMDeviceMotionEvent.cpp
rename to dom/events/nsDOMDeviceMotionEvent.cpp
diff --git a/content/events/src/nsDOMDeviceMotionEvent.h b/dom/events/nsDOMDeviceMotionEvent.h
similarity index 100%
rename from content/events/src/nsDOMDeviceMotionEvent.h
rename to dom/events/nsDOMDeviceMotionEvent.h
diff --git a/content/events/src/nsDOMDragEvent.cpp b/dom/events/nsDOMDragEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMDragEvent.cpp
rename to dom/events/nsDOMDragEvent.cpp
diff --git a/content/events/src/nsDOMDragEvent.h b/dom/events/nsDOMDragEvent.h
similarity index 100%
rename from content/events/src/nsDOMDragEvent.h
rename to dom/events/nsDOMDragEvent.h
diff --git a/content/events/src/nsDOMEvent.cpp b/dom/events/nsDOMEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMEvent.cpp
rename to dom/events/nsDOMEvent.cpp
diff --git a/content/events/src/nsDOMEvent.h b/dom/events/nsDOMEvent.h
similarity index 100%
rename from content/events/src/nsDOMEvent.h
rename to dom/events/nsDOMEvent.h
diff --git a/content/events/src/nsDOMEventTargetHelper.cpp b/dom/events/nsDOMEventTargetHelper.cpp
similarity index 100%
rename from content/events/src/nsDOMEventTargetHelper.cpp
rename to dom/events/nsDOMEventTargetHelper.cpp
diff --git a/content/events/src/nsDOMEventTargetHelper.h b/dom/events/nsDOMEventTargetHelper.h
similarity index 100%
rename from content/events/src/nsDOMEventTargetHelper.h
rename to dom/events/nsDOMEventTargetHelper.h
diff --git a/content/events/src/nsDOMFocusEvent.cpp b/dom/events/nsDOMFocusEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMFocusEvent.cpp
rename to dom/events/nsDOMFocusEvent.cpp
diff --git a/content/events/src/nsDOMFocusEvent.h b/dom/events/nsDOMFocusEvent.h
similarity index 100%
rename from content/events/src/nsDOMFocusEvent.h
rename to dom/events/nsDOMFocusEvent.h
diff --git a/content/events/public/nsDOMKeyNameList.h b/dom/events/nsDOMKeyNameList.h
similarity index 100%
rename from content/events/public/nsDOMKeyNameList.h
rename to dom/events/nsDOMKeyNameList.h
diff --git a/content/events/src/nsDOMKeyboardEvent.cpp b/dom/events/nsDOMKeyboardEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMKeyboardEvent.cpp
rename to dom/events/nsDOMKeyboardEvent.cpp
diff --git a/content/events/src/nsDOMKeyboardEvent.h b/dom/events/nsDOMKeyboardEvent.h
similarity index 100%
rename from content/events/src/nsDOMKeyboardEvent.h
rename to dom/events/nsDOMKeyboardEvent.h
diff --git a/content/events/src/nsDOMMessageEvent.cpp b/dom/events/nsDOMMessageEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMMessageEvent.cpp
rename to dom/events/nsDOMMessageEvent.cpp
diff --git a/content/events/src/nsDOMMessageEvent.h b/dom/events/nsDOMMessageEvent.h
similarity index 100%
rename from content/events/src/nsDOMMessageEvent.h
rename to dom/events/nsDOMMessageEvent.h
diff --git a/content/events/src/nsDOMMouseEvent.cpp b/dom/events/nsDOMMouseEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMMouseEvent.cpp
rename to dom/events/nsDOMMouseEvent.cpp
diff --git a/content/events/src/nsDOMMouseEvent.h b/dom/events/nsDOMMouseEvent.h
similarity index 100%
rename from content/events/src/nsDOMMouseEvent.h
rename to dom/events/nsDOMMouseEvent.h
diff --git a/content/events/src/nsDOMMouseScrollEvent.cpp b/dom/events/nsDOMMouseScrollEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMMouseScrollEvent.cpp
rename to dom/events/nsDOMMouseScrollEvent.cpp
diff --git a/content/events/src/nsDOMMouseScrollEvent.h b/dom/events/nsDOMMouseScrollEvent.h
similarity index 100%
rename from content/events/src/nsDOMMouseScrollEvent.h
rename to dom/events/nsDOMMouseScrollEvent.h
diff --git a/content/events/src/nsDOMMutationEvent.cpp b/dom/events/nsDOMMutationEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMMutationEvent.cpp
rename to dom/events/nsDOMMutationEvent.cpp
diff --git a/content/events/src/nsDOMMutationEvent.h b/dom/events/nsDOMMutationEvent.h
similarity index 100%
rename from content/events/src/nsDOMMutationEvent.h
rename to dom/events/nsDOMMutationEvent.h
diff --git a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp b/dom/events/nsDOMNotifyAudioAvailableEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
rename to dom/events/nsDOMNotifyAudioAvailableEvent.cpp
diff --git a/content/events/src/nsDOMNotifyAudioAvailableEvent.h b/dom/events/nsDOMNotifyAudioAvailableEvent.h
similarity index 100%
rename from content/events/src/nsDOMNotifyAudioAvailableEvent.h
rename to dom/events/nsDOMNotifyAudioAvailableEvent.h
diff --git a/content/events/src/nsDOMNotifyPaintEvent.cpp b/dom/events/nsDOMNotifyPaintEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMNotifyPaintEvent.cpp
rename to dom/events/nsDOMNotifyPaintEvent.cpp
diff --git a/content/events/src/nsDOMNotifyPaintEvent.h b/dom/events/nsDOMNotifyPaintEvent.h
similarity index 100%
rename from content/events/src/nsDOMNotifyPaintEvent.h
rename to dom/events/nsDOMNotifyPaintEvent.h
diff --git a/content/events/src/nsDOMScrollAreaEvent.cpp b/dom/events/nsDOMScrollAreaEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMScrollAreaEvent.cpp
rename to dom/events/nsDOMScrollAreaEvent.cpp
diff --git a/content/events/src/nsDOMScrollAreaEvent.h b/dom/events/nsDOMScrollAreaEvent.h
similarity index 100%
rename from content/events/src/nsDOMScrollAreaEvent.h
rename to dom/events/nsDOMScrollAreaEvent.h
diff --git a/content/events/src/nsDOMSimpleGestureEvent.cpp b/dom/events/nsDOMSimpleGestureEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMSimpleGestureEvent.cpp
rename to dom/events/nsDOMSimpleGestureEvent.cpp
diff --git a/content/events/src/nsDOMSimpleGestureEvent.h b/dom/events/nsDOMSimpleGestureEvent.h
similarity index 100%
rename from content/events/src/nsDOMSimpleGestureEvent.h
rename to dom/events/nsDOMSimpleGestureEvent.h
diff --git a/content/events/src/nsDOMTextEvent.cpp b/dom/events/nsDOMTextEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMTextEvent.cpp
rename to dom/events/nsDOMTextEvent.cpp
diff --git a/content/events/src/nsDOMTextEvent.h b/dom/events/nsDOMTextEvent.h
similarity index 100%
rename from content/events/src/nsDOMTextEvent.h
rename to dom/events/nsDOMTextEvent.h
diff --git a/content/events/src/nsDOMTouchEvent.cpp b/dom/events/nsDOMTouchEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMTouchEvent.cpp
rename to dom/events/nsDOMTouchEvent.cpp
diff --git a/content/events/src/nsDOMTouchEvent.h b/dom/events/nsDOMTouchEvent.h
similarity index 100%
rename from content/events/src/nsDOMTouchEvent.h
rename to dom/events/nsDOMTouchEvent.h
diff --git a/content/events/src/nsDOMTransitionEvent.cpp b/dom/events/nsDOMTransitionEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMTransitionEvent.cpp
rename to dom/events/nsDOMTransitionEvent.cpp
diff --git a/content/events/src/nsDOMTransitionEvent.h b/dom/events/nsDOMTransitionEvent.h
similarity index 100%
rename from content/events/src/nsDOMTransitionEvent.h
rename to dom/events/nsDOMTransitionEvent.h
diff --git a/content/events/src/nsDOMUIEvent.cpp b/dom/events/nsDOMUIEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMUIEvent.cpp
rename to dom/events/nsDOMUIEvent.cpp
diff --git a/content/events/src/nsDOMUIEvent.h b/dom/events/nsDOMUIEvent.h
similarity index 100%
rename from content/events/src/nsDOMUIEvent.h
rename to dom/events/nsDOMUIEvent.h
diff --git a/content/events/src/nsDOMXULCommandEvent.cpp b/dom/events/nsDOMXULCommandEvent.cpp
similarity index 100%
rename from content/events/src/nsDOMXULCommandEvent.cpp
rename to dom/events/nsDOMXULCommandEvent.cpp
diff --git a/content/events/src/nsDOMXULCommandEvent.h b/dom/events/nsDOMXULCommandEvent.h
similarity index 100%
rename from content/events/src/nsDOMXULCommandEvent.h
rename to dom/events/nsDOMXULCommandEvent.h
diff --git a/content/events/src/nsEventDispatcher.cpp b/dom/events/nsEventDispatcher.cpp
similarity index 100%
rename from content/events/src/nsEventDispatcher.cpp
rename to dom/events/nsEventDispatcher.cpp
diff --git a/content/events/public/nsEventDispatcher.h b/dom/events/nsEventDispatcher.h
similarity index 100%
rename from content/events/public/nsEventDispatcher.h
rename to dom/events/nsEventDispatcher.h
diff --git a/content/events/src/nsEventListenerManager.cpp b/dom/events/nsEventListenerManager.cpp
similarity index 100%
rename from content/events/src/nsEventListenerManager.cpp
rename to dom/events/nsEventListenerManager.cpp
diff --git a/content/events/src/nsEventListenerManager.h b/dom/events/nsEventListenerManager.h
similarity index 100%
rename from content/events/src/nsEventListenerManager.h
rename to dom/events/nsEventListenerManager.h
diff --git a/content/events/src/nsEventListenerService.cpp b/dom/events/nsEventListenerService.cpp
similarity index 100%
rename from content/events/src/nsEventListenerService.cpp
rename to dom/events/nsEventListenerService.cpp
diff --git a/content/events/src/nsEventListenerService.h b/dom/events/nsEventListenerService.h
similarity index 100%
rename from content/events/src/nsEventListenerService.h
rename to dom/events/nsEventListenerService.h
diff --git a/content/events/public/nsEventNameList.h b/dom/events/nsEventNameList.h
similarity index 100%
rename from content/events/public/nsEventNameList.h
rename to dom/events/nsEventNameList.h
diff --git a/content/events/src/nsEventStateManager.cpp b/dom/events/nsEventStateManager.cpp
similarity index 100%
rename from content/events/src/nsEventStateManager.cpp
rename to dom/events/nsEventStateManager.cpp
diff --git a/content/events/src/nsEventStateManager.h b/dom/events/nsEventStateManager.h
similarity index 100%
rename from content/events/src/nsEventStateManager.h
rename to dom/events/nsEventStateManager.h
diff --git a/content/events/public/nsEventStates.h b/dom/events/nsEventStates.h
similarity index 100%
rename from content/events/public/nsEventStates.h
rename to dom/events/nsEventStates.h
diff --git a/content/events/public/nsIEventListenerService.idl b/dom/events/nsIEventListenerService.idl
similarity index 100%
rename from content/events/public/nsIEventListenerService.idl
rename to dom/events/nsIEventListenerService.idl
diff --git a/dom/base/nsIJSEventListener.h b/dom/events/nsIJSEventListener.h
similarity index 100%
rename from dom/base/nsIJSEventListener.h
rename to dom/events/nsIJSEventListener.h
diff --git a/content/events/src/nsIMEStateManager.cpp b/dom/events/nsIMEStateManager.cpp
similarity index 100%
rename from content/events/src/nsIMEStateManager.cpp
rename to dom/events/nsIMEStateManager.cpp
diff --git a/content/events/src/nsIMEStateManager.h b/dom/events/nsIMEStateManager.h
similarity index 100%
rename from content/events/src/nsIMEStateManager.h
rename to dom/events/nsIMEStateManager.h
diff --git a/content/events/public/nsIPrivateTextEvent.h b/dom/events/nsIPrivateTextEvent.h
similarity index 100%
rename from content/events/public/nsIPrivateTextEvent.h
rename to dom/events/nsIPrivateTextEvent.h
diff --git a/content/events/public/nsIPrivateTextRange.h b/dom/events/nsIPrivateTextRange.h
similarity index 100%
rename from content/events/public/nsIPrivateTextRange.h
rename to dom/events/nsIPrivateTextRange.h
diff --git a/dom/src/events/nsJSEventListener.cpp b/dom/events/nsJSEventListener.cpp
similarity index 100%
rename from dom/src/events/nsJSEventListener.cpp
rename to dom/events/nsJSEventListener.cpp
diff --git a/dom/src/events/nsJSEventListener.h b/dom/events/nsJSEventListener.h
similarity index 100%
rename from dom/src/events/nsJSEventListener.h
rename to dom/events/nsJSEventListener.h
diff --git a/content/events/src/nsPaintRequest.cpp b/dom/events/nsPaintRequest.cpp
similarity index 100%
rename from content/events/src/nsPaintRequest.cpp
rename to dom/events/nsPaintRequest.cpp
diff --git a/content/events/src/nsPaintRequest.h b/dom/events/nsPaintRequest.h
similarity index 100%
rename from content/events/src/nsPaintRequest.h
rename to dom/events/nsPaintRequest.h
diff --git a/content/events/src/nsPrivateTextRange.cpp b/dom/events/nsPrivateTextRange.cpp
similarity index 100%
rename from content/events/src/nsPrivateTextRange.cpp
rename to dom/events/nsPrivateTextRange.cpp
diff --git a/content/events/src/nsPrivateTextRange.h b/dom/events/nsPrivateTextRange.h
similarity index 100%
rename from content/events/src/nsPrivateTextRange.h
rename to dom/events/nsPrivateTextRange.h
diff --git a/content/events/public/nsVKList.h b/dom/events/nsVKList.h
similarity index 100%
rename from content/events/public/nsVKList.h
rename to dom/events/nsVKList.h
diff --git a/content/events/test/bug226361_iframe.xhtml b/dom/events/test/bug226361_iframe.xhtml
similarity index 100%
rename from content/events/test/bug226361_iframe.xhtml
rename to dom/events/test/bug226361_iframe.xhtml
diff --git a/content/events/test/bug299673.js b/dom/events/test/bug299673.js
similarity index 100%
rename from content/events/test/bug299673.js
rename to dom/events/test/bug299673.js
diff --git a/content/events/test/bug322588-popup.html b/dom/events/test/bug322588-popup.html
similarity index 100%
rename from content/events/test/bug322588-popup.html
rename to dom/events/test/bug322588-popup.html
diff --git a/content/events/test/bug415498-doc1.html b/dom/events/test/bug415498-doc1.html
similarity index 100%
rename from content/events/test/bug415498-doc1.html
rename to dom/events/test/bug415498-doc1.html
diff --git a/content/events/test/bug415498-doc2.html b/dom/events/test/bug415498-doc2.html
similarity index 100%
rename from content/events/test/bug415498-doc2.html
rename to dom/events/test/bug415498-doc2.html
diff --git a/content/events/test/bug426082.html b/dom/events/test/bug426082.html
similarity index 100%
rename from content/events/test/bug426082.html
rename to dom/events/test/bug426082.html
diff --git a/content/events/test/bug457672.html b/dom/events/test/bug457672.html
similarity index 100%
rename from content/events/test/bug457672.html
rename to dom/events/test/bug457672.html
diff --git a/content/events/test/bug591249_iframe.xul b/dom/events/test/bug591249_iframe.xul
similarity index 100%
rename from content/events/test/bug591249_iframe.xul
rename to dom/events/test/bug591249_iframe.xul
diff --git a/content/events/test/bug602962.xul b/dom/events/test/bug602962.xul
similarity index 100%
rename from content/events/test/bug602962.xul
rename to dom/events/test/bug602962.xul
diff --git a/content/events/test/bug656379-1.html b/dom/events/test/bug656379-1.html
similarity index 100%
rename from content/events/test/bug656379-1.html
rename to dom/events/test/bug656379-1.html
diff --git a/content/events/test/chrome.ini b/dom/events/test/chrome.ini
similarity index 100%
rename from content/events/test/chrome.ini
rename to dom/events/test/chrome.ini
diff --git a/content/events/test/empty.js b/dom/events/test/empty.js
similarity index 100%
rename from content/events/test/empty.js
rename to dom/events/test/empty.js
diff --git a/content/events/test/file_bug679494.html b/dom/events/test/file_bug679494.html
similarity index 100%
rename from content/events/test/file_bug679494.html
rename to dom/events/test/file_bug679494.html
diff --git a/content/events/test/mochitest.ini b/dom/events/test/mochitest.ini
similarity index 100%
rename from content/events/test/mochitest.ini
rename to dom/events/test/mochitest.ini
diff --git a/content/events/test/test_addEventListenerExtraArg.html b/dom/events/test/test_addEventListenerExtraArg.html
similarity index 100%
rename from content/events/test/test_addEventListenerExtraArg.html
rename to dom/events/test/test_addEventListenerExtraArg.html
diff --git a/content/events/test/test_all_synthetic_events.html b/dom/events/test/test_all_synthetic_events.html
similarity index 100%
rename from content/events/test/test_all_synthetic_events.html
rename to dom/events/test/test_all_synthetic_events.html
diff --git a/content/events/test/test_bug226361.xhtml b/dom/events/test/test_bug226361.xhtml
similarity index 100%
rename from content/events/test/test_bug226361.xhtml
rename to dom/events/test/test_bug226361.xhtml
diff --git a/content/events/test/test_bug238987.html b/dom/events/test/test_bug238987.html
similarity index 100%
rename from content/events/test/test_bug238987.html
rename to dom/events/test/test_bug238987.html
diff --git a/content/events/test/test_bug288392.html b/dom/events/test/test_bug288392.html
similarity index 100%
rename from content/events/test/test_bug288392.html
rename to dom/events/test/test_bug288392.html
diff --git a/content/events/test/test_bug299673-1.html b/dom/events/test/test_bug299673-1.html
similarity index 100%
rename from content/events/test/test_bug299673-1.html
rename to dom/events/test/test_bug299673-1.html
diff --git a/content/events/test/test_bug299673-2.html b/dom/events/test/test_bug299673-2.html
similarity index 100%
rename from content/events/test/test_bug299673-2.html
rename to dom/events/test/test_bug299673-2.html
diff --git a/content/events/test/test_bug322588.html b/dom/events/test/test_bug322588.html
similarity index 100%
rename from content/events/test/test_bug322588.html
rename to dom/events/test/test_bug322588.html
diff --git a/content/events/test/test_bug328885.html b/dom/events/test/test_bug328885.html
similarity index 100%
rename from content/events/test/test_bug328885.html
rename to dom/events/test/test_bug328885.html
diff --git a/content/events/test/test_bug336682.js b/dom/events/test/test_bug336682.js
similarity index 100%
rename from content/events/test/test_bug336682.js
rename to dom/events/test/test_bug336682.js
diff --git a/content/events/test/test_bug336682_1.html b/dom/events/test/test_bug336682_1.html
similarity index 100%
rename from content/events/test/test_bug336682_1.html
rename to dom/events/test/test_bug336682_1.html
diff --git a/content/events/test/test_bug336682_2.xul b/dom/events/test/test_bug336682_2.xul
similarity index 100%
rename from content/events/test/test_bug336682_2.xul
rename to dom/events/test/test_bug336682_2.xul
diff --git a/content/events/test/test_bug367781.html b/dom/events/test/test_bug367781.html
similarity index 100%
rename from content/events/test/test_bug367781.html
rename to dom/events/test/test_bug367781.html
diff --git a/content/events/test/test_bug368835.html b/dom/events/test/test_bug368835.html
similarity index 100%
rename from content/events/test/test_bug368835.html
rename to dom/events/test/test_bug368835.html
diff --git a/content/events/test/test_bug379120.html b/dom/events/test/test_bug379120.html
similarity index 100%
rename from content/events/test/test_bug379120.html
rename to dom/events/test/test_bug379120.html
diff --git a/content/events/test/test_bug391568.xhtml b/dom/events/test/test_bug391568.xhtml
similarity index 100%
rename from content/events/test/test_bug391568.xhtml
rename to dom/events/test/test_bug391568.xhtml
diff --git a/content/events/test/test_bug402089.html b/dom/events/test/test_bug402089.html
similarity index 100%
rename from content/events/test/test_bug402089.html
rename to dom/events/test/test_bug402089.html
diff --git a/content/events/test/test_bug405632.html b/dom/events/test/test_bug405632.html
similarity index 100%
rename from content/events/test/test_bug405632.html
rename to dom/events/test/test_bug405632.html
diff --git a/content/events/test/test_bug409604.html b/dom/events/test/test_bug409604.html
similarity index 100%
rename from content/events/test/test_bug409604.html
rename to dom/events/test/test_bug409604.html
diff --git a/content/events/test/test_bug412567.html b/dom/events/test/test_bug412567.html
similarity index 100%
rename from content/events/test/test_bug412567.html
rename to dom/events/test/test_bug412567.html
diff --git a/content/events/test/test_bug415498.xul b/dom/events/test/test_bug415498.xul
similarity index 100%
rename from content/events/test/test_bug415498.xul
rename to dom/events/test/test_bug415498.xul
diff --git a/content/events/test/test_bug422132.html b/dom/events/test/test_bug422132.html
similarity index 100%
rename from content/events/test/test_bug422132.html
rename to dom/events/test/test_bug422132.html
diff --git a/content/events/test/test_bug426082.html b/dom/events/test/test_bug426082.html
similarity index 100%
rename from content/events/test/test_bug426082.html
rename to dom/events/test/test_bug426082.html
diff --git a/content/events/test/test_bug427537.html b/dom/events/test/test_bug427537.html
similarity index 100%
rename from content/events/test/test_bug427537.html
rename to dom/events/test/test_bug427537.html
diff --git a/content/events/test/test_bug428988.html b/dom/events/test/test_bug428988.html
similarity index 100%
rename from content/events/test/test_bug428988.html
rename to dom/events/test/test_bug428988.html
diff --git a/content/events/test/test_bug432698.html b/dom/events/test/test_bug432698.html
similarity index 100%
rename from content/events/test/test_bug432698.html
rename to dom/events/test/test_bug432698.html
diff --git a/content/events/test/test_bug443985.html b/dom/events/test/test_bug443985.html
similarity index 100%
rename from content/events/test/test_bug443985.html
rename to dom/events/test/test_bug443985.html
diff --git a/content/events/test/test_bug447736.html b/dom/events/test/test_bug447736.html
similarity index 100%
rename from content/events/test/test_bug447736.html
rename to dom/events/test/test_bug447736.html
diff --git a/content/events/test/test_bug448602.html b/dom/events/test/test_bug448602.html
similarity index 100%
rename from content/events/test/test_bug448602.html
rename to dom/events/test/test_bug448602.html
diff --git a/content/events/test/test_bug450876.html b/dom/events/test/test_bug450876.html
similarity index 100%
rename from content/events/test/test_bug450876.html
rename to dom/events/test/test_bug450876.html
diff --git a/content/events/test/test_bug456273.html b/dom/events/test/test_bug456273.html
similarity index 100%
rename from content/events/test/test_bug456273.html
rename to dom/events/test/test_bug456273.html
diff --git a/content/events/test/test_bug457672.html b/dom/events/test/test_bug457672.html
similarity index 100%
rename from content/events/test/test_bug457672.html
rename to dom/events/test/test_bug457672.html
diff --git a/content/events/test/test_bug489671.html b/dom/events/test/test_bug489671.html
similarity index 100%
rename from content/events/test/test_bug489671.html
rename to dom/events/test/test_bug489671.html
diff --git a/content/events/test/test_bug493251.html b/dom/events/test/test_bug493251.html
similarity index 100%
rename from content/events/test/test_bug493251.html
rename to dom/events/test/test_bug493251.html
diff --git a/content/events/test/test_bug502818.html b/dom/events/test/test_bug502818.html
similarity index 100%
rename from content/events/test/test_bug502818.html
rename to dom/events/test/test_bug502818.html
diff --git a/content/events/test/test_bug508479.html b/dom/events/test/test_bug508479.html
similarity index 100%
rename from content/events/test/test_bug508479.html
rename to dom/events/test/test_bug508479.html
diff --git a/content/events/test/test_bug517851.html b/dom/events/test/test_bug517851.html
similarity index 100%
rename from content/events/test/test_bug517851.html
rename to dom/events/test/test_bug517851.html
diff --git a/content/events/test/test_bug534833.html b/dom/events/test/test_bug534833.html
similarity index 100%
rename from content/events/test/test_bug534833.html
rename to dom/events/test/test_bug534833.html
diff --git a/content/events/test/test_bug545268.html b/dom/events/test/test_bug545268.html
similarity index 100%
rename from content/events/test/test_bug545268.html
rename to dom/events/test/test_bug545268.html
diff --git a/content/events/test/test_bug547996-1.html b/dom/events/test/test_bug547996-1.html
similarity index 100%
rename from content/events/test/test_bug547996-1.html
rename to dom/events/test/test_bug547996-1.html
diff --git a/content/events/test/test_bug547996-2.xhtml b/dom/events/test/test_bug547996-2.xhtml
similarity index 100%
rename from content/events/test/test_bug547996-2.xhtml
rename to dom/events/test/test_bug547996-2.xhtml
diff --git a/content/events/test/test_bug556493.html b/dom/events/test/test_bug556493.html
similarity index 100%
rename from content/events/test/test_bug556493.html
rename to dom/events/test/test_bug556493.html
diff --git a/content/events/test/test_bug563329.html b/dom/events/test/test_bug563329.html
similarity index 100%
rename from content/events/test/test_bug563329.html
rename to dom/events/test/test_bug563329.html
diff --git a/content/events/test/test_bug574663.html b/dom/events/test/test_bug574663.html
similarity index 100%
rename from content/events/test/test_bug574663.html
rename to dom/events/test/test_bug574663.html
diff --git a/content/events/test/test_bug586961.xul b/dom/events/test/test_bug586961.xul
similarity index 100%
rename from content/events/test/test_bug586961.xul
rename to dom/events/test/test_bug586961.xul
diff --git a/content/events/test/test_bug591249.xul b/dom/events/test/test_bug591249.xul
similarity index 95%
rename from content/events/test/test_bug591249.xul
rename to dom/events/test/test_bug591249.xul
index 273fc27b08bd8b56ac7d533a6bfaae85be463be6..8b0926d040e78e82fa93dbbbbe291bbd29437e2d 100644
--- a/content/events/test/test_bug591249.xul
+++ b/dom/events/test/test_bug591249.xul
@@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=591249
   <img id="image"
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAG0lEQVR42mP8z0A%2BYKJA76jmUc2jmkc1U0EzACKcASfOgGoMAAAAAElFTkSuQmCC"
        ondragstart="event.preventDefault();"/>
-  <iframe id="iframe" src="chrome://mochitests/content/chrome/content/events/test/bug591249_iframe.xul" style="height: 300px; width: 100%;"></iframe>
+  <iframe id="iframe" src="chrome://mochitests/content/chrome/dom/events/test/bug591249_iframe.xul" style="height: 300px; width: 100%;"></iframe>
 </body>
 
 <script class="testbody" type="application/javascript;version=1.8"><![CDATA[
diff --git a/content/events/test/test_bug591815.html b/dom/events/test/test_bug591815.html
similarity index 100%
rename from content/events/test/test_bug591815.html
rename to dom/events/test/test_bug591815.html
diff --git a/content/events/test/test_bug593959.html b/dom/events/test/test_bug593959.html
similarity index 100%
rename from content/events/test/test_bug593959.html
rename to dom/events/test/test_bug593959.html
diff --git a/content/events/test/test_bug602962.xul b/dom/events/test/test_bug602962.xul
similarity index 95%
rename from content/events/test/test_bug602962.xul
rename to dom/events/test/test_bug602962.xul
index 0163ebe42eb142f9991bc9461a891abefa56a2f3..cd9811b7d6c57e45b5b247e57a6f6483abc2d182 100644
--- a/content/events/test/test_bug602962.xul
+++ b/dom/events/test/test_bug602962.xul
@@ -26,7 +26,7 @@ var oldWidth = 0, oldHeight = 0;
 var win = null;
 
 function openWindow() {
-  win = window.open("chrome://mochitests/content/chrome/content/events/test/bug602962.xul", "_blank", "width=600,height=600");
+  win = window.open("chrome://mochitests/content/chrome/dom/events/test/bug602962.xul", "_blank", "width=600,height=600");
 }
 
 function doTest() {
diff --git a/content/events/test/test_bug603008.html b/dom/events/test/test_bug603008.html
similarity index 100%
rename from content/events/test/test_bug603008.html
rename to dom/events/test/test_bug603008.html
diff --git a/content/events/test/test_bug605242.html b/dom/events/test/test_bug605242.html
similarity index 100%
rename from content/events/test/test_bug605242.html
rename to dom/events/test/test_bug605242.html
diff --git a/content/events/test/test_bug607464.html b/dom/events/test/test_bug607464.html
similarity index 100%
rename from content/events/test/test_bug607464.html
rename to dom/events/test/test_bug607464.html
diff --git a/content/events/test/test_bug613634.html b/dom/events/test/test_bug613634.html
similarity index 100%
rename from content/events/test/test_bug613634.html
rename to dom/events/test/test_bug613634.html
diff --git a/content/events/test/test_bug615597.html b/dom/events/test/test_bug615597.html
similarity index 100%
rename from content/events/test/test_bug615597.html
rename to dom/events/test/test_bug615597.html
diff --git a/content/events/test/test_bug617528.xul b/dom/events/test/test_bug617528.xul
similarity index 100%
rename from content/events/test/test_bug617528.xul
rename to dom/events/test/test_bug617528.xul
diff --git a/content/events/test/test_bug624127.html b/dom/events/test/test_bug624127.html
similarity index 100%
rename from content/events/test/test_bug624127.html
rename to dom/events/test/test_bug624127.html
diff --git a/content/events/test/test_bug635465.html b/dom/events/test/test_bug635465.html
similarity index 100%
rename from content/events/test/test_bug635465.html
rename to dom/events/test/test_bug635465.html
diff --git a/content/events/test/test_bug641477.html b/dom/events/test/test_bug641477.html
similarity index 100%
rename from content/events/test/test_bug641477.html
rename to dom/events/test/test_bug641477.html
diff --git a/content/events/test/test_bug648573.html b/dom/events/test/test_bug648573.html
similarity index 100%
rename from content/events/test/test_bug648573.html
rename to dom/events/test/test_bug648573.html
diff --git a/content/events/test/test_bug650493.html b/dom/events/test/test_bug650493.html
similarity index 100%
rename from content/events/test/test_bug650493.html
rename to dom/events/test/test_bug650493.html
diff --git a/content/events/test/test_bug656379-1.html b/dom/events/test/test_bug656379-1.html
similarity index 100%
rename from content/events/test/test_bug656379-1.html
rename to dom/events/test/test_bug656379-1.html
diff --git a/content/events/test/test_bug656379-2.html b/dom/events/test/test_bug656379-2.html
similarity index 100%
rename from content/events/test/test_bug656379-2.html
rename to dom/events/test/test_bug656379-2.html
diff --git a/content/events/test/test_bug656954.html b/dom/events/test/test_bug656954.html
similarity index 100%
rename from content/events/test/test_bug656954.html
rename to dom/events/test/test_bug656954.html
diff --git a/content/events/test/test_bug659071.html b/dom/events/test/test_bug659071.html
similarity index 100%
rename from content/events/test/test_bug659071.html
rename to dom/events/test/test_bug659071.html
diff --git a/content/events/test/test_bug659350.html b/dom/events/test/test_bug659350.html
similarity index 100%
rename from content/events/test/test_bug659350.html
rename to dom/events/test/test_bug659350.html
diff --git a/content/events/test/test_bug662678.html b/dom/events/test/test_bug662678.html
similarity index 100%
rename from content/events/test/test_bug662678.html
rename to dom/events/test/test_bug662678.html
diff --git a/content/events/test/test_bug667612.html b/dom/events/test/test_bug667612.html
similarity index 100%
rename from content/events/test/test_bug667612.html
rename to dom/events/test/test_bug667612.html
diff --git a/content/events/test/test_bug667919-1.html b/dom/events/test/test_bug667919-1.html
similarity index 100%
rename from content/events/test/test_bug667919-1.html
rename to dom/events/test/test_bug667919-1.html
diff --git a/content/events/test/test_bug679494.xul b/dom/events/test/test_bug679494.xul
similarity index 100%
rename from content/events/test/test_bug679494.xul
rename to dom/events/test/test_bug679494.xul
diff --git a/content/events/test/test_bug689564.html b/dom/events/test/test_bug689564.html
similarity index 100%
rename from content/events/test/test_bug689564.html
rename to dom/events/test/test_bug689564.html
diff --git a/content/events/test/test_bug698929.html b/dom/events/test/test_bug698929.html
similarity index 100%
rename from content/events/test/test_bug698929.html
rename to dom/events/test/test_bug698929.html
diff --git a/content/events/test/test_bug741666.html b/dom/events/test/test_bug741666.html
similarity index 100%
rename from content/events/test/test_bug741666.html
rename to dom/events/test/test_bug741666.html
diff --git a/content/events/test/test_bug742376.html b/dom/events/test/test_bug742376.html
similarity index 100%
rename from content/events/test/test_bug742376.html
rename to dom/events/test/test_bug742376.html
diff --git a/content/events/test/test_bug812744.html b/dom/events/test/test_bug812744.html
similarity index 100%
rename from content/events/test/test_bug812744.html
rename to dom/events/test/test_bug812744.html
diff --git a/content/events/test/test_bug822898.html b/dom/events/test/test_bug822898.html
similarity index 100%
rename from content/events/test/test_bug822898.html
rename to dom/events/test/test_bug822898.html
diff --git a/content/events/test/test_bug847597.html b/dom/events/test/test_bug847597.html
similarity index 100%
rename from content/events/test/test_bug847597.html
rename to dom/events/test/test_bug847597.html
diff --git a/content/events/test/test_bug855741.html b/dom/events/test/test_bug855741.html
similarity index 100%
rename from content/events/test/test_bug855741.html
rename to dom/events/test/test_bug855741.html
diff --git a/content/events/test/test_bug864040.html b/dom/events/test/test_bug864040.html
similarity index 98%
rename from content/events/test/test_bug864040.html
rename to dom/events/test/test_bug864040.html
index d43376ef30ad6259eb8660c3062930d6146cff36..27bb1dd442a324dee0250490972e516916a9d402 100644
--- a/content/events/test/test_bug864040.html
+++ b/dom/events/test/test_bug864040.html
@@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=864040
   <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
-<body onload="setTimeout(runTests, 0);">
+<body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=864040">Mozilla Bug 864040</a>
 <div id="display">
   <textarea id="ta" rows="5" cols="20"></textarea>
@@ -79,6 +79,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=864040
     }
 
     SimpleTest.waitForExplicitFinish();
+
+    SimpleTest.waitForFocus(runTests);
   </script>
 </pre>
 </body>
diff --git a/content/events/test/test_bug930374-chrome.html b/dom/events/test/test_bug930374-chrome.html
similarity index 100%
rename from content/events/test/test_bug930374-chrome.html
rename to dom/events/test/test_bug930374-chrome.html
diff --git a/content/events/test/test_bug930374-content.html b/dom/events/test/test_bug930374-content.html
similarity index 100%
rename from content/events/test/test_bug930374-content.html
rename to dom/events/test/test_bug930374-content.html
diff --git a/content/events/test/test_bug944011.html b/dom/events/test/test_bug944011.html
similarity index 100%
rename from content/events/test/test_bug944011.html
rename to dom/events/test/test_bug944011.html
diff --git a/content/events/test/test_bug944847.html b/dom/events/test/test_bug944847.html
similarity index 100%
rename from content/events/test/test_bug944847.html
rename to dom/events/test/test_bug944847.html
diff --git a/content/events/test/test_bug946632.html b/dom/events/test/test_bug946632.html
similarity index 100%
rename from content/events/test/test_bug946632.html
rename to dom/events/test/test_bug946632.html
diff --git a/content/events/test/test_clickevent_on_input.html b/dom/events/test/test_clickevent_on_input.html
similarity index 100%
rename from content/events/test/test_clickevent_on_input.html
rename to dom/events/test/test_clickevent_on_input.html
diff --git a/content/events/test/test_continuous_wheel_events.html b/dom/events/test/test_continuous_wheel_events.html
similarity index 100%
rename from content/events/test/test_continuous_wheel_events.html
rename to dom/events/test/test_continuous_wheel_events.html
diff --git a/content/events/test/test_dblclick_explicit_original_target.html b/dom/events/test/test_dblclick_explicit_original_target.html
similarity index 100%
rename from content/events/test/test_dblclick_explicit_original_target.html
rename to dom/events/test/test_dblclick_explicit_original_target.html
diff --git a/content/events/test/test_dom_keyboard_event.html b/dom/events/test/test_dom_keyboard_event.html
similarity index 100%
rename from content/events/test/test_dom_keyboard_event.html
rename to dom/events/test/test_dom_keyboard_event.html
diff --git a/content/events/test/test_dom_mouse_event.html b/dom/events/test/test_dom_mouse_event.html
similarity index 100%
rename from content/events/test/test_dom_mouse_event.html
rename to dom/events/test/test_dom_mouse_event.html
diff --git a/content/events/test/test_dom_wheel_event.html b/dom/events/test/test_dom_wheel_event.html
similarity index 100%
rename from content/events/test/test_dom_wheel_event.html
rename to dom/events/test/test_dom_wheel_event.html
diff --git a/content/events/test/test_draggableprop.html b/dom/events/test/test_draggableprop.html
similarity index 100%
rename from content/events/test/test_draggableprop.html
rename to dom/events/test/test_draggableprop.html
diff --git a/content/events/test/test_dragstart.html b/dom/events/test/test_dragstart.html
similarity index 100%
rename from content/events/test/test_dragstart.html
rename to dom/events/test/test_dragstart.html
diff --git a/content/events/test/test_eventctors.html b/dom/events/test/test_eventctors.html
similarity index 85%
rename from content/events/test/test_eventctors.html
rename to dom/events/test/test_eventctors.html
index 2a8ddbd648eab9b0210cb8e2efa974d47ad38bd0..2d9737ec45f0b42c7fd800cd9061285d86fcaab9 100644
--- a/content/events/test/test_eventctors.html
+++ b/dom/events/test/test_eventctors.html
@@ -60,7 +60,7 @@ ex = false;
 
 
 e = new Event("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 e.isTrusted = true;
 ok(!e.isTrusted, "Event shouldn't be trusted!");
@@ -84,7 +84,7 @@ is(e.eventPhase, Event.NONE, "Wrong event phase");
 is(receivedEvent, e, "Wrong event!");
 
 e = new Event("hello", null);
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -94,7 +94,7 @@ is(e.eventPhase, Event.NONE, "Wrong event phase");
 is(receivedEvent, e, "Wrong event!");
 
 e = new Event("hello", undefined);
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -104,7 +104,7 @@ is(e.eventPhase, Event.NONE, "Wrong event phase");
 is(receivedEvent, e, "Wrong event!");
 
 e = new Event("hello", {});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -114,7 +114,7 @@ is(e.eventPhase, Event.NONE, "Wrong event phase");
 is(receivedEvent, e, "Wrong event!");
 
 e = new Event("hello", { bubbles: true, cancelable: true });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -132,7 +132,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new CustomEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -140,7 +140,7 @@ document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
 e = new CustomEvent("hello", { bubbles: true, cancelable: true, detail: window });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -149,7 +149,7 @@ document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
 e = new CustomEvent("hello", { cancelable: true, detail: window });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -187,7 +187,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new BlobEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 try {
   e.__defineGetter__("isTrusted", function() { return true });
@@ -205,7 +205,7 @@ is(receivedEvent, e, "Wrong event!");
 
 var blob = Blob();
 e = new BlobEvent("hello", { bubbles: true, cancelable: true, data: blob });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -215,7 +215,7 @@ is(receivedEvent, e, "Wrong event!");
 
 
 e = new BlobEvent("hello", {data: blob});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event should be cancelable1!");
@@ -237,7 +237,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new CloseEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -249,7 +249,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new CloseEvent("hello",
   { bubbles: true, cancelable: true, wasClean: true, code: 1, reason: "foo" });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -261,7 +261,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new CloseEvent("hello",
   { bubbles: true, cancelable: true, wasClean: true, code: 1 });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -283,7 +283,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new HashChangeEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -294,7 +294,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new HashChangeEvent("hello",
   { bubbles: true, cancelable: true, oldURL: "old", newURL: "new" });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -305,7 +305,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new HashChangeEvent("hello",
   { bubbles: true, cancelable: true, newURL: "new" });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -325,7 +325,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new PageTransitionEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -335,7 +335,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new PageTransitionEvent("hello",
   { bubbles: true, cancelable: true, persisted: true});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -344,7 +344,7 @@ document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
 e = new PageTransitionEvent("hello", { persisted: true});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -363,7 +363,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new PopStateEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -373,7 +373,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new PopStateEvent("hello",
   { bubbles: true, cancelable: true, state: window});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -383,7 +383,7 @@ is(receivedEvent, e, "Wrong event!");
 
 
 e = new PopStateEvent("hello", { state: window});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -420,7 +420,7 @@ is(e.view, null);
 ex = false;
 
 e = new UIEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -431,7 +431,7 @@ is(receivedEvent, e, "Wrong event!");
 
 e = new UIEvent("hello",
   { bubbles: true, cancelable: true, view: window, detail: 1});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -454,7 +454,7 @@ ok(ex, "First parameter is required!");
 ex = false;
 
 e = new StorageEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
@@ -469,7 +469,7 @@ e = new StorageEvent("hello",
   { bubbles: true, cancelable: true, key: "key",
     oldValue: "oldValue", newValue: "newValue", url: "url",
     storageArea: localStorage });
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
@@ -483,7 +483,7 @@ is(receivedEvent, e, "Wrong event!");
 
 // DeviceProximityEvent
 e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event should not be trusted");
 is(e.value, 1, "value should be 1");
 is(e.min, 0, "min should be 0");
@@ -497,7 +497,7 @@ is(e.max, Infinity, "Uninitialized max should be infinity");
 
 // UserProximityEvent
 e = new UserProximityEvent("hello", {near: true});
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event should not be trusted");
 is(e.near, true, "near should be true");
 document.dispatchEvent(e);
@@ -505,7 +505,7 @@ is(receivedEvent, e, "Wrong event!");
 
 // DeviceLightEvent
 e = new DeviceLightEvent("hello", {value: 1} );
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event should not be trusted");
 is(e.value, 1, "value should be 1");
 document.dispatchEvent(e);
@@ -513,7 +513,7 @@ is(receivedEvent, e, "Wrong event!");
 
 // DeviceOrientationEvent
 e = new DeviceOrientationEvent("hello");
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event should not be trusted");
 is(e.alpha, 0);
 is(e.beta, 0);
@@ -521,7 +521,7 @@ is(e.gamma, 0);
 is(e.absolute, false);
 
 e = new DeviceOrientationEvent("hello", { alpha: 1, beta: 2, gamma: 3, absolute: true } );
-ok(e.type, "hello", "Wrong event type!");
+is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event should not be trusted");
 is(e.alpha, 1);
 is(e.beta, 2);
@@ -541,7 +541,7 @@ ok(ex, "MouseEvent: First parameter is required!");
 ex = false;
 
 e = new MouseEvent("hello");
-ok(e.type, "hello", "MouseEvent: Wrong event type!");
+is(e.type, "hello", "MouseEvent: Wrong event type!");
 ok(!e.isTrusted, "MouseEvent: Event shouldn't be trusted!");
 ok(!e.bubbles, "MouseEvent: Event shouldn't bubble!");
 ok(!e.cancelable, "MouseEvent: Event shouldn't be cancelable!");
@@ -609,7 +609,7 @@ ok(ex, "PopupBlockedEvent: First parameter is required!");
 ex = false;
 
 e = new PopupBlockedEvent("hello");
-ok(e.type, "hello", "PopupBlockedEvent: Wrong event type!");
+is(e.type, "hello", "PopupBlockedEvent: Wrong event type!");
 ok(!e.isTrusted, "PopupBlockedEvent: Event shouldn't be trusted!");
 ok(!e.bubbles, "PopupBlockedEvent: Event shouldn't bubble!");
 ok(!e.cancelable, "PopupBlockedEvent: Event shouldn't be cancelable!");
@@ -637,7 +637,7 @@ ok(ex, "SmartCardEvent: First parameter is required!");
 ex = false;
 
 e = new SmartCardEvent("hello");
-ok(e.type, "hello", "SmartCardEvent: Wrong event type!");
+is(e.type, "hello", "SmartCardEvent: Wrong event type!");
 ok(!e.isTrusted, "SmartCardEvent: Event shouldn't be trusted!");
 ok(!e.bubbles, "SmartCardEvent: Event shouldn't bubble!");
 ok(!e.cancelable, "SmartCardEvent: Event shouldn't be cancelable!");
@@ -659,7 +659,7 @@ ok(ex, "WheelEvent: First parameter is required!");
 ex = false;
 
 e = new WheelEvent("hello");
-ok(e.type, "hello", "WheelEvent: Wrong event type!");
+is(e.type, "hello", "WheelEvent: Wrong event type!");
 ok(!e.isTrusted, "WheelEvent: Event shouldn't be trusted!");
 ok(!e.bubbles, "WheelEvent: Event shouldn't bubble!");
 ok(!e.cancelable, "WheelEvent: Event shouldn't be cancelable!");
@@ -724,6 +724,32 @@ while (testWheelProps.length) {
   }
 }
 
+// TransitionEvent
+e = new TransitionEvent("hello", { propertyName: "color", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
+is("propertyName" in e, true, "Transition events have propertyName property");
+is("foobar" in e, false, "Transition events do not copy random properties from event init");
+is(e.propertyName, "color", "Transition event copies propertyName from TransitionEventInit");
+is(e.elapsedTime, 3.5, "Transition event copies elapsedTime from TransitionEventInit");
+is(e.pseudoElement, "", "Transition event copies pseudoElement from TransitionEventInit");
+is(e.bubbles, false, "Lack of bubbles property in TransitionEventInit");
+is(e.cancelable, false, "Lack of cancelable property in TransitionEventInit");
+is(e.type, "hello", "Wrong event type!");
+is(e.isTrusted, false, "Event shouldn't be trusted!");
+is(e.eventPhase, Event.NONE, "Wrong event phase");
+
+// AnimationEvent
+e = new AnimationEvent("hello", { animationName: "bounce3", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
+is("animationName" in e, true, "Animation events have animationName property");
+is("foobar" in e, false, "Animation events do not copy random properties from event init");
+is(e.animationName, "bounce3", "Animation event copies animationName from AnimationEventInit");
+is(e.elapsedTime, 3.5, "Animation event copies elapsedTime from AnimationEventInit");
+is(e.pseudoElement, "", "Animation event copies pseudoElement from AnimationEventInit");
+is(e.bubbles, false, "Lack of bubbles property in AnimationEventInit");
+is(e.cancelable, false, "Lack of cancelable property in AnimationEventInit");
+is(e.type, "hello", "Wrong event type!");
+is(e.isTrusted, false, "Event shouldn't be trusted!");
+is(e.eventPhase, Event.NONE, "Wrong event phase");
+
 </script>
 </pre>
 </body>
diff --git a/content/events/test/test_eventctors.xul b/dom/events/test/test_eventctors.xul
similarity index 100%
rename from content/events/test/test_eventctors.xul
rename to dom/events/test/test_eventctors.xul
diff --git a/content/events/test/test_focus_disabled.html b/dom/events/test/test_focus_disabled.html
similarity index 100%
rename from content/events/test/test_focus_disabled.html
rename to dom/events/test/test_focus_disabled.html
diff --git a/content/events/test/test_messageEvent.html b/dom/events/test/test_messageEvent.html
similarity index 100%
rename from content/events/test/test_messageEvent.html
rename to dom/events/test/test_messageEvent.html
diff --git a/content/events/test/test_moz_mouse_pixel_scroll_event.html b/dom/events/test/test_moz_mouse_pixel_scroll_event.html
similarity index 100%
rename from content/events/test/test_moz_mouse_pixel_scroll_event.html
rename to dom/events/test/test_moz_mouse_pixel_scroll_event.html
diff --git a/content/events/test/test_wheel_default_action.html b/dom/events/test/test_wheel_default_action.html
similarity index 100%
rename from content/events/test/test_wheel_default_action.html
rename to dom/events/test/test_wheel_default_action.html
diff --git a/content/events/test/window_bug493251.html b/dom/events/test/window_bug493251.html
similarity index 100%
rename from content/events/test/window_bug493251.html
rename to dom/events/test/window_bug493251.html
diff --git a/content/events/test/window_bug617528.xul b/dom/events/test/window_bug617528.xul
similarity index 100%
rename from content/events/test/window_bug617528.xul
rename to dom/events/test/window_bug617528.xul
diff --git a/content/events/test/window_bug659071.html b/dom/events/test/window_bug659071.html
similarity index 100%
rename from content/events/test/window_bug659071.html
rename to dom/events/test/window_bug659071.html
diff --git a/content/events/test/window_wheel_default_action.html b/dom/events/test/window_wheel_default_action.html
similarity index 100%
rename from content/events/test/window_wheel_default_action.html
rename to dom/events/test/window_wheel_default_action.html
diff --git a/dom/icc/src/moz.build b/dom/icc/src/moz.build
index a03423bc434954262b218f2f8184aa95b9f1dee1..e3ff897b71079b0d108591dc5a58bdeddf1fa3ac 100644
--- a/dom/icc/src/moz.build
+++ b/dom/icc/src/moz.build
@@ -23,6 +23,6 @@ FINAL_LIBRARY = 'gklayout'
 
 LOCAL_INCLUDES += [
     '../../system/gonk',
-    '/content/events/src',
+    '/dom/events',
 ]
 
diff --git a/dom/indexedDB/ipc/moz.build b/dom/indexedDB/ipc/moz.build
index 0aff8c2b9d576b7e96448b253a71a59e4b61f981..290a608db4241b76d3471fd644840a7d003420c9 100644
--- a/dom/indexedDB/ipc/moz.build
+++ b/dom/indexedDB/ipc/moz.build
@@ -36,7 +36,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
     '/dom/indexedDB',
 ]
 
diff --git a/dom/indexedDB/moz.build b/dom/indexedDB/moz.build
index c14fa67a973d63981a453166dc724db7e44c866a..4e18e389d9d8b08882c84e80fbb16a40e73c11ea 100644
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -72,9 +72,9 @@ FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/caps/include',
     '/content/base/src',
-    '/content/events/src',
     '/db/sqlite3/src',
     '/dom/base',
+    '/dom/events',
     '/dom/quota',
     '/dom/src/storage',
     '/xpcom/build',
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index bfcde818f0e8178e9aa78c8809f38cd146ebcc2e..c03cf229c0986af41ef719a45503cfcc1d56d203 100644
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1242,10 +1242,12 @@ ContentParent::ContentParent(mozIApplication* aApp,
 {
     InitializeMembers();  // Perform common initialization.
 
-    // No more than one of !!aApp, aIsForBrowser, aIsForPreallocated, and
-    // aIsNuwaProcess should be true.
-    MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated + aIsNuwaProcess <=
-               1);
+    // No more than one of !!aApp, aIsForBrowser, aIsForPreallocated should be
+    // true.
+    MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
+
+    // Only the preallocated process uses Nuwa.
+    MOZ_ASSERT_IF(aIsNuwaProcess, aIsForPreallocated);
 
     // Insert ourselves into the global linked list of ContentParent objects.
     if (!sContentParents) {
diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build
index 90cb298fb97e52b6bb03f115988c82afc6e2a7dc..4786a38b4468a25941b78679f9fa3ac424298e08 100644
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -86,13 +86,13 @@ LOCAL_INCLUDES += [
     '../src/storage',
     '/chrome/src',
     '/content/base/src',
-    '/content/events/src',
     '/content/media/webspeech/synth/ipc',
     '/docshell/base',
     '/dom/base',
     '/dom/bluetooth',
     '/dom/bluetooth/ipc',
     '/dom/devicestorage',
+    '/dom/events',
     '/dom/fmradio/ipc',
     '/dom/indexedDB',
     '/dom/indexedDB/ipc',
@@ -117,4 +117,4 @@ for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'):
     if CONFIG[var]:
         DEFINES[var] = True
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+JAR_MANIFESTS += ['jar.mn']
diff --git a/dom/moz.build b/dom/moz.build
index 203f44312535606fac39c78d49640fb76eb6e6d1..20c76a59b8a20b9d074bdf35c5e3bb5905dec442 100644
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -48,6 +48,7 @@ PARALLEL_DIRS += [
     'datastore',
     'devicestorage',
     'encoding',
+    'events',
     'file',
     'fmradio',
     'asmjscache',
diff --git a/dom/network/interfaces/nsIDOMMobileConnection.idl b/dom/network/interfaces/nsIDOMMobileConnection.idl
index 875d00a97cc384eae13cbcff70bf50e494179501..7bbbcf38ba68d2defadac0ea7bdc4e4d8cd557a3 100644
--- a/dom/network/interfaces/nsIDOMMobileConnection.idl
+++ b/dom/network/interfaces/nsIDOMMobileConnection.idl
@@ -10,8 +10,9 @@ interface nsIDOMMozMobileConnectionInfo;
 interface nsIDOMMozMobileNetworkInfo;
 interface nsIDOMMozMobileCellInfo;
 interface nsIDOMMozMobileCFInfo;
+interface nsIVariant;
 
-[scriptable, builtinclass, uuid(f55510a9-8dfc-44f5-90ab-355d1e721808)]
+[scriptable, builtinclass, uuid(389ad352-4e43-4c1a-85e9-bae745554326)]
 interface nsIDOMMozMobileConnection : nsIDOMEventTarget
 {
   const long ICC_SERVICE_CLASS_VOICE = (1 << 0);
@@ -90,6 +91,13 @@ interface nsIDOMMozMobileConnection : nsIDOMEventTarget
    */
   readonly attribute DOMString radioState;
 
+  /**
+   * Array of network types that are supported by this radio.
+   *
+   * Possible values: 'gsm', 'wcdma', 'cdma', 'evdo', 'lte'
+   */
+  readonly attribute nsIVariant supportedNetworkTypes;
+
   /**
    * Search for available networks.
    *
@@ -135,8 +143,8 @@ interface nsIDOMMozMobileConnection : nsIDOMEventTarget
    * @param type
    *        DOMString indicates the desired preferred network type.
    *        Possible values: 'wcdma/gsm', 'gsm', 'wcdma', 'wcdma/gsm-auto',
-                             'cdma/evdo', 'cdma', 'evdo', or
-                             'wcdma/gsm/cdma/evdo'.
+   *                         'cdma/evdo', 'cdma', 'evdo', or
+   *                         'wcdma/gsm/cdma/evdo'.
    *
    * If successful, the request's onsuccess will be called.
    *
diff --git a/dom/network/interfaces/nsIMobileConnectionProvider.idl b/dom/network/interfaces/nsIMobileConnectionProvider.idl
index 63396f46d7340f968e176a61f9de3981446dff30..f074657d11950d8fb76f96e68c1a22df97ef983c 100644
--- a/dom/network/interfaces/nsIMobileConnectionProvider.idl
+++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl
@@ -9,6 +9,7 @@ interface nsIDOMMozMobileCFInfo;
 interface nsIDOMMozMobileConnectionInfo;
 interface nsIDOMMozMobileNetworkInfo;
 interface nsIDOMWindow;
+interface nsIVariant;
 
 [scriptable, uuid(5013f5cc-24f9-45dc-ba03-f5dc031a3a6b)]
 interface nsIMobileConnectionListener : nsISupports
@@ -35,7 +36,7 @@ interface nsIMobileConnectionListener : nsISupports
  * XPCOM component (in the content process) that provides the mobile
  * network information.
  */
-[scriptable, uuid(55b8d918-8631-4d72-a9d7-f8c9536d6e6f)]
+[scriptable, uuid(987fc93a-e538-4fd3-9e4d-0e0f0934f019)]
 interface nsIMobileConnectionProvider : nsISupports
 {
   /**
@@ -62,6 +63,7 @@ interface nsIMobileConnectionProvider : nsISupports
   DOMString getIccId(in unsigned long clientId);
   DOMString getNetworkSelectionMode(in unsigned long clientId);
   DOMString getRadioState(in unsigned long clientId);
+  nsIVariant getSupportedNetworkTypes(in unsigned long clientId);
 
   nsIDOMDOMRequest getNetworks(in unsigned long clientId,
                                in nsIDOMWindow window);
diff --git a/dom/network/src/MobileConnection.cpp b/dom/network/src/MobileConnection.cpp
index a7420242aebd520a7390ef07a8c8442c2b1bb964..61ac313913d3db3a5004f6ece59fac3ec82aaf17 100644
--- a/dom/network/src/MobileConnection.cpp
+++ b/dom/network/src/MobileConnection.cpp
@@ -15,6 +15,7 @@
 #include "nsIDOMClassInfo.h"
 #include "nsIDOMDOMRequest.h"
 #include "nsIPermissionManager.h"
+#include "nsIVariant.h"
 
 #include "nsJSUtils.h"
 #include "nsJSON.h"
@@ -220,6 +221,18 @@ MobileConnection::GetRadioState(nsAString& aRadioState)
   return mProvider->GetRadioState(mClientId, aRadioState);
 }
 
+NS_IMETHODIMP
+MobileConnection::GetSupportedNetworkTypes(nsIVariant** aSupportedNetworkTypes)
+{
+  *aSupportedNetworkTypes = nullptr;
+
+  if (!mProvider || !CheckPermission("mobileconnection")) {
+     return NS_OK;
+  }
+
+  return mProvider->GetSupportedNetworkTypes(mClientId, aSupportedNetworkTypes);
+}
+
 NS_IMETHODIMP
 MobileConnection::GetNetworks(nsIDOMDOMRequest** aRequest)
 {
diff --git a/dom/network/src/moz.build b/dom/network/src/moz.build
index f8e5daee3dcfe70479e9fcb7332835b0301c7a86..f3bb235117819cd51df6210ac4249f372e3280a8 100644
--- a/dom/network/src/moz.build
+++ b/dom/network/src/moz.build
@@ -71,6 +71,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
 ]
 
diff --git a/dom/network/tests/marionette/test_mobile_preferred_network_type.js b/dom/network/tests/marionette/test_mobile_preferred_network_type.js
index 3f5a6fd086cff6733f25e5a6e738806e33291fb3..e657af7652c2f480ce57011db3888c0c0f7a425a 100644
--- a/dom/network/tests/marionette/test_mobile_preferred_network_type.js
+++ b/dom/network/tests/marionette/test_mobile_preferred_network_type.js
@@ -9,6 +9,17 @@ let connection = navigator.mozMobileConnections[0];
 ok(connection instanceof MozMobileConnection,
    "connection is instanceof " + connection.constructor);
 
+function testSupportedNetworkTypes() {
+  let supportedNetworkTypes = connection.supportedNetworkTypes;
+
+  ok(Array.isArray(supportedNetworkTypes), "supportedNetworkTypes should be an array");
+  ok(supportedNetworkTypes.indexOf("gsm") >= 0, "Should support 'gsm'");
+  ok(supportedNetworkTypes.indexOf("wcdma") >= 0, "Should support 'wcdma'");
+  ok(supportedNetworkTypes.indexOf("cdma") >= 0, "Should support 'cdma'");
+  ok(supportedNetworkTypes.indexOf("evdo") >= 0, "Should support 'evdo'");
+
+  runNextTest();
+}
 
 function setPreferredNetworkType(type, callback) {
   log("setPreferredNetworkType: " + type);
@@ -119,6 +130,7 @@ let invalidTypes = [
 ];
 
 let tests = [
+  testSupportedNetworkTypes,
   testPreferredNetworkTypes,
   testInvalidNetworkTypes
 ];
diff --git a/dom/smil/moz.build b/dom/smil/moz.build
index 46c4905d90673fd79789216f6bf3e19bc343ef56..166cdc3a49e3cfcc382f551065283e19a4895f72 100644
--- a/dom/smil/moz.build
+++ b/dom/smil/moz.build
@@ -63,8 +63,8 @@ FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/content/svg/content/src',
+    '/dom/events',
     '/layout/style',
 ]
 
diff --git a/dom/src/events/moz.build b/dom/src/events/moz.build
deleted file mode 100644
index f8244cb768ee99247053ed789f1daa11b7045541..0000000000000000000000000000000000000000
--- a/dom/src/events/moz.build
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-UNIFIED_SOURCES += [
-    'nsJSEventListener.cpp',
-]
-
-FAIL_ON_WARNINGS = True
-
-MSVC_ENABLE_PGO = True
-
-LOCAL_INCLUDES += [
-    "/content/base/src",
-    "/dom/base",
-]
-
-FINAL_LIBRARY = 'gklayout'
diff --git a/dom/src/geolocation/moz.build b/dom/src/geolocation/moz.build
index 44f49b86b63cad57c1cbab65abe678adf3464baa..0340d9f0802609def726c930a5cdf2a90e714fb0 100644
--- a/dom/src/geolocation/moz.build
+++ b/dom/src/geolocation/moz.build
@@ -21,8 +21,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/dom/base',
+    '/dom/events',
     '/dom/ipc',
 ]
 
diff --git a/dom/src/moz.build b/dom/src/moz.build
index 23ec850386d8fc091f8ef81abe8df2e6c764b929..e578cd49e845ed7f02f9e344b8a3185e6ba09095 100644
--- a/dom/src/moz.build
+++ b/dom/src/moz.build
@@ -6,7 +6,6 @@
 
 DIRS += [
     'jsurl',
-    'events',
     'storage',
     'offline',
     'json',
@@ -14,4 +13,4 @@ DIRS += [
     'notification',
 ]
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+JAR_MANIFESTS += ['jar.mn']
diff --git a/dom/src/notification/moz.build b/dom/src/notification/moz.build
index 0210c771a8e45dcda38806119cce120ab6d064ba..d642ffa196ddbcea698b31d727ecf449adbbfb89 100644
--- a/dom/src/notification/moz.build
+++ b/dom/src/notification/moz.build
@@ -30,8 +30,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/dom/base',
+    '/dom/events',
     '/dom/ipc',
 ]
 
diff --git a/dom/src/offline/moz.build b/dom/src/offline/moz.build
index 03307dc3eb8cec85d7464d42efdd1ddf6b49ff70..51bb0996bbcfb1b2b57eea7b9ccdfcca5eda4fc6 100644
--- a/dom/src/offline/moz.build
+++ b/dom/src/offline/moz.build
@@ -15,8 +15,8 @@ FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     "/content/base/src",
-    "/content/events/src",
     "/dom/base",
+    "/dom/events",
 ]
 
 FINAL_LIBRARY = 'gklayout'
diff --git a/dom/src/storage/moz.build b/dom/src/storage/moz.build
index 1de2c448635eac82a556827855f86b6bac8e03f2..512ec5a22f2fbe340ec2aea2b44a31811cfca2bc 100644
--- a/dom/src/storage/moz.build
+++ b/dom/src/storage/moz.build
@@ -29,8 +29,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/content/events/src',
     '/dom/base',
+    '/dom/events',
 ]
 
 if CONFIG['ENABLE_TESTS']:
diff --git a/dom/system/android/moz.build b/dom/system/android/moz.build
index c857fda7622c89f41fd9cd74a0880a4a2a2e28ec..a33528d25ea86a22be20ebd0a1d54af7c1556cec 100644
--- a/dom/system/android/moz.build
+++ b/dom/system/android/moz.build
@@ -15,7 +15,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
     '/dom/src/geolocation',
 ]
 
diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js
index 9d87827a4f8e2fb037ef9468cef9574d9a044ab3..5e6829f7d11d9251eddd17f32dcefcfc700229b3 100644
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -677,6 +677,12 @@ RILContentHelper.prototype = {
     return context && context.radioState;
   },
 
+  getSupportedNetworkTypes: function(clientId) {
+    return cpmm.sendSyncMessage("RIL:GetSupportedNetworkTypes", {
+      clientId: clientId
+    })[0];
+  },
+
   /**
    * The networks that are currently trying to be selected (or "automatic").
    * This helps ensure that only one network per client is selected at a time.
diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js
index 95dd025f00fef806b89deac16aae1da0df6e9ea5..362010e387aa83ce78a33e1a4d66067836602fa0 100644
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -115,7 +115,8 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
   "RIL:ExitEmergencyCbMode",
   "RIL:SetRadioEnabled",
   "RIL:SetVoicePrivacyMode",
-  "RIL:GetVoicePrivacyMode"
+  "RIL:GetVoicePrivacyMode",
+  "RIL:GetSupportedNetworkTypes"
 ];
 
 const RIL_IPC_MOBILENETWORK_MSG_NAMES = [
@@ -1112,6 +1113,8 @@ function RadioInterface(options) {
     byApn: {}
   };
 
+  this.supportedNetworkTypes = this.getSupportedNetworkTypes();
+
   this.rilContext = {
     radioState:     RIL.GECKO_RADIOSTATE_UNAVAILABLE,
     detailedRadioState: null,
@@ -1248,6 +1251,26 @@ RadioInterface.prototype = {
     return false;
   },
 
+  /**
+   * A utility function to get supportedNetworkTypes from system property
+   */
+  getSupportedNetworkTypes: function() {
+    let key = "ro.moz.ril." + this.clientId + ".network_types";
+    let supportedNetworkTypes = libcutils.property_get(key, "").split(",");
+    for (let type of supportedNetworkTypes) {
+      // If the value in system property is not valid, use the default one which
+      // is defined in ril_consts.js.
+      if (RIL.GECKO_SUPPORTED_NETWORK_TYPES.indexOf(type) < 0) {
+        this.debug("Unknown network type: " + type);
+        supportedNetworkTypes =
+          RIL.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT.split(",");
+        break;
+      }
+    }
+    if (DEBUG) this.debug("Supported Network Types: " + supportedNetworkTypes);
+    return supportedNetworkTypes;
+  },
+
   /**
    * Process a message from the content process.
    */
@@ -1374,6 +1397,9 @@ RadioInterface.prototype = {
       case "RIL:GetVoicePrivacyMode":
         this.workerMessenger.sendWithIPCMessage(msg, "queryVoicePrivacyMode");
         break;
+      case "RIL:GetSupportedNetworkTypes":
+        // This message is sync.
+        return this.supportedNetworkTypes;
     }
     return null;
   },
@@ -2689,6 +2715,8 @@ RadioInterface.prototype = {
     }
   },
 
+  supportedNetworkTypes: null,
+
   // Data calls setting.
   dataCallSettings: null,
 
diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build
index 8b1c2012ac10cbe2276285b001eeca9b414adf51..fef112b714a89f9422c9fac7d4cc6ea9ef019366 100644
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -105,9 +105,9 @@ FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
-    '/content/events/src',
     '/dom/base',
     '/dom/bluetooth',
+    '/dom/events',
     '/dom/nfc',
     '/dom/src/geolocation',
     '/dom/wifi',
diff --git a/dom/system/gonk/nfc_worker.js b/dom/system/gonk/nfc_worker.js
index 39b7cedbdab8800e1a751c21f1d898c6bd2cefe8..0cfd43078a2f66d02c3f034a12b0d17878e5042e 100644
--- a/dom/system/gonk/nfc_worker.js
+++ b/dom/system/gonk/nfc_worker.js
@@ -368,7 +368,6 @@ NfcWorker[NFC_NOTIFICATION_INITIALIZED] = function NFC_NOTIFICATION_INITIALIZED
 NfcWorker[NFC_NOTIFICATION_TECH_DISCOVERED] = function NFC_NOTIFICATION_TECH_DISCOVERED() {
   debug("NFC_NOTIFICATION_TECH_DISCOVERED");
   let techList  = [];
-  let ndefMsgs  = [];
 
   let sessionId = Buf.readInt32();
   let techCount = Buf.readInt32();
@@ -385,14 +384,11 @@ NfcWorker[NFC_NOTIFICATION_TECH_DISCOVERED] = function NFC_NOTIFICATION_TECH_DIS
   }
 
   let ndefMsgCount = Buf.readInt32();
-  for (let count = 0; count < ndefMsgCount; count++) {
-    ndefMsgs.push(this.unMarshallNdefMessage());
-  }
+  let records = this.unMarshallNdefMessage();
   this.sendDOMMessage({type: "techDiscovered",
                        sessionId: sessionId,
                        techList: techList,
-                       ndef: ndefMsgs
-                       });
+                       records: records});
 };
 
 NfcWorker[NFC_NOTIFICATION_TECH_LOST] = function NFC_NOTIFICATION_TECH_LOST() {
diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js
index 2b2973416f009340b310ba850a0220f6b10e6e4d..516d7e9364ca7152241c4fa640bb13c3856188dd 100644
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -424,6 +424,15 @@ this.RIL_PREFERRED_NETWORK_TYPE_TO_GECKO = [
   GECKO_PREFERRED_NETWORK_TYPE_WCDMA_GSM_CDMA_EVDO
 ];
 
+this.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT = "gsm,wcdma,cdma,evdo";
+this.GECKO_SUPPORTED_NETWORK_TYPES = [
+  "gsm",
+  "wcdma",
+  "cdma",
+  "evdo",
+  "lte"
+];
+
 // Network registration states. See TS 27.007 7.2
 this.NETWORK_CREG_STATE_NOT_SEARCHING = 0;
 this.NETWORK_CREG_STATE_REGISTERED_HOME = 1;
diff --git a/dom/system/gonk/systemlibs.js b/dom/system/gonk/systemlibs.js
index decf2b45921f78db05f6509e6341fe4c5f640be1..b76822f77cabc597147652b5b98d53e8e64803ec 100644
--- a/dom/system/gonk/systemlibs.js
+++ b/dom/system/gonk/systemlibs.js
@@ -187,216 +187,7 @@ this.libnetutils = (function() {
   };
 
   iface.RESET_ALL_ADDRESSES = iface.RESET_IPV4_ADDRESSES |
-                              iface.RESET_IPV6_ADDRESSES
-
-  // dhcp_do_request's interface changed in SDK version 15. We try to hide
-  // this here by implementing the same JS API for both versions.
-
-  let sdkVersion = libcutils.property_get("ro.build.version.sdk") || "0";
-  sdkVersion = parseInt(sdkVersion, 10);
-  if (sdkVersion >= 15) {
-    let ipaddrbuf = ctypes.char.array(4096)();
-    let gatewaybuf = ctypes.char.array(4096)();
-    let prefixLen = ctypes.int();
-    let dns1buf = ctypes.char.array(4096)();
-    let dns2buf = ctypes.char.array(4096)();
-    let dnslistbuf = ctypes.char.ptr.array(4)();
-    let serverbuf = ctypes.char.array(4096)();
-    let lease = ctypes.int();
-    let vendorbuf = ctypes.char.array(4096)();
-    let domainbuf = ctypes.char.array(4096)();
-    let c_dhcp_do_request;
-    let c_dhcp_do_request_renew;
-
-    // also changed for 16 and 18
-    if (sdkVersion >= 18) { // 18 == JB 4.3
-      dnslistbuf[0] = dns1buf;
-      dnslistbuf[1] = dns2buf;
-      c_dhcp_do_request =
-        library.declare("dhcp_do_request", ctypes.default_abi,
-                        ctypes.int,       // return value
-                        ctypes.char.ptr,  // ifname
-                        ctypes.char.ptr,  // ipaddr
-                        ctypes.char.ptr,  // gateway
-                        ctypes.int.ptr,   // prefixlen
-                        ctypes.char.ptr.array(), // dns
-                        ctypes.char.ptr,  // server
-                        ctypes.int.ptr,   // lease
-                        ctypes.char.ptr,  // vendorinfo
-                        ctypes.char.ptr); // domain
-      c_dhcp_do_request_renew =
-        library.declare("dhcp_do_request_renew", ctypes.default_abi,
-                        ctypes.int,       // return value
-                        ctypes.char.ptr,  // ifname
-                        ctypes.char.ptr,  // ipaddr
-                        ctypes.char.ptr,  // gateway
-                        ctypes.int.ptr,   // prefixlen
-                        ctypes.char.ptr.array(),  // dns
-                        ctypes.char.ptr,  // server
-                        ctypes.int.ptr,   // lease
-                        ctypes.char.ptr,  // vendorinfo
-                        ctypes.char.ptr); // domain
-    } else if (sdkVersion >= 16) { // 16 == JB 4.1
-      c_dhcp_do_request =
-        library.declare("dhcp_do_request", ctypes.default_abi,
-                        ctypes.int,       // return value
-                        ctypes.char.ptr,  // ifname
-                        ctypes.char.ptr,  // ipaddr
-                        ctypes.char.ptr,  // gateway
-                        ctypes.int.ptr,   // prefixlen
-                        ctypes.char.ptr,  // dns1
-                        ctypes.char.ptr,  // dns2
-                        ctypes.char.ptr,  // server
-                        ctypes.int.ptr,   // lease
-                        ctypes.char.ptr); // vendorinfo
-    } else { // ICS
-      c_dhcp_do_request =
-        library.declare("dhcp_do_request", ctypes.default_abi,
-                        ctypes.int,      // return value
-                        ctypes.char.ptr, // ifname
-                        ctypes.char.ptr, // ipaddr
-                        ctypes.char.ptr, // gateway
-                        ctypes.int.ptr,  // prefixlen
-                        ctypes.char.ptr, // dns1
-                        ctypes.char.ptr, // dns2
-                        ctypes.char.ptr, // server
-                        ctypes.int.ptr); // lease
-    }
-
-
-    iface.dhcp_do_request = function dhcp_do_request(ifname) {
-      let ret;
-      if (sdkVersion >= 18) {
-        ret = c_dhcp_do_request(ifname,
-                                ipaddrbuf,
-                                gatewaybuf,
-                                prefixLen.address(),
-                                dnslistbuf,
-                                serverbuf,
-                                lease.address(),
-                                vendorbuf,
-                                domainbuf);
-      } else if (sdkVersion >= 16) {
-        ret = c_dhcp_do_request(ifname,
-                                ipaddrbuf,
-                                gatewaybuf,
-                                prefixLen.address(),
-                                dns1buf,
-                                dns2buf,
-                                serverbuf,
-                                lease.address(),
-                                vendorbuf);
-      } else {
-        ret = c_dhcp_do_request(ifname,
-                                ipaddrbuf,
-                                gatewaybuf,
-                                prefixLen.address(),
-                                dns1buf,
-                                dns2buf,
-                                serverbuf,
-                                lease.address());
-      }
-
-      if (ret && DEBUG) {
-        let error = iface.dhcp_get_errmsg();
-        dump("dhcp_do_request failed - " + error.readString());
-      }
-      let obj = {
-        ret: ret | 0,
-        ipaddr_str: ipaddrbuf.readString(),
-        mask: netHelpers.makeMask(prefixLen.value),
-        gateway_str: gatewaybuf.readString(),
-        dns1_str: dns1buf.readString(),
-        dns2_str: dns2buf.readString(),
-        server_str: serverbuf.readString(),
-        lease: lease.value | 0,
-        vendor_str: vendorbuf.readString(),
-        domain_str: domainbuf.readString()
-      };
-      obj.ipaddr = netHelpers.stringToIP(obj.ipaddr_str);
-      obj.mask_str = netHelpers.ipToString(obj.mask);
-      obj.broadcast_str = netHelpers.ipToString((obj.ipaddr & obj.mask) + ~obj.mask);
-      obj.gateway = netHelpers.stringToIP(obj.gateway_str);
-      obj.dns1 = netHelpers.stringToIP(obj.dns1_str);
-      obj.dns2 = netHelpers.stringToIP(obj.dns2_str);
-      obj.server = netHelpers.stringToIP(obj.server_str);
-      return obj;
-    };
-
-    // dhcp_do_request_renew() went away in newer libnetutils.
-    // .. and then came back in 4.3! XXX implement support for this
-    iface.dhcp_do_request_renew = iface.dhcp_do_request;
-
-    // Same deal with ifc_reset_connections.
-    let c_ifc_reset_connections =
-      library.declare("ifc_reset_connections",
-                      ctypes.default_abi,
-                      ctypes.int,
-                      ctypes.char.ptr,
-                      ctypes.int);
-    iface.ifc_reset_connections = function(ifname, reset_mask) {
-      return c_ifc_reset_connections(ifname, reset_mask) | 0;
-    }
-  } else { // version < 15 - we don't care anymore.
-    let ints = ctypes.int.array(8)();
-    let c_dhcp_do_request =
-      library.declare("dhcp_do_request", ctypes.default_abi,
-                      ctypes.int,      // return value
-                      ctypes.char.ptr, // ifname
-                      ctypes.int.ptr,  // ipaddr
-                      ctypes.int.ptr,  // gateway
-                      ctypes.int.ptr,  // mask
-                      ctypes.int.ptr,  // dns1
-                      ctypes.int.ptr,  // dns2
-                      ctypes.int.ptr,  // server
-                      ctypes.int.ptr); // lease
-    let c_dhcp_do_request_renew =
-      library.declare("dhcp_do_request_renew", ctypes.default_abi,
-                      ctypes.int,      // return value
-                      ctypes.char.ptr, // ifname
-                      ctypes.int.ptr,  // ipaddr
-                      ctypes.int.ptr,  // gateway
-                      ctypes.int.ptr,  // mask
-                      ctypes.int.ptr,  // dns1
-                      ctypes.int.ptr,  // dns2
-                      ctypes.int.ptr,  // server
-                      ctypes.int.ptr); // lease
-
-    let wrapCFunc = function wrapCFunc(c_fn) {
-      return function(ifname) {
-        let ret = c_fn(ifname,
-                       ints.addressOfElement(0),
-                       ints.addressOfElement(1),
-                       ints.addressOfElement(2),
-                       ints.addressOfElement(3),
-                       ints.addressOfElement(4),
-                       ints.addressOfElement(5),
-                       ints.addressOfElement(6));
-        if (ret && DEBUG) {
-          let error = iface.dhcp_get_errmsg();
-          dump("dhcp_do_request_* failed - " + error.readString());
-        }
-        return {ret: ret | 0,
-                ipaddr: ints[0] | 0,
-                gateway: ints[1] | 0,
-                mask: ints[2] | 0,
-                dns1: ints[3] | 0,
-                dns2: ints[4] | 0,
-                server: ints[5] | 0,
-                lease: ints[6] | 0};
-      };
-    };
-    iface.dhcp_do_request = wrapCFunc(c_dhcp_do_request);
-    iface.dhcp_do_request_renew = wrapCFunc(c_dhcp_do_request_renew);
-    let c_ifc_reset_connections =
-      library.declare("ifc_reset_connections",
-                      ctypes.default_abi,
-                      ctypes.int,
-                      ctypes.char.ptr);
-    iface.ifc_reset_connections = function(ifname, reset_mask) {
-      return c_ifc_reset_connections(ifname) | 0;
-    }
-  }
+                              iface.RESET_IPV6_ADDRESSES;
 
   return iface;
 })();
diff --git a/dom/system/moz.build b/dom/system/moz.build
index e810539bb85328f9e30688102ec716ed7df40f8e..801628d1e4b2bb947ac9c839ebe5673eb9ff662b 100644
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -53,9 +53,9 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'gklayout'
 # We fire the nsDOMDeviceAcceleration
 LOCAL_INCLUDES += [
-    '/content/events/src',
     '/dom/base',
     '/dom/bindings',
+    '/dom/events',
     '/js/xpconnect/loader',
 ]
 
diff --git a/dom/system/windows/moz.build b/dom/system/windows/moz.build
index 1c98a1daf6176650e32c7490fcdaa56f578d9c84..a112ceea9786bd0c670eb49064d928275e44f69a 100644
--- a/dom/system/windows/moz.build
+++ b/dom/system/windows/moz.build
@@ -10,7 +10,7 @@ SOURCES += [
 
 # We fire the nsDOMDeviceAcceleration
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
 ]
 
 FAIL_ON_WARNINGS = True
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
index 8457f1165fb738fc60db755ae4f87661ae1c5eda..3603136ccfb8075dbade0a8f119abbad6b20ceab 100644
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -110,555 +110,1105 @@ var legacyMozPrefixedInterfaces =
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AnalyserNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AnimationEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ArchiveRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Attr",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Audio",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioBuffer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AudioChannelManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioContext",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioBufferSourceNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioDestinationNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioListener",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioParam",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioProcessingEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioStreamTrack",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "BarProp",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "BatteryManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "BeforeUnloadEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "BiquadFilterNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Blob",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "BlobEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BluetoothAdapter", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BluetoothDevice", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BluetoothDeviceEvent", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BluetoothManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BluetoothStatusChangedEvent", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BoxObject", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BrowserFeedWriter", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CallEvent", b2g: true, pref: "dom.telephony.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CallGroupErrorEvent", b2g: true, pref: "dom.telephony.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CameraCapabilities",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CameraControl",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CameraManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasGradient",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasPattern",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasRenderingContext2D",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CaretPosition",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CDATASection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CFStateChangeEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ChannelMergerNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ChannelSplitterNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CharacterData",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ChromeWindow", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ClipboardEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CloseEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CommandEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Comment",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CompositionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Controllers",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ConvolverNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CRMFObject", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Crypto",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSS",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSS2Properties",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSCharsetRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSConditionRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSFontFaceRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "CSSFontFeatureValuesRule", release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSGroupingRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSImportRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSMediaRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSMozDocumentRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSNameSpaceRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSPageRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSPrimitiveValue",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSRuleList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSStyleDeclaration",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSStyleRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSStyleSheet",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSSupportsRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSValue",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSValueList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CustomEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DataChannel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DataContainerEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataErrorEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataStore", b2g: true, release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataStoreChangeEvent", b2g: true, release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataStoreCursor", b2g: true, release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransfer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DelayNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DesktopNotification",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DesktopNotificationCenter",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceLightEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceMotionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceOrientationEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceProximityEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceStorage",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceStorageChangeEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Document",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DocumentFragment",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DocumentType",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DOMConstructor", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMCursor",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMError",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMException",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMImplementation",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMMMIError",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMParser",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMRect",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMRectList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMSettableTokenList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMStringList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMStringMap",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMTokenList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMTransactionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DOMDownload", b2g: true, pref: "dom.mozDownloads.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DOMDownloadManager", b2g: true, pref: "dom.mozDownloads.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DownloadEvent", b2g: true, pref: "dom.mozDownloads.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DragEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "DynamicsCompressorNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Element",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ElementReplaceEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ErrorEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Event",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "EventListenerInfo",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "EventSource",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "EventTarget",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "File",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FileHandle",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FileList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FileReader",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FileRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "FMRadio", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FocusEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "FormData",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "GainNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Gamepad", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "GamepadAxisMoveEvent", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "GamepadButtonEvent", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "GamepadButton", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "GamepadEvent", desktop: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HashChangeEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "History",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAnchorElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAppletElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAreaElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAudioElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLBaseElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLBodyElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLBRElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLButtonElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLCanvasElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLCollection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLContentElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDataElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDataListElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDirectoryElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDivElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDListElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLDocument",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLEmbedElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFieldSetElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFontElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFormControlsCollection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFormElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFrameElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLFrameSetElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLHeadElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLHeadingElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLHRElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLHtmlElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLIFrameElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLImageElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLInputElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLLabelElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLLegendElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLLIElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLLinkElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMapElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMediaElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMenuElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMenuItemElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMetaElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLMeterElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLModElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLObjectElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLOListElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLOptGroupElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLOptionElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLOptionsCollection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLOutputElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLParagraphElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLParamElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLPreElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLProgressElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLPropertiesCollection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLQuoteElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLScriptElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLSelectElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLShadowElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLSourceElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLSpanElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLStyleElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableCaptionElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableCellElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableColElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableRowElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTableSectionElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTemplateElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTextAreaElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTimeElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTitleElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLTrackElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLUListElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLUnknownElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLVideoElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "IccChangeEvent", b2g: true, pref: "dom.icc.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "IccCardLockError", b2g: true, pref: "dom.icc.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBCursor",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBCursorWithValue",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBDatabase",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBFactory",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBFileHandle",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBIndex",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBKeyRange",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBObjectStore",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBOpenDBRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBTransaction",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "IDBVersionChangeEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Image",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ImageData",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "InstallTrigger", b2g: false, xbl: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyboardEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "LocalMediaStream",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Location",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "LockedFile",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaElementAudioSourceNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaError",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaQueryList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaRecorder",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaStream",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaStreamAudioDestinationNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaStreamAudioSourceNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MediaStreamEvent", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MediaStreamTrack",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MessageEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MessagePort",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MimeType",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MimeTypeArray",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ModalContentWindow",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MouseEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MouseScrollEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozActivity", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozApplicationEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozCellBroadcast", b2g: true, pref: "dom.cellbroadcast.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozCellBroadcastEvent", b2g: true, pref: "dom.cellbroadcast.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozConnection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "mozContact",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozContactChangeEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozCSSKeyframeRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozCSSKeyframesRule",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozEmergencyCbModeEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozIcc", b2g: true, pref: "dom.icc.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozIccManager", b2g: true, pref: "dom.icc.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozInputContext", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozInputMethodManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozMmsEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozMmsMessage",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozMobileConnection", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozMobileConnectionArray", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozMobileMessageManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozMobileMessageThread",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozNamedAttrMap",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozNdefRecord", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozNFCPeer", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozNFCTag", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozOtaStatusEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozPowerManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "mozRTCIceCandidate", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "mozRTCPeerConnection", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "mozRTCSessionDescription", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozSettingsEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozSmsEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozSmsFilter",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozSmsMessage",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozSmsSegmentInfo",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozSpeakerManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozStkCommandEvent", b2g: true, pref: "dom.icc.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozTimeManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemail", b2g: true, pref: "dom.voicemail.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MozWakeLock",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiConnectionInfoEvent", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiStatusChangeEvent", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationObserver",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationRecord",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Navigator",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Node",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "NodeFilter",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "NodeIterator",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "NodeList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "NotifyAudioAvailableEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Notification",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "NotifyPaintEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineAudioCompletionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineAudioContext",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineResourceList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Option",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "OscillatorNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PageTransitionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PaintRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PaintRequestList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PannerNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Performance",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceNavigation",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceTiming",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PeriodicWave",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PhoneNumberService",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Plugin",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PluginArray",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PointerEvent", pref: "dom.w3c_pointer_events.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PopStateEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PopupBlockedEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ProcessingInstruction",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ProgressEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Promise", b2g: false, release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "PropertyNodeList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Range",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "RecordErrorEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Rect",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "RGBColor",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "RTCDataChannelEvent", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "RTCPeerConnectionIceEvent", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "RTCStatsReport", pref: "media.peerconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Screen",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ScriptProcessorNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ScrollAreaEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Selection",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SettingsLock",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SettingsManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ShadowRoot", pref: "dom.webcomponents.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SharedWorker", pref: "dom.workers.sharedWorkers.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SimpleGestureEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SimpleTest", xbl: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SmartCardEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SpeechRecognitionError",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SpeechRecognitionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SpeechSynthesisEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SpeechSynthesis", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SpeechSynthesisUtterance", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SpeechSynthesisVoice", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SpecialPowers", xbl: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Storage",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "StorageEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "StyleSheet",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "StyleSheetList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAltGlyphElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAngle",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedAngle",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedBoolean",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedEnumeration",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedInteger",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedLength",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedLengthList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedNumber",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedNumberList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedPreserveAspectRatio",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedRect",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedString",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimatedTransformList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimateElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimateMotionElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimateTransformElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGAnimationElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGCircleElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGClipPathElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGComponentTransferFunctionElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGDefsElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGDescElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGDocument",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGEllipseElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEBlendElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEColorMatrixElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEComponentTransferElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFECompositeElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEConvolveMatrixElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEDiffuseLightingElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEDisplacementMapElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEDistantLightElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEFloodElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEFuncAElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEFuncBElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEFuncGElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEFuncRElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEGaussianBlurElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEImageElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEMergeElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEMergeNodeElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEMorphologyElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEOffsetElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFEPointLightElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFESpecularLightingElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFESpotLightElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFETileElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFETurbulenceElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGFilterElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGForeignObjectElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGGElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGGradientElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGGraphicsElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGImageElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGLength",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGLengthList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGLinearGradientElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGLineElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGMarkerElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGMaskElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGMatrix",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGMetadataElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGMPathElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGNumber",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGNumberList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSeg",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegArcAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegArcRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegClosePath",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoCubicAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoCubicRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoCubicSmoothAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoCubicSmoothRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoQuadraticAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoQuadraticRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoQuadraticSmoothAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegCurvetoQuadraticSmoothRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoHorizontalAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoHorizontalRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoVerticalAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegLinetoVerticalRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegMovetoAbs",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPathSegMovetoRel",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPatternElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPoint",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPointList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPolygonElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPolylineElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGPreserveAspectRatio",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGRadialGradientElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGRect",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGRectElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGScriptElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGSetElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGStopElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGStringList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGStyleElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGSVGElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGSwitchElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGSymbolElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTextContentElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTextElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTextPathElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTextPositioningElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTitleElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTransform",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTransformList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGTSpanElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGUnitTypes",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGUseElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGViewElement",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGZoomAndPan",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGZoomEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Telephony", b2g: true, pref: "dom.telephony.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TelephonyCall", b2g: true, pref: "dom.telephony.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TelephonyCallGroup", b2g: true, pref: "dom.telephony.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Text",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextDecoder",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextEncoder",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextMetrics",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextTrack",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextTrackCueList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TextTrackList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TimeEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TimeRanges",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Touch",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TouchEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TouchList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TrackEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TransitionEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeColumn", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeColumns", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeContentView", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeSelection", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "TreeWalker",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "UIEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "UndoManager",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "URL",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "URLSearchParams",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "UserDataHandler", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "UserProximityEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "USSDReceivedEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "ValidityState",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "VideoStreamTrack",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTCue",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTRegion",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTRegionList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WaveShaperNode",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLActiveInfo",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLBuffer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLFramebuffer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLProgram",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLRenderbuffer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLRenderingContext",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLShader",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLShaderPrecisionFormat",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLTexture",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLUniformLocation",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLVertexArray",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebSocket",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WheelEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Window",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "WindowUtils",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Worker",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLDocument",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLHttpRequest",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLHttpRequestUpload",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLSerializer",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLStylesheetProcessingInstruction",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XPathEvaluator",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XPathExpression",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XPathNamespace",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XPathNSResolver",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XPathResult",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "XSLTProcessor",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULButtonElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULCheckboxElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULCommandDispatcher", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULCommandEvent", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULControlElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULControllers", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULDocument", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULLabeledControlElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULPopupElement", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULTemplateBuilder", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULTreeBuilder", xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
diff --git a/dom/webidl/MozNfc.webidl b/dom/webidl/MozNfc.webidl
index 0560cc0c5741fe7a85fd0df2be25c70dcd894239..5d01c2cd75c89a32eb4ff6edac78b22127d41802 100644
--- a/dom/webidl/MozNfc.webidl
+++ b/dom/webidl/MozNfc.webidl
@@ -23,7 +23,9 @@ interface MozNfc : EventTarget {
     */
    DOMRequest checkP2PRegistration(DOMString manifestUrl);
 
+   [Func="Navigator::HasNfcPeerSupport"]
    attribute EventHandler onpeerready;
+   [Func="Navigator::HasNfcPeerSupport"]
    attribute EventHandler onpeerlost;
    [ChromeOnly]
    void eventListenerWasAdded(DOMString aType);
diff --git a/dom/webidl/URLUtils.webidl b/dom/webidl/URLUtils.webidl
index 12cebceb74deaa425c2419324ceb27139e294b21..a02503c2074d9e3548c5e9023c566ace9196098f 100644
--- a/dom/webidl/URLUtils.webidl
+++ b/dom/webidl/URLUtils.webidl
@@ -16,7 +16,9 @@
 [NoInterfaceObject]
 interface URLUtils {
   [SetterThrows]
-  stringifier attribute DOMString href;
+  // Bug 824857: no support for stringifier attributes yet.
+  //  stringifier attribute DOMString href;
+           attribute DOMString href;
   readonly attribute DOMString origin;
 
            attribute DOMString protocol;
diff --git a/dom/wifi/NetUtils.cpp b/dom/wifi/NetUtils.cpp
index 12ced65328bd6321b20e918e476f31b124f46584..90c4de24a991192ebdfd6b1571c40bd7f397eebe 100644
--- a/dom/wifi/NetUtils.cpp
+++ b/dom/wifi/NetUtils.cpp
@@ -132,6 +132,16 @@ int32_t NetUtils::do_dhcp_do_request(const char *ifname,
     char domains[PROPERTY_VALUE_MAX];
     ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns,
                           server, lease, vendorinfo, domains);
+  } else if (sdkVersion == 19) {
+    // JB 4.4
+    // http://androidxref.com/4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#18
+    DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*,  uint32_t*, char**, char*, uint32_t*, char*, char*, char*)
+    USE_DLFUNC(dhcp_do_request)
+    char *dns[3] = {dns1, dns2, nullptr};
+    char domains[PROPERTY_VALUE_MAX];
+    char mtu[PROPERTY_VALUE_MAX];
+    ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns,
+                          server, lease, vendorinfo, domains, mtu);
   } else {
     NS_WARNING("Unable to perform do_dhcp_request: unsupported sdk version!");
   }
diff --git a/dom/wifi/WifiUtils.cpp b/dom/wifi/WifiUtils.cpp
index 1fdb95241fba51004e55a9f23cdeb24b30c320bc..a92ba15a2e66b109bd2d226392afed3f4a45ff2c 100644
--- a/dom/wifi/WifiUtils.cpp
+++ b/dom/wifi/WifiUtils.cpp
@@ -141,7 +141,6 @@ class ICSWpaSupplicantImpl : public WpaSupplicantImpl
 public:
   DEFAULT_IMPL(wifi_load_driver, int32_t, )
   DEFAULT_IMPL(wifi_unload_driver, int32_t, )
-  DEFAULT_IMPL(wifi_stop_supplicant, int32_t, )
 
   DEFINE_DLFUNC(wifi_wait_for_event, int32_t, char*, size_t)
   int32_t do_wifi_wait_for_event(const char *iface, char *buf, size_t len) {
@@ -161,6 +160,12 @@ public:
     return wifi_start_supplicant();
   }
 
+  DEFINE_DLFUNC(wifi_stop_supplicant, int32_t)
+  int32_t do_wifi_stop_supplicant(int32_t) {
+    USE_DLFUNC(wifi_stop_supplicant)
+    return wifi_stop_supplicant();
+  }
+
   DEFINE_DLFUNC(wifi_connect_to_supplicant, int32_t, )
   int32_t do_wifi_connect_to_supplicant(const char* iface) {
     USE_DLFUNC(wifi_connect_to_supplicant)
@@ -197,6 +202,12 @@ public:
     return wifi_start_supplicant(arg);
   }
 
+  DEFINE_DLFUNC(wifi_stop_supplicant, int32_t, int32_t)
+  int32_t do_wifi_stop_supplicant(int32_t arg) {
+    USE_DLFUNC(wifi_stop_supplicant)
+    return wifi_stop_supplicant(arg);
+  }
+
   DEFINE_DLFUNC(wifi_connect_to_supplicant, int32_t, const char*)
   int32_t do_wifi_connect_to_supplicant(const char* iface) {
     USE_DLFUNC(wifi_connect_to_supplicant)
@@ -210,13 +221,33 @@ public:
   }
 };
 
+// KK implementation.
+// We only redefine the methods that have a different signature than on ICS.
+class KKWpaSupplicantImpl : public ICSWpaSupplicantImpl
+{
+public:
+  DEFINE_DLFUNC(wifi_start_supplicant, int32_t, int32_t)
+  int32_t do_wifi_start_supplicant(int32_t arg) {
+    USE_DLFUNC(wifi_start_supplicant)
+    return wifi_start_supplicant(arg);
+  }
+
+  DEFINE_DLFUNC(wifi_stop_supplicant, int32_t, int32_t)
+  int32_t do_wifi_stop_supplicant(int32_t arg) {
+    USE_DLFUNC(wifi_stop_supplicant)
+    return wifi_stop_supplicant(arg);
+  }
+};
+
 // Concrete class to use to access the wpa supplicant.
 WpaSupplicant::WpaSupplicant()
 {
   if (NetUtils::SdkVersion() < 16) {
     mImpl = new ICSWpaSupplicantImpl();
-  } else {
+  } else if (NetUtils::SdkVersion() < 19) {
     mImpl = new JBWpaSupplicantImpl();
+  } else {
+    mImpl = new KKWpaSupplicantImpl();
   }
   mNetUtils = new NetUtils();
 };
@@ -278,7 +309,7 @@ bool WpaSupplicant::ExecuteCommand(CommandOptions aOptions,
   } else if (aOptions.mCmd.EqualsLiteral("start_supplicant")) {
     aResult.mStatus = mImpl->do_wifi_start_supplicant(0);
   } else if (aOptions.mCmd.EqualsLiteral("stop_supplicant")) {
-    aResult.mStatus = mImpl->do_wifi_stop_supplicant();
+    aResult.mStatus = mImpl->do_wifi_stop_supplicant(0);
   } else if (aOptions.mCmd.EqualsLiteral("connect_to_supplicant")) {
     aResult.mStatus = mImpl->do_wifi_connect_to_supplicant(aInterface.get());
   } else if (aOptions.mCmd.EqualsLiteral("ifc_enable")) {
diff --git a/dom/wifi/WifiUtils.h b/dom/wifi/WifiUtils.h
index 6a82ceffcfbf22639177791df2552129f584022b..9398b407c32759d6f0d530cb9a025e6aa8b879b3 100644
--- a/dom/wifi/WifiUtils.h
+++ b/dom/wifi/WifiUtils.h
@@ -90,10 +90,10 @@ public:
   virtual ~WpaSupplicantImpl() {}
 
   virtual int32_t
-  do_wifi_wait_for_event(const char *iface, char *buf, size_t len) = 0; // ICS != JB
+  do_wifi_wait_for_event(const char *iface, char *buf, size_t len) = 0; // KK == ICS != JB
 
   virtual int32_t
-  do_wifi_command(const char* iface, const char* cmd, char* buff, size_t* len) = 0; // ICS != JB
+  do_wifi_command(const char* iface, const char* cmd, char* buff, size_t* len) = 0; // KK == ICS != JB
 
   virtual int32_t
   do_wifi_load_driver() = 0;
@@ -102,16 +102,16 @@ public:
   do_wifi_unload_driver() = 0;
 
   virtual int32_t
-  do_wifi_start_supplicant(int32_t) = 0; // ICS != JB
+  do_wifi_start_supplicant(int32_t) = 0; // ICS != JB == KK
 
   virtual int32_t
-  do_wifi_stop_supplicant() = 0;
+  do_wifi_stop_supplicant(int32_t) = 0; //ICS != JB == KK
 
   virtual int32_t
-  do_wifi_connect_to_supplicant(const char* iface) = 0; // ICS != JB
+  do_wifi_connect_to_supplicant(const char* iface) = 0; // KK == ICS != JB
 
   virtual void
-  do_wifi_close_supplicant_connection(const char* iface) = 0; // ICS != JB
+  do_wifi_close_supplicant_connection(const char* iface) = 0; // KK == ICS != JB
 };
 
 // Concrete class to use to access the wpa supplicant.
diff --git a/dom/workers/moz.build b/dom/workers/moz.build
index 584291d8fadd3570941c7f0c7901d64578b64be7..ee9acee1531b3fbb4862e85ec22720ce18e310dc 100644
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -58,7 +58,7 @@ LOCAL_INCLUDES += [
     '../base',
     '../system',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/xpcom/build',
     '/xpcom/threads',
 ]
diff --git a/dom/xbl/moz.build b/dom/xbl/moz.build
index b1026058945cb9ed708f91b126e97db1db0af659..c808bce44ff969e2bad0c51b9fb1575ef1ddb10b 100644
--- a/dom/xbl/moz.build
+++ b/dom/xbl/moz.build
@@ -43,12 +43,12 @@ MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
-    '/content/events/src',
     '/content/html/document/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/document/src',
     '/dom/base',
+    '/dom/events',
     '/layout/style',
     '/xpcom/ds',
 ]
diff --git a/editor/libeditor/base/moz.build b/editor/libeditor/base/moz.build
index 7d2a6c26e044008474ddf89916471a828391db0e..b0d4118e478edcdc2979a297d3230f7379f9bdc4 100644
--- a/editor/libeditor/base/moz.build
+++ b/editor/libeditor/base/moz.build
@@ -36,7 +36,7 @@ FAIL_ON_WARNINGS = True
 LOCAL_INCLUDES += [
     '../text',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/editor/txmgr/src',
     '/extensions/spellcheck/src',
     '/layout/style',
diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp
index a0c8c03527acd0de936a787a2b541e0f67493fcc..433c2f205050b2120c375859e4b00470867176f1 100644
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -381,18 +381,9 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
 
   MarkChanged();
 
-  IntRect sourceIntRect;
-  bool integerAligned = aSource.ToIntRect(&sourceIntRect);
-
   SkRect destRect = RectToSkRect(aDest);
   SkRect sourceRect = RectToSkRect(aSource);
 
-  Rect boundingSource = aSource;
-  boundingSource.RoundOut();
-
-  SkRect sourceBoundingRect = RectToSkRect(boundingSource);
-  SkIRect sourceBoundingIRect = RectToSkIRect(boundingSource);
-
   TempBitmap bitmap = GetBitmapForSurface(aSurface);
  
   AutoPaintSetup paint(mCanvas.get(), aOptions);
@@ -400,24 +391,7 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
     paint.mPaint.setFilterBitmap(false);
   }
 
-  if (!integerAligned) {
-    // We need to inflate our destRect by the same amount we inflated sourceRect
-    // by when we rounded up to the nearest integer size to ensure we interpolate
-    // the edge pixels properly, but clip to the true destination rect first so
-    // we don't draw outside our designated area.
-    mCanvas->save();
-    mCanvas->clipRect(destRect);
-
-    SkMatrix rectTransform;
-    rectTransform.setRectToRect(sourceRect, sourceBoundingRect, SkMatrix::kFill_ScaleToFit);
-    rectTransform.mapRect(&destRect);
-  }
-
-  mCanvas->drawBitmapRect(bitmap.mBitmap, &sourceBoundingIRect, destRect, &paint.mPaint);
-
-  if (!integerAligned) {
-    mCanvas->restore();
-  }
+  mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
 }
 
 void
diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp
index bf7f69b3d9dab25d31f65a6b59ae3f7fe6e5b46b..5d7c37a041f0150ed2a52a13e8812f5c35ecee2e 100644
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1470,6 +1470,17 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
         aLayerMetrics.mScrollOffset.x, aLayerMetrics.mScrollOffset.y);
 
       mFrameMetrics.mScrollOffset = aLayerMetrics.mScrollOffset;
+
+      // It is possible that when we receive this mUpdateScrollOffset flag, we have
+      // just sent a content repaint request, and it is pending inflight. That repaint
+      // request would have our old scroll offset, and will get processed on the content
+      // thread as we're processing this mUpdateScrollOffset flag. This would leave
+      // things in a state where content has the old APZC scroll offset and the APZC
+      // has the new content-specified scroll offset. In such a case we want to trigger
+      // another repaint request to bring things back in sync. In most cases this repaint
+      // request will be a no-op and get filtered out in RequestContentRepaint, so it
+      // shouldn't have bad performance implications.
+      needContentRepaint = true;
     }
   }
 
diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build
index 5d61bbb20e5edadb84f7a383a05ea3a55923ddcd..16cccb879d0d4525241f3b7892a70752be0a42aa 100644
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -312,7 +312,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'thebes'
 
 LOCAL_INCLUDES += [
-    '/content/events/src',
+    '/dom/events',
 ]
 
 if CONFIG['MOZ_DEBUG']:
diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp
index fc004d092ee65e8f266b6ad6b2b261c8bca118a8..641d916b50f9775f23b130b28da792e6fe6bcd93 100644
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -268,9 +268,6 @@ GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
   case gfx::SurfaceFormat::R5G6B5:
     format = android::PIXEL_FORMAT_RGB_565;
     break;
-  case gfx::SurfaceFormat::A8:
-    format = android::PIXEL_FORMAT_A_8;
-    break;
   default:
     NS_WARNING("Unsupported surface format");
     return false;
diff --git a/ipc/dbus/DBusThread.cpp b/ipc/dbus/DBusThread.cpp
index 621c2bfc96109b7495392f36843d31307e45f7c0..e0907f0637499169891d3ecb605df24d962f1eba 100644
--- a/ipc/dbus/DBusThread.cpp
+++ b/ipc/dbus/DBusThread.cpp
@@ -122,18 +122,31 @@ void DBusWatcher::StartWatching()
   int fd = dbus_watch_get_unix_fd(mWatch);
 
   MessageLoopForIO* ioLoop = MessageLoopForIO::current();
-  ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
-                              &mReadWatcher, this);
-  ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
-                              &mWriteWatcher, this);
+
+  unsigned int flags = dbus_watch_get_flags(mWatch);
+
+  if (flags & DBUS_WATCH_READABLE) {
+    ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
+                                &mReadWatcher, this);
+  }
+  if (flags & DBUS_WATCH_WRITABLE) {
+    ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
+                                &mWriteWatcher, this);
+  }
 }
 
 void DBusWatcher::StopWatching()
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  mReadWatcher.StopWatchingFileDescriptor();
-  mWriteWatcher.StopWatchingFileDescriptor();
+  unsigned int flags = dbus_watch_get_flags(mWatch);
+
+  if (flags & DBUS_WATCH_READABLE) {
+    mReadWatcher.StopWatchingFileDescriptor();
+  }
+  if (flags & DBUS_WATCH_WRITABLE) {
+    mWriteWatcher.StopWatchingFileDescriptor();
+  }
 }
 
 // DBus utility functions, used as function pointers in DBus setup
diff --git a/js/public/CallNonGenericMethod.h b/js/public/CallNonGenericMethod.h
index 05097f0294c86a2e27b16ba32f924afd9a6f4c20..c205e51c1e5a7625a73882666a27fd470b53440a 100644
--- a/js/public/CallNonGenericMethod.h
+++ b/js/public/CallNonGenericMethod.h
@@ -14,7 +14,7 @@
 namespace JS {
 
 // Returns true if |v| is considered an acceptable this-value.
-typedef bool (*IsAcceptableThis)(Handle<Value> v);
+typedef bool (*IsAcceptableThis)(HandleValue v);
 
 // Implements the guts of a method; guaranteed to be provided an acceptable
 // this-value, as determined by a corresponding IsAcceptableThis method.
diff --git a/js/public/Class.h b/js/public/Class.h
index 9c20294279f729ab6dc5c3dda7f119627a5d4174..320ba0ad0cfd48aaf79b73a81f37f9c252b0b480 100644
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -152,8 +152,8 @@ typedef JS::Handle<SpecialId> HandleSpecialId;
 // be a string (Unicode property identifier) or an int (element index).  The
 // *vp out parameter, on success, is the new property value after the action.
 typedef bool
-(* JSPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                 JS::MutableHandle<JS::Value> vp);
+(* JSPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
+                 JS::MutableHandleValue vp);
 
 // Set a property named by id in obj, treating the assignment as strict
 // mode code if strict is true. Note the jsid id type -- id may be a string
@@ -161,8 +161,8 @@ typedef bool
 // parameter, on success, is the new property value after the
 // set.
 typedef bool
-(* JSStrictPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                       bool strict, JS::MutableHandle<JS::Value> vp);
+(* JSStrictPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
+                       bool strict, JS::MutableHandleValue vp);
 
 // Delete a property named by id in obj.
 //
@@ -178,7 +178,7 @@ typedef bool
 // property, or an inherited property, is allowed -- it's just pointless),
 // set *succeeded to true and return true.
 typedef bool
-(* JSDeletePropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+(* JSDeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                        bool *succeeded);
 
 // This function type is used for callbacks that enumerate the properties of
@@ -212,13 +212,13 @@ typedef bool
 // The return value is used to indicate success, with a value of false
 // indicating failure.
 typedef bool
-(* JSNewEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp enum_op,
-                     JS::MutableHandle<JS::Value> statep, JS::MutableHandle<jsid> idp);
+(* JSNewEnumerateOp)(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
+                     JS::MutableHandleValue statep, JS::MutableHandleId idp);
 
 // The old-style JSClass.enumerate op should define all lazy properties not
 // yet reflected in obj.
 typedef bool
-(* JSEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj);
+(* JSEnumerateOp)(JSContext *cx, JS::HandleObject obj);
 
 // Resolve a lazy property named by id in obj by defining it directly in obj.
 // Lazy properties are those reflected from some peer native property space
@@ -231,7 +231,7 @@ typedef bool
 //
 // NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
 typedef bool
-(* JSResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id);
+(* JSResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 
 // Like JSResolveOp, but flags provide contextual information as follows:
 //
@@ -244,14 +244,14 @@ typedef bool
 // This hook instead of JSResolveOp is called via the JSClass.resolve member
 // if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
 typedef bool
-(* JSNewResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, unsigned flags,
-                   JS::MutableHandle<JSObject*> objp);
+(* JSNewResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned flags,
+                   JS::MutableHandleObject objp);
 
 // Convert obj to the given type, returning true with the resulting value in
 // *vp on success, and returning false on error or exception.
 typedef bool
-(* JSConvertOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSType type,
-                JS::MutableHandle<JS::Value> vp);
+(* JSConvertOp)(JSContext *cx, JS::HandleObject obj, JSType type,
+                JS::MutableHandleValue vp);
 
 // Finalize obj, which the garbage collector has determined to be unreachable
 // from other live objects or from GC roots.  Obviously, finalizers must never
@@ -269,8 +269,8 @@ struct JSStringFinalizer {
 // value in *vp, and its attributes in *attrsp.  As for JSPropertyOp above, id
 // is either a string or an int jsval.
 typedef bool
-(* JSCheckAccessOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                    JSAccessMode mode, JS::MutableHandle<JS::Value> vp);
+(* JSCheckAccessOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
+                    JSAccessMode mode, JS::MutableHandleValue vp);
 
 // Return whether the first principal subsumes the second. The exact meaning of
 // 'subsumes' is left up to the browser. Subsumption is checked inside the JS
@@ -282,7 +282,7 @@ typedef bool
 // true on success with true in *bp if v is an instance of obj, false in
 // *bp otherwise.
 typedef bool
-(* JSHasInstanceOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp,
+(* JSHasInstanceOp)(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp,
                     bool *bp);
 
 // Function type for trace operation of the class called to enumerate all
@@ -303,7 +303,7 @@ typedef void
 // A generic type for functions mapping an object to another object, or null
 // if an error or exception was thrown on cx.
 typedef JSObject *
-(* JSObjectOp)(JSContext *cx, JS::Handle<JSObject*> obj);
+(* JSObjectOp)(JSContext *cx, JS::HandleObject obj);
 
 // Hook that creates an iterator object for a given object. Returns the
 // iterator object or null if an error or exception was thrown on cx.
diff --git a/js/public/Id.h b/js/public/Id.h
index 5bdb2d4070fb65a1aebd4b2a60d46842c8a939bc..8c8d929e00a28155c94e0d391b8925b7902de45a 100644
--- a/js/public/Id.h
+++ b/js/public/Id.h
@@ -151,8 +151,8 @@ JSID_IS_EMPTY(const jsid id)
 extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
 extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
 
-extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_VOIDHANDLE;
-extern JS_PUBLIC_DATA(const JS::Handle<jsid>) JSID_EMPTYHANDLE;
+extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
+extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
 
 namespace js {
 
diff --git a/js/public/StructuredClone.h b/js/public/StructuredClone.h
index d32bdd8dd695b7eb7d1348705488336b61269c07..b3867d1237139791d8047ff8dc4efffadba270ad 100644
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -43,7 +43,7 @@ typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReade
 //
 // Return true on success, false on error/exception.
 typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
-                                         JS::Handle<JSObject*> obj, void *closure);
+                                         JS::HandleObject obj, void *closure);
 
 // This is called when JS_WriteStructuredClone is given an invalid transferable.
 // To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException
diff --git a/js/public/Value.h b/js/public/Value.h
index 2b5fe3144a977742657ddf3eca2ecaf98c43fd72..bad89b988288d556f32ecbf9dfc613c546f70d90 100644
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1951,8 +1951,8 @@ extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
 
 namespace JS {
 
-extern JS_PUBLIC_DATA(const Handle<Value>) NullHandleValue;
-extern JS_PUBLIC_DATA(const Handle<Value>) UndefinedHandleValue;
+extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue;
+extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
 
 }
 
diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
index 3bd1110ce5912e2f4bb103d03d61d4cdc18b7c03..eac3c0d669649557c261f7950776282eb6d7aa28 100644
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1475,14 +1475,14 @@ TypedDatum::createUnattachedWithClass(JSContext *cx,
     return static_cast<TypedDatum*>(&*obj);
 }
 
-/*static*/ void
+void
 TypedDatum::attach(uint8_t *memory)
 {
     setPrivate(memory);
     setReservedSlot(JS_DATUM_SLOT_OWNER, ObjectValue(*this));
 }
 
-/*static*/ void
+void
 TypedDatum::attach(JSObject &datum, uint32_t offset)
 {
     JS_ASSERT(IsTypedDatum(datum));
@@ -2244,6 +2244,15 @@ TypedDatum::typedMem() const
     return TypedMem(*this);
 }
 
+TypedDatum *
+TypedDatum::owner() const
+{
+    JSObject *owner = getReservedSlot(JS_DATUM_SLOT_OWNER).toObjectOrNull();
+    if (!owner)
+        return nullptr;
+    return &AsTypedDatum(*owner);
+}
+
 /******************************************************************************
  * Typed Objects
  */
diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h
index 8812cc4faf811113e0fd7e66ce2d076c5164a00b..295c9fb9d2f21bae29b6b9787f49cf29bde3ebc0 100644
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -400,6 +400,7 @@ class TypedDatum : public JSObject
 
     TypeRepresentation *datumTypeRepresentation() const;
     uint8_t *typedMem() const;
+    TypedDatum *owner() const;
 };
 
 class TypedObject : public TypedDatum
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 62b0c0962d9c8938cf9dfb1eb65842b92f1619cc..42686cb356435ae96584d17791a6a19427a1e4f4 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1496,7 +1496,7 @@ CodeGenerator::visitForkJoinSlice(LForkJoinSlice *lir)
 }
 
 bool
-CodeGenerator::visitGuardThreadLocalObject(LGuardThreadLocalObject *lir)
+CodeGenerator::visitGuardThreadExclusive(LGuardThreadExclusive *lir)
 {
     JS_ASSERT(gen->info().executionMode() == ParallelExecution);
 
@@ -1504,7 +1504,7 @@ CodeGenerator::visitGuardThreadLocalObject(LGuardThreadLocalObject *lir)
     masm.setupUnalignedABICall(2, tempReg);
     masm.passABIArg(ToRegister(lir->forkJoinSlice()));
     masm.passABIArg(ToRegister(lir->object()));
-    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, IsThreadLocalObject));
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ParallelWriteGuard));
 
     OutOfLineAbortPar *bail = oolAbortPar(ParallelBailoutIllegalWrite, lir);
     if (!bail)
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 570a4dc6c731301e5a60ed614a12fc45e589ad1f..61e3e39f75a6eed98b88b7ebd7a8ebf321a11d34 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -207,7 +207,7 @@ class CodeGenerator : public CodeGeneratorSpecific
     bool visitStringSplit(LStringSplit *lir);
     bool visitFunctionEnvironment(LFunctionEnvironment *lir);
     bool visitForkJoinSlice(LForkJoinSlice *lir);
-    bool visitGuardThreadLocalObject(LGuardThreadLocalObject *lir);
+    bool visitGuardThreadExclusive(LGuardThreadExclusive *lir);
     bool visitCallGetProperty(LCallGetProperty *lir);
     bool visitCallGetElement(LCallGetElement *lir);
     bool visitCallSetElement(LCallSetElement *lir);
diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h
index c9cc5baf1e58d8e18b369a472cf04630c609ed89..73cd2c323a6d7b3be0f413d83708d31060eda119 100644
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -5144,12 +5144,12 @@ class LRestPar : public LCallInstructionHelper<1, 2, 3>
     }
 };
 
-class LGuardThreadLocalObject : public LCallInstructionHelper<0, 2, 1>
+class LGuardThreadExclusive : public LCallInstructionHelper<0, 2, 1>
 {
   public:
-    LIR_HEADER(GuardThreadLocalObject);
+    LIR_HEADER(GuardThreadExclusive);
 
-    LGuardThreadLocalObject(const LAllocation &slice, const LAllocation &object, const LDefinition &temp1) {
+    LGuardThreadExclusive(const LAllocation &slice, const LAllocation &object, const LDefinition &temp1) {
         setOperand(0, slice);
         setOperand(1, object);
         setTemp(0, temp1);
diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h
index 730052356d4899abc08c1cc670c120c88642e806..6cf1a393bc510919033a9ca534ccc3d0436f2161 100644
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -168,7 +168,7 @@
     _(GuardObjectType)              \
     _(GuardObjectIdentity)          \
     _(GuardClass)                   \
-    _(GuardThreadLocalObject)       \
+    _(GuardThreadExclusive)         \
     _(TypeBarrierV)                 \
     _(TypeBarrierO)                 \
     _(MonitorTypes)                 \
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index 2b21064b4586a36c1600ab9c29bafa303a58942b..ee4daa5dc35d42a6d473f4a7d8c85aa1be72371d 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2055,12 +2055,16 @@ LIRGenerator::visitForkJoinSlice(MForkJoinSlice *ins)
 }
 
 bool
-LIRGenerator::visitGuardThreadLocalObject(MGuardThreadLocalObject *ins)
-{
-    LGuardThreadLocalObject *lir =
-        new(alloc()) LGuardThreadLocalObject(useFixed(ins->forkJoinSlice(), CallTempReg0),
-                                             useFixed(ins->object(), CallTempReg1),
-                                             tempFixed(CallTempReg2));
+LIRGenerator::visitGuardThreadExclusive(MGuardThreadExclusive *ins)
+{
+    // FIXME (Bug 956281) -- For now, we always generate the most
+    // general form of write guard check. we could employ TI feedback
+    // to optimize this if we know that the object being tested is a
+    // typed object or know that it is definitely NOT a typed object.
+    LGuardThreadExclusive *lir =
+        new(alloc()) LGuardThreadExclusive(useFixed(ins->forkJoinSlice(), CallTempReg0),
+                                           useFixed(ins->object(), CallTempReg1),
+                                           tempFixed(CallTempReg2));
     lir->setMir(ins);
     return add(lir, ins);
 }
diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
index c24dfca0d918b32dde720e9086e1846af74352e9..2e7869d505b5d1b0308cb88b051165cd0c5b9ae2 100644
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -159,7 +159,7 @@ class LIRGenerator : public LIRGeneratorSpecific
     bool visitLoadSlot(MLoadSlot *ins);
     bool visitFunctionEnvironment(MFunctionEnvironment *ins);
     bool visitForkJoinSlice(MForkJoinSlice *ins);
-    bool visitGuardThreadLocalObject(MGuardThreadLocalObject *ins);
+    bool visitGuardThreadExclusive(MGuardThreadExclusive *ins);
     bool visitInterruptCheck(MInterruptCheck *ins);
     bool visitCheckInterruptPar(MCheckInterruptPar *ins);
     bool visitStoreSlot(MStoreSlot *ins);
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 97f3c5991e76b727a206799bfc3dd9297cb6e280..ce6bf27878720b2f6df2dce2da906fac54c8b5b4 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -8579,24 +8579,24 @@ class MRestPar
     }
 };
 
-// Guard on an object being allocated in the current slice.
-class MGuardThreadLocalObject
+// Guard on an object being safe for writes by current parallel slice.
+// Must be either thread-local or else a handle into the destination array.
+class MGuardThreadExclusive
   : public MBinaryInstruction,
     public ObjectPolicy<1>
 {
-    MGuardThreadLocalObject(MDefinition *slice, MDefinition *obj)
+    MGuardThreadExclusive(MDefinition *slice, MDefinition *obj)
       : MBinaryInstruction(slice, obj)
     {
         setResultType(MIRType_None);
         setGuard();
-        setMovable();
     }
 
   public:
-    INSTRUCTION_HEADER(GuardThreadLocalObject);
+    INSTRUCTION_HEADER(GuardThreadExclusive);
 
-    static MGuardThreadLocalObject *New(TempAllocator &alloc, MDefinition *slice, MDefinition *obj) {
-        return new(alloc) MGuardThreadLocalObject(slice, obj);
+    static MGuardThreadExclusive *New(TempAllocator &alloc, MDefinition *slice, MDefinition *obj) {
+        return new(alloc) MGuardThreadExclusive(slice, obj);
     }
     MDefinition *forkJoinSlice() const {
         return getOperand(0);
diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h
index 982e64595985cea78785ba1d9ef0ce926960aff0..dcdf4bb892ba465eca260a20621ae656bf1f69b7 100644
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -209,7 +209,7 @@ namespace jit {
     _(LambdaPar)                                                            \
     _(RestPar)                                                              \
     _(ForkJoinSlice)                                                        \
-    _(GuardThreadLocalObject)                                               \
+    _(GuardThreadExclusive)                                                 \
     _(CheckInterruptPar)                                                    \
     _(RecompileCheck)
 
diff --git a/js/src/jit/ParallelFunctions.cpp b/js/src/jit/ParallelFunctions.cpp
index b0823d255f5d41541e33128b9746d0d702cf7173..39503041824f6acc4194b3ecf2350d78859d09f2 100644
--- a/js/src/jit/ParallelFunctions.cpp
+++ b/js/src/jit/ParallelFunctions.cpp
@@ -6,6 +6,7 @@
 
 #include "jit/ParallelFunctions.h"
 
+#include "builtin/TypedObject.h"
 #include "vm/ArrayObject.h"
 
 #include "jsgcinlines.h"
@@ -37,15 +38,86 @@ jit::NewGCThingPar(ForkJoinSlice *slice, gc::AllocKind allocKind)
     return gc::NewGCThing<JSObject, NoGC>(slice, allocKind, thingSize, gc::DefaultHeap);
 }
 
-// Check that the object was created by the current thread
-// (and hence is writable).
 bool
-jit::IsThreadLocalObject(ForkJoinSlice *slice, JSObject *object)
+jit::ParallelWriteGuard(ForkJoinSlice *slice, JSObject *object)
 {
+    // Implements the most general form of the write guard, which is
+    // suitable for writes to any object O. There are two cases to
+    // consider and test for:
+    //
+    // 1. Writes to thread-local memory are safe. Thread-local memory
+    //    is defined as memory allocated by the current thread.
+    //    The definition of the PJS API guarantees that such memory
+    //    cannot have escaped to other parallel threads.
+    //
+    // 2. Writes into the output buffer are safe. Some PJS operations
+    //    supply an out pointer into the final target buffer. The design
+    //    of the API ensures that this out pointer is always pointing
+    //    at a fresh region of the buffer that is not accessible to
+    //    other threads. Thus, even though this output buffer has not
+    //    been created by the current thread, it is writable.
+    //
+    // There are some subtleties to consider:
+    //
+    // A. Typed objects and typed arrays are just views onto a base buffer.
+    //    For the purposes of guarding parallel writes, it is not important
+    //    whether the *view* is thread-local -- what matters is whether
+    //    the *underlying buffer* is thread-local.
+    //
+    // B. With regard to the output buffer, we have to be careful
+    //    because of the potential for sequential iterations to be
+    //    intermingled with parallel ones. During a sequential
+    //    iteration, the out pointer could escape into global
+    //    variables and so forth, and thus be used during later
+    //    parallel operations. However, those out pointers must be
+    //    pointing to distinct regions of the final output buffer than
+    //    the ones that are currently being written, so there is no
+    //    harm done in letting them be read (but not written).
+    //
+    //    In order to be able to distinguish escaped out pointers from
+    //    prior iterations and the proper out pointers from the
+    //    current iteration, we always track a *target memory region*
+    //    (which is a span of bytes within the output buffer) and not
+    //    just the output buffer itself.
+
     JS_ASSERT(ForkJoinSlice::current() == slice);
+
+    if (IsTypedDatum(*object)) {
+        TypedDatum &datum = AsTypedDatum(*object);
+
+        // Note: check target region based on `datum`, not the owner.
+        // This is because `datum` may point to some subregion of the
+        // owner and we only care if that *subregion* is within the
+        // target region, not the entire owner.
+        if (IsInTargetRegion(slice, &datum))
+            return true;
+
+        // Also check whether owner is thread-local.
+        TypedDatum *owner = datum.owner();
+        return owner && slice->isThreadLocal(owner);
+    }
+
+    // For other kinds of writable objects, must be thread-local.
     return slice->isThreadLocal(object);
 }
 
+// Check that |object| (which must be a typed datum) maps
+// to memory in the target region.
+//
+// For efficiency, we assume that all handles which the user has
+// access to are either entirely within the target region or entirely
+// without, but not straddling the target region nor encompassing
+// it. This invariant is maintained by the PJS APIs, where the target
+// region and handles are always elements of the same output array.
+bool
+jit::IsInTargetRegion(ForkJoinSlice *slice, TypedDatum *datum)
+{
+    JS_ASSERT(IsTypedDatum(*datum)); // in case JIT supplies something bogus
+    uint8_t *typedMem = datum->typedMem();
+    return (typedMem >= slice->targetRegionStart &&
+            typedMem <  slice->targetRegionEnd);
+}
+
 #ifdef DEBUG
 static void
 printTrace(const char *prefix, struct IonLIRTraceData *cached)
diff --git a/js/src/jit/ParallelFunctions.h b/js/src/jit/ParallelFunctions.h
index a6747feb6cef7701587c7d907654f808d666e2d8..e8e7c6d22ddf418e029bad57533deab777e18845 100644
--- a/js/src/jit/ParallelFunctions.h
+++ b/js/src/jit/ParallelFunctions.h
@@ -11,11 +11,15 @@
 #include "vm/ForkJoin.h"
 
 namespace js {
+
+class TypedDatum; // subclass of JSObject* defined in builtin/TypedObject.h
+
 namespace jit {
 
 ForkJoinSlice *ForkJoinSlicePar();
 JSObject *NewGCThingPar(ForkJoinSlice *slice, gc::AllocKind allocKind);
-bool IsThreadLocalObject(ForkJoinSlice *slice, JSObject *object);
+bool ParallelWriteGuard(ForkJoinSlice *slice, JSObject *object);
+bool IsInTargetRegion(ForkJoinSlice *slice, TypedDatum *object);
 bool CheckOverRecursedPar(ForkJoinSlice *slice);
 bool CheckInterruptPar(ForkJoinSlice *slice);
 
diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp
index 2b3d8438de924888fb5a8e28eb79a9a6d9d28dd1..4faf86c993e82c9df65729fd7554fadd22a341e5 100644
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -143,7 +143,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
     UNSAFE_OP(FilterArgumentsOrEval)
     UNSAFE_OP(CallDirectEval)
     SAFE_OP(BitNot)
-    UNSAFE_OP(TypeOf)
+    SAFE_OP(TypeOf)
     UNSAFE_OP(ToId)
     SAFE_OP(BitAnd)
     SAFE_OP(BitOr)
@@ -287,7 +287,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
     UNSAFE_OP(NewDeclEnvObject)
     UNSAFE_OP(In)
     UNSAFE_OP(InArray)
-    SAFE_OP(GuardThreadLocalObject)
+    SAFE_OP(GuardThreadExclusive)
     SAFE_OP(CheckInterruptPar)
     SAFE_OP(CheckOverRecursedPar)
     SAFE_OP(FunctionDispatch)
@@ -656,6 +656,10 @@ ParallelSafetyVisitor::insertWriteGuard(MInstruction *writeInstruction,
             object = valueBeingWritten->toTypedArrayElements()->object();
             break;
 
+          case MDefinition::Op_TypedObjectElements:
+            object = valueBeingWritten->toTypedObjectElements()->object();
+            break;
+
           default:
             SpewMIR(writeInstruction, "cannot insert write guard for %s",
                     valueBeingWritten->opName());
@@ -682,8 +686,8 @@ ParallelSafetyVisitor::insertWriteGuard(MInstruction *writeInstruction,
     }
 
     MBasicBlock *block = writeInstruction->block();
-    MGuardThreadLocalObject *writeGuard =
-        MGuardThreadLocalObject::New(alloc(), forkJoinSlice(), object);
+    MGuardThreadExclusive *writeGuard =
+        MGuardThreadExclusive::New(alloc(), forkJoinSlice(), object);
     block->insertBefore(writeInstruction, writeGuard);
     writeGuard->adjustInputs(alloc(), writeGuard);
     return true;
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 0adef45a61e244183d7f1068f1633cf2a531303a..732de94bf002827e65f7b29a515460faaa4c18c2 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -228,7 +228,8 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
         }
         if (sp == argv + argc) {
             if (required) {
-                if (JSFunction *fun = ReportIfNotFunction(cx, argv[-2])) {
+                HandleValue callee = HandleValue::fromMarkedLocation(&argv[-2]);
+                if (JSFunction *fun = ReportIfNotFunction(cx, callee)) {
                     char numBuf[12];
                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
                     JSAutoByteString funNameBytes;
@@ -298,7 +299,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
             *va_arg(ap, JSObject **) = obj;
             break;
           case 'f':
-            obj = ReportIfNotFunction(cx, *sp);
+              obj = ReportIfNotFunction(cx, HandleValue::fromMarkedLocation(sp));
             if (!obj)
                 return false;
             *sp = OBJECT_TO_JSVAL(obj);
@@ -3985,7 +3986,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSObject *parentArg)
 
     if (!funobj->is<JSFunction>()) {
         AutoCompartment ac(cx, funobj);
-        ReportIsNotFunction(cx, ObjectValue(*funobj));
+        RootedValue v(cx, ObjectValue(*funobj));
+        ReportIsNotFunction(cx, v);
         return nullptr;
     }
 
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 0173cea004d0a4538997099aab571dc665a82136..a792507bc04881ddf4844833be16d2f47171dbe6 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -82,9 +82,9 @@ class JS_PUBLIC_API(AutoCheckRequestDepth)
  * Also check that GC would be safe at this point.
  */
 JS_PUBLIC_API(void)
-AssertArgumentsAreSane(JSContext *cx, JS::Handle<JS::Value> v);
+AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v);
 #else
-inline void AssertArgumentsAreSane(JSContext *cx, JS::Handle<JS::Value> v) {
+inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) {
     /* Do nothing */
 }
 #endif /* JS_DEBUG */
@@ -205,15 +205,15 @@ class AutoArrayRooter : private AutoGCRooter {
 
     Value *array;
 
-    MutableHandle<Value> handleAt(size_t i)
+    MutableHandleValue handleAt(size_t i)
     {
         JS_ASSERT(i < size_t(tag_));
-        return MutableHandle<Value>::fromMarkedLocation(&array[i]);
+        return MutableHandleValue::fromMarkedLocation(&array[i]);
     }
-    Handle<Value> handleAt(size_t i) const
+    HandleValue handleAt(size_t i) const
     {
         JS_ASSERT(i < size_t(tag_));
-        return Handle<Value>::fromMarkedLocation(&array[i]);
+        return HandleValue::fromMarkedLocation(&array[i]);
     }
 
     friend void AutoGCRooter::trace(JSTracer *trc);
@@ -777,19 +777,17 @@ typedef const JSErrorFormatString *
                     const unsigned errorNumber);
 
 typedef bool
-(* JSLocaleToUpperCase)(JSContext *cx, JS::Handle<JSString*> src,
-                        JS::MutableHandle<JS::Value> rval);
+(* JSLocaleToUpperCase)(JSContext *cx, JS::HandleString src, JS::MutableHandleValue rval);
 
 typedef bool
-(* JSLocaleToLowerCase)(JSContext *cx, JS::Handle<JSString*> src,
-                        JS::MutableHandle<JS::Value> rval);
+(* JSLocaleToLowerCase)(JSContext *cx, JS::HandleString src, JS::MutableHandleValue rval);
 
 typedef bool
-(* JSLocaleCompare)(JSContext *cx, JS::Handle<JSString*> src1, JS::Handle<JSString*> src2,
-                    JS::MutableHandle<JS::Value> rval);
+(* JSLocaleCompare)(JSContext *cx, JS::HandleString src1, JS::HandleString src2,
+                    JS::MutableHandleValue rval);
 
 typedef bool
-(* JSLocaleToUnicode)(JSContext *cx, const char *src, JS::MutableHandle<JS::Value> rval);
+(* JSLocaleToUnicode)(JSContext *cx, const char *src, JS::MutableHandleValue rval);
 
 /*
  * Security protocol types.
@@ -815,8 +813,8 @@ typedef bool
  * guaranteed not to wrap a function.
  */
 typedef JSObject *
-(* JSWrapObjectCallback)(JSContext *cx, JS::Handle<JSObject*> existing, JS::Handle<JSObject*> obj,
-                         JS::Handle<JSObject*> proto, JS::Handle<JSObject*> parent,
+(* JSWrapObjectCallback)(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj,
+                         JS::HandleObject proto, JS::HandleObject parent,
                          unsigned flags);
 
 /*
@@ -825,7 +823,7 @@ typedef JSObject *
  * or even finding a more suitable object for the new compartment.
  */
 typedef JSObject *
-(* JSPreWrapCallback)(JSContext *cx, JS::Handle<JSObject*> scope, JS::Handle<JSObject*> obj,
+(* JSPreWrapCallback)(JSContext *cx, JS::HandleObject scope, JS::HandleObject obj,
                       unsigned flags);
 
 /*
@@ -839,7 +837,7 @@ typedef JSObject *
  * compartment wrapper that gets passed to wrap.
  */
 typedef JSObject *
-(* JSSameCompartmentWrapObjectCallback)(JSContext *cx, JS::Handle<JSObject*> obj);
+(* JSSameCompartmentWrapObjectCallback)(JSContext *cx, JS::HandleObject obj);
 
 struct JSWrapObjectCallbacks
 {
@@ -1079,7 +1077,7 @@ namespace JS {
 
 /* ES5 9.3 ToNumber. */
 JS_ALWAYS_INLINE bool
-ToNumber(JSContext *cx, Handle<Value> v, double *out)
+ToNumber(JSContext *cx, HandleValue v, double *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
@@ -1135,29 +1133,29 @@ JS_DoubleToUint32(double d);
 namespace js {
 /* DO NOT CALL THIS. Use JS::ToUint16. */
 extern JS_PUBLIC_API(bool)
-ToUint16Slow(JSContext *cx, JS::Handle<JS::Value> v, uint16_t *out);
+ToUint16Slow(JSContext *cx, JS::HandleValue v, uint16_t *out);
 
 /* DO NOT CALL THIS. Use JS::ToInt32. */
 extern JS_PUBLIC_API(bool)
-ToInt32Slow(JSContext *cx, JS::Handle<JS::Value> v, int32_t *out);
+ToInt32Slow(JSContext *cx, JS::HandleValue v, int32_t *out);
 
 /* DO NOT CALL THIS. Use JS::ToUint32. */
 extern JS_PUBLIC_API(bool)
-ToUint32Slow(JSContext *cx, JS::Handle<JS::Value> v, uint32_t *out);
+ToUint32Slow(JSContext *cx, JS::HandleValue v, uint32_t *out);
 
 /* DO NOT CALL THIS. Use JS::ToInt64. */
 extern JS_PUBLIC_API(bool)
-ToInt64Slow(JSContext *cx, JS::Handle<JS::Value> v, int64_t *out);
+ToInt64Slow(JSContext *cx, JS::HandleValue v, int64_t *out);
 
 /* DO NOT CALL THIS. Use JS::ToUint64. */
 extern JS_PUBLIC_API(bool)
-ToUint64Slow(JSContext *cx, JS::Handle<JS::Value> v, uint64_t *out);
+ToUint64Slow(JSContext *cx, JS::HandleValue v, uint64_t *out);
 } /* namespace js */
 
 namespace JS {
 
 JS_ALWAYS_INLINE bool
-ToUint16(JSContext *cx, JS::Handle<JS::Value> v, uint16_t *out)
+ToUint16(JSContext *cx, JS::HandleValue v, uint16_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     js::MaybeCheckStackRoots(cx);
@@ -1170,7 +1168,7 @@ ToUint16(JSContext *cx, JS::Handle<JS::Value> v, uint16_t *out)
 }
 
 JS_ALWAYS_INLINE bool
-ToInt32(JSContext *cx, JS::Handle<JS::Value> v, int32_t *out)
+ToInt32(JSContext *cx, JS::HandleValue v, int32_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     js::MaybeCheckStackRoots(cx);
@@ -1183,7 +1181,7 @@ ToInt32(JSContext *cx, JS::Handle<JS::Value> v, int32_t *out)
 }
 
 JS_ALWAYS_INLINE bool
-ToUint32(JSContext *cx, JS::Handle<JS::Value> v, uint32_t *out)
+ToUint32(JSContext *cx, JS::HandleValue v, uint32_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     js::MaybeCheckStackRoots(cx);
@@ -1196,7 +1194,7 @@ ToUint32(JSContext *cx, JS::Handle<JS::Value> v, uint32_t *out)
 }
 
 JS_ALWAYS_INLINE bool
-ToInt64(JSContext *cx, JS::Handle<JS::Value> v, int64_t *out)
+ToInt64(JSContext *cx, JS::HandleValue v, int64_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     js::MaybeCheckStackRoots(cx);
@@ -1210,7 +1208,7 @@ ToInt64(JSContext *cx, JS::Handle<JS::Value> v, int64_t *out)
 }
 
 JS_ALWAYS_INLINE bool
-ToUint64(JSContext *cx, JS::Handle<JS::Value> v, uint64_t *out)
+ToUint64(JSContext *cx, JS::HandleValue v, uint64_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     js::MaybeCheckStackRoots(cx);
@@ -1669,7 +1667,7 @@ extern JS_PUBLIC_API(bool)
 JS_WrapId(JSContext *cx, jsid *idp);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_TransplantObject(JSContext *cx, JS::Handle<JSObject*> origobj, JS::Handle<JSObject*> target);
+JS_TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject target);
 
 extern JS_PUBLIC_API(bool)
 JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *ob);
@@ -1761,11 +1759,11 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj);
  * loops any classes not yet resolved lazily.
  */
 extern JS_PUBLIC_API(bool)
-JS_ResolveStandardClass(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+JS_ResolveStandardClass(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                         bool *resolved);
 
 extern JS_PUBLIC_API(bool)
-JS_EnumerateStandardClasses(JSContext *cx, JS::Handle<JSObject*> obj);
+JS_EnumerateStandardClasses(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(bool)
 JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp);
@@ -2333,26 +2331,26 @@ extern JS_PUBLIC_API(bool)
 JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
 
 extern JS_PUBLIC_API(bool)
-JS_PropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
-                JS::MutableHandle<JS::Value> vp);
+JS_PropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
+                JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_StrictPropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
-                      JS::MutableHandle<JS::Value> vp);
+JS_StrictPropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict,
+                      JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_DeletePropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+JS_DeletePropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                       bool *succeeded);
 
 extern JS_PUBLIC_API(bool)
-JS_EnumerateStub(JSContext *cx, JS::Handle<JSObject*> obj);
+JS_EnumerateStub(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(bool)
-JS_ResolveStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id);
+JS_ResolveStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 
 extern JS_PUBLIC_API(bool)
-JS_ConvertStub(JSContext *cx, JS::Handle<JSObject*> obj, JSType type,
-               JS::MutableHandle<JS::Value> vp);
+JS_ConvertStub(JSContext *cx, JS::HandleObject obj, JSType type,
+               JS::MutableHandleValue vp);
 
 struct JSConstDoubleSpec {
     double          dval;
@@ -2550,10 +2548,10 @@ JS_GetInstancePrivate(JSContext *cx, JSObject *obj, const JSClass *clasp,
                       jsval *argv);
 
 extern JS_PUBLIC_API(bool)
-JS_GetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> protop);
+JS_GetPrototype(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject protop);
 
 extern JS_PUBLIC_API(bool)
-JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*> proto);
+JS_SetPrototype(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetParent(JSObject *obj);
@@ -2725,7 +2723,7 @@ JS_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *par
 
 /* Queries the [[Extensible]] property of the object. */
 extern JS_PUBLIC_API(bool)
-JS_IsExtensible(JSContext *cx, JS::Handle<JSObject*> obj, bool *extensible);
+JS_IsExtensible(JSContext *cx, JS::HandleObject obj, bool *extensible);
 
 extern JS_PUBLIC_API(bool)
 JS_IsNative(JSObject *obj);
@@ -2756,7 +2754,7 @@ extern JS_PUBLIC_API(bool)
 JS_FreezeObject(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(bool)
-JS_PreventExtensions(JSContext *cx, JS::Handle<JSObject*> obj);
+JS_PreventExtensions(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv);
@@ -2803,18 +2801,18 @@ extern JS_PUBLIC_API(bool)
 JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, bool *foundp);
 
 extern JS_PUBLIC_API(bool)
-JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandle<JS::Value> vp);
+JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandle<JS::Value> vp);
+JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
-                           unsigned flags, JS::MutableHandle<JS::Value> vp);
+                           unsigned flags, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
-                               unsigned flags, JSObject **objp, JS::MutableHandle<JS::Value> vp);
+                               unsigned flags, JSObject **objp, JS::MutableHandleValue vp);
 
 struct JSPropertyDescriptor {
     JSObject           *obj;
@@ -2851,25 +2849,25 @@ class PropertyDescriptorOperations
     bool hasShortId() const { return desc()->attrs & JSPROP_SHORTID; }
     bool hasAttributes(unsigned attrs) const { return desc()->attrs & attrs; }
 
-    JS::Handle<JSObject*> object() const {
-        return JS::Handle<JSObject*>::fromMarkedLocation(&desc()->obj);
+    JS::HandleObject object() const {
+        return JS::HandleObject::fromMarkedLocation(&desc()->obj);
     }
     unsigned attributes() const { return desc()->attrs; }
     unsigned shortid() const { return desc()->shortid; }
     JSPropertyOp getter() const { return desc()->getter; }
     JSStrictPropertyOp setter() const { return desc()->setter; }
-    JS::Handle<JSObject*> getterObject() const {
+    JS::HandleObject getterObject() const {
         MOZ_ASSERT(hasGetterObject());
-        return JS::Handle<JSObject*>::fromMarkedLocation(
+        return JS::HandleObject::fromMarkedLocation(
                 reinterpret_cast<JSObject *const *>(&desc()->getter));
     }
-    JS::Handle<JSObject*> setterObject() const {
+    JS::HandleObject setterObject() const {
         MOZ_ASSERT(hasSetterObject());
-        return JS::Handle<JSObject*>::fromMarkedLocation(
+        return JS::HandleObject::fromMarkedLocation(
                 reinterpret_cast<JSObject *const *>(&desc()->setter));
     }
-    JS::Handle<Value> value() const {
-        return JS::Handle<Value>::fromMarkedLocation(&desc()->value);
+    JS::HandleValue value() const {
+        return JS::HandleValue::fromMarkedLocation(&desc()->value);
     }
 };
 
@@ -2889,14 +2887,14 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
         value().setUndefined();
     }
 
-    JS::MutableHandle<JSObject*> object() {
-        return JS::MutableHandle<JSObject*>::fromMarkedLocation(&desc()->obj);
+    JS::MutableHandleObject object() {
+        return JS::MutableHandleObject::fromMarkedLocation(&desc()->obj);
     }
     unsigned &attributesRef() { return desc()->attrs; }
     JSPropertyOp &getter() { return desc()->getter; }
     JSStrictPropertyOp &setter() { return desc()->setter; }
-    JS::MutableHandle<Value> value() {
-        return JS::MutableHandle<Value>::fromMarkedLocation(&desc()->value);
+    JS::MutableHandleValue value() {
+        return JS::MutableHandleValue::fromMarkedLocation(&desc()->value);
     }
 
     void setEnumerable() { desc()->attrs |= JSPROP_ENUMERATE; }
@@ -2987,20 +2985,20 @@ JS_GetPropertyDescriptor(JSContext *cx, JSObject *obj, const char *name, unsigne
                          JS::MutableHandle<JSPropertyDescriptor> desc);
 
 extern JS_PUBLIC_API(bool)
-JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandle<JS::Value> vp);
+JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandle<JS::Value> vp);
+JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id, JSObject *onBehalfOf,
-                        JS::MutableHandle<JS::Value> vp);
+                        JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, JS::Handle<JS::Value> v);
+JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, JS::HandleValue v);
 
 extern JS_PUBLIC_API(bool)
-JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::Handle<JS::Value> v);
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::HandleValue v);
 
 extern JS_PUBLIC_API(bool)
 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
@@ -3039,17 +3037,17 @@ JS_HasUCProperty(JSContext *cx, JSObject *obj,
 extern JS_PUBLIC_API(bool)
 JS_LookupUCProperty(JSContext *cx, JSObject *obj,
                     const jschar *name, size_t namelen,
-                    JS::MutableHandle<JS::Value> vp);
+                    JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_GetUCProperty(JSContext *cx, JSObject *obj,
                  const jschar *name, size_t namelen,
-                 JS::MutableHandle<JS::Value> vp);
+                 JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_SetUCProperty(JSContext *cx, JSObject *obj,
                  const jschar *name, size_t namelen,
-                 JS::Handle<JS::Value> v);
+                 JS::HandleValue v);
 
 extern JS_PUBLIC_API(bool)
 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
@@ -3078,17 +3076,17 @@ extern JS_PUBLIC_API(bool)
 JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, bool *foundp);
 
 extern JS_PUBLIC_API(bool)
-JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandle<JS::Value> vp);
+JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandle<JS::Value> vp);
+JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf,
-                       JS::MutableHandle<JS::Value> vp);
+                       JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandle<JS::Value> vp);
+JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index);
@@ -3435,7 +3433,7 @@ namespace JS {
  * is protected anyway); instead, create instances only of the derived classes:
  * CompileOptions and OwningCompileOptions.
  */
-class JS_PUBLIC_API(ReadOnlyCompileOptions)
+class JS_FRIEND_API(ReadOnlyCompileOptions)
 {
   protected:
     JSPrincipals *principals_;
@@ -3522,7 +3520,7 @@ class JS_PUBLIC_API(ReadOnlyCompileOptions)
  * comes to refer to the object that owns this, then the whole cycle, and
  * anything else it entrains, will never be freed.
  */
-class JS_PUBLIC_API(OwningCompileOptions) : public ReadOnlyCompileOptions
+class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
 {
     JSRuntime *runtime;
     PersistentRootedObject elementRoot;
@@ -3583,7 +3581,7 @@ class JS_PUBLIC_API(OwningCompileOptions) : public ReadOnlyCompileOptions
  * create an instance of this type, it's up to you to guarantee that
  * everything you store in it will outlive it.
  */
-class MOZ_STACK_CLASS JS_PUBLIC_API(CompileOptions) : public ReadOnlyCompileOptions
+class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOptions
 {
     RootedObject elementRoot;
     RootedString elementPropertyRoot;
@@ -3633,18 +3631,18 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(CompileOptions) : public ReadOnlyCompileOpti
 };
 
 extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         const jschar *chars, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options, FILE *file);
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file);
 
 extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options, const char *filename);
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename);
 
 extern JS_PUBLIC_API(bool)
 CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options);
@@ -3666,7 +3664,7 @@ CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options);
  */
 
 extern JS_PUBLIC_API(bool)
-CompileOffThread(JSContext *cx, Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+CompileOffThread(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                  const jschar *chars, size_t length,
                  OffThreadCompileCallback callback, void *callbackData);
 
@@ -3674,12 +3672,12 @@ extern JS_PUBLIC_API(JSScript *)
 FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token);
 
 extern JS_PUBLIC_API(JSFunction *)
-CompileFunction(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSFunction *)
-CompileFunction(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const jschar *chars, size_t length);
 
@@ -3805,15 +3803,15 @@ JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
 namespace JS {
 
 extern JS_PUBLIC_API(bool)
-Evaluate(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
          const jschar *chars, size_t length, jsval *rval);
 
 extern JS_PUBLIC_API(bool)
-Evaluate(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
          const char *bytes, size_t length, jsval *rval);
 
 extern JS_PUBLIC_API(bool)
-Evaluate(JSContext *cx, JS::Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
+Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
          const char *filename, jsval *rval);
 
 } /* namespace JS */
@@ -3834,31 +3832,31 @@ namespace JS {
 
 static inline bool
 Call(JSContext *cx, JSObject *thisObj, JSFunction *fun, unsigned argc, jsval *argv,
-     MutableHandle<Value> rval)
+     MutableHandleValue rval)
 {
     return !!JS_CallFunction(cx, thisObj, fun, argc, argv, rval.address());
 }
 
 static inline bool
 Call(JSContext *cx, JSObject *thisObj, const char *name, unsigned argc, jsval *argv,
-     MutableHandle<Value> rval)
+     MutableHandleValue rval)
 {
     return !!JS_CallFunctionName(cx, thisObj, name, argc, argv, rval.address());
 }
 
 static inline bool
 Call(JSContext *cx, JSObject *thisObj, jsval fun, unsigned argc, jsval *argv,
-     MutableHandle<Value> rval)
+     MutableHandleValue rval)
 {
     return !!JS_CallFunctionValue(cx, thisObj, fun, argc, argv, rval.address());
 }
 
 extern JS_PUBLIC_API(bool)
-Call(JSContext *cx, jsval thisv, jsval fun, unsigned argc, jsval *argv, MutableHandle<Value> rval);
+Call(JSContext *cx, jsval thisv, jsval fun, unsigned argc, jsval *argv, MutableHandleValue rval);
 
 static inline bool
 Call(JSContext *cx, jsval thisv, JSObject *funObj, unsigned argc, jsval *argv,
-     MutableHandle<Value> rval)
+     MutableHandleValue rval)
 {
     return Call(cx, thisv, OBJECT_TO_JSVAL(funObj), argc, argv, rval);
 }
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index 6d022a7308719637375d14c33bcd559f4f6ceb7c..29097ce8639199f6800f0ba5f63ac37191efd449 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -1207,7 +1207,7 @@ js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
 }
 
 JS_FRIEND_API(bool)
-js_ReportIsNotFunction(JSContext *cx, const JS::Value& v)
+js_ReportIsNotFunction(JSContext *cx, JS::HandleValue v)
 {
     return ReportIsNotFunction(cx, v);
 }
diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
index 4709b526bf5562fb7dded7f0f3c21c83597bb2d8..a1d0aabe9a0fbc08f17241c96fbabdc96bd3b73b 100644
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -549,7 +549,7 @@ JS_FRIEND_API(void)
 SetFunctionNativeReserved(JSObject *fun, size_t which, const JS::Value &val);
 
 JS_FRIEND_API(bool)
-GetObjectProto(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> proto);
+GetObjectProto(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject proto);
 
 JS_FRIEND_API(bool)
 GetOriginalEval(JSContext *cx, JS::HandleObject scope,
@@ -1360,7 +1360,7 @@ class JSJitGetterCallArgs : protected JS::MutableHandleValue
       : JS::MutableHandleValue(args.rval())
     {}
 
-    explicit JSJitGetterCallArgs(JS::Rooted<JS::Value>* rooted)
+    explicit JSJitGetterCallArgs(JS::RootedValue* rooted)
       : JS::MutableHandleValue(rooted)
     {}
 
@@ -1782,7 +1782,7 @@ js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
                      JS::Handle<JSPropertyDescriptor> descriptor, bool *bp);
 
 extern JS_FRIEND_API(bool)
-js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
+js_ReportIsNotFunction(JSContext *cx, JS::HandleValue v);
 
 #ifdef JSGC_GENERATIONAL
 extern JS_FRIEND_API(void)
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index ce9cb84bdf337aab4c0fa47b4856bdfd6f7a3e8b..49032d0b4caf5f2b20002e4f0c369b02377d36b1 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1305,7 +1305,8 @@ js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
          * So before anything else, if we are an arrow function, make sure we
          * don't even get here. You never saw me. Burn this comment.
          */
-        return ReportIsNotFunction(cx, ObjectValue(*fun), -1, CONSTRUCT);
+        RootedValue v(cx, ObjectValue(*fun));
+        return ReportIsNotFunction(cx, v, -1, CONSTRUCT);
     }
 
     /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp
index 1c5a2924efac2cc9f6743715286b59c29b7495a4..5281ac9b9e531dc28d9c1d50967da44f146894f5 100644
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -290,7 +290,8 @@ BaseProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned inden
 {
     if (proxy->isCallable())
         return JS_NewStringCopyZ(cx, "function () {\n    [native code]\n}");
-    ReportIsNotFunction(cx, ObjectValue(*proxy));
+    RootedValue v(cx, ObjectValue(*proxy));
+    ReportIsNotFunction(cx, v);
     return nullptr;
 }
 
@@ -3300,27 +3301,28 @@ proxy_create(JSContext *cx, unsigned argc, Value *vp)
 static bool
 proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
 {
-    if (argc < 2) {
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (args.length() < 2) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "createFunction", "1", "");
         return false;
     }
-    RootedObject handler(cx, NonNullObject(cx, vp[2]));
+    RootedObject handler(cx, NonNullObject(cx, args[0]));
     if (!handler)
         return false;
     RootedObject proto(cx), parent(cx);
-    parent = vp[0].toObject().getParent();
+    parent = args.callee().getParent();
     proto = parent->global().getOrCreateFunctionPrototype(cx);
     if (!proto)
         return false;
     parent = proto->getParent();
 
-    RootedObject call(cx, ValueToCallable(cx, vp[3], argc - 2));
+    RootedObject call(cx, ValueToCallable(cx, args[1], args.length() - 2));
     if (!call)
         return false;
     RootedObject construct(cx, nullptr);
-    if (argc > 2) {
-        construct = ValueToCallable(cx, vp[4], argc - 3);
+    if (args.length() > 2) {
+        construct = ValueToCallable(cx, args[2], args.length() - 3);
         if (!construct)
             return false;
     } else {
diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h
index adf643e9ff320381f7d5d4eda440ff02db438be4..852ef0c1afdd4408195bdf6c1d265530c842d347 100644
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -34,9 +34,9 @@ class Rooted;
 
 class JS_PUBLIC_API(AutoGCRooter);
 
-class JS_PUBLIC_API(CompileOptions);
-class JS_PUBLIC_API(ReadOnlyCompileOptions);
-class JS_PUBLIC_API(OwningCompileOptions);
+class JS_FRIEND_API(CompileOptions);
+class JS_FRIEND_API(ReadOnlyCompileOptions);
+class JS_FRIEND_API(OwningCompileOptions);
 class JS_PUBLIC_API(CompartmentOptions);
 
 struct Zone;
diff --git a/js/src/jstypes.h b/js/src/jstypes.h
index d5b15ccb1d3c87b5fe529bd21afe2e5af7051156..5ad1b5482b5989aee45a22c4a7908640de828380 100644
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -77,8 +77,13 @@
 #  define JS_PUBLIC_DATA(t)  MOZ_IMPORT_DATA t
 #endif
 
-#define JS_FRIEND_API(t)    JS_PUBLIC_API(t)
-#define JS_FRIEND_DATA(t)   JS_PUBLIC_DATA(t)
+#if defined(STATIC_JS_API) || defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
+#  define JS_FRIEND_API(t)    MOZ_EXPORT t
+#  define JS_FRIEND_DATA(t)   MOZ_EXPORT t
+#else
+#  define JS_FRIEND_API(t)   MOZ_IMPORT_API t
+#  define JS_FRIEND_DATA(t)  MOZ_IMPORT_DATA t
+#endif
 
 #if defined(_MSC_VER) && defined(_M_IX86)
 #define JS_FASTCALL __fastcall
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
index 9b13ac78090c4b1cf55b8eae6bf482683343298a..1f3ae935b8bcb458b2d99f46da9353521d948803 100644
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3428,16 +3428,17 @@ DebuggerScript_getLineOffsets(JSContext *cx, unsigned argc, Value *vp)
     REQUIRE_ARGC("Debugger.Script.getLineOffsets", 1);
 
     /* Parse lineno argument. */
+    RootedValue linenoValue(cx, args[0]);
     size_t lineno;
-    bool ok = false;
-    if (args[0].isNumber()) {
-        double d = args[0].toNumber();
-        lineno = size_t(d);
-        ok = (lineno == d);
-    }
-    if (!ok) {
-        JS_ReportErrorNumber(cx,  js_GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_LINE);
+    if (!ToNumber(cx, &linenoValue))
         return false;
+    {
+        double d = linenoValue.toNumber();
+        lineno = size_t(d);
+        if (lineno != d) {
+            JS_ReportErrorNumber(cx,  js_GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_LINE);
+            return false;
+        }
     }
 
     /*
diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp
index bd5ba72ebe050b9f25fd536ef8d899ca869a1004..29748c2d58c816269ad576a36c840fa9232376d7 100644
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -18,6 +18,8 @@
 #include "jslock.h"
 #include "jsprf.h"
 
+#include "builtin/TypedObject.h"
+
 #ifdef JS_THREADSAFE
 # include "jit/BaselineJIT.h"
 # include "vm/Monitor.h"
@@ -1582,6 +1584,8 @@ ForkJoinSlice::ForkJoinSlice(PerThreadData *perThreadData,
     sliceId(sliceId),
     workerId(workerId),
     bailoutRecord(bailoutRecord),
+    targetRegionStart(nullptr),
+    targetRegionEnd(nullptr),
     shared(shared),
     acquiredContext_(false),
     nogc_(shared->runtime())
@@ -2103,4 +2107,46 @@ js::ParallelTestsShouldPass(JSContext *cx)
            cx->runtime()->gcZeal() == 0;
 }
 
+bool
+js::intrinsic_SetForkJoinTargetRegion(JSContext *cx, unsigned argc, Value *vp)
+{
+    // This version of SetForkJoinTargetRegion is called during
+    // sequential execution. It is a no-op. The parallel version
+    // is intrinsic_SetForkJoinTargetRegionPar(), below.
+    return true;
+}
+
+static bool
+intrinsic_SetForkJoinTargetRegionPar(ForkJoinSlice *slice, unsigned argc, Value *vp)
+{
+    // Sets the *target region*, which is the portion of the output
+    // buffer that the current iteration is permitted to write to.
+    //
+    // Note: it is important that the target region should be an
+    // entire element (or several elements) of the output array and
+    // not some region that spans from the middle of one element into
+    // the middle of another. This is because the guarding code
+    // assumes that handles, which never straddle across elements,
+    // will either be contained entirely within the target region or
+    // be contained entirely without of the region, and not straddling
+    // the region nor encompassing it.
+
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JS_ASSERT(argc == 3);
+    JS_ASSERT(args[0].isObject() && IsTypedDatum(args[0].toObject()));
+    JS_ASSERT(args[1].isInt32());
+    JS_ASSERT(args[2].isInt32());
+
+    uint8_t *mem = AsTypedDatum(args[0].toObject()).typedMem();
+    int32_t start = args[1].toInt32();
+    int32_t end = args[2].toInt32();
+
+    slice->targetRegionStart = mem + start;
+    slice->targetRegionEnd = mem + end;
+    return true;
+}
+
+const JSJitInfo js::intrinsic_SetForkJoinTargetRegionInfo =
+    JS_JITINFO_NATIVE_PARALLEL(intrinsic_SetForkJoinTargetRegionPar);
+
 #endif // JS_THREADSAFE && JS_ION
diff --git a/js/src/vm/ForkJoin.h b/js/src/vm/ForkJoin.h
index 68f1e2ea4ac77b7c62119f563c19b733bf984d88..515dfa72c9c265dd12c66da9ddc98aa6c316f255 100644
--- a/js/src/vm/ForkJoin.h
+++ b/js/src/vm/ForkJoin.h
@@ -319,6 +319,23 @@ class ForkJoinSlice : public ThreadSafeContext
     uint32_t maxWorkerId;
 #endif
 
+    // When we run a par operation like mapPar, we create an out pointer
+    // into a specific region of the destination buffer. Even though the
+    // destination buffer is not thread-local, it is permissible to write into
+    // it via the handles provided. These two fields identify the memory
+    // region where writes are allowed so that the write guards can test for
+    // it.
+    //
+    // Note: we only permit writes into the *specific region* that the user
+    // is supposed to write. Normally, they only have access to this region
+    // anyhow. But due to sequential fallback it is possible for handles into
+    // other regions to escape into global variables in the sequential
+    // execution and then get accessed by later parallel sections. Thus we
+    // must be careful and ensure that the write is going through a handle
+    // into the correct *region* of the buffer.
+    uint8_t *targetRegionStart;
+    uint8_t *targetRegionEnd;
+
     ForkJoinSlice(PerThreadData *perThreadData, uint16_t sliceId, uint32_t workerId,
                   Allocator *allocator, ForkJoinShared *shared,
                   ParallelBailoutRecord *bailoutRecord);
@@ -433,6 +450,9 @@ bool InExclusiveParallelSection();
 
 bool ParallelTestsShouldPass(JSContext *cx);
 
+bool intrinsic_SetForkJoinTargetRegion(JSContext *cx, unsigned argc, Value *vp);
+extern const JSJitInfo intrinsic_SetForkJoinTargetRegionInfo;
+
 ///////////////////////////////////////////////////////////////////////////
 // Debug Spew
 
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index cefe234bc064d4e4eb8d8a975395b615246506ca..4032b5bd79018ecce7478bff37b11ae6b875b5ff 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -637,7 +637,7 @@ UrshOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *out)
 #undef RELATIONAL_OP
 
 inline JSFunction *
-ReportIfNotFunction(JSContext *cx, const Value &v, MaybeConstruct construct = NO_CONSTRUCT)
+ReportIfNotFunction(JSContext *cx, HandleValue v, MaybeConstruct construct = NO_CONSTRUCT)
 {
     if (v.isObject() && v.toObject().is<JSFunction>())
         return &v.toObject().as<JSFunction>();
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 99e9f003b0bd316abcafa00c76385fbc496f6e11..33f794576dd6ddcc8a14a1665de651844e5118d8 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -344,18 +344,17 @@ SetPropertyOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleV
 }
 
 bool
-js::ReportIsNotFunction(JSContext *cx, const Value &v, int numToSkip, MaybeConstruct construct)
+js::ReportIsNotFunction(JSContext *cx, HandleValue v, int numToSkip, MaybeConstruct construct)
 {
     unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION;
     int spIndex = numToSkip >= 0 ? -(numToSkip + 1) : JSDVG_SEARCH_STACK;
 
-    RootedValue val(cx, v);
-    js_ReportValueError3(cx, error, spIndex, val, NullPtr(), nullptr, nullptr);
+    js_ReportValueError3(cx, error, spIndex, v, NullPtr(), nullptr, nullptr);
     return false;
 }
 
 JSObject *
-js::ValueToCallable(JSContext *cx, const Value &v, int numToSkip, MaybeConstruct construct)
+js::ValueToCallable(JSContext *cx, HandleValue v, int numToSkip, MaybeConstruct construct)
 {
     if (v.isObject()) {
         JSObject *callable = &v.toObject();
@@ -441,7 +440,7 @@ js::Invoke(JSContext *cx, CallArgs args, MaybeConstruct construct)
     InitialFrameFlags initial = (InitialFrameFlags) construct;
 
     if (args.calleev().isPrimitive())
-        return ReportIsNotFunction(cx, args.calleev().get(), args.length() + 1, construct);
+        return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, construct);
 
     JSObject &callee = args.callee();
     const Class *clasp = callee.getClass();
@@ -454,7 +453,7 @@ js::Invoke(JSContext *cx, CallArgs args, MaybeConstruct construct)
 #endif
         JS_ASSERT_IF(construct, !clasp->construct);
         if (!clasp->call)
-            return ReportIsNotFunction(cx, args.calleev().get(), args.length() + 1, construct);
+            return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, construct);
         return CallJSNative(cx, clasp->call, args);
     }
 
@@ -533,7 +532,7 @@ js::InvokeConstructor(JSContext *cx, CallArgs args)
     args.setThis(MagicValue(JS_IS_CONSTRUCTING));
 
     if (!args.calleev().isObject())
-        return ReportIsNotFunction(cx, args.calleev().get(), args.length() + 1, CONSTRUCT);
+        return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, CONSTRUCT);
 
     JSObject &callee = args.callee();
     if (callee.is<JSFunction>()) {
@@ -545,7 +544,7 @@ js::InvokeConstructor(JSContext *cx, CallArgs args)
         }
 
         if (!fun->isInterpretedConstructor())
-            return ReportIsNotFunction(cx, args.calleev().get(), args.length() + 1, CONSTRUCT);
+            return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, CONSTRUCT);
 
         if (!Invoke(cx, args, CONSTRUCT))
             return false;
@@ -556,7 +555,7 @@ js::InvokeConstructor(JSContext *cx, CallArgs args)
 
     const Class *clasp = callee.getClass();
     if (!clasp->construct)
-        return ReportIsNotFunction(cx, args.calleev().get(), args.length() + 1, CONSTRUCT);
+        return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, CONSTRUCT);
 
     return CallJSNativeConstructor(cx, clasp->construct, args);
 }
diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h
index 4724413eee19fa6e149b8eaca63f9d1c62e10a83..f4b237f0ec7e7d6d22116252864300ec62ae532f 100644
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -108,12 +108,12 @@ enum MaybeConstruct {
  * before it reaches |v|. If it's -1, the decompiler will search the stack.
  */
 extern bool
-ReportIsNotFunction(JSContext *cx, const Value &v, int numToSkip = -1,
+ReportIsNotFunction(JSContext *cx, HandleValue v, int numToSkip = -1,
                     MaybeConstruct construct = NO_CONSTRUCT);
 
 /* See ReportIsNotFunction comment for the meaning of numToSkip. */
 extern JSObject *
-ValueToCallable(JSContext *cx, const Value &vp, int numToSkip = -1,
+ValueToCallable(JSContext *cx, HandleValue v, int numToSkip = -1,
                 MaybeConstruct construct = NO_CONSTRUCT);
 
 /*
diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h
index 31ee699507c1ee0299de4161531aac32d0ef2f51..4d07aad376f70d9c7a67bc131e1fc4d81a4f70f3 100644
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -1607,7 +1607,7 @@ inline void
 ObjectImpl::privateWriteBarrierPre(void **oldval)
 {
 #ifdef JSGC_INCREMENTAL
-    JS::shadow::Zone *shadowZone = this->shadowZone();
+    JS::shadow::Zone *shadowZone = this->shadowZoneFromAnyThread();
     if (shadowZone->needsBarrier()) {
         if (*oldval && getClass()->trace)
             getClass()->trace(shadowZone->barrierTracer(), this->asObjectPtr());
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index 87d876cf5e049dada1e1880cfcc22f731b36e2cd..ad310152ea63a9d9a56469ec8080c5209d8abc87 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -626,6 +626,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
     JS_FN("NewDenseArray",           intrinsic_NewDenseArray,           1,0),
     JS_FN("ShouldForceSequential",   intrinsic_ShouldForceSequential,   0,0),
     JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0),
+    JS_FNINFO("SetForkJoinTargetRegion",
+              intrinsic_SetForkJoinTargetRegion,
+              &intrinsic_SetForkJoinTargetRegionInfo, 2, 0),
 
     // See builtin/TypedObject.h for descriptors of the typedobj functions.
     JS_FN("NewTypedHandle",
diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl
index 755c13e24d979fdbfb2cf78bc62cf4754c4b406e..6f39ceed02eb517d371db028bb2eacac3c5dd0c9 100644
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports
 /**
 * interface of Components.utils
 */
-[scriptable, uuid(ae292d08-cfb0-4862-a2b6-4779e5ef7e72)]
+[scriptable, uuid(1b981569-2b21-4702-a01a-81ffdb5d3d4c)]
 interface nsIXPCComponents_Utils : nsISupports
 {
 
@@ -412,6 +412,13 @@ interface nsIXPCComponents_Utils : nsISupports
     [implicit_jscontext]
     void setWantXrays(in jsval vscope);
 
+    /*
+     * Forces the usage of a privileged |Components| object for a potentially-
+     * unprivileged scope. This will crash if used outside of automation.
+     */
+    [implicit_jscontext]
+    void forcePrivilegedComponentsForScope(in jsval vscope);
+
     /*
      * This seemingly-paradoxical API allows privileged code to explicitly give
      * unprivileged code a reference to its own Components object (whereas it's
@@ -544,17 +551,30 @@ interface nsIXPCComponents_Utils : nsISupports
 };
 
 /**
-* interface of JavaScript's 'Components' object
+* Interface for the 'Components' object.
+*
+* The first interface contains things that are available to non-chrome XBL code
+* that runs in a scope with an nsExpandedPrincipal. The second interface
+* includes members that are only exposed to chrome.
 */
-[scriptable, uuid(4229848f-f49e-40e5-90cc-66968aaf4e1b)]
-interface nsIXPCComponents : nsISupports
+
+[scriptable, uuid(eeeada2f-86c0-4609-b2bf-4bf2351b1ce6)]
+interface nsIXPCComponentsBase : nsISupports
 {
     readonly attribute nsIXPCComponents_Interfaces      interfaces;
     readonly attribute nsIXPCComponents_InterfacesByID  interfacesByID;
+    readonly attribute nsIXPCComponents_Results         results;
+
+    boolean isSuccessCode(in nsresult result);
+
+};
+
+[scriptable, uuid(aa28aaf6-70ce-4b03-9514-afe43c7dfda8)]
+interface nsIXPCComponents : nsIXPCComponentsBase
+{
     readonly attribute nsIXPCComponents_Classes         classes;
     readonly attribute nsIXPCComponents_ClassesByID     classesByID;
     readonly attribute nsIStackFrame                    stack;
-    readonly attribute nsIXPCComponents_Results         results;
     readonly attribute nsIComponentManager              manager;
     readonly attribute nsIXPCComponents_Utils           utils;
 
@@ -562,11 +582,11 @@ interface nsIXPCComponents : nsISupports
     readonly attribute nsIXPCComponents_Exception       Exception;
     readonly attribute nsIXPCComponents_Constructor     Constructor;
 
-    boolean isSuccessCode(in nsresult result);
+    [implicit_jscontext]
+    readonly attribute jsval                            lastResult;
+    [implicit_jscontext]
+    attribute jsval                                     returnCode;
 
     /* @deprecated Use Components.utils.reportError instead. */
     [deprecated, implicit_jscontext] void reportError(in jsval error);
-
-    /* 'lastResult' is accessible via JavaScript only */
-    /* 'returnCode' is accessible via JavaScript only */
 };
diff --git a/js/xpconnect/idl/xpcjsid.idl b/js/xpconnect/idl/xpcjsid.idl
index 54c9fff073b41ffa87d1a28120473b12cbe586fc..602d9b8e1f27d8ca8892102ff9b860dd3b53fa14 100644
--- a/js/xpconnect/idl/xpcjsid.idl
+++ b/js/xpconnect/idl/xpcjsid.idl
@@ -7,7 +7,7 @@
 
 [ptr] native const_nsID_ptr(const nsID);
 
-[builtinclass, scriptable, uuid(baedc96a-9cee-4b6b-9160-90d257b3c8ef)]
+[builtinclass, scriptable, uuid(62883d14-4146-4039-94f5-a5e1e1a51a15)]
 interface nsIJSID : nsISupports
 {
     readonly attribute string  name;
@@ -15,11 +15,10 @@ interface nsIJSID : nsISupports
     readonly attribute boolean valid;
 
     boolean equals(in nsIJSID other);
-
-    void initialize(in string idString);
-
     string toString();
 
+    [noscript] void initialize(in string idString);
+
     // returns a pointer to the internal nsID. this pointer is only valid
     // while the nsIJSID object remains alive!
     [notxpcom] const_nsID_ptr getID();
diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp
index 6ff153e0b2aeb227a56a0bf4ee8e6fa2a4be042f..5eb12419c88569f9794a4ffb17dff27420677b12 100644
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -1013,8 +1013,8 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
         if (script) {
             ok = JS_ExecuteScriptVersion(cx, obj, script, nullptr, JSVERSION_LATEST);
         } else {
-            jsval rval;
-            ok = JS_CallFunction(cx, obj, function, 0, nullptr, &rval);
+            RootedValue rval(cx);
+            ok = JS_CallFunction(cx, obj, function, 0, nullptr, rval.address());
         }
      }
 
diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp
index 2a1b9e5993e5bc948c1868dee157e9ec1282279d..46787e4cea669f68198b2ad0b2091f7786a05ef0 100644
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1116,7 +1116,7 @@ xpc::CreateSandboxObject(JSContext *cx, MutableHandleValue vp, nsISupports *prin
         bool allowComponents = nsContentUtils::IsSystemPrincipal(principal) ||
                                nsContentUtils::IsExpandedPrincipal(principal);
         if (options.wantComponents && allowComponents &&
-            !nsXPCComponents::AttachComponentsObject(cx, GetObjectScope(sandbox)))
+            !GetObjectScope(sandbox)->AttachComponentsObject(cx))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (!XPCNativeWrapper::AttachNewConstructorObject(cx, sandbox))
diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index 94a2b0cb30856ffd1aa1d7913378521089d36911..2dd85559ddecc7148716ba2d1916b8c115c68c88 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -90,8 +90,7 @@ xpc::CheckAccessList(const char16_t *wideName, const char *const list[])
 class nsXPCComponents_Interfaces :
             public nsIXPCComponents_Interfaces,
             public nsIXPCScriptable,
-            public nsIClassInfo,
-            public nsISecurityCheckedComponent
+            public nsIClassInfo
 {
 public:
     // all the interface method declarations...
@@ -99,7 +98,6 @@ public:
     NS_DECL_NSIXPCCOMPONENTS_INTERFACES
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
     nsXPCComponents_Interfaces();
@@ -190,7 +188,9 @@ nsXPCComponents_Interfaces::GetImplementationLanguage(uint32_t *aImplementationL
 NS_IMETHODIMP
 nsXPCComponents_Interfaces::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    // Mark ourselves as a DOM object so that instances may be created in
+    // unprivileged scopes.
+    *aFlags = nsIClassInfo::DOM_OBJECT;
     return NS_OK;
 }
 
@@ -215,7 +215,6 @@ NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
 NS_INTERFACE_MAP_END_THREADSAFE
 
@@ -333,42 +332,6 @@ nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
     return NS_OK;
 }
 
-/* string canCreateWrapper (in nsIIDPtr iid); */
-NS_IMETHODIMP
-nsXPCComponents_Interfaces::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-    // We let anyone do this...
-    *_retval = CloneAllAccess();
-    return NS_OK;
-}
-
-/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
-NS_IMETHODIMP
-nsXPCComponents_Interfaces::CanCallMethod(const nsIID * iid, const char16_t *methodName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
-/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_Interfaces::CanGetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
-/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_Interfaces::CanSetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
 /***************************************************************************/
 /***************************************************************************/
 /***************************************************************************/
@@ -376,8 +339,7 @@ nsXPCComponents_Interfaces::CanSetProperty(const nsIID * iid, const char16_t *pr
 class nsXPCComponents_InterfacesByID :
             public nsIXPCComponents_InterfacesByID,
             public nsIXPCScriptable,
-            public nsIClassInfo,
-            public nsISecurityCheckedComponent
+            public nsIClassInfo
 {
 public:
     // all the interface method declarations...
@@ -385,7 +347,6 @@ public:
     NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
     nsXPCComponents_InterfacesByID();
@@ -477,7 +438,9 @@ nsXPCComponents_InterfacesByID::GetImplementationLanguage(uint32_t *aImplementat
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    // Mark ourselves as a DOM object so that instances may be created in
+    // unprivileged scopes.
+    *aFlags = nsIClassInfo::DOM_OBJECT;
     return NS_OK;
 }
 
@@ -501,7 +464,6 @@ NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
@@ -626,42 +588,6 @@ nsXPCComponents_InterfacesByID::NewResolve(nsIXPConnectWrappedNative *wrapper,
     return NS_OK;
 }
 
-/* string canCreateWrapper (in nsIIDPtr iid); */
-NS_IMETHODIMP
-nsXPCComponents_InterfacesByID::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-    // We let anyone do this...
-    *_retval = CloneAllAccess();
-    return NS_OK;
-}
-
-/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
-NS_IMETHODIMP
-nsXPCComponents_InterfacesByID::CanCallMethod(const nsIID * iid, const char16_t *methodName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
-/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_InterfacesByID::CanGetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
-/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_InterfacesByID::CanSetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
 /***************************************************************************/
 /***************************************************************************/
 /***************************************************************************/
@@ -766,7 +692,7 @@ nsXPCComponents_Classes::GetImplementationLanguage(uint32_t *aImplementationLang
 NS_IMETHODIMP
 nsXPCComponents_Classes::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -1007,7 +933,7 @@ nsXPCComponents_ClassesByID::GetImplementationLanguage(uint32_t *aImplementation
 NS_IMETHODIMP
 nsXPCComponents_ClassesByID::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -1270,7 +1196,9 @@ nsXPCComponents_Results::GetImplementationLanguage(uint32_t *aImplementationLang
 NS_IMETHODIMP
 nsXPCComponents_Results::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    // Mark ourselves as a DOM object so that instances may be created in
+    // unprivileged scopes.
+    *aFlags = nsIClassInfo::DOM_OBJECT;
     return NS_OK;
 }
 
@@ -1492,7 +1420,7 @@ nsXPCComponents_ID::GetImplementationLanguage(uint32_t *aImplementationLanguage)
 NS_IMETHODIMP
 nsXPCComponents_ID::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -1711,7 +1639,7 @@ nsXPCComponents_Exception::GetImplementationLanguage(uint32_t *aImplementationLa
 NS_IMETHODIMP
 nsXPCComponents_Exception::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -2100,7 +2028,7 @@ nsXPCConstructor::GetImplementationLanguage(uint32_t *aImplementationLanguage)
 NS_IMETHODIMP
 nsXPCConstructor::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -2355,7 +2283,7 @@ nsXPCComponents_Constructor::GetImplementationLanguage(uint32_t *aImplementation
 NS_IMETHODIMP
 nsXPCComponents_Constructor::GetFlags(uint32_t *aFlags)
 {
-    *aFlags = nsIClassInfo::THREADSAFE;
+    *aFlags = 0;
     return NS_OK;
 }
 
@@ -2428,9 +2356,9 @@ nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
 
     nsXPConnect* xpc = nsXPConnect::XPConnect();
     XPCWrappedNativeScope* scope = GetObjectScope(obj);
-    nsXPCComponents* comp;
+    nsCOMPtr<nsIXPCComponents> comp;
 
-    if (!xpc || !scope || !(comp = scope->GetComponents()))
+    if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
     // Do the security check if necessary
@@ -2577,14 +2505,12 @@ nsXPCComponents_Constructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
 
 class nsXPCComponents_Utils :
             public nsIXPCComponents_Utils,
-            public nsIXPCScriptable,
-            public nsISecurityCheckedComponent
+            public nsIXPCScriptable
 {
 public:
     // all the interface method declarations...
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCSCRIPTABLE
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
     NS_DECL_NSIXPCCOMPONENTS_UTILS
 
 public:
@@ -2598,7 +2524,6 @@ private:
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
 NS_INTERFACE_MAP_END_THREADSAFE
 
@@ -3273,6 +3198,19 @@ nsXPCComponents_Utils::SetWantXrays(const jsval &vscope, JSContext *cx)
     return NS_OK;
 }
 
+/* jsval forcePrivilegedComponentsForScope(jsval vscope); */
+NS_IMETHODIMP
+nsXPCComponents_Utils::ForcePrivilegedComponentsForScope(const jsval &vscope,
+                                                         JSContext *cx)
+{
+    if (!vscope.isObject())
+        return NS_ERROR_INVALID_ARG;
+    JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
+    XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
+    scope->ForcePrivilegedComponents();
+    return NS_OK;
+}
+
 /* jsval getComponentsForScope(jsval vscope); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetComponentsForScope(const jsval &vscope, JSContext *cx,
@@ -3322,41 +3260,6 @@ nsXPCComponents_Utils::Dispatch(const jsval &runnableArg, const jsval &scope,
     return NS_DispatchToMainThread(run);
 }
 
-/* string canCreateWrapper (in nsIIDPtr iid); */
-NS_IMETHODIMP
-nsXPCComponents_Utils::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-    // We let anyone do this...
-    *_retval = CloneAllAccess();
-    return NS_OK;
-}
-
-/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
-NS_IMETHODIMP
-nsXPCComponents_Utils::CanCallMethod(const nsIID * iid, const char16_t *methodName, char **_retval)
-{
-    static const char* const allowed[] = { "evalInSandbox", nullptr };
-    *_retval = CheckAccessList(methodName, allowed);
-    return NS_OK;
-}
-
-/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_Utils::CanGetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    *_retval = nullptr;
-    return NS_OK;
-}
-
-/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents_Utils::CanSetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
 #define GENERATE_JSOPTION_GETTER_SETTER(_attr, _getter, _setter)    \
     NS_IMETHODIMP                                                   \
     nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
@@ -3505,8 +3408,8 @@ nsXPCComponents_Utils::GetIncumbentGlobal(const Value &aCallback,
 
     // Invoke the callback, if passed.
     if (aCallback.isObject()) {
-        Value ignored;
-        if (!JS_CallFunctionValue(aCx, nullptr, aCallback, 1, globalVal.address(), &ignored))
+        RootedValue ignored(aCx);
+        if (!JS_CallFunctionValue(aCx, nullptr, aCallback, 1, globalVal.address(), ignored.address()))
             return NS_ERROR_FAILURE;
     }
 
@@ -3576,155 +3479,55 @@ nsXPCComponents_Utils::GetWatchdogTimestamp(const nsAString& aCategory, PRTime *
 /***************************************************************************/
 /***************************************************************************/
 
-// XXXjband We ought to cache the wrapper in the object's slots rather than
-// re-wrapping on demand
-
-NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
-  NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
-  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
-  NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents)
-NS_INTERFACE_MAP_END_THREADSAFE
-
-NS_IMPL_ADDREF(nsXPCComponents)
-NS_IMPL_RELEASE(nsXPCComponents)
-
-/* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
-                       out nsIIDPtr array); */
-NS_IMETHODIMP
-nsXPCComponents::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
-{
-    const uint32_t count = 3;
-    *aCount = count;
-    nsIID **array;
-    *aArray = array = static_cast<nsIID**>(nsMemory::Alloc(count * sizeof(nsIID*)));
-    if (!array)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    uint32_t index = 0;
-    nsIID* clone;
-#define PUSH_IID(id)                                                          \
-    clone = static_cast<nsIID *>(nsMemory::Clone(&NS_GET_IID( id ),           \
-                                                 sizeof(nsIID)));             \
-    if (!clone)                                                               \
-        goto oom;                                                             \
-    array[index++] = clone;
-
-    PUSH_IID(nsIXPCComponents)
-    PUSH_IID(nsIXPCScriptable)
-    PUSH_IID(nsISecurityCheckedComponent)
-#undef PUSH_IID
-
-    return NS_OK;
-oom:
-    while (index)
-        nsMemory::Free(array[--index]);
-    nsMemory::Free(array);
-    *aArray = nullptr;
-    return NS_ERROR_OUT_OF_MEMORY;
-}
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
-NS_IMETHODIMP
-nsXPCComponents::GetHelperForLanguage(uint32_t language,
-                                      nsISupports **retval)
-{
-    nsCOMPtr<nsISupports> supports =
-        do_QueryInterface(static_cast<nsIXPCComponents *>(this));
-    supports.forget(retval);
-    return NS_OK;
-}
-
-/* readonly attribute string contractID; */
-NS_IMETHODIMP
-nsXPCComponents::GetContractID(char * *aContractID)
-{
-    *aContractID = nullptr;
-    return NS_ERROR_NOT_AVAILABLE;
-}
-
-/* readonly attribute string classDescription; */
-NS_IMETHODIMP
-nsXPCComponents::GetClassDescription(char * *aClassDescription)
-{
-    static const char classDescription[] = "XPCComponents";
-    *aClassDescription = (char*)nsMemory::Clone(classDescription, sizeof(classDescription));
-    return *aClassDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-/* readonly attribute nsCIDPtr classID; */
-NS_IMETHODIMP
-nsXPCComponents::GetClassID(nsCID * *aClassID)
-{
-    *aClassID = nullptr;
-    return NS_OK;
-}
-
-/* readonly attribute uint32_t implementationLanguage; */
-NS_IMETHODIMP
-nsXPCComponents::GetImplementationLanguage(uint32_t *aImplementationLanguage)
-{
-    *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
-    return NS_OK;
-}
-
-/* readonly attribute uint32_t flags; */
-NS_IMETHODIMP
-nsXPCComponents::GetFlags(uint32_t *aFlags)
-{
-    *aFlags = nsIClassInfo::THREADSAFE;
-    return NS_OK;
-}
-
-/* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
-NS_IMETHODIMP
-nsXPCComponents::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
+nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
+    :   mScope(aScope),
+        mInterfaces(nullptr),
+        mInterfacesByID(nullptr),
+        mResults(nullptr)
 {
-    return NS_ERROR_NOT_AVAILABLE;
+    MOZ_ASSERT(aScope, "aScope must not be null");
 }
 
 nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
-    :   mScope(aScope),
-        mInterfaces(nullptr),
-        mInterfacesByID(nullptr),
+    :   nsXPCComponentsBase(aScope),
         mClasses(nullptr),
         mClassesByID(nullptr),
-        mResults(nullptr),
         mID(nullptr),
         mException(nullptr),
         mConstructor(nullptr),
         mUtils(nullptr)
 {
-    MOZ_ASSERT(aScope, "aScope must not be null");
 }
 
-nsXPCComponents::~nsXPCComponents()
+void
+nsXPCComponentsBase::ClearMembers()
 {
-    ClearMembers();
+    NS_IF_RELEASE(mInterfaces);
+    NS_IF_RELEASE(mInterfacesByID);
+    NS_IF_RELEASE(mResults);
 }
 
 void
 nsXPCComponents::ClearMembers()
 {
-    NS_IF_RELEASE(mInterfaces);
-    NS_IF_RELEASE(mInterfacesByID);
     NS_IF_RELEASE(mClasses);
     NS_IF_RELEASE(mClassesByID);
-    NS_IF_RELEASE(mResults);
     NS_IF_RELEASE(mID);
     NS_IF_RELEASE(mException);
     NS_IF_RELEASE(mConstructor);
     NS_IF_RELEASE(mUtils);
+
+    nsXPCComponentsBase::ClearMembers();
 }
 
 /*******************************************/
-#define XPC_IMPL_GET_OBJ_METHOD(_n)                                           \
-NS_IMETHODIMP nsXPCComponents::Get##_n(nsIXPCComponents_##_n * *a##_n) {      \
+#define XPC_IMPL_GET_OBJ_METHOD(_class, _n)                                   \
+NS_IMETHODIMP _class::Get##_n(nsIXPCComponents_##_n * *a##_n) {               \
     NS_ENSURE_ARG_POINTER(a##_n);                                             \
     if (!m##_n) {                                                             \
         if (!(m##_n = new nsXPCComponents_##_n())) {                          \
-            *a##_n = nullptr;                                                  \
+            *a##_n = nullptr;                                                 \
             return NS_ERROR_OUT_OF_MEMORY;                                    \
         }                                                                     \
         NS_ADDREF(m##_n);                                                     \
@@ -3734,21 +3537,21 @@ NS_IMETHODIMP nsXPCComponents::Get##_n(nsIXPCComponents_##_n * *a##_n) {      \
     return NS_OK;                                                             \
 }
 
-XPC_IMPL_GET_OBJ_METHOD(Interfaces)
-XPC_IMPL_GET_OBJ_METHOD(InterfacesByID)
-XPC_IMPL_GET_OBJ_METHOD(Classes)
-XPC_IMPL_GET_OBJ_METHOD(ClassesByID)
-XPC_IMPL_GET_OBJ_METHOD(Results)
-XPC_IMPL_GET_OBJ_METHOD(ID)
-XPC_IMPL_GET_OBJ_METHOD(Exception)
-XPC_IMPL_GET_OBJ_METHOD(Constructor)
-XPC_IMPL_GET_OBJ_METHOD(Utils)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Interfaces)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, InterfacesByID)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Classes)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ClassesByID)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponentsBase, Results)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, ID)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Exception)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Constructor)
+XPC_IMPL_GET_OBJ_METHOD(nsXPCComponents, Utils)
 
 #undef XPC_IMPL_GET_OBJ_METHOD
 /*******************************************/
 
 NS_IMETHODIMP
-nsXPCComponents::IsSuccessCode(nsresult result, bool *out)
+nsXPCComponentsBase::IsSuccessCode(nsresult result, bool *out)
 {
     *out = NS_SUCCEEDED(result);
     return NS_OK;
@@ -3770,121 +3573,44 @@ nsXPCComponents::GetManager(nsIComponentManager * *aManager)
     return NS_GetComponentManager(aManager);
 }
 
-/**********************************************/
-
-// The nsIXPCScriptable map declaration that will generate stubs for us...
-#define XPC_MAP_CLASSNAME           nsXPCComponents
-#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
-#define                             XPC_MAP_WANT_NEWRESOLVE
-#define                             XPC_MAP_WANT_GETPROPERTY
-#define                             XPC_MAP_WANT_SETPROPERTY
-#define                             XPC_MAP_WANT_PRECREATE
-#define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
-#include "xpc_map_end.h" /* This will #undef the above */
-
-/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in uint32_t flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
-nsXPCComponents::NewResolve(nsIXPConnectWrappedNative *wrapper,
-                            JSContext *cx, JSObject *objArg,
-                            jsid idArg, uint32_t flags,
-                            JSObject **objp, bool *_retval)
+nsXPCComponents::GetLastResult(JSContext *aCx, Value *aOut)
 {
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-
-    XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
-    if (!rt)
+    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
+    if (!xpcc)
         return NS_ERROR_FAILURE;
-
-    unsigned attrs = 0;
-
-    if (id == rt->GetStringID(XPCJSRuntime::IDX_LAST_RESULT))
-        attrs = JSPROP_READONLY;
-    else if (id != rt->GetStringID(XPCJSRuntime::IDX_RETURN_CODE))
-        return NS_OK;
-
-    *objp = obj;
-    *_retval = JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, nullptr, nullptr,
-                                     JSPROP_ENUMERATE | JSPROP_PERMANENT |
-                                     attrs);
+    nsresult res = xpcc->GetLastResult();
+    *aOut = JS_NumberValue(static_cast<double>(static_cast<uint32_t>(res)));
     return NS_OK;
 }
 
-/* bool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in JSValPtr vp); */
 NS_IMETHODIMP
-nsXPCComponents::GetProperty(nsIXPConnectWrappedNative *wrapper,
-                             JSContext * cx, JSObject * obj,
-                             jsid id, jsval * vp, bool *_retval)
+nsXPCComponents::GetReturnCode(JSContext *aCx, Value *aOut)
 {
-    XPCContext* xpcc = XPCContext::GetXPCContext(cx);
+    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
     if (!xpcc)
         return NS_ERROR_FAILURE;
-
-    bool doResult = false;
-    nsresult res;
-    XPCJSRuntime* rt = xpcc->GetRuntime();
-    if (id == rt->GetStringID(XPCJSRuntime::IDX_LAST_RESULT)) {
-        res = xpcc->GetLastResult();
-        doResult = true;
-    } else if (id == rt->GetStringID(XPCJSRuntime::IDX_RETURN_CODE)) {
-        res = xpcc->GetPendingResult();
-        doResult = true;
-    }
-
-    nsresult rv = NS_OK;
-    if (doResult) {
-        *vp = JS_NumberValue((double)(uint32_t) res);
-        rv = NS_SUCCESS_I_DID_SOMETHING;
-    }
-
-    return rv;
+    nsresult res = xpcc->GetPendingResult();
+    *aOut = JS_NumberValue(static_cast<double>(static_cast<uint32_t>(res)));
+    return NS_OK;
 }
 
-/* bool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsid id, in JSValPtr vp); */
 NS_IMETHODIMP
-nsXPCComponents::SetProperty(nsIXPConnectWrappedNative *wrapper,
-                             JSContext * cx, JSObject * obj, jsid id,
-                             jsval * vp, bool *_retval)
+nsXPCComponents::SetReturnCode(JSContext *aCx, const Value &aCode)
 {
-    XPCContext* xpcc = XPCContext::GetXPCContext(cx);
+    XPCContext* xpcc = XPCContext::GetXPCContext(aCx);
     if (!xpcc)
         return NS_ERROR_FAILURE;
-
-    XPCJSRuntime* rt = xpcc->GetRuntime();
-    if (!rt)
-        return NS_ERROR_FAILURE;
-
-    if (id == rt->GetStringID(XPCJSRuntime::IDX_RETURN_CODE)) {
-        RootedValue v(cx, *vp);
-        nsresult rv;
-        if (ToUint32(cx, v, (uint32_t*)&rv)) {
-            xpcc->SetPendingResult(rv);
-            xpcc->SetLastResult(rv);
-            return NS_SUCCESS_I_DID_SOMETHING;
-        }
+    RootedValue code(aCx, aCode);
+    nsresult rv;
+    if (!ToUint32(aCx, code, (uint32_t*)&rv))
         return NS_ERROR_FAILURE;
-    }
-
-    return NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN;
+    xpcc->SetPendingResult(rv);
+    xpcc->SetLastResult(rv);
+    return NS_OK;
 }
 
 // static
-bool
-nsXPCComponents::AttachComponentsObject(JSContext* aCx,
-                                        XPCWrappedNativeScope* aScope)
-{
-    RootedObject components(aCx, aScope->GetComponentsJSObject());
-    if (!components)
-        return false;
-
-    RootedObject global(aCx, aScope->GetGlobalJSObject());
-    MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
-
-    RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
-    return JS_DefinePropertyById(aCx, global, id, ObjectValue(*components),
-                                 nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
-}
-
 /* void reportError (); */
 NS_IMETHODIMP nsXPCComponents::ReportError(const Value &error, JSContext *cx)
 {
@@ -3898,50 +3624,78 @@ NS_IMETHODIMP nsXPCComponents::ReportError(const Value &error, JSContext *cx)
     return utils->ReportError(error, cx);
 }
 
-/* string canCreateWrapper (in nsIIDPtr iid); */
-NS_IMETHODIMP
-nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-    // We let anyone do this...
-    *_retval = CloneAllAccess();
-    return NS_OK;
-}
+/**********************************************/
 
-/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
-NS_IMETHODIMP
-nsXPCComponents::CanCallMethod(const nsIID * iid, const char16_t *methodName, char **_retval)
+class ComponentsSH : public nsIXPCScriptable
 {
-    static const char* const allowed[] = { "isSuccessCode", nullptr };
-    *_retval = CheckAccessList(methodName, allowed);
-    return NS_OK;
-}
+public:
+    ComponentsSH(unsigned dummy)
+    {
+    }
 
-/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents::CanGetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    static const char* const allowed[] = { "interfaces", "interfacesByID", "results", nullptr};
-    *_retval = CheckAccessList(propertyName, allowed);
-    return NS_OK;
-}
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIXPCSCRIPTABLE
+    // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
+    // the referent to be declared __stdcall on Windows, and this is the only
+    // macro that does that.
+    static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports **helper)
+    {
+        *helper = &singleton;
+        return NS_OK;
+    }
 
-/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsXPCComponents::CanSetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
+private:
+    static ComponentsSH singleton;
+};
+
+ComponentsSH ComponentsSH::singleton(0);
+
+// Singleton refcounting.
+NS_IMETHODIMP_(nsrefcnt) ComponentsSH::AddRef(void) { return 1; }
+NS_IMETHODIMP_(nsrefcnt) ComponentsSH::Release(void) { return 1; }
+
+NS_INTERFACE_MAP_BEGIN(ComponentsSH)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+#define NSXPCCOMPONENTSBASE_CID \
+{ 0xc62998e5, 0x95f1, 0x4058, \
+  { 0xa5, 0x09, 0xec, 0x21, 0x66, 0x18, 0x92, 0xb9 } }
+
+#define NSXPCCOMPONENTS_CID \
+{ 0x3649f405, 0xf0ec, 0x4c28, \
+    { 0xae, 0xb0, 0xaf, 0x9a, 0x51, 0xe4, 0x4c, 0x81 } }
+
+NS_IMPL_CLASSINFO(nsXPCComponentsBase, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTSBASE_CID)
+NS_IMPL_ISUPPORTS1_CI(nsXPCComponentsBase, nsIXPCComponentsBase)
+
+NS_IMPL_CLASSINFO(nsXPCComponents, &ComponentsSH::Get, nsIClassInfo::DOM_OBJECT, NSXPCCOMPONENTS_CID)
+// Below is more or less what NS_IMPL_ISUPPORTS_CI_INHERITED1 would look like
+// if it existed.
+NS_IMPL_ADDREF_INHERITED(nsXPCComponents, nsXPCComponentsBase)
+NS_IMPL_RELEASE_INHERITED(nsXPCComponents, nsXPCComponentsBase)
+NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
+    NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
+    NS_IMPL_QUERY_CLASSINFO(nsXPCComponents)
+NS_INTERFACE_MAP_END_INHERITING(nsXPCComponentsBase)
+NS_IMPL_CI_INTERFACE_GETTER1(nsXPCComponents, nsIXPCComponents)
+
+// The nsIXPCScriptable map declaration that will generate stubs for us
+#define XPC_MAP_CLASSNAME           ComponentsSH
+#define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
+#define                             XPC_MAP_WANT_PRECREATE
+#include "xpc_map_end.h" /* This will #undef the above */
 
 NS_IMETHODIMP
-nsXPCComponents::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
+ComponentsSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
 {
+  nsXPCComponentsBase *self = static_cast<nsXPCComponentsBase*>(nativeObj);
   // this should never happen
-  if (!mScope) {
+  if (!self->GetScope()) {
       NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
       return NS_ERROR_FAILURE;
   }
-  *parentObj = mScope->GetGlobalJSObject();
+  *parentObj = self->GetScope()->GetGlobalJSObject();
   return NS_OK;
 }
diff --git a/js/xpconnect/src/XPCJSID.cpp b/js/xpconnect/src/XPCJSID.cpp
index 9cefafe42f30365827dcd72b3410e5bd9b0082bb..7ce17d265d7082e36facbfc0e50b45f8b06c64d2 100644
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -210,7 +210,7 @@ nsJSID::NewID(const nsID& id)
 class SharedScriptableHelperForJSIID MOZ_FINAL : public nsIXPCScriptable
 {
 public:
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCSCRIPTABLE
     SharedScriptableHelperForJSIID() {}
 };
@@ -218,7 +218,7 @@ public:
 NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
-NS_INTERFACE_MAP_END_THREADSAFE
+NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(SharedScriptableHelperForJSIID)
 NS_IMPL_RELEASE(SharedScriptableHelperForJSIID)
@@ -261,12 +261,14 @@ NS_METHOD GetSharedScriptableHelperForJSIID(uint32_t language,
 { 0x00000000, 0x0000, 0x0000,                                                 \
   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
 
+// We pass nsIClassInfo::DOM_OBJECT so that nsJSIID instances may be created
+// in unprivileged scopes.
 NS_DECL_CI_INTERFACE_GETTER(nsJSIID)
 NS_IMPL_CLASSINFO(nsJSIID, GetSharedScriptableHelperForJSIID,
-                  nsIClassInfo::THREADSAFE, NULL_CID)
+                  nsIClassInfo::DOM_OBJECT, NULL_CID)
 
 NS_DECL_CI_INTERFACE_GETTER(nsJSCID)
-NS_IMPL_CLASSINFO(nsJSCID, nullptr, nsIClassInfo::THREADSAFE, NULL_CID)
+NS_IMPL_CLASSINFO(nsJSCID, nullptr, 0, NULL_CID)
 
 void xpc_DestroyJSxIDClassObjects()
 {
@@ -285,10 +287,9 @@ NS_INTERFACE_MAP_BEGIN(nsJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIJSID)
   NS_INTERFACE_MAP_ENTRY(nsIJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
   NS_IMPL_QUERY_CLASSINFO(nsJSIID)
-NS_INTERFACE_MAP_END_THREADSAFE
+NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsJSIID)
 NS_IMPL_RELEASE(nsJSIID)
@@ -561,43 +562,6 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
     return xpc::HasInstance(cx, obj, iid, bp);
 }
 
-/* string canCreateWrapper (in nsIIDPtr iid); */
-NS_IMETHODIMP
-nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-    // We let anyone do this...
-    *_retval = xpc::CloneAllAccess();
-    return NS_OK;
-}
-
-/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
-NS_IMETHODIMP
-nsJSIID::CanCallMethod(const nsIID * iid, const char16_t *methodName, char **_retval)
-{
-    static const char* const allowed[] = {"equals", "toString", nullptr};
-
-    *_retval = xpc::CheckAccessList(methodName, allowed);
-    return NS_OK;
-}
-
-/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsJSIID::CanGetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    static const char* const allowed[] = {"name", "number", "valid", nullptr};
-    *_retval = xpc::CheckAccessList(propertyName, allowed);
-    return NS_OK;
-}
-
-/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
-NS_IMETHODIMP
-nsJSIID::CanSetProperty(const nsIID * iid, const char16_t *propertyName, char **_retval)
-{
-    // If you have to ask, then the answer is NO
-    *_retval = nullptr;
-    return NS_OK;
-}
-
 /***************************************************************************/
 
 NS_INTERFACE_MAP_BEGIN(nsJSCID)
@@ -606,7 +570,7 @@ NS_INTERFACE_MAP_BEGIN(nsJSCID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
   NS_IMPL_QUERY_CLASSINFO(nsJSCID)
-NS_INTERFACE_MAP_END_THREADSAFE
+NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsJSCID)
 NS_IMPL_RELEASE(nsJSCID)
diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
index 63d8c95951b30a86118de8353021d36422fd9959..1665cbe0ea380d145daa3fe00803d223e8a80f6b 100644
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -561,7 +561,8 @@ EnableUniversalXPConnect(JSContext *cx)
     XPCWrappedNativeScope *scope = priv->scope;
     if (!scope)
         return true;
-    return nsXPCComponents::AttachComponentsObject(cx, scope);
+    scope->ForcePrivilegedComponents();
+    return scope->AttachComponentsObject(cx);
 }
 
 JSObject *
diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp
index 6fbeba45ab355742c808fb15140e7fbaf81ea445..6aced78036336a92827a4f690778f8dd7045fdc9 100644
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1134,14 +1134,15 @@ ProcessArgs(JSContext *cx, JS::Handle<JSObject*> obj, char **argv, int argc, XPC
             break;
         case 'e':
         {
-            jsval rval;
+            RootedValue rval(cx);
 
             if (++i == argc) {
                 return usage();
             }
 
             JS_EvaluateScriptForPrincipals(cx, obj, gJSPrincipals, argv[i],
-                                           strlen(argv[i]), "-e", 1, &rval);
+                                           strlen(argv[i]), "-e", 1,
+                                           rval.address());
 
             isInteractive = false;
             break;
diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp
index 7a6f71af40fc9fa754c37600d4eccd77b9c7b378..daf1205f68ba06679c8b37f629d56ad943860886 100644
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -1709,10 +1709,6 @@ XPCWrappedNative::GetSameCompartmentSecurityWrapper(JSContext *cx)
         wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat);
         if (!wrapper)
             return nullptr;
-    } else if (xpc::WrapperFactory::IsComponentsObject(flat)) {
-        wrapper = xpc::WrapperFactory::WrapComponentsObject(cx, flat);
-        if (!wrapper)
-            return nullptr;
     }
 
     // If we made a wrapper, cache it and return it.
diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp
index 67bb6dc4106ca5af0e5b65b8ba5f363141ff9550..682d70bcd77eff638dab5c22fbf4b0333bfbb9b9 100644
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -1,11 +1,13 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ * 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/. */
 
 /* Class used to manage the wrapped native objects within a JS scope. */
 
 #include "xpcprivate.h"
+#include "XPCWrapper.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsPrincipal.h"
@@ -131,29 +133,60 @@ JSObject*
 XPCWrappedNativeScope::GetComponentsJSObject()
 {
     AutoJSContext cx;
-    if (!mComponents)
-        mComponents = new nsXPCComponents(this);
+    if (!mComponents) {
+        nsIPrincipal *p = GetPrincipal();
+        bool system = XPCWrapper::GetSecurityManager()->IsSystemPrincipal(p);
+        mComponents = system ? new nsXPCComponents(this)
+                             : new nsXPCComponentsBase(this);
+    }
 
-    AutoMarkingNativeInterfacePtr iface(cx);
-    iface = XPCNativeInterface::GetNewOrUsed(&NS_GET_IID(nsIXPCComponents));
-    if (!iface)
+    RootedValue val(cx);
+    xpcObjectHelper helper(mComponents);
+    bool ok = XPCConvert::NativeInterface2JSObject(&val, nullptr, helper,
+                                                   nullptr, nullptr, false,
+                                                   nullptr);
+    if (NS_WARN_IF(!ok))
         return nullptr;
 
-    nsCOMPtr<nsIXPCComponents> cholder(mComponents);
-    xpcObjectHelper helper(cholder);
-    nsCOMPtr<XPCWrappedNative> wrapper;
-    XPCWrappedNative::GetNewOrUsed(helper, this, iface, getter_AddRefs(wrapper));
-    if (!wrapper)
+    if (NS_WARN_IF(!val.isObject()))
         return nullptr;
 
     // The call to wrap() here is necessary even though the object is same-
     // compartment, because it applies our security wrapper.
-    JS::RootedObject obj(cx, wrapper->GetFlatJSObject());
-    if (!JS_WrapObject(cx, &obj))
+    JS::RootedObject obj(cx, &val.toObject());
+    if (NS_WARN_IF(!JS_WrapObject(cx, &obj)))
         return nullptr;
     return obj;
 }
 
+void
+XPCWrappedNativeScope::ForcePrivilegedComponents()
+{
+    // This may only be called on unprivileged scopes during automation where
+    // we allow insecure things.
+    MOZ_RELEASE_ASSERT(Preferences::GetBool("security.turn_off_all_security_so_"
+                                            "that_viruses_can_take_over_this_"
+                                            "computer"));
+    nsCOMPtr<nsIXPCComponents> c = do_QueryInterface(mComponents);
+    if (!c)
+        mComponents = new nsXPCComponents(this);
+}
+
+bool
+XPCWrappedNativeScope::AttachComponentsObject(JSContext* aCx)
+{
+    RootedObject components(aCx, GetComponentsJSObject());
+    if (!components)
+        return false;
+
+    RootedObject global(aCx, GetGlobalJSObject());
+    MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
+
+    RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
+    return JS_DefinePropertyById(aCx, global, id, ObjectValue(*components),
+                                 nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
+}
+
 JSObject*
 XPCWrappedNativeScope::EnsureXBLScope(JSContext *cx)
 {
diff --git a/js/xpconnect/src/moz.build b/js/xpconnect/src/moz.build
index 165d68b9d54379d814398434fba37df105480bc0..5d7844070ae4cece075ef7a5adba63c079152816 100644
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -86,11 +86,11 @@ LOCAL_INCLUDES += [
     '/caps/include',
     '/content/base/public',
     '/content/base/src',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/svg/content/src',
     '/dom/base',
+    '/dom/events',
     '/js/ipc',
     '/layout/base',
     '/layout/style',
diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp
index ef011136bd88c48ce08ff50effbbfbd987cb947e..f59d6c1d55a8c89634a7b555864dcdd44413572e 100644
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -502,7 +502,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
 
     if (!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
         // XPCCallContext gives us an active request needed to save/restore.
-        if (!nsXPCComponents::AttachComponentsObject(aJSContext, wrappedGlobal->GetScope()))
+        if (!wrappedGlobal->GetScope()->AttachComponentsObject(aJSContext))
             return UnexpectedFailure(NS_ERROR_FAILURE);
 
         if (!XPCNativeWrapper::AttachNewConstructorObject(aJSContext, global))
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index 55e7509774d3ea02f62e3fe37bc4b126caad8fbe..3a40ec1067c1a11a442c74a4299e45a6c17844d3 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1055,6 +1055,7 @@ enum WrapperType {
 /***************************************************************************/
 // XPCWrappedNativeScope is one-to-one with a JS global object.
 
+class nsXPCComponentsBase;
 class XPCWrappedNativeScope : public PRCList
 {
 public:
@@ -1071,9 +1072,16 @@ public:
     ClassInfo2WrappedNativeProtoMap*
     GetWrappedNativeProtoMap() const {return mWrappedNativeProtoMap;}
 
-    nsXPCComponents*
+    nsXPCComponentsBase*
     GetComponents() const {return mComponents;}
 
+    // Forces the creation of a privileged |Components| object, even in
+    // content scopes. This will crash if used outside of automation.
+    void
+    ForcePrivilegedComponents();
+
+    bool AttachComponentsObject(JSContext *aCx);
+
     // Returns the JS object reflection of the Components object.
     JSObject*
     GetComponentsJSObject();
@@ -1208,7 +1216,7 @@ private:
     XPCJSRuntime*                    mRuntime;
     Native2WrappedNativeMap*         mWrappedNativeMap;
     ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
-    nsRefPtr<nsXPCComponents>        mComponents;
+    nsRefPtr<nsXPCComponentsBase>    mComponents;
     XPCWrappedNativeScope*           mNext;
     // The JS global object for this scope.  If non-null, this will be the
     // default parent for the XPCWrappedNatives that have us as the scope,
@@ -2771,7 +2779,7 @@ class nsJSID : public nsIJSID
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
 
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_ISUPPORTS
     NS_DECL_NSIJSID
 
     bool InitWithName(const nsID& id, const char *nameString);
@@ -2802,11 +2810,10 @@ protected:
 // nsJSIID
 
 class nsJSIID : public nsIJSIID,
-                public nsIXPCScriptable,
-                public nsISecurityCheckedComponent
+                public nsIXPCScriptable
 {
 public:
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_ISUPPORTS
 
     // we manually delagate these to nsJSID
     NS_DECL_NSIJSID
@@ -2814,7 +2821,6 @@ public:
     // we implement the rest...
     NS_DECL_NSIJSIID
     NS_DECL_NSIXPCSCRIPTABLE
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
     static nsJSIID* NewID(nsIInterfaceInfo* aInfo);
 
@@ -2831,7 +2837,7 @@ private:
 class nsJSCID : public nsIJSCID, public nsIXPCScriptable
 {
 public:
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_ISUPPORTS
 
     // we manually delagate these to nsJSID
     NS_DECL_NSIJSID
@@ -2920,44 +2926,63 @@ private:
 };
 
 /***************************************************************************/
-// 'Components' object
+// 'Components' object implementations. nsXPCComponentsBase has the
+// less-privileged stuff that we're willing to expose to XBL.
 
-class nsXPCComponents : public nsIXPCComponents,
-                        public nsIXPCScriptable,
-                        public nsIClassInfo,
-                        public nsISecurityCheckedComponent
+class nsXPCComponentsBase : public nsIXPCComponentsBase
 {
 public:
-    NS_DECL_THREADSAFE_ISUPPORTS
-    NS_DECL_NSIXPCCOMPONENTS
-    NS_DECL_NSIXPCSCRIPTABLE
-    NS_DECL_NSICLASSINFO
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIXPCCOMPONENTSBASE
 
 public:
-    static bool
-    AttachComponentsObject(JSContext* aCx, XPCWrappedNativeScope* aScope);
-
-    void SystemIsBeingShutDown() {ClearMembers();}
+    void SystemIsBeingShutDown() { ClearMembers(); }
+    virtual ~nsXPCComponentsBase() { ClearMembers(); }
 
-    virtual ~nsXPCComponents();
+    XPCWrappedNativeScope *GetScope() { return mScope; }
 
-private:
-    nsXPCComponents(XPCWrappedNativeScope* aScope);
-    void ClearMembers();
+protected:
+    nsXPCComponentsBase(XPCWrappedNativeScope* aScope);
+    virtual void ClearMembers();
 
-private:
-    friend class XPCWrappedNativeScope;
     XPCWrappedNativeScope*          mScope;
+
+    // Unprivileged members from nsIXPCComponentsBase.
     nsXPCComponents_Interfaces*     mInterfaces;
     nsXPCComponents_InterfacesByID* mInterfacesByID;
+    nsXPCComponents_Results*        mResults;
+
+    friend class XPCWrappedNativeScope;
+};
+
+class nsXPCComponents : public nsXPCComponentsBase,
+                        public nsIXPCComponents
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_FORWARD_NSIXPCCOMPONENTSBASE(nsXPCComponentsBase::)
+    NS_DECL_NSIXPCCOMPONENTS
+
+protected:
+    nsXPCComponents(XPCWrappedNativeScope* aScope);
+
+    // One might think we could rely on the superclass destructor invoking
+    // the virtual cleanup function. But by the time we hit the superclass
+    // destructor, the derived class will be gone and the vtable pointer
+    // will be updated to point to that of the superclass, giving us only
+    // the superclass' cleanup.
+    virtual ~nsXPCComponents() { ClearMembers(); }
+    virtual void ClearMembers() MOZ_OVERRIDE;
+
+    // Privileged members added by nsIXPCComponents.
     nsXPCComponents_Classes*        mClasses;
     nsXPCComponents_ClassesByID*    mClassesByID;
-    nsXPCComponents_Results*        mResults;
     nsXPCComponents_ID*             mID;
     nsXPCComponents_Exception*      mException;
     nsXPCComponents_Constructor*    mConstructor;
     nsXPCComponents_Utils*          mUtils;
+
+    friend class XPCWrappedNativeScope;
 };
 
 
diff --git a/js/xpconnect/tests/unit/test_bug677864.js b/js/xpconnect/tests/unit/test_bug677864.js
index 14562757a5adc48652a7cef0728de5e9ff1cb0a8..a90a7b137fa120dcc62ac5f6a12f3d6f95819367 100644
--- a/js/xpconnect/tests/unit/test_bug677864.js
+++ b/js/xpconnect/tests/unit/test_bug677864.js
@@ -3,7 +3,6 @@ function check_cl(iface, desc) {
 }
 
 function run_test() {
-    check_cl(Components, 'XPCComponents');
     check_cl(Components.interfaces, 'XPCComponents_Interfaces');
     check_cl(Components.interfacesByID, 'XPCComponents_InterfacesByID');
     check_cl(Components.classes, 'XPCComponents_Classes');
diff --git a/js/xpconnect/tests/unit/test_components.js b/js/xpconnect/tests/unit/test_components.js
index 7cff627e47a61f553d5d6708406f61c4472efa01..623a365c064c641e3667fc0df6d25314fdfff221 100644
--- a/js/xpconnect/tests/unit/test_components.js
+++ b/js/xpconnect/tests/unit/test_components.js
@@ -18,15 +18,23 @@ function run_test() {
   checkThrows("C.classes", sb1);
 
   // non-chrome accessing own Components
-  checkThrows("Components.utils", sb1);
-  checkThrows("Components.classes", sb1);
+  do_check_eq(Cu.evalInSandbox("typeof Components.interfaces", sb1), 'object');
+  do_check_eq(Cu.evalInSandbox("typeof Components.utils", sb1), 'undefined');
+  do_check_eq(Cu.evalInSandbox("typeof Components.classes", sb1), 'undefined');
 
-  // non-chrome same origin
+  // Make sure an unprivileged Components is benign.
   var C2 = Cu.evalInSandbox("Components", sb2);
-  do_check_neq(rv, C2.utils);
+  var whitelist = ['interfaces', 'interfacesByID', 'results', 'isSuccessCode', 'QueryInterface'];
+  for (var prop in Components) {
+    do_print("Checking " + prop);
+    do_check_eq((prop in C2), whitelist.indexOf(prop) != -1);
+  }
+
+  // non-chrome same origin
   sb1.C2 = C2;
-  checkThrows("C2.utils", sb1);
-  checkThrows("C2.classes", sb1);
+  do_check_eq(Cu.evalInSandbox("typeof C2.interfaces", sb1), 'object');
+  do_check_eq(Cu.evalInSandbox("typeof C2.utils", sb1), 'undefined');
+  do_check_eq(Cu.evalInSandbox("typeof C2.classes", sb1), 'undefined');
 
   // chrome accessing chrome
   sb3.C = Components;
@@ -35,8 +43,9 @@ function run_test() {
 
   // non-chrome cross origin
   sb4.C2 = C2;
-  checkThrows("C2.utils", sb1);
-  checkThrows("C2.classes", sb1);
+  checkThrows("C2.interfaces", sb4);
+  checkThrows("C2.utils", sb4);
+  checkThrows("C2.classes", sb4);
 }
 
 function checkThrows(expression, sb) {
diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp
index f84c9bb13fdcb2a769d4303f02c516cbc46fa4af..f49708a51fbc755e3228f7e3dd17f37acc3e6fba 100644
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -401,33 +401,4 @@ ExposedPropertiesOnly::allowNativeCall(JSContext *cx, JS::IsAcceptableThis test,
     return js::IsReadOnlyDateMethod(test, impl) || js::IsTypedArrayThisCheck(test);
 }
 
-bool
-ComponentsObjectPolicy::check(JSContext *cx, JSObject *wrapperArg, jsid idArg, Wrapper::Action act)
-{
-    RootedObject wrapper(cx, wrapperArg);
-    RootedId id(cx, idArg);
-    JSAutoCompartment ac(cx, wrapper);
-
-    if (JSID_IS_STRING(id) && act == Wrapper::GET) {
-        JSFlatString *flatId = JSID_TO_FLAT_STRING(id);
-        if (JS_FlatStringEqualsAscii(flatId, "isSuccessCode") ||
-            JS_FlatStringEqualsAscii(flatId, "lookupMethod") ||
-            JS_FlatStringEqualsAscii(flatId, "interfaces") ||
-            JS_FlatStringEqualsAscii(flatId, "interfacesByID") ||
-            JS_FlatStringEqualsAscii(flatId, "results"))
-        {
-            return true;
-        }
-    }
-
-    // We don't have any way to recompute same-compartment Components wrappers,
-    // so we need this dynamic check. This can go away when we expose Components
-    // as SpecialPowers.wrap(Components) during automation.
-    if (xpc::IsUniversalXPConnectEnabled(cx)) {
-        return true;
-    }
-
-    return false;
-}
-
 }
diff --git a/js/xpconnect/wrappers/AccessCheck.h b/js/xpconnect/wrappers/AccessCheck.h
index 169e3e32112b86500e6d9fd22957ee0c3f8e1005..9a6b03d1b3d6e98531a959265e00b03b4f200d8c 100644
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -98,18 +98,6 @@ struct ExposedPropertiesOnly : public Policy {
     static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl);
 };
 
-// Components specific policy
-struct ComponentsObjectPolicy : public Policy {
-    static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act);
-
-    static bool deny(js::Wrapper::Action act, JS::HandleId id) {
-        return false;
-    }
-    static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl) {
-        return false;
-    }
-};
-
 }
 
 #endif /* __AccessCheck_h__ */
diff --git a/js/xpconnect/wrappers/FilteringWrapper.cpp b/js/xpconnect/wrappers/FilteringWrapper.cpp
index e7755b5f1c8fb83aad647d5c1931a317fb6f9f2f..1f5b93b0894f05e1b546cc6b26d278268984d88f 100644
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -194,17 +194,12 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, HandleObject wrapper,
 #define XOW FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>
 #define DXOW   FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>
 #define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>
-#define CW FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>
-#define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, ComponentsObjectPolicy>
 #define GO FilteringWrapper<CrossCompartmentSecurityWrapper, GentlyOpaque>
 template<> SCSOW SCSOW::singleton(0);
 template<> XOW XOW::singleton(0);
 template<> DXOW DXOW::singleton(0);
 template<> NNXOW NNXOW::singleton(0);
 
-template<> CW CW::singleton(0);
-template<> XCW XCW::singleton(0);
-
 template<> GO GO::singleton(0);
 
 template class XOW;
diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp
index fc64e78bd71623c0191bb1589a4ac1c3e35e5cf2..fc7bbddbb972d4619b9911171d364f0e46bf6ea6 100644
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -316,9 +316,6 @@ DEBUG_CheckUnwrapSafety(HandleObject obj, js::Wrapper *handler,
     if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) {
         // If the caller is chrome (or effectively so), unwrap should always be allowed.
         MOZ_ASSERT(handler->isSafeToUnwrap());
-    } else if (WrapperFactory::IsComponentsObject(obj)) {
-        // The Components object that is restricted regardless of origin.
-        MOZ_ASSERT(!handler->isSafeToUnwrap());
     } else if (AccessCheck::needsSystemOnlyWrapper(obj)) {
         // The rules for SOWs are complicated enough. Just skip double-checking them here.
     } else if (handler == &FilteringWrapper<CrossCompartmentSecurityWrapper, GentlyOpaque>::singleton) {
@@ -412,12 +409,9 @@ WrapperFactory::Rewrap(JSContext *cx, HandleObject existing, HandleObject obj,
     } else if (originIsChrome && !targetIsChrome && xrayType == NotXray) {
         wrapper = &ChromeObjectWrapper::singleton;
 
-    // If content is accessing a Components object or NAC, we need a special filter,
-    // even if the object is same origin. Note that we allow access to NAC for
-    // remote-XUL whitelisted domains, since they don't have XBL scopes.
-    } else if (IsComponentsObject(obj) && !AccessCheck::isChrome(target)) {
-        wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
-                                    ComponentsObjectPolicy>::singleton;
+    // If content is accessing NAC, we need a special filter, even if the
+    // object is same origin. Note that we allow access to NAC for remote-XUL
+    // whitelisted domains, since they don't have XBL scopes.
     } else if (AccessCheck::needsSystemOnlyWrapper(obj) &&
                xpc::AllowXBLScope(target) &&
                !(targetIsChrome || (targetSubsumesOrigin && nsContentUtils::IsCallerXBL())))
@@ -516,8 +510,6 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, HandleObject objArg)
 
     // The WN knows what to do.
     RootedObject wrapper(cx, wn->GetSameCompartmentSecurityWrapper(cx));
-    MOZ_ASSERT_IF(wrapper != obj && IsComponentsObject(js::UncheckedUnwrap(obj)),
-                  !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
     return wrapper;
 }
 
@@ -586,23 +578,6 @@ WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *objArg)
     return wrapperObj;
 }
 
-bool
-WrapperFactory::IsComponentsObject(JSObject *obj)
-{
-    const char *name = js::GetObjectClass(obj)->name;
-    return name[0] == 'n' && !strcmp(name, "nsXPCComponents");
-}
-
-JSObject *
-WrapperFactory::WrapComponentsObject(JSContext *cx, HandleObject obj)
-{
-    JSObject *wrapperObj =
-        Wrapper::New(cx, obj, JS_GetGlobalForObject(cx, obj),
-                     &FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>::singleton);
-
-    return wrapperObj;
-}
-
 bool
 WrapperFactory::XrayWrapperNotShadowing(JSObject *wrapper, jsid id)
 {
diff --git a/js/xpconnect/wrappers/WrapperFactory.h b/js/xpconnect/wrappers/WrapperFactory.h
index 1aab6c7e674a8d18200f3c93cc601a9386642b41..0261ba00a2bc7619e3a2c3232d21e92a8b103ae9 100644
--- a/js/xpconnect/wrappers/WrapperFactory.h
+++ b/js/xpconnect/wrappers/WrapperFactory.h
@@ -69,12 +69,6 @@ class WrapperFactory {
     // Wrap a (same compartment) object in a SOW.
     static JSObject *WrapSOWObject(JSContext *cx, JSObject *obj);
 
-    // Return true if this is a Components object.
-    static bool IsComponentsObject(JSObject *obj);
-
-    // Wrap a (same compartment) Components object.
-    static JSObject *WrapComponentsObject(JSContext *cx, JS::HandleObject obj);
-
     // Returns true if the wrapper is in not shadowing mode for the id.
     static bool XrayWrapperNotShadowing(JSObject *wrapper, jsid id);
 };
diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp
index 2610670ab61205462b3ad72254b3a48e697269d6..ef0b08d27beb98410ad6de8a43c9042c57f06f2a 100644
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1118,7 +1118,8 @@ DOMXrayTraits::call(JSContext *cx, HandleObject wrapper,
     // call those on the content compartment.
     if (clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS) {
         if (!clasp->call) {
-            js_ReportIsNotFunction(cx, JS::ObjectValue(*wrapper));
+            RootedValue v(cx, ObjectValue(*wrapper));
+            js_ReportIsNotFunction(cx, v);
             return false;
         }
         // call it on the Xray compartment
@@ -1143,7 +1144,8 @@ DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper,
     // See comments in DOMXrayTraits::call() explaining what's going on here.
     if (clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS) {
         if (!clasp->construct) {
-            js_ReportIsNotFunction(cx, JS::ObjectValue(*wrapper));
+            RootedValue v(cx, ObjectValue(*wrapper));
+            js_ReportIsNotFunction(cx, v);
             return false;
         }
         if (!clasp->construct(cx, args.length(), args.base()))
diff --git a/layout/base/moz.build b/layout/base/moz.build
index e97d5f01072868f304a67ea977d2aea85266e7ea..64b1a82d053c5139ee9f1fe2716e4ffa7b914536 100644
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -113,7 +113,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../../content/base/src',
-    '../../content/events/src',
     '../../content/html/content/src',
     '../../content/svg/content/src',
     '../../view/src',
@@ -128,6 +127,7 @@ LOCAL_INCLUDES += [
     '../xul/tree/',
     '/docshell/base',
     '/dom/base',
+    '/dom/events',
     '/dom/xbl',
     '/xpcom/ds',
 ]
diff --git a/layout/build/moz.build b/layout/build/moz.build
index e89596d41a0f5c7a0fe2e206c8251bfae2fc25cb..e7539ab45d3b84e70f355e1d1a702ad9bb0a33a8 100644
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -41,7 +41,6 @@ LOCAL_INCLUDES += [
     '/caps/include',
     '/content/base/src',
     '/content/canvas/src',
-    '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/svg/content/src',
@@ -52,6 +51,7 @@ LOCAL_INCLUDES += [
     '/dom/audiochannel',
     '/dom/base',
     '/dom/camera',
+    '/dom/events',
     '/dom/file',
     '/dom/media',
     '/dom/speakermanager',
diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp
index fe00defc3c6b912dce203172dec9bb92910c3bbb..5daa0b1d58667563a01c2bedd054799e6cc3f7d1 100644
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -55,8 +55,8 @@ class nsPresState;
 
 // Drop down list event management.
 // The combo box uses the following strategy for managing the drop-down list.
-// If the combo box or it's arrow button is clicked on the drop-down list is displayed
-// If mouse exit's the combo box with the drop-down list displayed the drop-down list
+// If the combo box or its arrow button is clicked on the drop-down list is displayed
+// If mouse exits the combo box with the drop-down list displayed the drop-down list
 // is asked to capture events
 // The drop-down list will capture all events including mouse down and up and will always
 // return with ListWasSelected method call regardless of whether an item in the list was
@@ -445,7 +445,7 @@ nsComboboxControlFrame::ReflowDropdown(nsPresContext*  aPresContext,
                             kidReflowState, rect.x, rect.y, flags,
                             ignoredStatus);
 
-   // Set the child's width and height to it's desired size
+   // Set the child's width and height to its desired size
   FinishReflowChild(mDropdownFrame, aPresContext, &kidReflowState,
                     desiredSize, rect.x, rect.y, flags);
   return rv;
@@ -1138,7 +1138,7 @@ nsComboboxControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // The frames used to display the combo box and the button used to popup the dropdown list
   // are created through anonymous content. The dropdown list is not created through anonymous
-  // content because it's frame is initialized specifically for the drop-down case and it is placed
+  // content because its frame is initialized specifically for the drop-down case and it is placed
   // a special list referenced through NS_COMBO_FRAME_POPUP_LIST_INDEX to keep separate from the
   // layout of the display and button.
   //
diff --git a/layout/forms/test/mochitest.ini b/layout/forms/test/mochitest.ini
index 47e408375e10b5dfb37defda25f1454bb32681dd..dfb1f6425395eb847b756e6aa9824ded17bc1fb2 100644
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -35,6 +35,7 @@ support-files =
 [test_bug717878_input_scroll.html]
 [test_bug869314.html]
 [test_bug903715.html]
+[test_bug957562.html]
 [test_listcontrol_search.html]
 [test_select_prevent_default.html]
 [test_textarea_resize.html]
diff --git a/layout/forms/test/test_bug957562.html b/layout/forms/test/test_bug957562.html
new file mode 100644
index 0000000000000000000000000000000000000000..6c52dc5e0c56450390c2cedd7fcccb1c3b1031e7
--- /dev/null
+++ b/layout/forms/test/test_bug957562.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=957562
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 903715</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=957562">Mozilla Bug 957562</a>
+<p id="display"></p>
+<input id="n" onfocus="kill()" type="number" style="border:20px solid black">
+<pre id="test">
+</pre>
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests, window);
+
+var killed = false;
+function kill() {
+  if (killed) {
+    return;
+  }
+  killed = true;
+  n.style.display = 'none';
+  r = n.getBoundingClientRect();
+  setTimeout(function() {
+    ok(true, "Didn't crash");
+    SimpleTest.finish();
+  }, 0);
+}
+
+function runTests()
+{
+  synthesizeMouse(n, 2, 2, {});
+}
+</script>
+</body>
+</html>
diff --git a/layout/style/test/test_animations.html b/layout/style/test/test_animations.html
index 0492cb3b2169622836463b90b45b959bc690f370..0d7fb506a0e52fff5df1176d8f12695c9edc58fe 100644
--- a/layout/style/test/test_animations.html
+++ b/layout/style/test/test_animations.html
@@ -255,7 +255,7 @@ function test_fill_mode(fill_mode, fills_backwards, fills_forwards)
   check_events([], "before start in test_fill_mode");
   advance_clock(1000);
   check_events([{ type: 'animationstart', target: div,
-                  bubbles: true, cancelable: true,
+                  bubbles: true, cancelable: false,
                   animationName: 'anim1', elapsedTime: 0.0,
                   pseudoElement: "" }],
                "right after start in test_fill_mode");
@@ -274,7 +274,7 @@ function test_fill_mode(fill_mode, fills_backwards, fills_forwards)
   check_events([], "before end in test_fill_mode");
   advance_clock(125);
   check_events([{ type: 'animationend', target: div,
-                  bubbles: true, cancelable: true,
+                  bubbles: true, cancelable: false,
                   animationName: 'anim1', elapsedTime: 10.0,
                   pseudoElement: "" }],
                "right after end in test_fill_mode");
diff --git a/layout/style/test/test_compute_data_with_start_struct.html b/layout/style/test/test_compute_data_with_start_struct.html
index 862bb8b06d38745baad9bb6d8621a27298471754..247c044d3d28bff1bd4bb5ffa55a896467276fd7 100644
--- a/layout/style/test/test_compute_data_with_start_struct.html
+++ b/layout/style/test/test_compute_data_with_start_struct.html
@@ -19,6 +19,34 @@
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+/**
+ * The purpose of this test is to test that nsRuleNode::Compute*Data
+ * functions are written correctly.  In particular, in these functions,
+ * when the specified value of a property has unit eCSSUnit_Null,
+ * touching the computed data is forbidden.  This is because we
+ * sometimes stop walking up the rule tree when we find computed data
+ * for an initial subsequence of our rules (i.e., an ancestor rule node)
+ * that we can use as a starting point (aStartStruct) for the
+ * computation for the current rule node.
+ *
+ * If one of these tests fails, you should look for a case where the
+ * property's code in nsRuleNode::Compute*Data touches the computed
+ * value when the specified value has eCSSUnit_Null, and fix it.
+ *
+ * The test works by maintaining one style rule that has every CSS
+ * property specified, and a second style rule that has different values
+ * for every property, an element that matches only the first rule (so
+ * that we'll have a cached struct), and *later* an element that matches
+ * both rules (for whose computation we'll find the struct cached from
+ * the first element).  (It does this twice, once with the overriding in
+ * each direction, because one of the cases might match the incorrect
+ * overwriting.)  Then, in the second style rule, it unsets each
+ * property, one at a time, and checks that the computation works
+ * correctly.  (The reason to want every property set is to hit a case
+ * where we can store the data in the rule tree... though this isn't
+ * guaranteed.)
+ */
+
 function xfail_computecheck(prop, roundnum) {
     return false;
 }
diff --git a/layout/style/test/test_extra_inherit_initial.html b/layout/style/test/test_extra_inherit_initial.html
index 8d57dd7f6ae5ee9bd8841d5a8f732fb770ebece3..7b12b7f632b95d856f2cee384cf05d266c3bd3e7 100644
--- a/layout/style/test/test_extra_inherit_initial.html
+++ b/layout/style/test/test_extra_inherit_initial.html
@@ -73,23 +73,20 @@ function test_property(property)
     test_value(info.other_values[idx]);
 }
 
-// To avoid triggering the slow script dialog, we have to test one
-// property at a time.
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestLongerTimeout(4);
-var props = [];
-for (var prop in gCSSProperties)
-  props.push(prop);
-props = props.reverse();
-function do_one() {
-  if (props.length == 0) {
-    SimpleTest.finish();
-    return;
+
+function start_test() {
+  for (var prop in gCSSProperties) {
+    test_property(prop);
   }
-  test_property(props.pop());
-  SimpleTest.executeSoon(do_one);
+  SimpleTest.finish();
 }
-SimpleTest.executeSoon(do_one);
+
+// Turn off CSS error reporting for this test, since it's a bit expensive,
+// and we're expecting to generate tons and tons of parse errors here.
+SpecialPowers.pushPrefEnv({ "set": [["layout.css.report_errors", false]] },
+                          start_test);
 
 </script>
 </pre>
diff --git a/layout/style/test/test_transitions_events.html b/layout/style/test/test_transitions_events.html
index 022b8b43e85bfb4a54f1bbc0edbb86b890bc9b06..f7f5308904e0189acc7560df612b094f5192a489 100644
--- a/layout/style/test/test_transitions_events.html
+++ b/layout/style/test/test_transitions_events.html
@@ -212,6 +212,10 @@ $("two").addEventListener("transitionend",
        "propertyName for transitionend on two");
     is(event.elapsedTime, 1,
        "elapsedTime for transitionend on two");
+    is(event.bubbles, true,
+       "transitionend events should bubble");
+    is(event.cancelable, false,
+       "transitionend events should not be cancelable");
     is(cs("two").marginLeft, "10px",
        "computed style for transitionend on two");
     got_two_target = true;
diff --git a/layout/xul/moz.build b/layout/xul/moz.build
index 2c9ff9a6e33a430539473af39db252e130d66a59..15be1021db2771276ac46b55949a62c110bdcbe6 100644
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -87,10 +87,10 @@ MSVC_ENABLE_PGO = True
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '../../content/base/src',
-    '../../content/events/src',
     '../base',
     '../generic',
     '../style',
+    '/content/base/src',
+    '/dom/events',
 ]
 
diff --git a/layout/xul/tree/moz.build b/layout/xul/tree/moz.build
index 920a4e6417ad21c3531b230cfbfbdc46683272b2..de93620e760709e479627dd8398af4f77d1bc98c 100644
--- a/layout/xul/tree/moz.build
+++ b/layout/xul/tree/moz.build
@@ -41,6 +41,6 @@ LOCAL_INCLUDES += [
     '../../generic',
     '../../style',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
 ]
 
diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
index ac87e3c49699f3f912107e00a7b03af114c3dda5..7a5b365500eafb549587e71de9b8c4418e9bbc0e 100644
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -502,8 +502,14 @@ PeerConnectionImpl::~PeerConnectionImpl()
   CloseInt();
 
 #ifdef MOZILLA_INTERNAL_API
-  // Deregister as an NSS Shutdown Object
-  shutdown(calledFromObject);
+  {
+    // Deregister as an NSS Shutdown Object
+    nsNSSShutDownPreventionLock locker;
+    if (!isAlreadyShutDown()) {
+      destructorSafeDestroyNSSReference();
+      shutdown(calledFromObject);
+    }
+  }
 #endif
 
   // Since this and Initialize() occur on MainThread, they can't both be
@@ -1611,6 +1617,12 @@ PeerConnectionImpl::ShutdownMedia()
 // finally deallocate it in our destructor.
 void
 PeerConnectionImpl::virtualDestroyNSSReference()
+{
+  destructorSafeDestroyNSSReference();
+}
+
+void
+PeerConnectionImpl::destructorSafeDestroyNSSReference()
 {
   MOZ_ASSERT(NS_IsMainThread());
   CSFLogDebug(logTag, "%s: NSS shutting down; freeing our DtlsIdentity.", __FUNCTION__);
diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
index f9fabf38c7f4db29a904c7a0b3e25471c40f5041..fcfbcb6fd8a64788bc5cb7b9357c7bdf92c22789 100644
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -523,6 +523,7 @@ private:
 
 #ifdef MOZILLA_INTERNAL_API
   void virtualDestroyNSSReference() MOZ_FINAL;
+  void destructorSafeDestroyNSSReference();
   nsresult GetTimeSinceEpoch(DOMHighResTimeStamp *result);
 #endif
 
diff --git a/memory/build/malloc_decls.h b/memory/build/malloc_decls.h
index 4c0ab714add1ebe8a1b82d811ea5b019bae6edb5..e46cf593b8766edb8d6a656f22286c8997311773 100644
--- a/memory/build/malloc_decls.h
+++ b/memory/build/malloc_decls.h
@@ -15,7 +15,7 @@
 
 #  include "jemalloc_types.h"
 
-#  if defined(__linux__) || (defined(MOZ_MEMORY_ANDROID) && (ANDROID_VERSION < 19))
+#  if defined(__linux__) && (!defined(MOZ_MEMORY_ANDROID) || ANDROID_VERSION < 19)
 typedef void * usable_ptr_t;
 #  else
 typedef const void * usable_ptr_t;
diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini
index 2a2f5b11b6f76aa73fa1be48ef245afa178bd4ed..b385d46b81e858c365e9af6fcece7718b58541f9 100644
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -28,6 +28,8 @@ skip-if = processor == "x86"
 [testGetUserMedia]
 # [testHistory] # see bug 915350
 [testHomeBanner]
+# disabled on x86 only; bug 957185
+skip-if = processor == "x86"
 [testImportFromAndroid]
 # disabled on x86 only; bug 900664
 skip-if = processor == "x86"
@@ -50,6 +52,8 @@ skip-if = processor == "x86"
 [testPrefsObserver]
 [testPrivateBrowsing]
 [testPromptGridInput]
+# disabled on x86 only; bug 957185
+skip-if = processor == "x86"
 # [testReaderMode] # see bug 913254
 # disabled on x86 only; bug 936224
 # skip-if = processor == "x86"
diff --git a/mozglue/linker/Mappable.cpp b/mozglue/linker/Mappable.cpp
index 8b6aa5a1c37856fe12069b8f2e262738f958d18b..49dc22d351f979574ea458292b35c9ba407a4eab 100644
--- a/mozglue/linker/Mappable.cpp
+++ b/mozglue/linker/Mappable.cpp
@@ -14,6 +14,7 @@
 #include <linux/ashmem.h>
 #endif
 #include <sys/stat.h>
+#include <errno.h>
 #include "ElfLoader.h"
 #include "SeekableZStream.h"
 #include "Logging.h"
@@ -556,10 +557,13 @@ MappableSeekableZStream::ensure(const void *addr)
   length = reinterpret_cast<uintptr_t>(end)
            - reinterpret_cast<uintptr_t>(start);
 
-  DEBUG_LOG("mprotect @%p, 0x%" PRIxSize ", 0x%x", start, length, map->prot);
-  if (mprotect(const_cast<void *>(start), length, map->prot) == 0)
+  if (mprotect(const_cast<void *>(start), length, map->prot) == 0) {
+    DEBUG_LOG("mprotect @%p, 0x%" PRIxSize ", 0x%x", start, length, map->prot);
     return true;
+  }
 
+  LOG("mprotect @%p, 0x%" PRIxSize ", 0x%x failed with errno %d",
+      start, length, map->prot, errno);
   LOG("mprotect failed");
   return false;
 }
diff --git a/netwerk/base/src/BackgroundFileSaver.cpp b/netwerk/base/src/BackgroundFileSaver.cpp
index 12c21d441544a62d46f31ebb5876283b27f91a07..3741e0854203928fe758f35a2179df5779f2c8b0 100644
--- a/netwerk/base/src/BackgroundFileSaver.cpp
+++ b/netwerk/base/src/BackgroundFileSaver.cpp
@@ -96,6 +96,10 @@ BackgroundFileSaver::BackgroundFileSaver()
 
 BackgroundFileSaver::~BackgroundFileSaver()
 {
+  nsNSSShutDownPreventionLock lock;
+  if (isAlreadyShutDown()) {
+    return;
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -103,10 +107,6 @@ BackgroundFileSaver::~BackgroundFileSaver()
 void
 BackgroundFileSaver::destructorSafeDestroyNSSReference()
 {
-  nsNSSShutDownPreventionLock lock;
-  if (isAlreadyShutDown()) {
-    return;
-  }
   if (mDigestContext) {
     mozilla::psm::PK11_DestroyContext_true(mDigestContext.forget());
     mDigestContext = nullptr;
diff --git a/netwerk/protocol/http/moz.build b/netwerk/protocol/http/moz.build
index ebb0ad4419a6954e63659035b3400708c134c2f7..f87ef4e24adf28fb270610e1785eba1bed74e321 100644
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -110,6 +110,6 @@ FINAL_LIBRARY = 'necko'
 LOCAL_INCLUDES += [
     '../../base/src',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/xpcom/ds',
 ]
diff --git a/netwerk/protocol/rtsp/moz.build b/netwerk/protocol/rtsp/moz.build
index f9dcee0bf2d468e28599a48f694fa44974ea709b..c0220867139b828f41615157b266cd8e225feb9a 100644
--- a/netwerk/protocol/rtsp/moz.build
+++ b/netwerk/protocol/rtsp/moz.build
@@ -55,7 +55,7 @@ DEFINES['FORCE_PR_LOG'] = True
 LOCAL_INCLUDES += [
     '../../base/src',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/xpcom/ds',
     'controller',
     'rtsp',
diff --git a/netwerk/protocol/websocket/moz.build b/netwerk/protocol/websocket/moz.build
index a2d79b25ee0505523c5f1113d3ab7a1ee93c5007..6e7ba8008e4b6a09ee791f8ecb75db80e5e4d57b 100644
--- a/netwerk/protocol/websocket/moz.build
+++ b/netwerk/protocol/websocket/moz.build
@@ -42,6 +42,6 @@ FINAL_LIBRARY = 'necko'
 LOCAL_INCLUDES += [
     '../../base/src',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/xpcom/ds',
 ]
diff --git a/netwerk/sctp/src/moz.build b/netwerk/sctp/src/moz.build
index 33b1663047962a3d4e4076e9e37c16df0bf6e145..9bc79850f3cceab4bd16505c98027da9026a4dc9 100644
--- a/netwerk/sctp/src/moz.build
+++ b/netwerk/sctp/src/moz.build
@@ -50,7 +50,7 @@ FINAL_LIBRARY = 'necko'
 LOCAL_INCLUDES += [
     '../../base/src',
     '/content/base/src',
-    '/content/events/src',
+    '/dom/events',
     '/xpcom/ds',
 ]
 
diff --git a/python/lldbutils/lldbutils/__init__.py b/python/lldbutils/lldbutils/__init__.py
index 1552d5f0bb4b4d7680f43d0331366134872123b7..23f1e05dc207a4937a3f45e25abb0320f5bfdd15 100644
--- a/python/lldbutils/lldbutils/__init__.py
+++ b/python/lldbutils/lldbutils/__init__.py
@@ -1,7 +1,13 @@
 import lldb
 
-__all__ = ['layout']
+__all__ = ['content', 'general', 'layout', 'utils']
 
 def init():
     for name in __all__:
-        __import__('lldbutils.' + name, globals(), locals(), ['init']).init(lldb.debugger)
+        init = None
+        try:
+            init = __import__('lldbutils.' + name, globals(), locals(), ['init']).init
+        except AttributeError:
+            pass
+        if init:
+            init(lldb.debugger)
diff --git a/python/lldbutils/lldbutils/content.py b/python/lldbutils/lldbutils/content.py
new file mode 100644
index 0000000000000000000000000000000000000000..020ba71ac4cb4dd0bc3b8a88ca4a6e0fd66a6f84
--- /dev/null
+++ b/python/lldbutils/lldbutils/content.py
@@ -0,0 +1,16 @@
+import lldb
+from lldbutils import utils
+
+def summarize_text_fragment(valobj, internal_dict):
+    content_union = valobj.GetChildAtIndex(0)
+    state_union = valobj.GetChildAtIndex(1).GetChildMemberWithName("mState")
+    length = state_union.GetChildMemberWithName("mLength").GetValueAsUnsigned(0)
+    if state_union.GetChildMemberWithName("mIs2b").GetValueAsUnsigned(0):
+        field = "m2b"
+    else:
+        field = "m1b"
+    ptr = content_union.GetChildMemberWithName(field)
+    return utils.format_string(ptr, length)
+
+def init(debugger):
+    debugger.HandleCommand("type summary add nsTextFragment -F lldbutils.content.summarize_text_fragment")
diff --git a/python/lldbutils/lldbutils/general.py b/python/lldbutils/lldbutils/general.py
new file mode 100644
index 0000000000000000000000000000000000000000..158ecf44f64cfc0155c78484587d3874cf81ad5e
--- /dev/null
+++ b/python/lldbutils/lldbutils/general.py
@@ -0,0 +1,42 @@
+import lldb
+from lldbutils import utils
+
+def summarize_string(valobj, internal_dict):
+    data = valobj.GetChildMemberWithName("mData")
+    length = valobj.GetChildMemberWithName("mLength").GetValueAsUnsigned(0)
+    return utils.format_string(data, length)
+
+class TArraySyntheticChildrenProvider:
+    def __init__(self, valobj, internal_dict):
+        self.valobj = valobj
+        self.header = self.valobj.GetChildMemberWithName("mHdr")
+        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
+        self.element_size = self.element_type.GetByteSize()
+        header_size = self.header.GetType().GetPointeeType().GetByteSize()
+        self.element_base_addr = self.header.GetValueAsUnsigned(0) + header_size
+
+    def num_children(self):
+        return self.header.Dereference().GetChildMemberWithName("mLength").GetValueAsUnsigned(0)
+
+    def get_child_index(self, name):
+        try:
+            index = int(name)
+            if index >= self.num_children():
+                return None
+        except:
+            pass
+        return None
+
+    def get_child_at_index(self, index):
+        if index >= self.num_children():
+            return None
+        addr = self.element_base_addr + index * self.element_size
+        return self.valobj.CreateValueFromAddress("[%d]" % index, addr, self.element_type)
+
+def init(debugger):
+    debugger.HandleCommand("type summary add nsAString_internal -F lldbutils.general.summarize_string")
+    debugger.HandleCommand("type summary add nsACString_internal -F lldbutils.general.summarize_string")
+    debugger.HandleCommand("type synthetic add -x \"nsTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
+    debugger.HandleCommand("type synthetic add -x \"nsAutoTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
+    debugger.HandleCommand("type synthetic add -x \"FallibleTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
+    debugger.HandleCommand("type synthetic add -x \"AutoFallibleTArray<\" -l lldbutils.general.TArraySyntheticChildrenProvider")
diff --git a/python/lldbutils/lldbutils/utils.py b/python/lldbutils/lldbutils/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..73ee25ddff5506956b12712559f9fd883965bad3
--- /dev/null
+++ b/python/lldbutils/lldbutils/utils.py
@@ -0,0 +1,58 @@
+def format_char(c):
+    if c == 0:
+        return "\\0"
+    elif c == 0x07:
+        return "\\a"
+    elif c == 0x08:
+        return "\\b"
+    elif c == 0x0c:
+        return "\\f"
+    elif c == 0x0a:
+        return "\\n"
+    elif c == 0x0d:
+        return "\\r"
+    elif c == 0x09:
+        return "\\t"
+    elif c == 0x0b:
+        return "\\v"
+    elif c == 0x5c:
+        return "\\"
+    elif c == 0x22:
+        return "\\\""
+    elif c == 0x39:
+        return "\\'"
+    elif c < 0x20 or c >= 0x80 and c <= 0xff:
+        return "\\x%02x" % c
+    elif c >= 0x0100:
+        return "\\u%04x" % c
+    else:
+        return chr(c)
+
+# Take an SBValue that is either a char* or char16_t* and formats it like lldb
+# would when printing it.
+def format_string(lldb_value, length=100):
+    ptr = lldb_value.GetValueAsUnsigned(0)
+    char_type = lldb_value.GetType().GetPointeeType()
+    if char_type.GetByteSize() == 1:
+        s = "\""
+        size = 1
+        mask = 0xff
+    elif char_type.GetByteSize() == 2:
+        s = "u\""
+        size = 2
+        mask = 0xffff
+    else:
+        return "(cannot format string with char type %s)" % char_type.GetName()
+    i = 0
+    terminated = False
+    while i < length:
+        c = lldb_value.CreateValueFromAddress("x", ptr + i * size, char_type).GetValueAsUnsigned(0) & mask
+        if c == 0:
+            terminated = True
+            break
+        s += format_char(c)
+        i = i + 1
+    s += "\""
+    if not terminated and i != length:
+        s += "..."
+    return s
diff --git a/security/manager/ssl/src/nsCMS.cpp b/security/manager/ssl/src/nsCMS.cpp
index a7ffb6d9cbf0ac61c2d3ba937ffdaed9e46e1cb4..ce59a8e9c2facd637640de5e6d49fe9cf7e1ce27 100644
--- a/security/manager/ssl/src/nsCMS.cpp
+++ b/security/manager/ssl/src/nsCMS.cpp
@@ -41,9 +41,9 @@ nsCMSMessage::nsCMSMessage(NSSCMSMessage *aCMSMsg)
 nsCMSMessage::~nsCMSMessage()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -55,9 +55,6 @@ void nsCMSMessage::virtualDestroyNSSReference()
 
 void nsCMSMessage::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (m_cmsMsg) {
     NSS_CMSMessage_Destroy(m_cmsMsg);
   }
@@ -384,9 +381,9 @@ public:
   ~nsZeroTerminatedCertArray()
   {
     nsNSSShutDownPreventionLock locker;
-    if (isAlreadyShutDown())
+    if (isAlreadyShutDown()) {
       return;
-
+    }
     destructorSafeDestroyNSSReference();
     shutdown(calledFromObject);
   }
@@ -398,9 +395,6 @@ public:
 
   void destructorSafeDestroyNSSReference()
   {
-    if (isAlreadyShutDown())
-      return;
-
     if (mCerts)
     {
       for (uint32_t i=0; i < mSize; i++) {
@@ -733,9 +727,9 @@ nsCMSDecoder::nsCMSDecoder()
 nsCMSDecoder::~nsCMSDecoder()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -747,9 +741,6 @@ void nsCMSDecoder::virtualDestroyNSSReference()
 
 void nsCMSDecoder::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (m_dcx) {
     NSS_CMSDecoder_Cancel(m_dcx);
     m_dcx = nullptr;
@@ -819,9 +810,9 @@ nsCMSEncoder::nsCMSEncoder()
 nsCMSEncoder::~nsCMSEncoder()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -833,10 +824,6 @@ void nsCMSEncoder::virtualDestroyNSSReference()
 
 void nsCMSEncoder::destructorSafeDestroyNSSReference()
 {
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
-    return;
-
   if (m_ecx)
     NSS_CMSEncoder_Cancel(m_ecx);
 }
diff --git a/security/manager/ssl/src/nsCryptoHash.cpp b/security/manager/ssl/src/nsCryptoHash.cpp
index 9554bf8fa048cdde6d337130ebb0b6ddb5960803..b8e000b932cf7c4a2380dbd8f86017ffa78fdcc0 100644
--- a/security/manager/ssl/src/nsCryptoHash.cpp
+++ b/security/manager/ssl/src/nsCryptoHash.cpp
@@ -36,10 +36,9 @@ nsCryptoHash::nsCryptoHash()
 nsCryptoHash::~nsCryptoHash()
 {
   nsNSSShutDownPreventionLock locker;
-
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -51,9 +50,6 @@ void nsCryptoHash::virtualDestroyNSSReference()
 
 void nsCryptoHash::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mHashContext)
     HASH_Destroy(mHashContext);
   mHashContext = nullptr;
@@ -222,10 +218,9 @@ nsCryptoHMAC::nsCryptoHMAC()
 nsCryptoHMAC::~nsCryptoHMAC()
 {
   nsNSSShutDownPreventionLock locker;
-
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -237,9 +232,6 @@ void nsCryptoHMAC::virtualDestroyNSSReference()
 
 void nsCryptoHMAC::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mHMACContext)
     PK11_DestroyContext(mHMACContext, true);
   mHMACContext = nullptr;
diff --git a/security/manager/ssl/src/nsNSSCertCache.cpp b/security/manager/ssl/src/nsNSSCertCache.cpp
index 9f0ebb406b9a7fbe013407bd844a256083fb7bfd..b182e02a6a38e084374774a894a9972c8686b94f 100644
--- a/security/manager/ssl/src/nsNSSCertCache.cpp
+++ b/security/manager/ssl/src/nsNSSCertCache.cpp
@@ -21,9 +21,9 @@ nsNSSCertCache::nsNSSCertCache()
 nsNSSCertCache::~nsNSSCertCache()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -35,8 +35,7 @@ void nsNSSCertCache::virtualDestroyNSSReference()
 
 void nsNSSCertCache::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
+  mCertList = nullptr;
 }
 
 NS_IMETHODIMP
diff --git a/security/manager/ssl/src/nsNSSCertificate.cpp b/security/manager/ssl/src/nsNSSCertificate.cpp
index 11e279fd89b51fc02fd5580cb69257133be5298f..533964724bca36e421870825b72cb8de69050193 100644
--- a/security/manager/ssl/src/nsNSSCertificate.cpp
+++ b/security/manager/ssl/src/nsNSSCertificate.cpp
@@ -172,9 +172,9 @@ nsNSSCertificate::nsNSSCertificate() :
 nsNSSCertificate::~nsNSSCertificate()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -186,9 +186,6 @@ void nsNSSCertificate::virtualDestroyNSSReference()
 
 void nsNSSCertificate::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mPermDelete) {
     if (mCertType == nsNSSCertificate::USER_CERT) {
       nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
@@ -1512,6 +1509,9 @@ nsNSSCertList::nsNSSCertList(CERTCertList *certList,
 nsNSSCertList::~nsNSSCertList()
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return;
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -1523,9 +1523,6 @@ void nsNSSCertList::virtualDestroyNSSReference()
 
 void nsNSSCertList::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown()) {
-    return;
-  }
   if (mCertList) {
     mCertList = nullptr;
   }
@@ -1649,6 +1646,9 @@ nsNSSCertListEnumerator::nsNSSCertListEnumerator(CERTCertList *certList,
 nsNSSCertListEnumerator::~nsNSSCertListEnumerator()
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return;
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -1660,9 +1660,6 @@ void nsNSSCertListEnumerator::virtualDestroyNSSReference()
 
 void nsNSSCertListEnumerator::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown()) {
-    return;
-  }
   if (mCertList) {
     mCertList = nullptr;
   }
diff --git a/security/manager/ssl/src/nsNSSShutDown.h b/security/manager/ssl/src/nsNSSShutDown.h
index 100ede478c5238466175e6f619784b3e678570ec..c6de7dfd3a711d79e74af58db30740248d7d6009 100644
--- a/security/manager/ssl/src/nsNSSShutDown.h
+++ b/security/manager/ssl/src/nsNSSShutDown.h
@@ -185,21 +185,22 @@ protected:
   class, and make the implementation of virtualDestroyNSSReference()
   call destructorSafeDestroyNSSReference().
 
-  The destructor of the derived class should call 
-  destructorSafeDestroyNSSReference() and afterwards call
-  shutdown(calledFromObject), in order to deregister with the
-  tracking list, to ensure no additional attempt to free the resources
+  The destructor of the derived class must prevent NSS shutdown on
+  another thread by acquiring an nsNSSShutDownPreventionLock. It must
+  then check to see if NSS has already been shut down by calling
+  isAlreadyShutDown(). If NSS has not been shut down, the destructor
+  must then call destructorSafeDestroyNSSReference() and then
+  shutdown(calledFromObject). The second call will deregister with
+  the tracking list, to ensure no additional attempt to free the resources
   will be made.
-  
-  Function destructorSafeDestroyNSSReference() must
-  also ensure, that NSS resources have not been freed already.
-  To achieve this, the deriving class should call 
-  isAlreadyShutDown() to check.
-  
-  It is important that you make your implementation
-  failsafe, and check whether the resources have already been freed,
-  in each function that requires the resources.
-  
+
+  destructorSafeDestroyNSSReference() does not need to acquire an
+  nsNSSShutDownPreventionLock or check isAlreadyShutDown() as long as it
+  is only called by the destructor that has already acquired the lock and
+  checked for shutdown or by the NSS shutdown code itself (which acquires
+  the same lock and checks if objects it cleans up have already cleaned
+  up themselves).
+
   class derivedClass : public nsISomeInterface,
                        public nsNSSShutDownObject
   {
@@ -210,14 +211,15 @@ protected:
     
     void destructorSafeDestroyNSSReference()
     {
-      if (isAlreadyShutDown())
-        return;
-      
       // clean up all NSS resources here
     }
 
     virtual ~derivedClass()
     {
+      nsNSSShutDownPreventionLock locker;
+      if (isAlreadyShutDown()) {
+        return;
+      }
       destructorSafeDestroyNSSReference();
       shutdown(calledFromObject);
     }
diff --git a/security/manager/ssl/src/nsPK11TokenDB.cpp b/security/manager/ssl/src/nsPK11TokenDB.cpp
index bdf2f382cdc43999a0fd377f5f905b3b099289f9..8b3882c8849dc96b1e0330bfd56a04d1524e4359 100644
--- a/security/manager/ssl/src/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/src/nsPK11TokenDB.cpp
@@ -83,9 +83,9 @@ nsPK11Token::refreshTokenInfo()
 nsPK11Token::~nsPK11Token()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -97,9 +97,6 @@ void nsPK11Token::virtualDestroyNSSReference()
 
 void nsPK11Token::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mSlot) {
     PK11_FreeSlot(mSlot);
     mSlot = nullptr;
diff --git a/security/manager/ssl/src/nsPKCS11Slot.cpp b/security/manager/ssl/src/nsPKCS11Slot.cpp
index 6df0ae8ea4ea02481706d291156d3fcf5858e0b1..ae70ce34f0f396f7fa8625cc18897e0b60a06e14 100644
--- a/security/manager/ssl/src/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/src/nsPKCS11Slot.cpp
@@ -67,9 +67,9 @@ nsPKCS11Slot::refreshSlotInfo()
 nsPKCS11Slot::~nsPKCS11Slot()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -81,9 +81,6 @@ void nsPKCS11Slot::virtualDestroyNSSReference()
 
 void nsPKCS11Slot::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mSlot) {
     PK11_FreeSlot(mSlot);
     mSlot = nullptr;
@@ -241,9 +238,9 @@ nsPKCS11Module::nsPKCS11Module(SECMODModule *module)
 nsPKCS11Module::~nsPKCS11Module()
 {
   nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown())
+  if (isAlreadyShutDown()) {
     return;
-
+  }
   destructorSafeDestroyNSSReference();
   shutdown(calledFromObject);
 }
@@ -255,9 +252,6 @@ void nsPKCS11Module::virtualDestroyNSSReference()
 
 void nsPKCS11Module::destructorSafeDestroyNSSReference()
 {
-  if (isAlreadyShutDown())
-    return;
-
   if (mModule) {
     SECMOD_DestroyModule(mModule);
     mModule = nullptr;
diff --git a/security/manager/ssl/tests/unit/test_ev_certs.js b/security/manager/ssl/tests/unit/test_ev_certs.js
index fdd685c38cff979ef723e12a4fdb7d8fbf3e834f..8dcac06d71dadb245e466e5f5de475cdb29663ec 100644
--- a/security/manager/ssl/tests/unit/test_ev_certs.js
+++ b/security/manager/ssl/tests/unit/test_ev_certs.js
@@ -5,6 +5,9 @@
 
 "use strict";
 
+// XXX: The isDebugBuild tests you see are here because the test EV root is
+// only enabled for EV in debug builds, as a security measure. An ugly hack.
+
 do_get_profile(); // must be called before getting nsIX509CertDB
 const certdb = Cc["@mozilla.org/security/x509certdb;1"]
                  .getService(Ci.nsIX509CertDB);
@@ -31,16 +34,28 @@ function load_ca(ca_name) {
   addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
 }
 
-var gHttpServer;
-var gOCSPResponseCounter = 0;
+const SERVER_PORT = 8888;
+
+function failingOCSPResponder() {
+  let httpServer = new HttpServer();
+  httpServer.registerPrefixHandler("/", function(request, response) {
+    do_check_true(false);
+  });
+  httpServer.start(SERVER_PORT);
+  return httpServer;
+}
 
-function start_ocsp_responder() {
-  const SERVER_PORT = 8888;
-  gHttpServer = new HttpServer();
-  gHttpServer.registerPrefixHandler("/",
+function start_ocsp_responder(expectedCertNames) {
+  let httpServer = new HttpServer();
+  httpServer.registerPrefixHandler("/",
       function handleServerCallback(aRequest, aResponse) {
         do_check_neq(aRequest.host, "crl.example.com"); // No CRL checks
         let cert_nick = aRequest.path.slice(1, aRequest.path.length - 1);
+
+        do_check_true(expectedCertNames.length >= 1);
+        let expected_nick = expectedCertNames.shift();
+        do_check_eq(cert_nick, expected_nick);
+
         do_print("Generating ocsp response for '" + cert_nick + "'");
         aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
         aResponse.setHeader("Content-Type", "application/ocsp-response");
@@ -54,11 +69,16 @@ function start_ocsp_responder() {
         let retArray = generateOCSPResponses(arg_array, "test_ev_certs");
         let responseBody = retArray[0];
         aResponse.bodyOutputStream.write(responseBody, responseBody.length);
-        gOCSPResponseCounter++;
       });
-  gHttpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT);
-  gHttpServer.identity.add("http", "crl.example.com", SERVER_PORT);
-  gHttpServer.start(SERVER_PORT);
+  httpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT);
+  httpServer.identity.add("http", "crl.example.com", SERVER_PORT);
+  httpServer.start(SERVER_PORT);
+  return {
+    stop: function(callback) {
+      do_check_eq(expectedCertNames.length, 0);
+      httpServer.stop(callback);
+    }
+  };
 }
 
 function check_cert_err(cert_name, expected_error) {
@@ -77,11 +97,7 @@ function check_ee_for_ev(cert_name, expected_ev) {
     let verifiedChain = {};
     let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
                                      NO_FLAGS, verifiedChain, hasEVPolicy);
-    if (isDebugBuild) {
-      do_check_eq(hasEVPolicy.value, expected_ev);
-    } else {
-      do_check_false(hasEVPolicy.value);
-    }
+    do_check_eq(hasEVPolicy.value, expected_ev);
     do_check_eq(0, error);
 }
 
@@ -97,44 +113,57 @@ function run_test() {
   Services.prefs.setCharPref("network.dns.localDomains",
                              'www.example.com, crl.example.com');
 
-  start_ocsp_responder();
-
   run_next_test();
 }
 
-
 add_test(function() {
-  check_ee_for_ev("ev-valid", true);
-  run_next_test();
+  clearOCSPCache();
+  let ocspResponder = start_ocsp_responder(
+                        isDebugBuild ? ["int-ev-valid", "ev-valid"]
+                                     : ["ev-valid"]);
+  check_ee_for_ev("ev-valid", isDebugBuild);
+  ocspResponder.stop(run_next_test);
 });
 
 add_test(function() {
+  clearOCSPCache();
+  let ocspResponder = start_ocsp_responder(["non-ev-root"]);
   check_ee_for_ev("non-ev-root", false);
-  run_next_test();
+  ocspResponder.stop(run_next_test);
 });
 
 add_test(function() {
+  clearOCSPCache();
+  let ocspResponder = failingOCSPResponder();
   check_ee_for_ev("no-ocsp-url-cert", false);
-  run_next_test();
+  ocspResponder.stop(run_next_test);
 });
 
-// Test for bug 917380
-add_test(function () {
-  const nsIX509Cert = Ci.nsIX509Cert;
+// bug 917380: Chcek that an untrusted EV root is untrusted.
+const nsIX509Cert = Ci.nsIX509Cert;
+add_test(function() {
   let evRootCA = certdb.findCertByNickname(null, evrootnick);
   certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT, 0);
+
+  clearOCSPCache();
+  let ocspResponder = failingOCSPResponder();
   check_cert_err("ev-valid", SEC_ERROR_UNTRUSTED_ISSUER);
+  ocspResponder.stop(run_next_test);
+});
+
+// bug 917380: Chcek that a trusted EV root is trusted after disabling and
+// re-enabling trust.
+add_test(function() {
+  let evRootCA = certdb.findCertByNickname(null, evrootnick);
   certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT,
                       Ci.nsIX509CertDB.TRUSTED_SSL |
                       Ci.nsIX509CertDB.TRUSTED_EMAIL |
                       Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
-  check_ee_for_ev("ev-valid", true);
-  run_next_test();
-});
 
-// The following test should be the last as it performs cleanups
-add_test(function() {
-  do_check_eq(4, gOCSPResponseCounter);
-  gHttpServer.stop(run_next_test);
+  clearOCSPCache();
+  let ocspResponder = start_ocsp_responder(
+                        isDebugBuild ? ["int-ev-valid", "ev-valid"]
+                                     : ["ev-valid"]);
+  check_ee_for_ev("ev-valid", isDebugBuild);
+  ocspResponder.stop(run_next_test);
 });
-
diff --git a/security/manager/ssl/tests/unit/test_ocsp_stapling_with_intermediate.js b/security/manager/ssl/tests/unit/test_ocsp_stapling_with_intermediate.js
new file mode 100644
index 0000000000000000000000000000000000000000..4cf28102b181cc11940d84c2b7d5ea35acea8140
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_with_intermediate.js
@@ -0,0 +1,43 @@
+// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"use strict";
+
+// In which we connect to a server that staples an OCSP response for a
+// certificate signed by an intermediate that has an OCSP AIA to ensure
+// that an OCSP request is not made for the intermediate.
+
+let gOCSPRequestCount = 0;
+
+function add_ocsp_test(aHost, aExpectedResult) {
+  add_connection_test(aHost, aExpectedResult,
+    function() {
+      clearOCSPCache();
+      clearSessionCache();
+    });
+}
+
+function run_test() {
+  do_get_profile();
+  Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
+
+  let ocspResponder = new HttpServer();
+  ocspResponder.registerPrefixHandler("/", function(request, response) {
+    gOCSPRequestCount++;
+    response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
+    let body = "Refusing to return a response";
+    response.bodyOutputStream.write(body, body.length);
+  });
+  ocspResponder.start(8080);
+
+  add_tls_server_setup("OCSPStaplingServer");
+
+  add_ocsp_test("ocsp-stapling-with-intermediate.example.com", Cr.NS_OK);
+  add_test(function() { ocspResponder.stop(run_next_test); });
+  add_test(function() {
+    do_check_eq(gOCSPRequestCount, 0);
+    run_next_test();
+  });
+  run_next_test();
+}
diff --git a/security/manager/ssl/tests/unit/tlsserver/cert8.db b/security/manager/ssl/tests/unit/tlsserver/cert8.db
index 6c82819df43f97267ab26d670f22b4487a471436..ac0939405ba15d6f36089591a35b411aab673c5d 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/cert8.db and b/security/manager/ssl/tests/unit/tlsserver/cert8.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
index 0d1b77f18d55f83e17245db230332459fd03b31a..5316752d19b62fda55cb3a1ca660b4a68146dda5 100644
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -35,6 +35,7 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-trylater.example.com", ORTTryLater, nullptr },
   { "ocsp-stapling-needssig.example.com", ORTNeedsSig, nullptr },
   { "ocsp-stapling-unauthorized.example.com", ORTUnauthorized, nullptr },
+  { "ocsp-stapling-with-intermediate.example.com", ORTGood, "ocspEEWithIntermediate" },
   { nullptr, ORTNull, nullptr }
 };
 
@@ -52,9 +53,17 @@ DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
     fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName);
   }
 
+  const char *certNickname;
+  if (strcmp(host->mHostName,
+             "ocsp-stapling-with-intermediate.example.com") == 0) {
+    certNickname = host->mAdditionalCertName;
+  } else {
+    certNickname = DEFAULT_CERT_NICKNAME;
+  }
+
   ScopedCERTCertificate cert;
   SSLKEAType certKEA;
-  if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, DEFAULT_CERT_NICKNAME,
+  if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, certNickname,
                                                     &cert, &certKEA)) {
     return SSL_SNI_SEND_ALERT;
   }
diff --git a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
index a70dc412a4115afb6f0a3c65791738b2a23467ba..a7cd8ab918674b2b13de18259ce7a04196238536 100755
--- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
+++ b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
@@ -59,7 +59,7 @@ $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -N -f $PASSWORD_FILE
 COMMON_ARGS="-v 360 -w -1 -2 -z $NOISE_FILE"
 
 function make_CA {
-  CA_RESPONSES="y\n0\ny"
+  CA_RESPONSES="y\n1\ny"
   NICKNAME="${1}"
   SUBJECT="${2}"
   DERFILE="${3}"
@@ -74,7 +74,24 @@ function make_CA {
 
 SERIALNO=1
 
-function make_cert {
+function make_INT {
+  INT_RESPONSES="y\n0\ny\n2\n7\nhttp://localhost:8080/\n\nn\nn\n"
+  NICKNAME="${1}"
+  SUBJECT="${2}"
+  CA="${3}"
+
+  echo -e "$INT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S \
+                                                    -n $NICKNAME \
+                                                    -s "$SUBJECT" \
+                                                    -c $CA \
+                                                    -t ",," \
+                                                    -m $SERIALNO \
+                                                    --extAIA \
+                                                    $COMMON_ARGS
+  SERIALNO=$(($SERIALNO + 1))
+}
+
+function make_EE {
   CERT_RESPONSES="n\n\ny\n2\n7\nhttp://localhost:8080/\n\nn\nn\n"
   NICKNAME="${1}"
   SUBJECT="${2}"
@@ -98,10 +115,13 @@ function make_cert {
 
 make_CA testCA 'CN=Test CA' test-ca.der
 make_CA otherCA 'CN=Other test CA' other-test-ca.der
-make_cert localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com"
+make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com"
 # A cert that is like localhostAndExampleCom, but with a different serial number for
 # testing the "OCSP response is from the right issuer, but it is for the wrong cert"
 # case.
-make_cert ocspOtherEndEntity 'CN=Other Cert' testCA "localhost,*.example.com"
+make_EE ocspOtherEndEntity 'CN=Other Cert' testCA "localhost,*.example.com"
+
+make_INT testINT 'CN=Test Intermediate' testCA
+make_EE ocspEEWithIntermediate 'CN=Test End-entity with Intermediate' testINT "localhost,*.example.com"
 
 cleanup
diff --git a/security/manager/ssl/tests/unit/tlsserver/key3.db b/security/manager/ssl/tests/unit/tlsserver/key3.db
index 4ccb58b7b73ea4bb8524451b013eb58005b7fa23..2d4698c8d1bedeec2aecfc114b31b546d0f9004f 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/key3.db and b/security/manager/ssl/tests/unit/tlsserver/key3.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
index b31ad5a3f844bbc02ff126173a03a3e2578642f6..4161f2bd76f0b97c2f9079641b96adc62bacc4d0 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/secmod.db b/security/manager/ssl/tests/unit/tlsserver/secmod.db
index a5f2f603a72865b8a22beb933932e44338599699..3dced7b9ece589b22ede0c537c179c08ba79fd55 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/secmod.db and b/security/manager/ssl/tests/unit/tlsserver/secmod.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/test-ca.der b/security/manager/ssl/tests/unit/tlsserver/test-ca.der
index 7d2283830dce7ba3caa86a517432381bffe9ab97..36cfcddcfb5a3363e425fa7a24cbaf5ce3622521 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/test-ca.der differ
diff --git a/security/manager/ssl/tests/unit/xpcshell.ini b/security/manager/ssl/tests/unit/xpcshell.ini
index ecb3798ae79af241c86c6283ccb09eeb907eb9ff..a62feabbd4d5cba81b09f21e9575d40a3520383c 100644
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -37,6 +37,10 @@ fail-if = os == "android"
 run-sequentially = hardcoded ports
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
+[test_ocsp_stapling_with_intermediate.js]
+run-sequentially = hardcoded ports
+# Bug 676972: test fails consistently on Android
+fail-if = os == "android"
 [test_ocsp_caching.js]
 run-sequentially = hardcoded ports
 # Bug 676972: test fails consistently on Android
diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep
index 590d1bfaeee3f134b616ff41d59c05c9917afa3c..5182f75552c81540c315e8eb17ce933d5f2039b8 100644
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -10,4 +10,3 @@
  */
 
 #error "Do not include this header file."
-
diff --git a/security/nss/lib/certdb/certi.h b/security/nss/lib/certdb/certi.h
index 82a372a5942a98b36ea145d65b5855b7b0f58a3b..ac7afa4f5bc29e3e409db122a2701463e8b662db 100644
--- a/security/nss/lib/certdb/certi.h
+++ b/security/nss/lib/certdb/certi.h
@@ -261,6 +261,28 @@ void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked);
  */
 void CERT_MapStanError();
 
+/* Like CERT_VerifyCert, except with an additional argument, flags. The
+ * flags are defined immediately below.
+ *
+ * OCSP checking is always skipped when certUsage is certUsageStatusResponder.
+ */
+SECStatus
+cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
+                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
+                         PRUint32 flags, void *wincx, CERTVerifyLog *log);
+
+/* Use the default settings.
+ * cert_VerifyCertWithFlags(..., CERT_VERIFYCERT_USE_DEFAULTS) is equivalent
+ * to CERT_VerifyCert(...);
+ */
+#define CERT_VERIFYCERT_USE_DEFAULTS 0
+
+/* Skip all the OCSP checks during certificate verification, regardless of
+ * the global OCSP settings. By default, certificate |cert| will have its
+ * revocation status checked via OCSP according to the global OCSP settings.
+ */
+#define CERT_VERIFYCERT_SKIP_OCSP 1
+
 /* Interface function for libpkix cert validation engine:
  * cert_verify wrapper. */
 SECStatus
diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
index fbed385eeb5c059132a8fb10669071e01f08df97..6917a254b8e9803224eddc8156daf417a429e207 100644
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -1200,7 +1200,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
 
         /*
          * Check OCSP revocation status, but only if the cert we are checking
-         * is not a status reponder itself.  We only do this in the case
+         * is not a status responder itself. We only do this in the case
          * where we checked the cert chain (above); explicit trust "wins"
          * (avoids status checking, just as it avoids CRL checking) by
          * bypassing this code.
@@ -1234,11 +1234,20 @@ SECStatus
 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
 		PRBool checkSig, SECCertUsage certUsage, PRTime t,
 		void *wincx, CERTVerifyLog *log)
+{
+    return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
+                                    CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
+}
+
+SECStatus
+cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
+                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
+                         PRUint32 flags, void *wincx, CERTVerifyLog *log)
 {
     SECStatus rv;
     unsigned int requiredKeyUsage;
     unsigned int requiredCertType;
-    unsigned int flags;
+    unsigned int failedFlags;
     unsigned int certType;
     PRBool       trusted;
     PRBool       allowOverride;
@@ -1307,10 +1316,10 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
 	LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
     }
 
-    rv = cert_CheckLeafTrust(cert,certUsage, &flags, &trusted);
+    rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
     if (rv  == SECFailure) {
 	PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
-	LOG_ERROR_OR_EXIT(log,cert,0,flags);
+	LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
     } else if (trusted) {
 	goto done;
     }
@@ -1323,15 +1332,17 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
     }
 
     /*
-     * Check revocation status, but only if the cert we are checking
-     * is not a status reponder itself.  We only do this in the case
-     * where we checked the cert chain (above); explicit trust "wins"
-     * (avoids status checking, just as it avoids CRL checking, which
-     * is all done inside VerifyCertChain) by bypassing this code.
+     * Check revocation status, but only if the cert we are checking is not a
+     * status responder itself and the caller did not ask us to skip the check.
+     * We only do this in the case where we checked the cert chain (above);
+     * explicit trust "wins" (avoids status checking, just as it avoids CRL
+     * checking, which is all done inside VerifyCertChain) by bypassing this
+     * code.
      */
-    statusConfig = CERT_GetStatusConfig(handle);
-    if (certUsage != certUsageStatusResponder && statusConfig != NULL) {
-	if (statusConfig->statusChecker != NULL) {
+    if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
+	certUsage != certUsageStatusResponder) {
+	statusConfig = CERT_GetStatusConfig(handle);
+	if (statusConfig && statusConfig->statusChecker) {
 	    rv = (* statusConfig->statusChecker)(handle, cert,
 							 t, wincx);
 	    if (rv != SECSuccess) {
diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c
index 2e3c7559c566b249c1615e4e56be1bedaaf8599c..f6c8bfeb8ab2326fe3b552fbc4ef7a58d85ec6d1 100644
--- a/security/nss/lib/certhigh/ocsp.c
+++ b/security/nss/lib/certhigh/ocsp.c
@@ -18,6 +18,7 @@
 #include "secasn1.h"
 #include "secder.h"
 #include "cert.h"
+#include "certi.h"
 #include "xconst.h"
 #include "secerr.h"
 #include "secoid.h"
@@ -4184,8 +4185,9 @@ CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
         } else {
             certUsage = certUsageStatusResponder;
         }
-        rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
-                             certUsage, producedAt, pwArg, NULL);
+        rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage,
+                                      producedAt, CERT_VERIFYCERT_SKIP_OCSP,
+                                      pwArg, NULL);
         if (rv != SECSuccess) {
             PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
             goto finish;
diff --git a/security/patches/README b/security/patches/README
index 788bf6a533c46a493ac2080051969b9441bae8d1..533bc9fba72d507d4474ff6778065d30b35c83fd 100644
--- a/security/patches/README
+++ b/security/patches/README
@@ -1,2 +1,5 @@
 This directory contains patches that were added locally
 on top of the NSS release.
+
+bug-950129.patch  Make OCSP fetching policy for OCSP response signing
+                  certificates consistent.
diff --git a/security/patches/bug-950129.patch b/security/patches/bug-950129.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ac68ea141739df13407359c6e523349523cb2df8
--- /dev/null
+++ b/security/patches/bug-950129.patch
@@ -0,0 +1,195 @@
+# HG changeset patch
+# Parent 352d188c67d9fefd82524c4439a5d04679687945
+# User Brian Smith <brian@briansmith.org>
+diff --git a/security/nss/lib/certdb/certi.h b/security/nss/lib/certdb/certi.h
+--- a/security/nss/lib/certdb/certi.h
++++ b/security/nss/lib/certdb/certi.h
+@@ -256,16 +256,38 @@ void ReleaseDPCache(CRLDPCache* dpcache,
+ 
+ /*
+  * map Stan errors into NSS errors
+  * This function examines the stan error stack and automatically sets
+  * PORT_SetError(); to the appropriate SEC_ERROR value.
+  */
+ void CERT_MapStanError();
+ 
++/* Like CERT_VerifyCert, except with an additional argument, flags. The
++ * flags are defined immediately below.
++ *
++ * OCSP checking is always skipped when certUsage is certUsageStatusResponder.
++ */
++SECStatus
++cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
++                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
++                         PRUint32 flags, void *wincx, CERTVerifyLog *log);
++
++/* Use the default settings.
++ * cert_VerifyCertWithFlags(..., CERT_VERIFYCERT_USE_DEFAULTS) is equivalent
++ * to CERT_VerifyCert(...);
++ */
++#define CERT_VERIFYCERT_USE_DEFAULTS 0
++
++/* Skip all the OCSP checks during certificate verification, regardless of
++ * the global OCSP settings. By default, certificate |cert| will have its
++ * revocation status checked via OCSP according to the global OCSP settings.
++ */
++#define CERT_VERIFYCERT_SKIP_OCSP 1
++
+ /* Interface function for libpkix cert validation engine:
+  * cert_verify wrapper. */
+ SECStatus
+ cert_VerifyCertChainPkix(CERTCertificate *cert,
+                          PRBool checkSig,
+                          SECCertUsage     requiredUsage,
+                          PRTime           time,
+                          void            *wincx,
+diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
+--- a/security/nss/lib/certhigh/certvfy.c
++++ b/security/nss/lib/certhigh/certvfy.c
+@@ -1195,17 +1195,17 @@ CERT_VerifyCertificate(CERTCertDBHandle 
+ 
+         if (rv != SECSuccess) {
+             /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
+             INVALID_USAGE();
+         }
+ 
+         /*
+          * Check OCSP revocation status, but only if the cert we are checking
+-         * is not a status reponder itself.  We only do this in the case
++         * is not a status responder itself. We only do this in the case
+          * where we checked the cert chain (above); explicit trust "wins"
+          * (avoids status checking, just as it avoids CRL checking) by
+          * bypassing this code.
+          */
+ 
+         if (PR_FALSE == checkedOCSP) {
+             checkedOCSP = PR_TRUE; /* only check OCSP once */
+             statusConfig = CERT_GetStatusConfig(handle);
+@@ -1230,20 +1230,29 @@ loser:
+     return(valid);
+ }
+ 
+ SECStatus
+ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
+ 		PRBool checkSig, SECCertUsage certUsage, PRTime t,
+ 		void *wincx, CERTVerifyLog *log)
+ {
++    return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
++                                    CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
++}
++
++SECStatus
++cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
++                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
++                         PRUint32 flags, void *wincx, CERTVerifyLog *log)
++{
+     SECStatus rv;
+     unsigned int requiredKeyUsage;
+     unsigned int requiredCertType;
+-    unsigned int flags;
++    unsigned int failedFlags;
+     unsigned int certType;
+     PRBool       trusted;
+     PRBool       allowOverride;
+     SECCertTimeValidity validity;
+     CERTStatusConfig *statusConfig;
+    
+ #ifdef notdef 
+     /* check if this cert is in the Evil list */
+@@ -1302,41 +1311,43 @@ CERT_VerifyCert(CERTCertDBHandle *handle
+ 	PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
+ 	LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage);
+     }
+     if ( !( certType & requiredCertType ) ) {
+ 	PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
+ 	LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
+     }
+ 
+-    rv = cert_CheckLeafTrust(cert,certUsage, &flags, &trusted);
++    rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
+     if (rv  == SECFailure) {
+ 	PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
+-	LOG_ERROR_OR_EXIT(log,cert,0,flags);
++	LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
+     } else if (trusted) {
+ 	goto done;
+     }
+ 
+ 
+     rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
+ 			      t, wincx, log);
+     if (rv != SECSuccess) {
+ 	EXIT_IF_NOT_LOGGING(log);
+     }
+ 
+     /*
+-     * Check revocation status, but only if the cert we are checking
+-     * is not a status reponder itself.  We only do this in the case
+-     * where we checked the cert chain (above); explicit trust "wins"
+-     * (avoids status checking, just as it avoids CRL checking, which
+-     * is all done inside VerifyCertChain) by bypassing this code.
++     * Check revocation status, but only if the cert we are checking is not a
++     * status responder itself and the caller did not ask us to skip the check.
++     * We only do this in the case where we checked the cert chain (above);
++     * explicit trust "wins" (avoids status checking, just as it avoids CRL
++     * checking, which is all done inside VerifyCertChain) by bypassing this
++     * code.
+      */
+-    statusConfig = CERT_GetStatusConfig(handle);
+-    if (certUsage != certUsageStatusResponder && statusConfig != NULL) {
+-	if (statusConfig->statusChecker != NULL) {
++    if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
++	certUsage != certUsageStatusResponder) {
++	statusConfig = CERT_GetStatusConfig(handle);
++	if (statusConfig && statusConfig->statusChecker) {
+ 	    rv = (* statusConfig->statusChecker)(handle, cert,
+ 							 t, wincx);
+ 	    if (rv != SECSuccess) {
+ 		LOG_ERROR_OR_EXIT(log,cert,0,0);
+ 	    }
+ 	}
+     }
+ 
+diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c
+--- a/security/nss/lib/certhigh/ocsp.c
++++ b/security/nss/lib/certhigh/ocsp.c
+@@ -13,16 +13,17 @@
+ #include "prnetdb.h"
+ 
+ #include "seccomon.h"
+ #include "secitem.h"
+ #include "secoidt.h"
+ #include "secasn1.h"
+ #include "secder.h"
+ #include "cert.h"
++#include "certi.h"
+ #include "xconst.h"
+ #include "secerr.h"
+ #include "secoid.h"
+ #include "hasht.h"
+ #include "sechash.h"
+ #include "secasn1.h"
+ #include "plbase64.h"
+ #include "keyhi.h"
+@@ -4179,18 +4180,19 @@ CERT_VerifyOCSPResponseSignature(CERTOCS
+         rv = SECSuccess;
+     } else {
+         SECCertUsage certUsage;
+         if (CERT_IsCACert(signerCert, NULL)) {
+             certUsage = certUsageAnyCA;
+         } else {
+             certUsage = certUsageStatusResponder;
+         }
+-        rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
+-                             certUsage, producedAt, pwArg, NULL);
++        rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage,
++                                      producedAt, CERT_VERIFYCERT_SKIP_OCSP,
++                                      pwArg, NULL);
+         if (rv != SECSuccess) {
+             PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
+             goto finish;
+         }
+     }
+ 
+     rv = ocsp_VerifyResponseSignature(signerCert, signature,
+                                       tbsResponseDataDER,
diff --git a/testing/crashtest/crashtests.list b/testing/crashtest/crashtests.list
index d2af11b4510229f89080f721f0e8f14b6b7f8bc7..60d301e3971b9dc902d3cdad53a2bb3fb4a2a055 100644
--- a/testing/crashtest/crashtests.list
+++ b/testing/crashtest/crashtests.list
@@ -7,7 +7,6 @@ include ../../accessible/tests/crashtests/crashtests.list
 
 include ../../content/base/crashtests/crashtests.list
 include ../../content/canvas/crashtests/crashtests.list
-include ../../content/events/crashtests/crashtests.list
 include ../../content/html/document/crashtests/crashtests.list
 include ../../content/html/content/crashtests/crashtests.list
 include ../../content/svg/content/src/crashtests/crashtests.list
@@ -25,6 +24,7 @@ include ../../docshell/base/crashtests/crashtests.list
 
 include ../../dom/base/crashtests/crashtests.list
 include ../../dom/bindings/crashtests/crashtests.list
+include ../../dom/events/crashtests/crashtests.list
 include ../../dom/indexedDB/crashtests/crashtests.list
 include ../../dom/smil/crashtests/crashtests.list
 include ../../dom/xbl/crashtests/crashtests.list
diff --git a/testing/marionette/client/MANIFEST.in b/testing/marionette/client/MANIFEST.in
index 9e70dc42a2f69b5ce5a17e2b6cdc3cd337ea66d1..5475b667f629510ef29b25b24871342a2b1f7adf 100644
--- a/testing/marionette/client/MANIFEST.in
+++ b/testing/marionette/client/MANIFEST.in
@@ -1,3 +1,4 @@
 recursive-include marionette/touch *.js
 recursive-include marionette/runner/mixins/resources *
 exclude MANIFEST.in
+include requirements.txt
diff --git a/testing/marionette/client/marionette/__init__.py b/testing/marionette/client/marionette/__init__.py
index fa13775e7312711a415fe62d4333e9bb87d960c3..d30605c021e4ac112e3951798cd41df56fb12ffd 100644
--- a/testing/marionette/client/marionette/__init__.py
+++ b/testing/marionette/client/marionette/__init__.py
@@ -10,3 +10,4 @@ from emulator import Emulator
 from errors import *
 from runner import *
 from wait import Wait
+from date_time_value import DateTimeValue
diff --git a/testing/marionette/client/docs/requirements.txt b/testing/marionette/client/requirements.txt
similarity index 69%
rename from testing/marionette/client/docs/requirements.txt
rename to testing/marionette/client/requirements.txt
index 009f75e6a5b3d22b603a730c97b7129e1db483b6..cac871c70c69753d390322db69ac45f7469925ac 100644
--- a/testing/marionette/client/docs/requirements.txt
+++ b/testing/marionette/client/requirements.txt
@@ -1,9 +1,9 @@
-# this is just taken verbatim from the deps list in setup.py
 manifestdestiny
-mozcrash >= 0.5
-mozdevice >= 0.22
 mozhttpd >= 0.5
-moznetwork >= 0.21
 mozprocess >= 0.9
-mozprofile >= 0.7
 mozrunner >= 5.15
+mozdevice >= 0.22
+moznetwork >= 0.21
+mozcrash >= 0.5
+mozprofile >= 0.7
+moztest >= 0.1
diff --git a/testing/marionette/client/setup.py b/testing/marionette/client/setup.py
index daa13d9a13ec0eccfdddae223ba49703f8c9fd5c..e1e1c43c0ea9a500bd422dcab0041ecfa0e17c2b 100644
--- a/testing/marionette/client/setup.py
+++ b/testing/marionette/client/setup.py
@@ -11,11 +11,8 @@ except (OSError, IOError):
     description = ''
 
 # dependencies
-deps = ['manifestdestiny', 'mozhttpd >= 0.5',
-        'mozprocess >= 0.9', 'mozrunner >= 5.15',
-        'mozdevice >= 0.22', 'moznetwork >= 0.21',
-        'mozcrash >= 0.5', 'mozprofile >= 0.7',
-        'moztest >= 0.1']
+with open('requirements.txt') as f:
+    deps = f.read().splitlines()
 
 setup(name='marionette_client',
       version=version,
diff --git a/testing/mochitest/android.json b/testing/mochitest/android.json
index cca8acb7a7635c759f7b87a54980f0ab55605878..317c62e23d3a033cd47106e12229c87c18b765fb 100644
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -43,45 +43,6 @@
  "content/base/test/websocket_hybi/test_send-arraybuffer.html": "",
  "content/base/test/websocket_hybi/test_send-blob.html": "",
  "content/canvas/test/webgl": "bug 865443- seperate suite",
- "content/events/test/test_bug409604.html": "TIMED_OUT",
- "content/events/test/test_bug426082.html": "",
- "content/events/test/test_bug457672.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug502818.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug508479.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug508906.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug517851.htm": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug534833.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug545268.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug547996-1.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug547996-2.xhtml": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug556493.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug574663.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug603008.html": "",
- "content/events/test/test_bug605242.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug607464.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug613634.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug624127.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug635465.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug648573.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug650493.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug656379-1.html": "TIMED_OUT",
- "content/events/test/test_bug656379-2.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug656954.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug659350.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug662678.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667612.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667919-1.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667919-2.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug689564.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug698929.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug741666.html": "",
- "content/events/test/test_clickevent_on_input.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dom_keyboard_event.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dom_mouse_event.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_draggableprop.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dragstart.html": "TIMED_OUT",
- "content/events/test/test_eventctors.html": "CRASH_DUMP, RANDOM",
- "content/events/test": "CRASH_DUMP, RANDOM",
  "content/html/content/test/test_bug209275.xhtml": "TIMED_OUT",
  "content/html/content/test/test_bug481335.xhtml": "TIMED_OUT",
  "content/html/content/test/test_bug514856.html": "",
@@ -124,6 +85,45 @@
  "dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/browser-element/mochitest/test_browserElement_inproc_CloseApp.html": "FAILS, bug 796982",
  "dom/devicestorage": "bug 781789 & bug 782275",
+ "dom/events/test/test_bug409604.html": "TIMED_OUT",
+ "dom/events/test/test_bug426082.html": "",
+ "dom/events/test/test_bug457672.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug502818.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug508479.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug508906.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug517851.htm": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug534833.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug545268.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug547996-1.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug547996-2.xhtml": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug556493.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug574663.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug603008.html": "",
+ "dom/events/test/test_bug605242.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug607464.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug613634.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug624127.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug635465.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug648573.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug650493.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug656379-1.html": "TIMED_OUT",
+ "dom/events/test/test_bug656379-2.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug656954.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug659350.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug662678.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667612.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667919-1.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667919-2.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug689564.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug698929.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug741666.html": "",
+ "dom/events/test/test_clickevent_on_input.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dom_keyboard_event.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dom_mouse_event.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_draggableprop.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dragstart.html": "TIMED_OUT",
+ "dom/events/test/test_eventctors.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test": "CRASH_DUMP, RANDOM",
  "dom/imptests/editing/conformancetest/test_runtest.html": "",
  "dom/imptests/editing/selecttest/test_addRange.html": "bug 775227",
  "dom/imptests/html/webgl": "WebGL",
diff --git a/testing/mochitest/androidx86.json b/testing/mochitest/androidx86.json
index 095a77cceaee957651f7ef7fa05b135c23365c51..44c085768e4c53736d557b5faad7dbe8c511b8b4 100644
--- a/testing/mochitest/androidx86.json
+++ b/testing/mochitest/androidx86.json
@@ -73,45 +73,6 @@
  "content/canvas/test/test_2d.composite.uncovered.image.source-out.html": "x86 only bug 913662",
  "content/canvas/test/test_canvas.html": "x86 only bug 913662",
  "content/canvas/test/webgl": "bug 865443- seperate suite",
- "content/events/test/test_bug409604.html": "TIMED_OUT",
- "content/events/test/test_bug426082.html": "",
- "content/events/test/test_bug457672.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug502818.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug508479.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug508906.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug517851.htm": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug534833.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug545268.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug547996-1.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug547996-2.xhtml": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug556493.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug574663.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug603008.html": "",
- "content/events/test/test_bug605242.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug607464.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug613634.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug624127.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug635465.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug648573.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug650493.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug656379-1.html": "TIMED_OUT",
- "content/events/test/test_bug656379-2.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug656954.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug659350.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug662678.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667612.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667919-1.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug667919-2.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug689564.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug698929.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_bug741666.html": "",
- "content/events/test/test_clickevent_on_input.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dom_keyboard_event.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dom_mouse_event.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_draggableprop.html": "CRASH_DUMP, RANDOM",
- "content/events/test/test_dragstart.html": "TIMED_OUT",
- "content/events/test/test_eventctors.html": "CRASH_DUMP, RANDOM",
- "content/events/test": "CRASH_DUMP, RANDOM",
  "content/html/content/test/forms/test_input_textarea_set_value_no_scroll.html": "x86 only",
  "content/html/content/test/test_bug209275.xhtml": "TIMED_OUT",
  "content/html/content/test/test_bug481335.xhtml": "TIMED_OUT",
@@ -201,6 +162,45 @@
  "dom/datastore/tests/test_readonly.html": "x86 only bug 936226",
  "dom/datastore/tests/test_sync.html": "x86 only bug 936226",
  "dom/devicestorage": "bug 781789 & bug 782275",
+ "dom/events/test/test_bug409604.html": "TIMED_OUT",
+ "dom/events/test/test_bug426082.html": "",
+ "dom/events/test/test_bug457672.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug502818.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug508479.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug508906.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug517851.htm": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug534833.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug545268.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug547996-1.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug547996-2.xhtml": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug556493.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug574663.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug603008.html": "",
+ "dom/events/test/test_bug605242.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug607464.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug613634.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug624127.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug635465.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug648573.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug650493.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug656379-1.html": "TIMED_OUT",
+ "dom/events/test/test_bug656379-2.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug656954.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug659350.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug662678.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667612.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667919-1.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug667919-2.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug689564.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug698929.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_bug741666.html": "",
+ "dom/events/test/test_clickevent_on_input.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dom_keyboard_event.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dom_mouse_event.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_draggableprop.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test/test_dragstart.html": "TIMED_OUT",
+ "dom/events/test/test_eventctors.html": "CRASH_DUMP, RANDOM",
+ "dom/events/test": "CRASH_DUMP, RANDOM",
  "dom/imptests/editing/conformancetest/test_runtest.html": "",
  "dom/imptests/editing/selecttest/test_addRange.html": "bug 775227",
  "dom/imptests/html/webgl": "WebGL",
diff --git a/testing/mochitest/b2g-debug.json b/testing/mochitest/b2g-debug.json
index 590f346ced626b20a5dc78fc014e6a6ff602d334..19a000a053597cbcbefaf68e3cf4231e98449632 100644
--- a/testing/mochitest/b2g-debug.json
+++ b/testing/mochitest/b2g-debug.json
@@ -78,9 +78,9 @@
     "dom/imptests/html/dom/ranges/test_Range-mutations.html":"Test timed out.",
     "dom/encoding/test/test_stringencoding.html":"Test timed out on b2g board",
 
-    "content/events/test/test_bug615597.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug615597.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
 
     "content/html/content/test/test_bug561636.html":"observerservice not working",
     "content/base/test/test_bug548193.html":"observerservice issue",
@@ -154,19 +154,19 @@
     "dom/tests/mochitest/bugs/test_bug504862.html":"showmodaldialog",
     "dom/tests/mochitest/bugs/test_bug61098.html":"showmodaldialog",
 
-    "content/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
-    "content/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
-    "content/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
-    "content/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
+    "dom/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
+    "dom/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
+    "dom/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
+    "dom/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
 
-    "content/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
-    "content/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
-    "content/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
+    "dom/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
+    "dom/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
+    "dom/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
 
-    "content/events/test/test_bug508479.html":"drag event, also fails on Android",
-    "content/events/test/test_dragstart.html":"drag event, also fails on Android",
+    "dom/events/test/test_bug508479.html":"drag event, also fails on Android",
+    "dom/events/test/test_dragstart.html":"drag event, also fails on Android",
 
-    "content/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
+    "dom/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
 
     "content/html/content/test/forms/test_input_file_picker.html":"5 failures out of 139 and timing out, bug 901581",
     "content/html/content/test/forms/test_validation.html":"374 total, bug 901848, no keygen support",
@@ -240,13 +240,6 @@
     "content/base/test/websocket_hybi/test_send-arraybuffer.html":"",
     "content/base/test/websocket_hybi/test_send-blob.html":"",
     "content/canvas/test/webgl/test_webgl_conformance_test_suite.html":"",
-    "content/events/test/test_bug226361.xhtml":"",
-    "content/events/test/test_bug238987.html":"",
-    "content/events/test/test_bug409604.html":"",
-    "content/events/test/test_bug457672.html":"",
-    "content/events/test/test_bug574663.html":"",
-    "content/events/test/test_bug607464.html":"",
-    "content/events/test/test_wheel_default_action.html":"",
     "content/base/test/test_bug682592.html":"",	
     "content/html/document/test/test_bug369370.html":"",
     "content/svg/content/test/test_text_selection.html":"Mouse selection not workin on b2g",
@@ -280,6 +273,14 @@
     "dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html":"",
     "dom/browser-element/":"",
 
+    "dom/events/test/test_bug226361.xhtml":"",
+    "dom/events/test/test_bug238987.html":"",
+    "dom/events/test/test_bug409604.html":"",
+    "dom/events/test/test_bug457672.html":"",
+    "dom/events/test/test_bug574663.html":"",
+    "dom/events/test/test_bug607464.html":"",
+    "dom/events/test/test_wheel_default_action.html":"",
+
     "dom/file/test/test_progress_events.html":"All of these fail fairly regularly with: UnknownError: The operation failed for reasons unrelated to the database itself and not covered by any other error code. at http://mochi.test:8888/tests/dom/file/test/helpers.js:126",
     "dom/file/test/test_request_readyState.html":"",
     "dom/file/test/test_stream_tracking.html":"",
@@ -438,6 +439,8 @@
     "Harness_sanity/test_sanityEventUtils.html": "bug 688052",
     "Harness_sanity/test_sanitySimpletest.html": "bug 688052",
 
+    "content/base/test/csp/test_hash_source.html":"can't use nsICryptoHash in CSPUtils.jsm (child process)",
+
     "content/base/test/csp/test_CSP_bug909029.html": "debug-only failure",
     "content/base/test/test_bug578096.html": "debug-only failure; crash",
     "content/base/test/test_bug827160.html": "debug-only failure",
diff --git a/testing/mochitest/b2g-desktop.json b/testing/mochitest/b2g-desktop.json
index 4f4733b0e128350e2c22de1582f7a290983a28f8..abc703aea6dace4941db7368c69c60edff0ccb6e 100644
--- a/testing/mochitest/b2g-desktop.json
+++ b/testing/mochitest/b2g-desktop.json
@@ -78,9 +78,9 @@
     "dom/imptests/html/dom/ranges/test_Range-mutations.html":"Test timed out.",
     "dom/encoding/test/test_stringencoding.html":"Test timed out on b2g board",
 
-    "content/events/test/test_bug615597.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug615597.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
 
     "content/html/content/test/test_bug561636.html":"observerservice not working",
     "content/base/test/test_bug548193.html":"observerservice issue",
@@ -155,19 +155,19 @@
     "dom/tests/mochitest/bugs/test_bug504862.html":"showmodaldialog",
     "dom/tests/mochitest/bugs/test_bug61098.html":"showmodaldialog",
 
-    "content/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
-    "content/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
-    "content/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
-    "content/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
+    "dom/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
+    "dom/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
+    "dom/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
+    "dom/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
 
-    "content/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
-    "content/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
-    "content/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
+    "dom/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
+    "dom/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
+    "dom/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
 
-    "content/events/test/test_bug508479.html":"drag event, also fails on Android",
-    "content/events/test/test_dragstart.html":"drag event, also fails on Android",
+    "dom/events/test/test_bug508479.html":"drag event, also fails on Android",
+    "dom/events/test/test_dragstart.html":"drag event, also fails on Android",
 
-    "content/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
+    "dom/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
 
     "content/html/content/test/forms/test_input_file_picker.html":"5 failures out of 139 and timing out, bug 901581",
     "content/html/content/test/forms/test_validation.html":"374 total, bug 901848, no keygen support",
@@ -236,13 +236,6 @@
     "content/base/test/websocket_hybi/test_send-arraybuffer.html":"",
     "content/base/test/websocket_hybi/test_send-blob.html":"",
     "content/canvas/test/webgl/test_webgl_conformance_test_suite.html":"",
-    "content/events/test/test_bug226361.xhtml":"",
-    "content/events/test/test_bug238987.html":"",
-    "content/events/test/test_bug409604.html":"",
-    "content/events/test/test_bug457672.html":"",
-    "content/events/test/test_bug574663.html":"",
-    "content/events/test/test_bug607464.html":"",
-    "content/events/test/test_wheel_default_action.html":"",
     "content/base/test/test_bug682592.html":"",
     "content/html/document/test/test_bug369370.html":"",
     "content/svg/content/test/test_text_selection.html":"Mouse selection not workin on b2g",
@@ -277,6 +270,14 @@
     "dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html":"",
     "dom/browser-element/":"",
 
+    "dom/events/test/test_bug226361.xhtml":"",
+    "dom/events/test/test_bug238987.html":"",
+    "dom/events/test/test_bug409604.html":"",
+    "dom/events/test/test_bug457672.html":"",
+    "dom/events/test/test_bug574663.html":"",
+    "dom/events/test/test_bug607464.html":"",
+    "dom/events/test/test_wheel_default_action.html":"",
+
     "dom/file/test/test_progress_events.html":"All of these fail fairly regularly with: UnknownError: The operation failed for reasons unrelated to the database itself and not covered by any other error code. at http://mochi.test:8888/tests/dom/file/test/helpers.js:126",
     "dom/file/test/test_request_readyState.html":"",
     "dom/file/test/test_stream_tracking.html":"",
@@ -414,10 +415,6 @@
     "content/base/test/test_bug557892.html": "Bug 931116, b2g desktop specific, initial triage",
     "content/base/test/test_bug578096.html": "Bug 931116, b2g desktop specific, initial triage",
     "content/base/test/test_copyimage.html": "Bug 931116, b2g desktop specific, initial triage",
-    "content/events/test/test_bug322588.html": "Bug 931116, b2g desktop specific, initial triage",
-    "content/events/test/test_bug493251.html": "Bug 931116, b2g desktop specific, initial triage",
-    "content/events/test/test_bug545268.html": "Bug 931116, b2g desktop specific, initial triage",
-    "content/events/test/test_bug656379-1.html": "Bug 931116, b2g desktop specific, initial triage",
     "content/html/content/test/forms/test_change_event.html": "Bug 931116, b2g desktop specific, initial triage",
     "content/html/content/test/forms/test_input_event.html": "Bug 931116, b2g desktop specific, initial triage",
     "content/html/content/test/forms/test_input_range_key_events.html": "Bug 931116, b2g desktop specific, initial triage",
@@ -470,6 +467,10 @@
     "dom/datastore/tests/test_readonly.html": "Bug 931116, b2g desktop specific, initial triage",
     "dom/datastore/tests/test_revision.html": "Bug 931116, b2g desktop specific, initial triage",
     "dom/datastore/tests/test_sync.html": "Bug 931116, b2g desktop specific, initial triage",
+    "dom/events/test/test_bug322588.html": "Bug 931116, b2g desktop specific, initial triage",
+    "dom/events/test/test_bug493251.html": "Bug 931116, b2g desktop specific, initial triage",
+    "dom/events/test/test_bug545268.html": "Bug 931116, b2g desktop specific, initial triage",
+    "dom/events/test/test_bug656379-1.html": "Bug 931116, b2g desktop specific, initial triage",
     "dom/indexedDB/test/test_add_put.html": "Bug 931116, b2g desktop specific, initial triage",
     "dom/indexedDB/test/test_add_twice_failure.html": "Bug 931116, b2g desktop specific, initial triage",
     "dom/indexedDB/test/test_advance.html": "Bug 931116, b2g desktop specific, initial triage",
diff --git a/testing/mochitest/b2g.json b/testing/mochitest/b2g.json
index b2d8ae53837d2229f73560afe5d2e8e8374a97b9..236646fafbe98fe3ff44e831ef88943b77c40a56 100644
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -77,10 +77,19 @@
     "dom/imptests/html/dom/ranges/test_Range-surroundContents.html":"",
     "dom/imptests/html/dom/ranges/test_Range-mutations.html":"Test timed out.",
     "dom/encoding/test/test_stringencoding.html":"Test timed out on b2g board",
-
-    "content/events/test/test_bug615597.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
-    "content/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug615597.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
+    "dom/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
+    "dom/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
+    "dom/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
+    "dom/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
+    "dom/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
+    "dom/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
+    "dom/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
+    "dom/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
+    "dom/events/test/test_bug508479.html":"drag event, also fails on Android",
+    "dom/events/test/test_dragstart.html":"drag event, also fails on Android",
+    "dom/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
 
     "content/html/content/test/test_bug561636.html":"observerservice not working",
     "content/base/test/test_bug548193.html":"observerservice issue",
@@ -155,20 +164,6 @@
     "dom/tests/mochitest/bugs/test_bug504862.html":"showmodaldialog",
     "dom/tests/mochitest/bugs/test_bug61098.html":"showmodaldialog",
 
-    "content/events/test/test_continuous_wheel_events.html":"5535 passed, 108 failed - more tests running than desktop",
-    "content/events/test/test_bug422132.html":"2 failures out of 8, mousewheel test",
-    "content/events/test/test_bug659071.html":"1 failure out of 2, mousewheel zoom test",
-    "content/events/test/test_dom_wheel_event.html":"456 failed out of 19873, mousewheel test",
-
-    "content/events/test/test_bug426082.html":"1 failure out of 6, Moving the mouse down from the label should have unpressed the button",
-    "content/events/test/test_bug534833.html":"4 failures out of 6, bug 901564,click not fired, also disabled on Android",
-    "content/events/test/test_bug603008.html":"1 failure out of 615, bug 901533, Six move events fired - got 7, expected 6, also disabled on Android, touchmove",
-
-    "content/events/test/test_bug508479.html":"drag event, also fails on Android",
-    "content/events/test/test_dragstart.html":"drag event, also fails on Android",
-
-    "content/events/test/test_bug864040.html":"failing when the test gets moved around, and on debug",
-
     "content/html/content/test/forms/test_input_file_picker.html":"5 failures out of 139 and timing out, bug 901581",
     "content/html/content/test/forms/test_validation.html":"374 total, bug 901848, no keygen support",
 
@@ -232,14 +227,7 @@
     "content/base/test/websocket_hybi/test_send-arraybuffer.html":"",
     "content/base/test/websocket_hybi/test_send-blob.html":"",
     "content/canvas/test/webgl/test_webgl_conformance_test_suite.html":"",
-    "content/events/test/test_bug226361.xhtml":"",
-    "content/events/test/test_bug238987.html":"",
-    "content/events/test/test_bug409604.html":"",
-    "content/events/test/test_bug457672.html":"",
-    "content/events/test/test_bug574663.html":"",
-    "content/events/test/test_bug607464.html":"",
-    "content/events/test/test_wheel_default_action.html":"",
-    "content/base/test/test_bug682592.html":"",
+    "content/base/test/test_bug682592.html":"",	
     "content/html/document/test/test_bug369370.html":"",
     "content/svg/content/test/test_text_selection.html":"Mouse selection not workin on b2g",
     "content/svg/content/test/test_SVGAnimatedImageSMILDisabled.html":"",
@@ -296,6 +284,13 @@
     "dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected.html":"",
     "dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html":"",
     "dom/browser-element/mochitest/test_browserElement_oop_TargetBlank.html":"",
+    "dom/events/test/test_bug226361.xhtml":"",
+    "dom/events/test/test_bug238987.html":"",
+    "dom/events/test/test_bug409604.html":"",
+    "dom/events/test/test_bug457672.html":"",
+    "dom/events/test/test_bug574663.html":"",
+    "dom/events/test/test_bug607464.html":"",
+    "dom/events/test/test_wheel_default_action.html":"",
 
     "dom/file/test/test_progress_events.html":"All of these fail fairly regularly with: UnknownError: The operation failed for reasons unrelated to the database itself and not covered by any other error code. at http://mochi.test:8888/tests/dom/file/test/helpers.js:126",
     "dom/file/test/test_request_readyState.html":"",
diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js
index 08f8186ae2fd8e040da631541379c7af68c86152..782bc03698744aae3bfac2efdbd83c510d807555 100644
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -42,6 +42,13 @@ function bindDOMWindowUtils(aWindow) {
 }
 
 function getRawComponents(aWindow) {
+  // If we're running in automation that supports enablePrivilege, then we also
+  // provided access to the privileged Components.
+  try {
+    let win = Cu.waiveXrays(aWindow);
+    if (typeof win.netscape.security.PrivilegeManager == 'object')
+      Cu.forcePrivilegedComponentsForScope(aWindow);
+  } catch (e) {}
   return Cu.getComponentsForScope(aWindow);
 }
 
@@ -548,21 +555,43 @@ SpecialPowersAPI.prototype = {
     return wrapPrivileged(Services);
   },
 
+  /*
+   * In general, any Components object created for unprivileged scopes is
+   * neutered (it implements nsIXPCComponentsBase, but not nsIXPCComponents).
+   * We override this in certain legacy automation configurations (see the
+   * implementation of getRawComponents() above), but don't want to support
+   * it in cases where it isn't already required.
+   *
+   * In scopes with neutered Components, we don't have a natural referent for
+   * things like SpecialPowers.Cc. So in those cases, we fall back to the
+   * Components object from the SpecialPowers scope. This doesn't quite behave
+   * the same way (in particular, SpecialPowers.Cc[foo].createInstance() will
+   * create an instance in the SpecialPowers scope), but SpecialPowers wrapping
+   * is already a YMMV / Whatever-It-Takes-To-Get-TBPL-Green sort of thing.
+   *
+   * It probably wouldn't be too much work to just make SpecialPowers.Components
+   * unconditionally point to the Components object in the SpecialPowers scope.
+   * Try will tell what needs to be fixed up.
+   */
+  getFullComponents: function() {
+    return typeof this.Components.classes == 'object' ? this.Components
+                                                      : Components;
+  },
+
   /*
    * Convenient shortcuts to the standard Components abbreviations. Note that
    * we don't SpecialPowers-wrap Components.interfaces, because it's available
    * to untrusted content, and wrapping it confuses QI and identity checks.
    */
-  get Cc() { return wrapPrivileged(this.Components).classes; },
+  get Cc() { return wrapPrivileged(this.getFullComponents()).classes; },
   get Ci() { return this.Components.interfaces; },
-  get Cu() { return wrapPrivileged(this.Components).utils; },
+  get Cu() { return wrapPrivileged(this.getFullComponents()).utils; },
   get Cr() { return wrapPrivileged(this.Components).results; },
 
   /*
-   * SpecialPowers.getRawComponents() allows content to get a reference to the
-   * naked (non-SpecialPowers-wrapped) Components object for its scope. This
-   * object is normally hidden away on a scope chain available only to XBL
-   * functions.
+   * SpecialPowers.getRawComponents() allows content to get a reference to a
+   * naked (and, in certain automation configurations, privileged) Components
+   * object for its scope.
    *
    * SpecialPowers.getRawComponents(window) is defined as the global property
    * window.SpecialPowers.Components for convenience.
diff --git a/toolkit/content/aboutTelemetry.css b/toolkit/content/aboutTelemetry.css
index 88fb4e1845d28f04896dabf4e4069f3606066128..4f9a7816103ecdc37618cd15ebe1b64dae693273 100644
--- a/toolkit/content/aboutTelemetry.css
+++ b/toolkit/content/aboutTelemetry.css
@@ -94,7 +94,7 @@ h2 {
   text-decoration: underline;
 }
 
-#histograms, #addon-histograms {
+#histograms, #addon-histograms, #thread-hang-stats>div {
   overflow: hidden;
 }
 
diff --git a/toolkit/content/aboutTelemetry.js b/toolkit/content/aboutTelemetry.js
index 16bb5375e189063f608a6e3aaaa4b6002bf2e437..3bbe29873eae6bebdfb09769c6065af5b2dbc6af 100644
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -410,6 +410,55 @@ let ChromeHangs = {
   }
 };
 
+let ThreadHangStats = {
+
+  /**
+   * Renders raw thread hang stats data
+   */
+  render: function() {
+    let div = document.getElementById("thread-hang-stats");
+    clearDivData(div);
+
+    let stats = Telemetry.threadHangStats;
+    stats.forEach((thread) => {
+      div.appendChild(this.renderThread(thread));
+    });
+    if (stats.length) {
+      setHasData("thread-hang-stats-section", true);
+    }
+  },
+
+  /**
+   * Creates and fills data corresponding to a thread
+   */
+  renderThread: function(aThread) {
+    let div = document.createElement("div");
+
+    let title = document.createElement("h2");
+    title.textContent = aThread.name;
+    div.appendChild(title);
+
+    // Don't localize the histogram name, because the
+    // name is also used as the div element's ID
+    Histogram.render(div, aThread.name + "-Activity",
+                     aThread.activity, {exponential: true});
+    aThread.hangs.forEach((hang, index) => {
+      let hangName = aThread.name + "-Hang-" + (index + 1);
+      let hangDiv = Histogram.render(
+        div, hangName, hang.histogram, {exponential: true});
+      let stackDiv = document.createElement("div");
+      hang.stack.forEach((frame) => {
+        stackDiv.appendChild(document.createTextNode(frame));
+        // Leave an extra <br> at the end of the stack listing
+        stackDiv.appendChild(document.createElement("br"));
+      });
+      // Insert stack after the histogram title
+      hangDiv.insertBefore(stackDiv, hangDiv.childNodes[1]);
+    });
+    return div;
+  },
+};
+
 let Histogram = {
 
   hgramSamplesCaption: bundle.GetStringFromName("histogramSamples"),
@@ -426,9 +475,12 @@ let Histogram = {
    * @param aParent Parent element
    * @param aName Histogram name
    * @param aHgram Histogram information
+   * @param aOptions Object with render options
+   *                 * exponential: bars follow logarithmic scale
    */
-  render: function Histogram_render(aParent, aName, aHgram) {
+  render: function Histogram_render(aParent, aName, aHgram, aOptions) {
     let hgram = this.unpack(aHgram);
+    let options = aOptions || {};
 
     let outerDiv = document.createElement("div");
     outerDiv.className = "histogram";
@@ -450,7 +502,8 @@ let Histogram = {
     if (isRTL())
       hgram.values.reverse();
 
-    let textData = this.renderValues(outerDiv, hgram.values, hgram.max, hgram.sample_count);
+    let textData = this.renderValues(outerDiv, hgram.values, hgram.max,
+                                     hgram.sample_count, options);
 
     // The 'Copy' button contains the textual data, copied to clipboard on click
     let copyButton = document.createElement("button");
@@ -464,6 +517,7 @@ let Histogram = {
     outerDiv.appendChild(copyButton);
 
     aParent.appendChild(outerDiv);
+    return outerDiv;
   },
 
   /**
@@ -514,6 +568,16 @@ let Histogram = {
     return result;
   },
 
+  /**
+   * Return a non-negative, logarithmic representation of a non-negative number.
+   * e.g. 0 => 0, 1 => 1, 10 => 2, 100 => 3
+   *
+   * @param aNumber Non-negative number
+   */
+  getLogValue: function(aNumber) {
+    return Math.max(0, Math.log10(aNumber) + 1);
+  },
+
   /**
    * Create histogram HTML bars, also returns a textual representation
    * Both aMaxValue and aSumValues must be positive.
@@ -523,21 +587,26 @@ let Histogram = {
    * @param aValues Histogram values
    * @param aMaxValue Value of the longest bar (length, not label)
    * @param aSumValues Sum of all bar values
+   * @param aOptions Object with render options (@see #render)
    */
-  renderValues: function Histogram_renderValues(aDiv, aValues, aMaxValue, aSumValues) {
+  renderValues: function Histogram_renderValues(aDiv, aValues, aMaxValue, aSumValues, aOptions) {
     let text = "";
     // If the last label is not the longest string, alignment will break a little
     let labelPadTo = String(aValues[aValues.length -1][0]).length;
+    let maxBarValue = aOptions.exponential ? this.getLogValue(aMaxValue) : aMaxValue;
 
     for (let [label, value] of aValues) {
+      let barValue = aOptions.exponential ? this.getLogValue(value) : value;
+
       // Create a text representation: <right-aligned-label> |<bar-of-#><value>  <percentage>
       text += EOL
               + " ".repeat(Math.max(0, labelPadTo - String(label).length)) + label // Right-aligned label
-              + " |" + "#".repeat(Math.round(MAX_BAR_CHARS * value / aMaxValue)) + value // Bars and value
+              + " |" + "#".repeat(Math.round(MAX_BAR_CHARS * barValue / maxBarValue)) // Bar
+              + "  " + value // Value
               + "  " + Math.round(100 * value / aSumValues) + "%"; // Percentage
 
       // Construct the HTML labels + bars
-      let belowEm = Math.round(MAX_BAR_HEIGHT * (value / aMaxValue) * 10) / 10;
+      let belowEm = Math.round(MAX_BAR_HEIGHT * (barValue / maxBarValue) * 10) / 10;
       let aboveEm = MAX_BAR_HEIGHT - belowEm;
 
       let barDiv = document.createElement("div");
@@ -865,6 +934,9 @@ function onLoad() {
   // Show chrome hang stacks
   ChromeHangs.render();
 
+  // Show thread hang stats
+  ThreadHangStats.render();
+
   // Show histogram data
   let histograms = Telemetry.histogramSnapshots;
   if (Object.keys(histograms).length) {
diff --git a/toolkit/content/aboutTelemetry.xhtml b/toolkit/content/aboutTelemetry.xhtml
index e52585173920ac3e67ba22bb2f93773dd3083fb9..c5da83e7e7332a03ee46b37d8dc1a39ef0e3ac65 100644
--- a/toolkit/content/aboutTelemetry.xhtml
+++ b/toolkit/content/aboutTelemetry.xhtml
@@ -60,6 +60,15 @@
       </div>
     </section>
 
+    <section id="thread-hang-stats-section" class="data-section">
+      <input type="checkbox" class="statebox"/>
+      <h1 class="section-name">&aboutTelemetry.threadHangStatsSection;</h1>
+      <span class="toggle-caption">&aboutTelemetry.toggle;</span>
+      <span class="empty-caption">&aboutTelemetry.emptySection;</span>
+      <div id="thread-hang-stats" class="data">
+      </div>
+    </section>
+
     <section id="histograms-section" class="data-section">
       <input type="checkbox" class="statebox"/>
       <h1 class="section-name">&aboutTelemetry.histogramsSection;</h1>
diff --git a/toolkit/identity/IdentityCryptoService.cpp b/toolkit/identity/IdentityCryptoService.cpp
index d5f45ce6c3f4a3b8c68cef66b0418384c4d22420..5ef5250d7939cb273c26b6a1f7bc3341261510c3 100644
--- a/toolkit/identity/IdentityCryptoService.cpp
+++ b/toolkit/identity/IdentityCryptoService.cpp
@@ -101,6 +101,10 @@ public:
 private:
   ~KeyPair()
   {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown()) {
+      return;
+    }
     destructorSafeDestroyNSSReference();
     shutdown(calledFromObject);
   }
@@ -112,10 +116,6 @@ private:
 
   void destructorSafeDestroyNSSReference()
   {
-    nsNSSShutDownPreventionLock locker;
-    if (isAlreadyShutDown())
-      return;
-
     SECKEY_DestroyPrivateKey(mPrivateKey);
     mPrivateKey = nullptr;
     SECKEY_DestroyPublicKey(mPublicKey);
@@ -141,6 +141,10 @@ public:
 private:
   ~KeyGenRunnable()
   {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown()) {
+      return;
+    }
     destructorSafeDestroyNSSReference();
     shutdown(calledFromObject);
   }
@@ -152,11 +156,7 @@ private:
 
   void destructorSafeDestroyNSSReference()
   {
-    nsNSSShutDownPreventionLock locker;
-    if (isAlreadyShutDown())
-      return;
-
-     mKeyPair = nullptr;
+    mKeyPair = nullptr;
   }
 
   const KeyType mKeyType; // in
@@ -179,6 +179,10 @@ public:
 private:
   ~SignRunnable()
   {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown()) {
+      return;
+    }
     destructorSafeDestroyNSSReference();
     shutdown(calledFromObject);
   }
@@ -190,10 +194,6 @@ private:
 
   void destructorSafeDestroyNSSReference()
   {
-    nsNSSShutDownPreventionLock locker;
-    if (isAlreadyShutDown())
-      return;
-
     SECKEY_DestroyPrivateKey(mPrivateKey);
     mPrivateKey = nullptr;
   }
diff --git a/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd b/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
index 34ce5ca17b219d27007ac9a7b661a16573ad88ea..4448481fdb28c1c2155a5fdf307d104a04997147 100644
--- a/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
@@ -20,6 +20,10 @@
   Browser Hangs
 ">
 
+<!ENTITY aboutTelemetry.threadHangStatsSection "
+  Thread Hangs
+">
+
 <!ENTITY aboutTelemetry.histogramsSection "
   Histograms
 ">
diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js
index 8bba4ab4535c30f5b45a6903596458ac8d8dae31..9ff777c38787c808ea68a954ce036a20a4a17dce 100644
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -257,9 +257,9 @@ const PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT   = 29;
 // Incompatible add-ons found (update notification)
 const PING_BGUC_ADDON_HAVE_INCOMPAT          = 30;
 
-var gLocale     = null;
+var gLocale = null;
 
-#ifdef MOZ_B2G
+#ifdef MOZ_WIDGET_GONK
 XPCOMUtils.defineLazyGetter(this, "gExtStorage", function aus_gExtStorage() {
     return Services.env.get("EXTERNAL_STORAGE");
 });
diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in
index 27a7a6f578a672f4f04dee57ac5fa88a87c63f55..2935f83a3f203ea6f5872554427ed8f48fd7af82 100644
--- a/uriloader/exthandler/Makefile.in
+++ b/uriloader/exthandler/Makefile.in
@@ -6,9 +6,9 @@
 LOCAL_INCLUDES = -I$(srcdir)
 
 LOCAL_INCLUDES += -I$(topsrcdir)/dom/base \
+            -I$(topsrcdir)/dom/events \
             -I$(topsrcdir)/dom/ipc \
             -I$(topsrcdir)/content/base/src \
-            -I$(topsrcdir)/content/events/src \
             -I$(topsrcdir)/netwerk/base/src \
             -I$(topsrcdir)/netwerk/protocol/http
 
diff --git a/uriloader/prefetch/Makefile.in b/uriloader/prefetch/Makefile.in
index 86e4a5052d4e44076948c7f4a2b29099ed335819..27cfb5d85c63f0e2636ef0cd1304bcf45ba69720 100644
--- a/uriloader/prefetch/Makefile.in
+++ b/uriloader/prefetch/Makefile.in
@@ -5,7 +5,7 @@
 
 LOCAL_INCLUDES = \
 		-I$(topsrcdir)/content/base/src \
-		-I$(topsrcdir)/content/events/src \
+		-I$(topsrcdir)/dom/events \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
diff --git a/view/src/moz.build b/view/src/moz.build
index b86d12baf188ade4c8b0540a70c0a1b00301e2f1..b267ad2e9ec5d67de246d598edd4c80ad1097428 100644
--- a/view/src/moz.build
+++ b/view/src/moz.build
@@ -17,5 +17,5 @@ MSVC_ENABLE_PGO = True
 FINAL_LIBRARY = 'gklayout'
 
 LOCAL_INCLUDES += [
-    '../../content/events/src/',
+    '/dom/events/',
 ]
diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h
index c312d873b8764e2d280e07235c4c128cedb53199..c58cf68915af4bdedf76aa5bd1c9f81832cd1562 100644
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -63,7 +63,7 @@ enum nsEventStructType
   NS_CONTENT_COMMAND_EVENT,          // WidgetContentCommandEvent
   NS_PLUGIN_EVENT,                   // WidgetPluginEvent
 
-  // MutationEvent.h (content/events/public)
+  // MutationEvent.h (dom/events)
   NS_MUTATION_EVENT,                 // InternalMutationEvent
 
   // Follwoing struct type values are ugly.  They indicate other struct type
diff --git a/widget/ContentEvents.h b/widget/ContentEvents.h
index 47b5fd90ac4374b3976a05e4d0da275010b275ee..280fa576376a5673a2637ac0b431488bdf24d503 100644
--- a/widget/ContentEvents.h
+++ b/widget/ContentEvents.h
@@ -228,6 +228,7 @@ public:
     propertyName(aPropertyName), elapsedTime(aElapsedTime),
     pseudoElement(aPseudoElement)
   {
+    mFlags.mCancelable = false;
   }
 
   nsString propertyName;
@@ -263,6 +264,7 @@ public:
     animationName(aAnimationName), elapsedTime(aElapsedTime),
     pseudoElement(aPseudoElement)
   {
+    mFlags.mCancelable = false;
   }
 
   nsString animationName;
diff --git a/widget/EventClassList.h b/widget/EventClassList.h
index 820df5d1d64a234df31fe6628aaa491ed207338d..27e3afcdd083d3219a3c4243b7c5b98da57e7265 100644
--- a/widget/EventClassList.h
+++ b/widget/EventClassList.h
@@ -55,5 +55,5 @@ NS_EVENT_CLASS(Widget, CommandEvent)
 NS_EVENT_CLASS(Widget, ContentCommandEvent)
 NS_EVENT_CLASS(Widget, PluginEvent)
 
-// MutationEvent.h (content/events/public)
+// MutationEvent.h (dom/events)
 NS_EVENT_CLASS(Internal, MutationEvent)
diff --git a/widget/TextEvents.h b/widget/TextEvents.h
index a0bb6c85acc148d3365c10268242c84cfaefcc11..7fd7d55e2193c87d7cdcb4472af0dab6a24eee74 100644
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -127,20 +127,7 @@ public:
   }
 
   static void GetDOMKeyName(mozilla::KeyNameIndex aKeyNameIndex,
-                            nsAString& aKeyName)
-  {
-#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) \
-      case KEY_NAME_INDEX_##aCPPName: \
-        aKeyName.Assign(NS_LITERAL_STRING(aDOMKeyName)); return;
-    switch (aKeyNameIndex) {
-#include "nsDOMKeyNameList.h"
-      case KEY_NAME_INDEX_USE_STRING:
-      default:
-        aKeyName.Truncate();
-        return;
-    }
-#undef NS_DEFINE_KEYNAME
-  }
+                            nsAString& aKeyName);
 
   void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
   {
diff --git a/widget/android/moz.build b/widget/android/moz.build
index ce461242d46db209eb7c289e98abd4b94c7f551e..db62591a085a04e8e4b93009c02acbbc6f1dccbd 100644
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -47,8 +47,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
-    '/content/events/src',
     '/docshell/base',
+    '/dom/events',
     '/dom/system/android',
     '/netwerk/cache',
     '/widget/android/android',
diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build
index 22948131ea229c1739472f90928de499d3068bb9..1f96efbecca3e8c798511d67da291cad3003c451 100644
--- a/widget/gonk/moz.build
+++ b/widget/gonk/moz.build
@@ -67,8 +67,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
-    '/content/events/src',
     '/content/media/omx/mediaresourcemanager',
+    '/dom/events',
     '/dom/system/android',
     '/gfx/skia/include/config',
     '/gfx/skia/include/core',
diff --git a/widget/shared/WidgetEventImpl.cpp b/widget/shared/WidgetEventImpl.cpp
index 91efa2880ec9b1c94584dbad6653309f8be3c59c..2090a6c81130e12aceee6d502be76fd24a97d9d7 100644
--- a/widget/shared/WidgetEventImpl.cpp
+++ b/widget/shared/WidgetEventImpl.cpp
@@ -237,4 +237,74 @@ WidgetEvent::IsAllowedToDispatchDOMEvent() const
   }
 }
 
+/******************************************************************************
+ * mozilla::WidgetKeyboardEvent (TextEvents.h)
+ ******************************************************************************/
+
+/*static*/ void
+WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
+                                   nsAString& aKeyName)
+{
+  // The expected way to implement this function would be to use a
+  // switch statement.  By using a table-based implementation, below, we
+  // ensure that this function executes in constant time in cases where
+  // compilers wouldn't be able to convert the switch statement to a
+  // jump table.  This table-based implementation also minimizes the
+  // space required by the code and data.
+#define KEY_STR_NUM_INTERNAL(line) key##line
+#define KEY_STR_NUM(line) KEY_STR_NUM_INTERNAL(line)
+
+  // Catch non-ASCII DOM key names in our key name list.
+#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName)                      \
+  static_assert(sizeof(aDOMKeyName) == MOZ_ARRAY_LENGTH(aDOMKeyName), \
+                "Invalid DOM key name");
+#include "nsDOMKeyNameList.h"
+#undef NS_DEFINE_KEYNAME
+
+  struct KeyNameTable
+  {
+#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName)          \
+    char16_t KEY_STR_NUM(__LINE__)[sizeof(aDOMKeyName)];
+#include "nsDOMKeyNameList.h"
+#undef NS_DEFINE_KEYNAME
+  };
+
+  static const KeyNameTable kKeyNameTable = {
+#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) MOZ_UTF16(aDOMKeyName),
+#include "nsDOMKeyNameList.h"
+#undef NS_DEFINE_KEYNAME
+  };
+
+  static const uint16_t kKeyNameOffsets[] = {
+#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName)          \
+    offsetof(struct KeyNameTable, KEY_STR_NUM(__LINE__)),
+#include "nsDOMKeyNameList.h"
+#undef NS_DEFINE_KEYNAME
+    // Include this entry so we can compute lengths easily.
+    sizeof(kKeyNameTable)
+  };
+
+  // Use the sizeof trick rather than MOZ_ARRAY_LENGTH to avoid problems
+  // with constexpr functions called inside static_assert with some
+  // compilers.
+  static_assert(KEY_NAME_INDEX_USE_STRING ==
+                (sizeof(kKeyNameOffsets)/sizeof(kKeyNameOffsets[0])) - 1,
+                "Invalid enumeration values!");
+
+  if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
+    aKeyName.Truncate();
+    return;
+  }
+
+  uint16_t offset = kKeyNameOffsets[aKeyNameIndex];
+  uint16_t nextOffset = kKeyNameOffsets[aKeyNameIndex + 1];
+  const char16_t* table = reinterpret_cast<const char16_t*>(&kKeyNameTable);
+
+  // Subtract off 1 for the null terminator.
+  aKeyName.Assign(table + offset, nextOffset - offset - 1);
+
+#undef KEY_STR_NUM
+#undef KEY_STR_NUM_INTERNAL
+}
+
 } // namespace mozilla
diff --git a/widget/windows/moz.build b/widget/windows/moz.build
index 566506e0a21d6e02ef5838585a7dad4094678afe..778cac47434b5b7afeb6ebd27dda1a1a5b197aa6 100644
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -100,7 +100,7 @@ FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../shared',
     '../xpwidgets',
-    '/content/events/src',
+    '/dom/events',
     '/layout/generic',
     '/layout/xul',
     '/toolkit/xre',
diff --git a/widget/xpwidgets/APZCCallbackHelper.cpp b/widget/xpwidgets/APZCCallbackHelper.cpp
index bd30184cb7f1947450628c40da2188f998dfd18c..0ccb9a8d455a644d9b25041ce4fd7fd8245adaa5 100644
--- a/widget/xpwidgets/APZCCallbackHelper.cpp
+++ b/widget/xpwidgets/APZCCallbackHelper.cpp
@@ -68,7 +68,7 @@ MaybeAlignAndClampDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics,
   // Correct the display-port by the difference between the requested scroll
   // offset and the resulting scroll offset after setting the requested value.
   CSSRect& displayPort = aFrameMetrics.mDisplayPort;
-  displayPort += aActualScrollOffset - aFrameMetrics.mScrollOffset;
+  displayPort += aFrameMetrics.mScrollOffset - aActualScrollOffset;
 
   // Expand the display port to the next tile boundaries, if tiled thebes layers
   // are enabled.
@@ -95,6 +95,12 @@ ScrollFrameTo(nsIScrollableFrame* aFrame, const CSSPoint& aPoint)
   // If the scrollable frame got a scroll request from something other than us
   // since the last layers update, then we don't want to push our scroll request
   // because we'll clobber that one, which is bad.
+  // Note that content may have just finished sending a layers update with a scroll
+  // offset update to the APZ, in which case the origin will be reset to null and we
+  // might actually be clobbering the content-side scroll offset with a stale APZ
+  // scroll offset. This is unavoidable because of the async communication between
+  // APZ and content; however the code in NotifyLayersUpdated should reissue a new
+  // repaint request to bring everything back into sync.
   if (!aFrame->OriginOfLastScroll() || aFrame->OriginOfLastScroll() == nsGkAtoms::apz) {
     aFrame->ScrollToCSSPixelsApproximate(aPoint, nsGkAtoms::apz);
   }
diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp
index aa50f33fabfb5df30268b1c3447e1c819c33621d..26e62ee0ad3e71353bf0600c7db72a1ecfb8e91c 100644
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -155,6 +155,7 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
+#include "mozilla/HoldDropJSObjects.h"
 /* This must occur *after* base/process_util.h to avoid typedefs conflicts. */
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/LinkedList.h"
@@ -1094,6 +1095,8 @@ enum ccType {
 
 typedef js::SliceBudget SliceBudget;
 
+class JSPurpleBuffer;
+
 class nsCycleCollector : public nsIMemoryReporter
 {
     NS_DECL_ISUPPORTS
@@ -1127,6 +1130,8 @@ class nsCycleCollector : public nsIMemoryReporter
     uint32_t mUnmergedNeeded;
     uint32_t mMergedInARow;
 
+    JSPurpleBuffer* mJSPurpleBuffer;
+
 public:
     nsCycleCollector();
     virtual ~nsCycleCollector();
@@ -1169,6 +1174,7 @@ public:
                              size_t *aWeakMapsSize,
                              size_t *aPurpleBufferSize) const;
 
+    JSPurpleBuffer* GetJSPurpleBuffer();
 private:
     void CheckThreadSafety();
     void ShutdownCollect();
@@ -2151,6 +2157,122 @@ MayHaveChild(void *o, nsCycleCollectionParticipant* cp)
     return cf.MayHaveChild();
 }
 
+template<class T>
+class SegmentedArrayElement : public LinkedListElement<SegmentedArrayElement<T>>
+                            , public AutoFallibleTArray<T, 60>
+{
+};
+
+template<class T>
+class SegmentedArray
+{
+public:
+    ~SegmentedArray()
+    {
+        MOZ_ASSERT(IsEmpty());
+    }
+
+    void AppendElement(T& aElement)
+    {
+        SegmentedArrayElement<T>* last = mSegments.getLast();
+        if (!last || last->Length() == last->Capacity()) {
+            last = new SegmentedArrayElement<T>();
+            mSegments.insertBack(last);
+        }
+        last->AppendElement(aElement);
+    }
+
+    void Clear()
+    {
+        SegmentedArrayElement<T>* first;
+        while ((first = mSegments.popFirst())) {
+            delete first;
+        }
+    }
+
+    SegmentedArrayElement<T>* GetFirstSegment()
+    {
+        return mSegments.getFirst();
+    }
+
+    bool IsEmpty()
+    {
+        return !GetFirstSegment();
+    }
+
+private:
+    mozilla::LinkedList<SegmentedArrayElement<T>> mSegments;
+};
+
+// JSPurpleBuffer keeps references to GCThings which might affect the
+// next cycle collection. It is owned only by itself and during unlink its
+// self reference is broken down and the object ends up killing itself.
+// If GC happens before CC, references to GCthings and the self reference are
+// removed.
+class JSPurpleBuffer
+{
+public:
+    JSPurpleBuffer(JSPurpleBuffer*& aReferenceToThis)
+      : mReferenceToThis(aReferenceToThis)
+    {
+        mReferenceToThis = this;
+        NS_ADDREF_THIS();
+        mozilla::HoldJSObjects(this);
+    }
+
+    ~JSPurpleBuffer()
+    {
+        MOZ_ASSERT(mValues.IsEmpty());
+        MOZ_ASSERT(mObjects.IsEmpty());
+    }
+
+    void Destroy()
+    {
+        mReferenceToThis = nullptr;
+        mValues.Clear();
+        mObjects.Clear();
+        mozilla::DropJSObjects(this);
+        NS_RELEASE_THIS();
+    }
+
+    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(JSPurpleBuffer)
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(JSPurpleBuffer)
+
+    JSPurpleBuffer*& mReferenceToThis;
+    SegmentedArray<JS::Heap<JS::Value>> mValues;
+    SegmentedArray<JS::Heap<JSObject*>> mObjects;
+};
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(JSPurpleBuffer)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(JSPurpleBuffer)
+    tmp->Destroy();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSPurpleBuffer)
+    CycleCollectionNoteChild(cb, tmp, "self");
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+#define NS_TRACE_SEGMENTED_ARRAY(_field)                                       \
+    {                                                                          \
+        auto segment = tmp->_field.GetFirstSegment();                          \
+        while (segment) {                                                      \
+            for (uint32_t i = segment->Length(); i > 0;) {                     \
+                aCallbacks.Trace(&segment->ElementAt(--i), #_field, aClosure); \
+            }                                                                  \
+            segment = segment->getNext();                                      \
+        }                                                                      \
+    }
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(JSPurpleBuffer)
+    NS_TRACE_SEGMENTED_ARRAY(mValues)
+    NS_TRACE_SEGMENTED_ARRAY(mObjects)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(JSPurpleBuffer, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(JSPurpleBuffer, Release)
+
 struct SnowWhiteObject
 {
   void* mPointer;
@@ -2158,7 +2280,7 @@ struct SnowWhiteObject
   nsCycleCollectingAutoRefCnt* mRefCnt;
 };
 
-class SnowWhiteKiller
+class SnowWhiteKiller : public TraceCallbacks
 {
 public:
     SnowWhiteKiller(nsCycleCollector *aCollector, uint32_t aMaxCount)
@@ -2183,6 +2305,7 @@ public:
             if (!o.mRefCnt->get() && !o.mRefCnt->IsInPurpleBuffer()) {
                 mCollector->RemoveObjectFromGraph(o.mPointer);
                 o.mRefCnt->stabilizeForDeletion();
+                o.mParticipant->Trace(o.mPointer, *this, nullptr);
                 o.mParticipant->DeleteCycleCollectable(o.mPointer);
             }
         }
@@ -2208,6 +2331,43 @@ public:
       return mObjects.Length() > 0;
     }
 
+    virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
+                       void* aClosure) const
+    {
+        void* thing = JSVAL_TO_TRACEABLE(aValue->get());
+        if (thing && xpc_GCThingIsGrayCCThing(thing)) {
+            mCollector->GetJSPurpleBuffer()->mValues.AppendElement(*aValue);
+        }
+    }
+
+    virtual void Trace(JS::Heap<jsid>* aId, const char* aName,
+                       void* aClosure) const
+    {
+    }
+
+    virtual void Trace(JS::Heap<JSObject*>* aObject, const char* aName,
+                       void* aClosure) const
+    {
+        if (*aObject && xpc_GCThingIsGrayCCThing(*aObject)) {
+            mCollector->GetJSPurpleBuffer()->mObjects.AppendElement(*aObject);
+        }
+    }
+
+    virtual void Trace(JS::Heap<JSString*>* aString, const char* aName,
+                       void* aClosure) const
+    {
+    }
+
+    virtual void Trace(JS::Heap<JSScript*>* aScript, const char* aName,
+                       void* aClosure) const
+    {
+    }
+
+    virtual void Trace(JS::Heap<JSFunction*>* aFunction, const char* aName,
+                       void* aClosure) const
+    {
+    }
+
 private:
     nsCycleCollector *mCollector;
     FallibleTArray<SnowWhiteObject> mObjects;
@@ -2812,7 +2972,8 @@ nsCycleCollector::nsCycleCollector() :
     mBeforeUnlinkCB(nullptr),
     mForgetSkippableCB(nullptr),
     mUnmergedNeeded(0),
-    mMergedInARow(0)
+    mMergedInARow(0),
+    mJSPurpleBuffer(nullptr)
 {
 }
 
@@ -3057,6 +3218,9 @@ nsCycleCollector::PrepareForGarbageCollection()
     if (mIncrementalPhase == IdlePhase) {
         MOZ_ASSERT(mGraph.IsEmpty(), "Non-empty graph when idle");
         MOZ_ASSERT(!mBuilder, "Non-null builder when idle");
+        if (mJSPurpleBuffer) {
+            mJSPurpleBuffer->Destroy();
+        }
         return;
     }
 
@@ -3232,6 +3396,18 @@ nsCycleCollector::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
     // - mParams: because it only contains scalars.
 }
 
+JSPurpleBuffer*
+nsCycleCollector::GetJSPurpleBuffer()
+{
+  if (!mJSPurpleBuffer) {
+    // JSPurpleBuffer keeps itself alive, but we need to create it in such way
+    // that it ends up in the normal purple buffer. That happens when
+    // nsRefPtr goes out of the scope and calls Release.
+    nsRefPtr<JSPurpleBuffer> pb = new JSPurpleBuffer(mJSPurpleBuffer);
+  }
+  return mJSPurpleBuffer;
+}
+
 ////////////////////////////////////////////////////////////////////////
 // Module public API (exported in nsCycleCollector.h)
 // Just functions that redirect into the singleton, once it's built.
diff --git a/xpcom/glue/nsCycleCollectionParticipant.h b/xpcom/glue/nsCycleCollectionParticipant.h
index b237c8a3f3e96fa137f2926c61ea1817fffcbddf..502bd1e63313088bcec557ea26a3456739f4d088 100644
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -101,6 +101,8 @@ public:
     NS_IMETHOD_(void) Unlink(void *p) = 0;
     NS_IMETHOD_(void) Unroot(void *p) = 0;
 
+    NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) {};
+
     // If CanSkip returns true, p is removed from the purple buffer during
     // a call to nsCycleCollector_forgetSkippable().
     // Note, calling CanSkip may remove objects from the purple buffer!