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