Bug 761422, part 1 - Clone before we adjust XPC maps in ReparentWrapperIfFound. r=bholley a=lsblakk
authorAndrew McCreight <amccreight@mozilla.com>
Mon, 30 Jul 2012 21:01:59 -0700
changeset 100465 d5fe000f51bf2b70141d9c546fb08abad5d802a1
parent 100464 bc0b53d05e68fd338401ab48dbce7edf469b9a86
child 100466 c6e67e5626e29e1915ccc9089e50182acf58b88f
push id1252
push useramccreight@mozilla.com
push dateThu, 09 Aug 2012 20:19:28 +0000
treeherdermozilla-beta@757d9c0a8d0a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, lsblakk
bugs761422
milestone15.0
Bug 761422, part 1 - Clone before we adjust XPC maps in ReparentWrapperIfFound. r=bholley a=lsblakk
js/xpconnect/src/XPCWrappedNative.cpp
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -1559,20 +1559,45 @@ XPCWrappedNative::ReparentWrapperIfFound
                                                     oldProto->GetClassInfo(),
                                                     &ci, oldProto->GetOffsetsMasked());
             if (!newProto) {
                 return NS_ERROR_FAILURE;
             }
         }
 
         if (wrapper) {
-            Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
-            Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
+
+            // First, the clone of the reflector, get a copy of its
+            // properties and clone its expando chain. The only part that is
+            // dangerous here if we have to return early is that we must avoid
+            // ending up with two reflectors pointing to the same WN. Other than
+            // that, the objects we create will just go away if we return early.
+
+            JSObject *newobj = JS_CloneObject(ccx, flat,
+                                              newProto->GetJSProtoObject(),
+                                              aNewParent);
+            if (!newobj)
+                return NS_ERROR_FAILURE;
+
+            JSObject *propertyHolder =
+                JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
+            if (!propertyHolder)
+                return NS_ERROR_OUT_OF_MEMORY;
+            if (!JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
+                return NS_ERROR_FAILURE;
+
+            // Expandos from other compartments are attached to the target JS object.
+            // Copy them over, and let the old ones die a natural death.
+            SetExpandoChain(newobj, nsnull);
+            if (!XrayUtils::CloneExpandoChain(ccx, newobj, flat))
+                return NS_ERROR_FAILURE;
 
             {   // scoped lock
+                Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
+                Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
                 XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock());
 
                 oldMap->Remove(wrapper);
 
                 if (wrapper->HasProto())
                     wrapper->SetProto(newProto);
 
                 // If the wrapper has no scriptable or it has a non-shared
@@ -1595,33 +1620,16 @@ XPCWrappedNative::ReparentWrapperIfFound
                 }
 
                 NS_ASSERTION(!newMap->Find(wrapper->GetIdentityObject()),
                              "wrapper already in new scope!");
 
                 (void) newMap->Add(wrapper);
             }
 
-            JSObject *newobj = JS_CloneObject(ccx, flat,
-                                              newProto->GetJSProtoObject(),
-                                              aNewParent);
-            if (!newobj)
-                return NS_ERROR_FAILURE;
-
-            JSObject *propertyHolder =
-                JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
-            if (!propertyHolder || !JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
-                return NS_ERROR_OUT_OF_MEMORY;
-
-            // Expandos from other compartments are attached to the target JS object.
-            // Copy them over, and let the old ones die a natural death.
-            SetExpandoChain(newobj, nsnull);
-            if (!XrayUtils::CloneExpandoChain(ccx, newobj, flat))
-                return NS_ERROR_FAILURE;
-
             // Before proceeding, eagerly create any same-compartment security wrappers
             // that the object might have. This forces us to take the 'WithWrapper' path
             // while transplanting that handles this stuff correctly.
             {
                 JSAutoEnterCompartment innerAC;
                 if (!innerAC.enter(ccx, aOldScope->GetGlobalJSObject()) ||
                     !wrapper->GetSameCompartmentSecurityWrapper(ccx))
                     return NS_ERROR_FAILURE;