Relanding part of the fix for bug 372960 (Make XPConnect traverse more JS edges). r=brendan, sr=jst.

git-svn-id: svn://10.0.0.236/trunk@222257 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
peterv%propagandism.org
2007-03-23 13:21:22 +00:00
parent 92f446fdda
commit 4f88013a35

View File

@@ -46,7 +46,10 @@
#include "XPCNativeWrapper.h"
#include "nsBaseHashtable.h"
#include "nsHashKeys.h"
#include "jsatom.h"
#include "jsfun.h"
#include "jsobj.h"
#include "jsscript.h"
NS_IMPL_THREADSAFE_ISUPPORTS2(nsXPConnect,nsIXPConnect,nsISupportsWeakReference)
@@ -577,6 +580,22 @@ nsXPConnect::Unroot(const nsDeque &nodes)
return NS_OK;
}
static void
TraverseJSScript(JSScript* script, nsCycleCollectionTraversalCallback& cb)
{
JSAtomMap* map = &script->atomMap;
uintN i, length = map->length;
JSAtom** vector = map->vector;
for(i = 0; i < length; i++)
{
JSAtom* atom = vector[i];
if(ATOM_IS_OBJECT(atom))
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
ATOM_TO_OBJECT(atom));
}
}
nsresult
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
{
@@ -594,14 +613,46 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
{
XPCWrappedNative* wn = XPCNativeWrapper::GetWrappedNative(cx, obj);
XPCNativeScriptableInfo* si = wn ? wn->GetScriptableInfo() : nsnull;
if(si)
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
si->GetJSClass()->name);
if(wn)
{
XPCNativeScriptableInfo* si = wn->GetScriptableInfo();
if(si)
{
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
si->GetJSClass()->name);
}
else
{
nsIClassInfo* ci = wn->GetClassInfo();
char* className = nsnull;
if(ci)
ci->GetClassDescription(&className);
if(className)
{
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
className);
PR_Free(className);
}
else
{
XPCNativeSet* set = wn->GetSet();
XPCNativeInterface** array = set->GetInterfaceArray();
PRUint16 count = set->GetInterfaceCount();
if(count > 0)
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
array[0]->GetNameString());
else
JS_snprintf(name, sizeof(name), "XPCNativeWrapper");
}
}
}
else
{
JS_snprintf(name, sizeof(name), "XPCNativeWrapper");
}
}
else if(obj)
else
{
XPCNativeScriptableInfo* si = nsnull;
if(IS_PROTO_CLASS(clazz))
@@ -611,15 +662,42 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
si = p->GetScriptableInfo();
}
if(si)
{
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)", clazz->name,
si->GetJSClass()->name);
}
else if(clazz == &js_ScriptClass)
{
JSScript* script = (JSScript*) JS_GetPrivate(cx, obj);
if(script->filename)
{
JS_snprintf(name, sizeof(name), "JS Object (Script - %s)",
script->filename);
}
else
{
JS_snprintf(name, sizeof(name), "JS Object (Script)");
}
}
else if(clazz == &js_FunctionClass)
{
JSFunction* fun = (JSFunction*) JS_GetPrivate(cx, obj);
if(fun->atom)
{
JS_snprintf(name, sizeof(name), "JS Object (Function - %s)",
js_AtomToPrintableString(cx, fun->atom));
}
else
{
JS_snprintf(name, sizeof(name), "JS Object (Function)");
}
}
else
{
JS_snprintf(name, sizeof(name), "JS Object (%s)", clazz->name);
}
}
else
{
JS_snprintf(name, sizeof(name), "JS Object");
}
cb.DescribeNode(refcount, sizeof(JSObject), name);
#else
cb.DescribeNode(refcount, sizeof(JSObject), "JS Object");
@@ -658,6 +736,24 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
{
cb.NoteXPCOMChild(NS_STATIC_CAST(nsISupports*, JS_GetPrivate(cx, obj)));
}
else if(clazz == &js_ScriptClass)
{
JSScript* script = (JSScript*) JS_GetPrivate(cx, obj);
TraverseJSScript(script, cb);
}
else if(clazz == &js_FunctionClass)
{
JSFunction* fun = (JSFunction*) JS_GetPrivate(cx, obj);
if (fun) {
JSAtom* atom = fun->atom;
if(atom && ATOM_IS_OBJECT(atom))
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
ATOM_TO_OBJECT(atom));
JSScript* script = FUN_SCRIPT(fun);
if (script)
TraverseJSScript(script, cb);
}
}
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
OBJ_GET_PARENT(cx, obj));
@@ -672,6 +768,28 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
JSVAL_TO_OBJECT(val));
}
JSScope* scope;
if(OBJ_IS_NATIVE(obj) && (scope = OBJ_SCOPE(obj)))
{
JSScopeProperty* sprop;
for(sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent)
{
if(SCOPE_HAD_MIDDLE_DELETE(scope) &&
!SCOPE_HAS_PROPERTY(scope, sprop))
continue;
jsid id = sprop->id;
if(JSID_IS_OBJECT(id))
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
JSID_TO_OBJECT(id));
if(sprop->attrs & JSPROP_GETTER)
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
JSVAL_TO_GCTHING((jsval)sprop->getter));
if(sprop->attrs & JSPROP_SETTER)
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
JSVAL_TO_GCTHING((jsval)sprop->setter));
}
}
#ifndef XPCONNECT_STANDALONE
if(clazz->flags & JSCLASS_IS_GLOBAL)
{