Bug 1096328 - Remove nativeOwnership from Bindings.conf, make rooting analysis happy. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Thu, 08 Jan 2015 22:56:42 +0100
changeset 223598 3bff2bbe6677f590c280c380202f138ba2a020af
parent 223597 b5be217117fa940df748fd31d05413dd2c9740ed
child 223599 7778319fce3211823402002f9aeb80a2a9868dfe
push id10804
push userkwierso@gmail.com
push dateWed, 14 Jan 2015 01:47:49 +0000
treeherderfx-team@b2d1d57c25b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1096328
milestone38.0a1
Bug 1096328 - Remove nativeOwnership from Bindings.conf, make rooting analysis happy. r=bz.
dom/base/AnonymousContent.cpp
dom/base/AnonymousContent.h
dom/base/NodeIterator.cpp
dom/base/NodeIterator.h
dom/base/TreeWalker.cpp
dom/base/TreeWalker.h
dom/base/URL.cpp
dom/base/URL.h
dom/base/nsGlobalWindow.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/StructuredClone.cpp
dom/bindings/test/TestBindingHeader.h
dom/canvas/ImageData.cpp
dom/canvas/ImageData.h
dom/canvas/TextMetrics.h
dom/canvas/WebGLActiveInfo.cpp
dom/canvas/WebGLActiveInfo.h
dom/canvas/WebGLShaderPrecisionFormat.cpp
dom/canvas/WebGLShaderPrecisionFormat.h
dom/canvas/WebGLUniformLocation.cpp
dom/canvas/WebGLUniformLocation.h
dom/datastore/DataStoreCursor.cpp
dom/datastore/DataStoreCursor.h
dom/encoding/TextDecoder.h
dom/encoding/TextEncoder.h
dom/html/TimeRanges.cpp
dom/html/TimeRanges.h
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBKeyRange.h
dom/vr/VRDevice.cpp
dom/vr/VRDevice.h
dom/workers/DataStoreCursor.cpp
dom/workers/DataStoreCursor.h
dom/workers/FileReaderSync.cpp
dom/workers/FileReaderSync.h
dom/workers/URL.cpp
dom/workers/URL.h
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerScope.cpp
dom/workers/WorkerScope.h
dom/xslt/xpath/XPathEvaluator.cpp
dom/xslt/xpath/XPathEvaluator.h
dom/xslt/xpath/XPathExpression.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
--- a/dom/base/AnonymousContent.cpp
+++ b/dom/base/AnonymousContent.cpp
@@ -124,16 +124,17 @@ AnonymousContent::GetElementById(const n
     nsIAtom* id = kid->AsElement()->GetID();
     if (id && id == elementId) {
       return kid->AsElement();
     }
   }
   return nullptr;
 }
 
-JSObject*
-AnonymousContent::WrapObject(JSContext* aCx)
+bool
+AnonymousContent::WrapObject(JSContext* aCx,
+                             JS::MutableHandle<JSObject*> aReflector)
 {
-  return AnonymousContentBinding::Wrap(aCx, this);
+  return AnonymousContentBinding::Wrap(aCx, this, aReflector);
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/base/AnonymousContent.h
+++ b/dom/base/AnonymousContent.h
@@ -22,17 +22,17 @@ class AnonymousContent MOZ_FINAL
 public:
   // Ref counting and cycle collection
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnonymousContent)
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnonymousContent)
 
   explicit AnonymousContent(Element* aContentNode);
   nsCOMPtr<Element> GetContentNode();
   void SetContentNode(Element* aContentNode);
-  JSObject* WrapObject(JSContext* aCx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   // WebIDL methods
   void SetTextContentForElement(const nsAString& aElementId,
                                 const nsAString& aText,
                                 ErrorResult& aRv);
 
   void GetTextContentForElement(const nsAString& aElementId,
                                 DOMString& aText,
--- a/dom/base/NodeIterator.cpp
+++ b/dom/base/NodeIterator.cpp
@@ -283,16 +283,16 @@ void NodeIterator::ContentRemoved(nsIDoc
                                   nsIContent *aPreviousSibling)
 {
     nsINode *container = NODE_FROM(aContainer, aDocument);
 
     mPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
     mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
 }
 
-JSObject*
-NodeIterator::WrapObject(JSContext *cx)
+bool
+NodeIterator::WrapObject(JSContext *cx, JS::MutableHandle<JSObject*> aReflector)
 {
-    return NodeIteratorBinding::Wrap(cx, this);
+    return NodeIteratorBinding::Wrap(cx, this, aReflector);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/NodeIterator.h
+++ b/dom/base/NodeIterator.h
@@ -64,17 +64,17 @@ public:
         return NextOrPrevNode(&NodePointer::MoveToNext, aResult);
     }
     already_AddRefed<nsINode> PreviousNode(ErrorResult& aResult)
     {
         return NextOrPrevNode(&NodePointer::MoveToPrevious, aResult);
     }
     // The XPCOM Detach() is fine for our purposes
 
-    JSObject* WrapObject(JSContext *cx);
+    bool WrapObject(JSContext *cx, JS::MutableHandle<JSObject*> aReflector);
 
 private:
     virtual ~NodeIterator();
 
     struct NodePointer {
         NodePointer() : mNode(nullptr) {}
         NodePointer(nsINode *aNode, bool aBeforeNode);
 
--- a/dom/base/TreeWalker.cpp
+++ b/dom/base/TreeWalker.cpp
@@ -445,16 +445,16 @@ TreeWalker::NextSiblingInternal(bool aRe
             return nullptr;
         }
         if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
             return nullptr;
         }
     }
 }
 
-JSObject*
-TreeWalker::WrapObject(JSContext *cx)
+bool
+TreeWalker::WrapObject(JSContext *aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-    return TreeWalkerBinding::Wrap(cx, this);
+    return TreeWalkerBinding::Wrap(aCx, this, aReflector);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/TreeWalker.h
+++ b/dom/base/TreeWalker.h
@@ -60,17 +60,17 @@ public:
     already_AddRefed<nsINode> ParentNode(ErrorResult& aResult);
     already_AddRefed<nsINode> FirstChild(ErrorResult& aResult);
     already_AddRefed<nsINode> LastChild(ErrorResult& aResult);
     already_AddRefed<nsINode> PreviousSibling(ErrorResult& aResult);
     already_AddRefed<nsINode> NextSibling(ErrorResult& aResult);
     already_AddRefed<nsINode> PreviousNode(ErrorResult& aResult);
     already_AddRefed<nsINode> NextNode(ErrorResult& aResult);
 
-    JSObject* WrapObject(JSContext *cx);
+    bool WrapObject(JSContext *aCx, JS::MutableHandle<JSObject*> aReflector);
 
 private:
     nsCOMPtr<nsINode> mCurrentNode;
 
     /*
      * Implements FirstChild and LastChild which only vary in which direction
      * they search.
      * @param aReversed Controls whether we search forwards or backwards
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -41,20 +41,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 URL::URL(nsIURI* aURI)
   : mURI(aURI)
 {
 }
 
-JSObject*
-URL::WrapObject(JSContext* aCx)
+bool
+URL::WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-  return URLBinding::Wrap(aCx, this);
+  return URLBinding::Wrap(aCx, this, aReflector);
 }
 
 /* static */ already_AddRefed<URL>
 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
                  URL& aBase, ErrorResult& aRv)
 {
   nsresult rv;
   nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -38,18 +38,18 @@ class URL MOZ_FINAL : public URLSearchPa
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(URL)
 
   explicit URL(nsIURI* aURI);
 
   // WebIDL methods
-  JSObject*
-  WrapObject(JSContext* aCx);
+  bool
+  WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               URL& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               const nsAString& aBase, ErrorResult& aRv);
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2294,19 +2294,19 @@ CreateNativeGlobalForInner(JSContext* aC
   }
 
   // Determine if we need the Components object.
   bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
                         TreatAsRemoteXUL(aPrincipal);
   uint32_t flags = needComponents ? 0 : nsIXPConnect::OMIT_COMPONENTS_OBJECT;
   flags |= nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK;
 
-  aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
-                                  nsJSPrincipals::get(aPrincipal), false));
-  if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
+  if (!WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
+                           nsJSPrincipals::get(aPrincipal), false, aGlobal) ||
+      !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
     return NS_ERROR_FAILURE;
   }
 
   MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information
   xpc::SetLocationForGlobal(aGlobal, aURI);
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1014,21 +1014,19 @@ WrapNewBindingNonWrapperCachedObject(JSC
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
       if (!scope)
         return false;
       ac.emplace(cx, scope);
     }
 
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
-    obj = value->WrapObject(cx);
-  }
-
-  if (!obj) {
-    return false;
+    if (!value->WrapObject(cx, &obj)) {
+      return false;
+    }
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
   rval.set(JS::ObjectValue(*obj));
   return JS_WrapValue(cx, rval);
 }
 
@@ -1062,24 +1060,21 @@ WrapNewBindingNonWrapperCachedObject(JSC
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
       if (!scope)
         return false;
       ac.emplace(cx, scope);
     }
 
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
-    obj = value->WrapObject(cx);
-    if (obj) {
-      value.forget();
+    if (!value->WrapObject(cx, &obj)) {
+      return false;
     }
-  }
-
-  if (!obj) {
-    return false;
+
+    value.forget();
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
   rval.set(JS::ObjectValue(*obj));
   return JS_WrapValue(cx, rval);
 }
 
@@ -2762,67 +2757,65 @@ ToSupportsIsOnPrimaryInheritanceChain(T*
 // the BindingJSObjectCreator object is destroyed and ForgetObject() was never
 // called on it then the JSObject's slot holding the native will be set to
 // undefined, and for a refcounted native the strong reference will be released.
 template<class T>
 class MOZ_STACK_CLASS BindingJSObjectCreator
 {
 public:
   explicit BindingJSObjectCreator(JSContext* aCx)
-    : mObject(aCx)
+    : mReflector(aCx)
   {
   }
 
   ~BindingJSObjectCreator()
   {
-    if (mObject) {
-      js::SetReservedOrProxyPrivateSlot(mObject, DOM_OBJECT_SLOT,
+    if (mReflector) {
+      js::SetReservedOrProxyPrivateSlot(mReflector, DOM_OBJECT_SLOT,
                                         JS::UndefinedValue());
     }
   }
 
-  JS::Rooted<JSObject*>&
+  void
   CreateProxyObject(JSContext* aCx, const js::Class* aClass,
                     const DOMProxyHandler* aHandler,
                     JS::Handle<JSObject*> aProto,
-                    JS::Handle<JSObject*> aParent, T* aNative)
+                    JS::Handle<JSObject*> aParent, T* aNative,
+                    JS::MutableHandle<JSObject*> aReflector)
   {
     js::ProxyOptions options;
     options.setClass(aClass);
     JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
-    mObject = js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
-                                 aParent, options);
-    if (mObject) {
+    aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
+                                      aParent, options));
+    if (aReflector) {
       mNative = aNative;
+      mReflector = aReflector;
     }
-    return mObject;
   }
 
-  JS::Rooted<JSObject*>&
+  void
   CreateObject(JSContext* aCx, const JSClass* aClass,
                JS::Handle<JSObject*> aProto, JS::Handle<JSObject*> aParent,
-               T* aNative)
+               T* aNative, JS::MutableHandle<JSObject*> aReflector)
   {
-    mObject = JS_NewObject(aCx, aClass, aProto, aParent);
-    if (mObject) {
-      js::SetReservedSlot(mObject, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
+    aReflector.set(JS_NewObject(aCx, aClass, aProto, aParent));
+    if (aReflector) {
+      js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
       mNative = aNative;
+      mReflector = aReflector;
     }
-    return mObject;
   }
 
-  JSObject*
-  ForgetObject()
+  void
+  InitializationSucceeded()
   {
     void* dummy;
     mNative.forget(&dummy);
-
-    JSObject* obj = mObject;
-    mObject = nullptr;
-    return obj;
+    mReflector = nullptr;
   }
 
 private:
   struct OwnedNative
   {
     // Make sure the native objects inherit from NonRefcountedDOMObject so
     // that we log their ctor and dtor.
     static_assert(IsBaseOf<NonRefcountedDOMObject, T>::value,
@@ -2838,17 +2831,17 @@ private:
     // This signature sucks, but it's the only one that will make a nsRefPtr
     // just forget about its pointer without warning.
     void
     forget(void**)
     {
     }
   };
 
-  JS::Rooted<JSObject*> mObject;
+  JS::Rooted<JSObject*> mReflector;
   typename Conditional<IsRefcounted<T>::value, nsRefPtr<T>, OwnedNative>::Type mNative;
 };
 
 template<class T,
          bool isISupports=IsBaseOf<nsISupports, T>::value>
 class DeferredFinalizer
 {
   typedef typename Conditional<IsRefcounted<T>::value,
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3059,37 +3059,35 @@ class CGConstructorEnabled(CGAbstractMet
 def CreateBindingJSObject(descriptor, properties):
     objDecl = "BindingJSObjectCreator<%s> creator(aCx);\n" % descriptor.nativeType
 
     # We don't always need to root obj, but there are a variety
     # of cases where we do, so for simplicity, just always root it.
     if descriptor.proxy:
         create = dedent(
             """
-            const JS::Rooted<JSObject*>& obj =
-              creator.CreateProxyObject(aCx, &Class.mBase, DOMProxyHandler::getInstance(),
-                                        proto, global, aObject);
-            if (!obj) {
-              return nullptr;
+            creator.CreateProxyObject(aCx, &Class.mBase, DOMProxyHandler::getInstance(),
+                                      proto, global, aObject, aReflector);
+            if (!aReflector) {
+              return false;
             }
 
             """)
         if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
             create += dedent("""
-                js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO,
+                js::SetProxyExtra(aReflector, JSPROXYSLOT_EXPANDO,
                                   JS::PrivateValue(&aObject->mExpandoAndGeneration));
 
                 """)
     else:
         create = dedent(
             """
-            const JS::Rooted<JSObject*>& obj =
-              creator.CreateObject(aCx, Class.ToJSClass(), proto, global, aObject);
-            if (!obj) {
-              return nullptr;
+            creator.CreateObject(aCx, Class.ToJSClass(), proto, global, aObject, aReflector);
+            if (!aReflector) {
+              return false;
             }
             """)
     return objDecl + create
 
 
 def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
     """
     properties is a PropertyArrays instance
@@ -3155,17 +3153,17 @@ def InitUnforgeableProperties(descriptor
         return ""
 
     if descriptor.proxy:
         unforgeableProperties = CGGeneric(
             "// Unforgeable properties on proxy-based bindings are stored in an object held\n"
             "// by the interface prototype object.\n")
     else:
         unforgeableProperties = CGWrapper(
-            InitUnforgeablePropertiesOnObject(descriptor, "obj", properties, "nullptr"),
+            InitUnforgeablePropertiesOnObject(descriptor, "aReflector", properties, "false"),
             pre=(
                 "// Important: do unforgeable property setup after we have handed\n"
                 "// over ownership of the C++ object to obj as needed, so that if\n"
                 "// we fail and it ends up GCed it won't have problems in the\n"
                 "// finalizer trying to drop its ownership of the C++ object.\n"))
     return CGWrapper(unforgeableProperties, pre="\n").define()
 
 
@@ -3193,73 +3191,72 @@ def InitMemberSlots(descriptor, wrapperC
     ClearWrapper.
     """
     if not descriptor.interface.hasMembersInSlots():
         return ""
     if wrapperCache:
         clearWrapper = "  aCache->ClearWrapper();\n"
     else:
         clearWrapper = ""
-    return ("if (!UpdateMemberSlots(aCx, obj, aObject)) {\n"
+    return ("if (!UpdateMemberSlots(aCx, aReflector, aObject)) {\n"
             "%s"
-            "  return nullptr;\n"
+            "  return false;\n"
             "}\n" % clearWrapper)
 
 
 class CGWrapWithCacheMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a given native that implements nsWrapperCache.
 
     properties should be a PropertyArrays instance.
     """
     def __init__(self, descriptor, properties):
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
                 Argument(descriptor.nativeType + '*', 'aObject'),
-                Argument('nsWrapperCache*', 'aCache')]
-        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
+                Argument('nsWrapperCache*', 'aCache'),
+                Argument('JS::MutableHandle<JSObject*>', 'aReflector')]
+        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'bool', args)
         self.properties = properties
 
     def definition_body(self):
         return fill(
             """
             $*{assertion}
 
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
             JS::Rooted<JSObject*> parent(aCx, WrapNativeParent(aCx, aObject->GetParentObject()));
             if (!parent) {
-              return nullptr;
+              return false;
             }
 
             // That might have ended up wrapping us already, due to the wonders
-            // of XBL.  Check for that, and bail out as needed.  Scope so we don't
-            // collide with the "obj" we declare in CreateBindingJSObject.
-            {
-              JSObject* obj = aCache->GetWrapper();
-              if (obj) {
-                return obj;
-              }
+            // of XBL.  Check for that, and bail out as needed.
+            aReflector.set(aCache->GetWrapper());
+            if (aReflector) {
+              return true;
             }
 
             JSAutoCompartment ac(aCx, parent);
             JS::Rooted<JSObject*> global(aCx, js::GetGlobalForObjectCrossCompartment(parent));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
-              return nullptr;
+              return false;
             }
 
             $*{createObject}
 
             $*{unforgeable}
 
-            aCache->SetWrapper(obj);
+            aCache->SetWrapper(aReflector);
             $*{slots}
-            return creator.ForgetObject();
+            creator.InitializationSucceeded();
+            return true;
             """,
             assertion=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
             slots=InitMemberSlots(self.descriptor, True))
 
 
 class CGWrapMethod(CGAbstractMethod):
@@ -3267,51 +3264,56 @@ class CGWrapMethod(CGAbstractMethod):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
                 Argument('T*', 'aObject')]
         CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args,
                                   inline=True, templateArgs=["class T"])
 
     def definition_body(self):
-        return "return Wrap(aCx, aObject, aObject);\n"
+        return dedent("""
+            JS::Rooted<JSObject*> reflector(aCx);
+            return Wrap(aCx, aObject, aObject, &reflector) ? reflector.get() : nullptr;
+            """)
 
 
 class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a given native that does not implement
     nsWrapperCache.
 
     properties should be a PropertyArrays instance.
     """
     def __init__(self, descriptor, properties):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
-                Argument(descriptor.nativeType + '*', 'aObject')]
-        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
+                Argument(descriptor.nativeType + '*', 'aObject'),
+                Argument('JS::MutableHandle<JSObject*>', 'aReflector')]
+        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'bool', args)
         self.properties = properties
 
     def definition_body(self):
         return fill(
             """
             $*{assertions}
 
             JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
-              return nullptr;
+              return false;
             }
 
             $*{createObject}
 
             $*{unforgeable}
 
             $*{slots}
-            return creator.ForgetObject();
+            creator.InitializationSucceeded();
+            return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
             slots=InitMemberSlots(self.descriptor, False))
 
 
 class CGWrapGlobalMethod(CGAbstractMethod):
@@ -3323,70 +3325,70 @@ class CGWrapGlobalMethod(CGAbstractMetho
     """
     def __init__(self, descriptor, properties):
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
                 Argument(descriptor.nativeType + '*', 'aObject'),
                 Argument('nsWrapperCache*', 'aCache'),
                 Argument('JS::CompartmentOptions&', 'aOptions'),
                 Argument('JSPrincipals*', 'aPrincipal'),
-                Argument('bool', 'aInitStandardClasses')]
-        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
+                Argument('bool', 'aInitStandardClasses'),
+                Argument('JS::MutableHandle<JSObject*>', 'aReflector')]
+        CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'bool', args)
         self.descriptor = descriptor
         self.properties = properties
 
     def definition_body(self):
         if self.properties.hasNonChromeOnly():
             properties = "GlobalPropertiesAreOwn() ? &sNativeProperties : nullptr"
         else:
             properties = "nullptr"
         if self.properties.hasChromeOnly():
             chromeProperties = "GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
         else:
             chromeProperties = "nullptr"
 
         if self.descriptor.workers:
             fireOnNewGlobal = """// XXXkhuey can't do this yet until workers can lazy resolve.
-// JS_FireOnNewGlobalObject(aCx, obj);
+// JS_FireOnNewGlobalObject(aCx, aReflector);
 """
         else:
             fireOnNewGlobal = ""
 
         return fill(
             """
             $*{assertions}
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
-            JS::Rooted<JSObject*> obj(aCx);
             CreateGlobal<${nativeType}, GetProtoObjectHandle>(aCx,
                                              aObject,
                                              aCache,
                                              Class.ToJSClass(),
                                              aOptions,
                                              aPrincipal,
                                              aInitStandardClasses,
-                                             &obj);
-            if (!obj) {
-              return nullptr;
-            }
-
-            // obj is a new global, so has a new compartment.  Enter it
+                                             aReflector);
+            if (!aReflector) {
+              return false;
+            }
+
+            // aReflector is a new global, so has a new compartment.  Enter it
             // before doing anything with it.
-            JSAutoCompartment ac(aCx, obj);
-
-            if (!DefineProperties(aCx, obj, ${properties}, ${chromeProperties})) {
-              return nullptr;
+            JSAutoCompartment ac(aCx, aReflector);
+
+            if (!DefineProperties(aCx, aReflector, ${properties}, ${chromeProperties})) {
+              return false;
             }
             $*{unforgeable}
 
             $*{slots}
             $*{fireOnNewGlobal}
 
-            return obj;
+            return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             nativeType=self.descriptor.nativeType,
             properties=properties,
             chromeProperties=chromeProperties,
             unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
             slots=InitMemberSlots(self.descriptor, True),
             fireOnNewGlobal=fireOnNewGlobal)
--- a/dom/bindings/StructuredClone.cpp
+++ b/dom/bindings/StructuredClone.cpp
@@ -27,17 +27,19 @@ ReadStructuredCloneImageData(JSContext* 
 
   // Protect the result from a moving GC in ~nsRefPtr.
   JS::Rooted<JSObject*> result(aCx);
   {
     // Construct the ImageData.
     nsRefPtr<ImageData> imageData = new ImageData(width, height,
                                                   dataArray.toObject());
     // Wrap it in a JS::Value.
-    result = imageData->WrapObject(aCx);
+    if (!imageData->WrapObject(aCx, &result)) {
+      return nullptr;
+    }
   }
   return result;
 }
 
 bool
 WriteStructuredCloneImageData(JSContext* aCx, JSStructuredCloneWriter* aWriter,
                               ImageData* aImageData)
 {
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -85,17 +85,17 @@ public:
 
 NS_DEFINE_STATIC_IID_ACCESSOR(TestExternalInterface, NS_TEST_EXTERNAL_INTERFACE_IID)
 
 class TestNonWrapperCacheInterface : public nsISupports
 {
 public:
   NS_DECL_ISUPPORTS
 
-  virtual JSObject* WrapObject(JSContext* cx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 };
 
 class OnlyForUseInConstructor : public nsISupports,
                                 public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
   // We need a GetParentObject to make binding codegen happy
--- a/dom/canvas/ImageData.cpp
+++ b/dom/canvas/ImageData.cpp
@@ -103,16 +103,16 @@ void
 ImageData::DropData()
 {
   if (mData) {
     mData = nullptr;
     mozilla::DropJSObjects(this);
   }
 }
 
-JSObject*
-ImageData::WrapObject(JSContext* cx)
+bool
+ImageData::WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-  return ImageDataBinding::Wrap(cx, this);
+  return ImageDataBinding::Wrap(aCx, this, aReflector);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/canvas/ImageData.h
+++ b/dom/canvas/ImageData.h
@@ -68,17 +68,17 @@ public:
     aData.set(GetDataObject());
   }
   JSObject* GetDataObject() const
   {
     JS::ExposeObjectToActiveJS(mData);
     return mData;
   }
 
-  JSObject* WrapObject(JSContext* cx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
 private:
   void HoldData();
   void DropData();
 
   ImageData() = delete;
 
   uint32_t mWidth, mHeight;
--- a/dom/canvas/TextMetrics.h
+++ b/dom/canvas/TextMetrics.h
@@ -25,19 +25,19 @@ public:
     MOZ_COUNT_DTOR(TextMetrics);
   }
 
   float Width() const
   {
     return width;
   }
 
-  JSObject* WrapObject(JSContext* aCx)
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
   {
-    return TextMetricsBinding::Wrap(aCx, this);
+    return TextMetricsBinding::Wrap(aCx, this, aReflector);
   }
 
 private:
   float width;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/canvas/WebGLActiveInfo.cpp
+++ b/dom/canvas/WebGLActiveInfo.cpp
@@ -6,15 +6,16 @@
 #include "WebGLActiveInfo.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 #include "WebGLTexture.h"
 
 namespace mozilla {
 
-JSObject*
-WebGLActiveInfo::WrapObject(JSContext* cx)
+bool
+WebGLActiveInfo::WrapObject(JSContext* aCx,
+                            JS::MutableHandle<JSObject*> aReflector)
 {
-    return dom::WebGLActiveInfoBinding::Wrap(cx, this);
+    return dom::WebGLActiveInfoBinding::Wrap(aCx, this, aReflector);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLActiveInfo.h
+++ b/dom/canvas/WebGLActiveInfo.h
@@ -30,17 +30,17 @@ public:
     GLenum Type() const {
         return mType;
     }
 
     void GetName(nsString& retval) const {
         retval = mName;
     }
 
-    JSObject* WrapObject(JSContext* cx);
+    bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
    NS_INLINE_DECL_REFCOUNTING(WebGLActiveInfo)
 
 private:
     // Private destructor, to discourage deletion outside of Release():
     ~WebGLActiveInfo()
     {
     }
--- a/dom/canvas/WebGLShaderPrecisionFormat.cpp
+++ b/dom/canvas/WebGLShaderPrecisionFormat.cpp
@@ -5,15 +5,16 @@
 
 #include "WebGLShaderPrecisionFormat.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-JSObject*
-WebGLShaderPrecisionFormat::WrapObject(JSContext* cx)
+bool
+WebGLShaderPrecisionFormat::WrapObject(JSContext* aCx,
+                                       JS::MutableHandle<JSObject*> aReflector)
 {
-    return dom::WebGLShaderPrecisionFormatBinding::Wrap(cx, this);
+    return dom::WebGLShaderPrecisionFormatBinding::Wrap(aCx, this, aReflector);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLShaderPrecisionFormat.h
+++ b/dom/canvas/WebGLShaderPrecisionFormat.h
@@ -19,17 +19,17 @@ public:
     WebGLShaderPrecisionFormat(WebGLContext* context, GLint rangeMin,
                                GLint rangeMax, GLint precision)
         : WebGLContextBoundObject(context)
         , mRangeMin(rangeMin)
         , mRangeMax(rangeMax)
         , mPrecision(precision)
     { }
 
-    JSObject* WrapObject(JSContext* cx);
+    bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
     // WebIDL WebGLShaderPrecisionFormat API
     GLint RangeMin() const {
         return mRangeMin;
     }
 
     GLint RangeMax() const {
         return mRangeMax;
--- a/dom/canvas/WebGLUniformLocation.cpp
+++ b/dom/canvas/WebGLUniformLocation.cpp
@@ -7,20 +7,21 @@
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 #include "WebGLProgram.h"
 #include "WebGLShader.h"
 
 namespace mozilla {
 
-JSObject*
-WebGLUniformLocation::WrapObject(JSContext* cx)
+bool
+WebGLUniformLocation::WrapObject(JSContext* aCx,
+                                 JS::MutableHandle<JSObject*> aReflector)
 {
-    return dom::WebGLUniformLocationBinding::Wrap(cx, this);
+    return dom::WebGLUniformLocationBinding::Wrap(aCx, this, aReflector);
 }
 
 WebGLUniformLocation::WebGLUniformLocation(WebGLContext* context,
                                            WebGLProgram* program,
                                            GLint location,
                                            const WebGLUniformInfo& info)
     : WebGLContextBoundObject(context)
     , mProgram(program)
--- a/dom/canvas/WebGLUniformLocation.h
+++ b/dom/canvas/WebGLUniformLocation.h
@@ -26,17 +26,17 @@ public:
 
     const WebGLUniformInfo& Info() const { return mInfo; }
 
     WebGLProgram* Program() const { return mProgram; }
     GLint Location() const { return mLocation; }
     uint32_t ProgramGeneration() const { return mProgramGeneration; }
     int ElementSize() const { return mElementSize; }
 
-    JSObject* WrapObject(JSContext* cx);
+    bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocation)
     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WebGLUniformLocation)
 
 protected:
     ~WebGLUniformLocation() { }
 
     // nsRefPtr, not WebGLRefPtr, so that we don't prevent the program from being explicitly deleted.
--- a/dom/datastore/DataStoreCursor.cpp
+++ b/dom/datastore/DataStoreCursor.cpp
@@ -24,20 +24,21 @@ NS_IMPL_CYCLE_COLLECTION(DataStoreCursor
 
 already_AddRefed<DataStoreCursor>
 DataStoreCursor::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
 {
   nsRefPtr<DataStoreCursor> cursor = new DataStoreCursor();
   return cursor.forget();
 }
 
-JSObject*
-DataStoreCursor::WrapObject(JSContext* aCx)
+bool
+DataStoreCursor::WrapObject(JSContext* aCx,
+                            JS::MutableHandle<JSObject*> aReflector)
 {
-  return DataStoreCursorBinding::Wrap(aCx, this);
+  return DataStoreCursorBinding::Wrap(aCx, this, aReflector);
 }
 
 already_AddRefed<DataStore>
 DataStoreCursor::GetStore(ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mCursor);
 
@@ -67,9 +68,9 @@ DataStoreCursor::SetDataStoreCursorImpl(
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mCursor);
 
   mCursor = &aCursor;
 }
 
 } //namespace dom
-} //namespace mozilla
\ No newline at end of file
+} //namespace mozilla
--- a/dom/datastore/DataStoreCursor.h
+++ b/dom/datastore/DataStoreCursor.h
@@ -28,17 +28,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DataStoreCursor)
 
   // WebIDL (internal functions)
 
   static already_AddRefed<DataStoreCursor> Constructor(GlobalObject& aGlobal,
                                                        ErrorResult& aRv);
 
-  JSObject* WrapObject(JSContext *aCx);
+  bool WrapObject(JSContext *aCx, JS::MutableHandle<JSObject*> aReflector);
 
   // WebIDL (public APIs)
 
   already_AddRefed<DataStore> GetStore(ErrorResult& aRv);
 
   already_AddRefed<Promise> Next(ErrorResult& aRv);
 
   void Close(ErrorResult& aRv);
@@ -51,9 +51,9 @@ public:
 private:
   ~DataStoreCursor() {}
   nsRefPtr<DataStoreCursorImpl> mCursor;
 };
 
 } //namespace dom
 } //namespace mozilla
 
-#endif
\ No newline at end of file
+#endif
--- a/dom/encoding/TextDecoder.h
+++ b/dom/encoding/TextDecoder.h
@@ -44,19 +44,19 @@ public:
     MOZ_COUNT_CTOR(TextDecoder);
   }
 
   ~TextDecoder()
   {
     MOZ_COUNT_DTOR(TextDecoder);
   }
 
-  JSObject* WrapObject(JSContext* aCx)
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
   {
-    return TextDecoderBinding::Wrap(aCx, this);
+    return TextDecoderBinding::Wrap(aCx, this, aReflector);
   }
 
   /**
    * Validates provided label and throws an exception if invalid label.
    *
    * @param aLabel       The encoding label (case insensitive) provided.
    * @param aFatal       indicates whether to throw an 'EncodingError'
    *                     exception or not when decoding.
--- a/dom/encoding/TextEncoder.h
+++ b/dom/encoding/TextEncoder.h
@@ -37,19 +37,19 @@ public:
   TextEncoder()
   {
   }
 
   virtual
   ~TextEncoder()
   {}
 
-  JSObject* WrapObject(JSContext* aCx)
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
   {
-    return TextEncoderBinding::Wrap(aCx, this);
+    return TextEncoderBinding::Wrap(aCx, this, aReflector);
   }
 
 protected:
 
   /**
    * Validates provided encoding and throws an exception if invalid encoding.
    * If no encoding is provided then mEncoding is default initialised to "utf-8".
    *
--- a/dom/html/TimeRanges.cpp
+++ b/dom/html/TimeRanges.cpp
@@ -161,16 +161,16 @@ TimeRanges::Find(double aTime, double aE
   for (index_type i = 0; i < mRanges.Length(); ++i) {
     if (aTime < mRanges[i].mEnd && (aTime + aError) >= mRanges[i].mStart) {
       return i;
     }
   }
   return NoIndex;
 }
 
-JSObject*
-TimeRanges::WrapObject(JSContext* aCx)
+bool
+TimeRanges::WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-  return TimeRangesBinding::Wrap(aCx, this);
+  return TimeRangesBinding::Wrap(aCx, this, aReflector);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/TimeRanges.h
+++ b/dom/html/TimeRanges.h
@@ -45,17 +45,17 @@ public:
   void Normalize(double aError = 0.0);
 
   // Mutate this TimeRange to be the union of this and aOtherRanges.
   void Union(const TimeRanges* aOtherRanges, double aError);
 
   // Mutate this TimeRange to be the intersection of this and aOtherRanges.
   void Intersection(const TimeRanges* aOtherRanges);
 
-  JSObject* WrapObject(JSContext* aCx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   uint32_t Length() const
   {
     return mRanges.Length();
   }
 
   virtual double Start(uint32_t aIndex, ErrorResult& aRv);
 
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -242,20 +242,20 @@ IDBKeyRange::DropJSObjects()
   mCachedLowerVal.setUndefined();
   mCachedUpperVal.setUndefined();
   mHaveCachedLowerVal = false;
   mHaveCachedUpperVal = false;
   mRooted = false;
   mozilla::DropJSObjects(this);
 }
 
-JSObject*
-IDBKeyRange::WrapObject(JSContext* aCx)
+bool
+IDBKeyRange::WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-  return IDBKeyRangeBinding::Wrap(aCx, this);
+  return IDBKeyRangeBinding::Wrap(aCx, this, aReflector);
 }
 
 void
 IDBKeyRange::GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                       ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
--- a/dom/indexedDB/IDBKeyRange.h
+++ b/dom/indexedDB/IDBKeyRange.h
@@ -135,18 +135,18 @@ public:
 
   nsresult
   BindToStatement(mozIStorageStatement* aStatement) const;
 
   void
   DropJSObjects();
 
   // WebIDL
-  JSObject*
-  WrapObject(JSContext* aCx);
+  bool
+  WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   nsISupports*
   GetParentObject() const
   {
     return mGlobal;
   }
 
   void
--- a/dom/vr/VRDevice.cpp
+++ b/dom/vr/VRDevice.cpp
@@ -30,20 +30,21 @@ VRFieldOfView::Constructor(const GlobalO
                            double aUpDegrees, double aRightDegrees,
                            double aDownDegrees, double aLeftDegrees,
                            ErrorResult& aRV)
 {
   return new VRFieldOfView(aUpDegrees, aRightDegrees, aDownDegrees,
                            aLeftDegrees);
 }
 
-JSObject*
-VRFieldOfView::WrapObject(JSContext* aCx)
+bool
+VRFieldOfView::WrapObject(JSContext* aCx,
+                          JS::MutableHandle<JSObject*> aReflector)
 {
-  return VRFieldOfViewBinding::Wrap(aCx, this);
+  return VRFieldOfViewBinding::Wrap(aCx, this, aReflector);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPositionState, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPositionState, Release)
 
 VRPositionState::VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
   : mParent(aParent)
--- a/dom/vr/VRDevice.h
+++ b/dom/vr/VRDevice.h
@@ -63,17 +63,17 @@ public:
               ErrorResult& aRv);
 
   static VRFieldOfView*
   Constructor(const GlobalObject& aGlobal,
               double aUpDegrees, double aRightDegrees,
               double aDownDegrees, double aLeftDegrees,
               ErrorResult& aRv);
 
-  JSObject* WrapObject(JSContext* aCx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   void SetUpDegrees(double aVal) { mUpDegrees = aVal; }
   void SetRightDegrees(double aVal) { mRightDegrees = aVal; }
   void SetDownDegrees(double aVal) { mDownDegrees = aVal; }
   void SetLeftDegrees(double aVal) { mLeftDegrees = aVal; }
 };
 
 class VRPositionState MOZ_FINAL : public nsWrapperCache
--- a/dom/workers/DataStoreCursor.cpp
+++ b/dom/workers/DataStoreCursor.cpp
@@ -35,20 +35,21 @@ already_AddRefed<WorkerDataStoreCursor>
 WorkerDataStoreCursor::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
 {
   // We don't allow Gecko to create WorkerDataStoreCursor through JS codes like
   // window.DataStoreCursor() on the worker, so disable this for now.
   NS_NOTREACHED("Cannot use the chrome constructor on the worker!");
   return nullptr;
 }
 
-JSObject*
-WorkerDataStoreCursor::WrapObject(JSContext* aCx)
+bool
+WorkerDataStoreCursor::WrapObject(JSContext* aCx,
+                                  JS::MutableHandle<JSObject*> aReflector)
 {
-  return DataStoreCursorBinding_workers::Wrap(aCx, this);
+  return DataStoreCursorBinding_workers::Wrap(aCx, this, aReflector);
 }
 
 // A WorkerMainThreadRunnable which holds a reference to DataStoreCursor.
 class DataStoreCursorRunnable : public WorkerMainThreadRunnable
 {
 protected:
   nsMainThreadPtrHandle<DataStoreCursor> mBackingCursor;
 
--- a/dom/workers/DataStoreCursor.h
+++ b/dom/workers/DataStoreCursor.h
@@ -30,17 +30,17 @@ public:
 
   explicit WorkerDataStoreCursor(WorkerDataStore* aWorkerStore);
 
   // WebIDL (internal functions)
 
   static already_AddRefed<WorkerDataStoreCursor> Constructor(GlobalObject& aGlobal,
                                                              ErrorResult& aRv);
 
-  JSObject* WrapObject(JSContext *aCx);
+  bool WrapObject(JSContext *aCx, JS::MutableHandle<JSObject*> aReflector);
 
   // WebIDL (public APIs)
 
   already_AddRefed<WorkerDataStore> GetStore(JSContext *aCx, ErrorResult& aRv);
 
   already_AddRefed<Promise> Next(JSContext *aCx, ErrorResult& aRv);
 
   void Close(JSContext *aCx, ErrorResult& aRv);
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -36,20 +36,21 @@ using mozilla::dom::GlobalObject;
 already_AddRefed<FileReaderSync>
 FileReaderSync::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
   nsRefPtr<FileReaderSync> frs = new FileReaderSync();
 
   return frs.forget();
 }
 
-JSObject*
-FileReaderSync::WrapObject(JSContext* aCx)
+bool
+FileReaderSync::WrapObject(JSContext* aCx,
+                           JS::MutableHandle<JSObject*> aReflector)
 {
-  return FileReaderSyncBinding_workers::Wrap(aCx, this);
+  return FileReaderSyncBinding_workers::Wrap(aCx, this, aReflector);
 }
 
 void
 FileReaderSync::ReadAsArrayBuffer(JSContext* aCx,
                                   JS::Handle<JSObject*> aScopeObj,
                                   File& aBlob,
                                   JS::MutableHandle<JSObject*> aRetval,
                                   ErrorResult& aRv)
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -36,17 +36,17 @@ private:
 
   nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
                          nsAString &aResult);
 
 public:
   static already_AddRefed<FileReaderSync>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
 
-  JSObject* WrapObject(JSContext* aCx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   void ReadAsArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aScopeObj,
                          File& aBlob, JS::MutableHandle<JSObject*> aRetval,
                          ErrorResult& aRv);
   void ReadAsBinaryString(File& aBlob, nsAString& aResult, ErrorResult& aRv);
   void ReadAsText(File& aBlob, const Optional<nsAString>& aEncoding,
                   nsAString& aResult, ErrorResult& aRv);
   void ReadAsDataURL(File& aBlob, nsAString& aResult, ErrorResult& aRv);
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -567,20 +567,20 @@ URL::~URL()
     mURLProxy = nullptr;
 
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_ERROR("Failed to dispatch teardown runnable!");
     }
   }
 }
 
-JSObject*
-URL::WrapObject(JSContext* aCx)
+bool
+URL::WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
 {
-  return URLBinding_workers::Wrap(aCx, this);
+  return URLBinding_workers::Wrap(aCx, this, aReflector);
 }
 
 void
 URL::GetHref(nsString& aHref, ErrorResult& aRv) const
 {
   nsRefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
                        mURLProxy);
--- a/dom/workers/URL.h
+++ b/dom/workers/URL.h
@@ -40,18 +40,18 @@ public:
 
   nsISupports*
   GetParentObject() const
   {
     // There's only one global on a worker, so we don't need to specify.
     return nullptr;
   }
 
-  JSObject*
-  WrapObject(JSContext* aCx);
+  bool
+  WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 
   // Methods for WebIDL
 
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               URL& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -6248,18 +6248,20 @@ WorkerPrivate::CreateGlobalScope(JSConte
   if (IsSharedWorker()) {
     globalScope = new SharedWorkerGlobalScope(this, SharedWorkerName());
   } else if (IsServiceWorker()) {
     globalScope = new ServiceWorkerGlobalScope(this, SharedWorkerName());
   } else {
     globalScope = new DedicatedWorkerGlobalScope(this);
   }
 
-  JS::Rooted<JSObject*> global(aCx, globalScope->WrapGlobalObject(aCx));
-  NS_ENSURE_TRUE(global, nullptr);
+  JS::Rooted<JSObject*> global(aCx);
+  if (!globalScope->WrapGlobalObject(aCx, &global)) {
+    return nullptr;
+  }
 
   JSAutoCompartment ac(aCx, global);
 
   if (!RegisterBindings(aCx, global)) {
     return nullptr;
   }
 
   mScope = globalScope.forget();
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -357,29 +357,30 @@ WorkerGlobalScope::GetIndexedDB(ErrorRes
   return indexedDB.forget();
 }
 
 DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
 : WorkerGlobalScope(aWorkerPrivate)
 {
 }
 
-JSObject*
-DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
+bool
+DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
+                                             JS::MutableHandle<JSObject*> aReflector)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
 
   JS::CompartmentOptions options;
   mWorkerPrivate->CopyJSCompartmentOptions(options);
 
   return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
                                                          options,
                                                          GetWorkerPrincipal(),
-                                                         true);
+                                                         true, aReflector);
 }
 
 void
 DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
                                         JS::Handle<JS::Value> aMessage,
                                         const Optional<Sequence<JS::Value>>& aTransferable,
                                         ErrorResult& aRv)
 {
@@ -388,28 +389,29 @@ DedicatedWorkerGlobalScope::PostMessage(
 }
 
 SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
                                                  const nsCString& aName)
 : WorkerGlobalScope(aWorkerPrivate), mName(aName)
 {
 }
 
-JSObject*
-SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
+bool
+SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
+                                          JS::MutableHandle<JSObject*> aReflector)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
 
   JS::CompartmentOptions options;
   mWorkerPrivate->CopyJSCompartmentOptions(options);
 
   return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
                                                       GetWorkerPrincipal(),
-                                                      true);
+                                                      true, aReflector);
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
                                    mClients)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope)
 NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope)
 
 NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
@@ -421,28 +423,29 @@ ServiceWorkerGlobalScope::ServiceWorkerG
     mScope(NS_ConvertUTF8toUTF16(aScope))
 {
 }
 
 ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope()
 {
 }
 
-JSObject*
-ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
+bool
+ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
+                                           JS::MutableHandle<JSObject*> aReflector)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
 
   JS::CompartmentOptions options;
   mWorkerPrivate->CopyJSCompartmentOptions(options);
 
   return ServiceWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
                                                        GetWorkerPrincipal(),
-                                                       true);
+                                                       true, aReflector);
 }
 
 ServiceWorkerClients*
 ServiceWorkerGlobalScope::Clients()
 {
   if (!mClients) {
     mClients = new ServiceWorkerClients(this);
   }
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -52,18 +52,18 @@ protected:
 
   explicit WorkerGlobalScope(WorkerPrivate* aWorkerPrivate);
   virtual ~WorkerGlobalScope();
 
 public:
   virtual JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
-  virtual JSObject*
-  WrapGlobalObject(JSContext* aCx) = 0;
+  virtual bool
+  WrapGlobalObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) = 0;
 
   virtual JSObject*
   GetGlobalJSObject(void) MOZ_OVERRIDE
   {
     return GetWrapper();
   }
 
   NS_DECL_ISUPPORTS_INHERITED
@@ -143,18 +143,19 @@ public:
 
 class DedicatedWorkerGlobalScope MOZ_FINAL : public WorkerGlobalScope
 {
   ~DedicatedWorkerGlobalScope() { }
 
 public:
   explicit DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate);
 
-  virtual JSObject*
-  WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
+  virtual bool
+  WrapGlobalObject(JSContext* aCx,
+                   JS::MutableHandle<JSObject*> aReflector) MOZ_OVERRIDE;
 
   void
   PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
               const Optional<Sequence<JS::Value>>& aTransferable,
               ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(message)
 };
@@ -164,18 +165,19 @@ class SharedWorkerGlobalScope MOZ_FINAL 
   const nsCString mName;
 
   ~SharedWorkerGlobalScope() { }
 
 public:
   SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
                           const nsCString& aName);
 
-  virtual JSObject*
-  WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
+  virtual bool
+  WrapGlobalObject(JSContext* aCx,
+                   JS::MutableHandle<JSObject*> aReflector) MOZ_OVERRIDE;
 
   void GetName(DOMString& aName) const
   {
     aName.AsAString() = NS_ConvertUTF8toUTF16(mName);
   }
 
   IMPL_EVENT_HANDLER(connect)
 };
@@ -189,18 +191,19 @@ class ServiceWorkerGlobalScope MOZ_FINAL
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope,
                                            WorkerGlobalScope)
 
   ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsACString& aScope);
 
-  virtual JSObject*
-  WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
+  virtual bool
+  WrapGlobalObject(JSContext* aCx,
+                   JS::MutableHandle<JSObject*> aReflector) MOZ_OVERRIDE;
 
   void
   GetScope(DOMString& aScope) const
   {
     aScope.AsAString() = mScope;
   }
 
   void
--- a/dom/xslt/xpath/XPathEvaluator.cpp
+++ b/dom/xslt/xpath/XPathEvaluator.cpp
@@ -153,20 +153,21 @@ XPathEvaluator::CreateExpression(const n
         }
 
         return nullptr;
     }
 
     return new XPathExpression(Move(expression), mRecycler, aDocument);
 }
 
-JSObject*
-XPathEvaluator::WrapObject(JSContext* aCx)
+bool
+XPathEvaluator::WrapObject(JSContext* aCx,
+                           JS::MutableHandle<JSObject*> aReflector)
 {
-    return dom::XPathEvaluatorBinding::Wrap(aCx, this);
+    return dom::XPathEvaluatorBinding::Wrap(aCx, this, aReflector);
 }
 
 /* static */
 already_AddRefed<XPathEvaluator>
 XPathEvaluator::Constructor(const GlobalObject& aGlobal,
                             ErrorResult& rv)
 {
     nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
--- a/dom/xslt/xpath/XPathEvaluator.h
+++ b/dom/xslt/xpath/XPathEvaluator.h
@@ -37,17 +37,17 @@ public:
     explicit XPathEvaluator(nsIDocument* aDocument = nullptr);
 
     NS_DECL_ISUPPORTS
 
     // nsIDOMXPathEvaluator interface
     NS_DECL_NSIDOMXPATHEVALUATOR
 
     // WebIDL API
-    JSObject* WrapObject(JSContext* aCx);
+    bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
     nsIDocument* GetParentObject()
     {
         nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
         return doc;
     }
     static already_AddRefed<XPathEvaluator>
         Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
     XPathExpression*
--- a/dom/xslt/xpath/XPathExpression.h
+++ b/dom/xslt/xpath/XPathExpression.h
@@ -29,19 +29,19 @@ class XPathResult;
  */
 class XPathExpression MOZ_FINAL : public NonRefcountedDOMObject
 {
 public:
     XPathExpression(nsAutoPtr<Expr>&& aExpression, txResultRecycler* aRecycler,
                     nsIDocument *aDocument);
     ~XPathExpression();
 
-    JSObject* WrapObject(JSContext* aCx)
+    bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector)
     {
-        return XPathExpressionBinding::Wrap(aCx, this);
+        return XPathExpressionBinding::Wrap(aCx, this, aReflector);
     }
 
     already_AddRefed<XPathResult>
         Evaluate(JSContext* aCx, nsINode& aContextNode, uint16_t aType,
                  JS::Handle<JSObject*> aInResult, ErrorResult& aRv)
     {
         return EvaluateWithContext(aCx, aContextNode, 1, 1, aType, aInResult,
                                    aRv);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -284,20 +284,21 @@ RTCStatsQuery::~RTCStatsQuery() {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 #endif
 
 NS_IMPL_ISUPPORTS0(PeerConnectionImpl)
 
 #ifdef MOZILLA_INTERNAL_API
-JSObject*
-PeerConnectionImpl::WrapObject(JSContext* aCx)
+bool
+PeerConnectionImpl::WrapObject(JSContext* aCx,
+                               JS::MutableHandle<JSObject*> aReflector)
 {
-  return PeerConnectionImplBinding::Wrap(aCx, this);
+  return PeerConnectionImplBinding::Wrap(aCx, this, aReflector);
 }
 #endif
 
 bool PCUuidGenerator::Generate(std::string* idp) {
   nsresult rv;
 
   if(!mGenerator) {
     mGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -246,17 +246,17 @@ public:
     kIncompatibleSessionDescription   = 6,
     kIncompatibleMediaStreamTrack     = 8,
     kInternalError                    = 9
   };
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
 #ifdef MOZILLA_INTERNAL_API
-  virtual JSObject* WrapObject(JSContext* cx);
+  bool WrapObject(JSContext* aCx, JS::MutableHandle<JSObject*> aReflector);
 #endif
 
   static already_AddRefed<PeerConnectionImpl>
       Constructor(const mozilla::dom::GlobalObject& aGlobal, ErrorResult& rv);
   static PeerConnectionImpl* CreatePeerConnection();
   static nsresult ConvertRTCConfiguration(const RTCConfiguration& aSrc,
                                           IceConfiguration *aDst);
   already_AddRefed<DOMMediaStream> MakeMediaStream(uint32_t aHint);