Backing out to fix orange.
Backing out to fix orange.
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -746,16 +746,52 @@ public:
}
/**
* Return the content policy service
*/
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
* of a given type that apply to this content or any of its ancestors.
* The method has the side effect to call document's MayDispatchMutationEvent
* using aTargetForSubtreeModified as the parameter.
*
* @param aNode The node to search for listeners
* @param aType The type of listener (NS_EVENT_BITS_MUTATION_*)
* @param aTargetForSubtreeModified The node which is the target of the
@@ -959,83 +995,50 @@ public:
}
}
/**
* Unbinds the content from the tree and nulls it out if it's not null.
*/
static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
- /**
- * Keep script object aNewObject, held by aScriptObjectHolder, alive.
- *
- * 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)
- {
- if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
- return aWasHoldingObjects ? NS_OK :
- HoldJSObjects(aScriptObjectHolder, aTracer);
- }
-
- return HoldScriptObject(aLangID, aNewObject);
- }
+ static nsresult HoldScriptObject(PRUint32 aLangID, void *aObject);
+ static nsresult DropScriptObject(PRUint32 aLangID, void *aObject);
- /**
- * 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)
+ class ScriptObjectHolder
{
- if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
- return DropJSObjects(aScriptObjectHolder);
+ public:
+ ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
+ mObject(nsnull)
+ {
+ MOZ_COUNT_CTOR(ScriptObjectHolder);
+ }
+ ~ScriptObjectHolder()
+ {
+ MOZ_COUNT_DTOR(ScriptObjectHolder);
+ if (mObject)
+ DropScriptObject(mLangID, mObject);
}
-
- aTracer->Trace(aScriptObjectHolder, DropScriptObject, nsnull);
-
- return NS_OK;
- }
-
- /**
- * Keep the JS objects held by aScriptObjectHolder alive.
- *
- * @param aScriptObjectHolder the object that holds JS objects that we want to
- * keep alive
- * @param aTracer the tracer for aScriptObject
- */
- static nsresult HoldJSObjects(void* aScriptObjectHolder,
- nsScriptObjectTracer* aTracer);
-
- /**
- * 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);
+ nsresult set(void *aObject)
+ {
+ NS_ASSERTION(aObject, "unexpected null object");
+ NS_ASSERTION(!mObject, "already have an object");
+ nsresult rv = HoldScriptObject(mLangID, aObject);
+ if (NS_SUCCEEDED(rv)) {
+ mObject = aObject;
+ }
+ return rv;
+ }
+ void traverse(nsCycleCollectionTraversalCallback &cb)
+ {
+ cb.NoteScriptChild(mLangID, mObject);
+ }
+ PRUint32 mLangID;
+ void *mObject;
+ };
/**
* Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
*/
static PRUint32 GetKBStateControlStatusFromIMEStatus(PRUint32 aState);
/*
* Notify when the first XUL menu is opened and when the all XUL menus are
@@ -1112,20 +1115,16 @@ private:
JSObject *aNewGlobal,
nsIDocument *aOldDocument,
nsIDocument *aNewDocument);
static nsresult EnsureStringBundle(PropertiesFile aFile);
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 nsIXPConnect *sXPConnect;
static nsIScriptSecurityManager *sSecurityManager;
static nsIThreadJSContextStack *sThreadJSContextStack;
@@ -1157,36 +1156,33 @@ private:
static nsILineBreaker* sLineBreaker;
static nsIWordBreaker* sWordBreaker;
static nsICaseConversion* sCaseConv;
// Holds pointers to nsISupports* that should be released at shutdown
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 PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
- static PRUint32 sJSGCThingRootCount;
#ifdef IBMBIDI
static nsIBidiKeyboard* sBidiKeyboard;
#endif
static PRBool sInitialized;
};
-#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
{
public:
nsCxPusher();
~nsCxPusher(); // Calls Pop();
// Returns PR_FALSE if something erroneous happened.
PRBool Push(nsISupports *aCurrentTarget);
@@ -1199,48 +1195,43 @@ private:
};
class nsAutoGCRoot {
public:
// aPtr should be the pointer to the jsval we want to protect
nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
mPtr(aPtr)
{
- mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
+ mResult = *aResult =
+ nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
}
// aPtr should be the pointer to the JSObject* we want to protect
nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
mPtr(aPtr)
{
- mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
+ mResult = *aResult =
+ nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
}
// aPtr should be the pointer to the thing we want to protect
nsAutoGCRoot(void* aPtr, nsresult* aResult) :
mPtr(aPtr)
{
- mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
+ mResult = *aResult =
+ nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
}
~nsAutoGCRoot() {
if (NS_SUCCEEDED(mResult)) {
- RemoveJSGCRoot(mPtr);
+ nsContentUtils::RemoveJSGCRoot(mPtr);
}
}
- static void Shutdown();
-
private:
- static nsresult AddJSGCRoot(void *aPtr, const char* aName);
- static nsresult RemoveJSGCRoot(void *aPtr);
-
- static nsIJSRuntimeService* sJSRuntimeService;
- static JSRuntime* sJSScriptRuntime;
-
void* mPtr;
nsresult mResult;
};
#define NS_AUTO_GCROOT_PASTE2(tok,line) tok##line
#define NS_AUTO_GCROOT_PASTE(tok,line) \
NS_AUTO_GCROOT_PASTE2(tok,line)
#define NS_AUTO_GCROOT(ptr, result) \ \
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -175,25 +175,25 @@ nsDataHashtable<nsISupportsHashKey, Even
nsIStringBundleService *nsContentUtils::sStringBundleService;
nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
nsIContentPolicy *nsContentUtils::sContentPolicyService;
PRBool nsContentUtils::sTriedToGetContentPolicy = PR_FALSE;
nsILineBreaker *nsContentUtils::sLineBreaker;
nsIWordBreaker *nsContentUtils::sWordBreaker;
nsICaseConversion *nsContentUtils::sCaseConv;
nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
+nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
+JSRuntime *nsContentUtils::sJSScriptRuntime;
+PRInt32 nsContentUtils::sJSScriptRootCount = 0;
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
-PRUint32 nsContentUtils::sJSGCThingRootCount;
#ifdef IBMBIDI
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
#endif
-nsIJSRuntimeService *nsAutoGCRoot::sJSRuntimeService;
-JSRuntime *nsAutoGCRoot::sJSScriptRuntime;
PRBool nsContentUtils::sInitialized = PR_FALSE;
static PLDHashTable sEventListenerManagersHash;
class EventListenerManagerMapEntry : public PLDHashEntryHdr
{
public:
@@ -666,18 +666,17 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sContentPolicyService);
sTriedToGetContentPolicy = PR_FALSE;
PRInt32 i;
for (i = 0; i < PRInt32(PropertiesFile_COUNT); ++i)
NS_IF_RELEASE(sStringBundles[i]);
NS_IF_RELEASE(sStringBundleService);
NS_IF_RELEASE(sConsoleService);
NS_IF_RELEASE(sDOMScriptObjectFactory);
- if (sJSGCThingRootCount == 0 && sXPConnect)
- NS_RELEASE(sXPConnect);
+ NS_IF_RELEASE(sXPConnect);
NS_IF_RELEASE(sSecurityManager);
NS_IF_RELEASE(sThreadJSContextStack);
NS_IF_RELEASE(sNameSpaceManager);
NS_IF_RELEASE(sParserService);
NS_IF_RELEASE(sIOService);
NS_IF_RELEASE(sLineBreaker);
NS_IF_RELEASE(sWordBreaker);
NS_IF_RELEASE(sCaseConv);
@@ -717,18 +716,16 @@ nsContentUtils::Shutdown()
// it could leave dangling references in DOMClassInfo's preserved
// wrapper table.
if (sEventListenerManagersHash.entryCount == 0) {
PL_DHashTableFinish(&sEventListenerManagersHash);
sEventListenerManagersHash.ops = nsnull;
}
}
-
- nsAutoGCRoot::Shutdown();
}
static PRBool IsCallerTrustedForCapability(const char* aCapability)
{
// The secman really should handle UniversalXPConnect case, since that
// should include UniversalBrowserRead... doesn't right now, though.
PRBool hasCap;
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
@@ -2667,17 +2664,17 @@ nsContentUtils::GetContentPolicy()
sTriedToGetContentPolicy = PR_TRUE;
}
return sContentPolicyService;
}
// static
nsresult
-nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName)
+nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
{
if (!sJSScriptRuntime) {
nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
&sJSRuntimeService);
NS_ENSURE_TRUE(sJSRuntimeService, rv);
sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
if (!sJSScriptRuntime) {
@@ -2685,34 +2682,48 @@ nsAutoGCRoot::AddJSGCRoot(void* aPtr, co
NS_WARNING("Unable to get JS runtime from JS runtime service");
return NS_ERROR_FAILURE;
}
}
PRBool ok;
ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
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");
return NS_ERROR_OUT_OF_MEMORY;
}
+ // We now have one more root we added to the runtime
+ ++sJSScriptRootCount;
+
return NS_OK;
}
/* static */
nsresult
-nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
+nsContentUtils::RemoveJSGCRoot(void* aPtr)
{
if (!sJSScriptRuntime) {
NS_NOTREACHED("Trying to remove a JS GC root when none were added");
return NS_ERROR_UNEXPECTED;
}
::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
+ if (--sJSScriptRootCount == 0) {
+ NS_RELEASE(sJSRuntimeService);
+ sJSScriptRuntime = nsnull;
+ }
+
return NS_OK;
}
// static
PRBool
nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
{
const char* name;
@@ -3506,18 +3517,16 @@ nsContentUtils::GetDOMScriptObjectFactor
return sDOMScriptObjectFactory;
}
/* static */
nsresult
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
{
NS_ASSERTION(aObject, "unexpected null object");
- NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
- "Should use HoldJSObjects.");
nsresult rv;
PRUint32 langIndex = NS_STID_INDEX(aLangID);
nsIScriptRuntime *runtime = sScriptRuntimes[langIndex];
if (!runtime) {
nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
@@ -3534,57 +3543,27 @@ nsContentUtils::HoldScriptObject(PRUint3
++sScriptRootCount[langIndex];
NS_LOG_ADDREF(sScriptRuntimes[langIndex], sScriptRootCount[langIndex],
"HoldScriptObject", sizeof(void*));
return NS_OK;
}
/* static */
-void
-nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject,
- void *aClosure)
+nsresult
+nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject)
{
NS_ASSERTION(aObject, "unexpected null object");
- NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
- "Should use DropJSObjects.");
PRUint32 langIndex = NS_STID_INDEX(aLangID);
NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
"HoldScriptObject");
- sScriptRuntimes[langIndex]->DropScriptObject(aObject);
+ nsresult rv = sScriptRuntimes[langIndex]->DropScriptObject(aObject);
if (--sScriptRootCount[langIndex] == 0) {
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;
}
/* static */
PRUint32
nsContentUtils::GetKBStateControlStatusFromIMEStatus(PRUint32 aState)
{
switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
@@ -3730,16 +3709,8 @@ nsContentUtils::IsNativeAnonymous(nsICon
aContent->GetParent()->NodeInfo()->
Equals(nsGkAtoms::use, kNameSpaceID_SVG)),
"Native anonymous node with wrong binding parent");
aContent = bindingParent;
}
return PR_FALSE;
}
-
-/* static */
-void
-nsAutoGCRoot::Shutdown()
-{
- NS_RELEASE(sJSRuntimeService);
- sJSScriptRuntime = nsnull;
-}
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -300,17 +300,17 @@ TraverseKey(nsISupports* aKey, nsInserti
cb.NoteXPCOMChild(aKey);
if (aData) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(*aData, nsXBLInsertionPoint)
}
return PL_DHASH_NEXT;
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
// mPrototypeBinding is weak.
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
// XXX What about mNextBinding and mInsertionPointTable?
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXBLBinding)
cb.NoteXPCOMChild(tmp->mPrototypeBinding->XBLDocumentInfo());
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -447,53 +447,31 @@ TraverseProtos(nsHashKey *aKey, void *aD
static PRIntn PR_CALLBACK
UnlinkProtos(nsHashKey *aKey, void *aData, void* aClosure)
{
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
proto->Unlink();
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_UNLINK_BEGIN(nsXBLDocumentInfo)
if (tmp->mBindingTable) {
tmp->mBindingTable->Enumerate(UnlinkProtos, nsnull);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalObject)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
if (tmp->mBindingTable) {
tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
}
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
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_ENTRY(nsIXBLDocumentInfo)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXBLDocumentInfo)
NS_INTERFACE_MAP_END
@@ -524,20 +502,17 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsI
nsXBLDocumentInfo::~nsXBLDocumentInfo()
{
/* destructor code */
if (mGlobalObject) {
// remove circular reference
mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
mGlobalObject->ClearGlobalObjectOwner(); // just in case
}
- if (mBindingTable) {
- NS_DROP_JS_OBJECTS(this, nsXBLDocumentInfo);
- delete mBindingTable;
- }
+ delete mBindingTable;
}
NS_IMETHODIMP
nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding** aResult)
{
*aResult = nsnull;
if (!mBindingTable)
return NS_OK;
@@ -561,23 +536,18 @@ DeletePrototypeBinding(nsHashKey* aKey,
nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding*>(aData);
delete binding;
return PR_TRUE;
}
NS_IMETHODIMP
nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
{
- if (!mBindingTable) {
+ if (!mBindingTable)
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);
nsCStringKey key(flat.get());
mBindingTable->Put(&key, aBinding);
return NS_OK;
}
--- a/content/xbl/src/nsXBLDocumentInfo.h
+++ b/content/xbl/src/nsXBLDocumentInfo.h
@@ -67,18 +67,18 @@ public:
NS_IMETHOD FlushSkinStylesheets();
NS_IMETHOD_(PRBool) IsChrome() { return mIsChrome; }
// nsIScriptGlobalObjectOwner methods
virtual nsIScriptGlobalObject* GetScriptGlobalObject();
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
- nsIXBLDocumentInfo)
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
+ nsIXBLDocumentInfo)
private:
nsCOMPtr<nsIDocument> mDocument;
PRPackedBool mScriptAccess;
PRPackedBool mIsChrome;
// the binding table owns each nsXBLPrototypeBinding
nsObjectHashtable* mBindingTable;
// non-owning pointer to the first binding in the table
--- a/content/xbl/src/nsXBLInsertionPoint.cpp
+++ b/content/xbl/src/nsXBLInsertionPoint.cpp
@@ -59,17 +59,17 @@ nsXBLInsertionPoint::Release()
if (mRefCnt == 0) {
mRefCnt = 1;
delete this;
return 0;
}
return mRefCnt;
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mElements)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDefaultContentTemplate)
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -195,28 +195,28 @@ nsXBLProtoImpl::CompilePrototypeMembers(
DestroyMembers(curr);
return rv;
}
}
return NS_OK;
}
void
-nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const
+nsXBLProtoImpl::Traverse(nsCycleCollectionTraversalCallback &cb) const
{
// 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
// members.
if (!mClassObject) {
return;
}
nsXBLProtoImplMember *member;
for (member = mMembers; member; member = member->GetNext()) {
- member->Trace(aCallback, aClosure);
+ member->Traverse(cb);
}
}
void
nsXBLProtoImpl::Unlink()
{
if (mClassObject) {
DestroyMembers(nsnull);
--- a/content/xbl/src/nsXBLProtoImpl.h
+++ b/content/xbl/src/nsXBLProtoImpl.h
@@ -85,17 +85,17 @@ public:
}
void SetFieldList(nsXBLProtoImplField* aFieldList)
{
delete mFields;
mFields = aFieldList;
}
- void Trace(TraceCallback aCallback, void *aClosure) const;
+ void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void Unlink();
nsXBLProtoImplField* FindField(const nsString& aFieldName) const;
// Resolve all the fields for this implementation on the object |obj| False
// return means a JS exception was set.
PRBool ResolveAllFields(JSContext *cx, JSObject *obj) const;
--- a/content/xbl/src/nsXBLProtoImplMember.h
+++ b/content/xbl/src/nsXBLProtoImplMember.h
@@ -42,21 +42,21 @@
#include "nsIAtom.h"
#include "nsString.h"
#include "jsapi.h"
#include "nsIContent.h"
#include "nsString.h"
#include "nsIJSRuntimeService.h"
#include "nsIServiceManager.h"
#include "nsReadableUtils.h"
-#include "nsCycleCollectionParticipant.h"
class nsIScriptContext;
struct JSRuntime;
class nsIJSRuntimeService;
+class nsCycleCollectionTraversalCallback;
struct nsXBLTextWithLineNumber
{
PRUnichar* mText;
PRUint32 mLineNumber;
nsXBLTextWithLineNumber() :
mText(nsnull),
@@ -109,17 +109,17 @@ public:
nsIContent* aBoundElement,
void* aScriptObject,
void* aTargetClassObject,
const nsCString& aClassStr) = 0;
virtual nsresult CompileMember(nsIScriptContext* aContext,
const nsCString& aClassStr,
void* aClassObject)=0;
- virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0;
+ virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const = 0;
protected:
friend class nsAutoGCRoot;
nsXBLProtoImplMember* mNext; // The members of an implementation are chained.
PRUnichar* mName; // The name of the field, method, or property.
};
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -67,16 +67,18 @@ nsXBLProtoImplMethod::~nsXBLProtoImplMet
}
void
nsXBLProtoImplMethod::Destroy(PRBool aIsCompiled)
{
NS_PRECONDITION(aIsCompiled == mIsCompiled,
"Incorrect aIsCompiled in nsXBLProtoImplMethod::Destroy");
if (aIsCompiled) {
+ if (mJSMethodObject)
+ nsContentUtils::RemoveJSGCRoot(&mJSMethodObject);
mJSMethodObject = nsnull;
}
else {
delete mUncompiledMethod;
mUncompiledMethod = nsnull;
}
}
@@ -256,35 +258,35 @@ nsXBLProtoImplMethod::CompileMember(nsIS
mUncompiledMethod = nsnull;
return rv;
}
mJSMethodObject = methodObject;
if (methodObject) {
// Root the compiled prototype script object.
+ rv = nsContentUtils::AddJSGCRoot(&mJSMethodObject,
+ "nsXBLProtoImplMethod::mJSMethodObject");
if (NS_FAILED(rv)) {
mJSMethodObject = nsnull;
}
}
#ifdef DEBUG
mIsCompiled = NS_SUCCEEDED(rv);
#endif
return rv;
}
void
-nsXBLProtoImplMethod::Trace(TraceCallback aCallback, void *aClosure) const
+nsXBLProtoImplMethod::Traverse(nsCycleCollectionTraversalCallback &cb) const
{
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
- if (mJSMethodObject) {
- aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject, aClosure);
- }
+ cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject);
}
nsresult
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
{
NS_PRECONDITION(mIsCompiled, "Can't execute uncompiled method");
if (!mJSMethodObject) {
--- a/content/xbl/src/nsXBLProtoImplMethod.h
+++ b/content/xbl/src/nsXBLProtoImplMethod.h
@@ -124,17 +124,17 @@ public:
nsIContent* aBoundElement,
void* aScriptObject,
void* aTargetClassObject,
const nsCString& aClassStr);
virtual nsresult CompileMember(nsIScriptContext* aContext,
const nsCString& aClassStr,
void* aClassObject);
- virtual void Trace(TraceCallback aCallback, void *aClosure) const;
+ virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
protected:
union {
nsXBLUncompiledMethod* mUncompiledMethod; // An object that represents the method before being compiled.
JSObject * mJSMethodObject; // The JS object for the method (after compilation)
};
#ifdef DEBUG
--- a/content/xbl/src/nsXBLProtoImplProperty.cpp
+++ b/content/xbl/src/nsXBLProtoImplProperty.cpp
@@ -82,24 +82,24 @@ nsXBLProtoImplProperty::~nsXBLProtoImplP
void
nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
{
NS_PRECONDITION(aIsCompiled == mIsCompiled,
"Incorrect aIsCompiled in nsXBLProtoImplProperty::Destroy");
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
- mJSGetterObject = nsnull;
+ nsContentUtils::RemoveJSGCRoot(&mJSGetterObject);
}
else {
delete mGetterText;
}
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
- mJSSetterObject = nsnull;
+ nsContentUtils::RemoveJSGCRoot(&mJSSetterObject);
}
else {
delete mSetterText;
}
mGetterText = mSetterText = nsnull;
}
@@ -263,16 +263,19 @@ nsXBLProtoImplProperty::CompileMember(ns
// Make sure we free mGetterText here before setting mJSGetterObject, since
// that'll overwrite mGetterText
delete mGetterText;
deletedGetter = PR_TRUE;
mJSGetterObject = getterObject;
if (mJSGetterObject && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
+ // Root the compiled prototype script object.
+ rv = nsContentUtils::AddJSGCRoot(&mJSGetterObject,
+ "nsXBLProtoImplProperty::mJSGetterObject");
}
if (NS_FAILED(rv)) {
mJSGetterObject = nsnull;
mJSAttributes &= ~JSPROP_GETTER;
/*chaining to return failure*/
}
}
} // if getter is not empty
@@ -312,16 +315,19 @@ nsXBLProtoImplProperty::CompileMember(ns
// Make sure we free mSetterText here before setting mJSGetterObject, since
// that'll overwrite mSetterText
delete mSetterText;
deletedSetter = PR_TRUE;
mJSSetterObject = setterObject;
if (mJSSetterObject && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
+ // Root the compiled prototype script object.
+ rv = nsContentUtils::AddJSGCRoot(&mJSSetterObject,
+ "nsXBLProtoImplProperty::mJSSetterObject");
}
if (NS_FAILED(rv)) {
mJSSetterObject = nsnull;
mJSAttributes &= ~JSPROP_SETTER;
/*chaining to return failure*/
}
}
} // if setter wasn't empty....
@@ -334,20 +340,20 @@ nsXBLProtoImplProperty::CompileMember(ns
#ifdef DEBUG
mIsCompiled = NS_SUCCEEDED(rv);
#endif
return rv;
}
void
-nsXBLProtoImplProperty::Trace(TraceCallback aCallback, void *aClosure) const
+nsXBLProtoImplProperty::Traverse(nsCycleCollectionTraversalCallback &cb) const
{
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
- if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
- aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject, aClosure);
+ if (mJSAttributes & JSPROP_GETTER) {
+ cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject);
}
- if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
- aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject, aClosure);
+ if (mJSAttributes & JSPROP_SETTER) {
+ cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject);
}
}
--- a/content/xbl/src/nsXBLProtoImplProperty.h
+++ b/content/xbl/src/nsXBLProtoImplProperty.h
@@ -67,17 +67,17 @@ public:
nsIContent* aBoundElement,
void* aScriptObject,
void* aTargetClassObject,
const nsCString& aClassStr);
virtual nsresult CompileMember(nsIScriptContext* aContext,
const nsCString& aClassStr,
void* aClassObject);
- virtual void Trace(TraceCallback aCallback, void *aClosure) const;
+ virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
protected:
union {
// The raw text for the getter (prior to compilation).
nsXBLTextWithLineNumber* mGetterText;
// The JS object for the getter (after compilation)
JSObject * mJSGetterObject;
};
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -239,17 +239,17 @@ private:
static nsFixedSizeAllocator* kPool;
static PRUint32 gRefCnt;
};
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPointEntry)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
if (tmp->mDefaultContent) {
// mDefaultContent is a sort of anonymous content within the XBL
// document, and we own and manage it. Unhook it here, since we're going
// away.
tmp->mDefaultContent->UnbindFromTree();
tmp->mDefaultContent = nsnull;
@@ -350,39 +350,34 @@ TraverseBinding(nsHashKey *aKey, void *a
cb->NoteXPCOMChild(static_cast<nsISupports*>(aData));
return kHashEnumerateNext;
}
void
nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const
{
cb.NoteXPCOMChild(mBinding);
+ if (mImplementation)
+ mImplementation->Traverse(cb);
if (mResources)
cb.NoteXPCOMChild(mResources->mLoader);
if (mInsertionPointTable)
mInsertionPointTable->Enumerate(TraverseInsertionPoint, &cb);
if (mInterfaceTable)
mInterfaceTable->Enumerate(TraverseBinding, &cb);
}
void
nsXBLPrototypeBinding::Unlink()
{
if (mImplementation)
mImplementation->Unlink();
}
void
-nsXBLPrototypeBinding::Trace(TraceCallback aCallback, void *aClosure) const
-{
- if (mImplementation)
- mImplementation->Trace(aCallback, aClosure);
-}
-
-void
nsXBLPrototypeBinding::Initialize()
{
nsIContent* content = GetImmediateChild(nsGkAtoms::content);
if (content) {
// Make sure to construct the attribute table first, since constructing the
// insertion point table removes some of the subtrees, which makes them
// unreachable by walking our DOM.
ConstructAttributeTable(content);
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -193,17 +193,16 @@ public:
// this with the Initialize() method, which must be called after the
// binding's handlers, properties, etc are all set.
nsresult Init(const nsACString& aRef,
nsIXBLDocumentInfo* aInfo,
nsIContent* aElement);
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void Unlink();
- void Trace(TraceCallback aCallback, void *aClosure) const;
// Static members
static PRUint32 gRefCnt;
static nsFixedSizeAllocator* kAttrPool;
// Internal member functions.
// XXXbz GetImmediateChild needs to be public to be called by SetAttrs,
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -50,16 +50,17 @@
* Modifications to Mozilla code or documentation
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
* use in OS2
*/
+#include "jsapi.h" // for JS_AddNamedRoot and JS_RemoveRootRT
#include "nsCOMPtr.h"
#include "nsDOMCID.h"
#include "nsDOMError.h"
#include "nsDOMString.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsHashtable.h"
#include "nsIAtom.h"
@@ -696,18 +697,17 @@ nsScriptEventHandlerOwnerTearoff::Compil
nsresult rv;
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
// XXX sXBL/XBL2 issue! Owner or current document?
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
nsIScriptContext *context;
- nsXULPrototypeElement *elem = mElement->mPrototype;
- if (elem && xuldoc) {
+ if (mElement->mPrototype && xuldoc) {
// It'll be shared among the instances of the prototype.
// Use the prototype document's special context. Because
// scopeObject is null, the JS engine has no other source of
// <the-new-shared-event-handler>.__proto__ than to look in
// cx->globalObject for Function.prototype. That prototype
// keeps the global object alive, so if we use this document's
// global object, we'll be putting something in the prototype
@@ -750,26 +750,19 @@ nsScriptEventHandlerOwnerTearoff::Compil
if (NS_FAILED(rv)) return rv;
nsXULPrototypeAttribute *attr =
mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
if (attr) {
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
// take a copy of the event handler, and tell the language about it.
if (aHandler) {
- NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
-
rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
- elem,
- &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
- aHandler,
- elem->mHoldsScriptObject);
+ aHandler);
if (NS_FAILED(rv)) return rv;
-
- elem->mHoldsScriptObject = PR_TRUE;
}
attr->mEventHandler = (void *)aHandler;
}
return NS_OK;
}
void
@@ -2353,61 +2346,58 @@ nsXULElement::RecompileScriptEventListen
nsAutoString value;
GetAttr(kNameSpaceID_None, attr, value);
AddScriptEventListener(attr, value, PR_TRUE);
}
}
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsXULPrototypeNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXULPrototypeNode)
if (tmp->mType == nsXULPrototypeNode::eType_Element) {
nsXULPrototypeElement *elem =
static_cast<nsXULPrototypeElement*>(tmp);
PRUint32 i;
+ for (i = 0; i < elem->mNumAttributes; ++i) {
+ cb.NoteScriptChild(elem->mScriptTypeID,
+ elem->mAttributes[i].mEventHandler);
+ }
for (i = 0; i < elem->mNumChildren; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i],
nsXULPrototypeNode)
}
}
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+ else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
+ static_cast<nsXULPrototypeScript*>(tmp)->mScriptObject.traverse(cb);
+ }
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_UNROOT_NATIVE(nsXULPrototypeNode, Release)
//----------------------------------------------------------------------
//
// nsXULPrototypeAttribute
//
nsXULPrototypeAttribute::~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;
+ }
}
//----------------------------------------------------------------------
//
// nsXULPrototypeElement
//
@@ -2684,29 +2674,16 @@ nsXULPrototypeElement::SetAttrAt(PRUint3
// Don't abort if parsing failed, it could just be malformed css.
}
mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
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::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 aVersion)
: nsXULPrototypeNode(eType_Script),
mLineNo(aLineNo),
@@ -2719,17 +2696,16 @@ nsXULPrototypeScript::nsXULPrototypeScri
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
"The language ID must be known and constant");
}
nsXULPrototypeScript::~nsXULPrototypeScript()
{
- Unlink();
}
nsresult
nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
nsIScriptGlobalObject* aGlobal,
const nsCOMArray<nsINodeInfo> *aNodeInfos)
{
nsIScriptContext *context = aGlobal->GetScriptContext(
@@ -2837,17 +2813,17 @@ nsXULPrototypeScript::Deserialize(nsIObj
NS_ASSERTION(context != nsnull, "Have no context for deserialization");
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
nsScriptObjectHolder newScriptObject(context);
rv = context->Deserialize(aStream, newScriptObject);
if (NS_FAILED(rv)) {
NS_WARNING("Language deseralization failed");
return rv;
}
- Set(newScriptObject);
+ mScriptObject.set(newScriptObject);
return NS_OK;
}
nsresult
nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
nsIScriptGlobalObject* aGlobal)
{
@@ -2890,17 +2866,17 @@ nsXULPrototypeScript::DeserializeOutOfLi
// setting langID to UNKNOWN in the nsXULPrototypeScript
// ctor and not setting it until the scriptObject is set -
// code that pre-fetches these globals will then start
// asserting.)
if (mScriptObject.mLangID != newLangID) {
NS_ERROR("XUL cache gave different language?");
return NS_ERROR_UNEXPECTED;
}
- Set(newScriptObject);
+ mScriptObject.set(newScriptObject);
}
}
}
if (! mScriptObject.mObject) {
nsCOMPtr<nsIURI> oldURI;
if (mSrcURI) {
@@ -3016,17 +2992,17 @@ nsXULPrototypeScript::Compile(const PRUn
aDocument->NodePrincipal(),
urlspec.get(),
aLineNo,
mLangVersion,
newScriptObject);
if (NS_FAILED(rv))
return rv;
- Set(newScriptObject);
+ mScriptObject.set(newScriptObject);
return rv;
}
//----------------------------------------------------------------------
//
// nsXULPrototypeText
//
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -3724,18 +3724,17 @@ nsresult NS_CreateJSRuntime(nsIScriptRun
// When consumed by non-JS (eg, another script language), conversion is done
// on-the-fly.
class nsJSArgArray : public nsIJSArgArray, public nsIArray {
public:
nsJSArgArray(JSContext *aContext, PRUint32 argc, jsval *argv, nsresult *prv);
~nsJSArgArray();
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSArgArray,
- nsIJSArgArray)
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSArgArray, nsIJSArgArray)
// nsIArray
NS_DECL_NSIARRAY
// nsIJSArgArray
nsresult GetArgs(PRUint32 *argc, void **argv);
void ReleaseJSObjects();
@@ -3755,62 +3754,65 @@ nsJSArgArray::nsJSArgArray(JSContext *aC
// copy the array - we don't know its lifetime, and ours is tied to xpcom
// refcounting. Alloc zero'd array so cleanup etc is safe.
mArgv = (jsval *) PR_CALLOC(argc * sizeof(jsval));
if (!mArgv) {
*prv = NS_ERROR_OUT_OF_MEMORY;
return;
}
- // Callers are allowed to pass in a nutll argv even for argc > 0. They can
- // then use GetArgs to initialized the values.
- if (argv) {
- for (PRUint32 i = 0; i < argc; ++i)
+ JSAutoRequest ar(aContext);
+ for (PRUint32 i = 0; i < argc; ++i) {
+ if (argv)
mArgv[i] = argv[i];
+ if (!::JS_AddNamedRoot(aContext, &mArgv[i], "nsJSArgArray.mArgv[i]")) {
+ *prv = NS_ERROR_UNEXPECTED;
+ return;
+ }
}
- if (argc > 0)
- *prv = NS_HOLD_JS_OBJECTS(this, nsJSArgArray);
+ *prv = NS_OK;
}
nsJSArgArray::~nsJSArgArray()
{
ReleaseJSObjects();
}
void
nsJSArgArray::ReleaseJSObjects()
{
- if (mArgc > 0)
- NS_DROP_JS_OBJECTS(this, nsJSArgArray);
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);
}
mArgc = 0;
}
// QueryInterface implementation for nsJSArgArray
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSArgArray)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
tmp->ReleaseJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray)
- jsval *argv = tmp->mArgv;
- if (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))
+ {
+ jsval *argv = tmp->mArgv;
+ if (argv) {
+ jsval *end;
+ for (end = argv + tmp->mArgc; argv < end; ++argv) {
+ if (JSVAL_IS_OBJECT(*argv))
+ cb.NoteScriptChild(JAVASCRIPT, JSVAL_TO_OBJECT(*argv));
+ }
}
}
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSArgArray)
NS_INTERFACE_MAP_ENTRY(nsIArray)
NS_INTERFACE_MAP_ENTRY(nsIJSArgArray)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSArgArray)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsJSArgArray, nsIJSArgArray)
--- a/dom/src/base/nsJSTimeoutHandler.cpp
+++ b/dom/src/base/nsJSTimeoutHandler.cpp
@@ -54,17 +54,17 @@ static const char kSetIntervalStr[] = "s
static const char kSetTimeoutStr[] = "setTimeout";
// Our JS nsIScriptTimeoutHandler implementation.
class nsJSScriptTimeoutHandler: public nsIScriptTimeoutHandler
{
public:
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSScriptTimeoutHandler)
+ NS_DECL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
nsJSScriptTimeoutHandler();
~nsJSScriptTimeoutHandler();
virtual const PRUnichar *GetHandlerText();
virtual void *GetScriptObject() {
return mFunObj;
}
@@ -113,24 +113,19 @@ private:
// QueryInterface implementation for nsJSScriptTimeoutHandler
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSScriptTimeoutHandler)
tmp->ReleaseJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSScriptTimeoutHandler)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgv)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+ cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mFunObj);
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_ENTRY(nsIScriptTimeoutHandler)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSScriptTimeoutHandler)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSScriptTimeoutHandler)
@@ -146,21 +141,59 @@ nsJSScriptTimeoutHandler::~nsJSScriptTim
{
ReleaseJSObjects();
}
void
nsJSScriptTimeoutHandler::ReleaseJSObjects()
{
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) {
- NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
+ ::JS_RemoveRootRT(rt, &mExpr);
mExpr = nsnull;
} else if (mFunObj) {
- NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
+ ::JS_RemoveRootRT(rt, &mFunObj);
mFunObj = nsnull;
} else {
NS_WARNING("No func and no expr - roots may not have been removed");
}
}
}
nsresult
@@ -242,29 +275,31 @@ nsJSScriptTimeoutHandler::Init(nsIScript
*aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
// Return an error that nsGlobalWindow can recognize and turn into NS_OK.
ncc->SetExceptionWasThrown(PR_TRUE);
return NS_ERROR_DOM_TYPE_ERR;
}
if (expr) {
- rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (!::JS_AddNamedRoot(cx, &mExpr, "timeout.mExpr")) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
mExpr = expr;
// Get the calling location.
const char *filename;
if (nsJSUtils::GetCallingLocation(cx, &filename, &mLineNo)) {
mFileName.Assign(filename);
}
} else if (funobj) {
- rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (!::JS_AddNamedRoot(cx, &mFunObj, "timeout.mFunObj")) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
mFunObj = funobj;
// Create our arg array - leave an extra slot for a secret final argument
// that indicates to the called function how "late" the timeout is. We
// will fill that in when SetLateness is called.
nsCOMPtr<nsIArray> array;
rv = NS_CreateJSArgv(cx, (argc > 1) ? argc - 1 : argc, nsnull,
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -76,40 +76,34 @@ nsJSEventListener::nsJSEventListener(nsI
nsISupports *aTarget)
: nsIJSEventListener(aContext, aScopeObject, aTarget),
mReturnResult(nsReturnResult_eNotSet)
{
// aScopeObject is the inner window's JS object, which we need to lock
// until we are done with it.
NS_ASSERTION(aScopeObject && aContext,
"EventListener with no context or scope?");
- NS_HOLD_JS_OBJECTS(this, nsJSEventListener);
+ aContext->HoldScriptObject(aScopeObject);
}
nsJSEventListener::~nsJSEventListener()
{
- if (mContext)
- NS_DROP_JS_OBJECTS(this, nsJSEventListener);
+ mContext->DropScriptObject(mScopeObject);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+ cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mScopeObject);
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_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIJSEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsJSEventListener, nsIDOMEventListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsJSEventListener, nsIDOMEventListener)
--- a/dom/src/events/nsJSEventListener.h
+++ b/dom/src/events/nsJSEventListener.h
@@ -60,18 +60,18 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
// nsIDOMEventListener interface
NS_DECL_NSIDOMEVENTLISTENER
// nsIJSEventListener interface
virtual void SetEventName(nsIAtom* aName);
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSEventListener,
- nsIDOMEventListener)
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSEventListener,
+ nsIDOMEventListener)
protected:
nsCOMPtr<nsIAtom> mEventName;
enum nsReturnResult {
nsReturnResult_eNotSet,
nsReturnResult_eReverseReturnResult,
nsReturnResult_eDoNotReverseReturnResult
};
--- a/js/src/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl
@@ -36,18 +36,16 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIXPConnect.idl"
-[ptr] native JSTracerPtr(JSTracer);
-
%{ C++
#define NS_SUCCESS_I_DID_SOMETHING \
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))
%}
/**
* Note: This is not really an XPCOM interface. For example, callers must
* guarantee that they set the *_retval of the various methods that return a
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -59,17 +59,17 @@
/***************************************************************************/
[ptr] native JSContextPtr(JSContext);
[ptr] native JSObjectPtr(JSObject);
[ptr] native JSValPtr(jsval);
native JSVal(jsval);
native JSID(jsid);
[ptr] native voidPtrPtr(void*);
-[ptr] native nsScriptObjectTracerPtr(nsScriptObjectTracer);
+[ptr] native JSTracerPtr(JSTracer);
/***************************************************************************/
%{ C++
/***************************************************************************/
#define GENERATE_XPC_FAILURE(x) \
(NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCONNECT,x))
@@ -145,17 +145,17 @@
interface nsIXPCScriptable;
interface nsIXPConnect;
interface nsIXPConnectWrappedNative;
interface nsIInterfaceInfo;
interface nsIXPCSecurityManager;
interface nsIPrincipal;
%{C++
-class nsScriptObjectTracer;
+class nsCycleCollectionTraversalCallback;
%}
/***************************************************************************/
[uuid(8916a320-d118-11d3-8f3a-0010a4e73d9a)]
interface nsIXPConnectJSObjectHolder : nsISupports
{
readonly attribute JSObjectPtr JSObject;
};
@@ -722,23 +722,9 @@ interface nsIXPConnect : nsISupports
* Wrap a jsval in a cross origin wrapper.
* @param aJSContext A context to use to create objects.
* @param aParent The parent to create the wrapper with.
* @param aWrappedObj The object to wrap.
*/
[noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext,
in JSObjectPtr aParent,
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);
};
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -690,53 +690,38 @@ NoteJSChild(JSTracer *trc, void *thing,
{
ContextCallbackItem *item = static_cast<ContextCallbackItem*>(trc);
item->cb->NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, thing);
}
}
static uint8 GCTypeToTraceKindMap[GCX_NTYPES] = {
JSTRACE_OBJECT, /* GCX_OBJECT */
- JSTRACE_STRING, /* GCX_STRING */
- JSTRACE_DOUBLE, /* GCX_DOUBLE */
- JSTRACE_FUNCTION, /* GCX_FUNCTION */
+ JSTRACE_STRING, /* GCX_STRING (unused) */
+ JSTRACE_DOUBLE, /* GCX_DOUBLE (unused) */
+ JSTRACE_STRING, /* GCX_MUTABLE_STRING (unused) */
+ JSTRACE_FUNCTION, /* GCX_FUNCTION (unused) */
JSTRACE_NAMESPACE, /* GCX_NAMESPACE */
JSTRACE_QNAME, /* GCX_QNAME */
- JSTRACE_XML, /* GCX_XML */
- (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 */
+ JSTRACE_XML /* GCX_XML */
+ // We don't care about JSTRACE_STRING, so stop here
};
-// static
-uint8
-nsXPConnect::GetTraceKind(void *thing)
-{
- uint8 type = *js_GetGCThingFlags(thing) & GCF_TYPEMASK;
- return GCTypeToTraceKindMap[type];
-}
-
NS_IMETHODIMP
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
{
if(!mCycleCollectionContext)
return NS_ERROR_FAILURE;
JSContext *cx = mCycleCollectionContext->GetJSContext();
PRUint32 refcount = mObjRefcounts->Get(p);
NS_ASSERTION(refcount > 0, "JS object but unknown to the JS GC?");
- uint8 ty = GetTraceKind(p);
+ uint8 ty = *js_GetGCThingFlags(p) & GCF_TYPEMASK;
if(ty != GCX_OBJECT && ty != GCX_NAMESPACE && ty != GCX_QNAME &&
ty != GCX_XML)
return NS_OK;
#ifdef DEBUG_CC
if(ty == GCX_OBJECT)
{
JSObject *obj = static_cast<JSObject*>(p);
@@ -2107,28 +2092,16 @@ nsXPConnect::AfterProcessNextEvent(nsITh
NS_IMETHODIMP
nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
{
NS_NOTREACHED("Why tell us?");
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
/* These are here to be callable from a debugger */
JS_BEGIN_EXTERN_C
void DumpJSStack()
{
nsresult rv;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
if(NS_SUCCEEDED(rv) && xpc)
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -246,52 +246,16 @@ ContextCallback(JSContext *cx, uintN ope
}
}
return gOldJSContextCallback
? gOldJSContextCallback(cx, operation)
: 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
void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
{
XPCJSRuntime* self = (XPCJSRuntime*)data;
// Skip this part if XPConnect is shutting down. We get into
// bad locking problems with the thread iteration otherwise.
if(!self->GetXPConnect()->IsShuttingDown())
@@ -308,58 +272,26 @@ void XPCJSRuntime::TraceJS(JSTracer* trc
XPCPerThreadData::IterateThreads(&iterp)))
{
// Trace those AutoMarkingPtr lists!
thread->TraceJS(trc);
}
}
}
- // 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);
-}
+ XPCWrappedNativeScope::TraceJS(trc, self);
-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())
+ for (XPCRootSetElem *e = self->mVariantRoots; e ; e = e->GetNextRoot())
static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
- for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot())
+ for (XPCRootSetElem *e = self->mWrappedJSRoots; e ; e = e->GetNextRoot())
static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
- if(mJSHolders.ops)
- JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc);
+ for (XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
+ static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
}
// static
JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
{
nsVoidArray* dyingWrappedJSArray;
XPCJSRuntime* self = nsXPConnect::GetRuntime();
@@ -872,22 +804,16 @@ XPCJSRuntime::~XPCJSRuntime()
// unwire the readable/JSString sharing magic
XPCStringConvert::ShutdownDOMStringFinalizer();
XPCConvert::RemoveXPCOMUCStringFinalizer();
gOldJSGCCallback = NULL;
gOldJSContextCallback = NULL;
-
- if(mJSHolders.ops)
- {
- JS_DHashTableFinish(&mJSHolders);
- mJSHolders.ops = nsnull;
- }
}
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
nsIJSRuntimeService* aJSRuntimeService)
: mXPConnect(aXPConnect),
mJSRuntime(nsnull),
mJSRuntimeService(aJSRuntimeService),
mContextMap(JSContext2XPCContextMap::newMap(XPC_CONTEXT_MAP_SIZE)),
@@ -931,20 +857,16 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect*
if(mJSRuntime)
{
gOldJSContextCallback = JS_SetContextCallback(mJSRuntime,
ContextCallback);
gOldJSGCCallback = JS_SetGCCallbackRT(mJSRuntime, GCCallback);
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
#ifdef DEBUG
if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)
xpc_InstallJSDebuggerKeywordHandler(mJSRuntime);
#endif
}
// static
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -493,19 +493,16 @@ public:
virtual nsresult FinishCycleCollection();
virtual nsCycleCollectionParticipant *ToParticipant(void *p);
#ifdef DEBUG_CC
virtual void PrintAllReferencesTo(void *p);
virtual void SuspectExtraPointers();
#endif
JSObjectRefcounts* GetJSObjectRefcounts() {return mObjRefcounts;}
-
- static uint8 GetTraceKind(void *thing);
-
#ifndef XPCONNECT_STANDALONE
void RecordTraversal(void *p, nsISupports *s);
#endif
#ifdef XPC_IDISPATCH_SUPPORT
public:
static PRBool IsIDispatchEnabled();
#endif
@@ -674,29 +671,23 @@ public:
}
const char* GetStringName(uintN index) const
{
NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
return mStrings[index];
}
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);
inline void AddVariantRoot(XPCTraceableVariant* variant);
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
- nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
- nsresult RemoveJSHolder(void* aHolder);
-
void DebugDump(PRInt16 depth);
void SystemIsBeingShutDown(JSContext* cx);
PRThread* GetThreadRunningGC() const {return mThreadRunningGC;}
~XPCJSRuntime();
@@ -750,17 +741,16 @@ private:
nsVoidArray mWrappedJSToReleaseArray;
nsVoidArray mNativesToReleaseArray;
JSBool mMainThreadOnlyGC;
JSBool mDeferReleases;
JSBool mDoingFinalization;
XPCRootSetElem *mVariantRoots;
XPCRootSetElem *mWrappedJSRoots;
XPCRootSetElem *mObjectHolderRoots;
- JSDHashTable mJSHolders;
};
/***************************************************************************/
/***************************************************************************/
// XPCContext is mostly a dumb class to hold JSContext specific data and
// maps that let us find wrappers created for the given JSContext.
// no virtuals
@@ -1196,16 +1186,18 @@ public:
static JSBool
IsDyingScope(XPCWrappedNativeScope *scope);
void SetComponents(nsXPCComponents* aComponents);
void SetGlobal(XPCCallContext& ccx, JSObject* aGlobal);
static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
+ void Traverse(nsCycleCollectionTraversalCallback &cb);
+
#ifndef XPCONNECT_STANDALONE
/**
* Fills the hash mapping global object to principal.
*/
static void TraverseScopes(XPCCallContext& ccx);
#endif
protected:
@@ -1934,21 +1926,20 @@ private:
/***************************************************************************/
// XPCWrappedNative the wrapper around one instance of a native xpcom object
// to be used from JavaScript.
class XPCWrappedNative : public nsIXPConnectWrappedNative
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
- NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
#ifndef XPCONNECT_STANDALONE
virtual nsIPrincipal* GetObjectPrincipal() const;
#endif
JSBool
IsValid() const {return nsnull != mFlatJSObject;}
@@ -2048,17 +2039,17 @@ public:
static nsresult
ReparentWrapperIfFound(XPCCallContext& ccx,
XPCWrappedNativeScope* aOldScope,
XPCWrappedNativeScope* aNewScope,
JSObject* aNewParent,
nsISupports* aCOMObj,
XPCWrappedNative** aWrapper);
- void FlatJSObjectFinalized(JSContext *cx);
+ void FlatJSObjectFinalized(JSContext *cx, JSObject *obj);
void SystemIsBeingShutDown(JSContext* cx);
#ifdef XPC_DETECT_LEADING_UPPERCASE_ACCESS_ERRORS
// This will try to find a member that is of the form "camelCased"
// but was accessed from JS using "CamelCased". This is here to catch
// mistakes caused by the confusion magnet that JS methods are by
// convention 'foo' while C++ members are by convention 'Foo'.
@@ -2200,20 +2191,18 @@ private:
XPCWrappedNativeProto* mMaybeProto;
};
XPCNativeSet* mSet;
JSObject* mFlatJSObject;
XPCNativeScriptableInfo* mScriptableInfo;
XPCWrappedNativeTearOffChunk mFirstChunk;
JSObject* mWrapper;
-#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
public:
nsCOMPtr<nsIThread> mThread; // Don't want to overload _mOwningThread
-#endif
};
/***************************************************************************
****************************************************************************
*
* Core classes for wrapped JSObject for use from native code...
*
****************************************************************************
@@ -3034,16 +3023,17 @@ private:
AutoMarkingPtr* mAutoRoots;
jsuword mStackLimit;
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
JSUint32 mWrappedNativeThreadsafetyReportDepth;
#endif
PRThread* mThread;
+ nsVoidArray mNativesToReleaseArray;
static PRLock* gLock;
static XPCPerThreadData* gThreads;
static PRUintn gTLSIndex;
};
/**************************************************************/
--- a/js/src/xpconnect/src/xpcwrappedjs.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjs.cpp
@@ -584,16 +584,20 @@ nsXPCWrappedJS::SystemIsBeingShutDown(JS
// mJSObj == nsnull is used to indicate that the wrapper is no longer valid
// and that calls should fail without trying to use any of the
// xpconnect mechanisms. 'IsValid' is implemented by checking this pointer.
// NOTE: that mClass is retained so that GetInterfaceInfo can continue to
// work (and avoid crashing some platforms).
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.
if(mNext)
mNext->SystemIsBeingShutDown(rt);
}
/***************************************************************************/
/* readonly attribute nsISimpleEnumerator enumerator; */
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -956,17 +956,17 @@ NS_IMPL_THREADSAFE_RELEASE(XPCWrappedNat
* mJSObject we set it's parent to be mFlatJSObject. This way we know that
* when mFlatJSObject get's collected there are no outstanding reachable
* tearoff mJSObjects. Note that we must clear the private of any lingering
* mJSObjects at this point because we have no guarentee of the *order* of
* finalization within a given gc cycle.
*/
void
-XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx)
+XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx, JSObject *obj)
{
if(!IsValid())
return;
// Iterate the tearoffs and null out each of their JSObject's privates.
// This will keep them from trying to access their pointers to the
// dying tearoff object. We can safely assume that those remaining
// JSObjects are about to be finalized too.
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -642,28 +642,28 @@ XPC_WN_Shared_Enumerate(JSContext *cx, J
/***************************************************************************/
JS_STATIC_DLL_CALLBACK(void)
XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
{
XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
if(!p)
return;
- p->FlatJSObjectFinalized(cx);
+ p->FlatJSObjectFinalized(cx, obj);
}
static void
TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
{
NS_ASSERTION(scope, "bad scope");
JSObject* obj;
obj = scope->GetGlobalJSObject();
- NS_ASSERTION(obj, "bad scope JSObject");
+ NS_ASSERTION(scope, "bad scope JSObject");
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
obj = scope->GetPrototypeJSObject();
if(obj)
{
JS_CALL_OBJECT_TRACER(trc, obj,
"XPCWrappedNativeScope::mPrototypeJSObject");
}
@@ -1030,17 +1030,17 @@ XPC_WN_Helper_HasInstance(JSContext *cx,
JS_STATIC_DLL_CALLBACK(void)
XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
{
XPCWrappedNative* wrapper = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
if(!wrapper)
return;
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
- wrapper->FlatJSObjectFinalized(cx);
+ wrapper->FlatJSObjectFinalized(cx, obj);
}
JS_STATIC_DLL_CALLBACK(void)
XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj)
{
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj);
if(wrapper && wrapper->IsValid())
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -846,16 +846,26 @@ XPCWrappedNativeScope::DebugDump(PRInt16
XPC_LOG_INDENT();
mWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMapDumpEnumerator, &depth);
XPC_LOG_OUTDENT();
}
XPC_LOG_OUTDENT();
#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
// static
void
XPCWrappedNativeScope::TraverseScopes(XPCCallContext& ccx)
{
// Hold the lock throughout.
XPCAutoLock lock(ccx.GetRuntime()->GetMapLock());
--- a/xpcom/base/nsAgg.h
+++ b/xpcom/base/nsAgg.h
@@ -113,18 +113,17 @@ public:
static _class* Downcast(nsISupports* s) \
{ \
return (_class*)((char*)(s) - offsetof(_class, fAggregated)); \
} \
static nsISupports* Upcast(_class *p) \
{ \
return p->InnerObject(); \
} \
-}; \
-NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
+};
// Put this in your class's constructor:
#define NS_INIT_AGGREGATED(outer) \
PR_BEGIN_MACRO \
fOuter = outer ? outer : &fAggregated; \
PR_END_MACRO
--- a/xpcom/glue/nsCycleCollectionParticipant.cpp
+++ b/xpcom/glue/nsCycleCollectionParticipant.cpp
@@ -33,31 +33,16 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCycleCollectionParticipant.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
nsXPCOMCycleCollectionParticipant::Root(void *p)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_ADDREF(s);
return NS_OK;
}
@@ -82,22 +67,16 @@ nsXPCOMCycleCollectionParticipant::Trave
return NS_OK;
}
void
nsXPCOMCycleCollectionParticipant::UnmarkPurple(nsISupports *n)
{
}
-NS_IMETHODIMP_(void)
-nsXPCOMCycleCollectionParticipant::Trace(void *p, TraceCallback cb,
- void *closure)
-{
-}
-
PRBool
nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
{
nsCOMPtr<nsISupports> foo;
s->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
getter_AddRefs(foo));
return s == foo;
}
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -120,39 +120,26 @@ public:
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant,
NS_CYCLECOLLECTIONPARTICIPANT_IID)
#undef IMETHOD_VISIBILITY
#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
- : public nsScriptObjectTracer
+ : public nsCycleCollectionParticipant
{
public:
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
NS_IMETHOD Root(void *p);
NS_IMETHOD Unlink(void *p);
NS_IMETHOD Unroot(void *p);
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
-
NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
PRBool CheckForRightISupports(nsISupports *s);
};
#undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
@@ -161,21 +148,18 @@ public:
///////////////////////////////////////////////////////////////////////////////
#define NS_CYCLE_COLLECTION_INNERCLASS \
cycleCollection
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERCLASS
-#define NS_CYCLE_COLLECTION_INNERNAME \
- _cycleCollectorGlobal
-
#define NS_CYCLE_COLLECTION_NAME(_class) \
- _class::NS_CYCLE_COLLECTION_INNERNAME
+ _class##_cycleCollectorGlobal
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = & NS_CYCLE_COLLECTION_NAME(_class); \
return NS_OK; \
} else
#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \
@@ -212,18 +196,16 @@ public:
NS_PRECONDITION(aInstancePtr, "null out param"); \
\
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = &NS_CYCLE_COLLECTION_NAME(_class); \
return NS_OK; \
} \
nsresult rv;
-#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
- NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing nsCycleCollectionParticipant::Unlink
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
@@ -336,198 +318,133 @@ public:
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(_field) \
{ \
PRInt32 i; \
for (i = 0; i < tmp->_field.Count(); ++i) \
cb.NoteXPCOMChild(tmp->_field[i]); \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class) \
- cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NAME(_ptr_class));
+ cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NATIVE_NAME(_ptr_class));
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(_array, _element_class) \
{ \
PRUint32 i, length = (_array).Length(); \
for (i = 0; i < length; ++i) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR((_array)[i], \
_element_class); \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_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 \
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
///////////////////////////////////////////////////////////////////////////////
-#define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE \
- static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
-
-#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
+#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
+class NS_CYCLE_COLLECTION_INNERCLASS \
+ : public nsXPCOMCycleCollectionParticipant \
+{ \
public: \
NS_IMETHOD Unlink(void *p); \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
NS_IMETHOD_(void) UnmarkPurple(nsISupports *s) \
{ \
Downcast(s)->UnmarkPurple(); \
} \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base*>(s)); \
} \
static nsISupports* Upcast(_class *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) \
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) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
public: \
NS_IMETHOD Unlink(void *p); \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base_class*>( \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
} \
-}; \
-NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
+};
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \
_base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
public: \
NS_IMETHOD Traverse(void *p, \
nsCycleCollectionTraversalCallback &cb); \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base_class*>( \
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
* traversed but whose AddRef/Release functions don't add/remove them to/from
* the purple buffer. If you're just using NS_DECL_CYCLE_COLLECTING_ISUPPORTS
* then you don't need this.
*/
#define NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(_class) \
NS_IMETHODIMP_(void) UnmarkPurple() \
{ \
} \
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
- NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class);
+ static NS_CYCLE_COLLECTION_CLASSNAME(_class) \
+ NS_CYCLE_COLLECTION_NAME(_class);
+
+#define NS_CYCLE_COLLECTION_NATIVE_INNERNAME \
+ _cycleCollectorGlobal
-#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
+#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: \
NS_IMETHOD Root(void *n); \
NS_IMETHOD Unlink(void *n); \
NS_IMETHOD Unroot(void *n); \
NS_IMETHOD Traverse(void *n, \
- nsCycleCollectionTraversalCallback &cb);
-
-#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
- class NS_CYCLE_COLLECTION_INNERCLASS \
- : public nsCycleCollectionParticipant \
- { \
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
+ nsCycleCollectionTraversalCallback &cb); \
}; \
- NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
+ static NS_CYCLE_COLLECTION_INNERCLASS \
+ NS_CYCLE_COLLECTION_NATIVE_INNERNAME;
-#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_NATIVE_CLASS(_class) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NATIVE_NAME(_class);
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p) \
{ \
_class *tmp = static_cast<_class*>(p); \
tmp->_root_function(); \
return NS_OK; \