зеркало из https://github.com/mozilla/pjs.git
Remove deadlock hazard when reparenting, single-threaded DOM so don't worry (390551, r+sr=jst).
This commit is contained in:
Родитель
a28adbad1b
Коммит
801db38b0d
|
@ -1241,87 +1241,87 @@ nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext,
|
|||
if(!newScope)
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
// First, look through the old scope and find all of the wrappers that
|
||||
// we're going to move.
|
||||
nsVoidArray wrappersToMove;
|
||||
|
||||
{ // scoped lock
|
||||
XPCAutoLock lock(oldScope->GetRuntime()->GetMapLock());
|
||||
|
||||
// First, look through the old scope and find all of the wrappers that
|
||||
// we're going to move.
|
||||
|
||||
Native2WrappedNativeMap *map = oldScope->GetWrappedNativeMap();
|
||||
nsVoidArray wrappersToMove(map->Count());
|
||||
wrappersToMove.SizeTo(map->Count());
|
||||
map->Enumerate(MoveableWrapperFinder, &wrappersToMove);
|
||||
}
|
||||
|
||||
// Now that we have the wrappers, reparent them to the new scope.
|
||||
for(PRInt32 i = 0, stop = wrappersToMove.Count(); i < stop; ++i)
|
||||
// Now that we have the wrappers, reparent them to the new scope.
|
||||
for(PRInt32 i = 0, stop = wrappersToMove.Count(); i < stop; ++i)
|
||||
{
|
||||
// First, check to see if this wrapper really needs to be
|
||||
// reparented.
|
||||
|
||||
XPCWrappedNative *wrapper =
|
||||
static_cast<XPCWrappedNative *>(wrappersToMove[i]);
|
||||
nsISupports *identity = wrapper->GetIdentityObject();
|
||||
nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity));
|
||||
|
||||
// ClassInfo is implemented as singleton objects. If the identity
|
||||
// object here is the same object as returned by the QI, then it
|
||||
// is the singleton classinfo, so we don't need to reparent it.
|
||||
if(SameCOMIdentity(identity, info))
|
||||
info = nsnull;
|
||||
|
||||
if(!info)
|
||||
continue;
|
||||
|
||||
XPCNativeScriptableCreateInfo sciProto;
|
||||
XPCNativeScriptableCreateInfo sciWrapper;
|
||||
|
||||
nsresult rv =
|
||||
XPCWrappedNative::GatherScriptableCreateInfo(identity,
|
||||
info.get(),
|
||||
&sciProto,
|
||||
&sciWrapper);
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// If the wrapper doesn't want precreate, then we don't need to
|
||||
// worry about reparenting it.
|
||||
if(!sciWrapper.GetFlags().WantPreCreate())
|
||||
continue;
|
||||
|
||||
JSObject *newParent = aOldScope;
|
||||
rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope,
|
||||
&newParent);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(newParent != aOldScope)
|
||||
{
|
||||
// First, check to see if this wrapper really needs to be
|
||||
// reparented.
|
||||
// The wrapper returned a new parent. If the new parent is in
|
||||
// a different scope, then we need to reparent it, otherwise,
|
||||
// the old scope is fine.
|
||||
|
||||
XPCWrappedNative *wrapper =
|
||||
static_cast<XPCWrappedNative *>(wrappersToMove[i]);
|
||||
nsISupports *identity = wrapper->GetIdentityObject();
|
||||
nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity));
|
||||
|
||||
// ClassInfo is implemented as singleton objects. If the identity
|
||||
// object here is the same object as returned by the QI, then it
|
||||
// is the singleton classinfo, so we don't need to reparent it.
|
||||
if(SameCOMIdentity(identity, info))
|
||||
info = nsnull;
|
||||
|
||||
if(!info)
|
||||
XPCWrappedNativeScope *betterScope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
|
||||
if(betterScope == oldScope)
|
||||
continue;
|
||||
|
||||
XPCNativeScriptableCreateInfo sciProto;
|
||||
XPCNativeScriptableCreateInfo sciWrapper;
|
||||
|
||||
nsresult rv =
|
||||
XPCWrappedNative::GatherScriptableCreateInfo(identity,
|
||||
info.get(),
|
||||
&sciProto,
|
||||
&sciWrapper);
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// If the wrapper doesn't want precreate, then we don't need to
|
||||
// worry about reparenting it.
|
||||
if(!sciWrapper.GetFlags().WantPreCreate())
|
||||
continue;
|
||||
|
||||
JSObject *newParent = aOldScope;
|
||||
rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope,
|
||||
&newParent);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(newParent != aOldScope)
|
||||
{
|
||||
// The wrapper returned a new parent. If the new parent is in
|
||||
// a different scope, then we need to reparent it, otherwise,
|
||||
// the old scope is fine.
|
||||
|
||||
XPCWrappedNativeScope *betterScope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
|
||||
if(betterScope == oldScope)
|
||||
continue;
|
||||
|
||||
NS_ASSERTION(betterScope == newScope, "Weird scope returned");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The old scope still works for this wrapper.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now, reparent the wrapper, since we know that it wants to be
|
||||
// reparented.
|
||||
|
||||
nsRefPtr<XPCWrappedNative> junk;
|
||||
rv = XPCWrappedNative::ReparentWrapperIfFound(ccx, oldScope,
|
||||
newScope, newParent,
|
||||
wrapper->GetIdentityObject(),
|
||||
getter_AddRefs(junk));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(betterScope == newScope, "Weird scope returned");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The old scope still works for this wrapper.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now, reparent the wrapper, since we know that it wants to be
|
||||
// reparented.
|
||||
|
||||
nsRefPtr<XPCWrappedNative> junk;
|
||||
rv = XPCWrappedNative::ReparentWrapperIfFound(ccx, oldScope,
|
||||
newScope, newParent,
|
||||
wrapper->GetIdentityObject(),
|
||||
getter_AddRefs(junk));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
Загрузка…
Ссылка в новой задаче