blob: a27b5331ebfcf32751c7806da41554c835db97ce [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* JavaScript Debugging support - Object support
*/
#include "jsd.h"
/*
* #define JSD_TRACE 1
*/
#ifdef JSD_TRACE
#define TRACEOBJ(jsdc, jsdobj, which) _traceObj(jsdc, jsdobj, which)
static char *
_describeObj(JSDContext* jsdc, JSDObject *jsdobj)
{
return
JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d",
(int)jsdobj,
JSD_GetObjectNewURL(jsdc, jsdobj),
JSD_GetObjectNewLineNumber(jsdc, jsdobj),
JSD_GetObjectConstructorName(jsdc, jsdobj),
JSD_GetObjectConstructorURL(jsdc, jsdobj),
JSD_GetObjectConstructorLineNumber(jsdc, jsdobj));
}
static void
_traceObj(JSDContext* jsdc, JSDObject* jsdobj, int which)
{
char* description;
if( !jsdobj )
return;
description = _describeObj(jsdc, jsdobj);
printf("%s : %s\n",
which == 0 ? "new " :
which == 1 ? "final" :
"ctor ",
description);
if(description)
free(description);
}
#else
#define TRACEOBJ(jsdc, jsdobj, which) ((void)0)
#endif /* JSD_TRACE */
#ifdef DEBUG
void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj)
{
JS_ASSERT(jsdobj);
JS_ASSERT(!JS_CLIST_IS_EMPTY(&jsdobj->links));
JS_ASSERT(jsdobj->obj);
}
#endif
static void
_destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
{
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
JS_REMOVE_LINK(&jsdobj->links);
JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj);
if(jsdobj->newURL)
jsd_DropAtom(jsdc, jsdobj->newURL);
if(jsdobj->ctorURL)
jsd_DropAtom(jsdc, jsdobj->ctorURL);
if(jsdobj->ctorName)
jsd_DropAtom(jsdc, jsdobj->ctorName);
free(jsdobj);
}
void
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
JSAbstractFramePtr frame)
{
JSDObject* jsdobj;
JS::RootedScript script(cx);
JSDScript* jsdscript;
const char* ctorURL;
JSString* ctorNameStr;
const char* ctorName;
JSD_LOCK_OBJECTS(jsdc);
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
if( jsdobj && !jsdobj->ctorURL )
{
script = frame.script();
if( script )
{
ctorURL = JS_GetScriptFilename(cx, script);
if( ctorURL )
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame);
JSD_UNLOCK_SCRIPTS(jsdc);
if( jsdscript && (ctorNameStr = jsd_GetScriptFunctionId(jsdc, jsdscript)) ) {
if( (ctorName = JS_EncodeString(cx, ctorNameStr)) ) {
jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName);
JS_free(cx, (void *) ctorName);
}
}
jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script);
}
}
TRACEOBJ(jsdc, jsdobj, 3);
JSD_UNLOCK_OBJECTS(jsdc);
}
static JSHashNumber
_hash_root(const void *key)
{
return ((JSHashNumber)(ptrdiff_t) key) >> 2; /* help lame MSVC1.5 on Win16 */
}
JSBool
jsd_InitObjectManager(JSDContext* jsdc)
{
JS_INIT_CLIST(&jsdc->objectsList);
jsdc->objectsTable = JS_NewHashTable(256, _hash_root,
JS_CompareValues, JS_CompareValues,
NULL, NULL);
return !!jsdc->objectsTable;
}
void
jsd_DestroyObjectManager(JSDContext* jsdc)
{
jsd_DestroyObjects(jsdc);
JSD_LOCK_OBJECTS(jsdc);
JS_HashTableDestroy(jsdc->objectsTable);
JSD_UNLOCK_OBJECTS(jsdc);
}
void
jsd_DestroyObjects(JSDContext* jsdc)
{
JSD_LOCK_OBJECTS(jsdc);
while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
_destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
JSD_UNLOCK_OBJECTS(jsdc);
}
JSDObject*
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp)
{
JSDObject *jsdobj = *iterp;
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
if( !jsdobj )
jsdobj = (JSDObject *)jsdc->objectsList.next;
if( jsdobj == (JSDObject *)&jsdc->objectsList )
return NULL;
*iterp = (JSDObject*) jsdobj->links.next;
return jsdobj;
}
JSObject*
jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj)
{
return jsdobj->obj;
}
const char*
jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj)
{
if( jsdobj->newURL )
return JSD_ATOM_TO_STRING(jsdobj->newURL);
return NULL;
}
unsigned
jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
{
return jsdobj->newLineno;
}
const char*
jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj)
{
if( jsdobj->ctorURL )
return JSD_ATOM_TO_STRING(jsdobj->ctorURL);
return NULL;
}
unsigned
jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
{
return jsdobj->ctorLineno;
}
const char*
jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj)
{
if( jsdobj->ctorName )
return JSD_ATOM_TO_STRING(jsdobj->ctorName);
return NULL;
}
JSDObject*
jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj)
{
JSDObject* jsdobj;
JSD_LOCK_OBJECTS(jsdc);
jsdobj = (JSDObject*) JS_HashTableLookup(jsdc->objectsTable, jsobj);
JSD_UNLOCK_OBJECTS(jsdc);
return jsdobj;
}
JSDObject*
jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval)
{
return jsd_GetJSDObjectForJSObject(jsdc, JSVAL_TO_OBJECT(jsdval->val));
}
JSDValue*
jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj)
{
return jsd_NewValue(jsdc, OBJECT_TO_JSVAL(jsdobj->obj));
}