|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 /* |
|
8 * JavaScript Debugging support - Object support |
|
9 */ |
|
10 |
|
11 #include "jsd.h" |
|
12 |
|
13 /* |
|
14 * #define JSD_TRACE 1 |
|
15 */ |
|
16 |
|
17 #ifdef JSD_TRACE |
|
18 #define TRACEOBJ(jsdc, jsdobj, which) _traceObj(jsdc, jsdobj, which) |
|
19 |
|
20 static char * |
|
21 _describeObj(JSDContext* jsdc, JSDObject *jsdobj) |
|
22 { |
|
23 return |
|
24 JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d", |
|
25 (int)jsdobj, |
|
26 JSD_GetObjectNewURL(jsdc, jsdobj), |
|
27 JSD_GetObjectNewLineNumber(jsdc, jsdobj), |
|
28 JSD_GetObjectConstructorName(jsdc, jsdobj), |
|
29 JSD_GetObjectConstructorURL(jsdc, jsdobj), |
|
30 JSD_GetObjectConstructorLineNumber(jsdc, jsdobj)); |
|
31 } |
|
32 |
|
33 static void |
|
34 _traceObj(JSDContext* jsdc, JSDObject* jsdobj, int which) |
|
35 { |
|
36 char* description; |
|
37 |
|
38 if( !jsdobj ) |
|
39 return; |
|
40 |
|
41 description = _describeObj(jsdc, jsdobj); |
|
42 |
|
43 printf("%s : %s\n", |
|
44 which == 0 ? "new " : |
|
45 which == 1 ? "final" : |
|
46 "ctor ", |
|
47 description); |
|
48 if(description) |
|
49 free(description); |
|
50 } |
|
51 #else |
|
52 #define TRACEOBJ(jsdc, jsdobj, which) ((void)0) |
|
53 #endif /* JSD_TRACE */ |
|
54 |
|
55 #ifdef DEBUG |
|
56 void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj) |
|
57 { |
|
58 MOZ_ASSERT(jsdobj); |
|
59 MOZ_ASSERT(!JS_CLIST_IS_EMPTY(&jsdobj->links)); |
|
60 MOZ_ASSERT(jsdobj->obj); |
|
61 } |
|
62 #endif |
|
63 |
|
64 |
|
65 static void |
|
66 _destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj) |
|
67 { |
|
68 MOZ_ASSERT(JSD_OBJECTS_LOCKED(jsdc)); |
|
69 |
|
70 JS_REMOVE_LINK(&jsdobj->links); |
|
71 JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj); |
|
72 |
|
73 if(jsdobj->newURL) |
|
74 jsd_DropAtom(jsdc, jsdobj->newURL); |
|
75 if(jsdobj->ctorURL) |
|
76 jsd_DropAtom(jsdc, jsdobj->ctorURL); |
|
77 if(jsdobj->ctorName) |
|
78 jsd_DropAtom(jsdc, jsdobj->ctorName); |
|
79 free(jsdobj); |
|
80 } |
|
81 |
|
82 void |
|
83 jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj, |
|
84 JSAbstractFramePtr frame) |
|
85 { |
|
86 JSDObject* jsdobj; |
|
87 JS::RootedScript script(cx); |
|
88 JSDScript* jsdscript; |
|
89 const char* ctorURL; |
|
90 JSString* ctorNameStr; |
|
91 const char* ctorName; |
|
92 |
|
93 JSD_LOCK_OBJECTS(jsdc); |
|
94 jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj); |
|
95 if( jsdobj && !jsdobj->ctorURL ) |
|
96 { |
|
97 script = frame.script(); |
|
98 if( script ) |
|
99 { |
|
100 ctorURL = JS_GetScriptFilename(script); |
|
101 if( ctorURL ) |
|
102 jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL); |
|
103 |
|
104 JSD_LOCK_SCRIPTS(jsdc); |
|
105 jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame); |
|
106 JSD_UNLOCK_SCRIPTS(jsdc); |
|
107 if( jsdscript && (ctorNameStr = jsd_GetScriptFunctionId(jsdc, jsdscript)) ) { |
|
108 if( (ctorName = JS_EncodeString(cx, ctorNameStr)) ) { |
|
109 jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName); |
|
110 JS_free(cx, (void *) ctorName); |
|
111 } |
|
112 } |
|
113 jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script); |
|
114 } |
|
115 } |
|
116 TRACEOBJ(jsdc, jsdobj, 3); |
|
117 JSD_UNLOCK_OBJECTS(jsdc); |
|
118 } |
|
119 |
|
120 static JSHashNumber |
|
121 _hash_root(const void *key) |
|
122 { |
|
123 return ((JSHashNumber)(ptrdiff_t) key) >> 2; /* help lame MSVC1.5 on Win16 */ |
|
124 } |
|
125 |
|
126 bool |
|
127 jsd_InitObjectManager(JSDContext* jsdc) |
|
128 { |
|
129 JS_INIT_CLIST(&jsdc->objectsList); |
|
130 jsdc->objectsTable = JS_NewHashTable(256, _hash_root, |
|
131 JS_CompareValues, JS_CompareValues, |
|
132 nullptr, nullptr); |
|
133 return !!jsdc->objectsTable; |
|
134 } |
|
135 |
|
136 void |
|
137 jsd_DestroyObjectManager(JSDContext* jsdc) |
|
138 { |
|
139 jsd_DestroyObjects(jsdc); |
|
140 JSD_LOCK_OBJECTS(jsdc); |
|
141 JS_HashTableDestroy(jsdc->objectsTable); |
|
142 JSD_UNLOCK_OBJECTS(jsdc); |
|
143 } |
|
144 |
|
145 void |
|
146 jsd_DestroyObjects(JSDContext* jsdc) |
|
147 { |
|
148 JSD_LOCK_OBJECTS(jsdc); |
|
149 while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) ) |
|
150 _destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList)); |
|
151 JSD_UNLOCK_OBJECTS(jsdc); |
|
152 } |
|
153 |
|
154 JSDObject* |
|
155 jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp) |
|
156 { |
|
157 JSDObject *jsdobj = *iterp; |
|
158 |
|
159 MOZ_ASSERT(JSD_OBJECTS_LOCKED(jsdc)); |
|
160 |
|
161 if( !jsdobj ) |
|
162 jsdobj = (JSDObject *)jsdc->objectsList.next; |
|
163 if( jsdobj == (JSDObject *)&jsdc->objectsList ) |
|
164 return nullptr; |
|
165 *iterp = (JSDObject*) jsdobj->links.next; |
|
166 return jsdobj; |
|
167 } |
|
168 |
|
169 JSObject* |
|
170 jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj) |
|
171 { |
|
172 return jsdobj->obj; |
|
173 } |
|
174 |
|
175 const char* |
|
176 jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj) |
|
177 { |
|
178 if( jsdobj->newURL ) |
|
179 return JSD_ATOM_TO_STRING(jsdobj->newURL); |
|
180 return nullptr; |
|
181 } |
|
182 |
|
183 unsigned |
|
184 jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj) |
|
185 { |
|
186 return jsdobj->newLineno; |
|
187 } |
|
188 |
|
189 const char* |
|
190 jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj) |
|
191 { |
|
192 if( jsdobj->ctorURL ) |
|
193 return JSD_ATOM_TO_STRING(jsdobj->ctorURL); |
|
194 return nullptr; |
|
195 } |
|
196 |
|
197 unsigned |
|
198 jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj) |
|
199 { |
|
200 return jsdobj->ctorLineno; |
|
201 } |
|
202 |
|
203 const char* |
|
204 jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj) |
|
205 { |
|
206 if( jsdobj->ctorName ) |
|
207 return JSD_ATOM_TO_STRING(jsdobj->ctorName); |
|
208 return nullptr; |
|
209 } |
|
210 |
|
211 JSDObject* |
|
212 jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj) |
|
213 { |
|
214 JSDObject* jsdobj; |
|
215 |
|
216 JSD_LOCK_OBJECTS(jsdc); |
|
217 jsdobj = (JSDObject*) JS_HashTableLookup(jsdc->objectsTable, jsobj); |
|
218 JSD_UNLOCK_OBJECTS(jsdc); |
|
219 return jsdobj; |
|
220 } |
|
221 |
|
222 JSDObject* |
|
223 jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval) |
|
224 { |
|
225 return jsd_GetJSDObjectForJSObject(jsdc, JSVAL_TO_OBJECT(jsdval->val)); |
|
226 } |
|
227 |
|
228 JSDValue* |
|
229 jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj) |
|
230 { |
|
231 return jsd_NewValue(jsdc, OBJECT_TO_JSVAL(jsdobj->obj)); |
|
232 } |
|
233 |
|
234 |