mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 08:35:26 +00:00
330 lines
8.8 KiB
C
330 lines
8.8 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* 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 ***** */
|
|
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
static JSDObject*
|
|
_createJSDObject(JSDContext* jsdc, JSContext *cx, JSObject *obj)
|
|
{
|
|
JSDObject* jsdobj;
|
|
JSStackFrame* fp;
|
|
JSStackFrame* iter = NULL;
|
|
const char* newURL;
|
|
jsbytecode* pc;
|
|
|
|
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
|
|
|
jsdobj = (JSDObject*) calloc(1, sizeof(JSDObject));
|
|
if (jsdobj)
|
|
{
|
|
JS_INIT_CLIST(&jsdobj->links);
|
|
JS_APPEND_LINK(&jsdobj->links, &jsdc->objectsList);
|
|
jsdobj->obj = obj;
|
|
JS_HashTableAdd(jsdc->objectsTable, obj, jsdobj);
|
|
|
|
if (jsdc->flags & JSD_DISABLE_OBJECT_TRACE)
|
|
return jsdobj;
|
|
|
|
/* walk the stack to find js frame (if any) causing creation */
|
|
while (NULL != (fp = JS_FrameIterator(cx, &iter)))
|
|
{
|
|
if( !JS_IsNativeFrame(cx, fp) )
|
|
{
|
|
JSScript* script = JS_GetFrameScript(cx, fp);
|
|
if( !script )
|
|
continue;
|
|
|
|
newURL = JS_GetScriptFilename(cx, script);
|
|
if( newURL )
|
|
jsdobj->newURL = jsd_AddAtom(jsdc, newURL);
|
|
|
|
pc = JS_GetFramePC(cx, fp);
|
|
if( pc )
|
|
jsdobj->newLineno = JS_PCToLineNumber(cx, script, pc);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return jsdobj;
|
|
}
|
|
|
|
void JS_DLL_CALLBACK
|
|
jsd_ObjectHook(JSContext *cx, JSObject *obj, JSBool isNew, void *closure)
|
|
{
|
|
JSDObject* jsdobj;
|
|
JSDContext* jsdc = (JSDContext*) closure;
|
|
|
|
if( ! jsdc || ! jsdc->inited )
|
|
return;
|
|
|
|
JSD_LOCK_OBJECTS(jsdc);
|
|
if(isNew)
|
|
{
|
|
jsdobj = _createJSDObject(jsdc, cx, obj);
|
|
TRACEOBJ(jsdc, jsdobj, 0);
|
|
}
|
|
else
|
|
{
|
|
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
|
if( jsdobj )
|
|
{
|
|
TRACEOBJ(jsdc, jsdobj, 1);
|
|
_destroyJSDObject(jsdc, jsdobj);
|
|
}
|
|
}
|
|
JSD_UNLOCK_OBJECTS(jsdc);
|
|
}
|
|
|
|
void
|
|
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
|
JSStackFrame *fp)
|
|
{
|
|
JSDObject* jsdobj;
|
|
JSScript* script;
|
|
JSDScript* jsdscript;
|
|
const char* ctorURL;
|
|
const char* ctorName;
|
|
|
|
JSD_LOCK_OBJECTS(jsdc);
|
|
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
|
if( jsdobj && !jsdobj->ctorURL && !JS_IsNativeFrame(cx, fp) )
|
|
{
|
|
script = JS_GetFrameScript(cx, fp);
|
|
if( script )
|
|
{
|
|
ctorURL = JS_GetScriptFilename(cx, script);
|
|
if( ctorURL )
|
|
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
|
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
|
if( jsdscript )
|
|
{
|
|
ctorName = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
|
if( ctorName )
|
|
jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName);
|
|
}
|
|
jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script);
|
|
}
|
|
}
|
|
TRACEOBJ(jsdc, jsdobj, 3);
|
|
JSD_UNLOCK_OBJECTS(jsdc);
|
|
}
|
|
|
|
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
|
_hash_root(const void *key)
|
|
{
|
|
return ((JSHashNumber) 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 (JSBool) jsdc->objectsTable;
|
|
}
|
|
|
|
void
|
|
jsd_DestroyObjectManager(JSDContext* jsdc)
|
|
{
|
|
JSD_LOCK_OBJECTS(jsdc);
|
|
while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
|
|
_destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
|
|
JS_HashTableDestroy(jsdc->objectsTable);
|
|
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;
|
|
}
|
|
|
|
uintN
|
|
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;
|
|
}
|
|
|
|
uintN
|
|
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));
|
|
}
|
|
|
|
|