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 - Call stack support
40 : */
41 :
42 : #include "jsd.h"
43 : #include "jsfriendapi.h"
44 :
45 : #ifdef DEBUG
46 3 : void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate)
47 : {
48 3 : JS_ASSERT(jsdthreadstate);
49 3 : JS_ASSERT(jsdthreadstate->stackDepth > 0);
50 3 : }
51 :
52 3 : void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe)
53 : {
54 3 : JS_ASSERT(jsdframe);
55 3 : JS_ASSERT(jsdframe->jsdthreadstate);
56 3 : }
57 : #endif
58 :
59 : static JSDStackFrameInfo*
60 21 : _addNewFrame(JSDContext* jsdc,
61 : JSDThreadState* jsdthreadstate,
62 : JSScript* script,
63 : uintptr_t pc,
64 : JSStackFrame* fp)
65 : {
66 : JSDStackFrameInfo* jsdframe;
67 21 : JSDScript* jsdscript = NULL;
68 :
69 21 : if (JS_IsScriptFrame(jsdthreadstate->context, fp))
70 : {
71 21 : JSD_LOCK_SCRIPTS(jsdc);
72 21 : jsdscript = jsd_FindJSDScript(jsdc, script);
73 21 : JSD_UNLOCK_SCRIPTS(jsdc);
74 21 : if (!jsdscript || (jsdc->flags & JSD_HIDE_DISABLED_FRAMES &&
75 0 : !JSD_IS_DEBUG_ENABLED(jsdc, jsdscript)))
76 : {
77 5 : return NULL;
78 : }
79 :
80 16 : if (!JSD_IS_DEBUG_ENABLED(jsdc, jsdscript))
81 0 : jsdthreadstate->flags |= TS_HAS_DISABLED_FRAME;
82 : }
83 :
84 16 : jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo));
85 16 : if( ! jsdframe )
86 0 : return NULL;
87 :
88 16 : jsdframe->jsdthreadstate = jsdthreadstate;
89 16 : jsdframe->jsdscript = jsdscript;
90 16 : jsdframe->pc = pc;
91 16 : jsdframe->fp = fp;
92 :
93 16 : JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
94 16 : jsdthreadstate->stackDepth++;
95 :
96 16 : return jsdframe;
97 : }
98 :
99 : static void
100 16 : _destroyFrame(JSDStackFrameInfo* jsdframe)
101 : {
102 : /* kill any alloc'd objects in frame here... */
103 :
104 16 : if( jsdframe )
105 16 : free(jsdframe);
106 16 : }
107 :
108 : JSDThreadState*
109 5 : jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
110 : {
111 : JSDThreadState* jsdthreadstate;
112 5 : JSStackFrame * iter = NULL;
113 : JSStackFrame * fp;
114 :
115 5 : jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState));
116 5 : if( ! jsdthreadstate )
117 0 : return NULL;
118 :
119 5 : jsdthreadstate->context = cx;
120 5 : jsdthreadstate->thread = JSD_CURRENT_THREAD();
121 5 : JS_INIT_CLIST(&jsdthreadstate->stack);
122 5 : jsdthreadstate->stackDepth = 0;
123 :
124 5 : JS_BeginRequest(jsdthreadstate->context);
125 5 : while( NULL != (fp = JS_FrameIterator(cx, &iter)) )
126 : {
127 21 : JSScript* script = JS_GetFrameScript(cx, fp);
128 21 : uintptr_t pc = (uintptr_t) JS_GetFramePC(cx, fp);
129 : jsval dummyThis;
130 :
131 : /*
132 : * don't construct a JSDStackFrame for dummy frames (those without a
133 : * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
134 : * isn't set.
135 : */
136 42 : if (JS_GetFrameThis(cx, fp, &dummyThis) &&
137 42 : ((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
138 21 : JS_IsScriptFrame(cx, fp)))
139 : {
140 : JSDStackFrameInfo *frame;
141 :
142 21 : frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
143 :
144 42 : if ((jsdthreadstate->stackDepth == 0 && !frame) ||
145 31 : (jsdthreadstate->stackDepth == 1 && frame &&
146 10 : frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript)))
147 : {
148 : /*
149 : * if we failed to create the first frame, or the top frame
150 : * is not enabled for debugging, fail the entire thread state.
151 : */
152 0 : JS_INIT_CLIST(&jsdthreadstate->links);
153 0 : JS_EndRequest(jsdthreadstate->context);
154 0 : jsd_DestroyThreadState(jsdc, jsdthreadstate);
155 0 : return NULL;
156 : }
157 : }
158 : }
159 5 : JS_EndRequest(jsdthreadstate->context);
160 :
161 5 : if (jsdthreadstate->stackDepth == 0)
162 : {
163 0 : free(jsdthreadstate);
164 0 : return NULL;
165 : }
166 :
167 5 : JSD_LOCK_THREADSTATES(jsdc);
168 5 : JS_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates);
169 5 : JSD_UNLOCK_THREADSTATES(jsdc);
170 :
171 5 : return jsdthreadstate;
172 : }
173 :
174 : void
175 5 : jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
176 : {
177 : JSDStackFrameInfo* jsdframe;
178 : JSCList* list;
179 :
180 5 : JS_ASSERT(jsdthreadstate);
181 5 : JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
182 :
183 5 : JSD_LOCK_THREADSTATES(jsdc);
184 5 : JS_REMOVE_LINK(&jsdthreadstate->links);
185 5 : JSD_UNLOCK_THREADSTATES(jsdc);
186 :
187 5 : list = &jsdthreadstate->stack;
188 26 : while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) )
189 : {
190 16 : JS_REMOVE_LINK(&jsdframe->links);
191 16 : _destroyFrame(jsdframe);
192 : }
193 5 : free(jsdthreadstate);
194 5 : }
195 :
196 : unsigned
197 0 : jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
198 : {
199 0 : unsigned count = 0;
200 :
201 0 : JSD_LOCK_THREADSTATES(jsdc);
202 :
203 0 : if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
204 0 : count = jsdthreadstate->stackDepth;
205 :
206 0 : JSD_UNLOCK_THREADSTATES(jsdc);
207 :
208 0 : return count;
209 : }
210 :
211 : JSDStackFrameInfo*
212 2 : jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
213 : {
214 2 : JSDStackFrameInfo* jsdframe = NULL;
215 :
216 2 : JSD_LOCK_THREADSTATES(jsdc);
217 :
218 2 : if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
219 2 : jsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdthreadstate->stack);
220 2 : JSD_UNLOCK_THREADSTATES(jsdc);
221 :
222 2 : return jsdframe;
223 : }
224 :
225 : JSContext *
226 1 : jsd_GetJSContext (JSDContext* jsdc, JSDThreadState* jsdthreadstate)
227 : {
228 1 : JSContext* cx = NULL;
229 :
230 1 : JSD_LOCK_THREADSTATES(jsdc);
231 1 : if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
232 1 : cx = jsdthreadstate->context;
233 1 : JSD_UNLOCK_THREADSTATES(jsdc);
234 :
235 1 : return cx;
236 : }
237 :
238 : JSDStackFrameInfo*
239 0 : jsd_GetCallingStackFrame(JSDContext* jsdc,
240 : JSDThreadState* jsdthreadstate,
241 : JSDStackFrameInfo* jsdframe)
242 : {
243 0 : JSDStackFrameInfo* nextjsdframe = NULL;
244 :
245 0 : JSD_LOCK_THREADSTATES(jsdc);
246 :
247 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
248 0 : if( JS_LIST_HEAD(&jsdframe->links) != &jsdframe->jsdthreadstate->stack )
249 0 : nextjsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdframe->links);
250 :
251 0 : JSD_UNLOCK_THREADSTATES(jsdc);
252 :
253 0 : return nextjsdframe;
254 : }
255 :
256 : JSDScript*
257 1 : jsd_GetScriptForStackFrame(JSDContext* jsdc,
258 : JSDThreadState* jsdthreadstate,
259 : JSDStackFrameInfo* jsdframe)
260 : {
261 1 : JSDScript* jsdscript = NULL;
262 :
263 1 : JSD_LOCK_THREADSTATES(jsdc);
264 :
265 1 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
266 1 : jsdscript = jsdframe->jsdscript;
267 :
268 1 : JSD_UNLOCK_THREADSTATES(jsdc);
269 :
270 1 : return jsdscript;
271 : }
272 :
273 : uintptr_t
274 1 : jsd_GetPCForStackFrame(JSDContext* jsdc,
275 : JSDThreadState* jsdthreadstate,
276 : JSDStackFrameInfo* jsdframe)
277 : {
278 1 : uintptr_t pc = 0;
279 :
280 1 : JSD_LOCK_THREADSTATES(jsdc);
281 :
282 1 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
283 1 : pc = jsdframe->pc;
284 :
285 1 : JSD_UNLOCK_THREADSTATES(jsdc);
286 :
287 1 : return pc;
288 : }
289 :
290 : JSDValue*
291 0 : jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
292 : JSDThreadState* jsdthreadstate,
293 : JSDStackFrameInfo* jsdframe)
294 : {
295 : JSObject* obj;
296 0 : JSDValue* jsdval = NULL;
297 :
298 0 : JSD_LOCK_THREADSTATES(jsdc);
299 :
300 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
301 : {
302 0 : obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp);
303 0 : if(obj)
304 0 : jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
305 : }
306 :
307 0 : JSD_UNLOCK_THREADSTATES(jsdc);
308 :
309 0 : return jsdval;
310 : }
311 :
312 : JSDValue*
313 1 : jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
314 : JSDThreadState* jsdthreadstate,
315 : JSDStackFrameInfo* jsdframe)
316 : {
317 : JSObject* obj;
318 1 : JSDValue* jsdval = NULL;
319 :
320 1 : JSD_LOCK_THREADSTATES(jsdc);
321 :
322 1 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
323 : {
324 1 : JS_BeginRequest(jsdthreadstate->context);
325 1 : obj = JS_GetFrameScopeChain(jsdthreadstate->context, jsdframe->fp);
326 1 : JS_EndRequest(jsdthreadstate->context);
327 1 : if(obj)
328 1 : jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
329 : }
330 :
331 1 : JSD_UNLOCK_THREADSTATES(jsdc);
332 :
333 1 : return jsdval;
334 : }
335 :
336 : JSDValue*
337 0 : jsd_GetThisForStackFrame(JSDContext* jsdc,
338 : JSDThreadState* jsdthreadstate,
339 : JSDStackFrameInfo* jsdframe)
340 : {
341 : JSObject* obj;
342 0 : JSDValue* jsdval = NULL;
343 0 : JSD_LOCK_THREADSTATES(jsdc);
344 :
345 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
346 : {
347 : JSBool ok;
348 : jsval thisval;
349 0 : JS_BeginRequest(jsdthreadstate->context);
350 0 : ok = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp, &thisval);
351 0 : JS_EndRequest(jsdthreadstate->context);
352 0 : if(ok)
353 0 : jsdval = JSD_NewValue(jsdc, thisval);
354 : }
355 :
356 0 : JSD_UNLOCK_THREADSTATES(jsdc);
357 0 : return jsdval;
358 : }
359 :
360 : JSString*
361 0 : jsd_GetIdForStackFrame(JSDContext* jsdc,
362 : JSDThreadState* jsdthreadstate,
363 : JSDStackFrameInfo* jsdframe)
364 : {
365 0 : JSString *rv = NULL;
366 :
367 0 : JSD_LOCK_THREADSTATES(jsdc);
368 :
369 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
370 : {
371 0 : JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
372 : jsdframe->fp);
373 0 : if( fun )
374 : {
375 0 : rv = JS_GetFunctionId (fun);
376 :
377 : /*
378 : * For compatibility we return "anonymous", not an empty string
379 : * here.
380 : */
381 0 : if( !rv )
382 0 : rv = JS_GetAnonymousString(jsdc->jsrt);
383 : }
384 : }
385 :
386 0 : JSD_UNLOCK_THREADSTATES(jsdc);
387 0 : return rv;
388 : }
389 :
390 : JSBool
391 0 : jsd_IsStackFrameDebugger(JSDContext* jsdc,
392 : JSDThreadState* jsdthreadstate,
393 : JSDStackFrameInfo* jsdframe)
394 : {
395 0 : JSBool rv = JS_TRUE;
396 0 : JSD_LOCK_THREADSTATES(jsdc);
397 :
398 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
399 : {
400 0 : rv = JS_IsDebuggerFrame(jsdthreadstate->context, jsdframe->fp);
401 : }
402 :
403 0 : JSD_UNLOCK_THREADSTATES(jsdc);
404 0 : return rv;
405 : }
406 :
407 : JSBool
408 0 : jsd_IsStackFrameConstructing(JSDContext* jsdc,
409 : JSDThreadState* jsdthreadstate,
410 : JSDStackFrameInfo* jsdframe)
411 : {
412 0 : JSBool rv = JS_TRUE;
413 0 : JSD_LOCK_THREADSTATES(jsdc);
414 :
415 0 : if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
416 : {
417 0 : rv = JS_IsConstructorFrame(jsdthreadstate->context, jsdframe->fp);
418 : }
419 :
420 0 : JSD_UNLOCK_THREADSTATES(jsdc);
421 0 : return rv;
422 : }
423 :
424 : JSBool
425 0 : jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
426 : JSDThreadState* jsdthreadstate,
427 : JSDStackFrameInfo* jsdframe,
428 : const jschar *bytes, unsigned length,
429 : const char *filename, unsigned lineno,
430 : JSBool eatExceptions, jsval *rval)
431 : {
432 : JSBool retval;
433 : JSBool valid;
434 0 : JSExceptionState* exceptionState = NULL;
435 : JSContext* cx;
436 :
437 0 : JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
438 :
439 0 : JSD_LOCK_THREADSTATES(jsdc);
440 0 : valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
441 0 : JSD_UNLOCK_THREADSTATES(jsdc);
442 :
443 0 : if( ! valid )
444 0 : return JS_FALSE;
445 :
446 0 : cx = jsdthreadstate->context;
447 0 : JS_ASSERT(cx);
448 :
449 0 : if (eatExceptions)
450 0 : exceptionState = JS_SaveExceptionState(cx);
451 0 : JS_ClearPendingException(cx);
452 0 : jsd_StartingEvalUsingFilename(jsdc, filename);
453 0 : retval = JS_EvaluateUCInStackFrame(cx, jsdframe->fp, bytes, length,
454 : filename, lineno, rval);
455 0 : jsd_FinishedEvalUsingFilename(jsdc, filename);
456 0 : if (eatExceptions)
457 0 : JS_RestoreExceptionState(cx, exceptionState);
458 :
459 0 : return retval;
460 : }
461 :
462 : JSBool
463 0 : jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
464 : JSDThreadState* jsdthreadstate,
465 : JSDStackFrameInfo* jsdframe,
466 : const char *bytes, unsigned length,
467 : const char *filename, unsigned lineno,
468 : JSBool eatExceptions, jsval *rval)
469 : {
470 : JSBool retval;
471 : JSBool valid;
472 0 : JSExceptionState* exceptionState = NULL;
473 : JSContext *cx;
474 :
475 0 : JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
476 :
477 0 : JSD_LOCK_THREADSTATES(jsdc);
478 0 : valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
479 0 : JSD_UNLOCK_THREADSTATES(jsdc);
480 :
481 0 : if (!valid)
482 0 : return JS_FALSE;
483 :
484 0 : cx = jsdthreadstate->context;
485 0 : JS_ASSERT(cx);
486 :
487 0 : if (eatExceptions)
488 0 : exceptionState = JS_SaveExceptionState(cx);
489 0 : JS_ClearPendingException(cx);
490 0 : jsd_StartingEvalUsingFilename(jsdc, filename);
491 0 : retval = JS_EvaluateInStackFrame(cx, jsdframe->fp, bytes, length,
492 : filename, lineno, rval);
493 0 : jsd_FinishedEvalUsingFilename(jsdc, filename);
494 0 : if (eatExceptions)
495 0 : JS_RestoreExceptionState(cx, exceptionState);
496 :
497 0 : return retval;
498 : }
499 :
500 : JSString*
501 0 : jsd_ValToStringInStackFrame(JSDContext* jsdc,
502 : JSDThreadState* jsdthreadstate,
503 : JSDStackFrameInfo* jsdframe,
504 : jsval val)
505 : {
506 : JSBool valid;
507 : JSString* retval;
508 : JSExceptionState* exceptionState;
509 : JSContext* cx;
510 :
511 0 : JSD_LOCK_THREADSTATES(jsdc);
512 0 : valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
513 0 : JSD_UNLOCK_THREADSTATES(jsdc);
514 :
515 0 : if( ! valid )
516 0 : return NULL;
517 :
518 0 : cx = jsdthreadstate->context;
519 0 : JS_ASSERT(cx);
520 :
521 0 : exceptionState = JS_SaveExceptionState(cx);
522 0 : retval = JS_ValueToString(cx, val);
523 0 : JS_RestoreExceptionState(cx, exceptionState);
524 :
525 0 : return retval;
526 : }
527 :
528 : JSBool
529 6 : jsd_IsValidThreadState(JSDContext* jsdc,
530 : JSDThreadState* jsdthreadstate)
531 : {
532 : JSDThreadState *cur;
533 :
534 6 : JS_ASSERT( JSD_THREADSTATES_LOCKED(jsdc) );
535 :
536 12 : for( cur = (JSDThreadState*)jsdc->threadsStates.next;
537 6 : cur != (JSDThreadState*)&jsdc->threadsStates;
538 0 : cur = (JSDThreadState*)cur->links.next )
539 : {
540 6 : if( cur == jsdthreadstate )
541 6 : return JS_TRUE;
542 : }
543 0 : return JS_FALSE;
544 : }
545 :
546 : JSBool
547 3 : jsd_IsValidFrameInThreadState(JSDContext* jsdc,
548 : JSDThreadState* jsdthreadstate,
549 : JSDStackFrameInfo* jsdframe)
550 : {
551 3 : JS_ASSERT(JSD_THREADSTATES_LOCKED(jsdc));
552 :
553 3 : if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) )
554 0 : return JS_FALSE;
555 3 : if( jsdframe->jsdthreadstate != jsdthreadstate )
556 0 : return JS_FALSE;
557 :
558 3 : JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate);
559 3 : JSD_ASSERT_VALID_STACK_FRAME(jsdframe);
560 :
561 3 : return JS_TRUE;
562 : }
563 :
564 : static JSContext*
565 0 : _getContextForThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
566 : {
567 : JSBool valid;
568 0 : JSD_LOCK_THREADSTATES(jsdc);
569 0 : valid = jsd_IsValidThreadState(jsdc, jsdthreadstate);
570 0 : JSD_UNLOCK_THREADSTATES(jsdc);
571 0 : if( valid )
572 0 : return jsdthreadstate->context;
573 0 : return NULL;
574 : }
575 :
576 : JSDValue*
577 0 : jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
578 : {
579 : JSContext* cx;
580 : jsval val;
581 :
582 0 : if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
583 0 : return NULL;
584 :
585 0 : if(JS_GetPendingException(cx, &val))
586 0 : return jsd_NewValue(jsdc, val);
587 0 : return NULL;
588 : }
589 :
590 : JSBool
591 0 : jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate,
592 : JSDValue* jsdval)
593 : {
594 : JSContext* cx;
595 :
596 0 : if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
597 0 : return JS_FALSE;
598 :
599 0 : if(jsdval)
600 0 : JS_SetPendingException(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval));
601 : else
602 0 : JS_ClearPendingException(cx);
603 0 : return JS_TRUE;
604 : }
605 :
|