Merge latest green fx-team changeset and mozilla-central; a=merge
authorEd Morley <emorley@mozilla.com>
Thu, 14 Aug 2014 08:50:16 +0100
changeset 199439 5299864050eeed64e46c67e4c88e7f95fe773b25
parent 199438 f7faa1038cfcbbccd5b6c57d63e61d7abf7895aa (current diff)
parent 199423 de1d3c229e5ab5a505b28ac9de5937d4aad0b0e1 (diff)
child 199440 b7d4ffccf5bf2178fd0493e05187a82393b2a44b
child 199524 a9a8bb2c8704bb5d61b31300851aff5f7430f078
child 199583 4b187398428e4ec72c3153455d41c5ea8da60532
push id47649
push useremorley@mozilla.com
push dateThu, 14 Aug 2014 07:54:55 +0000
treeherdermozilla-inbound@b7d4ffccf5bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
5299864050ee / 34.0a1 / 20140814030201 / files
nightly linux64
5299864050ee / 34.0a1 / 20140814005302 / files
nightly mac
5299864050ee / 34.0a1 / 20140814005302 / files
nightly win32
5299864050ee / 34.0a1 / 20140814005302 / files
nightly win64
5299864050ee / 34.0a1 / 20140814005302 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge latest green fx-team changeset and mozilla-central; a=merge
configure.in
testing/mochitest/runtestsremote.py
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -311,16 +311,18 @@ HyperTextAccessible::DOMPointToOffset(ns
 
     descendant = mDoc->GetAccessible(findNode);
     if (!descendant && findNode->IsContent()) {
       Accessible* container = mDoc->GetContainerAccessible(findNode);
       if (container) {
         TreeWalker walker(container, findNode->AsContent(),
                           TreeWalker::eWalkContextTree);
         descendant = walker.NextChild();
+        if (!descendant)
+          descendant = container;
       }
     }
   }
 
   return TransformOffset(descendant, offset, aIsEndOffset);
 }
 
 uint32_t
@@ -434,19 +436,24 @@ HyperTextAccessible::FindOffset(uint32_t
 
   // Find a leaf accessible frame to start with. PeekOffset wants this.
   HyperTextAccessible* text = this;
   Accessible* child = nullptr;
   int32_t innerOffset = aOffset;
 
   do {
     int32_t childIdx = text->GetChildIndexAtOffset(innerOffset);
-    NS_ASSERTION(childIdx != -1, "Bad in offset!");
-    if (childIdx == -1)
-      return 0;
+
+    // We can have an empty text leaf as our only child. Since empty text
+    // leaves are not accessible we then have no children, but 0 is a valid
+    // innerOffset.
+    if (childIdx == -1) {
+      NS_ASSERTION(innerOffset == 0 && !text->ChildCount(), "No childIdx?");
+      return DOMPointToOffset(text->GetNode(), 0, aDirection == eDirNext);
+    }
 
     child = text->GetChildAt(childIdx);
 
     // HTML list items may need special processing because PeekOffset doesn't
     // work with list bullets.
     if (text->IsHTMLListItem()) {
       HTMLLIAccessible* li = text->AsHTMLListItem();
       if (child == li->Bullet()) {
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -56,18 +56,25 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Promise', // jshint ignore:line
   'resource://gre/modules/Promise.jsm');
 
-// Maximum amount of time allowed for a gesture to be considered a multitouch.
-const MAX_MULTITOUCH = 250;
+// Default maximum duration of swipe
+const SWIPE_MAX_DURATION = 200;
+// Default maximum amount of time allowed for a gesture to be considered a
+// multitouch
+const MAX_MULTITOUCH = 125;
+// Default maximum consecutive pointer event timeout
+const MAX_CONSECUTIVE_GESTURE_DELAY = 200;
+// Default delay before tap turns into dwell
+const DWELL_THRESHOLD = 250;
 // Minimal swipe distance in inches
 const SWIPE_MIN_DISTANCE = 0.4;
 // Maximum distance the pointer could move during a tap in inches
 const TAP_MAX_RADIUS = 0.2;
 // Directness coefficient. It is based on the maximum 15 degree angle between
 // consequent pointer move lines.
 const DIRECTNESS_COEFF = 1.44;
 // An android flag.
@@ -75,16 +82,18 @@ const IS_ANDROID = Utils.MozBuildApp ===
   Utils.AndroidSdkVersion >= 14;
 // A single pointer down/up sequence periodically precedes the tripple swipe
 // gesture on Android. This delay acounts for that.
 const ANDROID_TRIPLE_SWIPE_DELAY = 50;
 // The virtual touch ID generated by a mouse event.
 const MOUSE_ID = 'mouse';
 // Amount in inches from the edges of the screen for it to be an edge swipe
 const EDGE = 0.1;
+// Multiply timeouts by this constant, x2 works great too for slower users.
+const TIMEOUT_MULTIPLIER = 1;
 
 /**
  * A point object containing distance travelled data.
  * @param {Object} aPoint A point object that looks like: {
  *   x: x coordinate in pixels,
  *   y: y coordinate in pixels
  * }
  */
@@ -137,29 +146,36 @@ Point.prototype = {
  * An externally accessible collection of settings used in gesture resolition.
  * @type {Object}
  */
 this.GestureSettings = { // jshint ignore:line
   /**
    * Maximum duration of swipe
    * @type {Number}
    */
-  swipeMaxDuration: 400,
+  swipeMaxDuration: SWIPE_MAX_DURATION * TIMEOUT_MULTIPLIER,
+
+  /**
+   * Maximum amount of time allowed for a gesture to be considered a multitouch.
+   * @type {Number}
+   */
+  maxMultitouch: MAX_MULTITOUCH * TIMEOUT_MULTIPLIER,
 
   /**
    * Maximum consecutive pointer event timeout.
    * @type {Number}
    */
-  maxConsecutiveGestureDelay: 400,
+  maxConsecutiveGestureDelay:
+    MAX_CONSECUTIVE_GESTURE_DELAY * TIMEOUT_MULTIPLIER,
 
   /**
    * Delay before tap turns into dwell
    * @type {Number}
    */
-  dwellThreshold: 500,
+  dwellThreshold: DWELL_THRESHOLD * TIMEOUT_MULTIPLIER,
 
   /**
    * Minimum distance that needs to be travelled for the pointer move to be
    * fired.
    * @type {Number}
    */
   travelThreshold: 0.025
 };
@@ -438,17 +454,17 @@ Gesture.prototype = {
   /**
    * Handle the pointer down event.
    * @param  {Array} aPoints A new pointer down points.
    * @param  {Number} aTimeStamp A new pointer down timeStamp.
    */
   pointerdown: function Gesture_pointerdown(aPoints, aTimeStamp) {
     this._inProgress = true;
     this._update(aPoints, 'pointerdown',
-      aTimeStamp - this.startTime < MAX_MULTITOUCH);
+      aTimeStamp - this.startTime < GestureSettings.maxMultitouch);
   },
 
   /**
    * Handle the pointer move event.
    * @param  {Array} aPoints A new pointer move points.
    */
   pointermove: function Gesture_pointermove(aPoints) {
     this._update(aPoints, 'pointermove');
--- a/accessible/tests/mochitest/text/test_lineboundary.html
+++ b/accessible/tests/mochitest/text/test_lineboundary.html
@@ -8,16 +8,21 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
   <script type="application/javascript">
     function doTest()
     {
+      testTextAtOffset("line_test_1", BOUNDARY_LINE_START,
+                       [[0, 6, "Line 1 ", 0, 7],
+                        [7, 7, "", 7, 7],
+                        [8, 15, "Line 3 ", 8, 15]]);
+
       //////////////////////////////////////////////////////////////////////////
       // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 
       var IDs = [ "input", "div", "editable", "textarea",
                   getNode("ta", getNode("ta_cntr").contentDocument) ];
 
       testTextBeforeOffset(IDs, BOUNDARY_LINE_START,
@@ -245,11 +250,16 @@ two words
   </ol>
 
   <div id="ht_5">
     <div>
       <p>sectiounus</p>
       <p>seciofarus</p>
     </div>
   </div>
-
+  <div id="line_test_1">
+    Line 1
+    <center><input type="TEXT"><input value="Button" type="SUBMIT"></center>
+    Line 3
+  </div>
+  </body>
 </body>
 </html>
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -569,28 +569,28 @@ ia2Accessible::get_relationTargetsOfType
 
   if (!aTargets || !aNTargets)
     return E_INVALIDARG;
   *aNTargets = 0;
 
   Maybe<RelationType> relationType;
   for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
     if (wcscmp(aType, sRelationTypePairs[idx].second) == 0) {
-      relationType.construct(sRelationTypePairs[idx].first);
+      relationType.emplace(sRelationTypePairs[idx].first);
       break;
     }
   }
-  if (relationType.empty())
+  if (!relationType)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  Relation rel = acc->RelationByType(relationType.ref());
+  Relation rel = acc->RelationByType(*relationType);
 
   nsTArray<Accessible*> targets;
   Accessible* target = nullptr;
   while ((target = rel.Next()) &&
          static_cast<long>(targets.Length()) <= aMaxTargets)
     targets.AppendElement(target);
 
   *aNTargets = targets.Length();
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -895,17 +895,17 @@ AccessibleWrap::accNavigate(
   if (accessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* navAccessible = nullptr;
   Maybe<RelationType> xpRelation;
 
 #define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \
   case msaaType: \
-    xpRelation.construct(RelationType::geckoType); \
+    xpRelation.emplace(RelationType::geckoType); \
     break;
 
   switch(navDir) {
     case NAVDIR_FIRSTCHILD:
       if (!nsAccUtils::MustPrune(accessible))
         navAccessible = accessible->FirstChild();
       break;
     case NAVDIR_LASTCHILD:
@@ -930,18 +930,18 @@ AccessibleWrap::accNavigate(
     default:
       return E_INVALIDARG;
   }
 
 #undef RELATIONTYPE
 
   pvarEndUpAt->vt = VT_EMPTY;
 
-  if (!xpRelation.empty()) {
-    Relation rel = RelationByType(xpRelation.ref());
+  if (xpRelation) {
+    Relation rel = RelationByType(*xpRelation);
     navAccessible = rel.Next();
   }
 
   if (!navAccessible)
     return E_FAIL;
 
   pvarEndUpAt->pdispVal = NativeAccessible(navAccessible);
   pvarEndUpAt->vt = VT_DISPATCH;
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="7945ca73e687be5edbc7b928dc7fe3a208242144">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "5574ba38d87128480049442edfa2c056404b45f2", 
+    "revision": "2fb6119da922ebdab70c79e7f515f49fa582b2c5", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a2219a55145e730e56e09527b40152d68a43b0d9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5e074831f9ddacdf6f622a6dffaecb626f740be8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0296e3a38710494ec87c3da936b276afa1555afa"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/configure.in
+++ b/configure.in
@@ -2089,17 +2089,17 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy"
         CXXFLAGS="$CXXFLAGS -W3 -Gy"
-        if test "$_CC_SUITE" -ge "11"; then
+        if test "$_CC_SUITE" -ge "11" -a "$CPU_ARCH" = "x86"; then
             dnl VS2012+ defaults to -arch:SSE2.
             CFLAGS="$CFLAGS -arch:IA32"
             CXXFLAGS="$CXXFLAGS -arch:IA32"
         fi
         if test "$_CC_SUITE" -ge "12"; then
             dnl VS2013+ requires -FS when parallel building by make -jN.
             dnl If nothing, compiler sometimes causes C1041 error.
             dnl
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -127,18 +127,18 @@ class AnimationPlayer;
 class Link;
 class UndoManager;
 class DOMRect;
 class DOMRectList;
 class DestinationInsertionPointList;
 
 // IID for the dom::Element interface
 #define NS_ELEMENT_IID \
-{ 0xd123f791, 0x124a, 0x43f3, \
-  { 0x84, 0xe3, 0x55, 0x81, 0x0b, 0x6c, 0xf3, 0x08 } }
+{ 0xb0135f9d, 0xa476, 0x4711, \
+  { 0x8b, 0xb9, 0xca, 0xe5, 0x2a, 0x05, 0xf9, 0xbe } }
 
 class Element : public FragmentOrElement
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
   explicit Element(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) :
     FragmentOrElement(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -34,18 +34,18 @@ struct IMEState;
 enum nsLinkState {
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3 
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID \
-{ 0xc534a378, 0x7b5f, 0x43a4, \
-  { 0xaf, 0x65, 0x5f, 0xfe, 0xea, 0xd6, 0x00, 0xfb } }
+{ 0x329f4c0f, 0x369d, 0x4f35, \
+  { 0x9a, 0x49, 0xd6, 0xa3, 0xaf, 0xb4, 0x34, 0x9f } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
   typedef mozilla::widget::IMEState IMEState;
--- a/content/base/public/nsIDOMDataChannel.idl
+++ b/content/base/public/nsIDOMDataChannel.idl
@@ -8,17 +8,17 @@
 #ifdef GetBinaryType
 // Windows apparently has a #define for GetBinaryType...
 #undef GetBinaryType
 #endif
 %}
 
 interface nsIVariant;
 
-[builtinclass, uuid(af7077ac-0f9f-44e1-815f-9b1a94618531)]
+[builtinclass, uuid(b00a4ca7-312e-4926-84f6-8ebb43e53d83)]
 interface nsIDOMDataChannel : nsIDOMEventTarget
 {
   readonly attribute DOMString label;
   readonly attribute DOMString protocol;
   readonly attribute boolean reliable;
   readonly attribute boolean ordered;
 
   readonly attribute DOMString readyState;
--- a/content/base/public/nsIDOMFileReader.idl
+++ b/content/base/public/nsIDOMFileReader.idl
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMBlob;
 
-[builtinclass, uuid(39ea2c73-7711-4cea-9f73-3166c24dfa69)]
+[builtinclass, uuid(2f34c719-bc14-4546-9fb9-2bab75e56e45)]
 interface nsIDOMFileReader : nsIDOMEventTarget
 {
   [implicit_jscontext]
   void readAsArrayBuffer(in nsIDOMBlob filedata);
   void readAsBinaryString(in nsIDOMBlob filedata);
   void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding);
   void readAsDataURL(in nsIDOMBlob file);
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -244,18 +244,18 @@ private:
 // Categories of node properties
 // 0 is global.
 #define DOM_USER_DATA         1
 #define DOM_USER_DATA_HANDLER 2
 #define SMIL_MAPPED_ATTR_ANIMVAL 3
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0x3bd80589, 0xa6f4, 0x4a57, \
-  { 0xab, 0x38, 0xa0, 0x5b, 0x77, 0x4c, 0x3e, 0xa8 } }
+{ 0x3a60353e, 0x04e5, 0x49ca, \
+  { 0x84, 0x1c, 0x59, 0xc6, 0xde, 0xe6, 0x36, 0xcc } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public mozilla::dom::EventTarget
 {
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -11,22 +11,22 @@ interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
 interface nsIURI;
 interface nsIVariant;
 interface nsIGlobalObject;
 interface nsIInputStream;
 interface nsIDOMBlob;
 
-[builtinclass, uuid(5ced7e7a-e2c3-4563-a57d-31b97ce64dc5)]
+[builtinclass, uuid(88e7d2a0-2e5b-4f65-9624-a61e607a9948)]
 interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
   // event handler attributes
 };
 
-[builtinclass, uuid(df3796fa-d98a-4185-9dda-d2f2b56a5d38)]
+[builtinclass, uuid(d74c4dc4-bc8c-4f5d-b7f1-121a48750abe)]
 interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
   // for future use
 };
 
 /**
  * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest
  * object. The goal has been to make Mozilla's version match Microsoft's
  * version as closely as possible, but there are bound to be some differences.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1561,20 +1561,20 @@ nsDocument::nsDocument(const char* aCont
 
   if (!gCspPRLog)
     gCspPRLog = PR_NewLogModule("CSP");
 #endif
 
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
 
-  if (sProcessingStack.empty()) {
-    sProcessingStack.construct();
+  if (!sProcessingStack) {
+    sProcessingStack.emplace();
     // Add the base queue sentinel to the processing stack.
-    sProcessingStack.ref().AppendElement((CustomElementData*) nullptr);
+    sProcessingStack->AppendElement((CustomElementData*) nullptr);
   }
 }
 
 static PLDHashOperator
 ClearAllBoxObjects(nsIContent* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
 {
   if (aBoxObject) {
     aBoxObject->Clear();
@@ -5628,36 +5628,36 @@ nsDocument::EnqueueLifecycleCallback(nsI
   // Ownership of callback is taken by mCallbackQueue.
   elementData->mCallbackQueue.AppendElement(callback);
   if (aArgs) {
     callback->SetArgs(*aArgs);
   }
 
   if (!elementData->mElementIsBeingCreated) {
     CustomElementData* lastData =
-      sProcessingStack.ref().SafeLastElement(nullptr);
+      sProcessingStack->SafeLastElement(nullptr);
 
     // A new element queue needs to be pushed if the queue at the
     // top of the stack is associated with another microtask level.
     // Don't push a queue for the level 0 microtask (base element queue)
     // because we don't want to process the queue until the
     // microtask checkpoint.
     bool shouldPushElementQueue = nsContentUtils::MicroTaskLevel() > 0 &&
       (!lastData || lastData->mAssociatedMicroTask <
          static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
 
     // Push a new element queue onto the processing stack when appropriate
     // (when we enter a new microtask).
     if (shouldPushElementQueue) {
       // Push a sentinel value on the processing stack to mark the
       // boundary between the element queues.
-      sProcessingStack.ref().AppendElement((CustomElementData*) nullptr);
-    }
-
-    sProcessingStack.ref().AppendElement(elementData);
+      sProcessingStack->AppendElement((CustomElementData*) nullptr);
+    }
+
+    sProcessingStack->AppendElement(elementData);
     elementData->mAssociatedMicroTask =
       static_cast<int32_t>(nsContentUtils::MicroTaskLevel());
 
     // Add a script runner to pop and process the element queue at
     // the top of the processing stack.
     if (shouldPushElementQueue) {
       // Lifecycle callbacks enqueued by user agent implementation
       // should be invoked prior to returning control back to script.
@@ -5669,32 +5669,32 @@ nsDocument::EnqueueLifecycleCallback(nsI
 }
 
 // static
 void
 nsDocument::ProcessBaseElementQueue()
 {
   // Prevent re-entrance. Also, if a microtask checkpoint is reached
   // and there is no processing stack to process, then we are done.
-  if (sProcessingBaseElementQueue || sProcessingStack.empty()) {
+  if (sProcessingBaseElementQueue || !sProcessingStack) {
     return;
   }
 
   MOZ_ASSERT(nsContentUtils::MicroTaskLevel() == 0);
   sProcessingBaseElementQueue = true;
   nsContentUtils::AddScriptRunner(new ProcessStackRunner(true));
 }
 
 // static
 void
 nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
 {
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
-  nsTArray<CustomElementData*>& stack = sProcessingStack.ref();
+  nsTArray<CustomElementData*>& stack = *sProcessingStack;
   uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
 
   if (aIsBaseQueue && firstQueue != 0) {
     return;
   }
 
   for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
     // Callback queue may have already been processed in an earlier
@@ -11808,17 +11808,17 @@ nsIDocument::GetMozPointerLockElement()
 
   return pointerLockedElement;
 }
 
 void
 nsDocument::XPCOMShutdown()
 {
   gPendingPointerLockRequest = nullptr;
-  sProcessingStack.destroyIfConstructed();
+  sProcessingStack.reset();
 }
 
 void
 nsDocument::UpdateVisibilityState()
 {
   dom::VisibilityState oldState = mVisibilityState;
   mVisibilityState = GetVisibilityState();
   if (oldState != mVisibilityState) {
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -1992,27 +1992,27 @@ nsINode::ReplaceOrInsertBefore(bool aRep
     }
   } else if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
     // Make sure to remove all the fragment's kids.  We need to do this before
     // we start inserting anything, so we will run out XBL destructors and
     // binding teardown (GOD, I HATE THESE THINGS) before we insert anything
     // into the DOM.
     uint32_t count = newContent->GetChildCount();
 
-    fragChildren.construct();
+    fragChildren.emplace();
 
     // Copy the children into a separate array to avoid having to deal with
     // mutations to the fragment later on here.
-    fragChildren.ref().SetCapacity(count);
+    fragChildren->SetCapacity(count);
     for (nsIContent* child = newContent->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
       NS_ASSERTION(child->GetCurrentDoc() == nullptr,
                    "How did we get a child with a current doc?");
-      fragChildren.ref().AppendElement(child);
+      fragChildren->AppendElement(child);
     }
 
     // Hold a strong ref to nodeToInsertBefore across the removals
     nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
 
     nsMutationGuard guard;
 
     // Scope for the mutation batch and scriptblocker, so they go away
@@ -2035,17 +2035,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
       // it's not, there's no way we can do this insert sanely; just bail out.
       if (nodeToInsertBefore && nodeToInsertBefore->GetParent() != this) {
         aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
         return nullptr;
       }
 
       // Verify that all the things in fragChildren have no parent.
       for (uint32_t i = 0; i < count; ++i) {
-        if (fragChildren.ref().ElementAt(i)->GetParentNode()) {
+        if (fragChildren->ElementAt(i)->GetParentNode()) {
           aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
           return nullptr;
         }
       }
 
       // Note that unlike the single-element case above, none of our kids can
       // be aRefChild, so we can always pass through aReplace in the
       // IsAllowedAsChild checks below and don't have to worry about whether
@@ -2066,17 +2066,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
 
       // And verify that newContent is still allowed as our child.  Sadly, we
       // need to reimplement the relevant part of IsAllowedAsChild() because
       // now our nodes are in an array and all.  If you change this code,
       // change the code there.
       if (IsNodeOfType(nsINode::eDOCUMENT)) {
         bool sawElement = false;
         for (uint32_t i = 0; i < count; ++i) {
-          nsIContent* child = fragChildren.ref().ElementAt(i);
+          nsIContent* child = fragChildren->ElementAt(i);
           if (child->IsElement()) {
             if (sawElement) {
               // No good
               aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
               return nullptr;
             }
             sawElement = true;
           }
@@ -2154,32 +2154,32 @@ nsINode::ReplaceOrInsertBefore(bool aRep
     }
     nsAutoMutationBatch* mutationBatch = nsAutoMutationBatch::GetCurrentBatch();
     if (mutationBatch) {
       mutationBatch->RemovalDone();
       mutationBatch->SetPrevSibling(GetChildAt(insPos - 1));
       mutationBatch->SetNextSibling(GetChildAt(insPos));
     }
 
-    uint32_t count = fragChildren.ref().Length();
+    uint32_t count = fragChildren->Length();
     if (!count) {
       return result;
     }
 
     bool appending =
       !IsNodeOfType(eDOCUMENT) && uint32_t(insPos) == GetChildCount();
     int32_t firstInsPos = insPos;
-    nsIContent* firstInsertedContent = fragChildren.ref().ElementAt(0);
+    nsIContent* firstInsertedContent = fragChildren->ElementAt(0);
 
     // Iterate through the fragment's children, and insert them in the new
     // parent
     for (uint32_t i = 0; i < count; ++i, ++insPos) {
       // XXXbz how come no reparenting here?  That seems odd...
       // Insert the child.
-      aError = InsertChildAt(fragChildren.ref().ElementAt(i), insPos,
+      aError = InsertChildAt(fragChildren->ElementAt(i), insPos,
                              !appending);
       if (aError.Failed()) {
         // Make sure to notify on any children that we did succeed to insert
         if (appending && i != 0) {
           nsNodeUtils::ContentAppended(static_cast<nsIContent*>(this),
                                        firstInsertedContent,
                                        firstInsPos);
         }
@@ -2196,17 +2196,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
       nsNodeUtils::ContentAppended(static_cast<nsIContent*>(this),
                                    firstInsertedContent, firstInsPos);
       if (mutationBatch) {
         mutationBatch->NodesAdded();
       }
       // Optimize for the case when there are no listeners
       if (nsContentUtils::
             HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
-        Element::FireNodeInserted(doc, this, fragChildren.ref());
+        Element::FireNodeInserted(doc, this, *fragChildren);
       }
     }
   }
   else {
     // Not inserting a fragment but rather a single node.
 
     // FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=544654
     //       We need to reparent here for nodes for which the parent of their
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -1157,18 +1157,18 @@ nsScriptLoader::EvaluateScript(nsScriptL
     Maybe<AutoCurrentScriptUpdater> masterScriptUpdater;
     nsCOMPtr<nsIDocument> master = mDocument->MasterDocument();
     if (master != mDocument) {
       // If this script belongs to an import document, it will be
       // executed in the context of the master document. During the
       // execution currentScript of the master should refer to this
       // script. So let's update the mCurrentScript of the ScriptLoader
       // of the master document too.
-      masterScriptUpdater.construct(master->ScriptLoader(),
-                                    aRequest->mElement);
+      masterScriptUpdater.emplace(master->ScriptLoader(),
+                                  aRequest->mElement);
     }
 
     JS::CompileOptions options(entryScript.cx());
     FillCompileOptionsForRequest(entryScript, aRequest, global, &options);
     rv = nsJSUtils::EvaluateString(entryScript.cx(), aSrcBuf, global, options,
                                    aOffThreadToken);
   }
 
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -867,19 +867,19 @@ Console::Method(JSContext* aCx, MethodNa
     uint32_t language;
     nsresult rv = stack->GetLanguage(&language);
     if (NS_FAILED(rv)) {
       return;
     }
 
     if (language == nsIProgrammingLanguage::JAVASCRIPT ||
         language == nsIProgrammingLanguage::JAVASCRIPT2) {
-      callData->mTopStackFrame.construct();
+      callData->mTopStackFrame.emplace();
       nsresult rv = StackFrameToStackEntry(stack,
-                                           callData->mTopStackFrame.ref(),
+                                           *callData->mTopStackFrame,
                                            language);
       if (NS_FAILED(rv)) {
         return;
       }
 
       break;
     }
 
@@ -892,18 +892,18 @@ Console::Method(JSContext* aCx, MethodNa
     stack.swap(caller);
   } while (stack);
 
   if (NS_IsMainThread()) {
     callData->mStack = stack;
   } else {
     // nsIStackFrame is not threadsafe, so we need to snapshot it now,
     // before we post our runnable to the main thread.
-    callData->mReifiedStack.construct();
-    nsresult rv = ReifyStack(stack, callData->mReifiedStack.ref());
+    callData->mReifiedStack.emplace();
+    nsresult rv = ReifyStack(stack, *callData->mReifiedStack);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
   }
 
   // Monotonic timer for 'time' and 'timeEnd'
   if ((aMethodName == MethodTime || aMethodName == MethodTimeEnd)) {
     if (mWindow) {
@@ -1033,18 +1033,18 @@ LazyStackGetter(JSContext* aCx, unsigned
 
 void
 Console::ProcessCallData(ConsoleCallData* aData)
 {
   MOZ_ASSERT(aData);
   MOZ_ASSERT(NS_IsMainThread());
 
   ConsoleStackEntry frame;
-  if (!aData->mTopStackFrame.empty()) {
-    frame = aData->mTopStackFrame.ref();
+  if (aData->mTopStackFrame) {
+    frame = *aData->mTopStackFrame;
   }
 
   AutoSafeJSContext cx;
   ClearException ce(cx);
   RootedDictionary<ConsoleEvent> event(cx);
 
   JSAutoCompartment ac(cx, aData->mGlobal);
 
@@ -1126,19 +1126,19 @@ Console::ProcessCallData(ConsoleCallData
   if (!JS_DefineProperty(cx, eventObj, "wrappedJSObject", eventValue, JSPROP_ENUMERATE)) {
     return;
   }
 
   if (ShouldIncludeStackrace(aData->mMethodName)) {
     // Now define the "stacktrace" property on eventObj.  There are two cases
     // here.  Either we came from a worker and have a reified stack, or we want
     // to define a getter that will lazily reify the stack.
-    if (!aData->mReifiedStack.empty()) {
+    if (aData->mReifiedStack) {
       JS::Rooted<JS::Value> stacktrace(cx);
-      if (!ToJSValue(cx, aData->mReifiedStack.ref(), &stacktrace) ||
+      if (!ToJSValue(cx, *aData->mReifiedStack, &stacktrace) ||
           !JS_DefineProperty(cx, eventObj, "stacktrace", stacktrace,
                              JSPROP_ENUMERATE)) {
         return;
       }
     } else {
       JSFunction* fun = js::NewFunctionWithReserved(cx, LazyStackGetter, 0, 0,
                                                     eventObj, "stacktrace");
       if (!fun) {
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -232,20 +232,20 @@ AutoJSAPI::InitInternal(JSObject* aGloba
 {
   mCx = aCx;
   if (aIsMainThread) {
     // This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
     // can GC, which is only possible because XPCJSContextStack::Push calls
     // nsIPrincipal.Equals. Once that is removed, the Rooted<> will no longer
     // be necessary.
     JS::Rooted<JSObject*> global(JS_GetRuntime(aCx), aGlobal);
-    mCxPusher.construct(mCx);
-    mAutoNullableCompartment.construct(mCx, global);
+    mCxPusher.emplace(mCx);
+    mAutoNullableCompartment.emplace(mCx, global);
   } else {
-    mAutoNullableCompartment.construct(mCx, aGlobal);
+    mAutoNullableCompartment.emplace(mCx, aGlobal);
   }
 }
 
 AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
                      bool aIsMainThread,
                      JSContext* aCx)
 {
   MOZ_ASSERT(aGlobalObject);
@@ -343,27 +343,35 @@ AutoEntryScript::AutoEntryScript(nsIGlob
   , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
   , mWebIDLCallerPrincipal(nullptr)
 {
   MOZ_ASSERT(aGlobalObject);
   MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
   MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
 }
 
+AutoEntryScript::~AutoEntryScript()
+{
+  // GC when we pop a script entry point. This is a useful heuristic that helps
+  // us out on certain (flawed) benchmarks like sunspider, because it lets us
+  // avoid GCing during the timing loop.
+  JS_MaybeGC(cx());
+}
+
 AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
   : ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ false)
   , mCallerOverride(nsContentUtils::GetCurrentJSContextForThread())
 {
 }
 
 AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
   : ScriptSettingsStackEntry()
 {
   MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContextForThread(),
                 !JS_IsExceptionPending(nsContentUtils::GetCurrentJSContextForThread()));
   if (aIsMainThread) {
-    mCxPusher.construct(static_cast<JSContext*>(nullptr),
-                        /* aAllowNull = */ true);
+    mCxPusher.emplace(static_cast<JSContext*>(nullptr),
+                      /* aAllowNull = */ true);
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -117,17 +117,17 @@ private:
  *
  * In situations where the consumer expects to run script, AutoEntryScript
  * should be used, which does additional manipulation of the script settings
  * stack. In bug 991758, we'll add hard invariants to SpiderMonkey, such that
  * any attempt to run script without an AutoEntryScript on the stack will
  * fail. This prevents system code from accidentally triggering script
  * execution at inopportune moments via surreptitious getters and proxies.
  */
-class AutoJSAPI {
+class MOZ_STACK_CLASS AutoJSAPI {
 public:
   // Trivial constructor. One of the Init functions must be called before
   // accessing the JSContext through cx().
   AutoJSAPI();
 
   // This uses the SafeJSContext (or worker equivalent), and enters a null
   // compartment, so that the consumer is forced to select a compartment to
   // enter before manipulating objects.
@@ -167,17 +167,17 @@ public:
   bool InitWithLegacyErrorReporting(nsGlobalWindow* aWindow);
 
   JSContext* cx() const {
     MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
     MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
     return mCx;
   }
 
-  bool CxPusherIsStackTop() const { return mCxPusher.ref().IsStackTop(); }
+  bool CxPusherIsStackTop() const { return mCxPusher->IsStackTop(); }
 
 protected:
   // Protected constructor, allowing subclasses to specify a particular cx to
   // be used. This constructor initialises the AutoJSAPI, so Init must NOT be
   // called on subclasses that use this.
   // If aGlobalObject, its associated JS global or aCx are null this will cause
   // an assertion, as will setting aIsMainThread incorrectly.
   AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
@@ -196,16 +196,18 @@ private:
 class AutoEntryScript : public AutoJSAPI,
                         protected ScriptSettingsStackEntry {
 public:
   explicit AutoEntryScript(nsIGlobalObject* aGlobalObject,
                   bool aIsMainThread = NS_IsMainThread(),
                   // Note: aCx is mandatory off-main-thread.
                   JSContext* aCx = nullptr);
 
+  ~AutoEntryScript();
+
   void SetWebIDLCallerPrincipal(nsIPrincipal *aPrincipal) {
     mWebIDLCallerPrincipal = aPrincipal;
   }
 
 private:
   // It's safe to make this a weak pointer, since it's the subject principal
   // when we go on the stack, so can't go away until after we're gone.  In
   // particular, this is only used from the CallSetup constructor, and only in
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11793,17 +11793,17 @@ nsGlobalWindow::OpenInternal(const nsASt
       if (aJSCallerContext) {
         // If script in some other window is doing a window.open on us and
         // it's being blocked, then it's OK to close us afterwards, probably.
         // But if we're doing a window.open on ourselves and block the popup,
         // prevent this window from closing until after this script terminates
         // so that whatever popup blocker UI the app has will be visible.
         if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) {
           mBlockScriptedClosingFlag = true;
-          closeUnblocker.construct(this);
+          closeUnblocker.emplace(this);
         }
       }
 
       FireAbuseEvents(true, false, aUrl, aName, aOptions);
       return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
     }
   }
 
@@ -11842,17 +11842,17 @@ nsGlobalWindow::OpenInternal(const nsASt
       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
 
       // Note: Because nsWindowWatcher is so broken, it's actually important
       // that we don't force a system caller here, because that screws it up
       // when it tries to compute the caller principal to associate with dialog
       // arguments. That whole setup just really needs to be rewritten. :-(
       Maybe<AutoNoJSAPI> nojsapi;
       if (!aContentModal) {
-        nojsapi.construct();
+        nojsapi.emplace();
       }
 
 
       rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
                                 /* aCalledFromScript = */ false,
                                 aDialog, aNavigate, nullptr, aExtraArgument,
                                 getter_AddRefs(domReturn));
 
--- a/dom/base/nsIDOMDOMRequest.idl
+++ b/dom/base/nsIDOMDOMRequest.idl
@@ -5,17 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMWindow;
 interface nsIDOMDOMCursor;
 interface nsICursorContinueCallback;
 
-[builtinclass, uuid(d4c7372a-661c-4798-9a13-af48128609e9)]
+[builtinclass, uuid(e39da69e-2232-4e49-9856-b8a4a6210336)]
 interface nsIDOMDOMRequest : nsIDOMEventTarget
 {
   readonly attribute DOMString readyState; // "pending" or "done"
 
   readonly attribute jsval result;
 
   // DOMError
   readonly attribute nsISupports error;
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -222,17 +222,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
   bool ok = false;
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK);
 
   mozilla::Maybe<AutoDontReportUncaught> dontReport;
   if (!aEvaluateOptions.reportUncaught) {
     // We need to prevent AutoLastFrameCheck from reporting and clearing
     // any pending exceptions.
-    dontReport.construct(aCx);
+    dontReport.emplace(aCx);
   }
 
   // Scope the JSAutoCompartment so that we can later wrap the return value
   // into the caller's cx.
   {
     JSAutoCompartment ac(aCx, aScopeObject);
 
     JS::Rooted<JSObject*> rootedScope(aCx, aScopeObject);
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -101,73 +101,71 @@ template<typename T, typename InternalTy
 class Optional_base
 {
 public:
   Optional_base()
   {}
 
   explicit Optional_base(const T& aValue)
   {
-    mImpl.construct(aValue);
+    mImpl.emplace(aValue);
   }
 
   template<typename T1, typename T2>
   explicit Optional_base(const T1& aValue1, const T2& aValue2)
   {
-    mImpl.construct(aValue1, aValue2);
+    mImpl.emplace(aValue1, aValue2);
   }
 
   bool WasPassed() const
   {
-    return !mImpl.empty();
+    return mImpl.isSome();
   }
 
   // Return InternalType here so we can work with it usefully.
   InternalType& Construct()
   {
-    mImpl.construct();
-    return mImpl.ref();
+    mImpl.emplace();
+    return *mImpl;
   }
 
   template <class T1>
   InternalType& Construct(const T1 &t1)
   {
-    mImpl.construct(t1);
-    return mImpl.ref();
+    mImpl.emplace(t1);
+    return *mImpl;
   }
 
   template <class T1, class T2>
   InternalType& Construct(const T1 &t1, const T2 &t2)
   {
-    mImpl.construct(t1, t2);
-    return mImpl.ref();
+    mImpl.emplace(t1, t2);
+    return *mImpl;
   }
 
   void Reset()
   {
-    if (WasPassed()) {
-      mImpl.destroy();
-    }
+    mImpl.reset();
   }
 
   const T& Value() const
   {
-    return mImpl.ref();
+    return *mImpl;
   }
 
   // Return InternalType here so we can work with it usefully.
   InternalType& Value()
   {
-    return mImpl.ref();
+    return *mImpl;
   }
 
   // And an explicit way to get the InternalType even if we're const.
   const InternalType& InternalValue() const
   {
-    return mImpl.ref();
+    return *mImpl;
   }
 
   // If we ever decide to add conversion operators for optional arrays
   // like the ones Nullable has, we'll need to ensure that Maybe<> has
   // the boolean before the actual data.
 
 private:
   // Forbid copy-construction and assignment
@@ -209,24 +207,24 @@ public:
   Optional(JSContext* cx, const T& aValue) :
     Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
   {}
 
   // Override the const Value() to return the right thing so we're not
   // returning references to temporaries.
   JS::Handle<T> Value() const
   {
-    return this->mImpl.ref();
+    return *this->mImpl;
   }
 
   // And we have to override the non-const one too, since we're
   // shadowing the one on the superclass.
   JS::Rooted<T>& Value()
   {
-    return this->mImpl.ref();
+    return *this->mImpl;
   }
 };
 
 // A specialization of Optional for JSObject* to make sure that when someone
 // calls Construct() on it we will pre-initialized the JSObject* to nullptr so
 // it can be traced safely.
 template<>
 class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*>
@@ -272,46 +270,46 @@ template<typename T>
 class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
 {
 public:
   // We want our Value to actually return a non-const reference, even
   // if we're const.  At least for things that are normally pointer
   // types...
   T& Value() const
   {
-    return *this->mImpl.ref().get();
+    return *this->mImpl->get();
   }
 
   // And we have to override the non-const one too, since we're
   // shadowing the one on the superclass.
   NonNull<T>& Value()
   {
-    return this->mImpl.ref();
+    return *this->mImpl;
   }
 };
 
 // A specialization of Optional for OwningNonNull that lets us get a
 // T& from Value()
 template<typename T>
 class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> >
 {
 public:
   // We want our Value to actually return a non-const reference, even
   // if we're const.  At least for things that are normally pointer
   // types...
   T& Value() const
   {
-    return *this->mImpl.ref().get();
+    return *this->mImpl->get();
   }
 
   // And we have to override the non-const one too, since we're
   // shadowing the one on the superclass.
   OwningNonNull<T>& Value()
   {
-    return this->mImpl.ref();
+    return *this->mImpl;
   }
 };
 
 // Specialization for strings.
 // XXXbz we can't pull in FakeString here, because it depends on internal
 // strings.  So we just have to forward-declare it and reimplement its
 // ToAStringPtr.
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1554,17 +1554,17 @@ GetPropertyOnPrototype(JSContext* cx, JS
 bool
 HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
                        JS::Handle<jsid> id)
 {
   JS::Rooted<JSObject*> obj(cx, proxy);
   Maybe<JSAutoCompartment> ac;
   if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
     obj = js::UncheckedUnwrap(obj);
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
   }
 
   bool found;
   // We ignore an error from GetPropertyOnPrototype.  We pass nullptr
   // for vp so that GetPropertyOnPrototype won't actually do a get.
   return !GetPropertyOnPrototype(cx, obj, id, &found, nullptr) || found;
 }
 
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -918,17 +918,17 @@ WrapNewBindingNonWrapperCachedObject(JSC
     // Maybe<Handle> doesn't so much work, and in any case, adding
     // more Maybe (one for a Rooted and one for a Handle) adds more
     // code (and branches!) than just adding a single rooted.
     JS::Rooted<JSObject*> scope(cx, scopeArg);
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
       if (!scope)
         return false;
-      ac.construct(cx, scope);
+      ac.emplace(cx, scope);
     }
 
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
     obj = value->WrapObject(cx);
   }
 
   if (!obj) {
     return false;
@@ -965,17 +965,17 @@ WrapNewBindingNonWrapperCachedOwnedObjec
     // Maybe<Handle> doesn't so much work, and in any case, adding
     // more Maybe (one for a Rooted and one for a Handle) adds more
     // code (and branches!) than just adding a single rooted.
     JS::Rooted<JSObject*> scope(cx, scopeArg);
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
       if (!scope)
         return false;
-      ac.construct(cx, scope);
+      ac.emplace(cx, scope);
     }
 
     bool tookOwnership = false;
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
     obj = value->WrapObject(cx, &tookOwnership);
     MOZ_ASSERT_IF(obj, tookOwnership);
     if (tookOwnership) {
       value.forget();
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -121,41 +121,41 @@ CallbackObject::CallSetup::CallSetup(Cal
 
     // Bail out if there's no useful global. This seems to happen intermittently
     // on gaia-ui tests, probably because nsInProcessTabChildGlobal is returning
     // null in some kind of teardown state.
     if (!globalObject->GetGlobalJSObject()) {
       return;
     }
 
-    mAutoEntryScript.construct(globalObject, mIsMainThread, cx);
-    mAutoEntryScript.ref().SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
+    mAutoEntryScript.emplace(globalObject, mIsMainThread, cx);
+    mAutoEntryScript->SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
     nsIGlobalObject* incumbent = aCallback->IncumbentGlobalOrNull();
     if (incumbent) {
       // The callback object traces its incumbent JS global, so in general it
       // should be alive here. However, it's possible that we could run afoul
       // of the same IPC global weirdness described above, wherein the
       // nsIGlobalObject has severed its reference to the JS global. Let's just
       // be safe here, so that nobody has to waste a day debugging gaia-ui tests.
       if (!incumbent->GetGlobalJSObject()) {
         return;
       }
-      mAutoIncumbentScript.construct(incumbent);
+      mAutoIncumbentScript.emplace(incumbent);
     }
 
     // Unmark the callable (by invoking Callback() and not the CallbackPreserveColor()
     // variant), and stick it in a Rooted before it can go gray again.
     // Nothing before us in this function can trigger a CC, so it's safe to wait
     // until here it do the unmark. This allows us to order the following two
     // operations _after_ the Push() above, which lets us take advantage of the
     // JSAutoRequest embedded in the pusher.
     //
     // We can do this even though we're not in the right compartment yet, because
     // Rooted<> does not care about compartments.
-    mRootedCallable.construct(cx, aCallback->Callback());
+    mRootedCallable.emplace(cx, aCallback->Callback());
   }
 
   // JS-implemented WebIDL is always OK to run, since it runs with Chrome
   // privileges anyway.
   if (mIsMainThread && !aIsJSImplementedWebIDL) {
     // Check that it's ok to run this callback at all.
     // Make sure to use realCallback to get the global of the callback object,
     // not the wrapper.
@@ -167,17 +167,17 @@ CallbackObject::CallSetup::CallSetup(Cal
     }
   }
 
   // Enter the compartment of our callback, so we can actually work with it.
   //
   // Note that if the callback is a wrapper, this will not be the same
   // compartment that we ended up in with mAutoEntryScript above, because the
   // entry point is based off of the unwrapped callback (realCallback).
-  mAc.construct(cx, mRootedCallable.ref());
+  mAc.emplace(cx, *mRootedCallable);
 
   // And now we're ready to go.
   mCx = cx;
 
   // Make sure the JS engine doesn't report exceptions we want to re-throw
   if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
       mExceptionHandling == eRethrowExceptions) {
     mSavedJSContextOptions = JS::ContextOptionsRef(cx);
@@ -214,17 +214,17 @@ CallbackObject::CallSetup::ShouldRethrow
 
 CallbackObject::CallSetup::~CallSetup()
 {
   // To get our nesting right we have to destroy our JSAutoCompartment first.
   // In particular, we want to do this before we try reporting any exceptions,
   // so we end up reporting them while in the compartment of our entry point,
   // not whatever cross-compartment wrappper mCallback might be.
   // Be careful: the JSAutoCompartment might not have been constructed at all!
-  mAc.destroyIfConstructed();
+  mAc.reset();
 
   // Now, if we have a JSContext, report any pending errors on it, unless we
   // were told to re-throw them.
   if (mCx) {
     bool needToDealWithException = JS_IsExceptionPending(mCx);
     if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
         mExceptionHandling == eRethrowExceptions) {
       // Restore the old context options
@@ -268,18 +268,18 @@ CallbackObject::CallSetup::~CallSetup()
         JS_ReportPendingException(mCx);
       }
       if (saved) {
         JS_RestoreFrameChain(mCx);
       }
     }
   }
 
-  mAutoIncumbentScript.destroyIfConstructed();
-  mAutoEntryScript.destroyIfConstructed();
+  mAutoIncumbentScript.reset();
+  mAutoEntryScript.reset();
 
   // It is important that this is the last thing we do, after leaving the
   // compartment and undoing all our entry/incumbent script changes
   if (mIsMainThread) {
     nsContentUtils::LeaveMicroTask();
   }
 }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -550,17 +550,17 @@ def CallOnUnforgeableHolder(descriptor, 
         pre = fill(
             """
             // Scope for 'global', 'ac' and 'unforgeableHolder'
             {
               JS::Rooted<JSObject*> global(cx);
               Maybe<JSAutoCompartment> ac;
               if (${isXrayCheck}) {
                 global = js::GetGlobalForObjectCrossCompartment(js::UncheckedUnwrap(proxy));
-                ac.construct(cx, global);
+                ac.emplace(cx, global);
               } else {
                 global = js::GetGlobalForObjectCrossCompartment(proxy);
               }
             """,
             isXrayCheck=isXrayCheck)
     else:
         pre = dedent("""
             // Scope for 'global' and 'unforgeableHolder'
@@ -4333,17 +4333,17 @@ def getJSToNativeConversionInfo(type, de
             if isOptional and not isMember:
                 holderArgs = "${declName}.Value().SetValue()"
                 declType = CGTemplatedType("Optional", declType)
                 constructDecl = CGGeneric("${declName}.Construct();\n")
                 declLoc = "${declName}.Value()"
             else:
                 holderArgs = "${declName}.SetValue()"
             if holderType is not None:
-                constructHolder = CGGeneric("${holderName}.construct(%s);\n" % holderArgs)
+                constructHolder = CGGeneric("${holderName}.emplace(%s);\n" % holderArgs)
             else:
                 constructHolder = None
             # Don't need to pass those args when the holder is being constructed
             holderArgs = None
         else:
             holderArgs = "${declName}"
             constructHolder = None
 
@@ -5085,17 +5085,17 @@ def instantiateJSToNativeConversion(info
         if dealWithOptional:
             declConstruct = CGIndenter(
                 CGGeneric("%s.Construct(%s);\n" %
                           (originalDeclName,
                            getArgsCGThing(info.declArgs).define() if
                            info.declArgs else "")))
             if holderType is not None:
                 holderConstruct = CGIndenter(
-                    CGGeneric("%s.construct(%s);\n" %
+                    CGGeneric("%s.emplace(%s);\n" %
                               (originalHolderName,
                                getArgsCGThing(info.holderArgs).define() if
                                info.holderArgs else "")))
             else:
                 holderConstruct = None
         else:
             declConstruct = None
             holderConstruct = None
@@ -6322,23 +6322,23 @@ class CGPerSignatureCall(CGThing):
         argsPost = []
         if isConstructor:
             needsUnwrap = True
             needsUnwrappedVar = False
             unwrappedVar = "obj"
         elif descriptor.interface.isJSImplemented():
             needsUnwrap = True
             needsUnwrappedVar = True
-            argsPost.append("js::GetObjectCompartment(unwrappedObj.empty() ? obj : unwrappedObj.ref())")
+            argsPost.append("js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)")
         elif needScopeObject(returnType, arguments, self.extendedAttributes,
                              descriptor.wrapperCache, True,
                              idlNode.getExtendedAttribute("StoreInSlot")):
             needsUnwrap = True
             needsUnwrappedVar = True
-            argsPre.append("unwrappedObj.empty() ? obj : unwrappedObj.ref()")
+            argsPre.append("unwrappedObj ? *unwrappedObj : obj")
 
         if needsUnwrap and needsUnwrappedVar:
             # We cannot assign into obj because it's a Handle, not a
             # MutableHandle, so we need a separate Rooted.
             cgThings.append(CGGeneric("Maybe<JS::Rooted<JSObject*> > unwrappedObj;\n"))
             unwrappedVar = "unwrappedObj.ref()"
 
         if idlNode.isMethod() and idlNode.isLegacycaller():
@@ -6362,17 +6362,17 @@ class CGPerSignatureCall(CGThing):
             # It's very important that we construct our unwrappedObj, if we need
             # to do it, before we might start setting up Rooted things for our
             # arguments, so that we don't violate the stack discipline Rooted
             # depends on.
             cgThings.append(CGGeneric(
                 "bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);\n"))
             if needsUnwrappedVar:
                 cgThings.append(CGIfWrapper(
-                    CGGeneric("unwrappedObj.construct(cx, obj);\n"),
+                    CGGeneric("unwrappedObj.emplace(cx, obj);\n"),
                     "objIsXray"))
 
         for i in range(argConversionStartsAt, self.argCount):
             cgThings.append(
                 CGArgumentConverter(arguments[i], i, self.descriptor,
                                     argDescription % {"index": i + 1},
                                     invalidEnumValueFatal=not setter,
                                     lenientFloatCode=lenientFloatCode))
@@ -6397,17 +6397,17 @@ class CGPerSignatureCall(CGThing):
                 # that compartment as needed.  This is all happening after we've
                 # already done the conversions from JS values to WebIDL (C++)
                 # values, so we only need to worry about cases where there are 'any'
                 # or 'object' types, or other things that we represent as actual
                 # JSAPI types, present.  Effectively, we're emulating a
                 # CrossCompartmentWrapper, but working with the C++ types, not the
                 # original list of JS::Values.
                 cgThings.append(CGGeneric("Maybe<JSAutoCompartment> ac;\n"))
-                xraySteps.append(CGGeneric("ac.construct(cx, obj);\n"))
+                xraySteps.append(CGGeneric("ac.emplace(cx, obj);\n"))
                 xraySteps.extend(
                     wrapArgIntoCurrentCompartment(arg, argname, isMember=False)
                     for arg, argname in self.getArguments())
 
             cgThings.append(
                 CGIfWrapper(CGList(xraySteps),
                             "objIsXray"))
 
@@ -8280,17 +8280,17 @@ def getUnionTypeTemplateVars(unionType, 
     conversionInfo = getJSToNativeConversionInfo(
         type, descriptorProvider, failureCode=tryNextCode,
         isDefinitelyObject=not type.isDictionary(),
         isMember=("OwningUnion" if ownsMembers else None),
         sourceDescription="member of %s" % unionType)
 
     if conversionInfo.holderType is not None:
         assert not ownsMembers
-        destroyHolder = "%s.destroy();\n" % holderName
+        destroyHolder = "%s.reset();\n" % holderName
     else:
         destroyHolder = ""
 
     ctorNeedsCx = conversionInfo.declArgs == "cx"
     ctorArgs = "cx" if ctorNeedsCx else ""
 
     structType = conversionInfo.declType.define()
     externalType = getUnionAccessorSignatureType(type, descriptorProvider).define()
@@ -8316,17 +8316,17 @@ def getUnionTypeTemplateVars(unionType, 
 
     else:
         # Important: we need to not have our declName involve
         # maybe-GCing operations.
         if conversionInfo.holderType is not None:
             holderArgs = conversionInfo.holderArgs
             if holderArgs is None:
                 holderArgs = ""
-            initHolder = "%s.construct(%s);\n" % (holderName, holderArgs)
+            initHolder = "%s.emplace(%s);\n" % (holderName, holderArgs)
         else:
             initHolder = ""
 
         jsConversion = fill(
             initHolder + conversionInfo.template,
             val="value",
             declName="memberSlot",
             holderName=(holderName if ownsMembers else "%s.ref()" % holderName),
@@ -11062,18 +11062,18 @@ class CGDictionary(CGThing):
         if memberInits:
             body += fill(
                 """
                 bool isNull = val.isNullOrUndefined();
                 // We only need these if !isNull, in which case we have |cx|.
                 Maybe<JS::Rooted<JSObject *> > object;
                 Maybe<JS::Rooted<JS::Value> > temp;
                 if (!isNull) {
-                  object.construct(cx, &val.toObject());
-                  temp.construct(cx);
+                  object.emplace(cx, &val.toObject());
+                  temp.emplace(cx);
                 }
                 $*{memberInits}
                 """,
                 memberInits="\n".join(memberInits))
 
         body += "return true;\n"
 
         return ClassMethod("Init", "bool", [
@@ -11316,35 +11316,35 @@ class CGDictionary(CGThing):
             # anything we want.
             "holderName": "holder"
         }
         # We can't handle having a holderType here
         assert conversionInfo.holderType is None
         if conversionInfo.dealWithOptional:
             replacements["declName"] = "(" + replacements["declName"] + ".Value())"
         if member.defaultValue:
-            replacements["haveValue"] = "!isNull && !temp.ref().isUndefined()"
+            replacements["haveValue"] = "!isNull && !temp->isUndefined()"
 
         propId = self.makeIdName(member.identifier.name)
-        propGet = ("JS_GetPropertyById(cx, object.ref(), atomsCache->%s, &temp.ref())" %
+        propGet = ("JS_GetPropertyById(cx, *object, atomsCache->%s, temp.ptr())" %
                    propId)
 
         conversionReplacements = {
             "prop": self.makeMemberName(member.identifier.name),
             "convert": string.Template(conversionInfo.template).substitute(replacements),
             "propGet": propGet
         }
         conversion = ("if (!isNull && !${propGet}) {\n"
                       "  return false;\n"
                       "}\n")
         if member.defaultValue:
             conversion += "${convert}"
         else:
             conversion += (
-                "if (!isNull && !temp.ref().isUndefined()) {\n"
+                "if (!isNull && !temp->isUndefined()) {\n"
                 "  ${prop}.Construct();\n"
                 "${convert}"
                 "}\n")
             conversionReplacements["convert"] = indent(conversionReplacements["convert"])
 
         return CGGeneric(
             string.Template(conversion).substitute(conversionReplacements))
 
--- a/dom/bindings/DOMString.h
+++ b/dom/bindings/DOMString.h
@@ -41,41 +41,41 @@ class MOZ_STACK_CLASS DOMString {
 public:
   DOMString()
     : mStringBuffer(nullptr)
     , mLength(0)
     , mIsNull(false)
   {}
   ~DOMString()
   {
-    MOZ_ASSERT(mString.empty() || !mStringBuffer,
+    MOZ_ASSERT(!mString || !mStringBuffer,
                "Shouldn't have both present!");
   }
 
   operator nsString&()
   {
     return AsAString();
   }
 
   nsString& AsAString()
   {
     MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?");
     MOZ_ASSERT(!mIsNull, "We're already set as null");
-    if (mString.empty()) {
-      mString.construct();
+    if (!mString) {
+      mString.emplace();
     }
-    return mString.ref();
+    return *mString;
   }
 
   bool HasStringBuffer() const
   {
-    MOZ_ASSERT(mString.empty() || !mStringBuffer,
+    MOZ_ASSERT(!mString || !mStringBuffer,
                "Shouldn't have both present!");
     MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
-    return mString.empty();
+    return !mString;
   }
 
   // Get the stringbuffer.  This can only be called if HasStringBuffer()
   // returned true and StringBufferLength() is nonzero.  If that's true, it will
   // never return null.
   nsStringBuffer* StringBuffer() const
   {
     MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
@@ -92,27 +92,27 @@ public:
   uint32_t StringBufferLength() const
   {
     MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer");
     return mLength;
   }
 
   void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength)
   {
-    MOZ_ASSERT(mString.empty(), "We already have a string?");
+    MOZ_ASSERT(mString.isNothing(), "We already have a string?");
     MOZ_ASSERT(!mIsNull, "We're already set as null");
     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
     MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
     mStringBuffer = aStringBuffer;
     mLength = aLength;
   }
 
   void SetOwnedString(const nsAString& aString)
   {
-    MOZ_ASSERT(mString.empty(), "We already have a string?");
+    MOZ_ASSERT(mString.isNothing(), "We already have a string?");
     MOZ_ASSERT(!mIsNull, "We're already set as null");
     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
     nsStringBuffer* buf = nsStringBuffer::FromString(aString);
     if (buf) {
       SetStringBuffer(buf, aString.Length());
     } else if (aString.IsVoid()) {
       SetNull();
     } else if (!aString.IsEmpty()) {
@@ -124,39 +124,39 @@ public:
   {
     eTreatNullAsNull,
     eTreatNullAsEmpty,
     eNullNotExpected
   };
 
   void SetOwnedAtom(nsIAtom* aAtom, NullHandling aNullHandling)
   {
-    MOZ_ASSERT(mString.empty(), "We already have a string?");
+    MOZ_ASSERT(mString.isNothing(), "We already have a string?");
     MOZ_ASSERT(!mIsNull, "We're already set as null");
     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
     MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected);
     if (aNullHandling == eNullNotExpected || aAtom) {
       SetStringBuffer(aAtom->GetStringBuffer(), aAtom->GetLength());
     } else if (aNullHandling == eTreatNullAsNull) {
       SetNull();
     }
   }
 
   void SetNull()
   {
     MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
-    MOZ_ASSERT(mString.empty(), "Should have no string if null");
+    MOZ_ASSERT(mString.isNothing(), "Should have no string if null");
     mIsNull = true;
   }
 
   bool IsNull() const
   {
-    MOZ_ASSERT(!mStringBuffer || mString.empty(),
+    MOZ_ASSERT(!mStringBuffer || mString.isNothing(),
                "How could we have a stringbuffer and a nonempty string?");
-    return mIsNull || (!mString.empty() && mString.ref().IsVoid());
+    return mIsNull || (mString && mString->IsVoid());
   }
 
   void ToString(nsAString& aString)
   {
     if (IsNull()) {
       SetDOMStringToNull(aString);
     } else if (HasStringBuffer()) {
       if (StringBufferLength() == 0) {
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -157,17 +157,17 @@ public:
   }
 
   static inline JSObject*
   Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
          const T* data = nullptr) {
     JS::Rooted<JSObject*> creatorWrapper(cx);
     Maybe<JSAutoCompartment> ac;
     if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
-      ac.construct(cx, creatorWrapper);
+      ac.emplace(cx, creatorWrapper);
     }
 
     return CreateCommon(cx, length, data);
   }
 
   static inline JSObject*
   Create(JSContext* cx, uint32_t length, const T* data = nullptr) {
     return CreateCommon(cx, length, data);
--- a/dom/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth2/BluetoothAdapter.cpp
@@ -916,17 +916,17 @@ BluetoothAdapter::HandleDevicePaired(con
   if (index != mDevices.NoIndex) {
     pairedDevice = mDevices[index];
   } else {
     mDevices.AppendElement(pairedDevice);
   }
 
   // Notify application of paired device
   BluetoothDeviceEventInit init;
-  init.mDevice = pairedDevice.
+  init.mDevice = pairedDevice;
   DispatchDeviceEvent(NS_LITERAL_STRING("devicepaired"), init);
 }
 
 void
 BluetoothAdapter::HandleDeviceUnpaired(const BluetoothValue& aValue)
 {
   MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
 
--- a/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp
@@ -748,17 +748,17 @@ BondStateChangedCallback(bt_status_t aSt
 
   nsAutoString remoteBdAddress;
   BdAddressTypeToString(aRemoteBdAddress, remoteBdAddress);
 
   bool bonded = (aState == BT_BOND_STATE_BONDED);
 
   // Update attribute BluetoothDevice.paired
   InfallibleTArray<BluetoothNamedValue> props;
-  BT_APPEND_NAMED_VALUE(props, "paired", bonded);
+  BT_APPEND_NAMED_VALUE(props, "Paired", bonded);
 
   BluetoothSignal deviceSignal(NS_LITERAL_STRING("PropertyChanged"),
                                remoteBdAddress,
                                BluetoothValue(props));
   NS_DispatchToMainThread(new DistributeBluetoothSignalTask(deviceSignal));
 
   props.Clear();
 
--- a/dom/bluetooth2/tests/marionette/head.js
+++ b/dom/bluetooth2/tests/marionette/head.js
@@ -576,17 +576,17 @@ function waitForAdapterAttributeChanged(
  *        The number of remote devices we expect to discover.
  *
  * @return A deferred promise.
  */
 function waitForDevicesFound(aDiscoveryHandle, aExpectedNumberOfDevices) {
   let deferred = Promise.defer();
 
   ok(aDiscoveryHandle instanceof BluetoothDiscoveryHandle,
-    "discoveryHandle should be a BluetoothDiscoveryHandle");
+    "aDiscoveryHandle should be a BluetoothDiscoveryHandle");
 
   let devicesArray = [];
   aDiscoveryHandle.ondevicefound = function onDeviceFound(aEvent) {
     ok(aEvent instanceof BluetoothDeviceEvent,
       "aEvent should be a BluetoothDeviceEvent");
 
     devicesArray.push(aEvent);
     if (devicesArray.length >= aExpectedNumberOfDevices) {
@@ -594,16 +594,202 @@ function waitForDevicesFound(aDiscoveryH
       deferred.resolve(devicesArray);
     }
   };
 
   return deferred.promise;
 }
 
 /**
+ * Wait for 'devicefound' events of specified devices.
+ *
+ * Resolve if every specified device has been found. Never reject.
+ *
+ * Fulfill params: an array which contains the BluetoothDeviceEvents that we
+ *                 expected to receive from the BluetoothDiscoveryHandle.
+ *
+ * @param aDiscoveryHandle
+ *        A BluetoothDiscoveryHandle which is used to notify application of
+ *        discovered remote bluetooth devices.
+ * @param aRemoteAddresses
+ *        An array which contains addresses of remote devices.
+ *
+ * @return A deferred promise.
+ */
+function waitForSpecifiedDevicesFound(aDiscoveryHandle, aRemoteAddresses) {
+  let deferred = Promise.defer();
+
+  ok(aDiscoveryHandle instanceof BluetoothDiscoveryHandle,
+    "aDiscoveryHandle should be a BluetoothDiscoveryHandle");
+
+  let devicesArray = [];
+  aDiscoveryHandle.ondevicefound = function onDeviceFound(aEvent) {
+    ok(aEvent instanceof BluetoothDeviceEvent,
+      "aEvent should be a BluetoothDeviceEvent");
+
+    if (aRemoteAddresses.indexOf(aEvent.device.address) != -1) {
+      devicesArray.push(aEvent);
+    }
+    if (devicesArray.length == aRemoteAddresses.length) {
+      aDiscoveryHandle.ondevicefound = null;
+      ok(true, "BluetoothAdapter has found all remote devices.");
+      deferred.resolve(devicesArray);
+    }
+  };
+
+  return deferred.promise;
+}
+
+/**
+ * Verify the correctness of 'devicepaired' or 'deviceunpaired' events.
+ *
+ * Use BluetoothAdapter.getPairedDevices() to get current device array.
+ * Resolve if the device of from 'devicepaired' event exists in device array or
+ * the device of address from 'deviceunpaired' event has been removed from
+ * device array.
+ * Otherwise, reject the promise.
+ *
+ * Fulfill params: the device event from 'devicepaired' or 'deviceunpaired'.
+ *
+ * @param aAdapter
+ *        The BluetoothAdapter you want to use.
+ * @param aDeviceEvent
+ *        The device event from "devicepaired" or "deviceunpaired".
+ *
+ * @return A deferred promise.
+ */
+function verifyDevicePairedUnpairedEvent(aAdapter, aDeviceEvent) {
+  let deferred = Promise.defer();
+
+  let devices = aAdapter.getPairedDevices();
+  let isPromisePending = true;
+  if (aDeviceEvent.device) {
+    log("  - Verify 'devicepaired' event");
+    for (let i in devices) {
+      if (devices[i].address == aDeviceEvent.device.address) {
+        deferred.resolve(aDeviceEvent);
+        isPromisePending = false;
+      }
+    }
+    if (isPromisePending) {
+      deferred.reject(aDeviceEvent);
+      isPromisePending = false;
+    }
+  } else if (aDeviceEvent.address) {
+    log("  - Verify 'deviceunpaired' event");
+    for (let i in devices) {
+      if (devices[i].address == aDeviceEvent.address) {
+        deferred.reject(aDeviceEvent);
+        isPromisePending = false;
+      }
+    }
+    if (isPromisePending) {
+      deferred.resolve(aDeviceEvent);
+      isPromisePending = false;
+    }
+  } else {
+    log("  - Exception occurs. Unexpected aDeviceEvent properties.");
+    deferred.reject(aDeviceEvent);
+    isPromisePending = false;
+  }
+
+  return deferred.promise;
+}
+
+/**
+ * Add event handlers for pairing request listener.
+ *
+ * @param aAdapter
+ *        The BluetoothAdapter you want to use.
+ * @param aSpecifiedBdAddress (optional)
+ *        Bluetooth address of the specified remote device which adapter wants
+ *        to pair with. If aSpecifiedBdAddress is an empty string, 'null' or
+ *        'undefined', this function accepts every pairing request.
+ */
+function addEventHandlerForPairingRequest(aAdapter, aSpecifiedBdAddress) {
+  log("  - Add event handlers for pairing requests.");
+
+  aAdapter.pairingReqs.ondisplaypasskeyreq = function onDisplayPasskeyReq(evt) {
+    let passkey = evt.handle.passkey; // passkey to display
+    ok(typeof passkey === 'string', "type checking for passkey.");
+    log("  - Received 'ondisplaypasskeyreq' event with passkey: " + passkey);
+
+    let device = evt.device;
+    if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
+      cleanupPairingListener(aAdapter.pairingReqs);
+    }
+  };
+
+  aAdapter.pairingReqs.onenterpincodereq = function onEnterPinCodeReq(evt) {
+    log("  - Received 'onenterpincodereq' event.");
+
+    let device = evt.device;
+    if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
+      // TODO: Allow user to enter pincode.
+      let UserEnteredPinCode = "0000";
+      let pinCode = UserEnteredPinCode;
+
+      evt.handle.setPinCode(pinCode).then(
+        function onResolve() {
+          log("  - 'setPinCode' resolve.");
+          cleanupPairingListener(aAdapter.pairingReqs);
+        },
+        function onReject() {
+          log("  - 'setPinCode' reject.");
+          cleanupPairingListener(aAdapter.pairingReqs);
+        });
+    }
+  };
+
+  aAdapter.pairingReqs.onpairingconfirmationreq
+    = function onPairingConfirmationReq(evt) {
+    let passkey = evt.handle.passkey; // passkey for user to confirm
+    ok(typeof passkey === 'string', "type checking for passkey.");
+    log("  - Received 'onpairingconfirmationreq' event with passkey: " + passkey);
+
+    let device = evt.device;
+    if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
+      let confirm = true;
+
+      evt.handle.setPairingConfirmation(confirm).then(
+        function onResolve() {
+          log("  - 'setPairingConfirmation' resolve.");
+          cleanupPairingListener(aAdapter.pairingReqs);
+        },
+        function onReject() {
+          log("  - 'setPairingConfirmation' reject.");
+          cleanupPairingListener(aAdapter.pairingReqs);
+        });
+    }
+  };
+
+  aAdapter.pairingReqs.onpairingconsentreq = function onPairingConsentReq(evt) {
+    log("  - Received 'onpairingconsentreq' event.");
+
+    let device = evt.device;
+    if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
+      cleanupPairingListener(aAdapter.pairingReqs);
+    }
+  };
+}
+
+/**
+ * Clean up event handlers for pairing listener.
+ *
+ * @param aPairingReqs
+ *        A BluetoothPairingListener with event handlers.
+ */
+function cleanupPairingListener(aPairingReqs) {
+  aPairingReqs.ondisplaypasskeyreq = null;
+  aPairingReqs.onenterpasskeyreq = null;
+  aPairingReqs.onpairingconfirmationreq = null;
+  aPairingReqs.onpairingconsentreq = null;
+}
+
+/**
  * Compare two uuid arrays to see if them are the same.
  *
  * @param aUuidArray1
  *        An array which contains uuid strings.
  * @param aUuidArray2
  *        Another array which contains uuid strings.
  *
  * @return A boolean value.
--- a/dom/bluetooth2/tests/marionette/manifest.ini
+++ b/dom/bluetooth2/tests/marionette/manifest.ini
@@ -3,8 +3,9 @@ b2g = true
 browser = false
 qemu = false
 
 [test_dom_BluetoothManager_API2.js]
 [test_dom_BluetoothAdapter_enable_API2.js]
 [test_dom_BluetoothAdapter_setters_API2.js]
 [test_dom_BluetoothAdapter_discovery_API2.js]
 [test_dom_BluetoothDevice_API2.js]
+[test_dom_BluetoothAdapter_pair_API2.js]
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/tests/marionette/test_dom_BluetoothAdapter_pair_API2.js
@@ -0,0 +1,141 @@
+/* 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/. */
+
+///////////////////////////////////////////////////////////////////////////////
+// Test Purpose:
+//   To verify entire paring process of BluetoothAdapter, except for
+//   in-line pairing.
+//   Testers have to put a discoverable remote device near the testing device
+//   and click the 'confirm' button on remote device when it receives a pairing
+//   request from testing device.
+//   To pass this test, Bluetooth address of the remote device should equal to
+//   ADDRESS_OF_TARGETED_REMOTE_DEVICE.
+//
+// Test Procedure:
+//   [0] Set Bluetooth permission and enable default adapter.
+//   [1] Unpair device if it's already paired.
+//   [2] Start discovery.
+//   [3] Wait for the specified 'devicefound' event.
+//   [4] Type checking for BluetoothDeviceEvent and BluetoothDevice.
+//   [5] Pair and wait for confirmation.
+//   [6] Get paired devices and verify 'devicepaired' event.
+//   [7] Pair again.
+//   [8] Unpair.
+//   [9] Get paired devices and verify 'deviceunpaired' event.
+//   [10] Unpair again.
+//   [11] Stop discovery.
+//
+// Test Coverage:
+//   - BluetoothAdapter.pair()
+//   - BluetoothAdapter.unpair()
+//   - BluetoothAdapter.getPairedDevices()
+//   - BluetoothAdapter.ondevicepaired()
+//   - BluetoothAdapter.ondeviceunpaired()
+//   - BluetoothAdapter.pairingReqs
+//
+//   - BluetoothPairingListener.ondisplaypassykeyreq()
+//   - BluetoothPairingListener.onenterpincodereq()
+//   - BluetoothPairingListener.onpairingconfirmationreq()
+//   - BluetoothPairingListener.onpairingconsentreq()
+//
+//   - BluetoothPairingEvent.device
+//   - BluetoothPairingEvent.handle
+//
+//   - BluetoothPairingHandle.setPinCode()
+//   - BluetoothPairingHandle.setPairingConfirmation()
+//
+///////////////////////////////////////////////////////////////////////////////
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ADDRESS_OF_TARGETED_REMOTE_DEVICE = "0c:bd:51:20:a1:e0";
+
+startBluetoothTest(true, function testCaseMain(aAdapter) {
+  log("Checking adapter attributes ...");
+
+  is(aAdapter.state, "enabled", "adapter.state");
+  isnot(aAdapter.address, "", "adapter.address");
+
+  // Since adapter has just been re-enabled, these properties should be 'false'.
+  is(aAdapter.discovering, false, "adapter.discovering");
+  is(aAdapter.discoverable, false, "adapter.discoverable");
+
+  log("adapter.address: " + aAdapter.address);
+  log("adapter.name: " + aAdapter.name);
+
+  return Promise.resolve()
+    .then(function() {
+      log("[1] Unpair device if it's already paired ... ");
+      let devices = aAdapter.getPairedDevices();
+      for (let i in devices) {
+        if (devices[i].address == ADDRESS_OF_TARGETED_REMOTE_DEVICE) {
+          log("  - The device has already been paired. Unpair it ...");
+          return aAdapter.unpair(devices[i].address);
+        }
+      }
+      log("  - The device hasn't been paired. Skip to Step [2] ...");
+      return;
+    })
+    .then(function() {
+      log("[2] Start discovery ... ");
+      return aAdapter.startDiscovery();
+    })
+    .then(function(discoveryHandle) {
+      log("[3] Wait for the specified 'devicefound' event ... ");
+      return waitForSpecifiedDevicesFound(discoveryHandle, [ADDRESS_OF_TARGETED_REMOTE_DEVICE]);
+    })
+    .then(function(deviceEvents) {
+      log("[4] Type checking for BluetoothDeviceEvent and BluetoothDevice ... ");
+
+      let device = deviceEvents[0].device;
+      ok(deviceEvents[0] instanceof BluetoothDeviceEvent, "device should be a BluetoothDeviceEvent");
+      ok(device instanceof BluetoothDevice, "device should be a BluetoothDevice");
+
+      log("  - BluetoothDevice.address: " + device.address);
+      log("  - BluetoothDevice.name: " + device.name);
+      log("  - BluetoothDevice.cod: " + device.cod);
+      log("  - BluetoothDevice.paired: " + device.paired);
+      log("  - BluetoothDevice.uuids: " + device.uuids);
+
+      return device;
+    })
+    .then(function(device) {
+      log("[5] Pair and wait for confirmation ... ");
+
+      addEventHandlerForPairingRequest(aAdapter, device.address);
+
+      let promises = [];
+      promises.push(waitForAdapterEvent(aAdapter, "devicepaired"));
+      promises.push(aAdapter.pair(device.address));
+      return Promise.all(promises);
+    })
+    .then(function(results) {
+      log("[6] Get paired devices and verify 'devicepaired' event ... ");
+      return verifyDevicePairedUnpairedEvent(aAdapter, results[0]);
+    })
+    .then(function(deviceEvent) {
+      log("[7] Pair again... ");
+      return aAdapter.pair(deviceEvent.device.address).then(deviceEvent.device.address);
+    })
+    .then(function(deviceAddress) {
+      log("[8] Unpair ... ");
+      let promises = [];
+      promises.push(waitForAdapterEvent(aAdapter, "deviceunpaired"));
+      promises.push(aAdapter.unpair(deviceAddress));
+      return Promise.all(promises);
+    })
+    .then(function(results) {
+      log("[9] Get paired devices and verify 'deviceunpaired' event ... ");
+      return verifyDevicePairedUnpairedEvent(aAdapter, results[0])
+    })
+    .then(function(deviceEvent) {
+      log("[10] Unpair again... ");
+      return aAdapter.unpair(deviceEvent.address);
+    })
+    .then(function() {
+      log("[11] Stop discovery ... ");
+      return aAdapter.stopDiscovery();
+    });
+});
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -970,17 +970,17 @@ EventListenerManager::HandleEventInterna
   //Set the value of the internal PreventDefault flag properly based on aEventStatus
   if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
     aEvent->mFlags.mDefaultPrevented = true;
   }
 
   nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
   Maybe<nsAutoPopupStatePusher> popupStatePusher;
   if (mIsMainThreadELM) {
-    popupStatePusher.construct(Event::GetEventPopupControlState(aEvent));
+    popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent));
   }
 
   bool hasListener = false;
   while (iter.HasMore()) {
     if (aEvent->mFlags.mImmediatePropagationStopped) {
       break;
     }
     Listener* listener = &iter.GetNext();
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -85,27 +85,27 @@ EventListenerInfo::GetJSVal(JSContext* a
 {
   aJSVal.setNull();
   nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
   if (wrappedJS) {
     JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject());
     if (!object) {
       return false;
     }
-    aAc.construct(aCx, object);
+    aAc.emplace(aCx, object);
     aJSVal.setObject(*object);
     return true;
   }
 
   nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener);
   if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) {
     JS::Handle<JSObject*> handler =
       jsHandler->GetTypedEventHandler().Ptr()->Callable();
     if (handler) {
-      aAc.construct(aCx, handler);
+      aAc.emplace(aCx, handler);
       aJSVal.setObject(*handler);
       return true;
     }
   }
   return false;
 }
 
 NS_IMETHODIMP
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -3849,18 +3849,18 @@ EventStateManager::NotifyMouseOver(Widge
   // Remember mLastOverElement as the related content for the
   // DispatchMouseOrPointerEvent() call below, since NotifyMouseOut() resets it, bug 298477.
   nsCOMPtr<nsIContent> lastOverElement = wrapper->mLastOverElement;
 
   bool isPointer = aMouseEvent->mClass == ePointerEventClass;
   
   Maybe<EnterLeaveDispatcher> enterDispatcher;
   if (dispatch) {
-    enterDispatcher.construct(this, aContent, lastOverElement, aMouseEvent,
-                              isPointer ? NS_POINTER_ENTER : NS_MOUSEENTER);
+    enterDispatcher.emplace(this, aContent, lastOverElement, aMouseEvent,
+                            isPointer ? NS_POINTER_ENTER : NS_MOUSEENTER);
   }
 
   NotifyMouseOut(aMouseEvent, aContent);
 
   // Store the first mouseOver event we fire and don't refire mouseOver
   // to that element while the first mouseOver is still ongoing.
   wrapper->mFirstOverEventElement = aContent;
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -190,17 +190,17 @@ IDBRequest::NotifyHelperCompleted(Helper
 
   // Otherwise we need to get the result from the helper.
   AutoJSAPI jsapi;
   Maybe<JSAutoCompartment> ac;
   if (GetScriptOwner()) {
     // If we have a script owner we want the SafeJSContext and then to enter
     // the script owner's compartment.
     jsapi.Init();
-    ac.construct(jsapi.cx(), GetScriptOwner());
+    ac.emplace(jsapi.cx(), GetScriptOwner());
   } else {
     // Otherwise our owner is a window and we use that to initialize.
     if (!jsapi.InitWithLegacyErrorReporting(GetOwner())) {
       IDB_WARNING("Failed to initialise AutoJSAPI!");
       rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       SetError(rv);
       return rv;
     }
--- a/dom/interfaces/base/nsIDOMScreen.idl
+++ b/dom/interfaces/base/nsIDOMScreen.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
-[builtinclass, uuid(e732649a-4f78-4ded-abe1-dbdc36fd59d3)]
+[builtinclass, uuid(82c7924b-4b46-4e5a-a8d2-6edb5fc0a60d)]
 interface nsIDOMScreen : nsIDOMEventTarget
 {
   readonly attribute long             top;
   readonly attribute long             left;
   readonly attribute long             width;
   readonly attribute long             height;
   readonly attribute long             pixelDepth;
   readonly attribute long             colorDepth;
--- a/dom/interfaces/core/nsIDOMElement.idl
+++ b/dom/interfaces/core/nsIDOMElement.idl
@@ -10,17 +10,17 @@ interface nsIDOMMozNamedAttrMap;
 /**
  * The nsIDOMElement interface represents an element in an HTML or 
  * XML document. 
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-element
  */
 
-[uuid(989422ef-120d-4d29-8a56-6aa2505a8b02)]
+[uuid(d7de6065-1776-4f52-a776-4bbeabacbdaf)]
 interface nsIDOMElement : nsIDOMNode
 {
   readonly attribute DOMString        tagName;
 
            attribute DOMString        id;
            attribute DOMString        className;
   /**
    * Returns a DOMTokenList object reflecting the class attribute.
--- a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
+++ b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
@@ -11,17 +11,17 @@ interface nsIDOMDeviceStorageChangeEvent
 interface nsIDOMEventListener;
 interface nsIFile;
 
 %{C++
 struct DeviceStorageFileDescriptor;
 %}
 [ptr] native DeviceStorageFdPtr(DeviceStorageFileDescriptor);
 
-[uuid(8b724547-3c78-4244-969a-f00a1f4ae0c3), builtinclass]
+[uuid(25e4e387-1974-4f77-83b5-e6f3cf1beae8), builtinclass]
 interface nsIDOMDeviceStorage : nsIDOMEventTarget
 {
     [implicit_jscontext] attribute jsval onchange;
     nsIDOMDOMRequest add(in nsIDOMBlob aBlob);
     nsIDOMDOMRequest addNamed(in nsIDOMBlob aBlob, in DOMString aName);
 
     nsIDOMDOMRequest get([Null(Stringify)] in DOMString aName);
     nsIDOMDOMRequest getEditable([Null(Stringify)] in DOMString aName);
--- a/dom/interfaces/events/nsIDOMEventTarget.idl
+++ b/dom/interfaces/events/nsIDOMEventTarget.idl
@@ -40,17 +40,17 @@ class nsPresContext;
 [ref] native EventChainPreVisitorRef(mozilla::EventChainPreVisitor);
 [ptr] native EventListenerManagerPtr(mozilla::EventListenerManager);
 [ptr] native EventTargetPtr(mozilla::dom::EventTarget);
 
 interface nsIScriptContext;
 interface nsIDOMEventListener;
 interface nsIDOMEvent;
 
-[scriptable, builtinclass, uuid(b128448c-7b53-4769-92cb-cd6eafee676c)]
+[scriptable, builtinclass, uuid(9a78ac3c-9507-4d00-b2d6-10b508d2ec31)]
 interface nsIDOMEventTarget : nsISupports
 {
   /**
    * This method allows the registration of event listeners on the event target.
    * If an EventListener is added to an EventTarget while it is processing an
    * event, it will not be triggered by the current actions but may be 
    * triggered during a later stage of event flow, such as the bubbling phase.
    * 
--- a/dom/interfaces/html/nsIDOMHTMLElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLElement.idl
@@ -14,17 +14,17 @@ interface nsIDOMHTMLMenuElement;
  * tree.
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
-[uuid(e29ddc73-ac40-40fe-8bbd-14bf2d52c53a)]
+[uuid(db3352cf-04f3-4e7e-baa0-cd2f81b46328)]
 interface nsIDOMHTMLElement : nsIDOMElement
 {
   // metadata attributes
            attribute DOMString        title;
            attribute DOMString        lang;
            attribute DOMString        dir;
   readonly attribute nsISupports      dataset;
 
--- a/dom/interfaces/svg/nsIDOMSVGElement.idl
+++ b/dom/interfaces/svg/nsIDOMSVGElement.idl
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMElement.idl"
 
 interface nsIDOMCSSStyleDeclaration;
 interface nsIDOMCSSValue;
 
 
-[uuid(abdf347a-0063-42cc-b6fc-c9a19a65248e)]
+[uuid(0a6c6f77-8256-402c-9b2d-01d177ad3877)]
 interface nsIDOMSVGElement : nsIDOMElement
 {
             // raises DOMException on setting
   readonly attribute nsIDOMSVGElement    ownerSVGElement;
   readonly attribute nsIDOMSVGElement    viewportElement;
 
   [binaryname(SVGClassName)]
   readonly attribute nsISupports   className;
--- a/dom/interfaces/xul/nsIDOMXULElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULElement.idl
@@ -7,17 +7,17 @@
 
 interface nsIRDFCompositeDataSource;
 interface nsIXULTemplateBuilder;
 interface nsIRDFResource;
 interface nsIControllers;
 interface nsIBoxObject;
 
 
-[uuid(e89578c8-64ec-4047-984a-cce1b1735543)]
+[uuid(604d10c0-6ad0-4419-ad2f-a090d20bd7dc)]
 interface nsIDOMXULElement : nsIDOMElement
 {
   // Layout properties
   attribute DOMString align;
   attribute DOMString dir;
   attribute DOMString flex;
   attribute DOMString flexGroup;
   attribute DOMString ordinal;
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -176,17 +176,17 @@ WriteCallback(const jschar *buf, uint32_
 NS_IMETHODIMP
 nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
 {
   result.Truncate();
 
   mozilla::Maybe<JSAutoCompartment> ac;
   if (value->isObject()) {
     JS::Rooted<JSObject*> obj(cx, &value->toObject());
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
   }
 
   nsJSONWriter writer;
   JS::Rooted<JS::Value> vp(cx, *value);
   if (!JS_Stringify(cx, &vp, JS::NullPtr(), JS::NullHandleValue, WriteCallback, &writer)) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
   *value = vp;
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -338,74 +338,74 @@ nsDeviceSensors::FireDOMMotionEvent(nsID
                                     double y,
                                     double z)
 {
   // Attempt to coalesce events
   bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL);
 
   switch (type) {
   case nsIDeviceSensorData::TYPE_LINEAR_ACCELERATION:
-    if (mLastAcceleration.empty()) {
-      mLastAcceleration.construct();
+    if (!mLastAcceleration) {
+      mLastAcceleration.emplace();
     }
-    mLastAcceleration.ref().mX.SetValue(x);
-    mLastAcceleration.ref().mY.SetValue(y);
-    mLastAcceleration.ref().mZ.SetValue(z);
+    mLastAcceleration->mX.SetValue(x);
+    mLastAcceleration->mY.SetValue(y);
+    mLastAcceleration->mZ.SetValue(z);
     break;
   case nsIDeviceSensorData::TYPE_ACCELERATION:
-    if (mLastAccelerationIncluduingGravity.empty()) {
-      mLastAccelerationIncluduingGravity.construct();
+    if (!mLastAccelerationIncluduingGravity) {
+      mLastAccelerationIncluduingGravity.emplace();
     }
-    mLastAccelerationIncluduingGravity.ref().mX.SetValue(x);
-    mLastAccelerationIncluduingGravity.ref().mY.SetValue(y);
-    mLastAccelerationIncluduingGravity.ref().mZ.SetValue(z);
+    mLastAccelerationIncluduingGravity->mX.SetValue(x);
+    mLastAccelerationIncluduingGravity->mY.SetValue(y);
+    mLastAccelerationIncluduingGravity->mZ.SetValue(z);
     break;
   case nsIDeviceSensorData::TYPE_GYROSCOPE:
-    if (mLastRotationRate.empty()) {
-      mLastRotationRate.construct();
+    if (!mLastRotationRate) {
+      mLastRotationRate.emplace();
     }
-    mLastRotationRate.ref().mAlpha.SetValue(x);
-    mLastRotationRate.ref().mBeta.SetValue(y);
-    mLastRotationRate.ref().mGamma.SetValue(z);
+    mLastRotationRate->mAlpha.SetValue(x);
+    mLastRotationRate->mBeta.SetValue(y);
+    mLastRotationRate->mGamma.SetValue(z);
     break;
   }
 
   if (fireEvent) {
-    if (mLastAcceleration.empty()) {
-      mLastAcceleration.construct();
+    if (!mLastAcceleration) {
+      mLastAcceleration.emplace();
     }
-    if (mLastAccelerationIncluduingGravity.empty()) {
-      mLastAccelerationIncluduingGravity.construct();
+    if (!mLastAccelerationIncluduingGravity) {
+      mLastAccelerationIncluduingGravity.emplace();
     }
-    if (mLastRotationRate.empty()) {
-      mLastRotationRate.construct();
+    if (!mLastRotationRate) {
+      mLastRotationRate.emplace();
     }
-  } else if (mLastAcceleration.empty() ||
-             mLastAccelerationIncluduingGravity.empty() ||
-             mLastRotationRate.empty()) {
+  } else if (!mLastAcceleration ||
+             !mLastAccelerationIncluduingGravity ||
+             !mLastRotationRate) {
     return;
   }
 
   nsCOMPtr<nsIDOMEvent> event;
   domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event));
 
   DeviceMotionEvent* me = static_cast<DeviceMotionEvent*>(event.get());
 
   ErrorResult rv;
   me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"),
                             true,
                             false,
-                            mLastAcceleration.ref(),
-                            mLastAccelerationIncluduingGravity.ref(),
-                            mLastRotationRate.ref(),
+                            *mLastAcceleration,
+                            *mLastAccelerationIncluduingGravity,
+                            *mLastRotationRate,
                             Nullable<double>(DEFAULT_SENSOR_POLL),
                             rv);
 
   event->SetTrusted(true);
 
   bool defaultActionEnabled = true;
   target->DispatchEvent(event, &defaultActionEnabled);
 
-  mLastRotationRate.destroy();
-  mLastAccelerationIncluduingGravity.destroy();
-  mLastAcceleration.destroy();
+  mLastRotationRate.reset();
+  mLastAccelerationIncluduingGravity.reset();
+  mLastAcceleration.reset();
   mLastDOMMotionEventTime = TimeStamp::Now();
 }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3625,27 +3625,27 @@ WorkerPrivate::Constructor(JSContext* aC
 
   MOZ_ASSERT_IF(aWorkerType != WorkerTypeDedicated,
                 !aSharedWorkerName.IsVoid());
   MOZ_ASSERT_IF(aWorkerType == WorkerTypeDedicated,
                 aSharedWorkerName.IsEmpty());
 
   Maybe<LoadInfo> stackLoadInfo;
   if (!aLoadInfo) {
-    stackLoadInfo.construct();
+    stackLoadInfo.emplace();
 
     nsresult rv = GetLoadInfo(aCx, nullptr, parent, aScriptURL,
-                              aIsChromeWorker, stackLoadInfo.addr());
+                              aIsChromeWorker, stackLoadInfo.ptr());
     if (NS_FAILED(rv)) {
       scriptloader::ReportLoadError(aCx, aScriptURL, rv, !parent);
       aRv.Throw(rv);
       return nullptr;
     }
 
-    aLoadInfo = stackLoadInfo.addr();
+    aLoadInfo = stackLoadInfo.ptr();
   }
 
   // NB: This has to be done before creating the WorkerPrivate, because it will
   // attempt to use static variables that are initialized in the RuntimeService
   // constructor.
   RuntimeService* runtimeService;
 
   if (!parent) {
@@ -3934,19 +3934,19 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
 
   InitializeGCTimers();
 
   Maybe<JSAutoCompartment> workerCompartment;
 
   for (;;) {
     // Workers lazily create a global object in CompileScriptRunnable. We need
     // to enter the global's compartment as soon as it has been created.
-    if (workerCompartment.empty()) {
+    if (!workerCompartment) {
       if (JSObject* global = js::DefaultObjectForContextOrNull(aCx)) {
-        workerCompartment.construct(aCx, global);
+        workerCompartment.emplace(aCx, global);
       }
     }
 
     Status currentStatus;
     bool normalRunnablesPending = false;
 
     {
       MutexAutoLock lock(mMutex);
@@ -4023,17 +4023,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
     // Start the periodic GC timer if it is not already running.
     SetGCTimerMode(PeriodicTimer);
 
     // Process a single runnable from the main queue.
     MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(mThread, false));
 
     if (NS_HasPendingEvents(mThread)) {
       // Now *might* be a good time to GC. Let the JS engine make the decision.
-      if (!workerCompartment.empty()) {
+      if (workerCompartment) {
         JS_MaybeGC(aCx);
       }
     }
     else {
       // The normal event queue has been exhausted, cancel the periodic GC timer
       // and schedule the idle GC timer.
       SetGCTimerMode(IdleTimer);
     }
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -97,17 +97,17 @@ WorkerRunnable::Dispatch(JSContext* aCx)
   }
 
   JSAutoRequest ar(aCx);
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
 
   Maybe<JSAutoCompartment> ac;
   if (global) {
-    ac.construct(aCx, global);
+    ac.emplace(aCx, global);
   }
 
   ok = PreDispatch(aCx, mWorkerPrivate);
 
   if (ok && !DispatchInternal()) {
     ok = false;
   }
 
@@ -303,38 +303,38 @@ WorkerRunnable::Run()
   // this is OK as we won't be running script in these circumstances.
   // It's important that aes is declared after jsapi, because if WorkerRun
   // creates a global then we construct aes before PostRun and we need them to
   // be destroyed in the correct order.
   mozilla::dom::AutoJSAPI jsapi;
   Maybe<mozilla::dom::AutoEntryScript> aes;
   JSContext* cx;
   if (globalObject) {
-    aes.construct(globalObject, isMainThread, isMainThread ? nullptr :
-                                              GetCurrentThreadJSContext());
-    cx = aes.ref().cx();
+    aes.emplace(globalObject, isMainThread, isMainThread ? nullptr :
+                                            GetCurrentThreadJSContext());
+    cx = aes->cx();
   } else {
     jsapi.Init();
     cx = jsapi.cx();
   }
 
   // If we're not on the worker thread we'll either be in our parent's
   // compartment or the null compartment, so we need to enter our own.
   Maybe<JSAutoCompartment> ac;
   if (!targetIsWorkerThread && mWorkerPrivate->GetWrapper()) {
-    ac.construct(cx, mWorkerPrivate->GetWrapper());
+    ac.emplace(cx, mWorkerPrivate->GetWrapper());
   }
 
   bool result = WorkerRun(cx, mWorkerPrivate);
 
   // In the case of CompileScriptRunnnable, WorkerRun above can cause us to
   // lazily create a global, so we construct aes here before calling PostRun.
-  if (targetIsWorkerThread && aes.empty() && mWorkerPrivate->GlobalScope()) {
-    aes.construct(mWorkerPrivate->GlobalScope(), false, GetCurrentThreadJSContext());
-    cx = aes.ref().cx();
+  if (targetIsWorkerThread && !aes && mWorkerPrivate->GlobalScope()) {
+    aes.emplace(mWorkerPrivate->GlobalScope(), false, GetCurrentThreadJSContext());
+    cx = aes->cx();
   }
 
   PostRun(cx, mWorkerPrivate, result);
 
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -1844,41 +1844,41 @@ XMLHttpRequest::SendInternal(const nsASt
   }
 
   AutoUnpinXHR autoUnpin(this);
   Maybe<AutoSyncLoopHolder> autoSyncLoop;
 
   nsCOMPtr<nsIEventTarget> syncLoopTarget;
   bool isSyncXHR = mProxy->mIsSyncXHR;
   if (isSyncXHR) {
-    autoSyncLoop.construct(mWorkerPrivate);
-    syncLoopTarget = autoSyncLoop.ref().EventTarget();
+    autoSyncLoop.emplace(mWorkerPrivate);
+    syncLoopTarget = autoSyncLoop->EventTarget();
   }
 
   mProxy->mOuterChannelId++;
 
   JSContext* cx = mWorkerPrivate->GetJSContext();
 
   nsRefPtr<SendRunnable> runnable =
     new SendRunnable(mWorkerPrivate, mProxy, aStringBody, Move(aBody),
                      aClonedObjects, syncLoopTarget, hasUploadListeners);
   if (!runnable->Dispatch(cx)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   if (!isSyncXHR)  {
     autoUnpin.Clear();
-    MOZ_ASSERT(autoSyncLoop.empty());
+    MOZ_ASSERT(!autoSyncLoop);
     return;
   }
 
   autoUnpin.Clear();
 
-  if (!autoSyncLoop.ref().Run()) {
+  if (!autoSyncLoop->Run()) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 bool
 XMLHttpRequest::Notify(JSContext* aCx, Status aStatus)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -849,16 +849,18 @@ nsresult
 nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
                             nsXBLDocumentInfo* aDocInfo,
                             nsIDocument* aDocument,
                             uint8_t aFlags)
 {
   mInheritStyle = (aFlags & XBLBinding_Serialize_InheritStyle) ? true : false;
   mChromeOnlyContent =
     (aFlags & XBLBinding_Serialize_ChromeOnlyContent) ? true : false;
+  mBindToUntrustedContent =
+    (aFlags & XBLBinding_Serialize_BindToUntrustedContent) ? true : false;
 
   // nsXBLContentSink::ConstructBinding doesn't create a binding with an empty
   // id, so we don't here either.
   nsAutoCString id;
   nsresult rv = aStream->ReadCString(id);
 
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(!id.IsEmpty(), NS_ERROR_FAILURE);
@@ -1072,16 +1074,20 @@ nsXBLPrototypeBinding::Write(nsIObjectOu
   if (mAlternateBindingURI) {
     flags |= XBLBinding_Serialize_IsFirstBinding;
   }
 
   if (mChromeOnlyContent) {
     flags |= XBLBinding_Serialize_ChromeOnlyContent;
   }
 
+  if (mBindToUntrustedContent) {
+    flags |= XBLBinding_Serialize_BindToUntrustedContent;
+  }
+
   nsresult rv = aStream->Write8(flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString id;
   mBindingURI->GetRef(id);
   rv = aStream->WriteStringZ(id.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -159,16 +159,18 @@ private:
   /**
    * Read a new binding from the stream aStream into the xbl document aDocument.
    * aDocInfo should be the xbl document info for the binding document.
    * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
    * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
    * to indicate the first binding in a document.
    * XBLBinding_Serialize_ChromeOnlyContent indicates that
    * nsXBLPrototypeBinding::mChromeOnlyContent should be true.
+   * XBLBinding_Serialize_BindToUntrustedContent indicates that
+   * nsXBLPrototypeBinding::mBindToUntrustedContent should be true.
    */
 public:
   static nsresult ReadNewBinding(nsIObjectInputStream* aStream,
                                  nsXBLDocumentInfo* aDocInfo,
                                  nsIDocument* aDocument,
                                  uint8_t aFlags);
 
   /**
--- a/dom/xbl/nsXBLSerialize.h
+++ b/dom/xbl/nsXBLSerialize.h
@@ -10,27 +10,30 @@
 #include "nsIObjectOutputStream.h"
 #include "mozilla/dom/NameSpaceConstants.h"
 #include "js/TypeDecls.h"
 
 typedef uint8_t XBLBindingSerializeDetails;
 
 // A version number to ensure we don't load cached data in a different
 // file format.
-#define XBLBinding_Serialize_Version 0x00000003
+#define XBLBinding_Serialize_Version 0x00000004
 
 // Set for the first binding in a document
 #define XBLBinding_Serialize_IsFirstBinding 1
 
 // Set to indicate that nsXBLPrototypeBinding::mInheritStyle should be true
 #define XBLBinding_Serialize_InheritStyle 2
 
 // Set to indicate that nsXBLPrototypeBinding::mChromeOnlyContent should be true
 #define XBLBinding_Serialize_ChromeOnlyContent 4
 
+// Set to indicate that nsXBLPrototypeBinding::mBindToUntrustedContent should be true
+#define XBLBinding_Serialize_BindToUntrustedContent 8
+
 // Appears at the end of the serialized data to indicate that no more bindings
 // are present for this document.
 #define XBLBinding_Serialize_NoMoreBindings 0x80
 
 // Implementation member types. The serialized value for each member contains one
 // of these values, combined with the read-only flag XBLBinding_Serialize_ReadOnly.
 // Use XBLBinding_Serialize_Mask to filter out the read-only flag and check for
 // just the member type.
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -31,17 +31,17 @@ using mozilla::AutoSafeJSContext;
 
 static mozilla::Maybe<JS::PersistentRooted<JSObject *> > autoconfigSb;
 
 nsresult CentralizedAdminPrefManagerInit()
 {
     nsresult rv;
 
     // If the sandbox is already created, no need to create it again.
-    if (!autoconfigSb.empty())
+    if (autoconfigSb)
         return NS_OK;
 
     // Grab XPConnect.
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
@@ -53,26 +53,26 @@ nsresult CentralizedAdminPrefManagerInit
     // Create a sandbox.
     AutoSafeJSContext cx;
     nsCOMPtr<nsIXPConnectJSObjectHolder> sandbox;
     rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(sandbox));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Unwrap, store and root the sandbox.
     NS_ENSURE_STATE(sandbox->GetJSObject());
-    autoconfigSb.construct(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
+    autoconfigSb.emplace(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
 
     return NS_OK;
 }
 
 nsresult CentralizedAdminPrefManagerFinish()
 {
-    if (!autoconfigSb.empty()) {
+    if (autoconfigSb) {
         AutoSafeJSContext cx;
-        autoconfigSb.destroy();
+        autoconfigSb.reset();
         JS_MaybeGC(cx);
     }
     return NS_OK;
 }
 
 nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
                                    const char *filename, bool bGlobalContext,
                                    bool bCallbacks, bool skipFirstLine)
@@ -103,19 +103,19 @@ nsresult EvaluateAdminConfigScript(const
 
     // Grab XPConnect.
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
     AutoSafeJSContext cx;
-    JSAutoCompartment ac(cx, autoconfigSb.ref());
+    JSAutoCompartment ac(cx, *autoconfigSb);
 
     nsAutoCString script(js_buffer, length);
     JS::RootedValue v(cx);
     rv = xpc->EvalInSandboxObject(NS_ConvertASCIItoUTF16(script), filename, cx,
-                                  autoconfigSb.ref(), &v);
+                                  *autoconfigSb, &v);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
--- a/gfx/2d/BorrowedContext.h
+++ b/gfx/2d/BorrowedContext.h
@@ -24,17 +24,17 @@ namespace gfx {
 class BorrowedCairoContext
 {
 public:
   BorrowedCairoContext()
     : mCairo(nullptr)
     , mDT(nullptr)
   { }
 
-  BorrowedCairoContext(DrawTarget *aDT)
+  explicit BorrowedCairoContext(DrawTarget *aDT)
     : mDT(aDT)
   {
     mCairo = BorrowCairoContextFromDrawTarget(aDT);
   }
 
   // We can optionally Init after construction in
   // case we don't know what the DT will be at construction
   // time.
@@ -79,17 +79,17 @@ private:
 class BorrowedCGContext
 {
 public:
   BorrowedCGContext()
     : cg(nullptr)
     , mDT(nullptr)
   { }
 
-  BorrowedCGContext(DrawTarget *aDT)
+  explicit BorrowedCGContext(DrawTarget *aDT)
     : mDT(aDT)
   {
     cg = BorrowCGContextFromDrawTarget(aDT);
   }
 
   // We can optionally Init after construction in
   // case we don't know what the DT will be at construction
   // time.
--- a/gfx/2d/DataSourceSurfaceWrapper.h
+++ b/gfx/2d/DataSourceSurfaceWrapper.h
@@ -12,17 +12,17 @@ namespace mozilla {
 namespace gfx {
 
 // Wraps a DataSourceSurface and forwards all methods except for GetType(),
 // from which it always returns SurfaceType::DATA.
 class DataSourceSurfaceWrapper : public DataSourceSurface
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceWrapper)
-  DataSourceSurfaceWrapper(DataSourceSurface *aSurface)
+  explicit DataSourceSurfaceWrapper(DataSourceSurface *aSurface)
    : mSurface(aSurface)
   {}
 
   virtual SurfaceType GetType() const MOZ_OVERRIDE { return SurfaceType::DATA; }
 
   virtual uint8_t *GetData() MOZ_OVERRIDE { return mSurface->GetData(); }
   virtual int32_t Stride() MOZ_OVERRIDE { return mSurface->Stride(); }
   virtual IntSize GetSize() const MOZ_OVERRIDE { return mSurface->GetSize(); }
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -21,17 +21,17 @@ namespace mozilla {
 namespace gfx {
 
 class PathRecording;
 
 class DrawEventRecorderPrivate : public DrawEventRecorder
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate)
-  DrawEventRecorderPrivate(std::ostream *aStream);
+  explicit DrawEventRecorderPrivate(std::ostream *aStream);
   virtual ~DrawEventRecorderPrivate() { }
 
   void RecordEvent(const RecordedEvent &aEvent);
   void WritePath(const PathRecording *aPath);
 
   void AddStoredPath(const ReferencePtr aPath) {
     mStoredPaths.insert(aPath);
   }
@@ -61,17 +61,17 @@ protected:
   ObjectSet mStoredPaths;
   ObjectSet mStoredScaledFonts;
 };
 
 class DrawEventRecorderFile : public DrawEventRecorderPrivate
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile)
-  DrawEventRecorderFile(const char *aFilename);
+  explicit DrawEventRecorderFile(const char *aFilename);
   ~DrawEventRecorderFile();
 
 private:
   virtual void Flush();
 
   std::ofstream mOutputFile;
 };
 
--- a/gfx/2d/Helpers.h
+++ b/gfx/2d/Helpers.h
@@ -9,17 +9,17 @@
 #include "2D.h"
 
 namespace mozilla {
 namespace gfx {
 
 class AutoSaveTransform
 {
  public:
-  AutoSaveTransform(DrawTarget *aTarget)
+  explicit AutoSaveTransform(DrawTarget *aTarget)
    : mDrawTarget(aTarget),
      mOldTransform(aTarget->GetTransform())
   {
   }
   ~AutoSaveTransform()
   {
     mDrawTarget->SetTransform(mOldTransform);
   }
--- a/gfx/2d/MacIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -67,17 +67,17 @@ public:
   static mozilla::TemporaryRef<MacIOSurface> CreateIOSurface(int aWidth, int aHeight,
                                                              double aContentsScaleFactor = 1.0,
                                                              bool aHasAlpha = true);
   static void ReleaseIOSurface(MacIOSurface *aIOSurface);
   static mozilla::TemporaryRef<MacIOSurface> LookupSurface(IOSurfaceID aSurfaceID,
                                                            double aContentsScaleFactor = 1.0,
                                                            bool aHasAlpha = true);
 
-  MacIOSurface(const void *aIOSurfacePtr, double aContentsScaleFactor = 1.0, bool aHasAlpha = true)
+  explicit MacIOSurface(const void *aIOSurfacePtr, double aContentsScaleFactor = 1.0, bool aHasAlpha = true)
     : mIOSurfacePtr(aIOSurfacePtr), mContentsScaleFactor(aContentsScaleFactor), mHasAlpha(aHasAlpha) {}
   virtual ~MacIOSurface();
   IOSurfaceID GetIOSurfaceID();
   void *GetBaseAddress();
   // GetWidth() and GetHeight() return values in "display pixels".  A
   // "display pixel" is the smallest fully addressable part of a display.
   // But in HiDPI modes each "display pixel" corresponds to more than one
   // device pixel.  Use GetDevicePixel**() to get device pixels.
--- a/gfx/2d/PathCG.h
+++ b/gfx/2d/PathCG.h
@@ -20,17 +20,17 @@ public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderCG)
   // absorbs a reference of aPath
   PathBuilderCG(CGMutablePathRef aPath, FillRule aFillRule)
     : mFillRule(aFillRule)
   {
       mCGPath = aPath;
   }
 
-  PathBuilderCG(FillRule aFillRule)
+  explicit PathBuilderCG(FillRule aFillRule)
     : mFillRule(aFillRule)
   {
       mCGPath = CGPathCreateMutable();
   }
 
   virtual ~PathBuilderCG();
 
   virtual void MoveTo(const Point &aPoint);
--- a/gfx/2d/PathCairo.h
+++ b/gfx/2d/PathCairo.h
@@ -15,17 +15,17 @@ namespace gfx {
 
 class DrawTargetCairo;
 class PathCairo;
 
 class PathBuilderCairo : public PathBuilder
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderCairo)
-  PathBuilderCairo(FillRule aFillRule);
+  explicit PathBuilderCairo(FillRule aFillRule);
 
   virtual void MoveTo(const Point &aPoint);
   virtual void LineTo(const Point &aPoint);
   virtual void BezierTo(const Point &aCP1,
                         const Point &aCP2,
                         const Point &aCP3);
   virtual void QuadraticBezierTo(const Point &aCP1,
                                  const Point &aCP2);
@@ -46,17 +46,17 @@ private: // data
   Point mBeginPoint;
 };
 
 class PathCairo : public Path
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCairo)
   PathCairo(FillRule aFillRule, std::vector<cairo_path_data_t> &aPathData, const Point &aCurrentPoint);
-  PathCairo(cairo_t *aContext);
+  explicit PathCairo(cairo_t *aContext);
   ~PathCairo();
 
   virtual BackendType GetBackendType() const { return BackendType::CAIRO; }
 
   virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const;
   virtual TemporaryRef<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
                                                              FillRule aFillRule = FillRule::FILL_WINDING) const;
 
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -26,17 +26,17 @@ const uint16_t kMajorRevision = 3;
 const uint16_t kMinorRevision = 2;
 
 struct ReferencePtr
 {
   ReferencePtr()
     : mLongPtr(0)
   {}
 
-  ReferencePtr(const void* aLongPtr)
+  MOZ_IMPLICIT ReferencePtr(const void* aLongPtr)
     : mLongPtr(uint64_t(aLongPtr))
   {}
 
   template <typename T>
   ReferencePtr(const RefPtr<T>& aPtr)
     : mLongPtr(uint64_t(aPtr.get()))
   {}
 
@@ -198,17 +198,17 @@ public:
   void OutputSimplePatternInfo(const PatternStorage &aStorage, std::stringstream &aOutput) const;
 
   static RecordedEvent *LoadEventFromStream(std::istream &aStream, EventType aType);
 
   EventType GetType() { return (EventType)mType; }
 protected:
   friend class DrawEventRecorderPrivate;
 
-  RecordedEvent(int32_t aType) : mType(aType)
+  MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType)
   {}
 
   int32_t mType;
   std::vector<Float> mDashPatternStorage;
 };
 
 class RecordedDrawingEvent : public RecordedEvent
 {
@@ -250,22 +250,22 @@ public:
   IntSize mSize;
   SurfaceFormat mFormat;
   bool mHasExistingData;
   RefPtr<SourceSurface> mExistingData;
   
 private:
   friend class RecordedEvent;
 
-  RecordedDrawTargetCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedDrawTargetCreation(std::istream &aStream);
 };
 
 class RecordedDrawTargetDestruction : public RecordedEvent {
 public:
-  RecordedDrawTargetDestruction(ReferencePtr aRefPtr)
+  MOZ_IMPLICIT RecordedDrawTargetDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(DRAWTARGETDESTRUCTION), mRefPtr(aRefPtr)
   {}
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
@@ -273,17 +273,17 @@ public:
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
   ReferencePtr mRefPtr;
 
   BackendType mBackendType;
 private:
   friend class RecordedEvent;
 
-  RecordedDrawTargetDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedDrawTargetDestruction(std::istream &aStream);
 };
 
 class RecordedFillRect : public RecordedDrawingEvent {
 public:
   RecordedFillRect(DrawTarget *aDT, const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
     : RecordedDrawingEvent(FILLRECT, aDT), mRect(aRect), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
@@ -293,17 +293,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FillRect"; }
 private:
   friend class RecordedEvent;
 
-  RecordedFillRect(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFillRect(std::istream &aStream);
 
   Rect mRect;
   PatternStorage mPattern;
   DrawOptions mOptions;
 };
 
 class RecordedStrokeRect : public RecordedDrawingEvent {
 public:
@@ -319,17 +319,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "StrokeRect"; }
 private:
   friend class RecordedEvent;
 
-  RecordedStrokeRect(std::istream &aStream);
+  MOZ_IMPLICIT RecordedStrokeRect(std::istream &aStream);
 
   Rect mRect;
   PatternStorage mPattern;
   StrokeOptions mStrokeOptions;
   DrawOptions mOptions;
 };
 
 class RecordedStrokeLine : public RecordedDrawingEvent {
@@ -347,17 +347,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "StrokeLine"; }
 private:
   friend class RecordedEvent;
 
-  RecordedStrokeLine(std::istream &aStream);
+  MOZ_IMPLICIT RecordedStrokeLine(std::istream &aStream);
 
   Point mBegin;
   Point mEnd;
   PatternStorage mPattern;
   StrokeOptions mStrokeOptions;
   DrawOptions mOptions;
 };
 
@@ -373,17 +373,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Fill"; }
 private:
   friend class RecordedEvent;
 
-  RecordedFill(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFill(std::istream &aStream);
 
   ReferencePtr mPath;
   PatternStorage mPattern;
   DrawOptions mOptions;
 };
 
 class RecordedFillGlyphs : public RecordedDrawingEvent {
 public:
@@ -402,17 +402,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FillGlyphs"; }
 private:
   friend class RecordedEvent;
 
-  RecordedFillGlyphs(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFillGlyphs(std::istream &aStream);
 
   ReferencePtr mScaledFont;
   PatternStorage mPattern;
   DrawOptions mOptions;
   Glyph *mGlyphs;
   uint32_t mNumGlyphs;
 };
 
@@ -429,17 +429,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Mask"; }
 private:
   friend class RecordedEvent;
 
-  RecordedMask(std::istream &aStream);
+  MOZ_IMPLICIT RecordedMask(std::istream &aStream);
 
   PatternStorage mSource;
   PatternStorage mMask;
   DrawOptions mOptions;
 };
 
 class RecordedStroke : public RecordedDrawingEvent {
 public:
@@ -455,17 +455,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Stroke"; }
 private:
   friend class RecordedEvent;
 
-  RecordedStroke(std::istream &aStream);
+  MOZ_IMPLICIT RecordedStroke(std::istream &aStream);
 
   ReferencePtr mPath;
   PatternStorage mPattern;
   StrokeOptions mStrokeOptions;
   DrawOptions mOptions;
 };
 
 class RecordedClearRect : public RecordedDrawingEvent {
@@ -479,17 +479,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "ClearRect"; }
 private:
   friend class RecordedEvent;
 
-  RecordedClearRect(std::istream &aStream);
+  MOZ_IMPLICIT RecordedClearRect(std::istream &aStream);
 
   Rect mRect;
 };
 
 class RecordedCopySurface : public RecordedDrawingEvent {
 public:
   RecordedCopySurface(DrawTarget *aDT, ReferencePtr aSourceSurface,
                       const IntRect &aSourceRect, const IntPoint &aDest)
@@ -502,17 +502,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "CopySurface"; }
 private:
   friend class RecordedEvent;
 
-  RecordedCopySurface(std::istream &aStream);
+  MOZ_IMPLICIT RecordedCopySurface(std::istream &aStream);
 
   ReferencePtr mSourceSurface;
   IntRect mSourceRect;
   IntPoint mDest;
 };
 
 class RecordedPushClip : public RecordedDrawingEvent {
 public:
@@ -525,17 +525,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PushClip"; }
 private:
   friend class RecordedEvent;
 
-  RecordedPushClip(std::istream &aStream);
+  MOZ_IMPLICIT RecordedPushClip(std::istream &aStream);
 
   ReferencePtr mPath;
 };
 
 class RecordedPushClipRect : public RecordedDrawingEvent {
 public:
   RecordedPushClipRect(DrawTarget *aDT, const Rect &aRect)
     : RecordedDrawingEvent(PUSHCLIPRECT, aDT), mRect(aRect)
@@ -546,37 +546,37 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PushClipRect"; }
 private:
   friend class RecordedEvent;
 
-  RecordedPushClipRect(std::istream &aStream);
+  MOZ_IMPLICIT RecordedPushClipRect(std::istream &aStream);
 
   Rect mRect;
 };
 
 class RecordedPopClip : public RecordedDrawingEvent {
 public:
-  RecordedPopClip(DrawTarget *aDT)
+  MOZ_IMPLICIT RecordedPopClip(DrawTarget *aDT)
     : RecordedDrawingEvent(POPCLIP, aDT)
   {}
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PopClip"; }
 private:
   friend class RecordedEvent;
 
-  RecordedPopClip(std::istream &aStream);
+  MOZ_IMPLICIT RecordedPopClip(std::istream &aStream);
 };
 
 class RecordedSetTransform : public RecordedDrawingEvent {
 public:
   RecordedSetTransform(DrawTarget *aDT, const Matrix &aTransform)
     : RecordedDrawingEvent(SETTRANSFORM, aDT), mTransform(aTransform)
   {
   }
@@ -585,17 +585,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SetTransform"; }
 private:
   friend class RecordedEvent;
 
-  RecordedSetTransform(std::istream &aStream);
+   MOZ_IMPLICIT RecordedSetTransform(std::istream &aStream);
 
   Matrix mTransform;
 };
 
 class RecordedDrawSurface : public RecordedDrawingEvent {
 public:
   RecordedDrawSurface(DrawTarget *aDT, ReferencePtr aRefSource, const Rect &aDest,
                       const Rect &aSource, const DrawSurfaceOptions &aDSOptions,
@@ -609,17 +609,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "DrawSurface"; }
 private:
   friend class RecordedEvent;
 
-  RecordedDrawSurface(std::istream &aStream);
+   MOZ_IMPLICIT RecordedDrawSurface(std::istream &aStream);
 
   ReferencePtr mRefSource;
   Rect mDest;
   Rect mSource;
   DrawSurfaceOptions mDSOptions;
   DrawOptions mOptions;
 };
 
@@ -637,17 +637,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "DrawSurfaceWithShadow"; }
 private:
   friend class RecordedEvent;
 
-  RecordedDrawSurfaceWithShadow(std::istream &aStream);
+  MOZ_IMPLICIT RecordedDrawSurfaceWithShadow(std::istream &aStream);
 
   ReferencePtr mRefSource;
   Point mDest;
   Color mColor;
   Point mOffset;
   Float mSigma;
   CompositionOp mOp;
 };
@@ -667,66 +667,66 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "DrawFilter"; }
 private:
   friend class RecordedEvent;
 
-  RecordedDrawFilter(std::istream &aStream);
+  MOZ_IMPLICIT RecordedDrawFilter(std::istream &aStream);
 
   ReferencePtr mNode;
   Rect mSourceRect;
   Point mDestPoint;
   DrawOptions mOptions;
 };
 
 class RecordedPathCreation : public RecordedEvent {
 public:
-  RecordedPathCreation(PathRecording *aPath);
+  MOZ_IMPLICIT RecordedPathCreation(PathRecording *aPath);
   ~RecordedPathCreation();
   
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "Path Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
   FillRule mFillRule;
   std::vector<PathOp> mPathOps;
 
-  RecordedPathCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedPathCreation(std::istream &aStream);
 };
 
 class RecordedPathDestruction : public RecordedEvent {
 public:
-  RecordedPathDestruction(PathRecording *aPath)
+  MOZ_IMPLICIT RecordedPathDestruction(PathRecording *aPath)
     : RecordedEvent(PATHDESTRUCTION), mRefPtr(aPath)
   {
   }
   
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "Path Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
 
-  RecordedPathDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedPathDestruction(std::istream &aStream);
 };
 
 class RecordedSourceSurfaceCreation : public RecordedEvent {
 public:
   RecordedSourceSurfaceCreation(ReferencePtr aRefPtr, uint8_t *aData, int32_t aStride,
                                 const IntSize &aSize, SurfaceFormat aFormat)
     : RecordedEvent(SOURCESURFACECREATION), mRefPtr(aRefPtr), mData(aData)
     , mStride(aStride), mSize(aSize), mFormat(aFormat), mDataOwned(false)
@@ -747,39 +747,39 @@ private:
 
   ReferencePtr mRefPtr;
   uint8_t *mData;
   int32_t mStride;
   IntSize mSize;
   SurfaceFormat mFormat;
   bool mDataOwned;
 
-  RecordedSourceSurfaceCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedSourceSurfaceCreation(std::istream &aStream);
 };
 
 class RecordedSourceSurfaceDestruction : public RecordedEvent {
 public:
-  RecordedSourceSurfaceDestruction(ReferencePtr aRefPtr)
+  MOZ_IMPLICIT RecordedSourceSurfaceDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(SOURCESURFACEDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SourceSurface Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
 
-  RecordedSourceSurfaceDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedSourceSurfaceDestruction(std::istream &aStream);
 };
 
 class RecordedFilterNodeCreation : public RecordedEvent {
 public:
   RecordedFilterNodeCreation(ReferencePtr aRefPtr, FilterType aType)
     : RecordedEvent(FILTERNODECREATION), mRefPtr(aRefPtr), mType(aType)
   {
   }
@@ -794,39 +794,39 @@ public:
   virtual std::string GetName() const { return "FilterNode Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
   FilterType mType;
 
-  RecordedFilterNodeCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFilterNodeCreation(std::istream &aStream);
 };
 
 class RecordedFilterNodeDestruction : public RecordedEvent {
 public:
-  RecordedFilterNodeDestruction(ReferencePtr aRefPtr)
+  MOZ_IMPLICIT RecordedFilterNodeDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(FILTERNODEDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FilterNode Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
 
-  RecordedFilterNodeDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFilterNodeDestruction(std::istream &aStream);
 };
 
 class RecordedGradientStopsCreation : public RecordedEvent {
 public:
   RecordedGradientStopsCreation(ReferencePtr aRefPtr, GradientStop *aStops,
                                 uint32_t aNumStops, ExtendMode aExtendMode)
     : RecordedEvent(GRADIENTSTOPSCREATION), mRefPtr(aRefPtr), mStops(aStops)
     , mNumStops(aNumStops), mExtendMode(aExtendMode), mDataOwned(false)
@@ -846,39 +846,39 @@ private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
   GradientStop *mStops;
   uint32_t mNumStops;
   ExtendMode mExtendMode;
   bool mDataOwned;
 
-  RecordedGradientStopsCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedGradientStopsCreation(std::istream &aStream);
 };
 
 class RecordedGradientStopsDestruction : public RecordedEvent {
 public:
-  RecordedGradientStopsDestruction(ReferencePtr aRefPtr)
+  MOZ_IMPLICIT RecordedGradientStopsDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(GRADIENTSTOPSDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "GradientStops Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
 
-  RecordedGradientStopsDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedGradientStopsDestruction(std::istream &aStream);
 };
 
 class RecordedSnapshot : public RecordedEvent {
 public:
   RecordedSnapshot(ReferencePtr aRefPtr, DrawTarget *aDT)
     : RecordedEvent(SNAPSHOT), mRefPtr(aRefPtr), mDT(aDT)
   {
   }
@@ -891,17 +891,17 @@ public:
   virtual std::string GetName() const { return "Snapshot"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
   ReferencePtr mDT;
 
-  RecordedSnapshot(std::istream &aStream);
+  MOZ_IMPLICIT RecordedSnapshot(std::istream &aStream);
 };
 
 class RecordedScaledFontCreation : public RecordedEvent {
 public:
   static void FontDataProc(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize, void* aBaton)
   {
     static_cast<RecordedScaledFontCreation*>(aBaton)->SetFontData(aData, aSize, aIndex, aGlyphSize);
   }
@@ -928,39 +928,39 @@ private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
   uint8_t *mData;
   uint32_t mSize;
   Float mGlyphSize;
   uint32_t mIndex;
 
-  RecordedScaledFontCreation(std::istream &aStream);
+  MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream);
 };
 
 class RecordedScaledFontDestruction : public RecordedEvent {
 public:
-  RecordedScaledFontDestruction(ReferencePtr aRefPtr)
+  MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "ScaledFont Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
 
   ReferencePtr mRefPtr;
 
-  RecordedScaledFontDestruction(std::istream &aStream);
+  MOZ_IMPLICIT RecordedScaledFontDestruction(std::istream &aStream);
 };
 
 class RecordedMaskSurface : public RecordedDrawingEvent {
 public:
   RecordedMaskSurface(DrawTarget *aDT, const Pattern &aPattern, ReferencePtr aRefMask,
                       const Point &aOffset, const DrawOptions &aOptions)
     : RecordedDrawingEvent(MASKSURFACE, aDT), mRefMask(aRefMask), mOffset(aOffset)
     , mOptions(aOptions)
@@ -972,17 +972,17 @@ public:
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "MaskSurface"; }
 private:
   friend class RecordedEvent;
 
-  RecordedMaskSurface(std::istream &aStream);
+  MOZ_IMPLICIT RecordedMaskSurface(std::istream &aStream);
 
   PatternStorage mPattern;
   ReferencePtr mRefMask;
   Point mOffset;
   DrawOptions mOptions;
 };
 
 class RecordedFilterNodeSetAttribute : public RecordedEvent
@@ -1031,17 +1031,17 @@ private:
   friend class RecordedEvent;
 
   ReferencePtr mNode;
 
   uint32_t mIndex;
   ArgType mArgType;
   std::vector<uint8_t> mPayload;
 
-  RecordedFilterNodeSetAttribute(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFilterNodeSetAttribute(std::istream &aStream);
 };
 
 class RecordedFilterNodeSetInput : public RecordedEvent
 {
 public:
   RecordedFilterNodeSetInput(FilterNode* aNode, uint32_t aIndex, FilterNode* aInputNode)
     : RecordedEvent(FILTERNODESETINPUT), mNode(aNode), mIndex(aIndex)
     , mInputFilter(aInputNode), mInputSurface(nullptr)
@@ -1065,15 +1065,15 @@ public:
 private:
   friend class RecordedEvent;
 
   ReferencePtr mNode;
   uint32_t mIndex;
   ReferencePtr mInputFilter;
   ReferencePtr mInputSurface;
 
-  RecordedFilterNodeSetInput(std::istream &aStream);
+  MOZ_IMPLICIT RecordedFilterNodeSetInput(std::istream &aStream);
 };
 
 }
 }
 
 #endif
--- a/gfx/2d/SVGTurbulenceRenderer-inl.h
+++ b/gfx/2d/SVGTurbulenceRenderer-inl.h
@@ -50,17 +50,17 @@ private:
   uint8_t mLatticeSelector[sBSize];
   f32x4_t mGradient[sBSize][2];
 };
 
 namespace {
 
 struct RandomNumberSource
 {
-  RandomNumberSource(int32_t aSeed) : mLast(SetupSeed(aSeed)) {}
+  explicit RandomNumberSource(int32_t aSeed) : mLast(SetupSeed(aSeed)) {}
   int32_t Next() { mLast = Random(mLast); return mLast; }
 
 private:
   static const int32_t RAND_M = 2147483647; /* 2**31 - 1 */
   static const int32_t RAND_A = 16807;      /* 7**5; primitive root of m */
   static const int32_t RAND_Q = 127773;     /* m / a */
   static const int32_t RAND_R = 2836;       /* m % a */
 
--- a/gfx/2d/SourceSurfaceCG.h
+++ b/gfx/2d/SourceSurfaceCG.h
@@ -24,17 +24,17 @@ CreateCGImage(void *aInfo,
 
 class DrawTargetCG;
 
 class SourceSurfaceCG : public SourceSurface
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceCG)
   SourceSurfaceCG() {}
-  SourceSurfaceCG(CGImageRef aImage) : mImage(aImage) {}
+  explicit SourceSurfaceCG(CGImageRef aImage) : mImage(aImage) {}
   ~SourceSurfaceCG();
 
   virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_IMAGE; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const;
   virtual TemporaryRef<DataSourceSurface> GetDataSurface();
 
   CGImageRef GetImage() { return mImage; }
@@ -53,17 +53,17 @@ private:
   SurfaceFormat mFormat;
 };
 
 class DataSourceSurfaceCG : public DataSourceSurface
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCG)
   DataSourceSurfaceCG() {}
-  DataSourceSurfaceCG(CGImageRef aImage);
+  explicit DataSourceSurfaceCG(CGImageRef aImage);
   ~DataSourceSurfaceCG();
 
   virtual SurfaceType GetType() const { return SurfaceType::DATA; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const { return mFormat; }
 
   CGImageRef GetImage() { return mImage; }
 
@@ -95,17 +95,17 @@ public:
   virtual void DrawTargetWillChange() = 0;
   virtual CGImageRef GetImage() = 0;
 };
 
 class SourceSurfaceCGBitmapContext : public SourceSurfaceCGContext
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGBitmapContext)
-  SourceSurfaceCGBitmapContext(DrawTargetCG *);
+  explicit SourceSurfaceCGBitmapContext(DrawTargetCG *);
   ~SourceSurfaceCGBitmapContext();
 
   virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_CGCONTEXT; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const { return mFormat; }
   virtual TemporaryRef<DataSourceSurface> GetDataSurface()
   {
     // This call to DrawTargetWillChange() is needed to make a local copy of
@@ -151,17 +151,17 @@ private:
   int32_t mStride;
   IntSize mSize;
 };
 
 class SourceSurfaceCGIOSurfaceContext : public SourceSurfaceCGContext
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGIOSurfaceContext)
-  SourceSurfaceCGIOSurfaceContext(DrawTargetCG *);
+  explicit SourceSurfaceCGIOSurfaceContext(DrawTargetCG *);
   ~SourceSurfaceCGIOSurfaceContext();
 
   virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_CGCONTEXT; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const { return mFormat; }
 
   CGImageRef GetImage() { EnsureImage(); return mImage; }
 
--- a/gfx/gl/GLBlitHelper.h
+++ b/gfx/gl/GLBlitHelper.h
@@ -140,17 +140,17 @@ class GLBlitHelper MOZ_FINAL
 #ifdef MOZ_WIDGET_GONK
     void BindAndUploadExternalTexture(EGLImage image);
     bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip = false);
 #endif
     bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip = false);
 
 public:
 
-    GLBlitHelper(GLContext* gl);
+    explicit GLBlitHelper(GLContext* gl);
     ~GLBlitHelper();
 
     // If you don't have |srcFormats| for the 2nd definition,
     // then you'll need the framebuffer_blit extensions to use
     // the first BlitFramebufferToFramebuffer.
     void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
                                       const gfx::IntSize& srcSize,
                                       const gfx::IntSize& destSize,
--- a/gfx/gl/GLBlitTextureImageHelper.h
+++ b/gfx/gl/GLBlitTextureImageHelper.h
@@ -26,17 +26,17 @@ class GLBlitTextureImageHelper MOZ_FINAL
 
     // lazy-initialized things
     GLuint mBlitProgram, mBlitFramebuffer;
     void UseBlitProgram();
     void SetBlitFramebufferForDestTexture(GLuint aTexture);
 
 public:
 
-    GLBlitTextureImageHelper(GLContext *gl);
+    explicit GLBlitTextureImageHelper(GLContext *gl);
     ~GLBlitTextureImageHelper();
 
     /**
      * Copy a rectangle from one TextureImage into another.  The
      * source and destination are given in integer coordinates, and
      * will be converted to texture coordinates.
      *
      * For the source texture, the wrap modes DO apply -- it's valid
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2562,19 +2562,19 @@ public:
         mSymbols.fGetFenceiv(fence, pname, params);
         AFTER_GL_CALL;
     }
 
 
 // -----------------------------------------------------------------------------
 // Constructor
 protected:
-    GLContext(const SurfaceCaps& caps,
-              GLContext* sharedContext = nullptr,
-              bool isOffscreen = false);
+    explicit GLContext(const SurfaceCaps& caps,
+                       GLContext* sharedContext = nullptr,
+                       bool isOffscreen = false);
 
 
 // -----------------------------------------------------------------------------
 // Destructor
 public:
     virtual ~GLContext();
 
 
--- a/gfx/gl/GLReadTexImageHelper.h
+++ b/gfx/gl/GLReadTexImageHelper.h
@@ -36,17 +36,17 @@ class GLReadTexImageHelper MOZ_FINAL
     GLuint mPrograms[4];
 
     GLuint TextureImageProgramFor(GLenum aTextureTarget, int aShader);
 
     bool DidGLErrorOccur(const char* str);
 
 public:
 
-    GLReadTexImageHelper(GLContext* gl);
+    explicit GLReadTexImageHelper(GLContext* gl);
     ~GLReadTexImageHelper();
 
     /**
       * Read the image data contained in aTexture, and return it as an ImageSurface.
       * If GL_RGBA is given as the format, a gfxImageFormat::ARGB32 surface is returned.
       * Not implemented yet:
       * If GL_RGB is given as the format, a gfxImageFormat::RGB24 surface is returned.
       * If GL_LUMINANCE is given as the format, a gfxImageFormat::A8 surface is returned.
--- a/gfx/gl/GLSharedHandleHelpers.cpp
+++ b/gfx/gl/GLSharedHandleHelpers.cpp
@@ -16,17 +16,17 @@ enum SharedHandleType {
 #ifdef MOZ_WIDGET_ANDROID
     , SharedHandleType_SurfaceTexture
 #endif
 };
 
 class SharedTextureHandleWrapper
 {
 public:
-    SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
+    explicit SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
     {
     }
 
     virtual ~SharedTextureHandleWrapper()
     {
     }
 
     SharedHandleType Type() { return mHandleType; }
--- a/gfx/gl/ScopedGLHelpers.h
+++ b/gfx/gl/ScopedGLHelpers.h
@@ -18,17 +18,17 @@ template <class Derived>
 struct ScopedGLWrapper
 {
 private:
     bool mIsUnwrapped;
 
 protected:
     GLContext* const mGL;
 
-    ScopedGLWrapper(GLContext* gl)
+    explicit ScopedGLWrapper(GLContext* gl)
         : mIsUnwrapped(false)
         , mGL(gl)
     {
         MOZ_ASSERT(&ScopedGLWrapper<Derived>::Unwrap == &Derived::Unwrap);
         MOZ_ASSERT(&Derived::UnwrapImpl);
         MOZ_ASSERT(mGL->IsCurrent());
     }
 
@@ -110,51 +110,51 @@ struct ScopedTexture
     : public ScopedGLWrapper<ScopedTexture>
 {
     friend struct ScopedGLWrapper<ScopedTexture>;
 
 protected:
     GLuint mTexture;
 
 public:
-    ScopedTexture(GLContext* aGL);
+    explicit ScopedTexture(GLContext* aGL);
     GLuint Texture() { return mTexture; }
 
 protected:
     void UnwrapImpl();
 };
 
 
 struct ScopedFramebuffer
     : public ScopedGLWrapper<ScopedFramebuffer>
 {
     friend struct ScopedGLWrapper<ScopedFramebuffer>;
 
 protected:
     GLuint mFB;
 
 public:
-    ScopedFramebuffer(GLContext* aGL);
+    explicit ScopedFramebuffer(GLContext* aGL);
     GLuint FB() { return mFB; }
 
 protected:
     void UnwrapImpl();
 };
 
 
 struct ScopedRenderbuffer
     : public ScopedGLWrapper<ScopedRenderbuffer>
 {
     friend struct ScopedGLWrapper<ScopedRenderbuffer>;
 
 protected:
     GLuint mRB;
 
 public:
-    ScopedRenderbuffer(GLContext* aGL);
+    explicit ScopedRenderbuffer(GLContext* aGL);
     GLuint RB() { return mRB; }
 
 protected:
     void UnwrapImpl();
 };
 
 
 struct ScopedBindTexture
@@ -302,17 +302,17 @@ public:
     explicit ScopedVertexAttribPointer(GLContext* aGL, GLuint index);
 
 protected:
     void WrapImpl(GLuint index);
     void UnwrapImpl();
 };
 
 struct ScopedGLDrawState {
-    ScopedGLDrawState(GLContext* gl);
+    explicit ScopedGLDrawState(GLContext* gl);
     ~ScopedGLDrawState();
 
     GLuint boundProgram;
     GLuint boundBuffer;
 
     ScopedGLState blend;
     ScopedGLState cullFace;
     ScopedGLState depthTest;
--- a/gfx/gl/SurfaceStream.h
+++ b/gfx/gl/SurfaceStream.h
@@ -131,17 +131,17 @@ public:
 class SurfaceStream_SingleBuffer
     : public SurfaceStream
 {
 protected:
     SharedSurface* mConsumer; // Only present after resize-swap.
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_SingleBuffer)
-    SurfaceStream_SingleBuffer(SurfaceStream* prevStream);
+    explicit SurfaceStream_SingleBuffer(SurfaceStream* prevStream);
     virtual ~SurfaceStream_SingleBuffer();
 
     /* Since we're non-OMTC, we know the order of execution here:
      * SwapProd gets called in UpdateSurface, followed by
      * SwapCons being called in Render.
      */
     virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
                                         const gfx::IntSize& size);
@@ -156,17 +156,17 @@ class SurfaceStream_TripleBuffer_Copy
     : public SurfaceStream
 {
 protected:
     SharedSurface* mStaging;
     SharedSurface* mConsumer;
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer_Copy)
-    SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream);
+    explicit SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream);
     virtual ~SurfaceStream_TripleBuffer_Copy();
 
     virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
                                         const gfx::IntSize& size);
 
     virtual SharedSurface* SwapConsumer_NoWait();
 
     virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer);
@@ -183,17 +183,17 @@ protected:
     // Returns true if we were able to wait, false if not
     virtual void WaitForCompositor() {}
 
     // To support subclasses initializing the mType.
     SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream);
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer)
-    SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
+    explicit SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
     virtual ~SurfaceStream_TripleBuffer();
     virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory);
 
 private:
     // Common constructor code.
     void Init(SurfaceStream* prevStream);
 
 public:
@@ -208,17 +208,17 @@ public:
 
 class SurfaceStream_TripleBuffer_Async
     : public SurfaceStream_TripleBuffer
 {
 protected:
     virtual void WaitForCompositor() MOZ_OVERRIDE;
 
 public:
-    SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream);
+    explicit SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream);
     virtual ~SurfaceStream_TripleBuffer_Async();
 };
 
 
 } // namespace gl
 } // namespace mozilla
 
 #endif // SURFACESTREAM_H_
--- a/gfx/gl/TextureGarbageBin.h
+++ b/gfx/gl/TextureGarbageBin.h
@@ -26,17 +26,17 @@ private:
     {
     }
 
     GLContext* mGL;
     Mutex mMutex;
     std::stack<GLuint> mGarbageTextures;
 
 public:
-    TextureGarbageBin(GLContext* gl)
+    explicit TextureGarbageBin(GLContext* gl)
         : mGL(gl)
         , mMutex("TextureGarbageBin mutex")
     {}
 
     void GLContextTeardown();
     void Trash(GLuint tex);
     void EmptyGarbage();
 };
--- a/gfx/skia/trunk/include/gpu/GrConfig.h
+++ b/gfx/skia/trunk/include/gpu/GrConfig.h
@@ -227,9 +227,21 @@ typedef unsigned __int64 uint64_t;
 /**
  * GR_STROKE_PATH_RENDERING controls whether or not the GrStrokePathRenderer can be selected
  * as a path renderer. GrStrokePathRenderer is currently an experimental path renderer.
  */
 #if !defined(GR_STROKE_PATH_RENDERING)
     #define GR_STROKE_PATH_RENDERING                 0
 #endif
 
+/**
+ * GR_ALWAYS_ALLOCATE_ON_HEAP determines whether various temporary buffers created
+ * in the GPU backend are always allocated on the heap or are allowed to be
+ * allocated on the stack for smaller memory requests.
+ *
+ * This is only used for memory buffers that are created and then passed through to the
+ * 3D API (e.g. as texture or geometry data)
+ */
+#if !defined(GR_ALWAYS_ALLOCATE_ON_HEAP)
+    #define GR_ALWAYS_ALLOCATE_ON_HEAP 0
 #endif
+
+#endif
--- a/gfx/skia/trunk/include/gpu/GrTypes.h
+++ b/gfx/skia/trunk/include/gpu/GrTypes.h
@@ -706,9 +706,25 @@ static inline size_t GrCompressedFormatD
 
 /**
  * This value translates to reseting all the context state for any backend.
  */
 static const uint32_t kAll_GrBackendState = 0xffffffff;
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#if GR_ALWAYS_ALLOCATE_ON_HEAP
+    #define GrAutoMallocBaseType SkAutoMalloc
+#else
+    #define GrAutoMallocBaseType SkAutoSMalloc<S>
 #endif
+
+template <size_t S> class GrAutoMalloc : public GrAutoMallocBaseType {
+public:
+    GrAutoMalloc() : INHERITED() {}
+    explicit GrAutoMalloc(size_t size) : INHERITED(size) {}
+    virtual ~GrAutoMalloc() {}
+private:
+    typedef GrAutoMallocBaseType INHERITED;
+};
+
+#undef GrAutoMallocBaseType
+#endif
--- a/gfx/skia/trunk/include/gpu/GrUserConfig.h
+++ b/gfx/skia/trunk/include/gpu/GrUserConfig.h
@@ -31,10 +31,10 @@
  */
 //#define GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT 2048
 
 /*
  * This allows us to set a callback to be called before each GL call to ensure
  * that our context is set correctly
  */
 #define GR_GL_PER_GL_FUNC_CALLBACK  1
-
+#define GR_ALWAYS_ALLOCATE_ON_HEAP  1
 #endif
--- a/gfx/skia/trunk/src/gpu/GrContext.cpp
+++ b/gfx/skia/trunk/src/gpu/GrContext.cpp
@@ -379,17 +379,17 @@ GrTexture* GrContext::createResizedTextu
         // no longer need to clamp at min RT size.
         rtDesc.fWidth  = GrNextPow2(desc.fWidth);
         rtDesc.fHeight = GrNextPow2(desc.fHeight);
 
         // We shouldn't be resizing a compressed texture.
         SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
 
         size_t bpp = GrBytesPerPixel(desc.fConfig);
-        SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
+        GrAutoMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
         stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
                       srcData, desc.fWidth, desc.fHeight, bpp);
 
         size_t stretchedRowBytes = rtDesc.fWidth * bpp;
 
         texture = fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
         SkASSERT(NULL != texture);
     }
--- a/gfx/skia/trunk/src/gpu/GrTextStrike.cpp
+++ b/gfx/skia/trunk/src/gpu/GrTextStrike.cpp
@@ -301,17 +301,18 @@ bool GrTextStrike::addGlyphToAtlas(GrGly
     SkASSERT(fCache.find(glyph->fPackedID));
     SkASSERT(NULL == glyph->fPlot);
 
     SkAutoUnref ar(SkSafeRef(scaler));
 
     int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
 
     size_t size = glyph->fBounds.area() * bytesPerPixel;
-    SkAutoSMalloc<1024> storage(size);
+    GrAutoMalloc<1024> storage(size);
+
     if (fUseDistanceField) {
         if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(),
                                            glyph->height(),
                                            storage.get())) {
             return false;
         }
     } else {
         if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
--- a/gfx/skia/trunk/src/gpu/gl/GrGpuGL.cpp
+++ b/gfx/skia/trunk/src/gpu/gl/GrGpuGL.cpp
@@ -562,17 +562,17 @@ bool GrGpuGL::uploadTexData(const GrGLTe
     size_t bpp = GrBytesPerPixel(dataConfig);
     if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
                                  &width, &height, &data, &rowBytes)) {
         return false;
     }
     size_t trimRowBytes = width * bpp;
 
     // in case we need a temporary, trimmed copy of the src pixels
-    SkAutoSMalloc<128 * 128> tempStorage;
+    GrAutoMalloc<128 * 128> tempStorage;
 
     // paletted textures cannot be partially updated
     // We currently lazily create MIPMAPs when the we see a draw with
     // GrTextureParams::kMipMap_FilterMode. Using texture storage requires that the
     // MIP levels are all created when the texture is created. So for now we don't use
     // texture storage.
     bool useTexStorage = false &&
                          isNewTexture &&
@@ -1669,17 +1669,17 @@ bool GrGpuGL::onReadPixels(GrRenderTarge
     if (0 == rowBytes) {
         rowBytes = tightRowBytes;
     }
     size_t readDstRowBytes = tightRowBytes;
     void* readDst = buffer;
 
     // determine if GL can read using the passed rowBytes or if we need
     // a scratch buffer.
-    SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
+    GrAutoMalloc<32 * sizeof(GrColor)> scratch;
     if (rowBytes != tightRowBytes) {
         if (this->glCaps().packRowLengthSupport()) {
             SkASSERT(!(rowBytes % sizeof(GrColor)));
             GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH,
                                 static_cast<GrGLint>(rowBytes / sizeof(GrColor))));
             readDstRowBytes = rowBytes;
         } else {
             scratch.reset(tightRowBytes * height);
--- a/gfx/src/FilterSupport.cpp
+++ b/gfx/src/FilterSupport.cpp
@@ -1625,26 +1625,26 @@ struct FilterAttribute {
   bool operator!=(const FilterAttribute& aOther) const
   {
     return !(*this == aOther);
   }
 
   AttributeType Type() const { return mType; }
 
 #define MAKE_CONSTRUCTOR_AND_ACCESSOR_BASIC(type, typeLabel)   \
-  FilterAttribute(type aValue)                                 \
+  explicit FilterAttribute(type aValue)                        \
    : mType(AttributeType::e##typeLabel), m##typeLabel(aValue)  \
   {}                                                           \
   type As##typeLabel() {                                       \
     MOZ_ASSERT(mType == AttributeType::e##typeLabel);          \
     return m##typeLabel;                                       \
   }
 
 #define MAKE_CONSTRUCTOR_AND_ACCESSOR_CLASS(className)         \
-  FilterAttribute(const className& aValue)                     \
+  explicit FilterAttribute(const className& aValue)            \
    : mType(AttributeType::e##className), m##className(new className(aValue)) \
   {}                                                           \
   className As##className() {                                  \
     MOZ_ASSERT(mType == AttributeType::e##className);          \
     return *m##className;                                      \
   }
 
   MAKE_CONSTRUCTOR_AND_ACCESSOR_BASIC(bool, Bool)
--- a/gfx/src/FilterSupport.h
+++ b/gfx/src/FilterSupport.h
@@ -288,17 +288,17 @@ public:
   enum {
     kPrimitiveIndexSourceGraphic = -1,
     kPrimitiveIndexSourceAlpha = -2,
     kPrimitiveIndexFillPaint = -3,
     kPrimitiveIndexStrokePaint = -4
   };
 
   FilterPrimitiveDescription();
-  FilterPrimitiveDescription(PrimitiveType aType);
+  explicit FilterPrimitiveDescription(PrimitiveType aType);
   FilterPrimitiveDescription(const FilterPrimitiveDescription& aOther);
   FilterPrimitiveDescription& operator=(const FilterPrimitiveDescription& aOther);
 
   PrimitiveType Type() const { return mType; }
   void SetType(PrimitiveType aType) { mType = aType; }
   const AttributeMap& Attributes() const { return mAttributes; }
   AttributeMap& Attributes() { return mAttributes; }
 
@@ -372,17 +372,17 @@ private:
 
 /**
  * A data structure that contains one or more FilterPrimitiveDescriptions.
  * Designed to be serializable via IPDL, so it must not contain complex
  * functionality.
  */
 struct FilterDescription MOZ_FINAL {
   FilterDescription() {}
-  FilterDescription(const nsTArray<FilterPrimitiveDescription>& aPrimitives)
+  explicit FilterDescription(const nsTArray<FilterPrimitiveDescription>& aPrimitives)
    : mPrimitives(aPrimitives)
   {}
 
   bool operator==(const FilterDescription& aOther) const;
   bool operator!=(const FilterDescription& aOther) const
   {
     return !(*this == aOther);
   }
--- a/gfx/src/gfxCrashReporterUtils.h
+++ b/gfx/src/gfxCrashReporterUtils.h
@@ -19,17 +19,17 @@ namespace mozilla {
   *
   * This ScopedGfxFeatureReporter class is designed to be fool-proof to use in functions that
   * have many exit points. We don't want to encourage having function with many exit points.
   * It just happens that our graphics features initialization functions are like that.
   */
 class NS_GFX ScopedGfxFeatureReporter
 {
 public:
-  ScopedGfxFeatureReporter(const char *aFeature, bool force = false)
+  explicit ScopedGfxFeatureReporter(const char *aFeature, bool force = false)
     : mFeature(aFeature), mStatusChar('-')
   {
     WriteAppNote(force ? '!' : '?');
   }
   ~ScopedGfxFeatureReporter() {
     WriteAppNote(mStatusChar);
   }
   void SetSuccessful() { mStatusChar = '+'; }
--- a/gfx/src/nsTransform2D.h
+++ b/gfx/src/nsTransform2D.h
@@ -23,22 +23,16 @@ private:
   * Transformation of a coordinate (x, y) is obtained by setting
   * v = (x, y, 1)^T and evaluating  M . v
   **/
 
   float     m00, m11, m20, m21;
 
 public:
   nsTransform2D(void)                         { m20 = m21 = 0.0f; m00 = m11 = 1.0f; }
-  nsTransform2D(nsTransform2D *aTransform2D)  {
-    m00 = aTransform2D->m00;
-    m11 = aTransform2D->m11;
-    m20 = aTransform2D->m20;
-    m21 = aTransform2D->m21;
-  }
 
   ~nsTransform2D(void)                        { }
 
  /**
   * set this transform to a translation
   *
   * @param      tx, x translation
   * @param      ty, y translation
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -166,17 +166,17 @@ struct BlurCacheKey : public PLDHashEntr
 
   BlurCacheKey(const gfxRect& aRect, const gfxIntSize &aBlurRadius, const gfxRect& aSkipRect, BackendType aBackend)
     : mRect(aRect)
     , mBlurRadius(aBlurRadius)
     , mSkipRect(aSkipRect)
     , mBackend(aBackend)
   { }
 
-  BlurCacheKey(const BlurCacheKey* aOther)
+  explicit BlurCacheKey(const BlurCacheKey* aOther)
     : mRect(aOther->mRect)
     , mBlurRadius(aOther->mBlurRadius)
     , mSkipRect(aOther->mSkipRect)
     , mBackend(aOther->mBackend)
   { }
 
   static PLDHashNumber
   HashKey(const KeyTypePointer aKey)
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -36,17 +36,17 @@ using namespace mozilla::gfx;
 UserDataKey gfxContext::sDontUseAsSourceKey;
 
 /* This class lives on the stack and allows gfxContext users to easily, and
  * performantly get a gfx::Pattern to use for drawing in their current context.
  */
 class GeneralPattern
 {
 public:    
-  GeneralPattern(gfxContext *aContext) : mContext(aContext), mPattern(nullptr) {}
+  explicit GeneralPattern(gfxContext *aContext) : mContext(aContext), mPattern(nullptr) {}
   ~GeneralPattern() { if (mPattern) { mPattern->~Pattern(); } }
 
   operator mozilla::gfx::Pattern&()
   {
     gfxContext::AzureState &state = mContext->CurrentState();
 
     if (state.pattern) {
       return *state.pattern->GetPattern(mContext->mDT, state.patternTransformChanged ? &state.patternTransform : nullptr);
--- a/gfx/thebes/gfxCoreTextShaper.h
+++ b/gfx/thebes/gfxCoreTextShaper.h
@@ -9,17 +9,17 @@
 #include "gfxFont.h"
 
 #include <ApplicationServices/ApplicationServices.h>
 
 class gfxMacFont;
 
 class gfxCoreTextShaper : public gfxFontShaper {
 public:
-    gfxCoreTextShaper(gfxMacFont *aFont);
+    explicit gfxCoreTextShaper(gfxMacFont *aFont);
 
     virtual ~gfxCoreTextShaper();
 
     virtual bool ShapeText(gfxContext      *aContext,
                            const char16_t *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
--- a/gfx/thebes/gfxDrawable.cpp
+++ b/gfx/thebes/gfxDrawable.cpp
@@ -120,17 +120,17 @@ gfxPatternDrawable::gfxPatternDrawable(g
 }
 
 gfxPatternDrawable::~gfxPatternDrawable()
 {
 }
 
 class DrawingCallbackFromDrawable : public gfxDrawingCallback {
 public:
-    DrawingCallbackFromDrawable(gfxDrawable* aDrawable)
+    explicit DrawingCallbackFromDrawable(gfxDrawable* aDrawable)
      : mDrawable(aDrawable) {
         NS_ASSERTION(aDrawable, "aDrawable is null!");
     }
 
     virtual ~DrawingCallbackFromDrawable() {}
 
     virtual bool operator()(gfxContext* aContext,
                               const gfxRect& aFillRect,
--- a/gfx/thebes/gfxDrawable.h
+++ b/gfx/thebes/gfxDrawable.h
@@ -19,17 +19,17 @@ class gfxPattern;
 /**
  * gfxDrawable
  * An Interface representing something that has an intrinsic size and can draw
  * itself repeatedly.
  */
 class gfxDrawable {
     NS_INLINE_DECL_REFCOUNTING(gfxDrawable)
 public:
-    gfxDrawable(const gfxIntSize aSize)
+    explicit gfxDrawable(const gfxIntSize aSize)
      : mSize(aSize) {}
 
     /**
      * Draw into aContext filling aFillRect, possibly repeating, using aFilter.
      * aTransform is a userspace to "image"space matrix. For example, if Draw
      * draws using a gfxPattern, this is the matrix that should be set on the
      * pattern prior to rendering it.
      *  @return whether drawing was successful
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -550,17 +550,17 @@ gfxFontEntry::TryGetColorGlyphs()
  * FontTableBlobData
  *
  * See FontTableHashEntry for the general strategy.
  */
 
 class gfxFontEntry::FontTableBlobData {
 public:
     // Adopts the content of aBuffer.
-    FontTableBlobData(FallibleTArray<uint8_t>& aBuffer)
+    explicit FontTableBlobData(FallibleTArray<uint8_t>& aBuffer)
         : mHashtable(nullptr), mHashKey(0)
     {
         MOZ_COUNT_CTOR(FontTableBlobData);
         mTableData.SwapElements(aBuffer);
     }
 
     ~FontTableBlobData() {
         MOZ_COUNT_DTOR(FontTableBlobData);
@@ -6127,17 +6127,17 @@ gfxFontGroup::UpdateFontList()
         mSkipDrawing = false;
         BuildFontList();
         mCurrGeneration = GetGeneration();
         mCachedEllipsisTextRun = nullptr;
     }
 }
 
 struct PrefFontCallbackData {
-    PrefFontCallbackData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamiliesArray)
+    explicit PrefFontCallbackData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamiliesArray)
         : mPrefFamilies(aFamiliesArray)
     {}
 
     nsTArray<nsRefPtr<gfxFontFamily> >& mPrefFamilies;
 
     static bool AddFontFamilyEntry(eFontPrefLang aLang, const nsAString& aName, void *aClosure)
     {
         PrefFontCallbackData *prefFontData = static_cast<PrefFontCallbackData*>(aClosure);
@@ -7004,17 +7004,17 @@ HasNonOpaqueColor(gfxContext *aContext, 
         }
     }
         
     return false;
 }
 
 // helper class for double-buffering drawing with non-opaque color
 struct BufferAlphaColor {
-    BufferAlphaColor(gfxContext *aContext)
+    explicit BufferAlphaColor(gfxContext *aContext)
         : mContext(aContext)
     {
 
     }
 
     ~BufferAlphaColor() {}
 
     void PushSolidColor(const gfxRect& aBounds, const gfxRGBA& aAlphaColor, uint32_t appsPerDevUnit)
--- a/gfx/thebes/gfxFontInfoLoader.cpp
+++ b/gfx/thebes/gfxFontInfoLoader.cpp
@@ -26,31 +26,31 @@ FontInfoData::Load()
     mLoadTime = TimeStamp::Now() - start;
 }
 
 class FontInfoLoadCompleteEvent : public nsRunnable {
     virtual ~FontInfoLoadCompleteEvent() {}
 
     NS_DECL_ISUPPORTS_INHERITED
 
-    FontInfoLoadCompleteEvent(FontInfoData *aFontInfo) :
+    explicit FontInfoLoadCompleteEvent(FontInfoData *aFontInfo) :
         mFontInfo(aFontInfo)
     {}
 
     NS_IMETHOD Run();
 
     nsRefPtr<FontInfoData> mFontInfo;
 };
 
 class AsyncFontInfoLoader : public nsRunnable {
     virtual ~AsyncFontInfoLoader() {}
 
     NS_DECL_ISUPPORTS_INHERITED
 
-    AsyncFontInfoLoader(FontInfoData *aFontInfo) :
+    explicit AsyncFontInfoLoader(FontInfoData *aFontInfo) :
         mFontInfo(aFontInfo)
     {
         mCompleteEvent = new FontInfoLoadCompleteEvent(aFontInfo);
     }
 
     NS_IMETHOD Run();
 
     nsRefPtr<FontInfoData> mFontInfo;
--- a/gfx/thebes/gfxFontInfoLoader.h
+++ b/gfx/thebes/gfxFontInfoLoader.h
@@ -187,17 +187,17 @@ public:
 
 protected:
     class ShutdownObserver : public nsIObserver
     {
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIOBSERVER
 
-        ShutdownObserver(gfxFontInfoLoader *aLoader)
+        explicit ShutdownObserver(gfxFontInfoLoader *aLoader)
             : mLoader(aLoader)
         { }
 
     protected:
         virtual ~ShutdownObserver()
         { }
 
         gfxFontInfoLoader *mLoader;
--- a/gfx/thebes/gfxGradientCache.cpp
+++ b/gfx/thebes/gfxGradientCache.cpp
@@ -24,17 +24,17 @@ struct GradientCacheKey : public PLDHash
   const nsTArray<GradientStop> mStops;
   ExtendMode mExtend;
   BackendType mBackendType;
 
   GradientCacheKey(const nsTArray<GradientStop>& aStops, ExtendMode aExtend, BackendType aBackendType)
     : mStops(aStops), mExtend(aExtend), mBackendType(aBackendType)
   { }
 
-  GradientCacheKey(const GradientCacheKey* aOther)
+  explicit GradientCacheKey(const GradientCacheKey* aOther)
     : mStops(aOther->mStops), mExtend(aOther->mExtend), mBackendType(aOther->mBackendType)
   { }
 
   union FloatUint32
   {
     float    f;
     uint32_t u;
   };
--- a/gfx/thebes/gfxGraphiteShaper.h
+++ b/gfx/thebes/gfxGraphiteShaper.h
@@ -9,17 +9,17 @@
 #include "gfxFont.h"
 
 struct gr_face;
 struct gr_font;
 struct gr_segment;
 
 class gfxGraphiteShaper : public gfxFontShaper {
 public:
-    gfxGraphiteShaper(gfxFont *aFont);
+    explicit gfxGraphiteShaper(gfxFont *aFont);
     virtual ~gfxGraphiteShaper();
 
     virtual bool ShapeText(gfxContext      *aContext,
                            const char16_t *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
                            gfxShapedText   *aShapedText);
--- a/gfx/thebes/gfxHarfBuzzShaper.h
+++ b/gfx/thebes/gfxHarfBuzzShaper.h
@@ -8,17 +8,17 @@
 
 #include "gfxFont.h"
 
 #include "harfbuzz/hb.h"
 #include "nsUnicodeProperties.h"
 
 class gfxHarfBuzzShaper : public gfxFontShaper {
 public:
-    gfxHarfBuzzShaper(gfxFont *aFont);
+    explicit gfxHarfBuzzShaper(gfxFont *aFont);
     virtual ~gfxHarfBuzzShaper();
 
     /*
      * For HarfBuzz font callback functions, font_data is a ptr to a
      * FontCallbackData struct
      */
     struct FontCallbackData {
         gfxHarfBuzzShaper *mShaper;
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -64,17 +64,17 @@ public:
      *        than width * stride, or width*stride <=0, this value is ignored.
      * @param aClear 
      *
      * @see gfxImageFormat
      */
     gfxImageSurface(const gfxIntSize& aSize, gfxImageFormat aFormat,
                     long aStride, int32_t aMinimalAllocation, bool aClear);
 
-    gfxImageSurface(cairo_surface_t *csurf);
+    explicit gfxImageSurface(cairo_surface_t *csurf);
 
     virtual ~gfxImageSurface();
 
     // ImageSurface methods
     gfxImageFormat Format() const { return mFormat; }
 
     virtual const gfxIntSize GetSize() const { return mSize; }
     int32_t Width() const { return mSize.width; }
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -375,17 +375,17 @@ MacOSFontEntry::AddSizeOfIncludingThis(M
 }
 
 /* gfxMacFontFamily */
 #pragma mark-
 
 class gfxMacFontFamily : public gfxFontFamily
 {
 public:
-    gfxMacFontFamily(nsAString& aName) :
+    explicit gfxMacFontFamily(nsAString& aName) :
         gfxFontFamily(aName)
     {}
 
     virtual ~gfxMacFontFamily() {}
 
     virtual void LocalizedName(nsAString& aLocalizedName);
 
     virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
@@ -538,17 +538,17 @@ gfxMacFontFamily::FindStyleVariations(Fo
 
 
 /* gfxSingleFaceMacFontFamily */
 #pragma mark-
 
 class gfxSingleFaceMacFontFamily : public gfxFontFamily
 {
 public:
-    gfxSingleFaceMacFontFamily(nsAString& aName) :
+    explicit gfxSingleFaceMacFontFamily(nsAString& aName) :
         gfxFontFamily(aName)
     {
         mFaceNamesInitialized = true; // omit from face name lists
     }
 
     virtual ~gfxSingleFaceMacFontFamily() {}
 
     virtual void LocalizedName(nsAString& aLocalizedName);
--- a/gfx/thebes/gfxMathTable.h
+++ b/gfx/thebes/gfxMathTable.h
@@ -24,17 +24,17 @@ class gfxMathTable
 public:
     /**
      * @param aMathTable The MATH table from the OpenType font
      *
      * The gfxMathTable object takes over ownership of the blob references
      * that are passed in, and will hb_blob_destroy() them when finished;
      * the caller should -not- destroy this reference.
      */
-    gfxMathTable(hb_blob_t* aMathTable);
+    explicit gfxMathTable(hb_blob_t* aMathTable);
 
     /**
      * Releases our reference to the MATH table and cleans up everything else.
      */
     ~gfxMathTable();
 
     /**
      * Returns the value of the specified constant from the MATH table.
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -506,17 +506,17 @@ gfxPlatformFontList::GetFontList(nsIAtom
 
     mFontFamilies.Enumerate(gfxPlatformFontList::HashEnumFuncForFamilies, &data);
 
     aListOfFonts.Sort();
     aListOfFonts.Compact();
 }
 
 struct FontFamilyListData {
-    FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 
+    explicit FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 
         : mFamilyArray(aFamilyArray)
     {}
 
     static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey,
                                         nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                         void *aUserArg)
     {
         FontFamilyListData *data = static_cast<FontFamilyListData*>(aUserArg);
@@ -963,17 +963,17 @@ gfxPlatformFontList::LoadFontInfo()
         mOtherFamilyNamesInitialized = true;
         mFaceNameListsInitialized = true;
     }
 
     return done;
 }
 
 struct LookupMissedFaceNamesData {
-    LookupMissedFaceNamesData(gfxPlatformFontList *aFontList)
+    explicit LookupMissedFaceNamesData(gfxPlatformFontList *aFontList)
         : mFontList(aFontList), mFoundName(false) {}
 
     gfxPlatformFontList *mFontList;
     bool mFoundName;
 };
 
 /*static*/ PLDHashOperator
 gfxPlatformFontList::LookupMissedFaceNamesProc(nsStringHashKey *aKey,
@@ -985,17 +985,17 @@ gfxPlatformFontList::LookupMissedFaceNam
     if (data->mFontList->FindFaceName(aKey->GetKey())) {
         data->mFoundName = true;
         return PL_DHASH_STOP;
     }
     return PL_DHASH_NEXT;
 }
 
 struct LookupMissedOtherNamesData {
-    LookupMissedOtherNamesData(gfxPlatformFontList *aFontList)
+    explicit LookupMissedOtherNamesData(gfxPlatformFontList *aFontList)
         : mFontList(aFontList), mFoundName(false) {}
 
     gfxPlatformFontList *mFontList;
     bool mFoundName;
 };
 
 /*static*/ PLDHashOperator
 gfxPlatformFontList::LookupMissedOtherNamesProc(nsStringHashKey *aKey,
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -20,17 +20,17 @@
 #include "mozilla/MemoryReporting.h"
 
 class CharMapHashKey : public PLDHashEntryHdr
 {
 public:
     typedef gfxCharacterMap* KeyType;
     typedef const gfxCharacterMap* KeyTypePointer;
 
-    CharMapHashKey(const gfxCharacterMap *aCharMap) :
+    explicit CharMapHashKey(const gfxCharacterMap *aCharMap) :
         mCharMap(const_cast<gfxCharacterMap*>(aCharMap))
     {
         MOZ_COUNT_CTOR(CharMapHashKey);
     }
     CharMapHashKey(const CharMapHashKey& toCopy) :
         mCharMap(toCopy.mCharMap)
     {
         MOZ_COUNT_CTOR(CharMapHashKey);
@@ -192,17 +192,17 @@ protected:
     class MemoryReporter MOZ_FINAL : public nsIMemoryReporter
     {
         ~MemoryReporter() {}
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIMEMORYREPORTER
     };
 
-    gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
+    explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
 
     static gfxPlatformFontList *sPlatformFontList;
 
     static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey,
                                                nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                                void* userArg);
 
     // returns default font for a given character, null otherwise
--- a/gfx/thebes/gfxQuartzImageSurface.h
+++ b/gfx/thebes/gfxQuartzImageSurface.h
@@ -8,18 +8,18 @@
 
 #include "gfxASurface.h"
 #include "nsSize.h"
 
 class gfxImageSurface;
 
 class gfxQuartzImageSurface : public gfxASurface {
 public:
-    gfxQuartzImageSurface(gfxImageSurface *imageSurface);
-    gfxQuartzImageSurface(cairo_surface_t *csurf);
+    explicit gfxQuartzImageSurface(gfxImageSurface *imageSurface);
+    explicit gfxQuartzImageSurface(cairo_surface_t *csurf);
 
     virtual ~gfxQuartzImageSurface();
 
     already_AddRefed<gfxImageSurface> GetAsImageSurface();
     virtual int32_t KnownMemoryUsed();
     virtual const gfxIntSize GetSize() const { return gfxIntSize(mSize.width, mSize.height); }
 
 protected:
--- a/gfx/thebes/gfxReusableImageSurfaceWrapper.h
+++ b/gfx/thebes/gfxReusableImageSurfaceWrapper.h
@@ -10,17 +10,17 @@
 class gfxImageSurface;
 
 /**
  * A cross-thread capable implementation of gfxReusableSurfaceWrapper based
  * on gfxImageSurface.
  */
 class gfxReusableImageSurfaceWrapper : public gfxReusableSurfaceWrapper {
 public:
-  gfxReusableImageSurfaceWrapper(gfxImageSurface* aSurface);
+  explicit gfxReusableImageSurfaceWrapper(gfxImageSurface* aSurface);
 protected:
   ~gfxReusableImageSurfaceWrapper();
 
 public:
   const unsigned char* GetReadOnlyData() const MOZ_OVERRIDE;
   gfxImageFormat Format() MOZ_OVERRIDE;
   gfxReusableSurfaceWrapper* GetWritable(gfxImageSurface** aSurface) MOZ_OVERRIDE;
   void ReadLock() MOZ_OVERRIDE;
--- a/gfx/thebes/gfxTeeSurface.h
+++ b/gfx/thebes/gfxTeeSurface.h
@@ -18,17 +18,17 @@ template<class T> class nsRefPtr;
  * All drawing is performed on all the surfaces.
  *
  * The device transform of a tee surface is applied before drawing to the
  * underlying surfaces --- which also applies the device transforms of the
  * underlying surfaces.
  */
 class gfxTeeSurface : public gfxASurface {
 public:
-    gfxTeeSurface(cairo_surface_t *csurf);
+    explicit gfxTeeSurface(cairo_surface_t *csurf);
     gfxTeeSurface(gfxASurface **aSurfaces, int32_t aSurfaceCount);
 
     virtual const gfxIntSize GetSize() const;
 
     /**
      * Returns the list of underlying surfaces.
      */
     void GetSurfaces(nsTArray<nsRefPtr<gfxASurface> > *aSurfaces);
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -81,17 +81,17 @@ public:
 
 // initially contains a set of proxy font entry objects, replaced with
 // platform/user fonts as downloaded
 
 class gfxMixedFontFamily : public gfxFontFamily {
 public:
     friend class gfxUserFontSet;
 
-    gfxMixedFontFamily(const nsAString& aName)
+    explicit gfxMixedFontFamily(const nsAString& aName)
         : gfxFontFamily(aName) { }
 
     virtual ~gfxMixedFontFamily() { }
 
     // Add the given font entry to the end of the family's list.
     // Any earlier occurrence is removed, so this has the effect of "advancing"
     // the entry to the end of the list.
     void AddFontEntry(gfxFontEntry *aFontEntry) {
@@ -368,17 +368,17 @@ public:
             { }
         };
 
         class Entry : public PLDHashEntryHdr {
         public:
             typedef const Key& KeyType;
             typedef const Key* KeyTypePointer;
 
-            Entry(KeyTypePointer aKey)
+            explicit Entry(KeyTypePointer aKey)
                 : mURI(aKey->mURI),
                   mPrincipal(aKey->mPrincipal),
                   mCRC32(aKey->mCRC32),
                   mLength(aKey->mLength),
                   mFontEntry(aKey->mFontEntry),
                   mPrivate(aKey->mPrivate),
                   mPersistence(aKey->mPersistence)
             { }
--- a/image/src/ClippedImage.cpp
+++ b/image/src/ClippedImage.cpp
@@ -35,27 +35,27 @@ public:
                             uint32_t aFlags)
     : mSurface(aSurface)
     , mViewportSize(aViewportSize)
     , mFrame(aFrame)
     , mFlags(aFlags)
   {
     MOZ_ASSERT(mSurface, "Must have a valid surface");
     if (aSVGContext) {
-      mSVGContext.construct(*aSVGContext);
+      mSVGContext.emplace(*aSVGContext);
     }
   }
 
   bool Matches(const nsIntSize& aViewportSize,
                const SVGImageContext* aSVGContext,
                float aFrame,
                uint32_t aFlags)
   {
-    bool matchesSVGContext = (!aSVGContext && mSVGContext.empty()) ||
-                             *aSVGContext == mSVGContext.ref();
+    bool matchesSVGContext = (!aSVGContext && !mSVGContext) ||
+                             (*aSVGContext == *mSVGContext);
     return mViewportSize == aViewportSize &&
            matchesSVGContext &&
            mFrame == aFrame &&
            mFlags == aFlags;
   }
 
   TemporaryRef<SourceSurface> Surface() {
     return mSurface;
@@ -123,46 +123,46 @@ ClippedImage::~ClippedImage()
 
 bool
 ClippedImage::ShouldClip()
 {
   // We need to evaluate the clipping region against the image's width and height
   // once they're available to determine if it's valid and whether we actually
   // need to do any work. We may fail if the image's width and height aren't
   // available yet, in which case we'll try again later.
-  if (mShouldClip.empty()) {
+  if (mShouldClip.isNothing()) {
     int32_t width, height;
     nsRefPtr<imgStatusTracker> innerImageStatusTracker =
       InnerImage()->GetStatusTracker();
     if (InnerImage()->HasError()) {
       // If there's a problem with the inner image we'll let it handle everything.
-      mShouldClip.construct(false);
+      mShouldClip.emplace(false);
     } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&width)) && width > 0 &&
                NS_SUCCEEDED(InnerImage()->GetHeight(&height)) && height > 0) {
       // Clamp the clipping region to the size of the underlying image.
       mClip = mClip.Intersect(nsIntRect(0, 0, width, height));
 
       // If the clipping region is the same size as the underlying image we
       // don't have to do anything.
-      mShouldClip.construct(!mClip.IsEqualInterior(nsIntRect(0, 0, width, height)));
+      mShouldClip.emplace(!mClip.IsEqualInterior(nsIntRect(0, 0, width, height)));
     } else if (innerImageStatusTracker &&
                innerImageStatusTracker->IsLoading()) {
       // The image just hasn't finished loading yet. We don't yet know whether
       // clipping with be needed or not for now. Just return without memoizing
       // anything.
       return false;
     } else {
       // We have a fully loaded image without a clearly defined width and
       // height. This can happen with SVG images.
-      mShouldClip.construct(false);
+      mShouldClip.emplace(false);
     }
   }
 
-  MOZ_ASSERT(!mShouldClip.empty(), "Should have computed a result");
-  return mShouldClip.ref();
+  MOZ_ASSERT(mShouldClip.isSome(), "Should have computed a result");
+  return *mShouldClip;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(ClippedImage, ImageWrapper)
 
 nsIntRect
 ClippedImage::FrameRect(uint32_t aWhichFrame)
 {
   if (!ShouldClip()) {
--- a/image/src/ImageMetadata.h
+++ b/image/src/ImageMetadata.h
@@ -43,26 +43,26 @@ public:
 
   void SetIsNonPremultiplied(bool nonPremult)
   {
     mIsNonPremultiplied = nonPremult;
   }
 
   void SetSize(int32_t width, int32_t height, Orientation orientation)
   {
-    mSize.construct(nsIntSize(width, height));
-    mOrientation.construct(orientation);
+    mSize.emplace(nsIntSize(width, height));
+    mOrientation.emplace(orientation);
   }
 
-  bool HasSize() const { return !mSize.empty(); }
-  bool HasOrientation() const { return !mOrientation.empty(); }
+  bool HasSize() const { return mSize.isSome(); }
+  bool HasOrientation() const { return mOrientation.isSome(); }
 
-  int32_t GetWidth() const { return mSize.ref().width; }
-  int32_t GetHeight() const { return mSize.ref().height; }
-  Orientation GetOrientation() const { return mOrientation.ref(); }
+  int32_t GetWidth() const { return mSize->width; }
+  int32_t GetHeight() const { return mSize->height; }
+  Orientation GetOrientation() const { return *mOrientation; }
 
 private:
   // The hotspot found on cursors, or -1 if none was found.
   int32_t mHotspotX;
   int32_t mHotspotY;
 
   // The loop count for animated images, or -1 for infinite loop.
   int32_t mLoopCount;
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -286,16 +286,17 @@ class Namespace(Block):
 
         Block.__init__(self)
         self.name = name
 
 class Type(Node):
     def __init__(self, name, const=0,
                  ptr=0, ptrconst=0, ptrptr=0, ptrconstptr=0,
                  ref=0,
+                 hasimplicitcopyctor=True,
                  T=None):
         """
 To avoid getting fancy with recursive types, we limit the kinds
 of pointer types that can be be constructed.
 
   ptr            => T*
   ptrconst       => T* const
   ptrptr         => T**
@@ -310,16 +311,17 @@ Any type, naked or pointer, can be const
         Node.__init__(self)
         self.name = name
         self.const = const
         self.ptr = ptr
         self.ptrconst = ptrconst
         self.ptrptr = ptrptr
         self.ptrconstptr = ptrconstptr
         self.ref = ref
+        self.hasimplicitcopyctor = hasimplicitcopyctor
         self.T = T
         # XXX could get serious here with recursive types, but shouldn't 
         # need that for this codegen
     def __deepcopy__(self, memo):
         return Type(self.name,
                     const=self.const,
                     ptr=self.ptr, ptrconst=self.ptrconst,
                     ptrptr=self.ptrptr, ptrconstptr=self.ptrconstptr,
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -327,17 +327,17 @@ def _refptrGet(expr):
 
 def _refptrForget(expr):
     return ExprCall(ExprSelect(expr, '.', 'forget'))
 
 def _refptrTake(expr):
     return ExprCall(ExprSelect(expr, '.', 'take'))
 
 def _cxxArrayType(basetype, const=0, ref=0):
-    return Type('InfallibleTArray', T=basetype, const=const, ref=ref)
+    return Type('nsTArray', T=basetype, const=const, ref=ref, hasimplicitcopyctor=False)
 
 def _cxxFallibleArrayType(basetype, const=0, ref=0):
     return Type('FallibleTArray', T=basetype, const=const, ref=ref)
 
 def _callCxxArrayLength(arr):
     return ExprCall(ExprSelect(arr, '.', 'Length'))
 
 def _callCxxCheckedArraySetLength(arr, lenexpr, sel='.'):
@@ -790,17 +790,17 @@ IPDL union type."""
 
     def callOperatorEq(self, rhs):
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
             rhs = ExprCast(rhs, self.bareType(), const=1)
         return ExprAssn(ExprDeref(self.callGetPtr()), rhs)
 
     def callCtor(self, expr=None):
         assert not isinstance(expr, list)
-        
+
         if expr is None:
             args = None
         elif self.ipdltype.isIPDL() and self.ipdltype.isActor():
             args = [ ExprCast(expr, self.bareType(), const=1) ]
         else:
             args = [ expr ]
 
         if self.recursive:
@@ -844,18 +844,23 @@ IPDL union type."""
 
     def ptrToInternalType(self):
         t = self.ptrToType()
         if self.recursive:
             t.ref = 1
         return t
 
     def defaultValue(self):
+        # Use the default constructor for any class that does not have an
+        # implicit copy constructor.
+        if not self.bareType().hasimplicitcopyctor:
+            return None
+
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
-            return ExprCast(ExprLiteral.NULL, self.bareType(), static=1)
+            return ExprLiteral.NULL
         # XXX sneaky here, maybe need ExprCtor()?
         return ExprCall(self.bareType())
 
     def getConstValue(self):
         v = ExprDeref(self.callGetConstPtr())
         # sigh
         if 'Shmem' == self.ipdltype.name():
             v = ExprCast(v, Type('Shmem', ref=1), const=1)
@@ -863,17 +868,17 @@ IPDL union type."""
             v = ExprCast(v, Type('FileDescriptor', ref=1), const=1)
         return v
 
 ##--------------------------------------------------
 
 class MessageDecl(ipdl.ast.MessageDecl):
     def baseName(self):
         return self.name
-    
+
     def recvMethod(self):
         name = _recvPrefix(self.decl.type) + self.baseName()
         if self.decl.type.isCtor():
             name += 'Constructor'
         return ExprVar(name)
 
     def sendMethod(self):
         name = _sendPrefix(self.decl.type) + self.baseName()
@@ -1086,17 +1091,17 @@ class Protocol(ipdl.ast.Protocol):
     def removeManageeMethod(self):
         return ExprVar('RemoveManagee')
 
     def createSharedMemory(self):
         return ExprVar('CreateSharedMemory')
 
     def adoptSharedMemory(self):
         return ExprVar('AdoptSharedMemory')
- 
+
     def lookupSharedMemory(self):
         return ExprVar('LookupSharedMemory')
 
     def isTrackingSharedMemory(self):
         return ExprVar('IsTrackingSharedMemory')
 
     def destroySharedMemory(self):
         return ExprVar('DestroySharedMemory')
@@ -1457,33 +1462,33 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                     aggregateTypeIncludes.add(typesToIncludes[typename])
 
         if len(aggregateTypeIncludes) != 0:
             hf.addthing(Whitespace.NL)
             hf.addthings([ Whitespace("// Headers for typedefs"), Whitespace.NL ])
 
             for headername in sorted(iter(aggregateTypeIncludes)):
                 hf.addthing(CppDirective('include', '"' + headername + '"'))
-            
+
         ipdl.ast.Visitor.visitTranslationUnit(self, tu)
         if tu.filetype == 'header':
             self.cppIncludeHeaders.append(_ipdlhHeaderName(tu))
 
         hf.addthing(Whitespace.NL)
         hf.addthings(_includeGuardEnd(hf))
 
         cf = self.cppfile
         cf.addthings((
             [ _DISCLAIMER, Whitespace.NL ]
             + [ CppDirective('include','"'+h+'.h"')
                 for h in self.cppIncludeHeaders ]
             + [ Whitespace.NL ]
         ))
 
-        if self.protocol:       
+        if self.protocol:
             # construct the namespace into which we'll stick all our defns
             ns = Namespace(self.protocol.name)
             cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
             ns.addstmts(([ Whitespace.NL]
                          + self.funcDefns
                          +[ Whitespace.NL ]))
 
         cf.addthings(self.structUnionDefns)
@@ -1494,17 +1499,17 @@ class _GenerateProtocolCode(ipdl.ast.Vis
 
     def visitInclude(self, inc):
         if inc.tu.filetype == 'header':
             self.hdrfile.addthing(CppDirective(
                     'include', '"'+ _ipdlhHeaderName(inc.tu) +'.h"'))
 
     def processStructOrUnionClass(self, su, which, forwarddecls, cls):
         clsdecl, methoddefns = _splitClassDeclDefn(cls)
-        
+
         self.hdrfile.addthings(
             [  Whitespace.NL ]
             + forwarddecls
             + [ Whitespace("""
 //-----------------------------------------------------------------------------
 // Declaration of the IPDL type |%s %s|
 //
 """% (which, su.name)),
@@ -1676,17 +1681,17 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                    ])))
         return openfunc
 
 
     def genTransitionFunc(self):
         ptype = self.protocol.decl.type
         usesend, sendvar = set(), ExprVar('__Send')
         userecv, recvvar = set(), ExprVar('__Recv')
-        
+
         def sameTrigger(trigger, actionexpr):
             if trigger is ipdl.ast.SEND or trigger is ipdl.ast.CALL:
                 usesend.add('yes')
                 return ExprBinary(sendvar, '==', actionexpr)
             else:
                 userecv.add('yes')
                 return ExprBinary(recvvar, '==',
                                   actionexpr)
@@ -1841,17 +1846,17 @@ def _generateMessageClass(clsname, msgid
     otherprocess = ExprVar('__otherProcess')
     receiving = ExprVar('__receiving')
     logger = MethodDefn(MethodDecl(
         'Log',
         params=([ Decl(Type('std::string', const=1, ref=1), pfxvar.name),
                   Decl(Type('base::ProcessHandle'), otherprocess.name),
                   Decl(Type('bool'), receiving.name) ]),
         const=1))
-    # TODO/cjones: allow selecting what information is printed to 
+    # TODO/cjones: allow selecting what information is printed to
     # the log
     msgvar = ExprVar('__logmsg')
     logger.addstmt(StmtDecl(Decl(Type('std::string'), msgvar.name)))
 
     def appendToMsg(thing):
         return StmtExpr(ExprCall(ExprSelect(msgvar, '.', 'append'),
                                  args=[ thing ]))
     logger.addstmts([
@@ -1906,17 +1911,17 @@ stmt.  Some types generate both kinds.''
         self.usingTypedefs = [ ]
         self.forwardDeclStmts = [ ]
         self.fortype = fortype
         self.unqualifiedTypedefs = unqualifiedTypedefs
 
     def maybeTypedef(self, fqname, name):
         if fqname != name or self.unqualifiedTypedefs:
             self.usingTypedefs.append(Typedef(Type(fqname), name))
-        
+
     def visitBuiltinCxxType(self, t):
         if t in self.visited: return
         self.visited.add(t)
         self.maybeTypedef(t.fullname(), t.name())
 
     def visitImportedCxxType(self, t):
         if t in self.visited: return
         self.visited.add(t)
@@ -2623,17 +2628,17 @@ class _GenerateProtocolActorCode(ipdl.as
         # make the .cpp file
         cf.addthings([
             _DISCLAIMER,
             Whitespace.NL,
             CppDirective(
                 'include',
                 '"'+ _protocolHeaderName(self.protocol, self.side) +'.h"') ]
             + setToIncludes(self.externalIncludes))
-             
+
         if self.protocol.decl.type.isToplevel():
             cf.addthings([
                 CppDirective('ifdef', 'MOZ_CRASHREPORTER'),
                 CppDirective('  include', '"nsXULAppAPI.h"'),
                 CppDirective('endif')
             ])
 
         cppheaders = [CppDirective('include', '"%s"' % filename)
@@ -2803,17 +2808,17 @@ class _GenerateProtocolActorCode(ipdl.as
 
         for md in p.messageDecls:
             managed = md.decl.type.constructedType()
             if not ptype.isManagerOf(managed) or md.decl.type.isDtor():
                 continue
 
             # add the Alloc/Dealloc interface for managed actors
             actortype = md.actorDecl().bareType(self.side)
-            
+
             self.cls.addstmt(StmtDecl(MethodDecl(
                 _allocMethod(managed, self.side).name,
                 params=md.makeCxxParams(side=self.side, implicit=0),
                 ret=actortype,
                 virtual=1, pure=1)))
 
             self.cls.addstmt(StmtDecl(MethodDecl(
                 _deallocMethod(managed, self.side).name,
@@ -3014,17 +3019,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 arrvar, p.managedVar(managed, self.side))))
 
             refmeth = MethodDefn(MethodDecl(
                 p.managedMethod(managed, self.side).name,
                 params=[ ],
                 ret=p.managedVarType(managed, self.side, const=1, ref=1),
                 const=1))
             refmeth.addstmt(StmtReturn(p.managedVar(managed, self.side)))
-            
+
             self.cls.addstmts([ meth, refmeth, Whitespace.NL ])
 
         statemethod = MethodDefn(MethodDecl(
             p.stateMethod().name,
             ret=p.fqStateType()))
         statemethod.addstmt(StmtReturn(p.stateVar()))
         self.cls.addstmts([ statemethod, Whitespace.NL ])
 
@@ -3332,17 +3337,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 CppDirective('endif')
             ])
             self.cls.addstmts([ otherpid, Whitespace.NL,
                                 getdump, Whitespace.NL ])
 
         ## private methods
         self.cls.addstmt(Label.PRIVATE)
 
-        ## FatalError()       
+        ## FatalError()
         msgparam = ExprVar('aMsg')
         msgvar = ExprVar('formattedMessage')
         actorname = _actorName(p.name, self.side)
         fatalerror = MethodDefn(MethodDecl(
             'FatalError',
             params=[ Decl(Type('char', const=1, ptrconst=1), msgparam.name) ],
             const=1, never_inline=1))
         if self.side is 'parent':
@@ -3798,17 +3803,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 abort.addstmts([
                     _runtimeAbort('this protocol tree does not use shmem'),
                     StmtReturn(_Result.NotKnown)
                 ])
                 self.asyncSwitch.addcase(
                     CaseLabel('SHMEM_CREATED_MESSAGE_TYPE'), abort)
                 self.asyncSwitch.addcase(
                     CaseLabel('SHMEM_DESTROYED_MESSAGE_TYPE'), abort)
-            
+
             otherprocess.addstmt(StmtReturn(p.otherProcessVar()))
             getchannel.addstmt(StmtReturn(ExprAddrOf(p.channelVar())))
         else:
             # delegate registration to manager
             register.addstmt(StmtReturn(ExprCall(
                 ExprSelect(p.managerVar(), '->', p.registerMethod().name),
                 [ routedvar ])))
             registerid.addstmt(StmtReturn(ExprCall(
@@ -4413,17 +4418,17 @@ class _GenerateProtocolActorCode(ipdl.as
             ExprBinary(ExprBinary(_NULL_ACTOR_ID, '==', idvar),
                        '&&',
                        ExprNot(nullablevar))))
         ifbadid.addifstmts([
                 _protocolErrorBreakpoint('bad ID for '+ self.protocol.name),
                 StmtReturn.FALSE
         ])
         read.addstmts([ ifbadid, Whitespace.NL ])
-        
+
         # if (NULL_ID == id)
         #   *var = null
         #   return true
         outactor = ExprDeref(var)
         ifnull = StmtIf(ExprBinary(_NULL_ACTOR_ID, '==', idvar))
         ifnull.addifstmts([ StmtExpr(ExprAssn(outactor, ExprLiteral.NULL)),
                             StmtReturn.TRUE ])
         read.addstmts([ ifnull, Whitespace.NL ])
@@ -4619,17 +4624,17 @@ class _GenerateProtocolActorCode(ipdl.as
         msgvar = self.msgvar
         itervar = self.itervar
         var = self.var
         intype = _cxxConstRefType(structtype, self.side)
         outtype = _cxxPtrToType(structtype, self.side)
         sd = structtype._ast
 
         write = MethodDefn(self.writeMethodDecl(intype, var))
-        read = MethodDefn(self.readMethodDecl(outtype, var))        
+        read = MethodDefn(self.readMethodDecl(outtype, var))
 
         def get(sel, f):
             return ExprCall(f.getMethod(thisexpr=var, sel=sel))
 
         for f in sd.fields:
             desc = f.getMethod().name + '\' (' + f.ipdltype.name() + \
                    ') member of \'' + intype.name
             writefield = StmtExpr(self.write(f.ipdltype, get('.', f), msgvar))
@@ -4687,18 +4692,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 # XXX: better error message
                 readcase.addstmt(StmtReturn.FALSE)
             else:
                 if c.special:
                     c = c.other       # see above
                 tmpvar = ExprVar('tmp')
                 ct = c.bareType()
                 readcase.addstmts([
-                    StmtDecl(Decl(ct, tmpvar.name),
-                      init=c.defaultValue() if ct.ptr else None),
+                    StmtDecl(Decl(ct, tmpvar.name), init=c.defaultValue()),
                     StmtExpr(ExprAssn(ExprDeref(var), tmpvar)),
                     StmtReturn(self.read(
                         c.ipdltype,
                         ExprAddrOf(ExprCall(ExprSelect(var, '->',
                                                        c.getTypeName()))),
                         msgvar, itervar))
                 ])
 
@@ -4806,17 +4810,17 @@ class _GenerateProtocolActorCode(ipdl.as
             elif isasync:
                 sendmethod = self.genAsyncSendMethod(md)
             else:
                 sendmethod = self.genBlockingSendMethod(md)
 
         # XXX figure out what to do here
         if isdtor and md.decl.type.constructedType().isToplevel():
             sendmethod = None
-                
+
         if sendmethod is not None:
             self.cls.addstmts([ sendmethod, Whitespace.NL ])
         if recvcase is not None:
             addRecvCase(recvlbl, recvcase)
             recvlbl, recvcase = None, None
 
         if self.receivesMessage(md):
             if isctor:
@@ -4905,17 +4909,17 @@ class _GenerateProtocolActorCode(ipdl.as
             StmtExpr(ExprAssn(_actorState(actorvar),
                               _startState(actorproto, fq=1)))
         ]
 
     def failCtorIf(self, md, cond):
         actorvar = md.actorDecl().var()
         type = md.decl.type.constructedType()
         failif = StmtIf(cond)
-        
+
         if self.side=='child':
             # in the child process this should not fail
             failif.addifstmt(_runtimeAbort('constructor for actor failed'))
         else:
             failif.addifstmts(self.destroyActor(md, actorvar,
                               why=_DestroyReason.FailedConstructor))
 
         failif.addifstmt(StmtReturn(ExprLiteral.NULL))
@@ -5094,17 +5098,17 @@ class _GenerateProtocolActorCode(ipdl.as
             + self.invokeRecvHandler(md, implicit=0)
             + [ Whitespace.NL ]
             + saveIdStmts
             + self.dtorEpilogue(md, md.actorDecl().var())
             + [ Whitespace.NL ]
             + self.makeReply(md, errfnRecv, routingId=idvar)
             + [ Whitespace.NL,
                 StmtReturn(_Result.Processed) ])
-        
+
         return lbl, case
 
 
     def genRecvCase(self, md):
         lbl = CaseLabel(md.pqMsgId())
         case = StmtBlock()
 
         stmts = self.deserializeMessage(md, self.side, errfn=errfnRecv)
@@ -5167,17 +5171,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 for r in md.returns ]
             + self.setMessageFlags(md, replyvar, reply=1, routingId=routingId)
             + [ self.logMessage(md, md.replyCast(replyvar), 'Sending reply ') ])
 
 
     def setMessageFlags(self, md, var, reply, routingId=None):
         if routingId is None:
             routingId = self.protocol.routingId()
-        
+
         stmts = [ StmtExpr(ExprCall(
             ExprSelect(var, '->', 'set_routing_id'),
             args=[ routingId ])) ]
 
         if md.decl.type.isSync():
             stmts.append(StmtExpr(ExprCall(
                 ExprSelect(var, '->', 'set_sync'))))
         elif md.decl.type.isRpc():
@@ -5339,17 +5343,17 @@ class _GenerateProtocolActorCode(ipdl.as
     def invokeRecvHandler(self, md, implicit=1):
         failif = StmtIf(ExprNot(
             ExprCall(md.recvMethod(),
                      args=md.makeCxxArgs(params=1,
                                          retsems='in', retcallsems='out',
                                          implicit=implicit))))
         failif.addifstmts([
             _protocolErrorBreakpoint('Handler for '+ md.name +' returned error code'),
-            StmtReturn(_Result.ProcessingError) 
+            StmtReturn(_Result.ProcessingError)
         ])
         return [ failif ]
 
     def makeDtorMethodDecl(self, md):
         decl = self.makeSendMethodDecl(md)
         decl.static = 1
         return decl
 
@@ -5389,17 +5393,17 @@ class _GenerateProtocolActorCode(ipdl.as
                                      self.protocol.routingId()) ]
         else:
             saveIdStmts = [ ]
         return idvar, saveIdStmts
 
     def transition(self, md, direction, actor=None, reply=False):
         if actor is not None:  stateexpr = _actorState(actor)
         else:                  stateexpr = self.protocol.stateVar()
-        
+
         if (self.side is 'parent' and direction is 'out'
             or self.side is 'child' and direction is 'in'):
             action = ExprVar('Trigger::Send')
         elif (self.side is 'parent' and direction is 'in'
             or self.side is 'child' and direction is 'out'):
             action = ExprVar('Trigger::Recv')
         else: assert 0 and 'unknown combo %s/%s'% (self.side, direction)
 
@@ -5532,17 +5536,17 @@ class _GenerateSkeletonImpl(Visitor):
         self.addmethodimpl(impl)
 
     def visitConstructorDecl(self, cd):
         self.cls.addstmt(StmtDecl(ConstructorDecl(self.name)))
         ctor = ConstructorDefn(ConstructorDecl(self.implname(self.name)))
         ctor.addstmt(StmtExpr(ExprCall(ExprVar( 'MOZ_COUNT_CTOR'),
                                                [ ExprVar(self.name) ])))
         self.addmethodimpl(ctor)
-        
+
     def visitDestructorDecl(self, dd):
         self.cls.addstmt(
             StmtDecl(DestructorDecl(self.name, virtual=1)))
         # FIXME/cjones: hack!
         dtor = DestructorDefn(ConstructorDecl(self.implname('~' +self.name)))
         dtor.addstmt(StmtExpr(ExprCall(ExprVar( 'MOZ_COUNT_DTOR'),
                                                [ ExprVar(self.name) ])))
         self.addmethodimpl(dtor)
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -166,17 +166,17 @@ class Base {
     // virtual, and a subclass overrides it, the subclass's destructor will be
     // ignored. Is there a way to make the compiler catch that error?
 
   protected:
     // Space for the actual pointer. Concrete subclasses should define a
     // properly typed 'get' member function to access this.
     void *ptr;
 
-    Base(void *ptr) : ptr(ptr) { }
+    explicit Base(void *ptr) : ptr(ptr) { }
 
   public:
     bool operator==(const Base &rhs) const {
         // Some compilers will indeed place objects of different types at
         // the same address, so technically, we should include the vtable
         // in this comparison. But it seems unlikely to cause problems in
         // practice.
         return ptr == rhs.ptr;
@@ -277,17 +277,17 @@ class Node {
     }
     template<typename T>
     Node &operator=(const Rooted<T *> &root) {
         construct(root.get());
         return *this;
     }
 
     // Constructors accepting SpiderMonkey's other generic-pointer-ish types.
-    Node(JS::Value value);
+    explicit Node(JS::Value value);
     Node(JSGCTraceKind kind, void *ptr);
 
     // copy construction and copy assignment just use memcpy, since we know
     // instances contain nothing but a vtable pointer and a data pointer.
     //
     // To be completely correct, concrete classes could provide a virtual
     // 'construct' member function, which we could invoke on rhs to construct an
     // instance in our storage. But this is good enough; there's no need to jump
@@ -428,17 +428,17 @@ template<typename Referent>
 class TracerConcrete : public Base {
     const jschar *typeName() const MOZ_OVERRIDE { return concreteTypeName; }
     size_t size() const MOZ_OVERRIDE { return 0; } // not implemented yet; bug 1011300
     EdgeRange *edges(JSContext *) const MOZ_OVERRIDE;
     JS::Zone *zone() const MOZ_OVERRIDE { return get().zone(); }
     JSCompartment *compartment() const MOZ_OVERRIDE { return nullptr; }
 
   protected:
-    TracerConcrete(Referent *ptr) : Base(ptr) { }
+    explicit TracerConcrete(Referent *ptr) : Base(ptr) { }
     Referent &get() const { return *static_cast<Referent *>(ptr); }
 
   public:
     static const jschar concreteTypeName[];
     static void construct(void *storage, Referent *ptr) { new (storage) TracerConcrete(ptr); };
 };
 
 // For JS_TraceChildren-based types that have a 'compartment' method.
@@ -471,17 +471,17 @@ template<> struct Concrete<js::types::Ty
 template<>
 class Concrete<void> : public Base {
     const jschar *typeName() const MOZ_OVERRIDE;
     size_t size() const MOZ_OVERRIDE;
     EdgeRange *edges(JSContext *cx) const MOZ_OVERRIDE;
     JS::Zone *zone() const MOZ_OVERRIDE;
     JSCompartment *compartment() const MOZ_OVERRIDE;
 
-    Concrete(void *ptr) : Base(ptr) { }
+    explicit Concrete(void *ptr) : Base(ptr) { }
 
   public:
     static void construct(void *storage, void *ptr) { new (storage) Concrete(ptr); }
     static const jschar concreteTypeName[];
 };
 
 
 } // namespace ubi
--- a/js/public/UbiNodeTraverse.h
+++ b/js/public/UbiNodeTraverse.h
@@ -184,17 +184,17 @@ struct BreadthFirst {
     // A queue template. Appending and popping the front are constant time.
     // Wasted space is never more than some recent actual population plus the
     // current population.
     template <typename T>
     class Queue {
         js::Vector<T, 0> head, tail;
         size_t frontIndex;
       public:
-        Queue(JSContext *cx) : head(cx), tail(cx), frontIndex(0) { }
+        explicit Queue(JSContext *cx) : head(cx), tail(cx), frontIndex(0) { }
         bool empty() { return frontIndex >= head.length(); }
         T &front() {
             MOZ_ASSERT(!empty());
             return head[frontIndex];
         }
         void popFront() {
             MOZ_ASSERT(!empty());
             frontIndex++;
--- a/js/src/asmjs/AsmJSFrameIterator.cpp
+++ b/js/src/asmjs/AsmJSFrameIterator.cpp
@@ -266,19 +266,19 @@ js::GenerateAsmJSFunctionPrologue(MacroA
 
     // Prologue join point, body begin:
     masm.bind(&body);
     masm.setFramePushed(framePushed);
 
     // Overflow checks are omitted by CodeGenerator in some cases (leaf
     // functions with small framePushed). Perform overflow-checking after
     // pushing framePushed to catch cases with really large frames.
-    if (!labels->overflowThunk.empty()) {
+    if (labels->overflowThunk) {
         // If framePushed is zero, we don't need a thunk to adjust StackPointer.
-        Label *target = framePushed ? labels->overflowThunk.addr() : &labels->overflowExit;
+        Label *target = framePushed ? labels->overflowThunk.ptr() : &labels->overflowExit;
         masm.branchPtr(Assembler::AboveOrEqual,
                        AsmJSAbsoluteAddress(AsmJSImm_StackLimit),
                        StackPointer,
                        target);
     }
 }
 
 // Similar to GenerateAsmJSFunctionPrologue (see comment), we generate both a
@@ -325,21 +325,21 @@ js::GenerateAsmJSFunctionEpilogue(MacroA
     masm.addPtr(Imm32(framePushed + AsmJSFrameBytesAfterReturnAddress), StackPointer);
     masm.ret();
     masm.setFramePushed(0);
 
     // Profiling epilogue:
     masm.bind(&labels->profilingEpilogue);
     GenerateProfilingEpilogue(masm, framePushed, AsmJSExit::None, &labels->profilingReturn);
 
-    if (!labels->overflowThunk.empty() && labels->overflowThunk.ref().used()) {
+    if (labels->overflowThunk && labels->overflowThunk->used()) {
         // The general throw stub assumes that only sizeof(AsmJSFrame) bytes
         // have been pushed. The overflow check occurs after incrementing by
         // framePushed, so pop that before jumping to the overflow exit.
-        masm.bind(labels->overflowThunk.addr());
+        masm.bind(labels->overflowThunk.ptr());
         masm.addPtr(Imm32(framePushed), StackPointer);
         masm.jump(&labels->overflowExit);
     }
 }
 
 void
 js::GenerateAsmJSStackOverflowExit(MacroAssembler &masm, Label *overflowExit, Label *throwLabel)
 {
--- a/js/src/asmjs/AsmJSFrameIterator.h
+++ b/js/src/asmjs/AsmJSFrameIterator.h
@@ -135,17 +135,17 @@ class AsmJSProfilingFrameIterator
     // Really, a const AsmJSModule::CodeRange*, but no forward declarations of
     // nested classes, so use void* to avoid pulling in all of AsmJSModule.h.
     const void *codeRange_;
 
     void initFromFP(const AsmJSActivation &activation);
 
   public:
     AsmJSProfilingFrameIterator() : codeRange_(nullptr) {}
-    AsmJSProfilingFrameIterator(const AsmJSActivation &activation);
+    explicit AsmJSProfilingFrameIterator(const AsmJSActivation &activation);
     AsmJSProfilingFrameIterator(const AsmJSActivation &activation,
                                 const JS::ProfilingFrameIterator::RegisterState &state);
     void operator++();
     bool done() const { return !codeRange_; }
 
     void *stackAddress() const { JS_ASSERT(!done()); return stackAddress_; }
     const char *label() const;
 };
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -522,17 +522,17 @@ class AsmJSModule
             RawPointer,
             CodeLabel,
             InstructionImmediate
         };
 
         RelativeLink()
         { }
 
-        RelativeLink(Kind kind)
+        explicit RelativeLink(Kind kind)
         {
 #if defined(JS_CODEGEN_MIPS)
             kind_ = kind;
 #elif defined(JS_CODEGEN_ARM)
             // On ARM, CodeLabels are only used to label raw pointers, so in
             // all cases on ARM, a RelativePatch means patching a raw pointer.
             JS_ASSERT(kind == CodeLabel || kind == RawPointer);
 #endif
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -1954,17 +1954,17 @@ class FunctionCompiler
         return varInitializers_.append(TypedValue(type, init));
     }
 
     bool prepareToEmitMIR(const VarTypeVector &argTypes)
     {
         JS_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
 
         alloc_  = lifo_.new_<TempAllocator>(&lifo_);
-        ionContext_.construct(m_.cx(), alloc_);
+        ionContext_.emplace(m_.cx(), alloc_);
 
         graph_  = lifo_.new_<MIRGraph>(alloc_);
         info_   = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
         const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_AsmJS);
         const JitCompileOptions options;
         mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()),
                                            options, alloc_,
                                            graph_, info_, optimizationInfo);
@@ -1990,25 +1990,25 @@ class FunctionCompiler
         }
         maybeAddInterruptCheck(fn_);
         return true;
     }
 
     /******************************* For consistency of returns in a function */
 
     bool hasAlreadyReturned() const {
-        return !alreadyReturned_.empty();
+        return alreadyReturned_.isSome();
     }
 
     RetType returnedType() const {
-        return alreadyReturned_.ref();
+        return *alreadyReturned_;
     }
 
     void setReturnedType(RetType retType) {
-        alreadyReturned_.construct(retType);
+        alreadyReturned_.emplace(retType);
     }
 
     /************************* Read-only interface (after local scope setup) */
 
     MIRGenerator & mirGen() const     { JS_ASSERT(mirGen_); return *mirGen_; }
     MIRGraph &     mirGraph() const   { JS_ASSERT(graph_); return *graph_; }
     CompileInfo &  info() const       { JS_ASSERT(info_); return *info_; }
 
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -784,18 +784,16 @@ function ArrayMapPar(func, mode) {
     while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
       var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
       var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
       for (var i = indexStart; i < indexEnd; i++)
         UnsafePutElements(buffer, i, func(self[i], i, self));
     }
     return sliceId;
   }
-
-  return undefined;
 }
 
 /**
  * Reduces the elements in an array in parallel. Order is not fixed and |func|
  * is assumed to be associative.
  */
 function ArrayReducePar(func, mode) {
   if (!IsCallable(func))
@@ -840,18 +838,16 @@ function ArrayReducePar(func, mode) {
       var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
       var accumulator = self[indexStart];
       for (var i = indexStart + 1; i < indexEnd; i++)
         accumulator = func(accumulator, self[i]);
       UnsafePutElements(subreductions, sliceId, accumulator);
     }
     return sliceId;
   }
-
-  return undefined;
 }
 
 /**
  * Returns an array [s_0, ..., s_N] where |s_i| is equal to the reduction (as
  * per |reduce()|) of elements |0..i|. This is the generalization of partial
  * sum.
  */
 function ArrayScanPar(func, mode) {
@@ -991,18 +987,16 @@ function ArrayScanPar(func, mode) {
       var indexPos = SLICE_START_INDEX(sliceShift, sliceId);
       var indexEnd = SLICE_END_INDEX(sliceShift, indexPos, length);
       var intermediate = intermediates[sliceId - 1];
       for (; indexPos < indexEnd; indexPos++)
         UnsafePutElements(buffer2, indexPos, func(intermediate, buffer[indexPos]));
     }
     return sliceId;
   }
-
-  return undefined;
 }
 
 /**
  * |scatter()| redistributes the elements in the array into a new array.
  *
  * - targets: The index targets[i] indicates where the ith element
  *   should appear in the result.
  *
@@ -1074,18 +1068,16 @@ function ArrayScatterPar(targets, defaul
       ThrowError(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, i);
 
     if (t < 0 || t >= length)
       ThrowError(JSMSG_PAR_ARRAY_SCATTER_BOUNDS);
 
     // It's not enough to return t, as -0 | 0 === -0.
     return TO_INT32(t);
   }
-
-  return undefined;
 }
 
 /**
  * The filter operation applied in parallel.
  */
 function ArrayFilterPar(func, mode) {
   if (!IsCallable(func))
     ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func));
@@ -1184,18 +1176,16 @@ function ArrayFilterPar(func, mode) {
           if (count == total)
             break;
         }
       }
     }
 
     return sliceId;
   }
-
-  return undefined;
 }
 
 /**
  * "Comprehension form": This is the function invoked for
  * |Array.{build,buildPar}(len, fn)| It creates a new array with length |len|
  * where index |i| is equal to |fn(i)|.
  *
  * The final |mode| argument is an internal argument used only during our
@@ -1246,18 +1236,16 @@ function ArrayStaticBuildPar(length, fun
     while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
       var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
       var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
       for (var i = indexStart; i < indexEnd; i++)
         UnsafePutElements(buffer, i, func(i));
     }
     return sliceId;
   }
-
-  return undefined;
 }
 
 /*
  * Mark the main operations as clone-at-callsite for better precision.
  * This is slightly overkill, as all that we really need is to
  * specialize to the receiver and the elemental function, but in
  * practice this is likely not so different, since element functions
  * are often used in exactly one place.
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -908,19 +908,21 @@ js::IdToStringOrSymbol(JSContext *cx, Ha
     } else if (JSID_IS_ATOM(id)) {
         result.setString(JSID_TO_STRING(id));
     } else {
         result.setSymbol(JSID_TO_SYMBOL(id));
     }
     return true;
 }
 
+namespace js {
+
 /* ES6 draft rev 25 (2014 May 22) 19.1.2.8.1 */
-static bool
-GetOwnPropertyKeys(JSContext *cx, const CallArgs &args, unsigned flags, const char *fnname)
+bool
+GetOwnPropertyKeys(JSContext *cx, const JS::CallArgs &args, unsigned flags)
 {
     // steps 1-2
     RootedObject obj(cx, ToObject(cx, args.get(0)));
     if (!obj)
         return false;
 
     // steps 3-10
     AutoIdVector keys(cx);
@@ -942,32 +944,32 @@ GetOwnPropertyKeys(JSContext *cx, const 
     JSObject *aobj = NewDenseCopiedArray(cx, vals.length(), vals.begin());
     if (!aobj)
         return false;
 
     args.rval().setObject(*aobj);
     return true;
 }
 
+} // namespace js
+
 static bool
 obj_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return GetOwnPropertyKeys(cx, args, JSITER_OWNONLY | JSITER_HIDDEN,
-                              "Object.getOwnPropertyNames");
+    return GetOwnPropertyKeys(cx, args, JSITER_OWNONLY | JSITER_HIDDEN);
 }
 
 /* ES6 draft rev 25 (2014 May 22) 19.1.2.8 */
 static bool
 obj_getOwnPropertySymbols(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return GetOwnPropertyKeys(cx, args,
-                              JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS | JSITER_SYMBOLSONLY,
-                              "Object.getOwnPropertySymbols");
+                              JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS | JSITER_SYMBOLSONLY);
 }
 
 /* ES5 15.2.3.6: Object.defineProperty(O, P, Attributes) */
 static bool
 obj_defineProperty(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx);
--- a/js/src/builtin/Object.h
+++ b/js/src/builtin/Object.h
@@ -4,29 +4,35 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef builtin_Object_h
 #define builtin_Object_h
 
 #include "jsapi.h"
 
-namespace JS { class Value; }
+namespace JS {
+class CallArgs;
+class Value;
+}
 
 namespace js {
 
 extern const JSFunctionSpec object_methods[];
 extern const JSPropertySpec object_properties[];
 extern const JSFunctionSpec object_static_methods[];
 extern const JSFunctionSpec object_static_selfhosted_methods[];
 
 // Object constructor native. Exposed only so the JIT can know its address.
 bool
 obj_construct(JSContext *cx, unsigned argc, JS::Value *vp);
 
+// Exposed so SelfHosting.cpp can use it in the OwnPropertyKeys intrinsic
+bool GetOwnPropertyKeys(JSContext *cx, const JS::CallArgs &args, unsigned flags);
+
 /*
  * Like IdToValue, but convert int jsids to strings. This is used when
  * exposing a jsid to script for Object.getOwnProperty{Names,Symbols}
  * or scriptable proxy traps.
  */
 bool
 IdToStringOrSymbol(JSContext *cx, JS::HandleId id, JS::MutableHandleValue result);
 
--- a/js/src/builtin/Object.js
+++ b/js/src/builtin/Object.js
@@ -14,17 +14,17 @@ function ObjectStaticAssign(target, firs
     // Step 4.
     var i = 1;
     do {
         // Step 5.a-b.
         var nextSource = arguments[i];
         var from = ToObject(nextSource);
 
         // Step 5.c-d.
-        var keysArray = std_Object_getOwnPropertyNames(from);
+        var keysArray = OwnPropertyKeys(from);
 
         // Steps 5.e-f.
         var len = keysArray.length;
 
         // Step 5.h.
         var nextIndex = 0;
 
         // Step 5.i (Modified a bit because we can't catch and store the
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1643,16 +1643,69 @@ DumpObject(JSContext *cx, unsigned argc,
     js_DumpObject(obj);
 
     args.rval().setUndefined();
     return true;
 }
 #endif
 
 static bool
+DumpBacktrace(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    js_DumpBacktrace(cx);
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
+GetBacktrace(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    bool showArgs = false;
+    bool showLocals = false;
+    bool showThisProps = false;
+
+    if (args.length() > 1) {
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Too many arguments");
+        return false;
+    }
+
+    if (args.length() == 1) {
+        RootedObject cfg(cx, ToObject(cx, args[0]));
+        if (!cfg)
+            return false;
+        RootedValue v(cx);
+
+        if (!JS_GetProperty(cx, cfg, "args", &v))
+            return false;
+        showArgs = ToBoolean(v);
+
+        if (!JS_GetProperty(cx, cfg, "locals", &v))
+            return false;
+        showLocals = ToBoolean(v);
+
+        if (!JS_GetProperty(cx, cfg, "thisprops", &v))
+            return false;
+        showThisProps = ToBoolean(v);
+    }
+
+    char *buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
+    RootedString str(cx);
+    if (!(str = JS_NewStringCopyZ(cx, buf)))
+        return false;
+    JS_smprintf_free(buf);
+
+    args.rval().setString(str);
+    return true;
+}
+
+static bool
 ReportOutOfMemory(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ReportOutOfMemory(cx);
     cx->clearPendingException();
     args.rval().setUndefined();
     return true;
 }
@@ -2219,16 +2272,28 @@ static const JSFunctionSpecWithHelp Test
 "dumpObject()",
 "  Dump an internal representation of an object."),
 #endif
 
     JS_FN_HELP("evalReturningScope", EvalReturningScope, 1, 0,
 "evalReturningScope(scriptStr)",
 "  Evaluate the script in a new scope and return the scope."),
 
+    JS_FN_HELP("backtrace", DumpBacktrace, 1, 0,
+"backtrace()",
+"  Dump out a brief backtrace."),
+
+    JS_FN_HELP("getBacktrace", GetBacktrace, 1, 0,
+"getBacktrace([options])",
+"  Return the current stack as a string. Takes an optional options object,\n"
+"  which may contain any or all of the boolean properties\n"
+"    options.args - show arguments to each function\n"
+"    options.locals - show local variables in each frame\n"
+"    options.thisprops - show the properties of the 'this' object of each frame\n"),
+
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -566,17 +566,16 @@ function StorageOfTypedObject(obj) {
 
       return { buffer: TYPEDOBJ_OWNER(obj),
                byteLength: byteLength,
                byteOffset: TYPEDOBJ_BYTEOFFSET(obj) };
     }
   }
 
   ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-  return null; // pacify silly "always returns a value" lint
 }
 
 // This is the `objectType()` function defined in the spec.
 // It returns the type of its argument.
 //
 // Warning: user exposed!
 function TypeOfTypedObject(obj) {
   if (IsObject(obj) && ObjectIsTypedObject(obj))
@@ -612,31 +611,31 @@ function TypedObjectArrayTypeBuild(a,b,c
   var kind = DESCR_KIND(this);
   switch (kind) {
   case JS_TYPEREPR_SIZED_ARRAY_KIND:
     if (typeof a === "function") // XXX here and elsewhere: these type dispatches are fragile at best.
       return BuildTypedSeqImpl(this, this.length, 1, a);
     else if (typeof a === "number" && typeof b === "function")
       return BuildTypedSeqImpl(this, this.length, a, b);
     else if (typeof a === "number")
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
     else
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
     var len = a;
     if (typeof b === "function")
       return BuildTypedSeqImpl(this, len, 1, b);
     else if (typeof b === "number" && typeof c === "function")
       return BuildTypedSeqImpl(this, len, b, c);
     else if (typeof b === "number")
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
     else
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   default:
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   }
 }
 
 // Warning: user exposed!
 function TypedObjectArrayTypeFrom(a, b, c) {
   // Arguments: arrayLike, [depth], func
 
   if (!IsObject(this) || !ObjectIsTypeDescr(this))
@@ -651,44 +650,44 @@ function TypedObjectArrayTypeFrom(a, b, 
 
   if (untypedInput) {
     var explicitDepth = (b === 1);
     if (explicitDepth && IsCallable(c))
       return MapUntypedSeqImpl(a, this, c);
     else if (IsCallable(b))
       return MapUntypedSeqImpl(a, this, b);
     else
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   } else {
     var explicitDepth = (typeof b === "number");
     if (explicitDepth && IsCallable(c))
       return MapTypedSeqImpl(a, b, this, c);
     else if (IsCallable(b))
       return MapTypedSeqImpl(a, 1, this, b);
     else if (explicitDepth)
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
     else
-      return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   }
 }
 
 // Warning: user exposed!
 function TypedArrayMap(a, b) {
   if (!IsObject(this) || !ObjectIsTypedObject(this))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   // Arguments: [depth], func
   if (typeof a === "number" && typeof b === "function")
     return MapTypedSeqImpl(this, a, thisType, b);
   else if (typeof a === "function")
     return MapTypedSeqImpl(this, 1, thisType, a);
-  return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+  ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 }
 
 // Warning: user exposed!
 function TypedArrayMapPar(a, b) {
   // Arguments: [depth], func
 
   // Defer to the sequential variant for error cases or
   // when not working with typed objects.
@@ -704,57 +703,57 @@ function TypedArrayMapPar(a, b) {
     return MapTypedParImpl(this, 1, thisType, a);
   return callFunction(TypedArrayMap, this, a, b);
 }
 
 // Warning: user exposed!
 function TypedArrayReduce(a, b) {
   // Arguments: func, [initial]
   if (!IsObject(this) || !ObjectIsTypedObject(this))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (a !== undefined && typeof a !== "function")
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   var outputType = thisType.elementType;
   return ReduceTypedSeqImpl(this, outputType, a, b);
 }
 
 // Warning: user exposed!
 function TypedArrayScatter(a, b, c, d) {
   // Arguments: outputArrayType, indices, defaultValue, conflictFunction
   if (!IsObject(this) || !ObjectIsTypedObject(this))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsSizedArrayType(a))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (d !== undefined && typeof d !== "function")
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   return ScatterTypedSeqImpl(this, a, b, c, d);
 }
 
 // Warning: user exposed!
 function TypedArrayFilter(func) {
   // Arguments: predicate
   if (!IsObject(this) || !ObjectIsTypedObject(this))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (typeof func !== "function")
-    return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   return FilterTypedSeqImpl(this, func);
 }
 
 // placeholders
 
 // Warning: user exposed!
 function TypedObjectArrayTypeBuildPar(a,b,c) {
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -178,12 +178,11 @@ function ForkJoinMode(mode) {
   } else if (mode.mode === "par") {
     return 2;
   } else if (mode.mode === "recover") {
     return 3;
   } else if (mode.mode === "bailout") {
     return 4;
   }
   ThrowError(JSMSG_PAR_ARRAY_BAD_ARG);
-  return undefined;
 }
 
 #endif
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1643,17 +1643,17 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy"
         CXXFLAGS="$CXXFLAGS -W3 -Gy"
-        if test "$_CC_SUITE" -ge "11"; then
+        if test "$_CC_SUITE" -ge "11" -a "$CPU_ARCH" = "x86"; then
             dnl VS2012+ defaults to -arch:SSE2.
             CFLAGS="$CFLAGS -arch:IA32"
             CXXFLAGS="$CXXFLAGS -arch:IA32"
         fi
         if test "$_CC_SUITE" -ge "12"; then
             dnl VS2013+ requires -FS when parallel building by make -jN.
             dnl If nothing, compiler sometimes causes C1041 error.
             dnl
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -255,25 +255,25 @@ frontend::CompileScript(ExclusiveContext
         else if (!ss->setSourceCopy(cx, srcBuf, false, sct))
             return nullptr;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
-        syntaxParser.construct(cx, alloc, options, srcBuf.get(), srcBuf.length(),
-                               /* foldConstants = */ false,
-                               (Parser<SyntaxParseHandler> *) nullptr,
-                               (LazyScript *) nullptr);
+        syntaxParser.emplace(cx, alloc, options, srcBuf.get(), srcBuf.length(),
+                             /* foldConstants = */ false,
+                             (Parser<SyntaxParseHandler> *) nullptr,
+                             (LazyScript *) nullptr);
     }
 
     Parser<FullParseHandler> parser(cx, alloc, options, srcBuf.get(), srcBuf.length(),
                                     /* foldConstants = */ true,
-                                    canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
+                                    canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr);
     parser.sct = sct;
     parser.ss = ss;
 
     Directives directives(options.strictOption);
     GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption);
 
     bool savedCallerFun = options.compileAndGo &&
                           evalCaller && evalCaller->functionOrCallerFunction();
@@ -296,20 +296,20 @@ frontend::CompileScript(ExclusiveContext
     if (!bce.init())
         return nullptr;
 
     // Syntax parsing may cause us to restart processing of top level
     // statements in the script. Use Maybe<> so that the parse context can be
     // reset when this occurs.
     Maybe<ParseContext<FullParseHandler> > pc;
 
-    pc.construct(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr, &globalsc,
-                 (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
-                 /* blockScopeDepth = */ 0);
-    if (!pc.ref().init(parser.tokenStream))
+    pc.emplace(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr, &globalsc,
+               (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
+               /* blockScopeDepth = */ 0);
+    if (!pc->init(parser.tokenStream))
         return nullptr;
 
     /* If this is a direct call to eval, inherit the caller's strictness.  */
     if (evalCaller && evalCaller->strict())
         globalsc.strict = true;
 
     if (options.compileAndGo) {
         if (source) {
@@ -326,17 +326,17 @@ frontend::CompileScript(ExclusiveContext
         if (evalCaller && evalCaller->functionOrCallerFunction()) {
             /*
              * An eval script in a caller frame needs to have its enclosing
              * function captured in case it refers to an upvar, and someone
              * wishes to decompile it while it's running.
              */
             JSFunction *fun = evalCaller->functionOrCallerFunction();
             Directives directives(/* strict = */ fun->strict());
-            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.addr(),
+            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
                                                       directives, fun->generatorKind());
             if (!funbox)
                 return nullptr;
             bce.objectList.add(funbox);
         }
     }
 
     bool canHaveDirectives = true;
@@ -360,39 +360,39 @@ frontend::CompileScript(ExclusiveContext
                 // level statement. Restart the parse; syntax parsing has
                 // already been disabled for the parser and the result will not
                 // be ambiguous.
                 parser.clearAbortedSyntaxParse();
                 parser.tokenStream.seek(pos);
 
                 // Destroying the parse context will destroy its free
                 // variables, so check if any deoptimization is needed.
-                if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref()))
+                if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, *pc))
                     return nullptr;
 
-                pc.destroy();
-                pc.construct(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr,
-                             &globalsc, (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
-                             script->bindings.numBlockScoped());
-                if (!pc.ref().init(parser.tokenStream))
+                pc.reset();
+                pc.emplace(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr,
+                           &globalsc, (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
+                           script->bindings.numBlockScoped());
+                if (!pc->init(parser.tokenStream))
                     return nullptr;
-                JS_ASSERT(parser.pc == pc.addr());
+                JS_ASSERT(parser.pc == pc.ptr());
 
                 pn = parser.statement();
             }
             if (!pn) {
                 JS_ASSERT(!parser.hadAbortedSyntaxParse());
                 return nullptr;
             }
         }
 
         // Accumulate the maximum block scope depth, so that EmitTree can assert
         // when emitting JSOP_GETLOCAL that the local is indeed within the fixed
         // part of the stack frame.
-        script->bindings.updateNumBlockScoped(pc.ref().blockScopeDepth);
+        script->bindings.updateNumBlockScoped(pc->blockScopeDepth);
 
         if (canHaveDirectives) {
             if (!parser.maybeParseDirective(/* stmtList = */ nullptr, pn, &canHaveDirectives))
                 return nullptr;
         }
 
         if (!FoldConstants(cx, &pn, &parser))
             return nullptr;
@@ -401,17 +401,17 @@ frontend::CompileScript(ExclusiveContext
             return nullptr;
 
         if (!EmitTree(cx, &bce, pn))
             return nullptr;
 
         parser.handler.freeTree(pn);
     }
 
-    if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref()))
+    if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, *pc))
         return nullptr;
 
     if (!SetDisplayURL(cx, parser.tokenStream, ss))
         return nullptr;
 
     if (!SetSourceMap(cx, parser.tokenStream, ss))
         return nullptr;
 
@@ -432,17 +432,17 @@ frontend::CompileScript(ExclusiveContext
         return nullptr;
 
     // Global/eval script bindings are always empty (all names are added to the
     // scope dynamically via JSOP_DEFFUN/VAR).  They may have block-scoped
     // locals, however, which are allocated to the fixed part of the stack
     // frame.
     InternalHandle<Bindings*> bindings(script, &script->bindings);
     if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, nullptr,
-                                            pc.ref().blockScopeDepth))
+                                            pc->blockScopeDepth))
         return nullptr;
 
     if (!JSScript::fullyInitFromEmitter(cx, script, &bce))
         return nullptr;
 
     // Note that this marking must happen before we tell Debugger
     // about the new script, in case Debugger delazifies the script's
     // inner functions.
@@ -550,29 +550,29 @@ CompileFunctionBody(JSContext *cx, Mutab
         if (!ss->setSourceCopy(cx, srcBuf, true, &sct))
             return false;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
-        syntaxParser.construct(cx, &cx->tempLifoAlloc(),
-                               options, srcBuf.get(), srcBuf.length(),
-                               /* foldConstants = */ false,
-                               (Parser<SyntaxParseHandler> *) nullptr,
-                               (LazyScript *) nullptr);
+        syntaxParser.emplace(cx, &cx->tempLifoAlloc(),
+                             options, srcBuf.get(), srcBuf.length(),
+                             /* foldConstants = */ false,
+                             (Parser<SyntaxParseHandler> *) nullptr,
+                             (LazyScript *) nullptr);
     }
 
     JS_ASSERT(!options.forEval);
 
     Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
                                     options, srcBuf.get(), srcBuf.length(),
                                     /* foldConstants = */ true,
-                                    canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
+                                    canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr);
     parser.sct = &sct;
     parser.ss = ss;
 
     JS_ASSERT(fun);
     JS_ASSERT(fun->isTenured());
 
     fun->setArgCount(formals.length());
 
--- a/js/src/gc/ForkJoinNursery.h
+++ b/js/src/gc/ForkJoinNursery.h
@@ -71,17 +71,17 @@ struct ForkJoinNurseryChunk
 };
 
 // A GC adapter to ForkJoinShared, which is a complex class hidden
 // inside ForkJoin.cpp.
 
 class ForkJoinGCShared
 {
   public:
-    ForkJoinGCShared(ForkJoinShared *shared) : shared_(shared) {}
+    explicit ForkJoinGCShared(ForkJoinShared *shared) : shared_(shared) {}
 
     JSRuntime *runtime();
     JS::Zone *zone();
 
     // The updatable object (the ForkJoin result array), or nullptr.
     JSObject *updatable();
 
     // allocateNurseryChunk() returns nullptr on oom.
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -52,17 +52,17 @@ class ChunkPool
     /* Must be called with the GC lock taken. */
     inline Chunk *get(JSRuntime *rt);
 
     /* Must be called either during the GC or with the GC lock taken. */
     inline void put(Chunk *chunk);
 
     class Enum {
       public:
-        Enum(ChunkPool &pool) : pool(pool), chunkp(&pool.emptyChunkListHead) {}
+        explicit Enum(ChunkPool &pool) : pool(pool), chunkp(&pool.emptyChunkListHead) {}
         bool empty() { return !*chunkp; }
         Chunk *front();
         inline void popFront();
         inline void removeAndPopFront();
       private:
         ChunkPool &pool;
         Chunk **chunkp;
     };
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -910,17 +910,17 @@ class HeapUsage
      * ArenaSize. This does not include any malloc data. It also does not
      * include not-actively-used addresses that are still reserved at the OS
      * level for GC usage. It is atomic because it is updated by both the main
      * and GC helper threads.
      */
     mozilla::Atomic<size_t, mozilla::ReleaseAcquire> gcBytes_;
 
   public:
-    HeapUsage(HeapUsage *parent)
+    explicit HeapUsage(HeapUsage *parent)
       : parent_(parent),
         gcBytes_(0)
     {}
 
     size_t gcBytes() const { return gcBytes_; }
 
     void addGCArena() {
         gcBytes_ += ArenaSize;
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -394,47 +394,47 @@ class CompartmentsIterT
     ZonesIterT zone;
     mozilla::Maybe<CompartmentsInZoneIter> comp;
 
   public:
     explicit CompartmentsIterT(JSRuntime *rt)
       : zone(rt)
     {
         if (zone.done())
-            comp.construct();
+            comp.emplace();
         else
-            comp.construct(zone);
+            comp.emplace(zone);
     }
 
     CompartmentsIterT(JSRuntime *rt, ZoneSelector selector)
       : zone(rt, selector)
     {
         if (zone.done())
-            comp.construct();
+            comp.emplace();
         else
-            comp.construct(zone);
+            comp.emplace(zone);
     }
 
     bool done() const { return zone.done(); }
 
     void next() {
         JS_ASSERT(!done());
-        JS_ASSERT(!comp.ref().done());
-        comp.ref().next();
-        if (comp.ref().done()) {
-            comp.destroy();
+        JS_ASSERT(!comp->done());
+        comp->next();
+        if (comp->done()) {
+            comp.reset();
             zone.next();
             if (!zone.done())
-                comp.construct(zone);
+                comp.emplace(zone);
         }
     }
 
     JSCompartment *get() const {
         JS_ASSERT(!done());
-        return comp.ref();
+        return *comp;
     }
 
     operator JSCompartment *() const { return get(); }
     JSCompartment *operator->() const { return get(); }
 };
 
 typedef CompartmentsIterT<ZonesIter> CompartmentsIter;
 
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1656,22 +1656,22 @@ irregexp::CompilePattern(JSContext *cx, 
     Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
 
     RegExpMacroAssembler *assembler;
     if (IsNativeRegExpEnabled(cx)) {
         NativeRegExpMacroAssembler::Mode mode =
             is_ascii ? NativeRegExpMacroAssembler::ASCII
                      : NativeRegExpMacroAssembler::JSCHAR;
 
-        ctx.construct(cx, (jit::TempAllocator *) nullptr);
-        native_assembler.construct(&alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
-        assembler = native_assembler.addr();
+        ctx.emplace(cx, (jit::TempAllocator *) nullptr);
+        native_assembler.emplace(&alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
+        assembler = native_assembler.ptr();
     } else {
-        interpreted_assembler.construct(&alloc, shared, (data->capture_count + 1) * 2);
-        assembler = interpreted_assembler.addr();
+        interpreted_assembler.emplace(&alloc, shared, (data->capture_count + 1) * 2);
+        assembler = interpreted_assembler.ptr();
     }
 
     // Inserted here, instead of in Assembler, because it depends on information
     // in the AST that isn't replicated in the Node structure.
     static const int kMaxBacksearchLimit = 1024;
     if (is_end_anchored &&
         !is_start_anchored &&
         max_length < kMaxBacksearchLimit) {
--- a/js/src/jit-test/lib/asm.js
+++ b/js/src/jit-test/lib/asm.js
@@ -29,17 +29,17 @@ function asmCompileCached()
         var f = Function.apply(null, arguments);
         assertEq(isAsmJSModule(f), true);
         return f;
     }
 
     var quotedArgs = [];
     for (var i = 0; i < arguments.length; i++)
         quotedArgs.push("'" + arguments[i] + "'");
-    var code = "var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
+    var code = "setCachingEnabled(true); var f = new Function(" + quotedArgs.join(',') + ");assertEq(isAsmJSModule(f), true);";
     nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
 
     var f = Function.apply(null, arguments);
     assertEq(isAsmJSModuleLoadedFromCache(f), true);
     return f;
 }
 
 function assertAsmDirectiveFail(str)
--- a/js/src/jit-test/tests/asm.js/testBullet.js
+++ b/js/src/jit-test/tests/asm.js/testBullet.js
@@ -1,18 +1,19 @@
 // Test a big fat asm.js module. First load/compile/cache bullet.js in a
 // separate process and then load it again in this process, which should be a
 // cache hit.
 
+setCachingEnabled(true);
 if (!isAsmJSCompilationAvailable())
     quit();
 
 // Note: if you get some failure in this test, it probably has to do with
 // bullet.js and not the nestedShell() call, so try first commenting out
 // nestedShell() (and the loadedFromCache assertion) to see if the error
 // reproduces.
-var code = "setIonCheckGraphCoherency(false); load('" + libdir + "bullet.js'); runBullet()";
+var code = "setIonCheckGraphCoherency(false); setCachingEnabled(true); load('" + libdir + "bullet.js'); runBullet()";
 nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
 setIonCheckGraphCoherency(false);
 load(libdir + 'bullet.js');
 var results = runBullet();
 assertEq(results.asmJSValidated, true);
 assertEq(results.loadedFromCache, true);
--- a/js/src/jit-test/tests/asm.js/testCaching.js
+++ b/js/src/jit-test/tests/asm.js/testCaching.js
@@ -1,10 +1,11 @@
 load(libdir + "asm.js");
 
+setCachingEnabled(true);
 if (!isAsmJSCompilationAvailable() || !isCachingEnabled())
     quit();
 
 var body1 = "'use asm'; function f() { return 42 } function ff() { return 43 } return f";
 var m = new Function(body1);
 assertEq(isAsmJSModule(m), true);
 assertEq(m()(), 42);
 var m = new Function(body1);
--- a/js/src/jit-test/tests/asm.js/testHeapAccess.js
+++ b/js/src/jit-test/tests/asm.js/testHeapAccess.js
@@ -10,16 +10,18 @@ assertAsmTypeFail('glob', 'imp', 'b', US
 assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>1]|0 }; return f');
 assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>4]|0 }; return f');
 assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0]|0 }; return f'), this, null, new ArrayBuffer(4096))(), 0);
 
 var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f');
 var f = asmLink(code, this, null, new ArrayBuffer(4096));
 assertEq(f(0), 0);
 
+setCachingEnabled(true);
+
 var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
 var f = asmLink(code, this, null, new ArrayBuffer(4096));
 assertEq(f(0),0);
 assertEq(f(0x7f),0x7f);
 assertEq(f(0xff),-1);
 assertEq(f(0x100),0);
 
 // Test signal handlers deactivation
@@ -44,16 +46,18 @@ assertEq(f(0x100),0);
         assertEq(f(0x100),0);
         setJitCompilerOption("signals.enable", 1);
     }
     jco = getJitCompilerOptions();
     var signalHandlersAfter = jco["signals.enable"];
     assertEq(signalHandlersBefore, signalHandlersAfter);
 })();
 
+setCachingEnabled(false);
+
 var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[0]|0}; return f');
 var f = asmLink(code, this, null, new ArrayBuffer(4096));
 assertEq(f(0),0);
 assertEq(f(0x7f),0x7f);
 assertEq(f(0xff),0xff);
 assertEq(f(0x100),0);
 
 var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i16[0]|0}; return f');
--- a/js/src/jit-test/tests/asm.js/testSource.js
+++ b/js/src/jit-test/tests/asm.js/testSource.js
@@ -1,8 +1,10 @@
+setCachingEnabled(true);
+
 (function() {
 /*
  * NO ARGUMENT
  */
 
 function f0() {
     "use asm";
     function g() {}
--- a/js/src/jit-test/tests/asm.js/testStackWalking.js
+++ b/js/src/jit-test/tests/asm.js/testStackWalking.js
@@ -15,16 +15,17 @@ var stack;
 function dumpStack()
 {
     stack = new Error().stack
 }
 
 setJitCompilerOption("ion.usecount.trigger", 10);
 setJitCompilerOption("baseline.usecount.trigger", 0);
 setJitCompilerOption("offthread-compilation.enable", 0);
+setCachingEnabled(true);
 
 var callFFI = asmCompile('global', 'ffis', USE_ASM + "var ffi=ffis.ffi; function f() { return ffi()|0 } return f");
 
 var f = asmLink(callFFI, null, {ffi:dumpStack});
 for (var i = 0; i < 15; i++) {
     stack = null;
     f();
     matchStack(stack, ['dumpStack', 'f']);
--- a/js/src/jit-test/tests/asm.js/testTimeout-deactivate-reactivate-signals.js
+++ b/js/src/jit-test/tests/asm.js/testTimeout-deactivate-reactivate-signals.js
@@ -1,12 +1,14 @@
 // |jit-test| exitstatus: 6;
 
 load(libdir + "asm.js");
 
+setCachingEnabled(true);
+
 var jco = getJitCompilerOptions();
 if (jco["signals.enable"] === 0 || !isCachingEnabled() || !isAsmJSCompilationAvailable())
     quit(6);
 
 // Modules compiled without signal handlers should still work even if signal
 // handlers have been reactivated.
 setJitCompilerOption("signals.enable", 0);
 
--- a/js/src/jit-test/tests/latin1/asm.js
+++ b/js/src/jit-test/tests/latin1/asm.js
@@ -1,10 +1,11 @@
 load(libdir + "asm.js");
 
+setCachingEnabled(true);
 if (!isAsmJSCompilationAvailable() || !isCachingEnabled())
     quit();
 
 // Test Latin1 and TwoByte PropertyName serialization.
 
 // Latin1
 var body1 = "'use asm'; function funName() { return 42 } return funName";
 var m = new Function(body1);
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -128,17 +128,17 @@ struct DebugModeOSREntry
 typedef Vector<DebugModeOSREntry> DebugModeOSREntryVector;
 
 class UniqueScriptOSREntryIter
 {
     const DebugModeOSREntryVector &entries_;
     size_t index_;
 
   public:
-    UniqueScriptOSREntryIter(const DebugModeOSREntryVector &entries)
+    explicit UniqueScriptOSREntryIter(const DebugModeOSREntryVector &entries)
       : entries_(entries),
         index_(0)
     { }
 
     bool done() {
         return index_ == entries_.length();
     }
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3379,35 +3379,35 @@ CodeGenerator::generateBody()
 
         IonSpew(IonSpew_Codegen, "# block%lu%s:", i,
                 current->mir()->isLoopHeader() ? " (loop header)" : "");
 
         masm.bind(current->label());
 
         mozilla::Maybe<ScriptCountBlockState> blockCounts;
         if (counts) {
-            blockCounts.construct(&counts->block(i), &masm);
-            if (!blockCounts.ref().init())
+            blockCounts.emplace(&counts->block(i), &masm);
+            if (!blockCounts->init())
                 return false;
         }
 
 #if defined(JS_ION_PERF)
         perfSpewer->startBasicBlock(current->mir(), masm);
 #endif
 
         for (LInstructionIterator iter = current->begin(); iter != current->end(); iter++) {
             IonSpewStart(IonSpew_Codegen, "instruction %s", iter->opName());
 #ifdef DEBUG
             if (const char *extra = iter->extraName())
                 IonSpewCont(IonSpew_Codegen, ":%s", extra);
 #endif
             IonSpewFin(IonSpew_Codegen);
 
             if (counts)
-                blockCounts.ref().visitInstruction(*iter);
+                blockCounts->visitInstruction(*iter);
 
             if (iter->safepoint() && pushedArgumentSlots_.length()) {
                 if (!markArgumentSlots(iter->safepoint()))
                     return false;
             }
 
 #ifdef CHECK_OSIPOINT_REGISTERS
             if (iter->safepoint())
@@ -4846,20 +4846,20 @@ CodeGenerator::visitIsNullOrLikeUndefine
         Label *notNullOrLikeUndefined;
         if (lir->mir()->operandMightEmulateUndefined()) {
             ool = new(alloc()) OutOfLineTestObjectWithLabels();
             if (!addOutOfLineCode(ool, lir->mir()))
                 return false;
             nullOrLikeUndefined = ool->label1();
             notNullOrLikeUndefined = ool->label2();
         } else {
-            label1.construct();
-            label2.construct();
-            nullOrLikeUndefined = label1.addr();
-            notNullOrLikeUndefined = label2.addr();
+            label1.emplace();
+            label2.emplace();
+            nullOrLikeUndefined = label1.ptr();
+            notNullOrLikeUndefined = label2.ptr();
         }
 
         Register tag = masm.splitTagForTest(value);
 
         masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined);
         masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined);
 
         if (ool) {
@@ -5556,20 +5556,20 @@ CodeGenerator::visitNotV(LNotV *lir)
     // object.
     if (lir->mir()->operandMightEmulateUndefined() && operand->mightBeType(MIRType_Object)) {
         ool = new(alloc()) OutOfLineTestObjectWithLabels();
         if (!addOutOfLineCode(ool, lir->mir()))
             return false;
         ifTruthy = ool->label1();
         ifFalsy = ool->label2();
     } else {
-        ifTruthyLabel.construct();
-        ifFalsyLabel.construct();
-        ifTruthy = ifTruthyLabel.addr();
-        ifFalsy = ifFalsyLabel.addr();
+        ifTruthyLabel.emplace();
+        ifFalsyLabel.emplace();
+        ifTruthy = ifTruthyLabel.ptr();
+        ifFalsy = ifFalsyLabel.ptr();
     }
 
     testValueTruthyKernel(ToValue(lir, LNotV::Input), lir->temp1(), lir->temp2(),
                           ToFloatRegister(lir->tempFloat()),
                           ifTruthy, ifFalsy, ool, operand);
 
     Label join;
     Register output = ToRegister(lir->output());
@@ -6544,17 +6544,17 @@ bool
 CodeGenerator::generateAsmJS(AsmJSFunctionLabels *labels)
 {
     IonSpew(IonSpew_Codegen, "# Emitting asm.js code");
 
     // AsmJS doesn't do SPS instrumentation.
     sps_.disable();
 
     if (!omitOverRecursedCheck())
-        labels->overflowThunk.construct();
+        labels->overflowThunk.emplace();
 
     GenerateAsmJSFunctionPrologue(masm, frameSize(), labels);
 
     if (!generateBody())
         return false;
 
     masm.bind(&returnLabel_);
     GenerateAsmJSFunctionEpilogue(masm, frameSize(), labels);
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -205,17 +205,17 @@ class MacroAssembler : public MacroAssem
     {
         IonContext *icx = GetIonContext();
         JSContext *cx = icx->cx;
         if (cx)
             constructRoot(cx);
 
         if (!icx->temp) {
             JS_ASSERT(cx);
-            alloc_.construct(cx);
+            alloc_.emplace(cx);
         }
 
         moveResolver_.setAllocator(*icx->temp);
 #ifdef JS_CODEGEN_ARM
         initWithAllocator();
         m_buffer.id = icx->getNextAssemblerId();
 #endif
     }
@@ -223,31 +223,31 @@ class MacroAssembler : public MacroAssem
     // This constructor should only be used when there is no IonContext active
     // (for example, Trampoline-$(ARCH).cpp and IonCaches.cpp).
     explicit MacroAssembler(JSContext *cx, IonScript *ion = nullptr,
                             JSScript *script = nullptr, jsbytecode *pc = nullptr)
       : embedsNurseryPointers_(false),
         sps_(nullptr)
     {
         constructRoot(cx);
-        ionContext_.construct(cx, (js::jit::TempAllocator *)nullptr);
-        alloc_.construct(cx);
-        moveResolver_.setAllocator(*ionContext_.ref().temp);
+        ionContext_.emplace(cx, (js::jit::TempAllocator *)nullptr);
+        alloc_.emplace(cx);
+        moveResolver_.setAllocator(*ionContext_->temp);
 #ifdef JS_CODEGEN_ARM
         initWithAllocator();
         m_buffer.id = GetIonContext()->getNextAssemblerId();
 #endif
         if (ion) {
             setFramePushed(ion->frameSize());
             if (pc && cx->runtime()->spsProfiler.enabled()) {
                 // We have to update the SPS pc when this IC stub calls into
                 // the VM.
                 spsPc_ = pc;
-                spsInstrumentation_.construct(&cx->runtime()->spsProfiler, &spsPc_);
-                sps_ = spsInstrumentation_.addr();
+                spsInstrumentation_.emplace(&cx->runtime()->spsProfiler, &spsPc_);
+                sps_ = spsInstrumentation_.ptr();
                 sps_->setPushed(script);
             }
         }
     }
 
     // asm.js compilation handles its own IonContext-pushing
     struct AsmJSToken {};
     explicit MacroAssembler(AsmJSToken)
@@ -266,17 +266,17 @@ class MacroAssembler : public MacroAssem
 
     void resetForNewCodeGenerator(TempAllocator &alloc) {
         setFramePushed(0);
         moveResolver_.clearTempObjectPool();
         moveResolver_.setAllocator(alloc);
     }
 
     void constructRoot(JSContext *cx) {
-        autoRooter_.construct(cx, this);
+        autoRooter_.emplace(cx, this);
     }
 
     MoveResolver &moveResolver() {
         return moveResolver_;
     }
 
     size_t instructionsSize() const {
         return size();
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -3364,17 +3364,17 @@ class LDoubleToString : public LInstruct
 };
 
 // Convert a primitive to a string with a function call.
 class LValueToString : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ValueToString)
 
-    LValueToString(const LDefinition &tempToUnbox)
+    explicit LValueToString(const LDefinition &tempToUnbox)
     {
         setTemp(0, tempToUnbox);
     }
 
     static const size_t Input = 0;
 
     const MToString *mir() {
         return mir_->toToString();
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3839,30 +3839,30 @@ TryAddTypeBarrierForWrite(TempAllocator 
         if (TypeSetIncludes(property.maybeTypes(), (*pvalue)->type(), (*pvalue)->resultTypeSet()))
             return false;
 
         // This freeze is not required for correctness, but ensures that we
         // will recompile if the property types change and the barrier can
         // potentially be removed.
         property.freeze(constraints);
 
-        if (aggregateProperty.empty()) {
-            aggregateProperty.construct(property);
+        if (!aggregateProperty) {
+            aggregateProperty.emplace(property);
         } else {
-            if (!aggregateProperty.ref().maybeTypes()->isSubset(property.maybeTypes()) ||
-                !property.maybeTypes()->isSubset(aggregateProperty.ref().maybeTypes()))
+            if (!aggregateProperty->maybeTypes()->isSubset(property.maybeTypes()) ||
+                !property.maybeTypes()->isSubset(aggregateProperty->maybeTypes()))
             {
                 return false;
             }
         }
     }
 
-    JS_ASSERT(!aggregateProperty.empty());
-
-    MIRType propertyType = aggregateProperty.ref().knownMIRType(constraints);
+    JS_ASSERT(aggregateProperty);
+
+    MIRType propertyType = aggregateProperty->knownMIRType(constraints);
     switch (propertyType) {
       case MIRType_Boolean:
       case MIRType_Int32:
       case MIRType_Double:
       case MIRType_String:
       case MIRType_Symbol: {
         // The property is a particular primitive type, guard by unboxing the
         // value before the write.
@@ -3878,17 +3878,17 @@ TryAddTypeBarrierForWrite(TempAllocator 
         return true;
       }
       default:;
     }
 
     if ((*pvalue)->type() != MIRType_Value)
         return false;
 
-    types::TemporaryTypeSet *types = aggregateProperty.ref().maybeTypes()->clone(alloc.lifoAlloc());
+    types::TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
     if (!types)
         return false;
 
     // If all possible objects can be stored without a barrier, we don't have to
     // guard on the specific object types.
     BarrierKind kind = BarrierKind::TypeSet;
     if ((*pvalue)->resultTypeSet() && (*pvalue)->resultTypeSet()->objectsAreSubset(types))
         kind = BarrierKind::TypeTagOnly;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -2020,17 +2020,17 @@ class MNewPar : public MUnaryInstruction
     }
 };
 
 class MTypedObjectProto
   : public MUnaryInstruction,
     public SingleObjectPolicy
 {
   private:
-    MTypedObjectProto(MDefinition *object)
+    explicit MTypedObjectProto(MDefinition *object)
       : MUnaryInstruction(object)
     {
         setResultType(MIRType_Object);
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(TypedObjectProto)
@@ -2127,17 +2127,17 @@ class MNewDerivedTypedObject
 // Represent the content of all slots of an object.  This instruction is not
 // lowered and is not used to generate code.
 class MObjectState : public MVariadicInstruction
 {
   private:
     uint32_t numSlots_;
     uint32_t numFixedSlots_;
 
-    MObjectState(MDefinition *obj);
+    explicit MObjectState(MDefinition *obj);
 
     bool init(TempAllocator &alloc, MDefinition *obj);
 
     void initSlot(uint32_t slot, MDefinition *def) {
         initOperand(slot + 1, def);
     }
 
   public:
@@ -2683,17 +2683,17 @@ class MApplyArgs
     bool possiblyCalls() const {
         return true;
     }
 };
 
 class MBail : public MNullaryInstruction
 {
   protected:
-    MBail(BailoutKind kind)
+    explicit MBail(BailoutKind kind)
       : MNullaryInstruction()
     {
         bailoutKind_ = kind;
         setGuard();
     }
 
   private:
     BailoutKind bailoutKind_;
@@ -10931,17 +10931,17 @@ class MAsmJSNeg : public MUnaryInstructi
 };
 
 class MAsmJSHeapAccess
 {
     Scalar::Type viewType_;
     bool skipBoundsCheck_;
 
   public:
-    MAsmJSHeapAccess(Scalar::Type vt)
+    explicit MAsmJSHeapAccess(Scalar::Type vt)
       : viewType_(vt), skipBoundsCheck_(false)
     {}
 
     Scalar::Type viewType() const { return viewType_; }
     bool skipBoundsCheck() const { return skipBoundsCheck_; }
     void setSkipBoundsCheck(bool v) { skipBoundsCheck_ = v; }
 };
 
--- a/js/src/jit/TypedObjectPrediction.h
+++ b/js/src/jit/TypedObjectPrediction.h
@@ -145,21 +145,21 @@ class TypedObjectPrediction {
     ///////////////////////////////////////////////////////////////////////////
     // Constructing a prediction. Generally, you start with an empty
     // prediction and invoke addProto() repeatedly.
 
     TypedObjectPrediction() {
         kind_ = Empty;
     }
 
-    TypedObjectPrediction(const TypedProto &proto) {
+    explicit TypedObjectPrediction(const TypedProto &proto) {
         setProto(proto);
     }
 
-    TypedObjectPrediction(const TypeDescr &descr) {
+    explicit TypedObjectPrediction(const TypeDescr &descr) {
         setDescr(descr);
     }
 
     TypedObjectPrediction(const StructTypeDescr &descr, size_t fields) {
         setPrefix(descr, fields);
     }
 
     void addProto(const TypedProto &proto);
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -28,18 +28,18 @@ using mozilla::DebugOnly;
 namespace js {
 namespace jit {
 
 MacroAssembler &
 CodeGeneratorShared::ensureMasm(MacroAssembler *masmArg)
 {
     if (masmArg)
         return *masmArg;
-    maybeMasm_.construct();
-    return maybeMasm_.ref();
+    maybeMasm_.emplace();
+    return *maybeMasm_;
 }
 
 CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masmArg)
   : oolIns(nullptr),
     maybeMasm_(),
     masm(ensureMasm(masmArg)),
     gen(gen),
     graph(*graph),
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1282,17 +1282,17 @@ class MOZ_STACK_CLASS AutoStableStringCh
         const jschar *twoByteChars_;
         const JS::Latin1Char *latin1Chars_;
     };
     enum State { Uninitialized, Latin1, TwoByte };
     State state_;
     bool ownsChars_;
 
   public:
-    AutoStableStringChars(JSContext *cx)
+    explicit AutoStableStringChars(JSContext *cx)
       : s_(cx), state_(Uninitialized), ownsChars_(false)
     {};
     ~AutoStableStringChars();
 
     bool init(JSContext *cx, JSString *s);
 
     /* Like init(), but Latin1 chars are inflated to TwoByte. */
     bool initTwoByte(JSContext *cx, JSString *s);
@@ -1334,17 +1334,17 @@ class MOZ_STACK_CLASS AutoStableStringCh
 
 // Creates a string of the form |ErrorType: ErrorMessage| for a JSErrorReport,
 // which generally matches the toString() behavior of an ErrorObject.
 extern JS_FRIEND_API(JSString *)
 ErrorReportToString(JSContext *cx, JSErrorReport *reportp);
 
 struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
 {
-    ErrorReport(JSContext *cx);
+    explicit ErrorReport(JSContext *cx);
     ~ErrorReport();
 
     bool init(JSContext *cx, JS::HandleValue exn);
 
     JSErrorReport *report()
     {
         return reportp;
     }
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1026,17 +1026,17 @@ GCRuntime::wantBackgroundAllocation() co
 
 class js::gc::AutoMaybeStartBackgroundAllocation
 {
   private:
     JSRuntime *runtime;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   public:
-    AutoMaybeStartBackgroundAllocation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+    explicit AutoMaybeStartBackgroundAllocation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
       : runtime(nullptr)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     void tryToStartBackgroundAllocation(JSRuntime *rt) {
         runtime = rt;
     }
@@ -2232,17 +2232,17 @@ ArenaLists::refillFreeList(ThreadSafeCon
              * return whatever value we get. If we aren't in a ForkJoin
              * session (i.e. we are in a helper thread async with the main
              * thread), we need to first ensure the main thread is not in a GC
              * session.
              */
             mozilla::Maybe<AutoLockHelperThreadState> lock;
             JSRuntime *rt = zone->runtimeFromAnyThread();
             if (rt->exclusiveThreadsPresent()) {
-                lock.construct();
+                lock.emplace();
                 while (rt->isHeapBusy())
                     HelperThreadState().wait(GlobalHelperThreadState::PRODUCER);
             }
 
             void *thing = cx->allocator()->arenas.allocateFromArenaInline(zone, thingKind,
                                                                           maybeStartBackgroundAllocation);
             if (thing)
                 return thing;
@@ -2524,17 +2524,17 @@ GCRuntime::decommitArenasFromAvailableLi
             {
                 /*
                  * If the main thread waits for the decommit to finish, skip
                  * potentially expensive unlock/lock pair on the contested
                  * lock.
                  */
                 Maybe<AutoUnlockGC> maybeUnlock;
                 if (!isHeapBusy())
-                    maybeUnlock.construct(rt);
+                    maybeUnlock.emplace(rt);
                 ok = MarkPagesUnused(aheader->getArena(), ArenaSize);
             }
 
             if (ok) {
                 ++chunk->info.numArenasFree;
                 chunk->decommittedArenas.set(arenaIndex);
             } else {
                 chunk->addArenaToFreeList(rt, aheader);
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -427,17 +427,17 @@ class ArenaList {
         copy(other);
     }
 
     ArenaList &operator=(const ArenaList &other) {
         copy(other);
         return *this;
     }
 
-    ArenaList(const SortedArenaListSegment &segment) {
+    explicit ArenaList(const SortedArenaListSegment &segment) {
         head_ = segment.head;
         cursorp_ = segment.isEmpty() ? &head_ : segment.tailp;
         check();
     }
 
     // This does checking just of |head_| and |cursorp_|.
     void check() const {
 #ifdef DEBUG
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -324,20 +324,20 @@ JO(JSContext *cx, HandleObject obj, Stri
     /* Steps 5-7. */
     Maybe<AutoIdVector> ids;
     const AutoIdVector *props;
     if (scx->replacer && !scx->replacer->isCallable()) {
         JS_ASSERT(JS_IsArrayObject(cx, scx->replacer));
         props = &scx->propertyList;
     } else {
         JS_ASSERT_IF(scx->replacer, scx->propertyList.length() == 0);
-        ids.construct(cx);
-        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, ids.addr()))
+        ids.emplace(cx);
+        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, ids.ptr()))
             return false;
-        props = ids.addr();
+        props = ids.ptr();
     }
 
     /* My kingdom for not-quite-initialized-from-the-start references. */
     const AutoIdVector &propertyList = *props;
 
     /* Steps 8-10, 13. */
     bool wroteMember = false;
     RootedId id(cx);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -49,41 +49,41 @@ js::AutoEnterPolicy::reportErrorIfExcept
 }
 
 #ifdef DEBUG
 void
 js::AutoEnterPolicy::recordEnter(JSContext *cx, HandleObject proxy, HandleId id, Action act)
 {
     if (allowed()) {
         context = cx;
-        enteredProxy.construct(proxy);
-        enteredId.construct(id);
+        enteredProxy.emplace(proxy);
+        enteredId.emplace(id);
         enteredAction = act;
         prev = cx->runtime()->enteredPolicy;
         cx->runtime()->enteredPolicy = this;
     }
 }
 
 void
 js::AutoEnterPolicy::recordLeave()
 {
-    if (!enteredProxy.empty()) {
+    if (enteredProxy) {
         JS_ASSERT(context->runtime()->enteredPolicy == this);
         context->runtime()->enteredPolicy = prev;
     }
 }
 
 JS_FRIEND_API(void)
 js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id,
                         BaseProxyHandler::Action act)
 {
     MOZ_ASSERT(proxy->is<ProxyObject>());
     MOZ_ASSERT(cx->runtime()->enteredPolicy);
-    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy.ref().get() == proxy);
-    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId.ref().get() == id);
+    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy->get() == proxy);
+    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId->get() == id);
     MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredAction & act);
 }
 #endif
 
 BaseProxyHandler::BaseProxyHandler(const void *family, bool hasPrototype, bool hasSecurityPolicy)
   : mFamily(family),
     mHasPrototype(hasPrototype),
     mHasSecurityPolicy(hasSecurityPolicy)
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -42,19 +42,19 @@ JSObject *
 Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, const Wrapper *handler,
              const WrapperOptions *options)
 {
     JS_ASSERT(parent);
 
     RootedValue priv(cx, ObjectValue(*obj));
     mozilla::Maybe<WrapperOptions> opts;
     if (!options) {
-        opts.construct();
-        opts.ref().selectDefaultClass(obj->isCallable());
-        options = opts.addr();
+        opts.emplace();
+        opts->selectDefaultClass(obj->isCallable());
+        options = opts.ptr();
     }
     return NewProxyObject(cx, handler, priv, options->proto(), parent, *options);
 }
 
 JSObject *
 Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, const Wrapper *handler)
 {
     JS_ASSERT(!obj->isCallable());
@@ -147,22 +147,22 @@ js::TransparentObjectWrapper(JSContext *
 {
     // Allow wrapping outer window proxies.
     JS_ASSERT(!obj->is<WrapperObject>() || obj->getClass()->ext.innerObject);
     return Wrapper::New(cx, obj, parent, &CrossCompartmentWrapper::singleton);
 }
 
 ErrorCopier::~ErrorCopier()
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
-    if (ac.ref().origin() != cx->compartment() && cx->isExceptionPending()) {
+    JSContext *cx = ac->context()->asJSContext();
+    if (ac->origin() != cx->compartment() && cx->isExceptionPending()) {
         RootedValue exc(cx);
         if (cx->getPendingException(&exc) && exc.isObject() && exc.toObject().is<ErrorObject>()) {
             cx->clearPendingException();
-            ac.destroy();
+            ac.reset();
             Rooted<ErrorObject*> errObj(cx, &exc.toObject().as<ErrorObject>());
             JSObject *copyobj = js_CopyErrorObject(cx, errObj);
             if (copyobj)
                 cx->setPendingException(ObjectValue(*copyobj));
         }
     }
 }
 
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -25,23 +25,23 @@ class MOZ_STACK_CLASS WrapperOptions : p
   public:
     WrapperOptions() : ProxyOptions(false, nullptr),
                        proto_()
     {}
 
     explicit WrapperOptions(JSContext *cx) : ProxyOptions(false, nullptr),
                                              proto_()
     {
-        proto_.construct(cx);
+        proto_.emplace(cx);
     }
 
     inline JSObject *proto() const;
     WrapperOptions &setProto(JSObject *protoArg) {
-        JS_ASSERT(!proto_.empty());
-        proto_.ref() = protoArg;
+        JS_ASSERT(proto_);
+        *proto_ = protoArg;
         return *this;
     }
 
   private:
     mozilla::Maybe<JS::RootedObject> proto_;
 };
 
 /*
@@ -91,17 +91,17 @@ class JS_FRIEND_API(Wrapper) : public Di
     static const Wrapper singletonWithPrototype;
 
     static JSObject *defaultProto;
 };
 
 inline JSObject *
 WrapperOptions::proto() const
 {
-    return proto_.empty() ? Wrapper::defaultProto : proto_.ref();
+    return proto_ ? *proto_ : Wrapper::defaultProto;
 }
 
 /* Base class for all cross compartment wrapper handlers. */
 class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
 {
   public:
     explicit CrossCompartmentWrapper(unsigned flags, bool hasPrototype = false,
                                      bool hasSecurityPolicy = false);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -125,17 +125,17 @@ static double gTimeoutInterval = -1.0;
 static volatile bool gServiceInterrupt = false;
 static Maybe<JS::PersistentRootedValue> gInterruptFunc;
 
 static bool enableDisassemblyDumps = false;
 
 static bool printTiming = false;
 static const char *jsCacheDir = nullptr;
 static const char *jsCacheAsmJSPath = nullptr;
-static bool jsCachingEnabled = true;
+static bool jsCachingEnabled = false;
 mozilla::Atomic<bool> jsCacheOpened(false);
 
 static bool
 SetTimeoutValue(JSContext *cx, double t);
 
 static bool
 InitWatchdog(JSRuntime *rt);
 
@@ -345,17 +345,17 @@ GetContextData(JSContext *cx)
 
 static bool
 ShellInterruptCallback(JSContext *cx)
 {
     if (!gServiceInterrupt)
         return true;
 
     bool result;
-    RootedValue interruptFunc(cx, gInterruptFunc.ref());
+    RootedValue interruptFunc(cx, *gInterruptFunc);
     if (!interruptFunc.isNull()) {
         JS::AutoSaveExceptionState savedExc(cx);
         JSAutoCompartment ac(cx, &interruptFunc.toObject());
         RootedValue rval(cx);
         if (!JS_CallFunctionValue(cx, JS::NullPtr(), interruptFunc,
                                   JS::HandleValueArray::empty(), &rval))
         {
             return false;
@@ -955,31 +955,31 @@ class AutoNewContext
         JS_ASSERT(!JS_IsExceptionPending(cx));
         oldcx = cx;
         newcx = NewContext(JS_GetRuntime(cx));
         if (!newcx)
             return false;
         JS::ContextOptionsRef(newcx).setDontReportUncaught(true);
         js::SetDefaultObjectForContext(newcx, JS::CurrentGlobalOrNull(cx));
 
-        newRequest.construct(newcx);
-        newCompartment.construct(newcx, JS::CurrentGlobalOrNull(cx));
+        newRequest.emplace(newcx);
+        newCompartment.emplace(newcx, JS::CurrentGlobalOrNull(cx));
         return true;
     }
 
     JSContext *get() { return newcx; }
 
     ~AutoNewContext() {
         if (newcx) {
             RootedValue exc(oldcx);
             bool throwing = JS_IsExceptionPending(newcx);
             if (throwing)
                 JS_GetPendingException(newcx, &exc);
-            newCompartment.destroy();
-            newRequest.destroy();
+            newCompartment.reset();
+            newRequest.reset();
             if (throwing)
                 JS_SetPendingException(oldcx, exc);
             DestroyContext(newcx, false);
         }
     }
 };
 
 static const uint32_t CacheEntry_SOURCE = 0;
@@ -2421,17 +2421,17 @@ Clone(JSContext *cx, unsigned argc, jsva
     }
 
     {
         Maybe<JSAutoCompartment> ac;
         RootedObject obj(cx, args[0].isPrimitive() ? nullptr : &args[0].toObject());
 
         if (obj && obj->is<CrossCompartmentWrapperObject>()) {
             obj = UncheckedUnwrap(obj);
-            ac.construct(cx, obj);
+            ac.emplace(cx, obj);
             args[0].setObject(*obj);
         }
         if (obj && obj->is<JSFunction>()) {
             funobj = obj;
         } else {
             JSFunction *fun = JS_ValueToFunction(cx, args[0]);
             if (!fun)
                 return false;
@@ -2603,17 +2603,17 @@ EvalInContext(JSContext *cx, unsigned ar
 
     DescribeScriptedCaller(cx, &filename, &lineno);
     {
         Maybe<JSAutoCompartment> ac;
         unsigned flags;
         JSObject *unwrapped = UncheckedUnwrap(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
-            ac.construct(cx, sobj);
+            ac.emplace(cx, sobj);
         }
 
         sobj = GetInnerObject(sobj);
         if (!sobj)
             return false;
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportError(cx, "Invalid scope argument to evalcx");
             return false;
@@ -2661,17 +2661,17 @@ EvalInFrame(JSContext *cx, unsigned argc
             break;
     }
 
     AutoSaveFrameChain sfc(cx);
     mozilla::Maybe<AutoCompartment> ac;
     if (saveCurrent) {
         if (!sfc.save())
             return false;
-        ac.construct(cx, DefaultObjectForContextOrNull(cx));
+        ac.emplace(cx, DefaultObjectForContextOrNull(cx));
     }
 
     AutoStableStringChars stableChars(cx);
     if (!stableChars.initTwoByte(cx, str))
         return JSTRAP_ERROR;
 
     AbstractFramePtr frame = fi.abstractFramePtr();
     RootedScript fpscript(cx, frame.script());
@@ -3105,17 +3105,17 @@ ScheduleWatchdog(JSRuntime *rt, double t
 }
 
 static void
 CancelExecution(JSRuntime *rt)
 {
     gServiceInterrupt = true;
     JS_RequestInterruptCallback(rt);
 
-    if (!gInterruptFunc.ref().get().isNull()) {
+    if (!gInterruptFunc->get().isNull()) {
         static const char msg[] = "Script runs for too long, terminating.\n";
         fputs(msg, stderr);
     }
 }
 
 static bool
 SetTimeoutValue(JSContext *cx, double t)
 {
@@ -3152,17 +3152,17 @@ Timeout(JSContext *cx, unsigned argc, Va
         return false;
 
     if (args.length() > 1) {
         RootedValue value(cx, args[1]);
         if (!value.isObject() || !value.toObject().is<JSFunction>()) {
             JS_ReportError(cx, "Second argument must be a timeout function");
             return false;
         }
-        gInterruptFunc.ref() = value;
+        *gInterruptFunc = value;
     }
 
     args.rval().setUndefined();
     return SetTimeoutValue(cx, t);
 }
 
 static bool
 InterruptIf(JSContext *cx, unsigned argc, Value *vp)
@@ -3223,17 +3223,17 @@ SetInterruptCallback(JSContext *cx, unsi
         return false;
     }
 
     RootedValue value(cx, args[0]);
     if (!value.isObject() || !value.toObject().is<JSFunction>()) {
         JS_ReportError(cx, "Argument must be a function");
         return false;
     }
-    gInterruptFunc.ref() = value;
+    *gInterruptFunc = value;
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 StackDump(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -4916,17 +4916,17 @@ my_GetErrorMessage(void *userRef, const 
 
     return &jsShell_ErrorFormatString[errorNumber];
 }
 
 static void
 my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 {
     gGotError = PrintError(cx, gErrFile, message, report, reportWarnings);
-    if (!JSREPORT_IS_WARNING(report->flags)) {
+    if (report->exnType != JSEXN_NONE && !JSREPORT_IS_WARNING(report->flags)) {
         if (report->errorNumber == JSMSG_OUT_OF_MEMORY) {
             gExitCode = EXITCODE_OUT_OF_MEMORY;
         } else {
             gExitCode = EXITCODE_RUNTIME_ERROR;
         }
     }
 }
 
@@ -6208,23 +6208,23 @@ main(int argc, char **argv, char **envp)
     rt = JS_NewRuntime(JS::DefaultHeapMaxBytes, nurseryBytes);
     if (!rt)
         return 1;
 
     JS::SetOutOfMemoryCallback(rt, my_OOMCallback, nullptr);
     if (!SetRuntimeOptions(rt, op))
         return 1;
 
-    gInterruptFunc.construct(rt, NullValue());
+    gInterruptFunc.emplace(rt, NullValue());
 
     JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
 #ifdef JSGC_GENERATIONAL
     Maybe<JS::AutoDisableGenerationalGC> noggc;
     if (op.getBoolOption("no-ggc"))
-        noggc.construct(rt);
+        noggc.emplace(rt);
 #endif
 
     size_t availMem = op.getIntOption("available-memory");
     if (availMem > 0)
         JS_SetGCParametersBasedOnAvailableMemory(rt, availMem);
 
     JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted);
     JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
@@ -6256,23 +6256,22 @@ main(int argc, char **argv, char **envp)
     if (OOM_printAllocationCount)
         printf("OOM max count: %u\n", OOM_counter);
 #endif
 
     DestroyContext(cx, true);
 
     KillWatchdog();
 
-    gInterruptFunc.destroy();
+    gInterruptFunc.reset();
 
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
     for (size_t i = 0; i < workerThreads.length(); i++)
         PR_JoinThread(workerThreads[i]);
 
 #ifdef JSGC_GENERATIONAL
-    if (!noggc.empty())
-        noggc.destroy();
+    noggc.reset();
 #endif
 
     JS_DestroyRuntime(rt);
     JS_ShutDown();
     return result;
 }
--- a/js/src/tests/ecma_6/Object/assign.js
+++ b/js/src/tests/ecma_6/Object/assign.js
@@ -21,16 +21,28 @@ function basicMultipleSources() {
     var b = { bProp : 7 };
     var c = { cProp : 8 };
     Object.assign(a, b, c);
     assertEq(a.bProp, 7);
     assertEq(a.cProp, 8);
 }
 basicMultipleSources();
 
+// Basic functionality works with symbols (Bug 1052358)
+function basicSymbols() {
+    var a = {};
+    var b = { bProp : 7 };
+    var aSymbol = Symbol("aSymbol");
+    b[aSymbol] = 22;
+    Object.assign(a, b);
+    assertEq(a.bProp, 7);
+    assertEq(a[aSymbol], 22);
+}
+basicSymbols();
+
 // Calls ToObject() for target and source
 function testToObject() {
     assertThrowsInstanceOf(() => Object.assign(null, null), TypeError);
     assertThrowsInstanceOf(() => Object.assign(), TypeError);
     assertThrowsInstanceOf(() => Object.assign(null, {}), TypeError);
     assertThrowsInstanceOf(() => Object.assign({}, null), TypeError);
     assertEq(Object.assign(true, {}) instanceof Boolean, true);
     assertEq(Object.assign(1, {}) instanceof Number, true);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -553,17 +553,17 @@ Debugger::slowPathOnLeaveFrame(JSContext
         RootedObject frameobj(cx, *p);
         Debugger *dbg = Debugger::fromChildJSObject(frameobj);
 
         if (dbg->enabled &&
             !frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER).isUndefined()) {
             RootedValue handler(cx, frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER));
 
             Maybe<AutoCompartment> ac;
-            ac.construct(cx, dbg->object);
+            ac.emplace(cx, dbg->object);
 
             RootedValue completion(cx);
             if (!dbg->newCompletionValue(cx, status, value, &completion)) {
                 status = dbg->handleUncaughtException(ac, false);
                 break;
             }
 
             /* Call the onPop handler. */
@@ -829,17 +829,17 @@ Debugger::unwrapPropDescInto(JSContext *
 
     return true;
 }
 
 JSTrapStatus
 Debugger::handleUncaughtExceptionHelper(Maybe<AutoCompartment> &ac,
                                         MutableHandleValue *vp, bool callHook)
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
     if (cx->isExceptionPending()) {
         if (callHook && uncaughtExceptionHook) {
             RootedValue exc(cx);
             if (!cx->getPendingException(&exc))
                 return JSTRAP_ERROR;
             cx->clearPendingException();
             RootedValue fval(cx, ObjectValue(*uncaughtExceptionHook));
             RootedValue rv(cx);
@@ -847,17 +847,17 @@ Debugger::handleUncaughtExceptionHelper(
                 return vp ? parseResumptionValue(ac, true, rv, *vp, false) : JSTRAP_CONTINUE;
         }
 
         if (cx->isExceptionPending()) {
             JS_ReportPendingException(cx);
             cx->clearPendingException();
         }
     }
-    ac.destroy();
+    ac.reset();
     return JSTRAP_ERROR;
 }
 
 JSTrapStatus
 Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, MutableHandleValue vp, bool callHook)
 {
     return handleUncaughtExceptionHelper(ac, &vp, callHook);
 }
@@ -932,43 +932,43 @@ Debugger::newCompletionValue(JSContext *
     return true;
 }
 
 bool
 Debugger::receiveCompletionValue(Maybe<AutoCompartment> &ac, bool ok,
                                  HandleValue val,
                                  MutableHandleValue vp)
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
 
     JSTrapStatus status;
     RootedValue value(cx);
     resultToCompletion(cx, ok, val, &status, &value);
-    ac.destroy();
+    ac.reset();
     return newCompletionValue(cx, status, value, vp);
 }
 
 JSTrapStatus
 Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value &rv, MutableHandleValue vp,
                                bool callHook)
 {
     vp.setUndefined();
     if (!ok)
         return handleUncaughtException(ac, vp, callHook);
     if (rv.isUndefined()) {
-        ac.destroy();
+        ac.reset();
         return JSTRAP_CONTINUE;
     }
     if (rv.isNull()) {
-        ac.destroy();
+        ac.reset();
         return JSTRAP_ERROR;
     }
 
     /* Check that rv is {return: val} or {throw: val}. */
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
     Rooted<JSObject*> obj(cx);
     RootedShape shape(cx);
     RootedId returnId(cx, NameToId(cx->names().return_));
     RootedId throwId(cx, NameToId(cx->names().throw_));
     bool okResumption = rv.isObject();
     if (okResumption) {
         obj = &rv.toObject();
         okResumption = obj->is<JSObject>();
@@ -984,17 +984,17 @@ Debugger::parseResumptionValue(Maybe<Aut
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_RESUMPTION);
         return handleUncaughtException(ac, vp, callHook);
     }
 
     RootedValue v(cx, vp.get());
     if (!NativeGet(cx, obj, obj, shape, &v) || !unwrapDebuggeeValue(cx, &v))
         return handleUncaughtException(ac, &v, callHook);
 
-    ac.destroy();
+    ac.reset();
     if (!cx->compartment()->wrap(cx, &v)) {
         vp.setUndefined();
         return JSTRAP_ERROR;
     }
     vp.set(v);
 
     return shape->propid() == returnId ? JSTRAP_RETURN : JSTRAP_THROW;
 }
@@ -1017,17 +1017,17 @@ CallMethodIfPresent(JSContext *cx, Handl
 JSTrapStatus
 Debugger::fireDebuggerStatement(JSContext *cx, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnDebuggerStatement));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     ScriptFrameIter iter(cx);
 
     RootedValue scriptFrame(cx);
     if (!getScriptFrame(cx, iter, &scriptFrame))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
@@ -1043,17 +1043,17 @@ Debugger::fireExceptionUnwind(JSContext 
     JS_ASSERT(hook->isCallable());
 
     RootedValue exc(cx);
     if (!cx->getPendingException(&exc))
         return JSTRAP_ERROR;
     cx->clearPendingException();
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     JS::AutoValueArray<2> argv(cx);
     argv[0].setUndefined();
     argv[1].set(exc);
 
     ScriptFrameIter iter(cx);
     if (!getScriptFrame(cx, iter, argv[0]) || !wrapDebuggeeValue(cx, argv[1]))
         return handleUncaughtException(ac, false);
@@ -1069,17 +1069,17 @@ Debugger::fireExceptionUnwind(JSContext 
 JSTrapStatus
 Debugger::fireEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnEnterFrame));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     RootedValue scriptFrame(cx);
     if (!getScriptFrame(cx, frame, &scriptFrame))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
     bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, scriptFrame.address(), &rv);
     return parseResumptionValue(ac, ok, rv, vp);
@@ -1088,17 +1088,17 @@ Debugger::fireEnterFrame(JSContext *cx, 
 void
 Debugger::fireNewScript(JSContext *cx, HandleScript script)
 {
     RootedObject hook(cx, getHook(OnNewScript));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     JSObject *dsobj = wrapScript(cx, script);
     if (!dsobj) {
         handleUncaughtException(ac, false);
         return;
     }
 
     RootedValue scriptObject(cx, ObjectValue(*dsobj));
@@ -1243,17 +1243,17 @@ Debugger::onTrap(JSContext *cx, MutableH
          *
          * The other has to do with non-compile-and-go scripts, which have no
          * specific global--until they are executed. Only now do we know which
          * global the script is running against.
          */
         Debugger *dbg = bp->debugger;
         if (dbg->enabled && dbg->debuggees.lookup(scriptGlobal)) {
             Maybe<AutoCompartment> ac;
-            ac.construct(cx, dbg->object);
+            ac.emplace(cx, dbg->object);
 
             RootedValue scriptFrame(cx);
             if (!dbg->getScriptFrame(cx, iter, &scriptFrame))
                 return dbg->handleUncaughtException(ac, false);
             RootedValue rv(cx);
             Rooted<JSObject*> handler(cx, bp->handler);
             bool ok = CallMethodIfPresent(cx, handler, "hit", 1, scriptFrame.address(), &rv);
             JSTrapStatus st = dbg->parseResumptionValue(ac, ok, rv, vp, true);
@@ -1354,17 +1354,17 @@ Debugger::onSingleStep(JSContext *cx, Mu
     PreserveIterValue piv(cx);
 
     /* Call all the onStep handlers we found. */
     for (JSObject **p = frames.begin(); p != frames.end(); p++) {
         RootedObject frame(cx, *p);
         Debugger *dbg = Debugger::fromChildJSObject(frame);
 
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, dbg->object);
+        ac.emplace(cx, dbg->object);
 
         const Value &handler = frame->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER);
         RootedValue rval(cx);
         bool ok = Invoke(cx, ObjectValue(*frame), handler, 0, nullptr, &rval);
         JSTrapStatus st = dbg->parseResumptionValue(ac, ok, rval, vp);
         if (st != JSTRAP_CONTINUE)
             return st;
     }
@@ -1378,17 +1378,17 @@ Debugger::onSingleStep(JSContext *cx, Mu
 JSTrapStatus
 Debugger::fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnNewGlobalObject));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     RootedValue wrappedGlobal(cx, ObjectValue(*global));
     if (!wrapDebuggeeValue(cx, &wrappedGlobal))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
 
     // onNewGlobalObject is infallible, and thus is only allowed to return
@@ -4384,30 +4384,30 @@ CheckThisFrame(JSContext *cx, const Call
     }
 
 #define THIS_FRAME_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter)  \
     THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj);                   \
     Maybe<ScriptFrameIter> maybeIter;                                          \
     {                                                                          \
         AbstractFramePtr f = AbstractFramePtr::FromRaw(thisobj->getPrivate()); \
         if (f.isScriptFrameIterData()) {                                       \
-            maybeIter.construct(*(ScriptFrameIter::Data *)(f.raw()));          \
+            maybeIter.emplace(*(ScriptFrameIter::Data *)(f.raw()));            \
         } else {                                                               \
-            maybeIter.construct(cx, ScriptFrameIter::ALL_CONTEXTS,             \
-                                ScriptFrameIter::GO_THROUGH_SAVED);            \
-            ScriptFrameIter &iter = maybeIter.ref();                           \
+            maybeIter.emplace(cx, ScriptFrameIter::ALL_CONTEXTS,               \
+                              ScriptFrameIter::GO_THROUGH_SAVED);              \
+            ScriptFrameIter &iter = *maybeIter;                                \
             while (iter.isIon() || iter.abstractFramePtr() != f)               \
                 ++iter;                                                        \
             AbstractFramePtr data = iter.copyDataAsAbstractFramePtr();         \
             if (!data)                                                         \
                 return false;                                                  \
             thisobj->setPrivate(data.raw());                                   \
         }                                                                      \
     }                                                                          \
-    ScriptFrameIter &iter = maybeIter.ref()
+    ScriptFrameIter &iter = *maybeIter
 
 #define THIS_FRAME_OWNER(cx, argc, vp, fnname, args, thisobj, frame, dbg)      \
     THIS_FRAME(cx, argc, vp, fnname, args, thisobj, frame);                    \
     Debugger *dbg = Debugger::fromChildJSObject(thisobj)
 
 #define THIS_FRAME_OWNER_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter, dbg) \
     THIS_FRAME_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter);               \
     Debugger *dbg = Debugger::fromChildJSObject(thisobj)
@@ -4896,19 +4896,19 @@ DebuggerGenericEval(JSContext *cx, const
             if (!ToUint32(cx, v, &lineno))
                 return false;
             lineNumber = lineno;
         }
     }
 
     Maybe<AutoCompartment> ac;
     if (iter)
-        ac.construct(cx, iter->scopeChain());
+        ac.emplace(cx, iter->scopeChain());
     else
-        ac.construct(cx, scope);
+        ac.emplace(cx, scope);
 
     RootedValue thisv(cx);
     Rooted<Env *> env(cx);
     if (iter) {
         /* ExecuteInEnv requires 'fp' to have a computed 'this" value. */
         if (!iter->computeThis(cx))
             return false;
         thisv = iter->computedThisValue();
@@ -5393,17 +5393,17 @@ DebuggerObject_getOwnPropertyDescriptor(
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, args.get(0), &id))
         return false;
 
     /* Bug: This can cause the debuggee to run! */
     Rooted<PropertyDescriptor> desc(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
 
         ErrorCopier ec(ac);
         if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
             return false;
     }
 
     if (desc.object()) {
         /* Rewrap the debuggee values in desc for the debugger. */
@@ -5430,17 +5430,17 @@ DebuggerObject_getOwnPropertyDescriptor(
 static bool
 DebuggerObject_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "getOwnPropertyNames", args, obj);
 
     AutoIdVector keys(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         ErrorCopier ec(ac);
         if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &keys))
             return false;
     }
 
     AutoValueVector vals(cx);
     if (!vals.resize(keys.length()))
         return false;
@@ -5483,17 +5483,17 @@ DebuggerObject_defineProperty(JSContext 
 
     if (!dbg->unwrapPropDescInto(cx, obj, desc, &desc))
         return false;
     if (!desc.checkGetter(cx) || !desc.checkSetter(cx))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         if (!cx->compartment()->wrap(cx, &desc))
             return false;
 
         ErrorCopier ec(ac);
         bool dummy;
         if (!DefineProperty(cx, obj, id, desc, true, &dummy))
             return false;
     }
@@ -5524,17 +5524,17 @@ DebuggerObject_defineProperties(JSContex
         if (!dbg->unwrapPropDescInto(cx, obj, descs[i], descs[i]))
             return false;
         if (!descs[i].checkGetter(cx) || !descs[i].checkSetter(cx))
             return false;
     }
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         for (size_t i = 0; i < n; i++) {
             if (!cx->compartment()->wrap(cx, descs[i]))
                 return false;
         }
 
         ErrorCopier ec(ac);
         for (size_t i = 0; i < n; i++) {
             bool dummy;
@@ -5555,17 +5555,17 @@ static bool
 DebuggerObject_deleteProperty(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "deleteProperty", args, obj);
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, args.get(0), &id))
         return false;
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
 
     bool succeeded;
     if (!JSObject::deleteGeneric(cx, obj, id, &succeeded))
         return false;
     args.rval().setBoolean(succeeded);
     return true;
 }
@@ -5573,17 +5573,17 @@ DebuggerObject_deleteProperty(JSContext 
 enum SealHelperOp { Seal, Freeze, PreventExtensions };
 
 static bool
 DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp op, const char *name)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, name, args, obj);
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
     bool ok;
     if (op == Seal) {
         ok = JSObject::seal(cx, obj);
     } else if (op == Freeze) {
         ok = JSObject::freeze(cx, obj);
     } else {
         JS_ASSERT(op == PreventExtensions);
@@ -5622,17 +5622,17 @@ DebuggerObject_preventExtensions(JSConte
 
 static bool
 DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp op,
                               const char *name)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, name, args, obj);
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
     bool r;
     if (op == Seal) {
         if (!JSObject::isSealed(cx, obj, &r))
             return false;
     } else if (op == Freeze) {
         if (!JSObject::isFrozen(cx, obj, &r))
             return false;
@@ -5716,17 +5716,17 @@ ApplyOrCall(JSContext *cx, unsigned argc
             return false;
     }
 
     /*
      * Enter the debuggee compartment and rewrap all input value for that compartment.
      * (Rewrapping always takes place in the destination compartment.)
      */
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     if (!cx->compartment()->wrap(cx, &calleev) || !cx->compartment()->wrap(cx, &thisv))
         return false;
 
     RootedValue arg(cx);
     for (unsigned i = 0; i < callArgc; i++) {
         if (!cx->compartment()->wrap(cx, callArgvRooter.handleAt(i)))
              return false;
     }
@@ -6122,17 +6122,17 @@ DebuggerEnv_getInspectable(JSContext *cx
 static bool
 DebuggerEnv_names(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGENV(cx, argc, vp, "names", args, envobj, env);
 
     AutoIdVector keys(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
         ErrorCopier ec(ac);
         if (!GetPropertyNames(cx, env, JSITER_HIDDEN, &keys))
             return false;
     }
 
     RootedObject arr(cx, NewDenseEmptyArray(cx));
     if (!arr)
         return false;
@@ -6156,17 +6156,17 @@ DebuggerEnv_find(JSContext *cx, unsigned
         return false;
 
     RootedId id(cx);
     if (!ValueToIdentifier(cx, args[0], &id))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
 
         /* This can trigger resolve hooks. */
         ErrorCopier ec(ac);
         RootedShape prop(cx);
         RootedObject pobj(cx);
         for (; env && !prop; env = env->enclosingScope()) {
             if (!JSObject::lookupGeneric(cx, env, id, &pobj, &prop))
                 return false;
@@ -6187,17 +6187,17 @@ DebuggerEnv_getVariable(JSContext *cx, u
 
     RootedId id(cx);
     if (!ValueToIdentifier(cx, args[0], &id))
         return false;
 
     RootedValue v(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
 
         /* This can trigger getters. */
         ErrorCopier ec(ac);
 
         // For DebugScopeObjects, we get sentinel values for optimized out
         // slots and arguments instead of throwing (the default behavior).
         //
         // See wrapDebuggeeValue for how the sentinel values are wrapped.
@@ -6228,17 +6228,17 @@ DebuggerEnv_setVariable(JSContext *cx, u
         return false;
 
     RootedValue v(cx, args[1]);
     if (!dbg->unwrapDebuggeeValue(cx, &v))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
         if (!cx->compartment()->wrap(cx, &v))
             return false;
 
         /* This can trigger setters. */
         ErrorCopier ec(ac);
 
         /* Make sure the environment actually has the specified binding. */
         bool has;
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -418,21 +418,21 @@ GlobalHelperThreadState::ensureInitializ
         return;
 
     threads = js_pod_calloc<HelperThread>(threadCount);
     if (!threads)
         CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
 
     for (size_t i = 0; i < threadCount; i++) {
         HelperThread &helper = threads[i];
-        helper.threadData.construct(static_cast<JSRuntime *>(nullptr));
+        helper.threadData.emplace(static_cast<JSRuntime *>(nullptr));
         helper.thread = PR_CreateThread(PR_USER_THREAD,
                                         HelperThread::ThreadMain, &helper,
                                         PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, HELPER_STACK_SIZE);
-        if (!helper.thread || !helper.threadData.ref().init())
+        if (!helper.thread || !helper.threadData->init())
             CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
     }
 
     resetAsmJSFailureState();
 }
 
 GlobalHelperThreadState::GlobalHelperThreadState()
 {
@@ -808,18 +808,17 @@ HelperThread::destroy()
 
             /* Notify all helpers, to ensure that this thread wakes up. */
             HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
         }
 
         PR_JoinThread(thread);
     }
 
-    if (!threadData.empty())
-        threadData.destroy();
+    threadData.reset();
 }
 
 #ifdef MOZ_NUWA_PROCESS
 extern "C" {
 MFBT_API bool IsNuwaProcess();
 MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
 }
 #endif
@@ -847,17 +846,17 @@ HelperThread::handleAsmJSWorkload()
     JS_ASSERT(HelperThreadState().canStartAsmJSCompile());
     JS_ASSERT(idle());
 
     asmData = HelperThreadState().asmJSWorklist().popCopy();
     bool success = false;
 
     do {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(), asmData->runtime);
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(), asmData->runtime);
 
         jit::IonContext icx(asmData->mir->compartment->runtime(),
                             asmData->mir->compartment,
                             &asmData->mir->alloc());
 
         int64_t before = PRMJ_Now();
 
         if (!OptimizeMIR(asmData->mir))
@@ -917,17 +916,17 @@ HelperThread::handleIonWorkload()
     TraceLogger *logger = TraceLoggerForCurrentThread();
     AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, ionBuilder->script()));
     AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
 
     JSRuntime *rt = ionBuilder->script()->compartment()->runtimeFromAnyThread();
 
     {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(),
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(),
                                               ionBuilder->script()->runtimeFromAnyThread());
         jit::IonContext ictx(jit::CompileRuntime::get(rt),
                              jit::CompileCompartment::get(ionBuilder->script()->compartment()),
                              &ionBuilder->alloc());
         ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
     }
 
     FinishOffThreadIonCompile(ionBuilder);
@@ -993,17 +992,17 @@ js::PauseCurrentHelperThread()
     while (thread->pause)
         HelperThreadState().wait(GlobalHelperThreadState::PAUSE);
 }
 
 void
 ExclusiveContext::setHelperThread(HelperThread *thread)
 {
     helperThread_ = thread;
-    perThreadData = thread->threadData.addr();
+    perThreadData = thread->threadData.ptr();
 }
 
 frontend::CompileError &
 ExclusiveContext::addPendingCompileError()
 {
     frontend::CompileError *error = js_new<frontend::CompileError>();
     if (!error)
         MOZ_CRASH();
@@ -1026,17 +1025,17 @@ HelperThread::handleParseWorkload()
     JS_ASSERT(HelperThreadState().canStartParseTask());
     JS_ASSERT(idle());
 
     parseTask = HelperThreadState().parseWorklist().popCopy();
     parseTask->cx->setHelperThread(this);
 
     {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(),
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(),
                                               parseTask->exclusiveContextGlobal->runtimeFromAnyThread());
         SourceBufferHolder srcBuf(parseTask->chars, parseTask->length,
                                   SourceBufferHolder::NoOwnership);
         parseTask->script = frontend::CompileScript(parseTask->cx, &parseTask->alloc,
                                                     NullPtr(), NullPtr(),
                                                     parseTask->options,
                                                     srcBuf);
     }
@@ -1182,27 +1181,27 @@ HelperThread::handleGCHelperWorkload()
 void
 HelperThread::threadLoop()
 {
     JS_ASSERT(CanUseExtraThreads());
 
     JS::AutoSuppressGCAnalysis nogc;
     AutoLockHelperThreadState lock;
 
-    js::TlsPerThreadData.set(threadData.addr());
+    js::TlsPerThreadData.set(threadData.ptr());
 
     // Compute the thread's stack limit, for over-recursed checks.
     uintptr_t stackLimit = GetNativeStackBase();
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackLimit += HELPER_STACK_QUOTA;
 #else
     stackLimit -= HELPER_STACK_QUOTA;
 #endif
-    for (size_t i = 0; i < ArrayLength(threadData.ref().nativeStackLimit); i++)
-        threadData.ref().nativeStackLimit[i] = stackLimit;
+    for (size_t i = 0; i < ArrayLength(threadData->nativeStackLimit); i++)
+        threadData->nativeStackLimit[i] = stackLimit;
 
     while (true) {
         JS_ASSERT(idle());
 
         // Block until a task is available. Save the value of whether we are
         // going to do an Ion compile, in case the value returned by the method
         // changes.
         bool ionCompile = false;
--- a/js/src/vm/ProxyObject.cpp
+++ b/js/src/vm/ProxyObject.cpp
@@ -37,21 +37,19 @@ ProxyObject::New(JSContext *cx, const Ba
         RootedObject protoObj(cx, proto.toObject());
         if (!JSObject::setNewTypeUnknown(cx, clasp, protoObj))
             return nullptr;
     }
 
     NewObjectKind newKind = options.singleton() ? SingletonObject : GenericObject;
     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
 
-#if 0
-    // Background finalization of proxies temporarily disabled. See bug 1008791
     if (handler->finalizeInBackground(priv))
         allocKind = GetBackgroundAllocKind(allocKind);
-#endif
+
     RootedObject obj(cx, NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind));
     if (!obj)
         return nullptr;
 
     Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
     proxy->initHandler(handler);
     proxy->initCrossCompartmentPrivate(priv);
 
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -299,21 +299,21 @@ RegExpObject::createNoStatics(ExclusiveC
 
 RegExpObject *
 RegExpObject::createNoStatics(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags,
                               TokenStream *tokenStream, LifoAlloc &alloc)
 {
     Maybe<CompileOptions> dummyOptions;
     Maybe<TokenStream> dummyTokenStream;
     if (!tokenStream) {
-        dummyOptions.construct(cx->asJSContext());
-        dummyTokenStream.construct(cx, dummyOptions.ref(),
+        dummyOptions.emplace(cx->asJSContext());
+        dummyTokenStream.emplace(cx, *dummyOptions,
                                    (const jschar *) nullptr, 0,
                                    (frontend::StrictModeGetter *) nullptr);
-        tokenStream = dummyTokenStream.addr();
+        tokenStream = dummyTokenStream.ptr();
     }
 
     if (!irregexp::ParsePatternSyntax(*tokenStream, alloc, source))
         return nullptr;
 
     RegExpObjectBuilder builder(cx);
     return builder.build(source, flags);
 }
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1276,17 +1276,17 @@ struct JSRuntime : public JS::shadow::Ru
   private:
     static mozilla::Atomic<size_t> liveRuntimesCount;
 
   public:
     static bool hasLiveRuntimes() {
         return liveRuntimesCount > 0;
     }
 
-    JSRuntime(JSRuntime *parentRuntime);
+    explicit JSRuntime(JSRuntime *parentRuntime);
     ~JSRuntime();
 
     bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
 
     JSRuntime *thisFromCtor() { return this; }
 
     /*
      * Call this after allocating memory held by GC things, to update memory
@@ -1678,17 +1678,17 @@ class RuntimeAllocPolicy
 
 extern const JSSecurityCallbacks NullSecurityCallbacks;
 
 // Debugging RAII class which marks the current thread as performing an Ion
 // compilation, for use by CurrentThreadCan{Read,Write}CompilationData
 class AutoEnterIonCompilation
 {
   public:
-    AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
+    explicit AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
 #ifdef DEBUG
         PerThreadData *pt = js::TlsPerThreadData.get();
         JS_ASSERT(!pt->ionCompiling);
         pt->ionCompiling = true;
 #endif
     }
--- a/js/src/vm/SavedStacks.h
+++ b/js/src/vm/SavedStacks.h
@@ -150,17 +150,17 @@ class SavedStacks {
         PreBarrieredAtom source;
         size_t           line;
         uint32_t         column;
     };
 
     class MOZ_STACK_CLASS AutoLocationValueRooter : public JS::CustomAutoRooter
     {
       public:
-        AutoLocationValueRooter(JSContext *cx)
+        explicit AutoLocationValueRooter(JSContext *cx)
             : JS::CustomAutoRooter(cx),
               value() {}
 
         inline LocationValue *operator->() { return &value; }
         void set(LocationValue &loc) { value = loc; }
         LocationValue &get() { return value; }
 
       private:
@@ -203,31 +203,31 @@ class SavedStacks {
     PCLocationMap pcLocationMap;
 
     void sweepPCLocationMap();
     bool getLocation(JSContext *cx, const FrameIter &iter, MutableHandleLocationValue locationp);
 
     struct FrameState
     {
         FrameState() : principals(nullptr), name(nullptr), location() { }
-        FrameState(const FrameIter &iter);
+        explicit FrameState(const FrameIter &iter);
         FrameState(const FrameState &fs);
 
         ~FrameState();
 
         void trace(JSTracer *trc);
 
         JSPrincipals  *principals;
         JSAtom        *name;
         LocationValue location;
     };
 
     class MOZ_STACK_CLASS AutoFrameStateVector : public JS::CustomAutoRooter {
       public:
-        AutoFrameStateVector(JSContext *cx)
+        explicit AutoFrameStateVector(JSContext *cx)
           : JS::CustomAutoRooter(cx),
             frames(cx)
         { }
 
         typedef Vector<FrameState> FrameStateVector;
         inline FrameStateVector *operator->() { return &frames; }
         inline FrameState &operator[](size_t i) { return frames[i]; }
 
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -10,16 +10,17 @@
 #include "jscompartment.h"
 #include "jsfriendapi.h"
 #include "jshashutil.h"
 #include "jsobj.h"
 #include "jswrapper.h"
 #include "selfhosted.out.h"
 
 #include "builtin/Intl.h"
+#include "builtin/Object.h"
 #include "builtin/SelfHostingDefines.h"
 #include "builtin/TypedObject.h"
 #include "gc/Marking.h"
 #include "vm/Compression.h"
 #include "vm/ForkJoin.h"
 #include "vm/Interpreter.h"
 #include "vm/String.h"
 
@@ -107,16 +108,24 @@ js::intrinsic_IsCallable(JSContext *cx, 
 static bool
 intrinsic_IsConstructor(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setBoolean(IsConstructor(args[0]));
     return true;
 }
 
+static bool
+intrinsic_OwnPropertyKeys(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return GetOwnPropertyKeys(cx, args,
+                              JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
+}
+
 bool
 js::intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() >= 1);
     uint32_t errorNumber = args[0].toInt32();
 
 #ifdef DEBUG
@@ -771,16 +780,17 @@ intrinsic_RuntimeDefaultLocale(JSContext
 
 static const JSFunctionSpec intrinsic_functions[] = {
     JS_FN("ToObject",                intrinsic_ToObject,                1,0),
     JS_FN("IsObject",                intrinsic_IsObject,                1,0),
     JS_FN("ToInteger",               intrinsic_ToInteger,               1,0),
     JS_FN("ToString",                intrinsic_ToString,                1,0),
     JS_FN("IsCallable",              intrinsic_IsCallable,              1,0),
     JS_FN("IsConstructor",           intrinsic_IsConstructor,           1,0),
+    JS_FN("OwnPropertyKeys",         intrinsic_OwnPropertyKeys,         1,0),
     JS_FN("ThrowError",              intrinsic_ThrowError,              4,0),
     JS_FN("AssertionFailed",         intrinsic_AssertionFailed,         1,0),
     JS_FN("SetScriptHints",          intrinsic_SetScriptHints,          2,0),
     JS_FN("MakeConstructible",       intrinsic_MakeConstructible,       1,0),
     JS_FN("DecompileArg",            intrinsic_DecompileArg,            2,0),
     JS_FN("RuntimeDefaultLocale",    intrinsic_RuntimeDefaultLocale,    0,0),
 
     JS_FN("UnsafePutElements",       intrinsic_UnsafePutElements,       3,0),
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -197,17 +197,17 @@ AutoRooterGetterSetter::Inner::Inner(Thr
 }
 
 inline
 AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
                                                PropertyOp *pgetter, StrictPropertyOp *psetter
                                                MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
 {
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
-        inner.construct(cx, attrs, pgetter, psetter);
+        inner.emplace(cx, attrs, pgetter, psetter);
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 }
 
 static inline uint8_t
 GetShapeAttributes(JSObject *obj, Shape *shape)
 {
     JS_ASSERT(obj->isNative());
 
--- a/js/src/vm/UbiNode.cpp
+++ b/js/src/vm/UbiNode.cpp
@@ -182,17 +182,17 @@ class SimpleEdgeRange : public EdgeRange
     SimpleEdgeVector edges;
     size_t i;
 
     void settle() {
         front_ = i < edges.length() ? &edges[i] : nullptr;
     }
 
   public:
-    SimpleEdgeRange(JSContext *cx) : edges(cx), i(0) { }
+    explicit SimpleEdgeRange(JSContext *cx) : edges(cx), i(0) { }
 
     bool init(JSContext *cx, void *thing, JSGCTraceKind kind) {
         SimpleEdgeVectorTracer tracer(cx, &edges);
         JS_TraceChildren(&tracer, thing, kind);
         settle();
         return tracer.okay;
     }
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -336,21 +336,21 @@ class MOZ_STACK_CLASS ComponentLoaderInf
     }
 
     nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
     nsresult EnsureResolvedURI() {
         BEGIN_ENSURE(ResolvedURI, ScriptChannel);
         return mScriptChannel->GetURI(getter_AddRefs(mResolvedURI));
     }
 
-    nsAutoCString& Key() { return mKey.ref(); }
+    nsAutoCString& Key() { return *mKey; }
     nsresult EnsureKey() {
         ENSURE_DEPS(ResolvedURI);
-        mKey.construct();
-        return mResolvedURI->GetSpec(mKey.ref());
+        mKey.emplace();
+        return mResolvedURI->GetSpec(*mKey);
     }
 
   private:
     const nsACString& mLocation;
     nsCOMPtr<nsIIOService> mIOService;
     nsCOMPtr<nsIURI> mURI;
     nsCOMPtr<nsIChannel> mScriptChannel;
     nsCOMPtr<nsIURI> mResolvedURI;
@@ -1108,17 +1108,17 @@ mozJSComponentLoader::Import(const nsACS
         }
     } else {
         nsresult rv = FindTargetObject(cx, &targetObject);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     Maybe<JSAutoCompartment> ac;
     if (targetObject) {
-        ac.construct(cx, targetObject);
+        ac.emplace(cx, targetObject);
     }
 
     RootedObject global(cx);
     nsresult rv = ImportInto(registryLocation, targetObject, cx, &global);
 
     if (global) {
         if (!JS_WrapObject(cx, &global)) {
             NS_ERROR("can't wrap return value");
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -180,17 +180,17 @@ StackScopedClone(JSContext *cx, StackSco
 {
     JSAutoStructuredCloneBuffer buffer;
     StackScopedCloneData data(cx, &options);
     {
         // For parsing val we have to enter its compartment.
         // (unless it's a primitive)
         Maybe<JSAutoCompartment> ac;
         if (val.isObject()) {
-            ac.construct(cx, &val.toObject());
+            ac.emplace(cx, &val.toObject());
         } else if (val.isString() && !JS_WrapValue(cx, val)) {
             return false;
         }
 
         if (!buffer.write(cx, val, &gStackScopedCloneCallbacks, &data))
             return false;
     }
 
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3186,17 +3186,17 @@ nsXPCComponents_Utils::Dispatch(HandleVa
 {
     RootedValue runnable(cx, runnableArg);
     // Enter the given compartment, if any, and rewrap runnable.
     Maybe<JSAutoCompartment> ac;
     if (scope.isObject()) {
         JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
         if (!scopeObj)
             return NS_ERROR_FAILURE;
-        ac.construct(cx, scopeObj);
+        ac.emplace(cx, scopeObj);
         if (!JS_WrapValue(cx, &runnable))
             return NS_ERROR_FAILURE;
     }
 
     // Get an XPCWrappedJS for |runnable|.
     if (!runnable.isObject())
         return NS_ERROR_INVALID_ARG;
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1182,17 +1182,17 @@ class WatchdogManager : public nsIObserv
     // the lock in each case).
     void
     RecordRuntimeActivity(bool active)
     {
         // The watchdog reads this state, so acquire the lock before writing it.
         MOZ_ASSERT(NS_IsMainThread());
         Maybe<AutoLockWatchdog> lock;
         if (mWatchdog)
-            lock.construct(mWatchdog);
+            lock.emplace(mWatchdog);
 
         // Write state.
         mTimestamps[TimestampRuntimeStateChange] = PR_Now();
         mRuntimeState = active ? RUNTIME_ACTIVE : RUNTIME_INACTIVE;
 
         // The watchdog may be hibernating, waiting for the runtime to go
         // active. Wake it up if necessary.
         if (active && mWatchdog && mWatchdog->Hibernating())
@@ -1206,25 +1206,25 @@ class WatchdogManager : public nsIObserv
 
     // Note - Because of the runtime activity timestamp, these are read and
     // written from both threads.
     void RecordTimestamp(WatchdogTimestampCategory aCategory)
     {
         // The watchdog thread always holds the lock when it runs.
         Maybe<AutoLockWatchdog> maybeLock;
         if (NS_IsMainThread() && mWatchdog)
-            maybeLock.construct(mWatchdog);
+            maybeLock.emplace(mWatchdog);
         mTimestamps[aCategory] = PR_Now();
     }
     PRTime GetTimestamp(WatchdogTimestampCategory aCategory)
     {
         // The watchdog thread always holds the lock when it runs.
         Maybe<AutoLockWatchdog> maybeLock;
         if (NS_IsMainThread() && mWatchdog)
-            maybeLock.construct(mWatchdog);
+            maybeLock.emplace(mWatchdog);
         return mTimestamps[aCategory];
     }
 
     XPCJSRuntime* Runtime() { return mRuntime; }
     Watchdog* GetWatchdog() { return mWatchdog; }
 
     void RefreshWatchdog()
     {
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -643,18 +643,18 @@ File(JSContext *cx, unsigned argc, Value
   return true;
 }
 
 static Maybe<PersistentRootedValue> sScriptedInterruptCallback;
 
 static bool
 XPCShellInterruptCallback(JSContext *cx)
 {
-    MOZ_ASSERT(!sScriptedInterruptCallback.empty());
-    RootedValue callback(cx, sScriptedInterruptCallback.ref());
+    MOZ_ASSERT(sScriptedInterruptCallback);
+    RootedValue callback(cx, *sScriptedInterruptCallback);
 
     // If no interrupt callback was set by script, no-op.
     if (callback.isUndefined())
         return true;
 
     JSAutoCompartment ac(cx, &callback.toObject());
     RootedValue rv(cx);
     if (!JS_CallFunctionValue(cx, JS::NullPtr(), callback, JS::HandleValueArray::empty(), &rv) ||
@@ -666,38 +666,38 @@ XPCShellInterruptCallback(JSContext *cx)
     }
 
     return rv.toBoolean();
 }
 
 static bool
 SetInterruptCallback(JSContext *cx, unsigned argc, jsval *vp)
 {
-    MOZ_ASSERT(!sScriptedInterruptCallback.empty());
+    MOZ_ASSERT(sScriptedInterruptCallback);
 
     // Sanity-check args.
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         JS_ReportError(cx, "Wrong number of arguments");
         return false;
     }
 
     // Allow callers to remove the interrupt callback by passing undefined.
     if (args[0].isUndefined()) {
-        sScriptedInterruptCallback.ref() = UndefinedValue();
+        *sScriptedInterruptCallback = UndefinedValue();
         return true;
     }
 
     // Otherwise, we should have a callable object.
     if (!args[0].isObject() || !JS_ObjectIsCallable(cx, &args[0].toObject())) {
         JS_ReportError(cx, "Argument must be callable");
         return false;
     }
 
-    sScriptedInterruptCallback.ref() = args[0];
+    *sScriptedInterruptCallback = args[0];
 
     return true;
 }
 
 static bool
 SimulateActivityCallback(JSContext *cx, unsigned argc, jsval *vp)
 {
     // Sanity-check args.
@@ -1454,17 +1454,17 @@ XRE_XPCShellMain(int argc, char **argv, 
             return 1;
         }
 
         rtsvc->RegisterContextCallback(ContextCallback);
 
         // Override the default XPConnect interrupt callback. We could store the
         // old one and restore it before shutting down, but there's not really a
         // reason to bother.
-        sScriptedInterruptCallback.construct(rt, UndefinedValue());
+        sScriptedInterruptCallback.emplace(rt, UndefinedValue());
         JS_SetInterruptCallback(rt, XPCShellInterruptCallback);
 
         dom::AutoJSAPI jsapi;
         jsapi.Init();
         cx = jsapi.cx();
 
         argc--;
         argv++;
@@ -1585,17 +1585,17 @@ XRE_XPCShellMain(int argc, char **argv, 
 
     if (!XRE_ShutdownTestShell())
         NS_ERROR("problem shutting down testshell");
 
     // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
     rv = NS_ShutdownXPCOM( nullptr );
     MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
 
-    sScriptedInterruptCallback.destroyIfConstructed();
+    sScriptedInterruptCallback.reset();
 
 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
     // test of late call and release (see above)
     JSContext* bogusCX;
     bogus->Peek(&bogusCX);
     bogus = nullptr;
 #endif
 
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -41,34 +41,34 @@ bool AutoScriptEvaluate::StartEvaluating
 
     mEvaluated = true;
     if (!JS_GetErrorReporter(mJSContext)) {
         JS_SetErrorReporter(mJSContext, errorReporter);
         mErrorReporterSet = true;
     }
 
     JS_BeginRequest(mJSContext);
-    mAutoCompartment.construct(mJSContext, scope);
+    mAutoCompartment.emplace(mJSContext, scope);
 
     // Saving the exception state keeps us from interfering with another script
     // that may also be running on this context.  This occurred first with the
     // js debugger, as described in
     // http://bugzilla.mozilla.org/show_bug.cgi?id=88130 but presumably could
     // show up in any situation where a script calls into a wrapped js component
     // on the same context, while the context has a nonzero exception state.
-    mState.construct(mJSContext);
+    mState.emplace(mJSContext);
 
     return true;
 }
 
 AutoScriptEvaluate::~AutoScriptEvaluate()
 {
     if (!mJSContext || !mEvaluated)
         return;
-    mState.ref().restore();
+    mState->restore();
 
     JS_EndRequest(mJSContext);
 
     if (mErrorReporterSet)
         JS_SetErrorReporter(mJSContext, nullptr);
 }
 
 // It turns out that some errors may be not worth reporting. So, this
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -361,17 +361,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
                                                           parent, parent.address());
         if (NS_FAILED(rv))
             return rv;
         rv = NS_OK;
 
         MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(parent),
                    "Xray wrapper being used to parent XPCWrappedNative?");
 
-        ac.construct(static_cast<JSContext*>(cx), parent);
+        ac.emplace(static_cast<JSContext*>(cx), parent);
 
         if (parent != plannedParent) {
             XPCWrappedNativeScope* betterScope = ObjectScope(parent);
             if (betterScope != Scope)
                 return GetNewOrUsed(helper, betterScope, Interface, resultWrapper);
 
             newParentVal = OBJECT_TO_JSVAL(parent);
         }
@@ -392,17 +392,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
             if (wrapper->FindTearOff(Interface, false, &rv)) {
                 MOZ_ASSERT(NS_FAILED(rv), "returning NS_OK on failure");
                 return rv;
             }
             wrapper.forget(resultWrapper);
             return NS_OK;
         }
     } else {
-        ac.construct(static_cast<JSContext*>(cx), parent);
+        ac.emplace(static_cast<JSContext*>(cx), parent);
     }
 
     AutoMarkingWrappedNativeProtoPtr proto(cx);
 
     // If there is ClassInfo (and we are not building a wrapper for the
     // nsIClassInfo interface) then we use a wrapper that needs a prototype.
 
     // Note that the security check happens inside FindTearOff - after the
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -34,40 +34,31 @@ AutoCxPusher::AutoCxPusher(JSContext* cx
 #ifdef DEBUG
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
 
   // Enter a request and a compartment for the duration that the cx is on the
   // stack if non-null.
   if (cx) {
-    mAutoRequest.construct(cx);
+    mAutoRequest.emplace(cx);
 
     // DOM JSContexts don't store their default compartment object on the cx.
     JSObject *compartmentObject = mScx ? mScx->GetWindowProxy()
                                        : js::DefaultObjectForContextOrNull(cx);
     if (compartmentObject)
-      mAutoCompartment.construct(cx, compartmentObject);
+      mAutoCompartment.emplace(cx, compartmentObject);
   }
 }
 
 AutoCxPusher::~AutoCxPusher()
 {
-  // GC when we pop a script entry point. This is a useful heuristic that helps
-  // us out on certain (flawed) benchmarks like sunspider, because it lets us
-  // avoid GCing during the timing loop.
-  //
-  // NB: We need to take care to only do this if we're in a compartment,
-  // otherwise JS_MaybeGC will segfault.
-  if (mScx && !mAutoCompartment.empty())
-    JS_MaybeGC(nsXPConnect::XPConnect()->GetCurrentJSContext());
-
   // Leave the compartment and request before popping.
-  mAutoCompartment.destroyIfConstructed();
-  mAutoRequest.destroyIfConstructed();
+  mAutoCompartment.reset();
+  mAutoRequest.reset();
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
                                 js::GetEnterCompartmentDepth(mPushedContext));
@@ -107,68 +98,68 @@ AutoJSContext::Init(bool aSafe MOZ_GUARD
 
   nsXPConnect *xpc = nsXPConnect::XPConnect();
   if (!aSafe) {
     mCx = xpc->GetCurrentJSContext();
   }
 
   if (!mCx) {
     mCx = xpc->GetSafeJSContext();
-    mPusher.construct(mCx);
+    mPusher.emplace(mCx);
   }
 }
 
 AutoJSContext::operator JSContext*() const
 {
   return mCx;
 }
 
 ThreadsafeAutoJSContext::ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
   if (NS_IsMainThread()) {
     mCx = nullptr;
-    mAutoJSContext.construct();
+    mAutoJSContext.emplace();
   } else {
     mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
-    mRequest.construct(mCx);
+    mRequest.emplace(mCx);
   }
 }
 
 ThreadsafeAutoJSContext::operator JSContext*() const
 {
   if (mCx) {
     return mCx;
   } else {
-    return mAutoJSContext.ref();
+    return *mAutoJSContext;
   }
 }
 
 AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
   : AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
   , mAc(mCx, XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContextGlobal())
 {
 }
 
 ThreadsafeAutoSafeJSContext::ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
   if (NS_IsMainThread()) {
     mCx = nullptr;
-    mAutoSafeJSContext.construct();
+    mAutoSafeJSContext.emplace();
   } else {
     mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
-    mRequest.construct(mCx);
+    mRequest.emplace(mCx);
   }
 }
 
 ThreadsafeAutoSafeJSContext::operator JSContext*() const
 {
   if (mCx) {
     return mCx;
   } else {
-    return mAutoSafeJSContext.ref();
+    return *mAutoSafeJSContext;
   }
 }
 
 } // namespace mozilla
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -391,48 +391,47 @@ class AsyncFreeSnowWhite;
 
 template <class StringType>
 class ShortLivedStringBuffer
 {
 public:
     StringType* Create()
     {
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            if (mStrings[i].empty()) {
-                mStrings[i].construct();
-                return mStrings[i].addr();
+            if (!mStrings[i]) {
+                mStrings[i].emplace();
+                return mStrings[i].ptr();
             }
         }
 
         // All our internal string wrappers are used, allocate a new string.
         return new StringType();
     }
 
     void Destroy(StringType *string)
     {
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            if (!mStrings[i].empty() &&
-                mStrings[i].addr() == string) {
+            if (mStrings[i] && mStrings[i].ptr() == string) {
                 // One of our internal strings is no longer in use, mark
                 // it as such and free its data.
-                mStrings[i].destroy();
+                mStrings[i].reset();
                 return;
             }
         }
 
         // We're done with a string that's not one of our internal
         // strings, delete it.
         delete string;
     }
 
     ~ShortLivedStringBuffer()
     {
 #ifdef DEBUG
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            MOZ_ASSERT(mStrings[i].empty(), "Short lived string still in use");
+            MOZ_ASSERT(!mStrings[i], "Short lived string still in use");
         }
 #endif
     }
 
 private:
     mozilla::Maybe<StringType> mStrings[2];
 };
 
--- a/js/xpconnect/wrappers/AddonWrapper.cpp
+++ b/js/xpconnect/wrappers/AddonWrapper.cpp
@@ -185,19 +185,19 @@ AddonWrapper<Base>::delete_(JSContext *c
     js::ReportErrorWithId(cx, "unable to delete interposed property %s", id);
     return false;
 }
 
 #define AddonWrapperCC AddonWrapper<CrossCompartmentWrapper>
 #define AddonWrapperXrayXPCWN AddonWrapper<PermissiveXrayXPCWN>
 #define AddonWrapperXrayDOM AddonWrapper<PermissiveXrayDOM>
 
-template<> AddonWrapperCC AddonWrapperCC::singleton(0);
-template<> AddonWrapperXrayXPCWN AddonWrapperXrayXPCWN::singleton(0);
-template<> AddonWrapperXrayDOM AddonWrapperXrayDOM::singleton(0);
+template<> const AddonWrapperCC AddonWrapperCC::singleton(0);
+template<> const AddonWrapperXrayXPCWN AddonWrapperXrayXPCWN::singleton(0);
+template<> const AddonWrapperXrayDOM AddonWrapperXrayDOM::singleton(0);
 
 template class AddonWrapperCC;
 template class AddonWrapperXrayXPCWN;
 template class AddonWrapperXrayDOM;
 
 #undef AddonWrapperCC
 #undef AddonWrapperXrayXPCWN
 #undef AddonWrapperXrayDOM
--- a/js/xpconnect/wrappers/AddonWrapper.h
+++ b/js/xpconnect/wrappers/AddonWrapper.h
@@ -36,14 +36,14 @@ class AddonWrapper : public Base {
                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
     virtual bool set(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject receiver,
                      JS::HandleId id, bool strict, JS::MutableHandleValue vp) const MOZ_OVERRIDE;
 
     virtual bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
                                 JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp) const MOZ_OVERRIDE;
 
-    static AddonWrapper singleton;
+    static const AddonWrapper singleton;
 };
 
 } // namespace xpc
 
 #endif // AddonWrapper_h
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -2277,17 +2277,17 @@ HasNativeProperty(JSContext *cx, HandleO
     NS_ENSURE_TRUE(holder, false);
     *hasProp = false;
     Rooted<JSPropertyDescriptor> desc(cx);
     const Wrapper *handler = Wrapper::wrapperHandler(wrapper);
 
     // Try resolveOwnProperty.
     Maybe<ResolvingId> resolvingId;
     if (traits == &XPCWrappedNativeXrayTraits::singleton)
-        resolvingId.construct(cx, wrapper, id);
+        resolvingId.emplace(cx, wrapper, id);
     if (!traits->resolveOwnProperty(cx, *handler, wrapper, holder, id, &desc))
         return false;
     if (desc.object()) {
         *hasProp = true;
         return true;
     }
 
     // Try the holder.
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -50,16 +50,17 @@ RestyleManager::RestyleManager(nsPresCon
   , mRebuildAllStyleData(false)
   , mObservingRefreshDriver(false)
   , mInStyleRefresh(false)
   , mHoverGeneration(0)
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mLastUpdateForThrottledAnimations(aPresContext->RefreshDriver()->
                                         MostRecentRefresh())
   , mAnimationGeneration(0)
+  , mReframingStyleContexts(nullptr)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT)
   , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
                               ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT)
 {
   mPendingRestyles.Init(this);
   mPendingAnimationRestyles.Init(this);
 }
@@ -714,16 +715,19 @@ RestyleManager::ProcessRestyledFrames(ns
     }
     if (hint & nsChangeHint_ReconstructFrame) {
       // If we ever start passing true here, be careful of restyles
       // that involve a reframe and animations.  In particular, if the
       // restyle we're processing here is an animation restyle, but
       // the style resolution we will do for the frame construction
       // happens async when we're not in an animation restyle already,
       // problems could arise.
+      // We could also have problems with triggering of CSS transitions
+      // on elements whose frames are reconstructed, since we depend on
+      // the reconstruction happening synchronously.
       FrameConstructor()->RecreateFramesForContent(content, false);
     } else {
       NS_ASSERTION(frame, "This shouldn't happen");
 
       if ((frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
           (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
         // frame does not maintain overflow rects, so avoid calling
         // FinishAndStoreOverflow on it:
@@ -897,20 +901,18 @@ RestyleManager::RestyleElement(Element* 
         aPrimaryFrame = aElement->GetPrimaryFrame();
       }
     }
   }
 
   if (aMinHint & nsChangeHint_ReconstructFrame) {
     FrameConstructor()->RecreateFramesForContent(aElement, false);
   } else if (aPrimaryFrame) {
-    nsStyleChangeList changeList;
-    ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
-                          aRestyleTracker, aRestyleHint);
-    ProcessRestyledFrames(changeList);
+    ComputeAndProcessStyleChange(aPrimaryFrame, aMinHint, aRestyleTracker,
+                                 aRestyleHint);
   } else if (aRestyleHint & ~eRestyle_LaterSiblings) {
     // We're restyling an element with no frame, so we should try to
     // make one if its new style says it should have one.  But in order
     // to try to honor the restyle hint (which we'd like to do so that,
     // for example, an animation-only style flush doesn't flush other
     // buffered style changes), we only do this if the restyle hint says
     // we have *some* restyling for this frame.  This means we'll
     // potentially get ahead of ourselves in that case, but not as much
@@ -1456,26 +1458,22 @@ RestyleManager::DoRebuildAllStyleData(Re
   }
 
   // Recalculate all of the style contexts for the document
   // Note that we can ignore the return value of ComputeStyleChangeFor
   // because we never need to reframe the root frame
   // XXX This could be made faster by not rerunning rule matching
   // (but note that nsPresShell::SetPreferenceStyleRules currently depends
   // on us re-running rule matching here
-  nsStyleChangeList changeList;
   // XXX Does it matter that we're passing aExtraHint to the real root
   // frame and not the root node's primary frame?  (We could do
   // roughly what we do for aRestyleHint above.)
   // Note: The restyle tracker we pass in here doesn't matter.
-  ComputeStyleChangeFor(mPresContext->PresShell()->GetRootFrame(),
-                        &changeList, aExtraHint,
-                        aRestyleTracker, aRestyleHint);
-  // Process the required changes
-  ProcessRestyledFrames(changeList);
+  ComputeAndProcessStyleChange(mPresContext->PresShell()->GetRootFrame(),
+                               aExtraHint, aRestyleTracker, aRestyleHint);
   FlushOverflowChangedTracker();
 
   // Tell the style set it's safe to destroy the old rule tree.  We
   // must do this after the ProcessRestyledFrames call in case the
   // change list has frame reconstructs in it (since frames to be
   // reconstructed will still have their old style context pointers
   // until they are destroyed).
   mPresContext->StyleSet()->EndReconstruct();
@@ -1818,20 +1816,22 @@ RestyleManager::DebugVerifyStyleTree(nsI
     VerifyStyleTree(mPresContext, aFrame, parentContext);
   }
 }
 
 #endif // DEBUG
 
 // aContent must be the content for the frame in question, which may be
 // :before/:after content
-static void
-TryStartingTransition(nsPresContext *aPresContext, nsIContent *aContent,
-                      nsStyleContext *aOldStyleContext,
-                      nsRefPtr<nsStyleContext> *aNewStyleContext /* inout */)
+/* static */ void
+RestyleManager::TryStartingTransition(nsPresContext* aPresContext,
+                                      nsIContent* aContent,
+                                      nsStyleContext* aOldStyleContext,
+                                      nsRefPtr<nsStyleContext>*
+                                        aNewStyleContext /* inout */)
 {
   if (!aContent || !aContent->IsElement()) {
     return;
   }
 
   // Notify the transition manager, and if it starts a transition,
   // it will give us back a transition-covering style rule which
   // we'll use to get *another* style context.  We want to ignore
@@ -2605,18 +2605,18 @@ ElementRestyler::RestyleSelf(nsIFrame* a
       // style contexts around.  However, we need to start from the
       // same root.
       newContext = oldContext;
     }
   }
 
   if (newContext != oldContext) {
     if (!copyFromContinuation) {
-      TryStartingTransition(mPresContext, aSelf->GetContent(),
-                            oldContext, &newContext);
+      RestyleManager::TryStartingTransition(mPresContext, aSelf->GetContent(),
+                                            oldContext, &newContext);
 
       CaptureChange(oldContext, newContext, assumeDifferenceHint);
     }
 
     if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
       // If the frame gets regenerated, let it keep its old context,
       // which is important to maintain various invariants about
       // frame types matching their style contexts.
@@ -3068,16 +3068,35 @@ GetNextBlockInInlineSibling(FramePropert
     return nullptr;
   }
 
   return static_cast<nsIFrame*>
     (aPropTable->Get(aFrame, nsIFrame::IBSplitSibling()));
 }
 
 void
+RestyleManager::ComputeAndProcessStyleChange(nsIFrame*          aFrame,
+                                             nsChangeHint       aMinChange,
+                                             RestyleTracker&    aRestyleTracker,
+                                             nsRestyleHint      aRestyleHint)
+{
+  // Create a ReframingStyleContexts struct on the stack and put it in
+  // our mReframingStyleContexts for the scope of this function.
+  MOZ_ASSERT(!mReframingStyleContexts, "shouldn't call recursively");
+  AutoRestore<ReframingStyleContexts*> ar(mReframingStyleContexts);
+  ReframingStyleContexts reframingStyleContexts;
+  mReframingStyleContexts = &reframingStyleContexts;
+
+  nsStyleChangeList changeList;
+  ComputeStyleChangeFor(aFrame, &changeList, aMinChange,
+                        aRestyleTracker, aRestyleHint);
+  ProcessRestyledFrames(changeList);
+}
+
+void
 RestyleManager::ComputeStyleChangeFor(nsIFrame*          aFrame,
                                       nsStyleChangeList* aChangeList,
                                       nsChangeHint       aMinChange,
                                       RestyleTracker&    aRestyleTracker,
                                       nsRestyleHint      aRestyleHint)
 {
   PROFILER_LABEL("RestyleManager", "ComputeStyleChangeFor",
     js::ProfileEntry::Category::CSS);
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -11,16 +11,18 @@
 #ifndef mozilla_RestyleManager_h
 #define mozilla_RestyleManager_h
 
 #include "nsISupportsImpl.h"
 #include "nsChangeHint.h"
 #include "RestyleTracker.h"
 #include "nsPresContext.h"
 #include "nsRefreshDriver.h"
+#include "nsRefPtrHashtable.h"
+#include "nsCSSPseudoElements.h"
 
 class nsIFrame;
 class nsStyleChangeList;
 struct TreeMatchContext;
 
 namespace mozilla {
   class EventStates;
 
@@ -36,16 +38,18 @@ public:
   typedef mozilla::dom::Element Element;
 
   RestyleManager(nsPresContext* aPresContext);
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~RestyleManager()
   {
+    MOZ_ASSERT(!mReframingStyleContexts,
+               "temporary member should be nulled out before destruction");
   }
 
 public:
   NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
 
   void Disconnect() {
     mPresContext = nullptr;
   }
@@ -92,42 +96,123 @@ public:
    * aFrame must be changed to the new parent before this function is called;
    * the new parent style context will be automatically computed based on the
    * new position in the frame tree.
    *
    * @param aFrame the root of the subtree to reparent.  Must not be null.
    */
   nsresult ReparentStyleContext(nsIFrame* aFrame);
 
+private:
+  void ComputeAndProcessStyleChange(nsIFrame* aFrame,
+                                    nsChangeHint aMinChange,
+                                    RestyleTracker& aRestyleTracker,
+                                    nsRestyleHint aRestyleHint);
+
   /**
    * Re-resolve the style contexts for a frame tree, building
    * aChangeList based on the resulting style changes, plus aMinChange
    * applied to aFrame.
    */
   void
     ComputeStyleChangeFor(nsIFrame* aFrame,
                           nsStyleChangeList* aChangeList,
                           nsChangeHint aMinChange,
                           RestyleTracker& aRestyleTracker,
                           nsRestyleHint aRestyleHint);
 
+public:
+
 #ifdef DEBUG
   /**
    * DEBUG ONLY method to verify integrity of style tree versus frame tree
    */
   void DebugVerifyStyleTree(nsIFrame* aFrame);
 #endif
 
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessRestyledFrames call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
   nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
 
+  /**
+   * In order to start CSS transitions on elements that are being
+   * reframed, we need to stash their style contexts somewhere during
+   * the reframing process.
+   *
+   * In all cases, the content node in the hash table is the real
+   * content node, not the anonymous content node we create for ::before
+   * or ::after.  The content node passed to the Get and Put methods is,
+   * however, the content node to be associate with the frame's style
+   * context.
+   */
+  typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIContent>, nsStyleContext>
+            ReframingStyleContextTable;
+  class ReframingStyleContexts {
+  public:
+    void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
+      MOZ_ASSERT(aContent);
+      nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType();
+      if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
+        mElementContexts.Put(aContent, aStyleContext);
+      } else if (pseudoType == nsCSSPseudoElements::ePseudo_before) {
+        MOZ_ASSERT(aContent->Tag() == nsGkAtoms::mozgeneratedcontentbefore);
+        mBeforePseudoContexts.Put(aContent->GetParent(), aStyleContext);
+      } else if (pseudoType == nsCSSPseudoElements::ePseudo_after) {
+        MOZ_ASSERT(aContent->Tag() == nsGkAtoms::mozgeneratedcontentafter);
+        mAfterPseudoContexts.Put(aContent->GetParent(), aStyleContext);
+      }
+    }
+
+    nsStyleContext* Get(nsIContent* aContent,
+                        nsCSSPseudoElements::Type aPseudoType) {
+      MOZ_ASSERT(aContent);
+      if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
+        return mElementContexts.GetWeak(aContent);
+      }
+      if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
+        MOZ_ASSERT(aContent->Tag() == nsGkAtoms::mozgeneratedcontentbefore);
+        return mBeforePseudoContexts.GetWeak(aContent->GetParent());
+      }
+      if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
+        MOZ_ASSERT(aContent->Tag() == nsGkAtoms::mozgeneratedcontentafter);
+        return mAfterPseudoContexts.GetWeak(aContent->GetParent());
+      }
+      MOZ_ASSERT(false, "unexpected aPseudoType");
+      return nullptr;
+    }
+  private:
+    ReframingStyleContextTable mElementContexts;
+    ReframingStyleContextTable mBeforePseudoContexts;
+    ReframingStyleContextTable mAfterPseudoContexts;
+  };
+
+  /**
+   * Return the current ReframingStyleContexts struct, or null if we're
+   * not currently in a restyling operation.
+   */
+  ReframingStyleContexts* GetReframingStyleContexts() {
+    return mReframingStyleContexts;
+  }
+
+  /**
+   * Try starting a transition for an element or a ::before or ::after
+   * pseudo-element, given an old and new style context.  This may
+   * change the new style context if a transition is started.
+   *
+   * For the pseudo-elements, aContent must be the anonymous content
+   * that we're creating for that pseudo-element, not the real element.
+   */
+  static void
+  TryStartingTransition(nsPresContext* aPresContext, nsIContent* aContent,
+                        nsStyleContext* aOldStyleContext,
+                        nsRefPtr<nsStyleContext>* aNewStyleContext /* inout */);
+
 private:
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
   // Restyling for a ContentInserted (notification after insertion) or
   // for a CharacterDataChanged.  |aContainer| must be non-null; when
   // the container is null, no work is needed.
   void RestyleForInsertOrChange(Element* aContainer, nsIContent* aChild);
@@ -299,16 +384,18 @@ private:
   mozilla::TimeStamp mLastUpdateForThrottledAnimations;
 
   OverflowChangedTracker mOverflowChangedTracker;
 
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
+  ReframingStyleContexts* mReframingStyleContexts;
+
   RestyleTracker mPendingRestyles;
   RestyleTracker mPendingAnimationRestyles;
 };
 
 /**
  * An ElementRestyler is created for *each* element in a subtree that we
  * recompute styles for.
  */
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1767,16 +1767,20 @@ nsCSSFrameConstructor::CreateGeneratedCo
 void
 nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
                                                   nsContainerFrame* aParentFrame,
                                                   nsIContent*      aParentContent,
                                                   nsStyleContext*  aStyleContext,
                                                   nsCSSPseudoElements::Type aPseudoElement,
                                                   FrameConstructionItemList& aItems)
 {
+  MOZ_ASSERT(aPseudoElement == nsCSSPseudoElements::ePseudo_before ||
+             aPseudoElement == nsCSSPseudoElements::ePseudo_after,
+             "unexpected aPseudoElement");
+
   // XXXbz is this ever true?
   if (!aParentContent->IsElement()) {
     NS_ERROR("Bogus generated content parent");
     return;
   }
 
   nsStyleSet *styleSet = mPresShell->StyleSet();
 
@@ -1784,20 +1788,23 @@ nsCSSFrameConstructor::CreateGeneratedCo
   nsRefPtr<nsStyleContext> pseudoStyleContext;
   pseudoStyleContext =
     styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
                                       aPseudoElement,
                                       aStyleContext,
                                       aState.mTreeMatchContext);
   if (!pseudoStyleContext)
     return;
+
+  bool isBefore = aPseudoElement == nsCSSPseudoElements::ePseudo_before;
+
   // |ProbePseudoStyleFor| checked the 'display' property and the
   // |ContentCount()| of the 'content' property for us.
   nsRefPtr<NodeInfo> nodeInfo;
-  nsIAtom* elemName = aPseudoElement == nsCSSPseudoElements::ePseudo_before ?
+  nsIAtom* elemName = isBefore ?
     nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
                                                        kNameSpaceID_None,
                                                        nsIDOMNode::ELEMENT_NODE);
   nsCOMPtr<Element> container;
   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
   if (NS_FAILED(rv))
     return;
@@ -1809,16 +1816,28 @@ nsCSSFrameConstructor::CreateGeneratedCo
   nsIDocument* bindDocument =
     aParentContent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
   rv = container->BindToTree(bindDocument, aParentContent, aParentContent, true);
   if (NS_FAILED(rv)) {
     container->UnbindFromTree();
     return;
   }
 
+  RestyleManager::ReframingStyleContexts* rsc =
+    RestyleManager()->GetReframingStyleContexts();
+  if (rsc) {
+    nsStyleContext* oldStyleContext = rsc->Get(container, aPseudoElement);
+    if (oldStyleContext) {
+      RestyleManager::TryStartingTransition(aState.mPresContext,
+                                            container,
+                                            oldStyleContext,
+                                            &pseudoStyleContext);
+    }
+  }
+
   uint32_t contentCount = pseudoStyleContext->StyleContent()->ContentCount();
   for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
     nsCOMPtr<nsIContent> content =
       CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
                              contentIndex);
     if (content) {
       container->AppendChildTo(content, false);
     }
@@ -2403,16 +2422,19 @@ nsCSSFrameConstructor::ConstructDocEleme
   // the future.  We need this, because the document element might
   // have stale restyle bits from a previous frame constructor for
   // this document.  Unlike in AddFrameConstructionItems, it's safe to
   // unset all element restyle flags, since we don't have any
   // siblings.
   aDocElement->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
 
   // --------- CREATE AREA OR BOX FRAME -------
+  // FIXME: Should this use ResolveStyleContext?  (The calls in this
+  // function are the only case in nsCSSFrameConstructor where we don't
+  // do so for the construction of a style context for an element.)
   nsRefPtr<nsStyleContext> styleContext;
   styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
                                                          nullptr);
 
   const nsStyleDisplay* display = styleContext->StyleDisplay();
 
   // Ensure that our XBL bindings are installed.
   if (display->mBinding) {
@@ -2435,16 +2457,20 @@ nsCSSFrameConstructor::ConstructDocEleme
     if (binding) {
       // For backwards compat, keep firing the root's constructor
       // after all of its kids' constructors.  So tell the binding
       // manager about it right now.
       mDocument->BindingManager()->AddToAttachedQueue(binding);
     }
 
     if (resolveStyle) {
+      // FIXME: Should this use ResolveStyleContext?  (The calls in this
+      // function are the only case in nsCSSFrameConstructor where we
+      // don't do so for the construction of a style context for an
+      // element.)
       styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
                                                              nullptr);
       display = styleContext->StyleDisplay();
     }
   }
 
   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
 
@@ -4740,31 +4766,46 @@ nsCSSFrameConstructor::ResolveStyleConte
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
                                            nsIContent* aContent,
                                            nsFrameConstructorState* aState)
 {
   nsStyleSet *styleSet = mPresShell->StyleSet();
   aContent->OwnerDoc()->FlushPendingLinkUpdates();
 
+  nsRefPtr<nsStyleContext> result;
   if (aContent->IsElement()) {
     if (aState) {
-      return styleSet->ResolveStyleFor(aContent->AsElement(),
-                                       aParentStyleContext,
-                                       aState->mTreeMatchContext);
-    }
-    return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext);
-
-  }
-
-  NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
-               "shouldn't waste time creating style contexts for "
-               "comments and processing instructions");
-
-  return styleSet->ResolveStyleForNonElement(aParentStyleContext);
+      result = styleSet->ResolveStyleFor(aContent->AsElement(),
+                                         aParentStyleContext,
+                                         aState->mTreeMatchContext);
+    } else {
+      result = styleSet->ResolveStyleFor(aContent->AsElement(),
+                                         aParentStyleContext);
+    }
+  } else {
+    NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
+                 "shouldn't waste time creating style contexts for "
+                 "comments and processing instructions");
+    result = styleSet->ResolveStyleForNonElement(aParentStyleContext);
+  }
+
+  RestyleManager::ReframingStyleContexts* rsc =
+    RestyleManager()->GetReframingStyleContexts();
+  if (rsc) {
+    nsStyleContext* oldStyleContext =
+      rsc->Get(aContent, nsCSSPseudoElements::ePseudo_NotPseudoElement);
+    if (oldStyleContext) {
+      RestyleManager::TryStartingTransition(mPresShell->GetPresContext(),
+                                            aContent,
+                                            oldStyleContext, &result);
+    }
+  }
+
+  return result.forget();
 }
 
 // MathML Mod - RBS
 void
 nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
                                              nsIContent* aContent,
                                              nsContainerFrame* aParentFrame,
                                              nsFrameItems& aBlockItems,
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1330,18 +1330,18 @@ nsRefreshDriver::BeginRefreshingImages(n
 /* static */ PLDHashOperator
 nsRefreshDriver::StartTableRefresh(const uint32_t& aDelay,
                                    ImageStartData* aData,
                                    void* aUserArg)
 {
   ImageRequestParameters* parms =
     static_cast<ImageRequestParameters*> (aUserArg);
 
-  if (!aData->mStartTime.empty()) {
-    TimeStamp& start = aData->mStartTime.ref();
+  if (aData->mStartTime) {
+    TimeStamp& start = *aData->mStartTime;
     TimeDuration prev = parms->mPrevious - start;
     TimeDuration curr = parms->mCurrent - start;
     uint32_t prevMultiple = static_cast<uint32_t>(prev.ToMilliseconds()) / aDelay;
 
     // We want to trigger images' refresh if we've just crossed over a multiple
     // of the first image's start time. If so, set the animation start time to
     // the nearest multiple of the delay and move all the images in this table
     // to the main requests table.
@@ -1350,17 +1350,17 @@ nsRefreshDriver::StartTableRefresh(const
       aData->mEntries.EnumerateEntries(nsRefreshDriver::BeginRefreshingImages, parms);
     }
   } else {
     // This is the very first time we've drawn images with this time delay.
     // Set the animation start time to "now" and move all the images in this
     // table to the main requests table.
     parms->mDesired = parms->mCurrent;
     aData->mEntries.EnumerateEntries(nsRefreshDriver::BeginRefreshingImages, parms);
-    aData->mStartTime.construct(parms->mCurrent);
+    aData->mStartTime.emplace(parms->mCurrent);
   }
 
   return PL_DHASH_NEXT;
 }
 
 void
 nsRefreshDriver::Freeze()
 {
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -390,23 +390,23 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   nsMargin border = aReflowState.ComputedPhysicalBorderPadding() - aReflowState.ComputedPhysicalPadding();
 
   // Figure out how big the legend is if there is one. 
   // get the legend's margin
   nsMargin legendMargin(0,0,0,0);
   // reflow the legend only if needed
   Maybe<nsHTMLReflowState> legendReflowState;
   if (legend) {
-    legendReflowState.construct(aPresContext, aReflowState, legend,
+    legendReflowState.emplace(aPresContext, aReflowState, legend,
                                 legendAvailSize);
   }
   if (reflowLegend) {
     nsHTMLReflowMetrics legendDesiredSize(aReflowState);
 
-    ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ref(),
+    ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowState,
                 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
 #ifdef NOISY_REFLOW
     printf("  returned (%d, %d)\n",
            legendDesiredSize.Width(), legendDesiredSize.Height());
 #endif
     // figure out the legend's rectangle
     legendMargin = legend->GetUsedMargin();
     mLegendRect.width  = legendDesiredSize.Width() + legendMargin.left + legendMargin.right;
@@ -425,17 +425,17 @@ nsFieldSetFrame::Reflow(nsPresContext*  
 
     // if the legend space changes then we need to reflow the 
     // content area as well.
     if (mLegendSpace != oldSpace && inner) {
       reflowInner = true;
     }
 
     FinishReflowChild(legend, aPresContext, legendDesiredSize,
-                      &legendReflowState.ref(), 0, 0, NS_FRAME_NO_MOVE_FRAME);    
+                      legendReflowState.ptr(), 0, 0, NS_FRAME_NO_MOVE_FRAME);    
   } else if (!legend) {
     mLegendRect.SetEmpty();
     mLegendSpace = 0;
   } else {
     // mLegendSpace and mLegendRect haven't changed, but we need
     // the used margin when placing the legend.
     legendMargin = legend->GetUsedMargin();
   }
@@ -524,17 +524,17 @@ nsFieldSetFrame::Reflow(nsPresContext*  
       physicalContentRect.width = mLegendRect.width +
         aReflowState.ComputedPhysicalPadding().LeftRight();
     }
 
     // place the legend
     nsRect actualLegendRect(mLegendRect);
     actualLegendRect.Deflate(legendMargin);
     nsPoint actualLegendPos(actualLegendRect.TopLeft());
-    legendReflowState.ref().ApplyRelativePositioning(&actualLegendPos);
+    legendReflowState->ApplyRelativePositioning(&actualLegendPos);
     legend->SetPosition(actualLegendPos);
     nsContainerFrame::PositionFrameView(legend);
     nsContainerFrame::PositionChildViews(legend);
   }
 
   // Return our size and our result.
   WritingMode wm = aReflowState.GetWritingMode();
   nsSize finalSize(physicalContentRect.width + border.LeftRight(),
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1044,19 +1044,19 @@ nsBlockFrame::Reflow(nsPresContext*     
       // Bottom margin never causes us to create continuations, so we
       // don't need to worry about whether it fits in its entirety.
       blockDirExtras.BStart(wm) +=
         aReflowState.ComputedLogicalMargin().BStart(wm);
     }
 
     if (effectiveComputedBSize + blockDirExtras.BStartEnd(wm) <=
         aReflowState.AvailableBSize()) {
-      mutableReflowState.construct(aReflowState);
-      mutableReflowState.ref().AvailableBSize() = NS_UNCONSTRAINEDSIZE;
-      reflowState = mutableReflowState.addr();
+      mutableReflowState.emplace(aReflowState);
+      mutableReflowState->AvailableBSize() = NS_UNCONSTRAINEDSIZE;
+      reflowState = mutableReflowState.ptr();
     }
   }
 
   // See comment below about oldSize. Use *only* for the
   // abs-pos-containing-block-size-change optimization!
   nsSize oldSize = GetSize();
 
   // Should we create a float manager?
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -28,16 +28,17 @@
 #include "nsStyleConsts.h"
 #include "nsStyleUtil.h"
 #include "nsIPresShell.h"
 #include "prlog.h"
 #include "prprf.h"
 #include <stdarg.h>
 #include "nsFrameManager.h"
 #include "nsLayoutUtils.h"
+#include "RestyleManager.h"
 
 #include "nsIDOMNode.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsFrameSelection.h"
 #include "nsGkAtoms.h"
 #include "nsCSSAnonBoxes.h"
 
@@ -646,21 +647,31 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
     if (nextSib) {
       NS_WARN_IF_FALSE(this ==
          nextSib->Properties().Get(nsIFrame::IBSplitPrevSibling()),
          "IB sibling chain is inconsistent");
       nextSib->Properties().Delete(nsIFrame::IBSplitPrevSibling());
     }
   }
 
-  // This needs to happen before shell->NotifyDestroyingFrame because that
-  // clears our Properties() table.
   bool isPrimaryFrame = (mContent && mContent->GetPrimaryFrame() == this);
   if (isPrimaryFrame) {
+    // This needs to happen before shell->NotifyDestroyingFrame because
+    // that clears our Properties() table.
     ActiveLayerTracker::TransferActivityToContent(this, mContent);
+
+    // Unfortunately, we need to do this for all frames being reframed
+    // and not only those whose current style involves CSS transitions,
+    // because what matters is whether the new style (not the old)
+    // specifies CSS transitions.
+    RestyleManager::ReframingStyleContexts* rsc =
+      presContext->RestyleManager()->GetReframingStyleContexts();
+    if (rsc) {
+      rsc->Put(mContent, mStyleContext);
+    }
   }
 
   shell->NotifyDestroyingFrame(this);
 
   if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
     shell->ClearFrameRefs(this);
   }
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -785,19 +785,19 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   // Setup reflow state for reflowing the frame
   Maybe<nsHTMLReflowState> reflowStateHolder;
   if (!isText) {
     // Compute the available size for the frame. This available width
     // includes room for the side margins.
     // For now, set the available block-size to unconstrained always.
     LogicalSize availSize = mBlockReflowState->ComputedSize(frameWM);
     availSize.BSize(frameWM) = NS_UNCONSTRAINEDSIZE;
-    reflowStateHolder.construct(mPresContext, *psd->mReflowState,
-                                aFrame, availSize);
-    nsHTMLReflowState& reflowState = reflowStateHolder.ref();
+    reflowStateHolder.emplace(mPresContext, *psd->mReflowState,
+                              aFrame, availSize);
+    nsHTMLReflowState& reflowState = *reflowStateHolder;
     reflowState.mLineLayout = this;
     reflowState.mFlags.mIsTopOfPage = mIsTopOfPage;
     if (reflowState.ComputedWidth() == NS_UNCONSTRAINEDSIZE)
       reflowState.AvailableWidth() = availableSpaceOnLine;
     WritingMode stateWM = reflowState.GetWritingMode();
     pfd->mMargin =
       reflowState.ComputedLogicalMargin().ConvertTo(frameWM, stateWM);
     pfd->mBorderPadding =
@@ -847,18 +847,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
 
   int32_t savedOptionalBreakOffset;
   gfxBreakPriority savedOptionalBreakPriority;
   nsIContent* savedOptionalBreakContent =
     GetLastOptionalBreakPosition(&savedOptionalBreakOffset,
                                  &savedOptionalBreakPriority);
 
   if (!isText) {
-    aFrame->Reflow(mPresContext, metrics, reflowStateHolder.ref(),
-                   aReflowStatus);
+    aFrame->Reflow(mPresContext, metrics, *reflowStateHolder, aReflowStatus);
   } else {
     static_cast<nsTextFrame*>(aFrame)->
       ReflowText(*this, availableSpaceOnLine, psd->mReflowState->rendContext,
                  metrics, aReflowStatus);
   }
   
   pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
   pfd->mJustificationNumLetters = mTextJustificationNumLetters;
@@ -969,17 +968,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   pfd->mBounds.ISize(lineWM) = metrics.ISize(lineWM);
   pfd->mBounds.BSize(lineWM) = metrics.BSize(lineWM);
 
   // Size the frame, but |RelativePositionFrames| will size the view.
   aFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth);
 
   // Tell the frame that we're done reflowing it
   aFrame->DidReflow(mPresContext,
-                    isText ? nullptr : reflowStateHolder.addr(),
+                    isText ? nullptr : reflowStateHolder.ptr(),
                     nsDidReflowStatus::FINISHED);
 
   if (aMetrics) {
     *aMetrics = metrics;
   }
 
   if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
     // If frame is complete and has a next-in-flow, we need to delete
@@ -1005,17 +1004,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
     if (!continuingTextRun && !pfd->GetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE)) {
       mTrimmableWidth = 0;
     }
 
     // See if we can place the frame. If we can't fit it, then we
     // return now.
     bool optionalBreakAfterFits;
     NS_ASSERTION(isText ||
-                 !reflowStateHolder.ref().IsFloating(),
+                 !reflowStateHolder->IsFloating(),
                  "How'd we get a floated inline frame? "
                  "The frame ctor should've dealt with this.");
     if (CanPlaceFrame(pfd, notSafeToBreak, continuingTextRun,
                       savedOptionalBreakContent != nullptr, metrics,
                       aReflowStatus, &optionalBreakAfterFits)) {
       if (!isEmpty) {
         psd->mHasNonemptyContent = true;
         mLineIsEmpty = false;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2590,30 +2590,30 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyle
   /* can't call parentContext->Style##type_() since it could recur into */    \
   /* setting the same struct on the same rule node, causing a leak. */        \
   if (aRuleDetail != eRuleFullReset &&                                        \
       (!aStartStruct || (aRuleDetail != eRulePartialReset &&                  \
                          aRuleDetail != eRuleNone))) {                        \
     if (parentContext) {                                                      \
       parentdata_ = parentContext->Style##type_();                            \
     } else {                                                                  \
-      maybeFakeParentData.construct ctorargs_;                                \
-      parentdata_ = maybeFakeParentData.addr();                               \
+      maybeFakeParentData.emplace ctorargs_;                                  \
+      parentdata_ = maybeFakeParentData.ptr();                                \
     }                                                                         \
   }                                                                           \
   if (aStartStruct)                                                           \
     /* We only need to compute the delta between this computed data and */    \
     /* our computed data. */                                                  \
     data_ = new (mPresContext)                                                \
             nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct));      \
   else {                                                                      \
     if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) {     \
       /* No question. We will have to inherit. Go ahead and init */           \
       /* with inherited vals from parent. */                                  \
-      canStoreInRuleTree = false;                                          \
+      canStoreInRuleTree = false;                                             \
       if (parentdata_)                                                        \
         data_ = new (mPresContext) nsStyle##type_(*parentdata_);              \
       else                                                                    \
         data_ = new (mPresContext) nsStyle##type_ ctorargs_;                  \
     }                                                                         \
     else                                                                      \
       data_ = new (mPresContext) nsStyle##type_ ctorargs_;                    \
   }                                                                           \
@@ -2658,18 +2658,18 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyle
   mozilla::Maybe<nsStyle##type_> maybeFakeParentData;                         \
   const nsStyle##type_* parentdata_ = data_;                                  \
   if (aRuleDetail != eRuleFullReset &&                                        \
       aRuleDetail != eRulePartialReset &&                                     \
       aRuleDetail != eRuleNone) {                                             \
     if (parentContext) {                                                      \
       parentdata_ = parentContext->Style##type_();                            \
     } else {                                                                  \
-      maybeFakeParentData.construct ctorargs_;                                \
-      parentdata_ = maybeFakeParentData.addr();                               \
+      maybeFakeParentData.emplace ctorargs_;                                  \
+      parentdata_ = maybeFakeParentData.ptr();                                \
     }                                                                         \
   }                                                                           \
   bool canStoreInRuleTree = aCanStoreInRuleTree;
 
 /**
  * End an nsRuleNode::Compute*Data function for an inherited struct.
  *
  * @param type_ The nsStyle* type this function computes.
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -100,38 +100,51 @@ nsTransitionManager::AddElementCollectio
 already_AddRefed<nsIStyleRule>
 nsTransitionManager::StyleContextChanged(dom::Element *aElement,
                                          nsStyleContext *aOldStyleContext,
                                          nsStyleContext *aNewStyleContext)
 {
   NS_PRECONDITION(aOldStyleContext->GetPseudo() ==
                       aNewStyleContext->GetPseudo(),
                   "pseudo type mismatch");
-  // If we were called from ReparentStyleContext, this assertion would
-  // actually fire.  If we need to be called from there, we can probably
-  // just remove it; the condition probably isn't critical, although
-  // it's worth thinking about some more.
-  NS_PRECONDITION(aOldStyleContext->HasPseudoElementData() ==
-                      aNewStyleContext->HasPseudoElementData(),
-                  "pseudo type mismatch");
 
   if (mInAnimationOnlyStyleUpdate) {
     // If we're doing an animation-only style update, return, since the
     // purpose of an animation-only style update is to update only the
     // animation styles so that we don't consider style changes
     // resulting from changes in the animation time for starting a
     // transition.
     return nullptr;
   }
 
   if (!mPresContext->IsDynamic()) {
     // For print or print preview, ignore transitions.
     return nullptr;
   }
 
+  if (aOldStyleContext->HasPseudoElementData() !=
+      aNewStyleContext->HasPseudoElementData()) {
+    // If the old style context and new style context differ in terms of
+    // whether they're inside ::first-letter, ::first-line, or similar,
+    // bail.  We can't hit this codepath for normal style changes
+    // involving moving frames around the boundaries of these
+    // pseudo-elements since we don't call StyleContextChanged from
+    // ReparentStyleContext.  However, we can hit this codepath during
+    // the handling of transitions that start across reframes.
+    //
+    // While there isn't an easy *perfect* way to handle this case, err
+    // on the side of missing some transitions that we ought to have
+    // rather than having bogus transitions that we shouldn't.
+    //
+    // We could consider changing this handling, although it's worth
+    // thinking about whether the code below could do anything weird in
+    // this case.
+    return nullptr;
+  }
+
   // NOTE: Things in this function (and ConsiderStartingTransition)
   // should never call PeekStyleData because we don't preserve gotten
   // structs across reframes.
 
   // Return sooner (before the startedAny check below) for the most
   // common case: no transitions specified or running.
   const nsStyleDisplay *disp = aNewStyleContext->StyleDisplay();
   nsCSSPseudoElements::Type pseudoType = aNewStyleContext->GetPseudoType();
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -185,16 +185,17 @@ skip-if = (toolkit == 'gonk' && debug) |
 [test_selectors_on_anonymous_content.html]
 [test_shorthand_property_getters.html]
 [test_specified_value_serialization.html]
 [test_style_attribute_quirks.html]
 [test_style_attribute_standards.html]
 [test_style_struct_copy_constructors.html]
 [test_supports_rules.html]
 [test_system_font_serialization.html]
+[test_transitions_and_reframes.html]
 [test_transitions_and_zoom.html]
 [test_transitions_cancel_near_end.html]
 [test_transitions_computed_values.html]
 [test_transitions_computed_value_combinations.html]
 [test_transitions_events.html]
 [test_transitions.html]
 [test_transitions_per_property.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227 # b2g(times out, needs more time + various failures) b2g-debug(times out, needs more time + various failures) b2g-desktop(times out, needs more time + various failures)
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_transitions_and_reframes.html
@@ -0,0 +1,268 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=625289
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 625289</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  :root,
+  #e1, #e2 > div,
+  #b1::before, #b2 > div::before,
+  #a1::after, #a2 > div::after {
+    margin-left: 0;
+  }
+  :root.t,
+  #e1.t, #e2.t > div,
+  #b1.t::before, #b2.t > div::before,
+  #a1.t::after, #a2.t > div::after {
+    transition: margin-left linear 1s;
+  }
+  #b1::before, #b2 > div::before,
+  #a1::after, #a2 > div::after {
+    content: "x";
+    display: block;
+  }
+  :root.m,
+  #e1.m, #e2.m > div,
+  #b1.m::before, #b2.m > div::before,
+  #a1.m::after, #a2.m > div::after {
+    margin-left: 100px;
+  }
+  .o { overflow: hidden }
+  .n { display: none }
+
+  #fline { color: blue; font-size: 20px; width: 800px; }
+  #fline::first-line { color: yellow }
+  #fline.narrow { width: 50px }
+  #fline i { transition: color linear 1s }
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=625289">Mozilla Bug 625289</a>
+<div id="container"></div>
+<div id="fline">
+  This text has an <i>i element</i> in it.
+</div>
+<pre id="test">
+<script>
+"use strict";
+
+function advance_clock(milliseconds) {
+  SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
+}
+
+var container = document.getElementById("container");
+
+function make_elements(idName, child) {
+  var e = document.createElement("div");
+  e.setAttribute("id", idName);
+  if (child) {
+    e.appendChild(document.createElement("div"));
+  }
+  container.appendChild(e);
+  return e;
+}
+
+function assert_margin_at_quarter(element, pseudo, passes)
+{
+  var desc;
+  var useParent = false;
+  if (element == document.documentElement) {
+    desc = "root element";
+  } else if (element.id) {
+    desc = "element " + element.id;
+  } else {
+    desc = "child of element " + element.parentNode.id;
+    useParent = true;
+  }
+  var classes = (useParent ? element.parentNode : element).getAttribute("class");
+  if (classes) {
+    desc += " (classes: " + classes + ")";
+  }
+  if (pseudo) {
+    desc += " " + pseudo + " pseudo-element";
+  }
+  (passes ? is : todo_is)(getComputedStyle(element, pseudo).marginLeft, "25px",
+                          "margin of " + desc);
+}
+
+function do_test(test)
+{
+  var expected_props = [ "element", "test_child", "pseudo", "passes",
+                         "dynamic_change_transition", "start_from_none" ];
+  for (var propidx in expected_props) {
+    if (! expected_props[propidx] in test) {
+      ok(false, "expected " + expected_props[propidx] + " on test object");
+    }
+  }
+
+  var e;
+  if (typeof(test.element) == "string") {
+    e = make_elements(test.element, test.test_child);
+  } else {
+    if (test.test_child) {
+      ok(false, "test_child unexpected");
+    }
+    e = test.element;
+  }
+
+  var target = test.test_child ? e.firstChild : e;
+
+  if (!test.dynamic_change_transition) {
+    e.classList.add("t");
+  }
+  if (test.start_from_none) {
+    e.classList.add("n");
+  }
+
+  advance_clock(100);
+  e.classList.add("m");
+  e.classList.add("o");
+  if (test.dynamic_change_transition) {
+    e.classList.add("t");
+  }
+  if (test.start_from_none) {
+    e.classList.remove("n");
+  }
+  advance_clock(0);
+  advance_clock(250);
+  assert_margin_at_quarter(target, test.pseudo, test.passes);
+  if (typeof(test.element) == "string") {
+    e.remove();
+  } else {
+    target.style.transition = "";
+    target.removeAttribute("class");
+  }
+}
+
+advance_clock(0);
+
+var tests = [
+  { element:"e1", test_child:false, pseudo:"", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:"e2", test_child:true, pseudo:"", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:"b1", test_child:false, pseudo:"::before", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:"b2", test_child:true, pseudo:"::before", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:"a1", test_child:false, pseudo:"::after", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:"a2", test_child:true, pseudo:"::after", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  { element:document.documentElement, test_child:false, pseudo:"", passes:true,
+    dynamic_change_transition:false, start_from_none:false },
+  // Recheck with a dynamic change in transition
+  { element:"e1", test_child:false, pseudo:"", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:"e2", test_child:true, pseudo:"", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:"b1", test_child:false, pseudo:"::before", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:"b2", test_child:true, pseudo:"::before", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:"a1", test_child:false, pseudo:"::after", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:"a2", test_child:true, pseudo:"::after", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  { element:document.documentElement, test_child:false, pseudo:"", passes:true,
+    dynamic_change_transition:true, start_from_none:false },
+  // Recheck starting from display:none.  Note that these tests all fail,
+  // although we could get *some* of them to pass by calling
+  // RestyleManager::TryStartingTransition from
+  // ElementRestyler::RestyleUndisplayedChildren.
+  { element:"e1", test_child:false, pseudo:"", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:"e2", test_child:true, pseudo:"", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:"b1", test_child:false, pseudo:"::before", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:"b2", test_child:true, pseudo:"::before", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:"a1", test_child:false, pseudo:"::after", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:"a2", test_child:true, pseudo:"::after", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  { element:document.documentElement, test_child:false, pseudo:"", passes:false,
+    dynamic_change_transition:false, start_from_none:true },
+  // Recheck with a dynamic change in transition and starting from display:none
+  { element:"e1", test_child:false, pseudo:"", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:"e2", test_child:true, pseudo:"", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:"b1", test_child:false, pseudo:"::before", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:"b2", test_child:true, pseudo:"::before", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:"a1", test_child:false, pseudo:"::after", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:"a2", test_child:true, pseudo:"::after", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+  { element:document.documentElement, test_child:false, pseudo:"", passes:false,
+    dynamic_change_transition:true, start_from_none:true },
+];
+
+for (var testidx in tests) {
+  do_test(tests[testidx]);
+}
+
+var fline = document.getElementById("fline");
+var fline_i_cs = getComputedStyle(fline.firstElementChild, "");
+// Note that the color in the ::first-line is never used in the test
+// since we avoid reporting ::first-line data in getComputedStyle.
+// However, if we were to start a transition (incorectly), that would
+// show up in getComputedStyle.
+var COLOR_IN_LATER_LINES = "rgb(0, 0, 255)";
+
+function do_firstline_test(test) {
+  if (test.widening) {
+    fline.classList.add("narrow");
+    is (fline_i_cs.color, COLOR_IN_LATER_LINES, "initial color");
+  } else {
+    is (fline_i_cs.color, COLOR_IN_LATER_LINES, "initial color");
+  }
+
+  if (test.widening) {
+    fline.classList.remove("narrow");
+  } else {
+    fline.classList.add("narrow");
+  }
+
+  if (test.set_overflow) {
+    fline.classList.add("o");
+  }
+
+  advance_clock(100);
+
+  if (test.widening) {
+    is (fline_i_cs.color, COLOR_IN_LATER_LINES,
+        "::first-line changes don't trigger transitions");
+  } else {
+    is (fline_i_cs.color, COLOR_IN_LATER_LINES,
+        "::first-line changes don't trigger transitions");
+  }
+
+  fline.removeAttribute("class");
+}
+
+var firstline_tests = [
+  { widening: true, set_overflow: false },
+  { widening: false, set_overflow: false },
+  { widening: true, set_overflow: true },
+  { widening: false, set_overflow: true },
+];
+
+for (var firstline_test_idx in firstline_tests) {
+  do_firstline_test(firstline_tests[firstline_test_idx]);
+}
+
+SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/tools/reftest/mach_commands.py
+++ b/layout/tools/reftest/mach_commands.py
@@ -362,20 +362,22 @@ def B2GCommand(func):
         help='Emulator resolution of the format \'<width>x<height>\'')
     func = emulator_res(func)
 
     marionette = CommandArgument('--marionette', default=None,
         help='host:port to use when connecting to Marionette')
     func = marionette(func)
 
     totalChunks = CommandArgument('--total-chunks', dest='totalChunks',
+        type = int,
         help = 'How many chunks to split the tests up into.')
     func = totalChunks(func)
 
     thisChunk = CommandArgument('--this-chunk', dest='thisChunk',
+        type = int,
         help = 'Which chunk to run between 1 and --total-chunks.')
     func = thisChunk(func)
 
     oop = CommandArgument('--enable-oop', action='store_true', dest='oop',
         help = 'Run tests in out-of-process mode.')
     func = oop(func)
 
     path = CommandArgument('test_file', default=None, nargs='?',
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -916,28 +916,30 @@ TEST_F(TransportTest, TestNoDtlsVerifica
   ConnectSocketExpectFail();
 }
 
 TEST_F(TransportTest, TestConnect) {
   SetDtlsPeer();
   ConnectSocket();
 
   // check that we got the right suite
-  ASSERT_EQ(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
+  // bug 1052610
+  //ASSERT_EQ(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
 
   // no SRTP on this one
   ASSERT_EQ(0, p1_->srtpCipher());
 }
 
 TEST_F(TransportTest, TestConnectSrtp) {
   SetupSrtp();
   SetDtlsPeer();
   ConnectSocket();
 
-  ASSERT_EQ(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
+  // bug 1052610
+  //ASSERT_EQ(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
 
   // SRTP is on
   ASSERT_EQ(SRTP_AES128_CM_HMAC_SHA1_80, p1_->srtpCipher());
 }
 
 
 TEST_F(TransportTest, TestConnectDestroyFlowsMainThread) {
   SetDtlsPeer();
@@ -1082,17 +1084,18 @@ static void ConfigureOneCipher(Transport
 
 TEST_F(TransportTest, TestCipherMismatch) {
   SetDtlsPeer();
   ConfigureOneCipher(p1_, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
   ConfigureOneCipher(p2_, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
   ConnectSocketExpectFail();
 }
 
-TEST_F(TransportTest, TestCipherMandatoryOnlyGcm) {
+// TODO(mt@mozilla.com) restore; bug 1052610
+TEST_F(TransportTest, DISABLED_TestCipherMandatoryOnlyGcm) {
   SetDtlsPeer();
   ConfigureOneCipher(p1_, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
   ConnectSocket();
   ASSERT_EQ(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, p1_->cipherSuite());
 }
 
 TEST_F(TransportTest, TestCipherMandatoryOnlyCbc) {
   SetDtlsPeer();
--- a/media/mtransport/transportlayerdtls.cpp
+++ b/media/mtransport/transportlayerdtls.cpp
@@ -496,17 +496,17 @@ bool TransportLayerDtls::Setup() {
       return false;
     }
   }
 
   // Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS
   // 1.0 for stream modes.
   SSLVersionRange version_range = {
     SSL_LIBRARY_VERSION_TLS_1_1,
-    SSL_LIBRARY_VERSION_TLS_1_2
+    SSL_LIBRARY_VERSION_TLS_1_1 // version intolerance; bug 1052610
   };
 
   rv = SSL_VersionRangeSet(ssl_fd, &version_range);
   if (rv != SECSuccess) {
     MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3");
     return false;
   }
 
@@ -667,16 +667,18 @@ bool TransportLayerDtls::SetupCipherSuit
     rv = SSL_CipherPrefSet(ssl_fd, EnabledCiphers[i], PR_TRUE);
     if (rv != SECSuccess) {
       MOZ_MTLOG(ML_ERROR, LAYER_INFO <<
                 "Unable to enable suite: " << EnabledCiphers[i]);
       return false;
     }
   }
 
+// Don't remove suites; TODO(mt@mozilla.com) restore; bug 1052610
+#if 0
   for (size_t i = 0; i < PR_ARRAY_SIZE(DisabledCiphers); ++i) {
     MOZ_MTLOG(ML_INFO, LAYER_INFO << "Disabling: " << DisabledCiphers[i]);
 
     PRBool enabled = false;
     rv = SSL_CipherPrefGet(ssl_fd, DisabledCiphers[i], &enabled);
     if (rv != SECSuccess) {
       MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
                 "Unable to check if suite is enabled: " << DisabledCiphers[i]);
@@ -686,16 +688,17 @@ bool TransportLayerDtls::SetupCipherSuit
       rv = SSL_CipherPrefSet(ssl_fd, DisabledCiphers[i], PR_FALSE);
       if (rv != SECSuccess) {
         MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
                   "Unable to disable suite: " << DisabledCiphers[i]);
         return false;
       }
     }
   }
+#endif
   return true;
 }
 
 nsresult TransportLayerDtls::GetCipherSuite(uint16_t* cipherSuite) const {
   CheckThread();
   if (!cipherSuite) {
     MOZ_MTLOG(ML_ERROR, LAYER_INFO << "GetCipherSuite passed a nullptr");
     return NS_ERROR_NULL_POINTER;
--- a/mfbt/Maybe.h
+++ b/mfbt/Maybe.h
@@ -1,182 +1,365 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* A class for lazily constructing an object without sticking it on the heap. */
+/* A class for optional values and in-place lazy construction. *