1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /*
39 : * JavaScript Debugging support - Hook support
40 : */
41 :
42 : #include "jsd.h"
43 :
44 : JSTrapStatus
45 0 : jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
46 : void *closure)
47 : {
48 : JSDScript* jsdscript;
49 0 : JSDContext* jsdc = (JSDContext*) closure;
50 : JSD_ExecutionHookProc hook;
51 : void* hookData;
52 :
53 0 : if( ! jsdc || ! jsdc->inited )
54 0 : return JSTRAP_CONTINUE;
55 :
56 : if( JSD_IS_DANGEROUS_THREAD(jsdc) )
57 : return JSTRAP_CONTINUE;
58 :
59 : /* local in case jsdc->interruptHook gets cleared on another thread */
60 0 : JSD_LOCK();
61 0 : hook = jsdc->interruptHook;
62 0 : hookData = jsdc->interruptHookData;
63 0 : JSD_UNLOCK();
64 :
65 0 : if (!hook)
66 0 : return JSTRAP_CONTINUE;
67 :
68 0 : JSD_LOCK_SCRIPTS(jsdc);
69 0 : jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
70 0 : JSD_UNLOCK_SCRIPTS(jsdc);
71 0 : if( ! jsdscript )
72 0 : return JSTRAP_CONTINUE;
73 :
74 : #ifdef LIVEWIRE
75 : if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) )
76 : return JSTRAP_CONTINUE;
77 : #endif
78 :
79 0 : return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
80 : hook, hookData, rval);
81 : }
82 :
83 : JSTrapStatus
84 0 : jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
85 : jsval *rval, void *closure)
86 : {
87 : JSDScript* jsdscript;
88 0 : JSDContext* jsdc = (JSDContext*) closure;
89 : JSD_ExecutionHookProc hook;
90 : void* hookData;
91 :
92 0 : if( ! jsdc || ! jsdc->inited )
93 0 : return JSTRAP_CONTINUE;
94 :
95 : if( JSD_IS_DANGEROUS_THREAD(jsdc) )
96 : return JSTRAP_CONTINUE;
97 :
98 : /* local in case jsdc->debuggerHook gets cleared on another thread */
99 0 : JSD_LOCK();
100 0 : hook = jsdc->debuggerHook;
101 0 : hookData = jsdc->debuggerHookData;
102 0 : JSD_UNLOCK();
103 0 : if(!hook)
104 0 : return JSTRAP_CONTINUE;
105 :
106 0 : JSD_LOCK_SCRIPTS(jsdc);
107 0 : jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
108 0 : JSD_UNLOCK_SCRIPTS(jsdc);
109 0 : if( ! jsdscript )
110 0 : return JSTRAP_CONTINUE;
111 :
112 0 : return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
113 : hook, hookData, rval);
114 : }
115 :
116 :
117 : JSTrapStatus
118 28981 : jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
119 : jsval *rval, void *closure)
120 : {
121 : JSDScript* jsdscript;
122 28981 : JSDContext* jsdc = (JSDContext*) closure;
123 : JSD_ExecutionHookProc hook;
124 : void* hookData;
125 :
126 28981 : if( ! jsdc || ! jsdc->inited )
127 0 : return JSTRAP_CONTINUE;
128 :
129 : if( JSD_IS_DANGEROUS_THREAD(jsdc) )
130 : return JSTRAP_CONTINUE;
131 :
132 : /* local in case jsdc->throwHook gets cleared on another thread */
133 28981 : JSD_LOCK();
134 28981 : hook = jsdc->throwHook;
135 28981 : hookData = jsdc->throwHookData;
136 28981 : JSD_UNLOCK();
137 28981 : if (!hook)
138 28981 : return JSTRAP_CONTINUE;
139 :
140 0 : JSD_LOCK_SCRIPTS(jsdc);
141 0 : jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
142 0 : JSD_UNLOCK_SCRIPTS(jsdc);
143 0 : if( ! jsdscript )
144 0 : return JSTRAP_CONTINUE;
145 :
146 0 : JS_GetPendingException(cx, rval);
147 :
148 0 : return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
149 : hook, hookData, rval);
150 : }
151 :
152 : JSTrapStatus
153 5 : jsd_CallExecutionHook(JSDContext* jsdc,
154 : JSContext *cx,
155 : unsigned type,
156 : JSD_ExecutionHookProc hook,
157 : void* hookData,
158 : jsval* rval)
159 : {
160 5 : unsigned hookanswer = JSD_HOOK_THROW == type ?
161 : JSD_HOOK_RETURN_CONTINUE_THROW :
162 : JSD_HOOK_RETURN_CONTINUE;
163 : JSDThreadState* jsdthreadstate;
164 :
165 5 : if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx)))
166 : {
167 5 : if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
168 0 : jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
169 0 : !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
170 : {
171 : /*
172 : * if it's not a throw and it's not an interrupt,
173 : * or we're only masking the top frame,
174 : * or there are no disabled frames in this stack,
175 : * then call out.
176 : */
177 5 : hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
178 5 : jsd_DestroyThreadState(jsdc, jsdthreadstate);
179 : }
180 : }
181 :
182 5 : switch(hookanswer)
183 : {
184 : case JSD_HOOK_RETURN_ABORT:
185 : case JSD_HOOK_RETURN_HOOK_ERROR:
186 0 : return JSTRAP_ERROR;
187 : case JSD_HOOK_RETURN_RET_WITH_VAL:
188 0 : return JSTRAP_RETURN;
189 : case JSD_HOOK_RETURN_THROW_WITH_VAL:
190 0 : return JSTRAP_THROW;
191 : case JSD_HOOK_RETURN_CONTINUE:
192 5 : break;
193 : case JSD_HOOK_RETURN_CONTINUE_THROW:
194 : /* only makes sense for jsd_ThrowHandler (which init'd rval) */
195 0 : JS_ASSERT(JSD_HOOK_THROW == type);
196 0 : return JSTRAP_THROW;
197 : default:
198 0 : JS_ASSERT(0);
199 0 : break;
200 : }
201 5 : return JSTRAP_CONTINUE;
202 : }
203 :
204 : JSBool
205 0 : jsd_CallCallHook (JSDContext* jsdc,
206 : JSContext *cx,
207 : unsigned type,
208 : JSD_CallHookProc hook,
209 : void* hookData)
210 : {
211 : JSBool hookanswer;
212 : JSDThreadState* jsdthreadstate;
213 :
214 0 : hookanswer = JS_FALSE;
215 0 : if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
216 : {
217 0 : hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
218 0 : jsd_DestroyThreadState(jsdc, jsdthreadstate);
219 : }
220 :
221 0 : return hookanswer;
222 : }
223 :
224 : JSBool
225 0 : jsd_SetInterruptHook(JSDContext* jsdc,
226 : JSD_ExecutionHookProc hook,
227 : void* callerdata)
228 : {
229 0 : JSD_LOCK();
230 0 : jsdc->interruptHookData = callerdata;
231 0 : jsdc->interruptHook = hook;
232 0 : JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
233 0 : JSD_UNLOCK();
234 :
235 0 : return JS_TRUE;
236 : }
237 :
238 : JSBool
239 282 : jsd_ClearInterruptHook(JSDContext* jsdc)
240 : {
241 282 : JSD_LOCK();
242 282 : JS_ClearInterrupt(jsdc->jsrt, NULL, NULL );
243 282 : jsdc->interruptHook = NULL;
244 282 : JSD_UNLOCK();
245 :
246 282 : return JS_TRUE;
247 : }
248 :
249 : JSBool
250 0 : jsd_SetDebugBreakHook(JSDContext* jsdc,
251 : JSD_ExecutionHookProc hook,
252 : void* callerdata)
253 : {
254 0 : JSD_LOCK();
255 0 : jsdc->debugBreakHookData = callerdata;
256 0 : jsdc->debugBreakHook = hook;
257 0 : JSD_UNLOCK();
258 :
259 0 : return JS_TRUE;
260 : }
261 :
262 : JSBool
263 282 : jsd_ClearDebugBreakHook(JSDContext* jsdc)
264 : {
265 282 : JSD_LOCK();
266 282 : jsdc->debugBreakHook = NULL;
267 282 : JSD_UNLOCK();
268 :
269 282 : return JS_TRUE;
270 : }
271 :
272 : JSBool
273 0 : jsd_SetDebuggerHook(JSDContext* jsdc,
274 : JSD_ExecutionHookProc hook,
275 : void* callerdata)
276 : {
277 0 : JSD_LOCK();
278 0 : jsdc->debuggerHookData = callerdata;
279 0 : jsdc->debuggerHook = hook;
280 0 : JSD_UNLOCK();
281 :
282 0 : return JS_TRUE;
283 : }
284 :
285 : JSBool
286 282 : jsd_ClearDebuggerHook(JSDContext* jsdc)
287 : {
288 282 : JSD_LOCK();
289 282 : jsdc->debuggerHook = NULL;
290 282 : JSD_UNLOCK();
291 :
292 282 : return JS_TRUE;
293 : }
294 :
295 : JSBool
296 0 : jsd_SetThrowHook(JSDContext* jsdc,
297 : JSD_ExecutionHookProc hook,
298 : void* callerdata)
299 : {
300 0 : JSD_LOCK();
301 0 : jsdc->throwHookData = callerdata;
302 0 : jsdc->throwHook = hook;
303 0 : JSD_UNLOCK();
304 :
305 0 : return JS_TRUE;
306 : }
307 :
308 : JSBool
309 282 : jsd_ClearThrowHook(JSDContext* jsdc)
310 : {
311 282 : JSD_LOCK();
312 282 : jsdc->throwHook = NULL;
313 282 : JSD_UNLOCK();
314 :
315 282 : return JS_TRUE;
316 : }
317 :
318 : JSBool
319 0 : jsd_SetFunctionHook(JSDContext* jsdc,
320 : JSD_CallHookProc hook,
321 : void* callerdata)
322 : {
323 0 : JSD_LOCK();
324 0 : jsdc->functionHookData = callerdata;
325 0 : jsdc->functionHook = hook;
326 0 : JSD_UNLOCK();
327 :
328 0 : return JS_TRUE;
329 : }
330 :
331 : JSBool
332 564 : jsd_ClearFunctionHook(JSDContext* jsdc)
333 : {
334 564 : JSD_LOCK();
335 564 : jsdc->functionHook = NULL;
336 564 : JSD_UNLOCK();
337 :
338 564 : return JS_TRUE;
339 : }
340 :
341 : JSBool
342 0 : jsd_SetTopLevelHook(JSDContext* jsdc,
343 : JSD_CallHookProc hook,
344 : void* callerdata)
345 : {
346 0 : JSD_LOCK();
347 0 : jsdc->toplevelHookData = callerdata;
348 0 : jsdc->toplevelHook = hook;
349 0 : JSD_UNLOCK();
350 :
351 0 : return JS_TRUE;
352 : }
353 :
354 : JSBool
355 564 : jsd_ClearTopLevelHook(JSDContext* jsdc)
356 : {
357 564 : JSD_LOCK();
358 564 : jsdc->toplevelHook = NULL;
359 564 : JSD_UNLOCK();
360 :
361 564 : return JS_TRUE;
362 : }
363 :
|