Bug 1404107 - Refactor: Move some reparenting complexity into XPConnect. r=mrbkap, r=bz, a=ritu
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 05 Oct 2017 11:49:43 -0500
changeset 432447 68132ce4a0ed15bd6ab98e129c1a05a17d5a9417
parent 432446 e3697ba2690a5de980805437302a9e3afea19e19
child 432448 e316a95d1d60cd81c031be32a460167bc8a2cfd5
push id7955
push userryanvm@gmail.com
push dateThu, 12 Oct 2017 18:26:39 +0000
treeherdermozilla-beta@c8d3b27528f7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap, bz, ritu
bugs1404107
milestone57.0
Bug 1404107 - Refactor: Move some reparenting complexity into XPConnect. r=mrbkap, r=bz, a=ritu
dom/bindings/BindingUtils.cpp
js/xpconnect/src/xpcpublic.h
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2256,44 +2256,31 @@ ReparentWrapper(JSContext* aCx, JS::Hand
     if (!JS_CopyPropertiesFrom(aCx, propertyHolder, copyFrom)) {
       aError.StealExceptionFromJSContext(aCx);
       return;
     }
   } else {
     propertyHolder = nullptr;
   }
 
-  // Grab a reference to the chain of objects that carry aObj's Xray expando
-  // properties (from all compartments). Transplanting will blow this away;
-  // we'll restore it manually afterwards.
-  JS::Rooted<JSObject*> expandoChain(aCx, xpc::XrayUtils::GetExpandoChain(aObj));
-
   // We've set up |newobj|, so we make it own the native by setting its reserved
   // slot and nulling out the reserved slot of |obj|.
   //
   // NB: It's important to do this _after_ copying the properties to
   // propertyHolder. Otherwise, an object with |foo.x === foo| will
   // crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
   js::SetReservedSlot(newobj, DOM_OBJECT_SLOT,
                       js::GetReservedSlot(aObj, DOM_OBJECT_SLOT));
   js::SetReservedSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
 
-  aObj = xpc::TransplantObject(aCx, aObj, newobj);
+  aObj = xpc::TransplantObjectRetainingXrayExpandos(aCx, aObj, newobj);
   if (!aObj) {
     MOZ_CRASH();
   }
 
-  // Copy Xray expando properties to the new wrapper.
-  if (!xpc::XrayUtils::CloneExpandoChain(aCx, aObj, expandoChain)) {
-    // Failure here means some expandos were not copied over. The object graph
-    // and the Xray machinery are left in a consistent state, but mysteriously
-    // losing these expandos is too weird to allow.
-    MOZ_CRASH();
-  }
-
   nsWrapperCache* cache = nullptr;
   CallQueryInterface(native, &cache);
   bool preserving = cache->PreservingWrapper();
   cache->SetPreservingWrapper(false);
   cache->SetWrapper(aObj);
   cache->SetPreservingWrapper(preserving);
 
   if (propertyHolder) {
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -72,16 +72,19 @@ private:
     // Whether the new-style domain policy when this compartment was created
     // forbids script execution.
     bool mScriptBlockedByPolicy;
 };
 
 JSObject*
 TransplantObject(JSContext* cx, JS::HandleObject origobj, JS::HandleObject target);
 
+JSObject*
+TransplantObjectRetainingXrayExpandos(JSContext* cx, JS::HandleObject origobj, JS::HandleObject target);
+
 bool IsContentXBLCompartment(JSCompartment* compartment);
 bool IsContentXBLScope(JS::Realm* realm);
 bool IsInContentXBLScope(JSObject* obj);
 
 // Return a raw XBL scope object corresponding to contentScope, which must
 // be an object whose global is a DOM window.
 //
 // The return value is not wrapped into cx->compartment, so be sure to enter
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -677,16 +677,38 @@ TransplantObject(JSContext* cx, JS::Hand
     if (!newIdentity || !oldWaiver)
        return newIdentity;
 
     if (!FixWaiverAfterTransplant(cx, oldWaiver, newIdentity))
         return nullptr;
     return newIdentity;
 }
 
+JSObject*
+TransplantObjectRetainingXrayExpandos(JSContext* cx, JS::HandleObject origobj,
+                                      JS::HandleObject target)
+{
+    // Save the chain of objects that carry origobj's Xray expando properties
+    // (from all compartments). TransplantObject will blow this away; we'll
+    // restore it manually afterwards.
+    RootedObject expandoChain(cx, GetXrayTraits(origobj)->getExpandoChain(origobj));
+
+    RootedObject newIdentity(cx, TransplantObject(cx, origobj, target));
+
+    // Copy Xray expando properties to the new wrapper.
+    if (!GetXrayTraits(newIdentity)->cloneExpandoChain(cx, newIdentity, expandoChain)) {
+        // Failure here means some expandos were not copied over. The object graph
+        // and the Xray machinery are left in a consistent state, but mysteriously
+        // losing these expandos is too weird to allow.
+        MOZ_CRASH();
+    }
+
+    return newIdentity;
+}
+
 nsIGlobalObject*
 NativeGlobal(JSObject* obj)
 {
     obj = js::GetGlobalForObjectCrossCompartment(obj);
 
     // Every global needs to hold a native as its private or be a
     // WebIDL object with an nsISupports DOM object.
     MOZ_ASSERT((GetObjectClass(obj)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1294,28 +1294,16 @@ EnsureXrayExpandoObject(JSContext* cx, J
 }
 
 const JSClass*
 XrayTraits::getExpandoClass(JSContext* cx, HandleObject target) const
 {
     return &DefaultXrayExpandoObjectClass;
 }
 
-namespace XrayUtils {
-JSObject* GetExpandoChain(HandleObject target)
-{
-    return GetXrayTraits(target)->getExpandoChain(target);
-}
-
-bool CloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject srcChain)
-{
-    return GetXrayTraits(dst)->cloneExpandoChain(cx, dst, srcChain);
-}
-} // namespace XrayUtils
-
 static JSObject*
 GetHolder(JSObject* obj)
 {
     return &js::GetProxyReservedSlot(obj, 0).toObject();
 }
 
 JSObject*
 XrayTraits::getHolder(JSObject* wrapper)
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -33,22 +33,16 @@ class XPCWrappedNative;
 
 namespace xpc {
 
 namespace XrayUtils {
 
 bool
 IsXPCWNHolderClass(const JSClass* clasp);
 
-JSObject*
-GetExpandoChain(JS::HandleObject target);
-
-bool
-CloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject srcChain);
-
 bool
 IsTransparent(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id);
 
 JSObject*
 GetNativePropertiesObject(JSContext* cx, JSObject* wrapper);
 
 bool
 HasNativeProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,