diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index a712e196782..15f8ac927b5 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -4245,8 +4245,9 @@ nsXPCComponents::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) return NS_ERROR_NOT_AVAILABLE; } -nsXPCComponents::nsXPCComponents() - : mInterfaces(nsnull), +nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope) + : mScope(aScope), + mInterfaces(nsnull), mInterfacesByID(nsnull), mClasses(nsnull), mClassesByID(nsnull), @@ -4256,6 +4257,7 @@ nsXPCComponents::nsXPCComponents() mConstructor(nsnull), mUtils(nsnull) { + MOZ_ASSERT(aScope, "aScope must not be null"); } nsXPCComponents::~nsXPCComponents() @@ -4434,7 +4436,7 @@ nsXPCComponents::AttachNewComponentsObject(XPCCallContext& ccx, if (!aGlobal) return false; - nsXPCComponents* components = new nsXPCComponents(); + nsXPCComponents* components = new nsXPCComponents(aScope); if (!components) return false; diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index 1a58273759b..1fbe13f9f3b 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -190,11 +190,15 @@ XPCWrappedNativeScope::IsDyingScope(XPCWrappedNativeScope *scope) void XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents) { - NS_IF_ADDREF(aComponents); - NS_IF_RELEASE(mComponents); mComponents = aComponents; } +nsXPCComponents* +XPCWrappedNativeScope::GetComponents() +{ + return mComponents; +} + // Dummy JS class to let wrappers w/o an xpc prototype share // scopes. By doing this we avoid allocating a new scope for every // wrapper on creation of the wrapper, and most wrappers won't need @@ -308,9 +312,14 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope() if (mContext) mContext->RemoveScope(this); + // This should not be necessary, since the Components object should die + // with the scope but just in case. + if (mComponents) + mComponents->mScope = nsnull; + // XXX we should assert that we are dead or that xpconnect has shutdown // XXX might not want to do this at xpconnect shutdown time??? - NS_IF_RELEASE(mComponents); + mComponents = nsnull; JSRuntime *rt = mRuntime->GetJSRuntime(); mGlobalJSObject.finalize(rt); diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 9b0733ded1f..d9fde002840 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -1610,6 +1610,7 @@ public: IsDyingScope(XPCWrappedNativeScope *scope); void SetComponents(nsXPCComponents* aComponents); + nsXPCComponents *GetComponents(); void SetGlobal(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative); static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; } @@ -1659,7 +1660,7 @@ private: Native2WrappedNativeMap* mWrappedNativeMap; ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap; ClassInfo2WrappedNativeProtoMap* mMainThreadWrappedNativeProtoMap; - nsXPCComponents* mComponents; + nsRefPtr mComponents; XPCWrappedNativeScope* mNext; // The JS global object for this scope. If non-null, this will be the // default parent for the XPCWrappedNatives that have us as the scope, @@ -3911,10 +3912,12 @@ public: virtual ~nsXPCComponents(); private: - nsXPCComponents(); + nsXPCComponents(XPCWrappedNativeScope* aScope); void ClearMembers(); private: + friend class XPCWrappedNativeScope; + XPCWrappedNativeScope* mScope; nsXPCComponents_Interfaces* mInterfaces; nsXPCComponents_InterfacesByID* mInterfacesByID; nsXPCComponents_Classes* mClasses;