Try to fix orange
authorpeterv@propagandism.org
Tue, 29 Jan 2008 13:42:05 -0800
changeset 10948 c2810568bf4b85150874bae8c8152ca058eba70a
parent 10947 494178105d5c837258cccd528420a880aaacd0d7
child 10949 2e91ef19c4339a61f39b6834b9808d75561f1026
push idunknown
push userunknown
push dateunknown
milestone1.9b3pre
Try to fix orange
content/xbl/src/nsXBLDocumentInfo.cpp
content/xbl/src/nsXBLProtoImpl.cpp
content/xbl/src/nsXBLProtoImpl.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLPrototypeHandler.h
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
dom/src/base/nsJSEnvironment.cpp
dom/src/base/nsJSTimeoutHandler.cpp
dom/src/events/nsJSEventListener.cpp
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcwrappedjs.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/glue/nsCycleCollectionParticipant.cpp
xpcom/glue/nsCycleCollectionParticipant.h
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -440,20 +440,20 @@ TraverseProtos(nsHashKey *aKey, void *aD
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
   proto->Traverse(*cb);
   return kHashEnumerateNext;
 }
 
 static PRIntn PR_CALLBACK
-UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
+UnlinkProtos(nsHashKey *aKey, void *aData, void* aClosure)
 {
   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
-  proto->UnlinkJSObjects();
+  proto->Unlink();
   return kHashEnumerateNext;
 }
 
 struct ProtoTracer
 {
   TraceCallback mCallback;
   void *mClosure;
 };
@@ -463,22 +463,20 @@ TraceProtos(nsHashKey *aKey, void *aData
 {
   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_ROOT_BEGIN(nsXBLDocumentInfo)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
-    tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nsnull);
+    tmp->mBindingTable->Enumerate(UnlinkProtos, nsnull);
   }
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   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);
   }
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -211,17 +211,17 @@ nsXBLProtoImpl::Trace(TraceCallback aCal
 
   nsXBLProtoImplMember *member;
   for (member = mMembers; member; member = member->GetNext()) {
     member->Trace(aCallback, aClosure);
   }
 }
 
 void
-nsXBLProtoImpl::UnlinkJSObjects()
+nsXBLProtoImpl::Unlink()
 {
   if (mClassObject) {
     DestroyMembers(nsnull);
   }
 }
 
 nsXBLProtoImplField*
 nsXBLProtoImpl::FindField(const nsString& aFieldName) const
--- a/content/xbl/src/nsXBLProtoImpl.h
+++ b/content/xbl/src/nsXBLProtoImpl.h
@@ -86,17 +86,17 @@ public:
 
   void SetFieldList(nsXBLProtoImplField* aFieldList)
   {
     delete mFields;
     mFields = aFieldList;
   }
 
   void Trace(TraceCallback aCallback, void *aClosure) const;
-  void UnlinkJSObjects();
+  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;
 
   // Undefine all our fields from object |obj| (which should be a
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -359,24 +359,24 @@ nsXBLPrototypeBinding::Traverse(nsCycleC
     cb.NoteXPCOMChild(mResources->mLoader);
   if (mInsertionPointTable)
     mInsertionPointTable->Enumerate(TraverseInsertionPoint, &cb);
   if (mInterfaceTable)
     mInterfaceTable->Enumerate(TraverseBinding, &cb);
 }
 
 void
-nsXBLPrototypeBinding::UnlinkJSObjects()
+nsXBLPrototypeBinding::Unlink()
 {
   if (mImplementation)
-    mImplementation->UnlinkJSObjects();
+    mImplementation->Unlink();
 
   nsXBLPrototypeHandler* curr = mPrototypeHandler;
   while (curr) {
-    curr->UnlinkJSObjects();
+    curr->Unlink();
     curr = curr->GetNextHandler();
   }
 }
 
 void
 nsXBLPrototypeBinding::Trace(TraceCallback aCallback, void *aClosure) const
 {
   if (mImplementation)
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -192,17 +192,17 @@ public:
   // binding.  It may well throw errors (eg on out-of-memory).  Do not confuse
   // 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 UnlinkJSObjects();
+  void Unlink();
   void Trace(TraceCallback aCallback, void *aClosure) const;
 
 // Static members
   static PRUint32 gRefCnt;
  
   static nsFixedSizeAllocator* kAttrPool;
 
 // Internal member functions.
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -164,17 +164,17 @@ nsXBLPrototypeHandler::~nsXBLPrototypeHa
 void
 nsXBLPrototypeHandler::Trace(TraceCallback aCallback, void *aClosure) const
 {
   if (mCachedHandler)
     aCallback(nsIProgrammingLanguage::JAVASCRIPT, mCachedHandler, aClosure);
 }
 
 void
-nsXBLPrototypeHandler::UnlinkJSObjects()
+nsXBLPrototypeHandler::Unlink()
 {
   ForgetCachedHandler();
 }
 
 already_AddRefed<nsIContent>
 nsXBLPrototypeHandler::GetHandlerElement()
 {
   if (mType & NS_HANDLER_TYPE_XUL) {
--- a/content/xbl/src/nsXBLPrototypeHandler.h
+++ b/content/xbl/src/nsXBLPrototypeHandler.h
@@ -149,17 +149,17 @@ public:
   // This returns a valid value only if HasAllowUntrustedEventsAttr returns
   // PR_TRUE.
   PRBool AllowUntrustedEvents()
   {
     return (mType & NS_HANDLER_ALLOW_UNTRUSTED) != 0;
   }
 
   void Trace(TraceCallback aCallback, void *aClosure) const;
-  void UnlinkJSObjects();
+  void Unlink();
 	
 public:
   static PRUint32 gRefCnt;
   
 protected:
   already_AddRefed<nsIController> GetController(nsPIDOMEventTarget* aTarget);
   
   inline PRInt32 GetMatchingKeyCode(const nsAString& aKeyName);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2411,16 +2411,19 @@ nsXULElement::RecompileScriptEventListen
     }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXULPrototypeNode)
     if (tmp->mType == nsXULPrototypeNode::eType_Element) {
         static_cast<nsXULPrototypeElement*>(tmp)->Unlink();
     }
+    else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
+        static_cast<nsXULPrototypeScript*>(tmp)->Unlink();
+    }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 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->mNumChildren; ++i) {
             NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i],
@@ -2444,25 +2447,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BE
     }
     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_BEGIN_NATIVE(nsXULPrototypeNode, AddRef)
-    if (tmp->mType == nsXULPrototypeNode::eType_Element) {
-        static_cast<nsXULPrototypeElement*>(tmp)->UnlinkJSObjects();
-    }
-    else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
-        static_cast<nsXULPrototypeScript*>(tmp)->UnlinkJSObjects();
-    }
-NS_IMPL_CYCLE_COLLECTION_ROOT_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)
 
 //----------------------------------------------------------------------
 //
 // nsXULPrototypeAttribute
 //
 
 nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
@@ -2750,28 +2745,23 @@ nsXULPrototypeElement::SetAttrAt(PRUint3
     }
 
     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
 
     return NS_OK;
 }
 
 void
-nsXULPrototypeElement::UnlinkJSObjects()
+nsXULPrototypeElement::Unlink()
 {
     if (mHoldsScriptObject) {
         nsContentUtils::DropScriptObjects(mScriptTypeID, this,
                                           &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
         mHoldsScriptObject = PR_FALSE;
     }
-}
-
-void
-nsXULPrototypeElement::Unlink()
-{
     mNumAttributes = 0;
     delete[] mAttributes;
     mAttributes = nsnull;
 }
 
 //----------------------------------------------------------------------
 //
 // nsXULPrototypeScript
@@ -2789,17 +2779,17 @@ nsXULPrototypeScript::nsXULPrototypeScri
     NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
     NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
                  "The language ID must be known and constant");
 }
 
 
 nsXULPrototypeScript::~nsXULPrototypeScript()
 {
-    UnlinkJSObjects();
+    Unlink();
 }
 
 nsresult
 nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
                                 nsIScriptGlobalObject* aGlobal,
                                 const nsCOMArray<nsINodeInfo> *aNodeInfos)
 {
     nsIScriptContext *context = aGlobal->GetScriptContext(
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -249,17 +249,16 @@ public:
           mHoldsScriptObject(PR_FALSE),
           mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
     {
         NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
     }
 
     virtual ~nsXULPrototypeElement()
     {
-        UnlinkJSObjects();
         Unlink();
         NS_ASSERTION(!mChildren && mNumChildren == 0,
                      "ReleaseSubtree not called");
     }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
     virtual const char* ClassName() { return "nsXULPrototypeElement"; }
     virtual PRUint32 ClassSize() { return sizeof(*this); }
@@ -285,17 +284,16 @@ public:
                                const nsCOMArray<nsINodeInfo> *aNodeInfos);
     virtual nsresult Deserialize(nsIObjectInputStream* aStream,
                                  nsIScriptGlobalObject* aGlobal,
                                  nsIURI* aDocumentURI,
                                  const nsCOMArray<nsINodeInfo> *aNodeInfos);
 
     nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
 
-    void UnlinkJSObjects();
     void Unlink();
 
     PRUint32                 mNumChildren;
     nsXULPrototypeNode**     mChildren;           // [OWNER]
 
     nsCOMPtr<nsINodeInfo>    mNodeInfo;           // [OWNER]
 
     PRUint32                 mNumAttributes;
@@ -356,17 +354,17 @@ public:
     nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
                                   nsIScriptGlobalObject* aGlobal);
 
     nsresult Compile(const PRUnichar* aText, PRInt32 aTextLength,
                      nsIURI* aURI, PRUint32 aLineNo,
                      nsIDocument* aDocument,
                      nsIScriptGlobalObjectOwner* aGlobalOwner);
 
-    void UnlinkJSObjects()
+    void Unlink()
     {
         if (mScriptObject.mObject) {
             nsContentUtils::DropScriptObjects(mScriptObject.mLangID, this,
                                               &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
             mScriptObject.mObject = nsnull;
         }
     }
 
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -3836,20 +3836,19 @@ nsJSArgArray::ReleaseJSObjects()
   if (mArgv) {
     PR_DELETE(mArgv);
   }
   mArgc = 0;
 }
 
 // QueryInterface implementation for nsJSArgArray
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSArgArray)
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsJSArgArray)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
   tmp->ReleaseJSObjects();
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsJSArgArray)
+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;
--- a/dom/src/base/nsJSTimeoutHandler.cpp
+++ b/dom/src/base/nsJSTimeoutHandler.cpp
@@ -107,20 +107,19 @@ private:
   JSString *mExpr;
   JSObject *mFunObj;
 };
 
 
 // nsJSScriptTimeoutHandler
 // QueryInterface implementation for nsJSScriptTimeoutHandler
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsJSScriptTimeoutHandler)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSScriptTimeoutHandler)
   tmp->ReleaseJSObjects();
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsJSScriptTimeoutHandler)
+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
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSScriptTimeoutHandler)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mExpr)
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -76,44 +76,31 @@ 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?");
-  nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(), this,
-                                   &NS_CYCLE_COLLECTION_NAME(nsJSEventListener),
-                                   aScopeObject, PR_FALSE);
+  NS_HOLD_JS_OBJECTS(this, nsJSEventListener);
 }
 
 nsJSEventListener::~nsJSEventListener() 
 {
   if (mContext)
-    nsContentUtils::DropScriptObjects(mContext->GetScriptTypeID(), this,
-                                &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
+    NS_DROP_JS_OBJECTS(this, nsJSEventListener);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsJSEventListener)
-  if (tmp->mContext &&
-      tmp->mContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
-    NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
-    tmp->mScopeObject = nsnull;
-  }
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTarget)
   if (tmp->mContext) {
-    if (tmp->mScopeObject) {
-      nsContentUtils::DropScriptObjects(tmp->mContext->GetScriptTypeID(), this,
-                                  &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
-      tmp->mScopeObject = nsnull;
-    }
+    tmp->mScopeObject = nsnull;
+    NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   }
 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
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -674,17 +674,17 @@ nsXPConnect::FinishCycleCollection()
 
 nsCycleCollectionParticipant *
 nsXPConnect::ToParticipant(void *p)
 {
     return this;
 }
 
 NS_IMETHODIMP
-nsXPConnect::RootAndUnlinkJSObjects(void *p)
+nsXPConnect::Root(void *p)
 {
     return NS_OK;
 }
 
 #ifdef DEBUG_CC
 void
 nsXPConnect::PrintAllReferencesTo(void *p)
 {
@@ -932,17 +932,17 @@ nsXPConnect::GetRequestDepth(JSContext* 
         // collection.
         --requestDepth;
     return requestDepth;
 }
 
 class JSContextParticipant : public nsCycleCollectionParticipant
 {
 public:
-    NS_IMETHOD RootAndUnlinkJSObjects(void *n)
+    NS_IMETHOD Root(void *n)
     {
         return NS_OK;
     }
     NS_IMETHOD Unlink(void *n)
     {
         // We must not unlink a JSContext because Root/Unroot don't ensure that
         // the pointer is still valid.
         return NS_OK;
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -492,17 +492,17 @@ public:
     virtual ~nsXPConnect();
 
     JSBool IsShuttingDown() const {return mShuttingDown;}
 
     nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
     nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
 
     // nsCycleCollectionParticipant
-    NS_IMETHOD RootAndUnlinkJSObjects(void *p);
+    NS_IMETHOD Root(void *p);
     NS_IMETHOD Unlink(void *p);
     NS_IMETHOD Unroot(void *p);
     NS_IMETHOD Traverse(void *p,
                         nsCycleCollectionTraversalCallback &cb);
     
     // nsCycleCollectionLanguageRuntime
     virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
     virtual nsresult FinishCycleCollection();
@@ -2483,24 +2483,18 @@ class nsXPCWrappedJS : protected nsAutoX
                        public XPCRootSetElem
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
     NS_DECL_NSIXPCONNECTWRAPPEDJS
     NS_DECL_NSISUPPORTSWEAKREFERENCE
     NS_DECL_NSIPROPERTYBAG
-
-    class NS_CYCLE_COLLECTION_INNERCLASS
-     : public nsXPCOMCycleCollectionParticipant
-    {
-      NS_IMETHOD RootAndUnlinkJSObjects(void *p);
-      NS_DECL_CYCLE_COLLECTION_CLASS_BODY(nsXPCWrappedJS, nsIXPConnectWrappedJS)
-    };
-    NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPCWrappedJS,
+                                             nsIXPConnectWrappedJS)
     NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(nsXPCWrappedJS)
 
     NS_IMETHOD CallMethod(PRUint16 methodIndex,
                           const XPTMethodDescriptor *info,
                           nsXPTCMiniVariant* params);
 
     /*
     * This is rarely called directly. Instead one usually calls
--- a/js/src/xpconnect/src/xpcwrappedjs.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjs.cpp
@@ -107,45 +107,27 @@ NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrapp
         cb.NoteXPCOMChild(tmp->GetAggregatedNativeObject());
     else
         // Non-root wrappers keep their root alive.
         cb.NoteXPCOMChild(static_cast<nsIXPConnectWrappedJS*>(root));
 
     return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsXPCWrappedJS)
-    if(tmp->mRoot && !tmp->mRoot->HasWeakReferences() && tmp->IsValid())
-    {
-        XPCJSRuntime* rt = nsXPConnect::GetRuntime();
-        if(rt)
-        {
-            if(tmp->mRoot == tmp)
-            {
-                // remove this root wrapper from the map
-                JSObject2WrappedJSMap* map = rt->GetWrappedJSMap();
-                if(map)
-                {
-                    XPCAutoLock lock(rt->GetMapLock());
-                    map->Remove(tmp);
-                }
-            }
-
-            if(tmp->mRefCnt > 1)
-                tmp->RemoveFromRootSet(rt->GetJSRuntime());
-        }
-
-        tmp->mJSObj = nsnull;
-    }
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXPCWrappedJS)
     if(tmp->mRoot && !tmp->mRoot->HasWeakReferences())
     {
         tmp->Unlink();
+        if(tmp->IsValid())
+        {
+            XPCJSRuntime* rt = nsXPConnect::GetRuntime();
+            if(tmp->mRefCnt > 1)
+                tmp->RemoveFromRootSet(rt->GetJSRuntime());
+            tmp->mJSObj = nsnull;
+        }
     }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMETHODIMP
 nsXPCWrappedJS::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
     NS_ASSERTION(IsAggregatedToNative(), "bad AggregatedQueryInterface call");
 
@@ -164,16 +146,19 @@ nsXPCWrappedJS::AggregatedQueryInterface
     }
 
     return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
 }
 
 NS_IMETHODIMP
 nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
+    if(!IsValid())
+        return NS_ERROR_UNEXPECTED;
+
     if(nsnull == aInstancePtr)
     {
         NS_PRECONDITION(0, "null pointer");
         return NS_ERROR_NULL_POINTER;
     }
 
     if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {
         *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(nsXPCWrappedJS);
@@ -183,19 +168,16 @@ nsXPCWrappedJS::QueryInterface(REFNSIID 
     if(aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)))
     {
         NS_ADDREF(this);
         *aInstancePtr =
             NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Upcast(this);
         return NS_OK;
     }
 
-    if(!IsValid())
-        return NS_ERROR_UNEXPECTED;
-
     // Always check for this first so that our 'outer' can get this interface
     // from us without recurring into a call to the outer's QI!
     if(aIID.Equals(NS_GET_IID(nsIXPConnectWrappedJS)))
     {
         NS_ADDREF(this);
         *aInstancePtr = (void*) static_cast<nsIXPConnectWrappedJS*>(this);
         return NS_OK;
     }
@@ -466,36 +448,38 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallCo
 nsXPCWrappedJS::~nsXPCWrappedJS()
 {
     NS_PRECONDITION(0 == mRefCnt, "refcounting error");
 
     if(mRoot == this)
     {
         // Let the nsWeakReference object (if present) know of our demise.
         ClearWeakReferences();
+    }
+    Unlink();
+}
 
-        // Remove this root wrapper from the map
-        XPCJSRuntime* rt = nsXPConnect::GetRuntime();
+void
+nsXPCWrappedJS::Unlink()
+{
+    XPCJSRuntime* rt = nsXPConnect::GetRuntime();
+    if(mRoot == this)
+    {
+        // remove this root wrapper from the map
         if(rt)
         {
             JSObject2WrappedJSMap* map = rt->GetWrappedJSMap();
             if(map)
             {
                 XPCAutoLock lock(rt->GetMapLock());
                 map->Remove(this);
             }
         }
     }
-    Unlink();
-}
-
-void
-nsXPCWrappedJS::Unlink()
-{
-    if(mRoot != this && mRoot)
+    else if(mRoot)
     {
         // unlink this wrapper
         nsXPCWrappedJS* cur = mRoot;
         while(1)
         {
             if(cur->mNext == this)
             {
                 cur->mNext = mNext;
@@ -508,17 +492,16 @@ nsXPCWrappedJS::Unlink()
         NS_RELEASE(mRoot);
     }
 
     if(IsValid())
     {
         NS_IF_RELEASE(mClass);
         if (mOuter)
         {
-            XPCJSRuntime* rt = nsXPConnect::GetRuntime();
             if (rt && rt->GetThreadRunningGC())
             {
                 rt->DeferredRelease(mOuter);
                 mOuter = nsnull;
             }
             else
             {
                 NS_RELEASE(mOuter);
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -873,18 +873,18 @@ struct nsCycleCollector
 
     void RegisterRuntime(PRUint32 langID, 
                          nsCycleCollectionLanguageRuntime *rt);
     void ForgetRuntime(PRUint32 langID);
 
     void SelectPurple();
     void MarkRoots(GCGraphBuilder &builder);
     void ScanRoots();
-    void RootWhite();
-    PRBool CollectWhite(); // returns whether anything was collected
+    void CollectWhite();
+    PRBool UnrootWhite(); // returns whether anything was collected
 
     nsCycleCollector();
     ~nsCycleCollector();
 
     PRBool Suspect(nsISupports *n);
     PRBool Forget(nsISupports *n);
     PRBool Collect(PRUint32 aTryCollections = 1);
     PRBool BeginCollection();
@@ -1520,17 +1520,17 @@ nsCycleCollector::ScanRoots()
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Bacon & Rajan's |CollectWhite| routine, somewhat modified.
 ////////////////////////////////////////////////////////////////////////
 
 void
-nsCycleCollector::RootWhite()
+nsCycleCollector::CollectWhite()
 {
     // Explanation of "somewhat modified": we have no way to collect the
     // set of whites "all at once", we have to ask each of them to drop
     // their outgoing links and assume this will cause the garbage cycle
     // to *mostly* self-destruct (except for the reference we continue
     // to hold). 
     // 
     // To do this "safely" we must make sure that the white nodes we're
@@ -1557,43 +1557,43 @@ nsCycleCollector::RootWhite()
         if (pinfo->mColor == white) {
             mBuf.Push(pinfo);
         }
     }
 
     PRUint32 i, count = mBuf.GetSize();
     for (i = 0; i < count; ++i) {
         PtrInfo *pinfo = static_cast<PtrInfo*>(mBuf.ObjectAt(i));
-        rv = pinfo->mParticipant->RootAndUnlinkJSObjects(pinfo->mPointer);
+        rv = pinfo->mParticipant->Root(pinfo->mPointer);
         if (NS_FAILED(rv))
             Fault("Failed root call while unlinking", pinfo);
     }
-}
-
-PRBool
-nsCycleCollector::CollectWhite()
-{
-    nsresult rv;
-    PRUint32 i, count = mBuf.GetSize();
+
     for (i = 0; i < count; ++i) {
         PtrInfo *pinfo = static_cast<PtrInfo*>(mBuf.ObjectAt(i));
         rv = pinfo->mParticipant->Unlink(pinfo->mPointer);
         if (NS_FAILED(rv)) {
             Fault("Failed unlink call while unlinking", pinfo);
 #ifdef DEBUG_CC
             mStats.mFailedUnlink++;
 #endif
         }
         else {
 #ifdef DEBUG_CC
             ++mStats.mCollectedNode;
 #endif
         }
     }
-
+}
+
+PRBool
+nsCycleCollector::UnrootWhite()
+{
+    nsresult rv;
+    PRUint32 i, count = mBuf.GetSize();
     for (i = 0; i < count; ++i) {
         PtrInfo *pinfo = static_cast<PtrInfo*>(mBuf.ObjectAt(i));
         rv = pinfo->mParticipant->Unroot(pinfo->mPointer);
         if (NS_FAILED(rv))
             Fault("Failed unroot call while unlinking", pinfo);
     }
 
     mBuf.Empty();
@@ -2281,31 +2281,31 @@ nsCycleCollector::BeginCollection()
                 }
             }
         }
 #endif
 
 #ifdef COLLECT_TIME_DEBUG
         now = PR_Now();
 #endif
-        RootWhite();
+        CollectWhite();
 
 #ifdef COLLECT_TIME_DEBUG
         printf("cc: CollectWhite() took %lldms\n",
                (PR_Now() - now) / PR_USEC_PER_MSEC);
 #endif
     }
 
     return PR_TRUE;
 }
 
 PRBool
 nsCycleCollector::FinishCollection()
 {
-    PRBool collected = CollectWhite();
+    PRBool collected = UnrootWhite();
 
 #ifdef DEBUG_CC
     mStats.mCollection++;
     if (mParams.mReportStats)
         mStats.Dump();
 #endif
 
     for (PRUint32 i = 0; i <= nsIProgrammingLanguage::MAX; ++i) {
--- a/xpcom/glue/nsCycleCollectionParticipant.cpp
+++ b/xpcom/glue/nsCycleCollectionParticipant.cpp
@@ -49,17 +49,17 @@ NoteChild(PRUint32 aLangID, void *aScrip
 void
 nsScriptObjectTracer::TraverseScriptObjects(void *p,
                                         nsCycleCollectionTraversalCallback &cb)
 {
   Trace(p, NoteChild, &cb);
 }
 
 nsresult
-nsXPCOMCycleCollectionParticipant::RootAndUnlinkJSObjects(void *p)
+nsXPCOMCycleCollectionParticipant::Root(void *p)
 {
     nsISupports *s = static_cast<nsISupports*>(p);
     NS_ADDREF(s);
     return NS_OK;
 }
 
 nsresult
 nsXPCOMCycleCollectionParticipant::Unlink(void *p)
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -117,17 +117,17 @@ public:
 
 class NS_NO_VTABLE nsCycleCollectionParticipant
 {
 public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONPARTICIPANT_IID)
 
     NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0;
 
-    NS_IMETHOD RootAndUnlinkJSObjects(void *p) = 0;
+    NS_IMETHOD Root(void *p) = 0;
     NS_IMETHOD Unlink(void *p) = 0;
     NS_IMETHOD Unroot(void *p) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant, 
                               NS_CYCLECOLLECTIONPARTICIPANT_IID)
 
 #undef IMETHOD_VISIBILITY
@@ -145,17 +145,17 @@ public:
 };
 
 class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
     : public nsScriptObjectTracer
 {
 public:
     NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
 
-    NS_IMETHOD RootAndUnlinkJSObjects(void *p);
+    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);
@@ -224,41 +224,16 @@ public:
       return NS_OK;                                                           \
     }                                                                         \
     nsresult rv;
 
 #define NS_CYCLE_COLLECTION_UPCAST(obj, clazz)                                 \
   NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
 
 ///////////////////////////////////////////////////////////////////////////////
-// Helpers for implementing nsCycleCollectionParticipant::RootAndUnlinkJSObjects
-///////////////////////////////////////////////////////////////////////////////
-
-#define NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(_class)                            \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::RootAndUnlinkJSObjects(void *p)       \
-  {                                                                            \
-    nsISupports *s = static_cast<nsISupports*>(p);                             \
-    NS_ASSERTION(CheckForRightISupports(s),                                    \
-                 "not the nsISupports pointer we expect");                     \
-    nsXPCOMCycleCollectionParticipant::RootAndUnlinkJSObjects(s);              \
-    _class *tmp = Downcast(s);
-
-#define NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN_NATIVE(_class, _root_function)     \
-  NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::RootAndUnlinkJSObjects(void *p)       \
-  {                                                                            \
-    _class *tmp = static_cast<_class*>(p);                                     \
-    tmp->_root_function();
-
-#define NS_IMPL_CYCLE_COLLECTION_ROOT_END                                      \
-    return NS_OK;                                                              \
-  }
-
-///////////////////////////////////////////////////////////////////////////////
 // Helpers for implementing nsCycleCollectionParticipant::Unlink
 ///////////////////////////////////////////////////////////////////////////////
 
 #define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                          \
   NS_IMETHODIMP                                                                \
   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p)                       \
   {                                                                            \
     nsISupports *s = static_cast<nsISupports*>(p);                             \
@@ -474,23 +449,23 @@ class NS_CYCLE_COLLECTION_INNERCLASS    
 };                                                                             \
 NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS(_class)                                 \
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
 
 // Cycle collector helper for classes that don't want to unlink anything.
 // Note: if this is used a lot it might make sense to have a base class that
-//       doesn't do anything in RootAndUnlinkJSObjects/Unlink/Unroot.
+//       doesn't do anything in Root/Unlink/Unroot.
 #define NS_DECL_CYCLE_COLLECTION_CLASS_NO_UNLINK(_class)                       \
 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
  : public nsXPCOMCycleCollectionParticipant                                    \
 {                                                                              \
   NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _class)                \
-  NS_IMETHOD RootAndUnlinkJSObjects(void *p)                                   \
+  NS_IMETHOD Root(void *p)                                                     \
   {                                                                            \
     return NS_OK;                                                              \
   }                                                                            \
   NS_IMETHOD Unlink(void *p)                                                   \
   {                                                                            \
     return NS_OK;                                                              \
   }                                                                            \
   NS_IMETHOD Unroot(void *p)                                                   \
@@ -499,17 +474,16 @@ class NS_CYCLE_COLLECTION_INNERCLASS    
   }                                                                            \
 };                                                                             \
 NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
 
 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base)  \
 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
  : public nsXPCOMCycleCollectionParticipant                                    \
 {                                                                              \
-  NS_IMETHOD RootAndUnlinkJSObjects(void *p);                                  \
   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)
 
@@ -556,17 +530,17 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
   {                                                                            \
   }                                                                            \
 
 #define NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                 \
   NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class);
 
 #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY                             \
   public:                                                                      \
-    NS_IMETHOD RootAndUnlinkJSObjects(void *n);                                \
+    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                                       \
@@ -581,17 +555,17 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
   {                                                                            \
     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)           \
   NS_IMETHODIMP                                                                \
-  NS_CYCLE_COLLECTION_CLASSNAME(_class)::RootAndUnlinkJSObjects(void *p)       \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p)                         \
   {                                                                            \
     _class *tmp = static_cast<_class*>(p);                                     \
     tmp->_root_function();                                                     \
     return NS_OK;                                                              \
   }
 
 #define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function)       \
   NS_IMETHODIMP                                                                \