From 1a87ec52f156100d5e6c27957c7bca15f5908614 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Mon, 30 Jul 2012 21:01:59 -0700 Subject: [PATCH] Bug 761422, part 1 - Clone before we adjust XPC maps in ReparentWrapperIfFound. r=bholley --- js/xpconnect/src/XPCWrappedNative.cpp | 46 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 17cbbf4b3913..7c93472238ff 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -1540,10 +1540,35 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx, } 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, nullptr); + 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); @@ -1576,23 +1601,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx, (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, nullptr); - 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.