зеркало из https://github.com/mozilla/pjs.git
More fixes for bug 294893. When a XPCWrappedNative's scope is cleared, make sure we clear the scope for all of its XPCNativeWrappers as well. r+sr=bzbarsky@mit.edu, a=drivers
This commit is contained in:
Родитель
a68e2d534e
Коммит
a81b370e90
|
@ -723,8 +723,12 @@ XPC_NW_Finalize(JSContext *cx, JSObject *obj)
|
|||
XPCWrappedNative *wrappedNative =
|
||||
XPCNativeWrapper::GetWrappedNative(cx, obj);
|
||||
|
||||
if (wrappedNative && wrappedNative->GetNativeWrapper() == obj) {
|
||||
wrappedNative->SetNativeWrapper(nsnull);
|
||||
if (wrappedNative) {
|
||||
XPCJSRuntime *rt = wrappedNative->GetRuntime();
|
||||
|
||||
// scoped lock
|
||||
XPCAutoLock lock(rt->GetMapLock());
|
||||
rt->GetExplicitNativeWrapperMap()->Remove(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,6 +915,14 @@ XPCNativeWrapperCtor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
*rval = OBJECT_TO_JSVAL(wrapperObj);
|
||||
|
||||
{
|
||||
XPCJSRuntime *rt = wrappedNative->GetRuntime();
|
||||
|
||||
// scoped lock
|
||||
XPCAutoLock lock(rt->GetMapLock());
|
||||
rt->GetExplicitNativeWrapperMap()->Add(wrapperObj);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1099,3 +1111,45 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper)
|
|||
wrapper->SetNativeWrapper(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct WrapperAndCxHolder
|
||||
{
|
||||
XPCWrappedNative* wrapper;
|
||||
JSContext* cx;
|
||||
};
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
||||
ClearNativeWrapperScope(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
uint32 number, void *arg)
|
||||
{
|
||||
JSDHashEntryStub* entry = (JSDHashEntryStub*)hdr;
|
||||
WrapperAndCxHolder* d = (WrapperAndCxHolder*)arg;
|
||||
|
||||
if (d->wrapper->GetNativeWrapper() == (JSObject*)entry->key)
|
||||
{
|
||||
::JS_ClearScope(d->cx, (JSObject*)entry->key);
|
||||
}
|
||||
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
XPCNativeWrapper::ClearWrappedNativeScopes(JSContext* cx,
|
||||
XPCWrappedNative* wrapper)
|
||||
{
|
||||
JSObject *nativeWrapper = wrapper->GetNativeWrapper();
|
||||
|
||||
if (nativeWrapper) {
|
||||
::JS_ClearScope(cx, nativeWrapper);
|
||||
}
|
||||
|
||||
WrapperAndCxHolder d =
|
||||
{
|
||||
wrapper,
|
||||
cx
|
||||
};
|
||||
|
||||
wrapper->GetRuntime()->GetExplicitNativeWrapperMap()->
|
||||
Enumerate(ClearNativeWrapperScope, &d);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ public:
|
|||
return &sXPC_NW_JSClass.base;
|
||||
}
|
||||
|
||||
static void ClearWrappedNativeScopes(JSContext* cx,
|
||||
XPCWrappedNative* wrapper);
|
||||
|
||||
protected:
|
||||
static JSExtendedClass sXPC_NW_JSClass;
|
||||
};
|
||||
|
|
|
@ -79,6 +79,7 @@ class NativeSetMap;
|
|||
class IID2ThisTranslatorMap;
|
||||
class XPCNativeScriptableSharedMap;
|
||||
class XPCWrappedNativeProtoMap;
|
||||
class XPCNativeWrapperMap;
|
||||
|
||||
class nsXPCComponents;
|
||||
class nsXPCComponents_Interfaces;
|
||||
|
|
|
@ -744,6 +744,16 @@ XPCJSRuntime::~XPCJSRuntime()
|
|||
delete mDetachedWrappedNativeProtoMap;
|
||||
}
|
||||
|
||||
if(mExplicitNativeWrapperMap)
|
||||
{
|
||||
#ifdef XPC_DUMP_AT_SHUTDOWN
|
||||
uint32 count = mExplicitNativeWrapperMap->Count();
|
||||
if(count)
|
||||
printf("deleting XPCJSRuntime with %d live explicit XPCNativeWrapper\n", (int)count);
|
||||
#endif
|
||||
delete mExplicitNativeWrapperMap;
|
||||
}
|
||||
|
||||
// unwire the readable/JSString sharing magic
|
||||
XPCStringConvert::ShutdownDOMStringFinalizer();
|
||||
|
||||
|
@ -767,6 +777,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
|||
mNativeScriptableSharedMap(XPCNativeScriptableSharedMap::newMap(XPC_NATIVE_JSCLASS_MAP_SIZE)),
|
||||
mDyingWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DYING_NATIVE_PROTO_MAP_SIZE)),
|
||||
mDetachedWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DETACHED_NATIVE_PROTO_MAP_SIZE)),
|
||||
mExplicitNativeWrapperMap(XPCNativeWrapperMap::newMap(XPC_NATIVE_WRAPPER_MAP_SIZE)),
|
||||
mMapLock(XPCAutoLock::NewLock("XPCJSRuntime::mMapLock")),
|
||||
mThreadRunningGC(nsnull),
|
||||
mWrappedJSToReleaseArray(),
|
||||
|
@ -825,6 +836,7 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect,
|
|||
self->GetThisTranslatorMap() &&
|
||||
self->GetNativeScriptableSharedMap() &&
|
||||
self->GetDyingWrappedNativeProtoMap() &&
|
||||
self->GetExplicitNativeWrapperMap() &&
|
||||
self->GetMapLock())
|
||||
{
|
||||
return self;
|
||||
|
@ -854,7 +866,7 @@ XPCJSRuntime::GetXPCContext(JSContext* cx)
|
|||
|
||||
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
||||
SweepContextsCB(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
uint32 number, void *arg)
|
||||
uint32 number, void *arg)
|
||||
{
|
||||
XPCContext* xpcc = ((JSContext2XPCContextMap::Entry*)hdr)->value;
|
||||
if(xpcc->IsMarked())
|
||||
|
|
|
@ -634,3 +634,29 @@ XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()
|
|||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement XPCNativeWrapperMap...
|
||||
|
||||
// static
|
||||
XPCNativeWrapperMap*
|
||||
XPCNativeWrapperMap::newMap(int size)
|
||||
{
|
||||
XPCNativeWrapperMap* map = new XPCNativeWrapperMap(size);
|
||||
if(map && map->mTable)
|
||||
return map;
|
||||
delete map;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
XPCNativeWrapperMap::XPCNativeWrapperMap(int size)
|
||||
{
|
||||
mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
|
||||
sizeof(JSDHashEntryStub), size);
|
||||
}
|
||||
|
||||
XPCNativeWrapperMap::~XPCNativeWrapperMap()
|
||||
{
|
||||
if(mTable)
|
||||
JS_DHashTableDestroy(mTable);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -651,4 +651,40 @@ private:
|
|||
JSDHashTable *mTable;
|
||||
};
|
||||
|
||||
class XPCNativeWrapperMap
|
||||
{
|
||||
public:
|
||||
static XPCNativeWrapperMap* newMap(int size);
|
||||
|
||||
inline JSObject* Add(JSObject* nw)
|
||||
{
|
||||
NS_PRECONDITION(nw,"bad param");
|
||||
JSDHashEntryStub* entry = (JSDHashEntryStub*)
|
||||
JS_DHashTableOperate(mTable, nw, JS_DHASH_ADD);
|
||||
if(!entry)
|
||||
return nsnull;
|
||||
if(entry->key)
|
||||
return (JSObject*) entry->key;
|
||||
entry->key = nw;
|
||||
return nw;
|
||||
}
|
||||
|
||||
inline void Remove(JSObject* nw)
|
||||
{
|
||||
NS_PRECONDITION(nw,"bad param");
|
||||
JS_DHashTableOperate(mTable, nw, JS_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32 Count() {return mTable->entryCount;}
|
||||
inline uint32 Enumerate(JSDHashEnumerator f, void *arg)
|
||||
{return JS_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
~XPCNativeWrapperMap();
|
||||
private:
|
||||
XPCNativeWrapperMap(); // no implementation
|
||||
XPCNativeWrapperMap(int size);
|
||||
private:
|
||||
JSDHashTable *mTable;
|
||||
};
|
||||
|
||||
#endif /* xpcmaps_h___ */
|
||||
|
|
|
@ -208,6 +208,7 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper);
|
|||
#define XPC_NATIVE_SET_MAP_SIZE 64
|
||||
#define XPC_NATIVE_JSCLASS_MAP_SIZE 32
|
||||
#define XPC_THIS_TRANSLATOR_MAP_SIZE 8
|
||||
#define XPC_NATIVE_WRAPPER_MAP_SIZE 16
|
||||
|
||||
/***************************************************************************/
|
||||
// data declarations...
|
||||
|
@ -520,6 +521,9 @@ public:
|
|||
XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
|
||||
{return mDetachedWrappedNativeProtoMap;}
|
||||
|
||||
XPCNativeWrapperMap* GetExplicitNativeWrapperMap() const
|
||||
{return mExplicitNativeWrapperMap;}
|
||||
|
||||
XPCLock* GetMapLock() const {return mMapLock;}
|
||||
|
||||
XPCContext* GetXPCContext(JSContext* cx);
|
||||
|
@ -635,6 +639,7 @@ private:
|
|||
XPCNativeScriptableSharedMap* mNativeScriptableSharedMap;
|
||||
XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
|
||||
XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
|
||||
XPCNativeWrapperMap* mExplicitNativeWrapperMap;
|
||||
XPCLock* mMapLock;
|
||||
PRThread* mThreadRunningGC;
|
||||
nsVoidArray mWrappedJSToReleaseArray;
|
||||
|
@ -1917,6 +1922,11 @@ public:
|
|||
{
|
||||
if(mScriptableInfo) mScriptableInfo->Mark();
|
||||
if(HasProto()) mMaybeProto->MarkBeforeJSFinalize(cx);
|
||||
if(mNativeWrapper)
|
||||
{
|
||||
JS_MarkGCThing(cx, mNativeWrapper,
|
||||
"XPCWrappedNative::mNativeWrapper", nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -1149,10 +1149,7 @@ XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj)
|
|||
|
||||
if(wrapper && wrapper->IsValid())
|
||||
{
|
||||
JSObject *nativeWrapper = wrapper->GetNativeWrapper();
|
||||
|
||||
if(nativeWrapper)
|
||||
JS_ClearScope(cx, nativeWrapper);
|
||||
XPCNativeWrapper::ClearWrappedNativeScopes(cx, wrapper);
|
||||
}
|
||||
|
||||
js_ObjectOps.clear(cx, obj);
|
||||
|
|
Загрузка…
Ссылка в новой задаче