Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
7 /*
8 * JavaScript Debugging support - Hook support
9 */
11 #include "jsd.h"
13 JSTrapStatus
14 jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
15 void *closure)
16 {
17 JSDScript* jsdscript;
18 JSDContext* jsdc = (JSDContext*) closure;
19 JSD_ExecutionHookProc hook;
20 void* hookData;
22 if( ! jsdc || ! jsdc->inited )
23 return JSTRAP_CONTINUE;
25 if( JSD_IS_DANGEROUS_THREAD(jsdc) )
26 return JSTRAP_CONTINUE;
28 /* local in case jsdc->interruptHook gets cleared on another thread */
29 JSD_LOCK();
30 hook = jsdc->interruptHook;
31 hookData = jsdc->interruptHookData;
32 JSD_UNLOCK();
34 if (!hook)
35 return JSTRAP_CONTINUE;
37 JSD_LOCK_SCRIPTS(jsdc);
38 jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
39 JSD_UNLOCK_SCRIPTS(jsdc);
40 if( ! jsdscript )
41 return JSTRAP_CONTINUE;
43 return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
44 hook, hookData, rval);
45 }
47 JSTrapStatus
48 jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
49 jsval *rval, void *closure)
50 {
51 JSDScript* jsdscript;
52 JSDContext* jsdc = (JSDContext*) closure;
53 JSD_ExecutionHookProc hook;
54 void* hookData;
56 if( ! jsdc || ! jsdc->inited )
57 return JSTRAP_CONTINUE;
59 if( JSD_IS_DANGEROUS_THREAD(jsdc) )
60 return JSTRAP_CONTINUE;
62 /* local in case jsdc->debuggerHook gets cleared on another thread */
63 JSD_LOCK();
64 hook = jsdc->debuggerHook;
65 hookData = jsdc->debuggerHookData;
66 JSD_UNLOCK();
67 if(!hook)
68 return JSTRAP_CONTINUE;
70 JSD_LOCK_SCRIPTS(jsdc);
71 jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
72 JSD_UNLOCK_SCRIPTS(jsdc);
73 if( ! jsdscript )
74 return JSTRAP_CONTINUE;
76 return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
77 hook, hookData, rval);
78 }
81 JSTrapStatus
82 jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
83 jsval *rvalArg, void *closure)
84 {
85 JSDScript* jsdscript;
86 JSDContext* jsdc = (JSDContext*) closure;
87 JSD_ExecutionHookProc hook;
88 void* hookData;
90 if( ! jsdc || ! jsdc->inited )
91 return JSTRAP_CONTINUE;
93 if( JSD_IS_DANGEROUS_THREAD(jsdc) )
94 return JSTRAP_CONTINUE;
96 /* local in case jsdc->throwHook gets cleared on another thread */
97 JSD_LOCK();
98 hook = jsdc->throwHook;
99 hookData = jsdc->throwHookData;
100 JSD_UNLOCK();
101 if (!hook)
102 return JSTRAP_CONTINUE;
104 JSD_LOCK_SCRIPTS(jsdc);
105 jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
106 JSD_UNLOCK_SCRIPTS(jsdc);
107 if( ! jsdscript )
108 return JSTRAP_CONTINUE;
110 JS::RootedValue rval(cx);
111 JS_GetPendingException(cx, &rval);
113 JSTrapStatus result = jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
114 hook, hookData, rval.address());
115 *rvalArg = rval;
116 return result;
117 }
119 JSTrapStatus
120 jsd_CallExecutionHook(JSDContext* jsdc,
121 JSContext *cx,
122 unsigned type,
123 JSD_ExecutionHookProc hook,
124 void* hookData,
125 jsval* rval)
126 {
127 unsigned hookanswer = JSD_HOOK_THROW == type ?
128 JSD_HOOK_RETURN_CONTINUE_THROW :
129 JSD_HOOK_RETURN_CONTINUE;
130 JSDThreadState* jsdthreadstate;
132 if(hook && nullptr != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
133 {
134 if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
135 jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
136 !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
137 {
138 /*
139 * if it's not a throw and it's not an interrupt,
140 * or we're only masking the top frame,
141 * or there are no disabled frames in this stack,
142 * then call out.
143 */
144 hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
145 jsd_DestroyThreadState(jsdc, jsdthreadstate);
146 }
147 }
149 switch(hookanswer)
150 {
151 case JSD_HOOK_RETURN_ABORT:
152 case JSD_HOOK_RETURN_HOOK_ERROR:
153 return JSTRAP_ERROR;
154 case JSD_HOOK_RETURN_RET_WITH_VAL:
155 return JSTRAP_RETURN;
156 case JSD_HOOK_RETURN_THROW_WITH_VAL:
157 return JSTRAP_THROW;
158 case JSD_HOOK_RETURN_CONTINUE:
159 break;
160 case JSD_HOOK_RETURN_CONTINUE_THROW:
161 /* only makes sense for jsd_ThrowHandler (which init'd rval) */
162 MOZ_ASSERT(JSD_HOOK_THROW == type);
163 return JSTRAP_THROW;
164 default:
165 MOZ_ASSERT(0);
166 break;
167 }
168 return JSTRAP_CONTINUE;
169 }
171 bool
172 jsd_CallCallHook (JSDContext* jsdc,
173 JSContext *cx,
174 unsigned type,
175 JSD_CallHookProc hook,
176 void* hookData)
177 {
178 bool hookanswer;
179 JSDThreadState* jsdthreadstate;
181 hookanswer = false;
182 if(hook && nullptr != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
183 {
184 hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
185 jsd_DestroyThreadState(jsdc, jsdthreadstate);
186 }
188 return hookanswer;
189 }
191 bool
192 jsd_SetInterruptHook(JSDContext* jsdc,
193 JSD_ExecutionHookProc hook,
194 void* callerdata)
195 {
196 JSD_LOCK();
197 jsdc->interruptHookData = callerdata;
198 jsdc->interruptHook = hook;
199 JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
200 JSD_UNLOCK();
202 return true;
203 }
205 bool
206 jsd_ClearInterruptHook(JSDContext* jsdc)
207 {
208 JSD_LOCK();
209 JS_ClearInterrupt(jsdc->jsrt, nullptr, nullptr);
210 jsdc->interruptHook = nullptr;
211 JSD_UNLOCK();
213 return true;
214 }
216 bool
217 jsd_SetDebugBreakHook(JSDContext* jsdc,
218 JSD_ExecutionHookProc hook,
219 void* callerdata)
220 {
221 JSD_LOCK();
222 jsdc->debugBreakHookData = callerdata;
223 jsdc->debugBreakHook = hook;
224 JSD_UNLOCK();
226 return true;
227 }
229 bool
230 jsd_ClearDebugBreakHook(JSDContext* jsdc)
231 {
232 JSD_LOCK();
233 jsdc->debugBreakHook = nullptr;
234 JSD_UNLOCK();
236 return true;
237 }
239 bool
240 jsd_SetDebuggerHook(JSDContext* jsdc,
241 JSD_ExecutionHookProc hook,
242 void* callerdata)
243 {
244 JSD_LOCK();
245 jsdc->debuggerHookData = callerdata;
246 jsdc->debuggerHook = hook;
247 JSD_UNLOCK();
249 return true;
250 }
252 bool
253 jsd_ClearDebuggerHook(JSDContext* jsdc)
254 {
255 JSD_LOCK();
256 jsdc->debuggerHook = nullptr;
257 JSD_UNLOCK();
259 return true;
260 }
262 bool
263 jsd_SetThrowHook(JSDContext* jsdc,
264 JSD_ExecutionHookProc hook,
265 void* callerdata)
266 {
267 JSD_LOCK();
268 jsdc->throwHookData = callerdata;
269 jsdc->throwHook = hook;
270 JSD_UNLOCK();
272 return true;
273 }
275 bool
276 jsd_ClearThrowHook(JSDContext* jsdc)
277 {
278 JSD_LOCK();
279 jsdc->throwHook = nullptr;
280 JSD_UNLOCK();
282 return true;
283 }
285 bool
286 jsd_SetFunctionHook(JSDContext* jsdc,
287 JSD_CallHookProc hook,
288 void* callerdata)
289 {
290 JSD_LOCK();
291 jsdc->functionHookData = callerdata;
292 jsdc->functionHook = hook;
293 JSD_UNLOCK();
295 return true;
296 }
298 bool
299 jsd_ClearFunctionHook(JSDContext* jsdc)
300 {
301 JSD_LOCK();
302 jsdc->functionHook = nullptr;
303 JSD_UNLOCK();
305 return true;
306 }
308 bool
309 jsd_SetTopLevelHook(JSDContext* jsdc,
310 JSD_CallHookProc hook,
311 void* callerdata)
312 {
313 JSD_LOCK();
314 jsdc->toplevelHookData = callerdata;
315 jsdc->toplevelHook = hook;
316 JSD_UNLOCK();
318 return true;
319 }
321 bool
322 jsd_ClearTopLevelHook(JSDContext* jsdc)
323 {
324 JSD_LOCK();
325 jsdc->toplevelHook = nullptr;
326 JSD_UNLOCK();
328 return true;
329 }