зеркало из https://github.com/mozilla/pjs.git
Part 1 of fix for bug 379718 (using trace API for reference counts) and bug 386912 (cycle collector faults after tracing "JS object but unknown to the JS GC"). r=igor/jst, sr=jst, a=blocking1.9+/M9 (for bug 386912).
This commit is contained in:
Родитель
5c8cad31eb
Коммит
a76fba526b
|
@ -752,42 +752,6 @@ public:
|
||||||
*/
|
*/
|
||||||
static nsIContentPolicy *GetContentPolicy();
|
static nsIContentPolicy *GetContentPolicy();
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that whatever value *aPtr contains at any given moment is
|
|
||||||
* protected from JS GC until we remove the GC root. A call to this that
|
|
||||||
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
|
|
||||||
*/
|
|
||||||
static nsresult AddJSGCRoot(jsval* aPtr, const char* aName) {
|
|
||||||
return AddJSGCRoot((void*)aPtr, aName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that whatever object *aPtr is pointing to at any given moment is
|
|
||||||
* protected from JS GC until we remove the GC root. A call to this that
|
|
||||||
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
|
|
||||||
*/
|
|
||||||
static nsresult AddJSGCRoot(JSObject** aPtr, const char* aName) {
|
|
||||||
return AddJSGCRoot((void*)aPtr, aName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that whatever object *aPtr is pointing to at any given moment is
|
|
||||||
* protected from JS GC until we remove the GC root. A call to this that
|
|
||||||
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
|
|
||||||
*/
|
|
||||||
static nsresult AddJSGCRoot(void* aPtr, const char* aName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove aPtr as a JS GC root
|
|
||||||
*/
|
|
||||||
static nsresult RemoveJSGCRoot(jsval* aPtr) {
|
|
||||||
return RemoveJSGCRoot((void*)aPtr);
|
|
||||||
}
|
|
||||||
static nsresult RemoveJSGCRoot(JSObject** aPtr) {
|
|
||||||
return RemoveJSGCRoot((void*)aPtr);
|
|
||||||
}
|
|
||||||
static nsresult RemoveJSGCRoot(void* aPtr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick helper to determine whether there are any mutation listeners
|
* Quick helper to determine whether there are any mutation listeners
|
||||||
* of a given type that apply to this content or any of its ancestors.
|
* of a given type that apply to this content or any of its ancestors.
|
||||||
|
@ -1002,40 +966,73 @@ public:
|
||||||
*/
|
*/
|
||||||
static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
|
static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
|
||||||
|
|
||||||
static nsresult HoldScriptObject(PRUint32 aLangID, void *aObject);
|
/**
|
||||||
static nsresult DropScriptObject(PRUint32 aLangID, void *aObject);
|
* Keep script object aNewObject, held by aScriptObjectHolder, alive.
|
||||||
|
*
|
||||||
class ScriptObjectHolder
|
* NOTE: This currently only supports objects that hold script objects of one
|
||||||
|
* scripting language.
|
||||||
|
*
|
||||||
|
* @param aLangID script language ID of aNewObject
|
||||||
|
* @param aScriptObjectHolder the object that holds aNewObject
|
||||||
|
* @param aTracer the tracer for aScriptObject
|
||||||
|
* @param aNewObject the script object to hold
|
||||||
|
* @param aWasHoldingObjects whether aScriptObjectHolder was already holding
|
||||||
|
* script objects (ie. HoldScriptObject was called
|
||||||
|
* on it before, without a corresponding call to
|
||||||
|
* DropScriptObjects)
|
||||||
|
*/
|
||||||
|
static nsresult HoldScriptObject(PRUint32 aLangID, void* aScriptObjectHolder,
|
||||||
|
nsScriptObjectTracer* aTracer,
|
||||||
|
void* aNewObject, PRBool aWasHoldingObjects)
|
||||||
{
|
{
|
||||||
public:
|
if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||||
ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
|
return aWasHoldingObjects ? NS_OK :
|
||||||
mObject(nsnull)
|
HoldJSObjects(aScriptObjectHolder, aTracer);
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(ScriptObjectHolder);
|
|
||||||
}
|
}
|
||||||
~ScriptObjectHolder()
|
|
||||||
{
|
return HoldScriptObject(aLangID, aNewObject);
|
||||||
MOZ_COUNT_DTOR(ScriptObjectHolder);
|
}
|
||||||
if (mObject)
|
|
||||||
DropScriptObject(mLangID, mObject);
|
/**
|
||||||
|
* Drop any script objects that aScriptObjectHolder is holding.
|
||||||
|
*
|
||||||
|
* NOTE: This currently only supports objects that hold script objects of one
|
||||||
|
* scripting language.
|
||||||
|
*
|
||||||
|
* @param aLangID script language ID of the objects that
|
||||||
|
* @param aScriptObjectHolder the object that holds script object that we want
|
||||||
|
* to drop
|
||||||
|
* @param aTracer the tracer for aScriptObject
|
||||||
|
*/
|
||||||
|
static nsresult DropScriptObjects(PRUint32 aLangID, void* aScriptObjectHolder,
|
||||||
|
nsScriptObjectTracer* aTracer)
|
||||||
|
{
|
||||||
|
if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||||
|
return DropJSObjects(aScriptObjectHolder);
|
||||||
}
|
}
|
||||||
nsresult set(void *aObject)
|
|
||||||
{
|
aTracer->Trace(aScriptObjectHolder, DropScriptObject, nsnull);
|
||||||
NS_ASSERTION(aObject, "unexpected null object");
|
|
||||||
NS_ASSERTION(!mObject, "already have an object");
|
return NS_OK;
|
||||||
nsresult rv = HoldScriptObject(mLangID, aObject);
|
}
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
mObject = aObject;
|
/**
|
||||||
}
|
* Keep the JS objects held by aScriptObjectHolder alive.
|
||||||
return rv;
|
*
|
||||||
}
|
* @param aScriptObjectHolder the object that holds JS objects that we want to
|
||||||
void traverse(nsCycleCollectionTraversalCallback &cb)
|
* keep alive
|
||||||
{
|
* @param aTracer the tracer for aScriptObject
|
||||||
cb.NoteScriptChild(mLangID, mObject);
|
*/
|
||||||
}
|
static nsresult HoldJSObjects(void* aScriptObjectHolder,
|
||||||
PRUint32 mLangID;
|
nsScriptObjectTracer* aTracer);
|
||||||
void *mObject;
|
|
||||||
};
|
/**
|
||||||
|
* Drop the JS objects held by aScriptObjectHolder.
|
||||||
|
*
|
||||||
|
* @param aScriptObjectHolder the object that holds JS objects that we want to
|
||||||
|
* drop
|
||||||
|
*/
|
||||||
|
static nsresult DropJSObjects(void* aScriptObjectHolder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
|
* Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
|
||||||
|
@ -1122,6 +1119,10 @@ private:
|
||||||
|
|
||||||
static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
|
static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
|
||||||
|
|
||||||
|
static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
|
||||||
|
PR_STATIC_CALLBACK(void) DropScriptObject(PRUint32 aLangID, void *aObject,
|
||||||
|
void *aClosure);
|
||||||
|
|
||||||
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
|
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
|
||||||
|
|
||||||
static nsIXPConnect *sXPConnect;
|
static nsIXPConnect *sXPConnect;
|
||||||
|
@ -1163,14 +1164,9 @@ private:
|
||||||
// Holds pointers to nsISupports* that should be released at shutdown
|
// Holds pointers to nsISupports* that should be released at shutdown
|
||||||
static nsVoidArray* sPtrsToPtrsToRelease;
|
static nsVoidArray* sPtrsToPtrsToRelease;
|
||||||
|
|
||||||
// For now, we don't want to automatically clean this up in Shutdown(), since
|
|
||||||
// consumers might unfortunately end up wanting to use it after that
|
|
||||||
static nsIJSRuntimeService* sJSRuntimeService;
|
|
||||||
static JSRuntime* sJSScriptRuntime;
|
|
||||||
static PRInt32 sJSScriptRootCount;
|
|
||||||
|
|
||||||
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||||
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||||
|
static PRUint32 sJSGCThingRootCount;
|
||||||
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
static nsIBidiKeyboard* sBidiKeyboard;
|
static nsIBidiKeyboard* sBidiKeyboard;
|
||||||
|
@ -1180,6 +1176,14 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define NS_HOLD_JS_OBJECTS(obj, clazz) \
|
||||||
|
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz), \
|
||||||
|
&NS_CYCLE_COLLECTION_NAME(clazz))
|
||||||
|
|
||||||
|
#define NS_DROP_JS_OBJECTS(obj, clazz) \
|
||||||
|
nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
|
||||||
|
|
||||||
|
|
||||||
class nsCxPusher
|
class nsCxPusher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1202,33 +1206,38 @@ public:
|
||||||
nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
|
nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
|
||||||
mPtr(aPtr)
|
mPtr(aPtr)
|
||||||
{
|
{
|
||||||
mResult = *aResult =
|
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
||||||
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// aPtr should be the pointer to the JSObject* we want to protect
|
// aPtr should be the pointer to the JSObject* we want to protect
|
||||||
nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
|
nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
|
||||||
mPtr(aPtr)
|
mPtr(aPtr)
|
||||||
{
|
{
|
||||||
mResult = *aResult =
|
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
||||||
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// aPtr should be the pointer to the thing we want to protect
|
// aPtr should be the pointer to the thing we want to protect
|
||||||
nsAutoGCRoot(void* aPtr, nsresult* aResult) :
|
nsAutoGCRoot(void* aPtr, nsresult* aResult) :
|
||||||
mPtr(aPtr)
|
mPtr(aPtr)
|
||||||
{
|
{
|
||||||
mResult = *aResult =
|
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
||||||
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~nsAutoGCRoot() {
|
~nsAutoGCRoot() {
|
||||||
if (NS_SUCCEEDED(mResult)) {
|
if (NS_SUCCEEDED(mResult)) {
|
||||||
nsContentUtils::RemoveJSGCRoot(mPtr);
|
RemoveJSGCRoot(mPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static nsresult AddJSGCRoot(void *aPtr, const char* aName);
|
||||||
|
static nsresult RemoveJSGCRoot(void *aPtr);
|
||||||
|
|
||||||
|
static nsIJSRuntimeService* sJSRuntimeService;
|
||||||
|
static JSRuntime* sJSScriptRuntime;
|
||||||
|
|
||||||
void* mPtr;
|
void* mPtr;
|
||||||
nsresult mResult;
|
nsresult mResult;
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,15 +180,15 @@ nsILineBreaker *nsContentUtils::sLineBreaker;
|
||||||
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
||||||
nsICaseConversion *nsContentUtils::sCaseConv;
|
nsICaseConversion *nsContentUtils::sCaseConv;
|
||||||
nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
|
nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
|
||||||
nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
|
|
||||||
JSRuntime *nsContentUtils::sJSScriptRuntime;
|
|
||||||
PRInt32 nsContentUtils::sJSScriptRootCount = 0;
|
|
||||||
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||||
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||||
|
PRUint32 nsContentUtils::sJSGCThingRootCount;
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
|
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nsIJSRuntimeService *nsAutoGCRoot::sJSRuntimeService;
|
||||||
|
JSRuntime *nsAutoGCRoot::sJSScriptRuntime;
|
||||||
|
|
||||||
PRBool nsContentUtils::sInitialized = PR_FALSE;
|
PRBool nsContentUtils::sInitialized = PR_FALSE;
|
||||||
|
|
||||||
|
@ -671,7 +671,8 @@ nsContentUtils::Shutdown()
|
||||||
NS_IF_RELEASE(sStringBundleService);
|
NS_IF_RELEASE(sStringBundleService);
|
||||||
NS_IF_RELEASE(sConsoleService);
|
NS_IF_RELEASE(sConsoleService);
|
||||||
NS_IF_RELEASE(sDOMScriptObjectFactory);
|
NS_IF_RELEASE(sDOMScriptObjectFactory);
|
||||||
NS_IF_RELEASE(sXPConnect);
|
if (sJSGCThingRootCount == 0 && sXPConnect)
|
||||||
|
NS_RELEASE(sXPConnect);
|
||||||
NS_IF_RELEASE(sSecurityManager);
|
NS_IF_RELEASE(sSecurityManager);
|
||||||
NS_IF_RELEASE(sThreadJSContextStack);
|
NS_IF_RELEASE(sThreadJSContextStack);
|
||||||
NS_IF_RELEASE(sNameSpaceManager);
|
NS_IF_RELEASE(sNameSpaceManager);
|
||||||
|
@ -721,6 +722,8 @@ nsContentUtils::Shutdown()
|
||||||
sEventListenerManagersHash.ops = nsnull;
|
sEventListenerManagersHash.ops = nsnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoGCRoot::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRBool IsCallerTrustedForCapability(const char* aCapability)
|
static PRBool IsCallerTrustedForCapability(const char* aCapability)
|
||||||
|
@ -2672,7 +2675,7 @@ nsContentUtils::GetContentPolicy()
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
|
nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName)
|
||||||
{
|
{
|
||||||
if (!sJSScriptRuntime) {
|
if (!sJSScriptRuntime) {
|
||||||
nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
|
nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
|
||||||
|
@ -2690,25 +2693,16 @@ nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
|
||||||
PRBool ok;
|
PRBool ok;
|
||||||
ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
|
ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (sJSScriptRootCount == 0) {
|
|
||||||
// We just got the runtime... Just null things out, since no
|
|
||||||
// one's expecting us to have a runtime yet
|
|
||||||
NS_RELEASE(sJSRuntimeService);
|
|
||||||
sJSScriptRuntime = nsnull;
|
|
||||||
}
|
|
||||||
NS_WARNING("JS_AddNamedRootRT failed");
|
NS_WARNING("JS_AddNamedRootRT failed");
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now have one more root we added to the runtime
|
|
||||||
++sJSScriptRootCount;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsresult
|
nsresult
|
||||||
nsContentUtils::RemoveJSGCRoot(void* aPtr)
|
nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
|
||||||
{
|
{
|
||||||
if (!sJSScriptRuntime) {
|
if (!sJSScriptRuntime) {
|
||||||
NS_NOTREACHED("Trying to remove a JS GC root when none were added");
|
NS_NOTREACHED("Trying to remove a JS GC root when none were added");
|
||||||
|
@ -2717,11 +2711,6 @@ nsContentUtils::RemoveJSGCRoot(void* aPtr)
|
||||||
|
|
||||||
::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
|
::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
|
||||||
|
|
||||||
if (--sJSScriptRootCount == 0) {
|
|
||||||
NS_RELEASE(sJSRuntimeService);
|
|
||||||
sJSScriptRuntime = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3525,6 +3514,8 @@ nsresult
|
||||||
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
|
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aObject, "unexpected null object");
|
NS_ASSERTION(aObject, "unexpected null object");
|
||||||
|
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
|
||||||
|
"Should use HoldJSObjects.");
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
||||||
|
@ -3551,17 +3542,47 @@ nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsresult
|
void
|
||||||
nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject)
|
nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject,
|
||||||
|
void *aClosure)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aObject, "unexpected null object");
|
NS_ASSERTION(aObject, "unexpected null object");
|
||||||
|
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
|
||||||
|
"Should use DropJSObjects.");
|
||||||
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
||||||
NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
|
NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
|
||||||
"HoldScriptObject");
|
"HoldScriptObject");
|
||||||
nsresult rv = sScriptRuntimes[langIndex]->DropScriptObject(aObject);
|
sScriptRuntimes[langIndex]->DropScriptObject(aObject);
|
||||||
if (--sScriptRootCount[langIndex] == 0) {
|
if (--sScriptRootCount[langIndex] == 0) {
|
||||||
NS_RELEASE(sScriptRuntimes[langIndex]);
|
NS_RELEASE(sScriptRuntimes[langIndex]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
nsresult
|
||||||
|
nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
|
||||||
|
nsScriptObjectTracer* aTracer)
|
||||||
|
{
|
||||||
|
PRBool newHolder;
|
||||||
|
nsresult rv = sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
++sJSGCThingRootCount;
|
||||||
|
NS_LOG_ADDREF(sXPConnect, sJSGCThingRootCount, "HoldJSObjects",
|
||||||
|
sizeof(void*));
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
nsresult
|
||||||
|
nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
|
||||||
|
{
|
||||||
|
NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects");
|
||||||
|
nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder);
|
||||||
|
if (--sJSGCThingRootCount == 0 && !sInitialized) {
|
||||||
|
NS_RELEASE(sXPConnect);
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3717,3 +3738,10 @@ nsContentUtils::IsNativeAnonymous(nsIContent* aContent)
|
||||||
|
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void
|
||||||
|
nsAutoGCRoot::Shutdown()
|
||||||
|
{
|
||||||
|
NS_IF_RELEASE(sJSRuntimeService);
|
||||||
|
}
|
||||||
|
|
|
@ -306,7 +306,7 @@ TraverseKey(nsISupports* aKey, nsInsertionPointList* aData, void* aClosure)
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
|
||||||
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
|
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
|
||||||
// mPrototypeBinding is weak.
|
// mPrototypeBinding is weak.
|
||||||
|
|
|
@ -452,6 +452,21 @@ UnlinkProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
return kHashEnumerateNext;
|
return kHashEnumerateNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ProtoTracer
|
||||||
|
{
|
||||||
|
TraceCallback mCallback;
|
||||||
|
void *mClosure;
|
||||||
|
};
|
||||||
|
|
||||||
|
static PRIntn PR_CALLBACK
|
||||||
|
TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
|
||||||
|
{
|
||||||
|
ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
|
||||||
|
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
|
||||||
|
proto->Trace(closure->mCallback, closure->mClosure);
|
||||||
|
return kHashEnumerateNext;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
|
||||||
if (tmp->mBindingTable) {
|
if (tmp->mBindingTable) {
|
||||||
|
@ -466,7 +481,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
|
||||||
tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
|
tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
|
||||||
}
|
}
|
||||||
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
|
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
|
||||||
|
if (tmp->mBindingTable) {
|
||||||
|
ProtoTracer closure = { aCallback, aClosure };
|
||||||
|
tmp->mBindingTable->Enumerate(TraceProtos, &closure);
|
||||||
|
}
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIXBLDocumentInfo)
|
NS_INTERFACE_MAP_ENTRY(nsIXBLDocumentInfo)
|
||||||
|
@ -507,7 +529,10 @@ nsXBLDocumentInfo::~nsXBLDocumentInfo()
|
||||||
mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
|
mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
|
||||||
mGlobalObject->ClearGlobalObjectOwner(); // just in case
|
mGlobalObject->ClearGlobalObjectOwner(); // just in case
|
||||||
}
|
}
|
||||||
delete mBindingTable;
|
if (mBindingTable) {
|
||||||
|
NS_DROP_JS_OBJECTS(this, nsXBLDocumentInfo);
|
||||||
|
delete mBindingTable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -541,8 +566,13 @@ DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
|
nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
|
||||||
{
|
{
|
||||||
if (!mBindingTable)
|
if (!mBindingTable) {
|
||||||
mBindingTable = new nsObjectHashtable(nsnull, nsnull, DeletePrototypeBinding, nsnull);
|
mBindingTable = new nsObjectHashtable(nsnull, nsnull, DeletePrototypeBinding, nsnull);
|
||||||
|
if (!mBindingTable)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
NS_HOLD_JS_OBJECTS(this, nsXBLDocumentInfo);
|
||||||
|
}
|
||||||
|
|
||||||
const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
|
const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
|
||||||
nsCStringKey key(flat.get());
|
nsCStringKey key(flat.get());
|
||||||
|
|
|
@ -72,8 +72,8 @@ public:
|
||||||
// nsIScriptGlobalObjectOwner methods
|
// nsIScriptGlobalObjectOwner methods
|
||||||
virtual nsIScriptGlobalObject* GetScriptGlobalObject();
|
virtual nsIScriptGlobalObject* GetScriptGlobalObject();
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
|
||||||
nsIXBLDocumentInfo)
|
nsIXBLDocumentInfo)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
nsCOMPtr<nsIDocument> mDocument;
|
||||||
|
|
|
@ -64,7 +64,7 @@ nsXBLInsertionPoint::Release()
|
||||||
return mRefCnt;
|
return mRefCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)
|
||||||
|
|
|
@ -200,7 +200,7 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLProtoImpl::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const
|
||||||
{
|
{
|
||||||
// If we don't have a class object then we either didn't compile members
|
// If we don't have a class object then we either didn't compile members
|
||||||
// or we only have fields, in both cases there are no cycles through our
|
// or we only have fields, in both cases there are no cycles through our
|
||||||
|
@ -211,7 +211,7 @@ nsXBLProtoImpl::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
||||||
|
|
||||||
nsXBLProtoImplMember *member;
|
nsXBLProtoImplMember *member;
|
||||||
for (member = mMembers; member; member = member->GetNext()) {
|
for (member = mMembers; member; member = member->GetNext()) {
|
||||||
member->Traverse(cb);
|
member->Trace(aCallback, aClosure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
mFields = aFieldList;
|
mFields = aFieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
|
void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||||
void Unlink();
|
void Unlink();
|
||||||
|
|
||||||
nsXBLProtoImplField* FindField(const nsString& aFieldName) const;
|
nsXBLProtoImplField* FindField(const nsString& aFieldName) const;
|
||||||
|
|
|
@ -47,11 +47,11 @@
|
||||||
#include "nsIJSRuntimeService.h"
|
#include "nsIJSRuntimeService.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
|
||||||
class nsIScriptContext;
|
class nsIScriptContext;
|
||||||
struct JSRuntime;
|
struct JSRuntime;
|
||||||
class nsIJSRuntimeService;
|
class nsIJSRuntimeService;
|
||||||
class nsCycleCollectionTraversalCallback;
|
|
||||||
|
|
||||||
struct nsXBLTextWithLineNumber
|
struct nsXBLTextWithLineNumber
|
||||||
{
|
{
|
||||||
|
@ -114,7 +114,7 @@ public:
|
||||||
const nsCString& aClassStr,
|
const nsCString& aClassStr,
|
||||||
void* aClassObject)=0;
|
void* aClassObject)=0;
|
||||||
|
|
||||||
virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const = 0;
|
virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class nsAutoGCRoot;
|
friend class nsAutoGCRoot;
|
||||||
|
|
|
@ -72,8 +72,6 @@ nsXBLProtoImplMethod::Destroy(PRBool aIsCompiled)
|
||||||
NS_PRECONDITION(aIsCompiled == mIsCompiled,
|
NS_PRECONDITION(aIsCompiled == mIsCompiled,
|
||||||
"Incorrect aIsCompiled in nsXBLProtoImplMethod::Destroy");
|
"Incorrect aIsCompiled in nsXBLProtoImplMethod::Destroy");
|
||||||
if (aIsCompiled) {
|
if (aIsCompiled) {
|
||||||
if (mJSMethodObject)
|
|
||||||
nsContentUtils::RemoveJSGCRoot(&mJSMethodObject);
|
|
||||||
mJSMethodObject = nsnull;
|
mJSMethodObject = nsnull;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -263,8 +261,6 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||||
|
|
||||||
if (methodObject) {
|
if (methodObject) {
|
||||||
// Root the compiled prototype script object.
|
// Root the compiled prototype script object.
|
||||||
rv = nsContentUtils::AddJSGCRoot(&mJSMethodObject,
|
|
||||||
"nsXBLProtoImplMethod::mJSMethodObject");
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
mJSMethodObject = nsnull;
|
mJSMethodObject = nsnull;
|
||||||
}
|
}
|
||||||
|
@ -277,11 +273,13 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLProtoImplMethod::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
nsXBLProtoImplMethod::Trace(TraceCallback aCallback, void *aClosure) const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
|
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
|
||||||
|
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject);
|
if (mJSMethodObject) {
|
||||||
|
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject, aClosure);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -129,7 +129,7 @@ public:
|
||||||
const nsCString& aClassStr,
|
const nsCString& aClassStr,
|
||||||
void* aClassObject);
|
void* aClassObject);
|
||||||
|
|
||||||
virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
|
virtual void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -87,14 +87,14 @@ nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
|
||||||
"Incorrect aIsCompiled in nsXBLProtoImplProperty::Destroy");
|
"Incorrect aIsCompiled in nsXBLProtoImplProperty::Destroy");
|
||||||
|
|
||||||
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
|
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
|
||||||
nsContentUtils::RemoveJSGCRoot(&mJSGetterObject);
|
mJSGetterObject = nsnull;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete mGetterText;
|
delete mGetterText;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
|
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
|
||||||
nsContentUtils::RemoveJSGCRoot(&mJSSetterObject);
|
mJSSetterObject = nsnull;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete mSetterText;
|
delete mSetterText;
|
||||||
|
@ -268,9 +268,6 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||||
|
|
||||||
if (mJSGetterObject && NS_SUCCEEDED(rv)) {
|
if (mJSGetterObject && NS_SUCCEEDED(rv)) {
|
||||||
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||||
// Root the compiled prototype script object.
|
|
||||||
rv = nsContentUtils::AddJSGCRoot(&mJSGetterObject,
|
|
||||||
"nsXBLProtoImplProperty::mJSGetterObject");
|
|
||||||
}
|
}
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
mJSGetterObject = nsnull;
|
mJSGetterObject = nsnull;
|
||||||
|
@ -320,9 +317,6 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||||
|
|
||||||
if (mJSSetterObject && NS_SUCCEEDED(rv)) {
|
if (mJSSetterObject && NS_SUCCEEDED(rv)) {
|
||||||
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||||
// Root the compiled prototype script object.
|
|
||||||
rv = nsContentUtils::AddJSGCRoot(&mJSSetterObject,
|
|
||||||
"nsXBLProtoImplProperty::mJSSetterObject");
|
|
||||||
}
|
}
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
mJSSetterObject = nsnull;
|
mJSSetterObject = nsnull;
|
||||||
|
@ -345,15 +339,15 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLProtoImplProperty::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
nsXBLProtoImplProperty::Trace(TraceCallback aCallback, void *aClosure) const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
|
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
|
||||||
|
|
||||||
if (mJSAttributes & JSPROP_GETTER) {
|
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject);
|
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject, aClosure);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mJSAttributes & JSPROP_SETTER) {
|
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject);
|
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject, aClosure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
const nsCString& aClassStr,
|
const nsCString& aClassStr,
|
||||||
void* aClassObject);
|
void* aClassObject);
|
||||||
|
|
||||||
virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
|
virtual void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -244,7 +244,7 @@ private:
|
||||||
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
|
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
|
||||||
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
|
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPointEntry)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPointEntry)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
|
||||||
if (tmp->mDefaultContent) {
|
if (tmp->mDefaultContent) {
|
||||||
|
@ -355,8 +355,6 @@ void
|
||||||
nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const
|
||||||
{
|
{
|
||||||
cb.NoteXPCOMChild(mBinding);
|
cb.NoteXPCOMChild(mBinding);
|
||||||
if (mImplementation)
|
|
||||||
mImplementation->Traverse(cb);
|
|
||||||
if (mResources)
|
if (mResources)
|
||||||
cb.NoteXPCOMChild(mResources->mLoader);
|
cb.NoteXPCOMChild(mResources->mLoader);
|
||||||
if (mInsertionPointTable)
|
if (mInsertionPointTable)
|
||||||
|
@ -372,6 +370,13 @@ nsXBLPrototypeBinding::Unlink()
|
||||||
mImplementation->Unlink();
|
mImplementation->Unlink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLPrototypeBinding::Trace(TraceCallback aCallback, void *aClosure) const
|
||||||
|
{
|
||||||
|
if (mImplementation)
|
||||||
|
mImplementation->Trace(aCallback, aClosure);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLPrototypeBinding::Initialize()
|
nsXBLPrototypeBinding::Initialize()
|
||||||
{
|
{
|
||||||
|
|
|
@ -198,6 +198,7 @@ public:
|
||||||
|
|
||||||
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
|
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
|
||||||
void Unlink();
|
void Unlink();
|
||||||
|
void Trace(TraceCallback aCallback, void *aClosure) const;
|
||||||
|
|
||||||
// Static members
|
// Static members
|
||||||
static PRUint32 gRefCnt;
|
static PRUint32 gRefCnt;
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
* use in OS2
|
* use in OS2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsapi.h" // for JS_AddNamedRoot and JS_RemoveRootRT
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsDOMCID.h"
|
#include "nsDOMCID.h"
|
||||||
#include "nsDOMError.h"
|
#include "nsDOMError.h"
|
||||||
|
@ -702,7 +701,8 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
|
||||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
|
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
|
||||||
|
|
||||||
nsIScriptContext *context;
|
nsIScriptContext *context;
|
||||||
if (mElement->mPrototype && xuldoc) {
|
nsXULPrototypeElement *elem = mElement->mPrototype;
|
||||||
|
if (elem && xuldoc) {
|
||||||
// It'll be shared among the instances of the prototype.
|
// It'll be shared among the instances of the prototype.
|
||||||
|
|
||||||
// Use the prototype document's special context. Because
|
// Use the prototype document's special context. Because
|
||||||
|
@ -755,9 +755,16 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
|
||||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
||||||
// take a copy of the event handler, and tell the language about it.
|
// take a copy of the event handler, and tell the language about it.
|
||||||
if (aHandler) {
|
if (aHandler) {
|
||||||
|
NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
|
||||||
|
|
||||||
rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
|
rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
|
||||||
aHandler);
|
elem,
|
||||||
|
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
|
||||||
|
aHandler,
|
||||||
|
elem->mHoldsScriptObject);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
elem->mHoldsScriptObject = PR_TRUE;
|
||||||
}
|
}
|
||||||
attr->mEventHandler = (void *)aHandler;
|
attr->mEventHandler = (void *)aHandler;
|
||||||
}
|
}
|
||||||
|
@ -2351,26 +2358,40 @@ nsXULElement::RecompileScriptEventListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsXULPrototypeNode)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsXULPrototypeNode)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXULPrototypeNode)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXULPrototypeNode)
|
||||||
if (tmp->mType == nsXULPrototypeNode::eType_Element) {
|
if (tmp->mType == nsXULPrototypeNode::eType_Element) {
|
||||||
nsXULPrototypeElement *elem =
|
nsXULPrototypeElement *elem =
|
||||||
static_cast<nsXULPrototypeElement*>(tmp);
|
static_cast<nsXULPrototypeElement*>(tmp);
|
||||||
PRUint32 i;
|
PRUint32 i;
|
||||||
for (i = 0; i < elem->mNumAttributes; ++i) {
|
|
||||||
cb.NoteScriptChild(elem->mScriptTypeID,
|
|
||||||
elem->mAttributes[i].mEventHandler);
|
|
||||||
}
|
|
||||||
for (i = 0; i < elem->mNumChildren; ++i) {
|
for (i = 0; i < elem->mNumChildren; ++i) {
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i],
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i],
|
||||||
nsXULPrototypeNode)
|
nsXULPrototypeNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||||
static_cast<nsXULPrototypeScript*>(tmp)->mScriptObject.traverse(cb);
|
|
||||||
}
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(nsXULPrototypeNode)
|
||||||
|
if (tmp->mType == nsXULPrototypeNode::eType_Element) {
|
||||||
|
nsXULPrototypeElement *elem =
|
||||||
|
static_cast<nsXULPrototypeElement*>(tmp);
|
||||||
|
if (elem->mHoldsScriptObject) {
|
||||||
|
PRUint32 i;
|
||||||
|
for (i = 0; i < elem->mNumAttributes; ++i) {
|
||||||
|
void *handler = elem->mAttributes[i].mEventHandler;
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(elem->mScriptTypeID,
|
||||||
|
handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
|
||||||
|
nsXULPrototypeScript *script =
|
||||||
|
static_cast<nsXULPrototypeScript*>(tmp);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(script->mScriptObject.mLangID,
|
||||||
|
script->mScriptObject.mObject)
|
||||||
|
}
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXULPrototypeNode, AddRef)
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXULPrototypeNode, AddRef)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
|
||||||
|
|
||||||
|
@ -2382,17 +2403,6 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
|
||||||
nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
|
nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
|
MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
|
||||||
NS_ASSERTION(!mEventHandler, "Finalize not called - language object leak!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsXULPrototypeAttribute::Finalize(PRUint32 aLangID)
|
|
||||||
{
|
|
||||||
if (mEventHandler) {
|
|
||||||
if (NS_FAILED(nsContentUtils::DropScriptObject(aLangID, mEventHandler)))
|
|
||||||
NS_ERROR("Failed to drop script object");
|
|
||||||
mEventHandler = nsnull;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2679,6 +2689,19 @@ nsXULPrototypeElement::SetAttrAt(PRUint32 aPos, const nsAString& aValue,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULPrototypeElement::Unlink()
|
||||||
|
{
|
||||||
|
if (mHoldsScriptObject) {
|
||||||
|
nsContentUtils::DropScriptObjects(mScriptTypeID, this,
|
||||||
|
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
|
||||||
|
mHoldsScriptObject = PR_FALSE;
|
||||||
|
}
|
||||||
|
mNumAttributes = 0;
|
||||||
|
delete[] mAttributes;
|
||||||
|
mAttributes = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// nsXULPrototypeScript
|
// nsXULPrototypeScript
|
||||||
|
@ -2701,6 +2724,7 @@ nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, P
|
||||||
|
|
||||||
nsXULPrototypeScript::~nsXULPrototypeScript()
|
nsXULPrototypeScript::~nsXULPrototypeScript()
|
||||||
{
|
{
|
||||||
|
Unlink();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -2818,7 +2842,7 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
|
||||||
NS_WARNING("Language deseralization failed");
|
NS_WARNING("Language deseralization failed");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
mScriptObject.set(newScriptObject);
|
Set(newScriptObject);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2871,7 +2895,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||||
NS_ERROR("XUL cache gave different language?");
|
NS_ERROR("XUL cache gave different language?");
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
mScriptObject.set(newScriptObject);
|
Set(newScriptObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2997,7 +3021,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
mScriptObject.set(newScriptObject);
|
Set(newScriptObject);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,9 +124,6 @@ public:
|
||||||
// nsScriptObjectHolder, but want to avoid the extra lang ID.
|
// nsScriptObjectHolder, but want to avoid the extra lang ID.
|
||||||
void* mEventHandler;
|
void* mEventHandler;
|
||||||
|
|
||||||
// Containing element must tell us the langID so we can cleanup.
|
|
||||||
void Finalize(PRUint32 aLangID);
|
|
||||||
|
|
||||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||||
/**
|
/**
|
||||||
If enough attributes, on average, are event handlers, it pays to keep
|
If enough attributes, on average, are event handlers, it pays to keep
|
||||||
|
@ -230,7 +227,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void ReleaseSubtree() { Release(); }
|
virtual void ReleaseSubtree() { Release(); }
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsXULPrototypeNode)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsXULPrototypeNode(Type aType)
|
nsXULPrototypeNode(Type aType)
|
||||||
|
@ -249,6 +246,7 @@ public:
|
||||||
mHasIdAttribute(PR_FALSE),
|
mHasIdAttribute(PR_FALSE),
|
||||||
mHasClassAttribute(PR_FALSE),
|
mHasClassAttribute(PR_FALSE),
|
||||||
mHasStyleAttribute(PR_FALSE),
|
mHasStyleAttribute(PR_FALSE),
|
||||||
|
mHoldsScriptObject(PR_FALSE),
|
||||||
mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
|
mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
|
||||||
{
|
{
|
||||||
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
|
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
|
||||||
|
@ -256,10 +254,7 @@ public:
|
||||||
|
|
||||||
virtual ~nsXULPrototypeElement()
|
virtual ~nsXULPrototypeElement()
|
||||||
{
|
{
|
||||||
PRUint32 i;
|
Unlink();
|
||||||
for (i = 0; i < mNumAttributes; i++)
|
|
||||||
mAttributes[i].Finalize(mScriptTypeID);
|
|
||||||
delete[] mAttributes;
|
|
||||||
NS_ASSERTION(!mChildren && mNumChildren == 0,
|
NS_ASSERTION(!mChildren && mNumChildren == 0,
|
||||||
"ReleaseSubtree not called");
|
"ReleaseSubtree not called");
|
||||||
}
|
}
|
||||||
|
@ -294,6 +289,8 @@ public:
|
||||||
|
|
||||||
nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
|
nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
|
||||||
|
|
||||||
|
void Unlink();
|
||||||
|
|
||||||
PRUint32 mNumChildren;
|
PRUint32 mNumChildren;
|
||||||
nsXULPrototypeNode** mChildren; // [OWNER]
|
nsXULPrototypeNode** mChildren; // [OWNER]
|
||||||
|
|
||||||
|
@ -305,6 +302,7 @@ public:
|
||||||
PRPackedBool mHasIdAttribute:1;
|
PRPackedBool mHasIdAttribute:1;
|
||||||
PRPackedBool mHasClassAttribute:1;
|
PRPackedBool mHasClassAttribute:1;
|
||||||
PRPackedBool mHasStyleAttribute:1;
|
PRPackedBool mHasStyleAttribute:1;
|
||||||
|
PRPackedBool mHoldsScriptObject:1;
|
||||||
|
|
||||||
// The language ID can not be set on a per-node basis, but is tracked
|
// The language ID can not be set on a per-node basis, but is tracked
|
||||||
// so that the language ID from the originating root can be used
|
// so that the language ID from the originating root can be used
|
||||||
|
@ -361,13 +359,52 @@ public:
|
||||||
nsIDocument* aDocument,
|
nsIDocument* aDocument,
|
||||||
nsIScriptGlobalObjectOwner* aGlobalOwner);
|
nsIScriptGlobalObjectOwner* aGlobalOwner);
|
||||||
|
|
||||||
|
void Unlink()
|
||||||
|
{
|
||||||
|
if (mScriptObject.mObject) {
|
||||||
|
nsContentUtils::DropScriptObjects(mScriptObject.mLangID, this,
|
||||||
|
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
|
||||||
|
mScriptObject.mObject = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(nsScriptObjectHolder &aHolder)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mScriptObject.mLangID == aHolder.getScriptTypeID(),
|
||||||
|
"Wrong language, this will leak the previous object.");
|
||||||
|
|
||||||
|
mScriptObject.mLangID = aHolder.getScriptTypeID();
|
||||||
|
Set((void*)aHolder);
|
||||||
|
}
|
||||||
|
void Set(void *aObject)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(!mScriptObject.mObject, "Leaking script object.");
|
||||||
|
|
||||||
|
nsresult rv = nsContentUtils::HoldScriptObject(mScriptObject.mLangID,
|
||||||
|
this,
|
||||||
|
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
|
||||||
|
aObject, PR_FALSE);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mScriptObject.mObject = aObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScriptObjectHolder
|
||||||
|
{
|
||||||
|
ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
|
||||||
|
mObject(nsnull)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
PRUint32 mLangID;
|
||||||
|
void* mObject;
|
||||||
|
};
|
||||||
nsCOMPtr<nsIURI> mSrcURI;
|
nsCOMPtr<nsIURI> mSrcURI;
|
||||||
PRUint32 mLineNo;
|
PRUint32 mLineNo;
|
||||||
PRPackedBool mSrcLoading;
|
PRPackedBool mSrcLoading;
|
||||||
PRPackedBool mOutOfLine;
|
PRPackedBool mOutOfLine;
|
||||||
nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
|
nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
|
||||||
PRUint32 mLangVersion;
|
PRUint32 mLangVersion;
|
||||||
nsContentUtils::ScriptObjectHolder mScriptObject;
|
ScriptObjectHolder mScriptObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsXULPrototypeText : public nsXULPrototypeNode
|
class nsXULPrototypeText : public nsXULPrototypeNode
|
||||||
|
|
|
@ -3209,7 +3209,7 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
|
||||||
NS_ERROR("XUL cache gave me an incorrect script language");
|
NS_ERROR("XUL cache gave me an incorrect script language");
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
aScriptProto->mScriptObject.set(newScriptObject);
|
aScriptProto->Set(newScriptObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aScriptProto->mScriptObject.mObject) {
|
if (aScriptProto->mScriptObject.mObject) {
|
||||||
|
|
|
@ -3729,7 +3729,8 @@ public:
|
||||||
~nsJSArgArray();
|
~nsJSArgArray();
|
||||||
// nsISupports
|
// nsISupports
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSArgArray, nsIJSArgArray)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSArgArray,
|
||||||
|
nsIJSArgArray)
|
||||||
|
|
||||||
// nsIArray
|
// nsIArray
|
||||||
NS_DECL_NSIARRAY
|
NS_DECL_NSIARRAY
|
||||||
|
@ -3759,16 +3760,14 @@ nsJSArgArray::nsJSArgArray(JSContext *aContext, PRUint32 argc, jsval *argv,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAutoRequest ar(aContext);
|
// Callers are allowed to pass in a null argv even for argc > 0. They can
|
||||||
for (PRUint32 i = 0; i < argc; ++i) {
|
// then use GetArgs to initialize the values.
|
||||||
if (argv)
|
if (argv) {
|
||||||
|
for (PRUint32 i = 0; i < argc; ++i)
|
||||||
mArgv[i] = argv[i];
|
mArgv[i] = argv[i];
|
||||||
if (!::JS_AddNamedRoot(aContext, &mArgv[i], "nsJSArgArray.mArgv[i]")) {
|
|
||||||
*prv = NS_ERROR_UNEXPECTED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*prv = NS_OK;
|
if (argc > 0)
|
||||||
|
*prv = NS_HOLD_JS_OBJECTS(this, nsJSArgArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJSArgArray::~nsJSArgArray()
|
nsJSArgArray::~nsJSArgArray()
|
||||||
|
@ -3779,13 +3778,9 @@ nsJSArgArray::~nsJSArgArray()
|
||||||
void
|
void
|
||||||
nsJSArgArray::ReleaseJSObjects()
|
nsJSArgArray::ReleaseJSObjects()
|
||||||
{
|
{
|
||||||
|
if (mArgc > 0)
|
||||||
|
NS_DROP_JS_OBJECTS(this, nsJSArgArray);
|
||||||
if (mArgv) {
|
if (mArgv) {
|
||||||
NS_ASSERTION(nsJSRuntime::sRuntime, "Where's the runtime gone?");
|
|
||||||
if (nsJSRuntime::sRuntime) {
|
|
||||||
for (PRUint32 i = 0; i < mArgc; ++i) {
|
|
||||||
::JS_RemoveRootRT(nsJSRuntime::sRuntime, &mArgv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PR_DELETE(mArgv);
|
PR_DELETE(mArgv);
|
||||||
}
|
}
|
||||||
mArgc = 0;
|
mArgc = 0;
|
||||||
|
@ -3797,17 +3792,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
|
||||||
tmp->ReleaseJSObjects();
|
tmp->ReleaseJSObjects();
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
|
||||||
{
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||||
jsval *argv = tmp->mArgv;
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
if (argv) {
|
|
||||||
jsval *end;
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray)
|
||||||
for (end = argv + tmp->mArgc; argv < end; ++argv) {
|
jsval *argv = tmp->mArgv;
|
||||||
if (JSVAL_IS_OBJECT(*argv))
|
if (argv) {
|
||||||
cb.NoteScriptChild(JAVASCRIPT, JSVAL_TO_OBJECT(*argv));
|
jsval *end;
|
||||||
}
|
for (end = argv + tmp->mArgc; argv < end; ++argv) {
|
||||||
|
if (JSVAL_IS_GCTHING(*argv))
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(JAVASCRIPT,
|
||||||
|
JSVAL_TO_GCTHING(*argv))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSArgArray)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSArgArray)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIArray)
|
NS_INTERFACE_MAP_ENTRY(nsIArray)
|
||||||
|
|
|
@ -59,7 +59,7 @@ class nsJSScriptTimeoutHandler: public nsIScriptTimeoutHandler
|
||||||
public:
|
public:
|
||||||
// nsISupports
|
// nsISupports
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSScriptTimeoutHandler)
|
||||||
|
|
||||||
nsJSScriptTimeoutHandler();
|
nsJSScriptTimeoutHandler();
|
||||||
~nsJSScriptTimeoutHandler();
|
~nsJSScriptTimeoutHandler();
|
||||||
|
@ -118,9 +118,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSScriptTimeoutHandler)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSScriptTimeoutHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgv)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgv)
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mFunObj);
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSScriptTimeoutHandler)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mExpr)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mFunObj)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSScriptTimeoutHandler)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSScriptTimeoutHandler)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler)
|
NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
|
@ -146,49 +151,11 @@ void
|
||||||
nsJSScriptTimeoutHandler::ReleaseJSObjects()
|
nsJSScriptTimeoutHandler::ReleaseJSObjects()
|
||||||
{
|
{
|
||||||
if (mExpr || mFunObj) {
|
if (mExpr || mFunObj) {
|
||||||
nsCOMPtr<nsIScriptContext> scx = mContext;
|
|
||||||
JSRuntime *rt = nsnull;
|
|
||||||
|
|
||||||
if (scx) {
|
|
||||||
JSContext *cx;
|
|
||||||
cx = (JSContext *)scx->GetNativeContext();
|
|
||||||
rt = ::JS_GetRuntime(cx);
|
|
||||||
mContext = nsnull;
|
|
||||||
} else {
|
|
||||||
// XXX The timeout *must* be unrooted, even if !scx. This can be
|
|
||||||
// done without a JS context using the JSRuntime. This is safe
|
|
||||||
// enough, but it would be better to drop all a window's
|
|
||||||
// timeouts before its context is cleared. Bug 50705 describes a
|
|
||||||
// situation where we're not. In that case, at the time the
|
|
||||||
// context is cleared, a timeout (actually an Interval) is still
|
|
||||||
// active, but temporarily removed from the window's list of
|
|
||||||
// timers (placed instead on the timer manager's list). This
|
|
||||||
// makes the nearly handy ClearAllTimeouts routine useless, so
|
|
||||||
// we settled on using the JSRuntime rather than relying on the
|
|
||||||
// window having a context. It would be good to remedy this
|
|
||||||
// workable but clumsy situation someday.
|
|
||||||
|
|
||||||
nsCOMPtr<nsIJSRuntimeService> rtsvc =
|
|
||||||
do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
|
||||||
|
|
||||||
if (rtsvc) {
|
|
||||||
rtsvc->GetRuntime(&rt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rt) {
|
|
||||||
// most unexpected. not much choice but to bail.
|
|
||||||
|
|
||||||
NS_ERROR("nsTimeout::Release() with no JSRuntime. eek!");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mExpr) {
|
if (mExpr) {
|
||||||
::JS_RemoveRootRT(rt, &mExpr);
|
NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
|
||||||
mExpr = nsnull;
|
mExpr = nsnull;
|
||||||
} else if (mFunObj) {
|
} else if (mFunObj) {
|
||||||
::JS_RemoveRootRT(rt, &mFunObj);
|
NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
|
||||||
mFunObj = nsnull;
|
mFunObj = nsnull;
|
||||||
} else {
|
} else {
|
||||||
NS_WARNING("No func and no expr - roots may not have been removed");
|
NS_WARNING("No func and no expr - roots may not have been removed");
|
||||||
|
@ -280,9 +247,8 @@ nsJSScriptTimeoutHandler::Init(nsIScriptContext *aContext, PRBool *aIsInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr) {
|
if (expr) {
|
||||||
if (!::JS_AddNamedRoot(cx, &mExpr, "timeout.mExpr")) {
|
rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
|
|
||||||
mExpr = expr;
|
mExpr = expr;
|
||||||
|
|
||||||
|
@ -292,9 +258,8 @@ nsJSScriptTimeoutHandler::Init(nsIScriptContext *aContext, PRBool *aIsInterval,
|
||||||
mFileName.Assign(filename);
|
mFileName.Assign(filename);
|
||||||
}
|
}
|
||||||
} else if (funobj) {
|
} else if (funobj) {
|
||||||
if (!::JS_AddNamedRoot(cx, &mFunObj, "timeout.mFunObj")) {
|
rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
|
|
||||||
mFunObj = funobj;
|
mFunObj = funobj;
|
||||||
|
|
||||||
|
|
|
@ -81,12 +81,13 @@ nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
|
||||||
// until we are done with it.
|
// until we are done with it.
|
||||||
NS_ASSERTION(aScopeObject && aContext,
|
NS_ASSERTION(aScopeObject && aContext,
|
||||||
"EventListener with no context or scope?");
|
"EventListener with no context or scope?");
|
||||||
aContext->HoldScriptObject(aScopeObject);
|
NS_HOLD_JS_OBJECTS(this, nsJSEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJSEventListener::~nsJSEventListener()
|
nsJSEventListener::~nsJSEventListener()
|
||||||
{
|
{
|
||||||
mContext->DropScriptObject(mScopeObject);
|
if (mContext)
|
||||||
|
NS_DROP_JS_OBJECTS(this, nsJSEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
|
||||||
|
@ -96,9 +97,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mScopeObject);
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
|
||||||
|
mScopeObject)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSEventListener)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSEventListener)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIJSEventListener)
|
NS_INTERFACE_MAP_ENTRY(nsIJSEventListener)
|
||||||
|
|
|
@ -65,8 +65,8 @@ public:
|
||||||
// nsIJSEventListener interface
|
// nsIJSEventListener interface
|
||||||
virtual void SetEventName(nsIAtom* aName);
|
virtual void SetEventName(nsIAtom* aName);
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSEventListener,
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSEventListener,
|
||||||
nsIDOMEventListener)
|
nsIDOMEventListener)
|
||||||
protected:
|
protected:
|
||||||
nsCOMPtr<nsIAtom> mEventName;
|
nsCOMPtr<nsIAtom> mEventName;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIXPConnect.idl"
|
#include "nsIXPConnect.idl"
|
||||||
|
|
||||||
|
[ptr] native JSTracerPtr(JSTracer);
|
||||||
|
|
||||||
%{ C++
|
%{ C++
|
||||||
#define NS_SUCCESS_I_DID_SOMETHING \
|
#define NS_SUCCESS_I_DID_SOMETHING \
|
||||||
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))
|
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
native JSVal(jsval);
|
native JSVal(jsval);
|
||||||
native JSID(jsid);
|
native JSID(jsid);
|
||||||
[ptr] native voidPtrPtr(void*);
|
[ptr] native voidPtrPtr(void*);
|
||||||
[ptr] native JSTracerPtr(JSTracer);
|
[ptr] native nsScriptObjectTracerPtr(nsScriptObjectTracer);
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ interface nsIXPCSecurityManager;
|
||||||
interface nsIPrincipal;
|
interface nsIPrincipal;
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
class nsCycleCollectionTraversalCallback;
|
class nsScriptObjectTracer;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -443,7 +443,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
||||||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||||
%}
|
%}
|
||||||
|
|
||||||
[uuid(52fc2ff3-c0ea-46c1-9105-655283c361ff)]
|
[uuid(3eb7f5fc-1325-43af-aead-6033162e04af)]
|
||||||
interface nsIXPConnect : nsISupports
|
interface nsIXPConnect : nsISupports
|
||||||
{
|
{
|
||||||
%{ C++
|
%{ C++
|
||||||
|
@ -727,4 +727,18 @@ interface nsIXPConnect : nsISupports
|
||||||
[noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext,
|
[noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext,
|
||||||
in JSObjectPtr aParent,
|
in JSObjectPtr aParent,
|
||||||
in JSObjectPtr aWrappedObj);
|
in JSObjectPtr aWrappedObj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root JS objects held by aHolder.
|
||||||
|
* @param aHolder The object that hold the JS objects that should be rooted.
|
||||||
|
* @param aTrace The tracer for aHolder.
|
||||||
|
*/
|
||||||
|
[noscript] void addJSHolder(in voidPtr aHolder,
|
||||||
|
in nsScriptObjectTracerPtr aTracer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop rooting the JS objects held by aHolder.
|
||||||
|
* @param aHolder The object that hold the rooted JS objects.
|
||||||
|
*/
|
||||||
|
[noscript] void removeJSHolder(in voidPtr aHolder);
|
||||||
};
|
};
|
||||||
|
|
|
@ -695,16 +695,31 @@ NoteJSChild(JSTracer *trc, void *thing, uint32 kind)
|
||||||
|
|
||||||
static uint8 GCTypeToTraceKindMap[GCX_NTYPES] = {
|
static uint8 GCTypeToTraceKindMap[GCX_NTYPES] = {
|
||||||
JSTRACE_OBJECT, /* GCX_OBJECT */
|
JSTRACE_OBJECT, /* GCX_OBJECT */
|
||||||
JSTRACE_STRING, /* GCX_STRING (unused) */
|
JSTRACE_STRING, /* GCX_STRING */
|
||||||
JSTRACE_DOUBLE, /* GCX_DOUBLE (unused) */
|
JSTRACE_DOUBLE, /* GCX_DOUBLE */
|
||||||
JSTRACE_STRING, /* GCX_MUTABLE_STRING (unused) */
|
JSTRACE_FUNCTION, /* GCX_FUNCTION */
|
||||||
JSTRACE_FUNCTION, /* GCX_FUNCTION (unused) */
|
|
||||||
JSTRACE_NAMESPACE, /* GCX_NAMESPACE */
|
JSTRACE_NAMESPACE, /* GCX_NAMESPACE */
|
||||||
JSTRACE_QNAME, /* GCX_QNAME */
|
JSTRACE_QNAME, /* GCX_QNAME */
|
||||||
JSTRACE_XML /* GCX_XML */
|
JSTRACE_XML, /* GCX_XML */
|
||||||
// We don't care about JSTRACE_STRING, so stop here
|
(uint8)-1, /* unused */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 0 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 1 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 2 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 3 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 4 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 5 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 6 */
|
||||||
|
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 7 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
uint8
|
||||||
|
nsXPConnect::GetTraceKind(void *thing)
|
||||||
|
{
|
||||||
|
uint8 type = *js_GetGCThingFlags(thing) & GCF_TYPEMASK;
|
||||||
|
return GCTypeToTraceKindMap[type];
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||||
{
|
{
|
||||||
|
@ -716,7 +731,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||||
PRUint32 refcount = mObjRefcounts->Get(p);
|
PRUint32 refcount = mObjRefcounts->Get(p);
|
||||||
NS_ASSERTION(refcount > 0, "JS object but unknown to the JS GC?");
|
NS_ASSERTION(refcount > 0, "JS object but unknown to the JS GC?");
|
||||||
|
|
||||||
uint8 ty = *js_GetGCThingFlags(p) & GCF_TYPEMASK;
|
uint8 ty = GetTraceKind(p);
|
||||||
if(ty != GCX_OBJECT && ty != GCX_NAMESPACE && ty != GCX_QNAME &&
|
if(ty != GCX_OBJECT && ty != GCX_NAMESPACE && ty != GCX_QNAME &&
|
||||||
ty != GCX_XML)
|
ty != GCX_XML)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -2097,6 +2112,18 @@ nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPConnect::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
|
||||||
|
{
|
||||||
|
return mRuntime->AddJSHolder(aHolder, aTracer);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPConnect::RemoveJSHolder(void* aHolder)
|
||||||
|
{
|
||||||
|
return mRuntime->RemoveJSHolder(aHolder);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* These are here to be callable from a debugger */
|
/* These are here to be callable from a debugger */
|
||||||
JS_BEGIN_EXTERN_C
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
|
@ -251,6 +251,42 @@ ContextCallback(JSContext *cx, uintN operation)
|
||||||
: JS_TRUE;
|
: JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ObjectHolder : public JSDHashEntryHdr
|
||||||
|
{
|
||||||
|
void *holder;
|
||||||
|
nsScriptObjectTracer* tracer;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
XPCJSRuntime::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
|
||||||
|
{
|
||||||
|
if(!mJSHolders.ops)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
ObjectHolder *entry =
|
||||||
|
reinterpret_cast<ObjectHolder*>(JS_DHashTableOperate(&mJSHolders,
|
||||||
|
aHolder,
|
||||||
|
JS_DHASH_ADD));
|
||||||
|
if(!entry)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
entry->holder = aHolder;
|
||||||
|
entry->tracer = aTracer;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
XPCJSRuntime::RemoveJSHolder(void* aHolder)
|
||||||
|
{
|
||||||
|
if(!mJSHolders.ops)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
JS_DHashTableOperate(&mJSHolders, aHolder, JS_DHASH_REMOVE);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
|
void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
|
||||||
{
|
{
|
||||||
|
@ -277,16 +313,48 @@ void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XPCWrappedNativeScope::TraceJS(trc, self);
|
// XPCJSObjectHolders don't participate in cycle collection, so always trace
|
||||||
|
// them here.
|
||||||
|
for(XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
|
||||||
|
static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
|
||||||
|
|
||||||
|
self->TraceXPConnectRoots(trc);
|
||||||
|
}
|
||||||
|
|
||||||
for (XPCRootSetElem *e = self->mVariantRoots; e ; e = e->GetNextRoot())
|
PR_STATIC_CALLBACK(void)
|
||||||
|
TraceJSObject(PRUint32 aLangID, void *aScriptThing, void *aClosure)
|
||||||
|
{
|
||||||
|
if(aLangID == nsIProgrammingLanguage::JAVASCRIPT)
|
||||||
|
{
|
||||||
|
JS_CALL_TRACER(static_cast<JSTracer*>(aClosure), aScriptThing,
|
||||||
|
nsXPConnect::GetXPConnect()->GetTraceKind(aScriptThing),
|
||||||
|
"JSObjectHolder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
||||||
|
TraceJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
ObjectHolder* entry = reinterpret_cast<ObjectHolder*>(hdr);
|
||||||
|
|
||||||
|
entry->tracer->Trace(entry->holder, TraceJSObject, arg);
|
||||||
|
|
||||||
|
return JS_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc)
|
||||||
|
{
|
||||||
|
XPCWrappedNativeScope::TraceJS(trc, this);
|
||||||
|
|
||||||
|
for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot())
|
||||||
static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
|
static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
|
||||||
|
|
||||||
for (XPCRootSetElem *e = self->mWrappedJSRoots; e ; e = e->GetNextRoot())
|
for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot())
|
||||||
static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
|
static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
|
||||||
|
|
||||||
for (XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
|
if(mJSHolders.ops)
|
||||||
static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
|
JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -809,6 +877,12 @@ XPCJSRuntime::~XPCJSRuntime()
|
||||||
|
|
||||||
gOldJSGCCallback = NULL;
|
gOldJSGCCallback = NULL;
|
||||||
gOldJSContextCallback = NULL;
|
gOldJSContextCallback = NULL;
|
||||||
|
|
||||||
|
if(mJSHolders.ops)
|
||||||
|
{
|
||||||
|
JS_DHashTableFinish(&mJSHolders);
|
||||||
|
mJSHolders.ops = nsnull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
||||||
|
@ -862,6 +936,10 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
||||||
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
|
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
|
||||||
|
sizeof(ObjectHolder), 512))
|
||||||
|
mJSHolders.ops = nsnull;
|
||||||
|
|
||||||
// Install a JavaScript 'debugger' keyword handler in debug builds only
|
// Install a JavaScript 'debugger' keyword handler in debug builds only
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)
|
if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)
|
||||||
|
|
|
@ -498,6 +498,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JSObjectRefcounts* GetJSObjectRefcounts() {return mObjRefcounts;}
|
JSObjectRefcounts* GetJSObjectRefcounts() {return mObjRefcounts;}
|
||||||
|
|
||||||
|
static uint8 GetTraceKind(void *thing);
|
||||||
|
|
||||||
#ifndef XPCONNECT_STANDALONE
|
#ifndef XPCONNECT_STANDALONE
|
||||||
void RecordTraversal(void *p, nsISupports *s);
|
void RecordTraversal(void *p, nsISupports *s);
|
||||||
#endif
|
#endif
|
||||||
|
@ -676,6 +679,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void JS_DLL_CALLBACK TraceJS(JSTracer* trc, void* data);
|
static void JS_DLL_CALLBACK TraceJS(JSTracer* trc, void* data);
|
||||||
|
void TraceXPConnectRoots(JSTracer *trc);
|
||||||
|
void AddXPConnectRoots(JSContext* cx,
|
||||||
|
nsCycleCollectionTraversalCallback& cb);
|
||||||
|
|
||||||
static JSBool JS_DLL_CALLBACK GCCallback(JSContext *cx, JSGCStatus status);
|
static JSBool JS_DLL_CALLBACK GCCallback(JSContext *cx, JSGCStatus status);
|
||||||
|
|
||||||
|
@ -683,6 +689,9 @@ public:
|
||||||
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
|
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
|
||||||
inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
|
inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
|
||||||
|
|
||||||
|
nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
|
||||||
|
nsresult RemoveJSHolder(void* aHolder);
|
||||||
|
|
||||||
void DebugDump(PRInt16 depth);
|
void DebugDump(PRInt16 depth);
|
||||||
|
|
||||||
void SystemIsBeingShutDown(JSContext* cx);
|
void SystemIsBeingShutDown(JSContext* cx);
|
||||||
|
@ -746,6 +755,7 @@ private:
|
||||||
XPCRootSetElem *mVariantRoots;
|
XPCRootSetElem *mVariantRoots;
|
||||||
XPCRootSetElem *mWrappedJSRoots;
|
XPCRootSetElem *mWrappedJSRoots;
|
||||||
XPCRootSetElem *mObjectHolderRoots;
|
XPCRootSetElem *mObjectHolderRoots;
|
||||||
|
JSDHashTable mJSHolders;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -1191,8 +1201,6 @@ public:
|
||||||
|
|
||||||
static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
|
static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
|
||||||
|
|
||||||
void Traverse(nsCycleCollectionTraversalCallback &cb);
|
|
||||||
|
|
||||||
#ifndef XPCONNECT_STANDALONE
|
#ifndef XPCONNECT_STANDALONE
|
||||||
/**
|
/**
|
||||||
* Fills the hash mapping global object to principal.
|
* Fills the hash mapping global object to principal.
|
||||||
|
@ -1931,10 +1939,11 @@ private:
|
||||||
class XPCWrappedNative : public nsIXPConnectWrappedNative
|
class XPCWrappedNative : public nsIXPConnectWrappedNative
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
|
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
|
||||||
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
|
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
|
NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
|
||||||
|
|
||||||
#ifndef XPCONNECT_STANDALONE
|
#ifndef XPCONNECT_STANDALONE
|
||||||
virtual nsIPrincipal* GetObjectPrincipal() const;
|
virtual nsIPrincipal* GetObjectPrincipal() const;
|
||||||
|
@ -2044,7 +2053,7 @@ public:
|
||||||
nsISupports* aCOMObj,
|
nsISupports* aCOMObj,
|
||||||
XPCWrappedNative** aWrapper);
|
XPCWrappedNative** aWrapper);
|
||||||
|
|
||||||
void FlatJSObjectFinalized(JSContext *cx, JSObject *obj);
|
void FlatJSObjectFinalized(JSContext *cx);
|
||||||
|
|
||||||
void SystemIsBeingShutDown(JSContext* cx);
|
void SystemIsBeingShutDown(JSContext* cx);
|
||||||
|
|
||||||
|
@ -2196,8 +2205,10 @@ private:
|
||||||
XPCWrappedNativeTearOffChunk mFirstChunk;
|
XPCWrappedNativeTearOffChunk mFirstChunk;
|
||||||
JSObject* mWrapper;
|
JSObject* mWrapper;
|
||||||
|
|
||||||
|
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
||||||
public:
|
public:
|
||||||
nsCOMPtr<nsIThread> mThread; // Don't want to overload _mOwningThread
|
nsCOMPtr<nsIThread> mThread; // Don't want to overload _mOwningThread
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -3028,7 +3039,6 @@ private:
|
||||||
JSUint32 mWrappedNativeThreadsafetyReportDepth;
|
JSUint32 mWrappedNativeThreadsafetyReportDepth;
|
||||||
#endif
|
#endif
|
||||||
PRThread* mThread;
|
PRThread* mThread;
|
||||||
nsVoidArray mNativesToReleaseArray;
|
|
||||||
|
|
||||||
static PRLock* gLock;
|
static PRLock* gLock;
|
||||||
static XPCPerThreadData* gThreads;
|
static XPCPerThreadData* gThreads;
|
||||||
|
|
|
@ -589,10 +589,6 @@ nsXPCWrappedJS::SystemIsBeingShutDown(JSRuntime* rt)
|
||||||
// work (and avoid crashing some platforms).
|
// work (and avoid crashing some platforms).
|
||||||
mJSObj = nsnull;
|
mJSObj = nsnull;
|
||||||
|
|
||||||
// There is no reason to keep this root any longer. Since we've cleared
|
|
||||||
// mJSObj our dtor will not remove the root later. So, we do it now.
|
|
||||||
JS_RemoveRootRT(rt, &mJSObj);
|
|
||||||
|
|
||||||
// Notify other wrappers in the chain.
|
// Notify other wrappers in the chain.
|
||||||
if(mNext)
|
if(mNext)
|
||||||
mNext->SystemIsBeingShutDown(rt);
|
mNext->SystemIsBeingShutDown(rt);
|
||||||
|
|
|
@ -961,7 +961,7 @@ NS_IMPL_THREADSAFE_RELEASE(XPCWrappedNative)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx, JSObject *obj)
|
XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx)
|
||||||
{
|
{
|
||||||
if(!IsValid())
|
if(!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -647,7 +647,7 @@ XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
|
||||||
XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
|
XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
|
||||||
if(!p)
|
if(!p)
|
||||||
return;
|
return;
|
||||||
p->FlatJSObjectFinalized(cx, obj);
|
p->FlatJSObjectFinalized(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -658,7 +658,7 @@ TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
|
||||||
JSObject* obj;
|
JSObject* obj;
|
||||||
|
|
||||||
obj = scope->GetGlobalJSObject();
|
obj = scope->GetGlobalJSObject();
|
||||||
NS_ASSERTION(scope, "bad scope JSObject");
|
NS_ASSERTION(obj, "bad scope JSObject");
|
||||||
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
|
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
|
||||||
|
|
||||||
obj = scope->GetPrototypeJSObject();
|
obj = scope->GetPrototypeJSObject();
|
||||||
|
@ -1035,7 +1035,7 @@ XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
|
||||||
if(!wrapper)
|
if(!wrapper)
|
||||||
return;
|
return;
|
||||||
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
|
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
|
||||||
wrapper->FlatJSObjectFinalized(cx, obj);
|
wrapper->FlatJSObjectFinalized(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_STATIC_DLL_CALLBACK(void)
|
JS_STATIC_DLL_CALLBACK(void)
|
||||||
|
|
|
@ -851,16 +851,6 @@ XPCWrappedNativeScope::DebugDump(PRInt16 depth)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
XPCWrappedNativeScope::Traverse(nsCycleCollectionTraversalCallback &cb)
|
|
||||||
{
|
|
||||||
// See TraceScopeJSObjects.
|
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mGlobalJSObject);
|
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mPrototypeJSObject);
|
|
||||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
|
||||||
mPrototypeJSFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef XPCONNECT_STANDALONE
|
#ifndef XPCONNECT_STANDALONE
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
|
|
|
@ -118,7 +118,8 @@ public: \
|
||||||
{ \
|
{ \
|
||||||
return p->InnerObject(); \
|
return p->InnerObject(); \
|
||||||
} \
|
} \
|
||||||
};
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
// Put this in your class's constructor:
|
// Put this in your class's constructor:
|
||||||
#define NS_INIT_AGGREGATED(outer) \
|
#define NS_INIT_AGGREGATED(outer) \
|
||||||
|
|
|
@ -38,6 +38,21 @@
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
PR_STATIC_CALLBACK(void)
|
||||||
|
NoteChild(PRUint32 aLangID, void *aScriptThing, void *aClosure)
|
||||||
|
{
|
||||||
|
nsCycleCollectionTraversalCallback *cb =
|
||||||
|
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||||
|
cb->NoteScriptChild(aLangID, aScriptThing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsScriptObjectTracer::TraverseScriptObjects(void *p,
|
||||||
|
nsCycleCollectionTraversalCallback &cb)
|
||||||
|
{
|
||||||
|
Trace(p, NoteChild, &cb);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsXPCOMCycleCollectionParticipant::Root(void *p)
|
nsXPCOMCycleCollectionParticipant::Root(void *p)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +87,12 @@ nsXPCOMCycleCollectionParticipant::UnmarkPurple(nsISupports *n)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(void)
|
||||||
|
nsXPCOMCycleCollectionParticipant::Trace(void *p, TraceCallback cb,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
|
nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -125,8 +125,19 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant,
|
||||||
#undef IMETHOD_VISIBILITY
|
#undef IMETHOD_VISIBILITY
|
||||||
#define IMETHOD_VISIBILITY NS_COM_GLUE
|
#define IMETHOD_VISIBILITY NS_COM_GLUE
|
||||||
|
|
||||||
|
typedef void
|
||||||
|
(* PR_CALLBACK TraceCallback)(PRUint32 langID, void *p, void *closure);
|
||||||
|
|
||||||
|
class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure) = 0;
|
||||||
|
void NS_COM_GLUE TraverseScriptObjects(void *p,
|
||||||
|
nsCycleCollectionTraversalCallback &cb);
|
||||||
|
};
|
||||||
|
|
||||||
class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
|
class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
|
||||||
: public nsCycleCollectionParticipant
|
: public nsScriptObjectTracer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
|
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
|
||||||
|
@ -135,6 +146,8 @@ public:
|
||||||
NS_IMETHOD Unlink(void *p);
|
NS_IMETHOD Unlink(void *p);
|
||||||
NS_IMETHOD Unroot(void *p);
|
NS_IMETHOD Unroot(void *p);
|
||||||
|
|
||||||
|
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
|
||||||
|
|
||||||
NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
|
NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
|
||||||
|
|
||||||
PRBool CheckForRightISupports(nsISupports *s);
|
PRBool CheckForRightISupports(nsISupports *s);
|
||||||
|
@ -153,8 +166,11 @@ public:
|
||||||
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
|
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
|
||||||
_class::NS_CYCLE_COLLECTION_INNERCLASS
|
_class::NS_CYCLE_COLLECTION_INNERCLASS
|
||||||
|
|
||||||
|
#define NS_CYCLE_COLLECTION_INNERNAME \
|
||||||
|
_cycleCollectorGlobal
|
||||||
|
|
||||||
#define NS_CYCLE_COLLECTION_NAME(_class) \
|
#define NS_CYCLE_COLLECTION_NAME(_class) \
|
||||||
_class##_cycleCollectorGlobal
|
_class::NS_CYCLE_COLLECTION_INNERNAME
|
||||||
|
|
||||||
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
|
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
|
||||||
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
|
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
|
||||||
|
@ -201,6 +217,8 @@ public:
|
||||||
} \
|
} \
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
|
||||||
|
NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Helpers for implementing nsCycleCollectionParticipant::Unlink
|
// Helpers for implementing nsCycleCollectionParticipant::Unlink
|
||||||
|
@ -323,7 +341,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class) \
|
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class) \
|
||||||
cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NATIVE_NAME(_ptr_class));
|
cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NAME(_ptr_class));
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
|
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
|
||||||
|
@ -340,18 +358,61 @@ public:
|
||||||
_element_class) \
|
_element_class) \
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class)
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
|
||||||
|
TraverseScriptObjects(tmp, cb);
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||||
return NS_OK; \
|
return NS_OK; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helpers for implementing nsScriptObjectTracer::Trace
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
|
||||||
|
void \
|
||||||
|
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
|
||||||
|
TraceCallback aCallback, \
|
||||||
|
void *aClosure) \
|
||||||
|
{ \
|
||||||
|
nsISupports *s = static_cast<nsISupports*>(p); \
|
||||||
|
NS_ASSERTION(CheckForRightISupports(s), \
|
||||||
|
"not the nsISupports pointer we expect"); \
|
||||||
|
_class *tmp = Downcast(s);
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(_class) \
|
||||||
|
void \
|
||||||
|
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
|
||||||
|
TraceCallback aCallback, \
|
||||||
|
void *aClosure) \
|
||||||
|
{ \
|
||||||
|
_class *tmp = static_cast<_class*>(p);
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(_langID, _object) \
|
||||||
|
if (_object) \
|
||||||
|
aCallback(_langID, _object, aClosure);
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(_langID, _field) \
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(_langID, tmp->_field)
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(_object) \
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(nsIProgrammingLanguage::JAVASCRIPT, \
|
||||||
|
_object)
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->_field)
|
||||||
|
|
||||||
|
#define NS_IMPL_CYCLE_COLLECTION_TRACE_END \
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Helpers for implementing a concrete nsCycleCollectionParticipant
|
// Helpers for implementing a concrete nsCycleCollectionParticipant
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
|
#define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE \
|
||||||
class NS_CYCLE_COLLECTION_INNERCLASS \
|
static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
|
||||||
: public nsXPCOMCycleCollectionParticipant \
|
|
||||||
{ \
|
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
|
||||||
public: \
|
public: \
|
||||||
NS_IMETHOD Unlink(void *p); \
|
NS_IMETHOD Unlink(void *p); \
|
||||||
NS_IMETHOD Traverse(void *p, \
|
NS_IMETHOD Traverse(void *p, \
|
||||||
|
@ -367,12 +428,31 @@ public: \
|
||||||
static nsISupports* Upcast(_class *p) \
|
static nsISupports* Upcast(_class *p) \
|
||||||
{ \
|
{ \
|
||||||
return NS_ISUPPORTS_CAST(_base*, p); \
|
return NS_ISUPPORTS_CAST(_base*, p); \
|
||||||
} \
|
}
|
||||||
};
|
|
||||||
|
#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
|
||||||
|
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||||
|
: public nsXPCOMCycleCollectionParticipant \
|
||||||
|
{ \
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
|
||||||
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
#define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \
|
#define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
|
||||||
|
|
||||||
|
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
|
||||||
|
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||||
|
: public nsXPCOMCycleCollectionParticipant \
|
||||||
|
{ \
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
|
||||||
|
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
|
||||||
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
|
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
|
||||||
|
|
||||||
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
|
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
|
||||||
class NS_CYCLE_COLLECTION_INNERCLASS \
|
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||||
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
|
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
|
||||||
|
@ -386,7 +466,8 @@ public: \
|
||||||
return static_cast<_class*>(static_cast<_base_class*>( \
|
return static_cast<_class*>(static_cast<_base_class*>( \
|
||||||
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
|
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
|
||||||
} \
|
} \
|
||||||
};
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \
|
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \
|
||||||
_base_class) \
|
_base_class) \
|
||||||
|
@ -401,7 +482,8 @@ public: \
|
||||||
return static_cast<_class*>(static_cast<_base_class*>( \
|
return static_cast<_class*>(static_cast<_base_class*>( \
|
||||||
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
|
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
|
||||||
} \
|
} \
|
||||||
};
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implements a stub UnmarkPurple function for classes that want to be
|
* This implements a stub UnmarkPurple function for classes that want to be
|
||||||
|
@ -415,31 +497,32 @@ public: \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
|
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
|
||||||
static NS_CYCLE_COLLECTION_CLASSNAME(_class) \
|
NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class);
|
||||||
NS_CYCLE_COLLECTION_NAME(_class);
|
|
||||||
|
|
||||||
#define NS_CYCLE_COLLECTION_NATIVE_INNERNAME \
|
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
|
||||||
_cycleCollectorGlobal
|
|
||||||
|
|
||||||
#define NS_CYCLE_COLLECTION_NATIVE_NAME(_class) \
|
|
||||||
_class::NS_CYCLE_COLLECTION_NATIVE_INNERNAME
|
|
||||||
|
|
||||||
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
|
|
||||||
class NS_CYCLE_COLLECTION_INNERCLASS \
|
|
||||||
: public nsCycleCollectionParticipant \
|
|
||||||
{ \
|
|
||||||
public: \
|
public: \
|
||||||
NS_IMETHOD Root(void *n); \
|
NS_IMETHOD Root(void *n); \
|
||||||
NS_IMETHOD Unlink(void *n); \
|
NS_IMETHOD Unlink(void *n); \
|
||||||
NS_IMETHOD Unroot(void *n); \
|
NS_IMETHOD Unroot(void *n); \
|
||||||
NS_IMETHOD Traverse(void *n, \
|
NS_IMETHOD Traverse(void *n, \
|
||||||
nsCycleCollectionTraversalCallback &cb); \
|
nsCycleCollectionTraversalCallback &cb);
|
||||||
}; \
|
|
||||||
static NS_CYCLE_COLLECTION_INNERCLASS \
|
|
||||||
NS_CYCLE_COLLECTION_NATIVE_INNERNAME;
|
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
|
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
|
||||||
NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NATIVE_NAME(_class);
|
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||||
|
: public nsCycleCollectionParticipant \
|
||||||
|
{ \
|
||||||
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
|
||||||
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
|
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \
|
||||||
|
class NS_CYCLE_COLLECTION_INNERCLASS \
|
||||||
|
: public nsScriptObjectTracer \
|
||||||
|
{ \
|
||||||
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
|
||||||
|
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
|
||||||
|
}; \
|
||||||
|
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
|
||||||
|
|
||||||
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
|
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
|
||||||
NS_IMETHODIMP \
|
NS_IMETHODIMP \
|
||||||
|
|
Загрузка…
Ссылка в новой задаче