From 9811c6933619d60cade6a44c6b069b878d18b0fc Mon Sep 17 00:00:00 2001 From: "mrbkap%gmail.com" Date: Mon, 30 Jul 2007 22:39:53 +0000 Subject: [PATCH] Don't call FindInJSObjectScope on an object that's being finalized because its parent might have been finalized already. bug 389985, r+sr=jst --- .../xpconnect/src/XPCCrossOriginWrapper.cpp | 40 +++++++++++++------ js/src/xpconnect/src/xpcprivate.h | 3 ++ .../xpconnect/src/xpcwrappednativescope.cpp | 12 ++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp index daeecfb5d32..65b2980ab91 100644 --- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp +++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp @@ -91,7 +91,7 @@ JSExtendedClass sXPC_XOW_JSClass = { // JSClass (JSExtendedClass.base) initialization { "XPCCrossOriginWrapper", JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | - JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots), + JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1), XPC_XOW_AddProperty, XPC_XOW_DelProperty, XPC_XOW_GetProperty, XPC_XOW_SetProperty, XPC_XOW_Enumerate, (JSResolveOp)XPC_XOW_NewResolve, @@ -105,6 +105,17 @@ JSExtendedClass sXPC_XOW_JSClass = { XPC_XOW_Equality }; +// The slot that we stick our scope into. +// This is used in the finalizer to see if we actually need to remove +// ourselves from our scope's map. Because we cannot outlive our scope +// (the parent link ensures this), we know that, when we're being +// finalized, either our scope is still alive (i.e. we became garbage +// due to no more references) or it is being garbage collected right now. +// Therefore, we can look in gDyingScopes, and if our scope is there, +// then the map is about to be destroyed anyway, so we don't need to +// do anything. +static const int XPC_XOW_ScopeSlot = XPCWrapper::sNumSlots; + JS_STATIC_DLL_CALLBACK(JSBool) XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); @@ -432,7 +443,9 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp) if (!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sWrappedObjSlot, *vp) || !JS_SetReservedSlot(cx, outerObj, XPCWrapper::sResolvingSlot, - BOOLEAN_TO_JSVAL(JS_FALSE))) { + BOOLEAN_TO_JSVAL(JS_FALSE)) || + !JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot, + PRIVATE_TO_JSVAL(parentScope))) { return JS_FALSE; } @@ -712,20 +725,23 @@ XPC_XOW_Finalize(JSContext *cx, JSObject *obj) return; } - // Get our scope. Use the safe context in case cx has been deleted. - XPCCallContext ccx(NATIVE_CALLER); - if (!ccx.IsValid()) { + // Get our scope. + jsval scopeVal; + if (!JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &scopeVal)) { return; } - // Get our scope, using ourselves to find the right scope. - // It's OK if we're not intialized, we can be called pretty late. - XPCWrappedNativeScope *scope = - XPCWrappedNativeScope::FindInJSObjectScope(ccx, obj, JS_TRUE); - - if (scope) { - scope->GetWrapperMap()->Remove(wrappedObj); + // Now that we have our scope, see if it's going away. If it is, + // then our work here is going to be done when we destroy the scope + // entirely. + XPCWrappedNativeScope *scope = reinterpret_cast + (JSVAL_TO_PRIVATE(scopeVal)); + if (XPCWrappedNativeScope::IsDyingScope(scope)) { + return; } + + // Remove ourselves from the map. + scope->GetWrapperMap()->Remove(wrappedObj); } JS_STATIC_DLL_CALLBACK(JSBool) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e31f1103718..07822a8a56d 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -1177,6 +1177,9 @@ public: JSBool IsValid() const {return mRuntime != nsnull;} + static JSBool + IsDyingScope(XPCWrappedNativeScope *scope); + void SetComponents(nsXPCComponents* aComponents); void SetGlobal(XPCCallContext& ccx, JSObject* aGlobal); diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index 1adc1761a72..d711d178090 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -161,6 +161,18 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx, MOZ_COUNT_CTOR(XPCWrappedNativeScope); } +// static +JSBool +XPCWrappedNativeScope::IsDyingScope(XPCWrappedNativeScope *scope) +{ + for(XPCWrappedNativeScope *cur = gDyingScopes; cur; cur = cur->mNext) + { + if(scope == cur) + return JS_TRUE; + } + return JS_FALSE; +} + void XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents) {