1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/jsd/jsd_stak.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,575 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * JavaScript Debugging support - Call stack support 1.12 + */ 1.13 + 1.14 +#include "jsd.h" 1.15 +#include "jsfriendapi.h" 1.16 +#include "nsCxPusher.h" 1.17 + 1.18 +using mozilla::AutoPushJSContext; 1.19 + 1.20 +#ifdef DEBUG 1.21 +void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate) 1.22 +{ 1.23 + MOZ_ASSERT(jsdthreadstate); 1.24 + MOZ_ASSERT(jsdthreadstate->stackDepth > 0); 1.25 +} 1.26 + 1.27 +void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe) 1.28 +{ 1.29 + MOZ_ASSERT(jsdframe); 1.30 + MOZ_ASSERT(jsdframe->jsdthreadstate); 1.31 +} 1.32 +#endif 1.33 + 1.34 +static JSDStackFrameInfo* 1.35 +_addNewFrame(JSDContext* jsdc, 1.36 + JSDThreadState* jsdthreadstate, 1.37 + JSScript* script, 1.38 + uintptr_t pc, 1.39 + bool isConstructing, 1.40 + JSAbstractFramePtr frame) 1.41 +{ 1.42 + JSDStackFrameInfo* jsdframe; 1.43 + JSDScript* jsdscript = nullptr; 1.44 + 1.45 + JSD_LOCK_SCRIPTS(jsdc); 1.46 + jsdscript = jsd_FindJSDScript(jsdc, script); 1.47 + JSD_UNLOCK_SCRIPTS(jsdc); 1.48 + if (!jsdscript || (jsdc->flags & JSD_HIDE_DISABLED_FRAMES && 1.49 + !JSD_IS_DEBUG_ENABLED(jsdc, jsdscript))) 1.50 + { 1.51 + return nullptr; 1.52 + } 1.53 + 1.54 + if (!JSD_IS_DEBUG_ENABLED(jsdc, jsdscript)) 1.55 + jsdthreadstate->flags |= TS_HAS_DISABLED_FRAME; 1.56 + 1.57 + jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo)); 1.58 + if( ! jsdframe ) 1.59 + return nullptr; 1.60 + 1.61 + jsdframe->jsdthreadstate = jsdthreadstate; 1.62 + jsdframe->jsdscript = jsdscript; 1.63 + jsdframe->isConstructing = isConstructing; 1.64 + jsdframe->pc = pc; 1.65 + jsdframe->frame = frame; 1.66 + 1.67 + JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack); 1.68 + jsdthreadstate->stackDepth++; 1.69 + 1.70 + return jsdframe; 1.71 +} 1.72 + 1.73 +static void 1.74 +_destroyFrame(JSDStackFrameInfo* jsdframe) 1.75 +{ 1.76 + /* kill any alloc'd objects in frame here... */ 1.77 + 1.78 + if( jsdframe ) 1.79 + free(jsdframe); 1.80 +} 1.81 + 1.82 +JSDThreadState* 1.83 +jsd_NewThreadState(JSDContext* jsdc, JSContext *cx ) 1.84 +{ 1.85 + JSDThreadState* jsdthreadstate; 1.86 + 1.87 + jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState)); 1.88 + if( ! jsdthreadstate ) 1.89 + return nullptr; 1.90 + 1.91 + jsdthreadstate->context = cx; 1.92 + jsdthreadstate->thread = JSD_CURRENT_THREAD(); 1.93 + JS_INIT_CLIST(&jsdthreadstate->stack); 1.94 + jsdthreadstate->stackDepth = 0; 1.95 + 1.96 + JS_BeginRequest(jsdthreadstate->context); 1.97 + 1.98 + JSBrokenFrameIterator iter(cx); 1.99 + while(!iter.done()) 1.100 + { 1.101 + JSAbstractFramePtr frame = iter.abstractFramePtr(); 1.102 + JS::RootedScript script(cx, frame.script()); 1.103 + uintptr_t pc = (uintptr_t)frame.pc(); 1.104 + JS::RootedValue dummyThis(cx); 1.105 + 1.106 + /* 1.107 + * don't construct a JSDStackFrame for dummy frames (those without a 1.108 + * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES 1.109 + * isn't set. 1.110 + */ 1.111 + if (frame.getThisValue(cx, &dummyThis)) 1.112 + { 1.113 + bool isConstructing = iter.isConstructing(); 1.114 + JSDStackFrameInfo *frameInfo = _addNewFrame( jsdc, jsdthreadstate, script, pc, isConstructing, frame ); 1.115 + 1.116 + if ((jsdthreadstate->stackDepth == 0 && !frameInfo) || 1.117 + (jsdthreadstate->stackDepth == 1 && frameInfo && 1.118 + frameInfo->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frameInfo->jsdscript))) 1.119 + { 1.120 + /* 1.121 + * if we failed to create the first frame, or the top frame 1.122 + * is not enabled for debugging, fail the entire thread state. 1.123 + */ 1.124 + JS_INIT_CLIST(&jsdthreadstate->links); 1.125 + JS_EndRequest(jsdthreadstate->context); 1.126 + jsd_DestroyThreadState(jsdc, jsdthreadstate); 1.127 + return nullptr; 1.128 + } 1.129 + } 1.130 + 1.131 + ++iter; 1.132 + } 1.133 + JS_EndRequest(jsdthreadstate->context); 1.134 + 1.135 + if (jsdthreadstate->stackDepth == 0) 1.136 + { 1.137 + free(jsdthreadstate); 1.138 + return nullptr; 1.139 + } 1.140 + 1.141 + JSD_LOCK_THREADSTATES(jsdc); 1.142 + JS_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates); 1.143 + JSD_UNLOCK_THREADSTATES(jsdc); 1.144 + 1.145 + return jsdthreadstate; 1.146 +} 1.147 + 1.148 +void 1.149 +jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.150 +{ 1.151 + JSDStackFrameInfo* jsdframe; 1.152 + JSCList* list; 1.153 + 1.154 + MOZ_ASSERT(jsdthreadstate); 1.155 + MOZ_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread); 1.156 + 1.157 + JSD_LOCK_THREADSTATES(jsdc); 1.158 + JS_REMOVE_LINK(&jsdthreadstate->links); 1.159 + JSD_UNLOCK_THREADSTATES(jsdc); 1.160 + 1.161 + list = &jsdthreadstate->stack; 1.162 + while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) ) 1.163 + { 1.164 + JS_REMOVE_LINK(&jsdframe->links); 1.165 + _destroyFrame(jsdframe); 1.166 + } 1.167 + free(jsdthreadstate); 1.168 +} 1.169 + 1.170 +unsigned 1.171 +jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.172 +{ 1.173 + unsigned count = 0; 1.174 + 1.175 + JSD_LOCK_THREADSTATES(jsdc); 1.176 + 1.177 + if( jsd_IsValidThreadState(jsdc, jsdthreadstate) ) 1.178 + count = jsdthreadstate->stackDepth; 1.179 + 1.180 + JSD_UNLOCK_THREADSTATES(jsdc); 1.181 + 1.182 + return count; 1.183 +} 1.184 + 1.185 +JSDStackFrameInfo* 1.186 +jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.187 +{ 1.188 + JSDStackFrameInfo* jsdframe = nullptr; 1.189 + 1.190 + JSD_LOCK_THREADSTATES(jsdc); 1.191 + 1.192 + if( jsd_IsValidThreadState(jsdc, jsdthreadstate) ) 1.193 + jsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdthreadstate->stack); 1.194 + JSD_UNLOCK_THREADSTATES(jsdc); 1.195 + 1.196 + return jsdframe; 1.197 +} 1.198 + 1.199 +JSContext * 1.200 +jsd_GetJSContext (JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.201 +{ 1.202 + JSContext* cx = nullptr; 1.203 + 1.204 + JSD_LOCK_THREADSTATES(jsdc); 1.205 + if( jsd_IsValidThreadState(jsdc, jsdthreadstate) ) 1.206 + cx = jsdthreadstate->context; 1.207 + JSD_UNLOCK_THREADSTATES(jsdc); 1.208 + 1.209 + return cx; 1.210 +} 1.211 + 1.212 +JSDStackFrameInfo* 1.213 +jsd_GetCallingStackFrame(JSDContext* jsdc, 1.214 + JSDThreadState* jsdthreadstate, 1.215 + JSDStackFrameInfo* jsdframe) 1.216 +{ 1.217 + JSDStackFrameInfo* nextjsdframe = nullptr; 1.218 + 1.219 + JSD_LOCK_THREADSTATES(jsdc); 1.220 + 1.221 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.222 + if( JS_LIST_HEAD(&jsdframe->links) != &jsdframe->jsdthreadstate->stack ) 1.223 + nextjsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdframe->links); 1.224 + 1.225 + JSD_UNLOCK_THREADSTATES(jsdc); 1.226 + 1.227 + return nextjsdframe; 1.228 +} 1.229 + 1.230 +JSDScript* 1.231 +jsd_GetScriptForStackFrame(JSDContext* jsdc, 1.232 + JSDThreadState* jsdthreadstate, 1.233 + JSDStackFrameInfo* jsdframe) 1.234 +{ 1.235 + JSDScript* jsdscript = nullptr; 1.236 + 1.237 + JSD_LOCK_THREADSTATES(jsdc); 1.238 + 1.239 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.240 + jsdscript = jsdframe->jsdscript; 1.241 + 1.242 + JSD_UNLOCK_THREADSTATES(jsdc); 1.243 + 1.244 + return jsdscript; 1.245 +} 1.246 + 1.247 +uintptr_t 1.248 +jsd_GetPCForStackFrame(JSDContext* jsdc, 1.249 + JSDThreadState* jsdthreadstate, 1.250 + JSDStackFrameInfo* jsdframe) 1.251 +{ 1.252 + uintptr_t pc = 0; 1.253 + 1.254 + JSD_LOCK_THREADSTATES(jsdc); 1.255 + 1.256 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.257 + pc = jsdframe->pc; 1.258 + 1.259 + JSD_UNLOCK_THREADSTATES(jsdc); 1.260 + 1.261 + return pc; 1.262 +} 1.263 + 1.264 +JSDValue* 1.265 +jsd_GetCallObjectForStackFrame(JSDContext* jsdc, 1.266 + JSDThreadState* jsdthreadstate, 1.267 + JSDStackFrameInfo* jsdframe) 1.268 +{ 1.269 + JSObject* obj; 1.270 + JSDValue* jsdval = nullptr; 1.271 + 1.272 + JSD_LOCK_THREADSTATES(jsdc); 1.273 + 1.274 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.275 + { 1.276 + obj = jsdframe->frame.callObject(jsdthreadstate->context); 1.277 + if(obj) 1.278 + jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj)); 1.279 + } 1.280 + 1.281 + JSD_UNLOCK_THREADSTATES(jsdc); 1.282 + 1.283 + return jsdval; 1.284 +} 1.285 + 1.286 +JSDValue* 1.287 +jsd_GetScopeChainForStackFrame(JSDContext* jsdc, 1.288 + JSDThreadState* jsdthreadstate, 1.289 + JSDStackFrameInfo* jsdframe) 1.290 +{ 1.291 + JS::RootedObject obj(jsdthreadstate->context); 1.292 + JSDValue* jsdval = nullptr; 1.293 + 1.294 + JSD_LOCK_THREADSTATES(jsdc); 1.295 + 1.296 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.297 + { 1.298 + JS_BeginRequest(jsdthreadstate->context); 1.299 + obj = jsdframe->frame.scopeChain(jsdthreadstate->context); 1.300 + JS_EndRequest(jsdthreadstate->context); 1.301 + if(obj) 1.302 + jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj)); 1.303 + } 1.304 + 1.305 + JSD_UNLOCK_THREADSTATES(jsdc); 1.306 + 1.307 + return jsdval; 1.308 +} 1.309 + 1.310 +JSDValue* 1.311 +jsd_GetThisForStackFrame(JSDContext* jsdc, 1.312 + JSDThreadState* jsdthreadstate, 1.313 + JSDStackFrameInfo* jsdframe) 1.314 +{ 1.315 + JSDValue* jsdval = nullptr; 1.316 + JSD_LOCK_THREADSTATES(jsdc); 1.317 + 1.318 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.319 + { 1.320 + bool ok; 1.321 + JS::RootedValue thisval(jsdthreadstate->context); 1.322 + JS_BeginRequest(jsdthreadstate->context); 1.323 + ok = jsdframe->frame.getThisValue(jsdthreadstate->context, &thisval); 1.324 + JS_EndRequest(jsdthreadstate->context); 1.325 + if(ok) 1.326 + jsdval = JSD_NewValue(jsdc, thisval); 1.327 + } 1.328 + 1.329 + JSD_UNLOCK_THREADSTATES(jsdc); 1.330 + return jsdval; 1.331 +} 1.332 + 1.333 +JSString* 1.334 +jsd_GetIdForStackFrame(JSDContext* jsdc, 1.335 + JSDThreadState* jsdthreadstate, 1.336 + JSDStackFrameInfo* jsdframe) 1.337 +{ 1.338 + JSString *rv = nullptr; 1.339 + 1.340 + JSD_LOCK_THREADSTATES(jsdc); 1.341 + 1.342 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.343 + { 1.344 + JSFunction *fun = jsdframe->frame.maybeFun(); 1.345 + if( fun ) 1.346 + { 1.347 + rv = JS_GetFunctionId (fun); 1.348 + 1.349 + /* 1.350 + * For compatibility we return "anonymous", not an empty string 1.351 + * here. 1.352 + */ 1.353 + if( !rv ) 1.354 + rv = JS_GetAnonymousString(jsdc->jsrt); 1.355 + } 1.356 + } 1.357 + 1.358 + JSD_UNLOCK_THREADSTATES(jsdc); 1.359 + return rv; 1.360 +} 1.361 + 1.362 +bool 1.363 +jsd_IsStackFrameDebugger(JSDContext* jsdc, 1.364 + JSDThreadState* jsdthreadstate, 1.365 + JSDStackFrameInfo* jsdframe) 1.366 +{ 1.367 + bool rv = true; 1.368 + JSD_LOCK_THREADSTATES(jsdc); 1.369 + 1.370 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.371 + { 1.372 + rv = jsdframe->frame.isDebuggerFrame(); 1.373 + } 1.374 + 1.375 + JSD_UNLOCK_THREADSTATES(jsdc); 1.376 + return rv; 1.377 +} 1.378 + 1.379 +bool 1.380 +jsd_IsStackFrameConstructing(JSDContext* jsdc, 1.381 + JSDThreadState* jsdthreadstate, 1.382 + JSDStackFrameInfo* jsdframe) 1.383 +{ 1.384 + bool rv = true; 1.385 + JSD_LOCK_THREADSTATES(jsdc); 1.386 + 1.387 + if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) ) 1.388 + { 1.389 + rv = jsdframe->isConstructing; 1.390 + } 1.391 + 1.392 + JSD_UNLOCK_THREADSTATES(jsdc); 1.393 + return rv; 1.394 +} 1.395 + 1.396 +bool 1.397 +jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc, 1.398 + JSDThreadState* jsdthreadstate, 1.399 + JSDStackFrameInfo* jsdframe, 1.400 + const jschar *bytes, unsigned length, 1.401 + const char *filename, unsigned lineno, 1.402 + bool eatExceptions, JS::MutableHandleValue rval) 1.403 +{ 1.404 + bool retval; 1.405 + bool valid; 1.406 + JSExceptionState* exceptionState = nullptr; 1.407 + 1.408 + MOZ_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread); 1.409 + 1.410 + JSD_LOCK_THREADSTATES(jsdc); 1.411 + valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe); 1.412 + JSD_UNLOCK_THREADSTATES(jsdc); 1.413 + 1.414 + if( ! valid ) 1.415 + return false; 1.416 + 1.417 + AutoPushJSContext cx(jsdthreadstate->context); 1.418 + MOZ_ASSERT(cx); 1.419 + 1.420 + if (eatExceptions) 1.421 + exceptionState = JS_SaveExceptionState(cx); 1.422 + JS_ClearPendingException(cx); 1.423 + jsd_StartingEvalUsingFilename(jsdc, filename); 1.424 + retval = jsdframe->frame.evaluateUCInStackFrame(cx, bytes, length, filename, lineno, 1.425 + rval); 1.426 + jsd_FinishedEvalUsingFilename(jsdc, filename); 1.427 + if (eatExceptions) 1.428 + JS_RestoreExceptionState(cx, exceptionState); 1.429 + 1.430 + return retval; 1.431 +} 1.432 + 1.433 +bool 1.434 +jsd_EvaluateScriptInStackFrame(JSDContext* jsdc, 1.435 + JSDThreadState* jsdthreadstate, 1.436 + JSDStackFrameInfo* jsdframe, 1.437 + const char *bytes, unsigned length, 1.438 + const char *filename, unsigned lineno, 1.439 + bool eatExceptions, JS::MutableHandleValue rval) 1.440 +{ 1.441 + bool retval; 1.442 + bool valid; 1.443 + JSExceptionState* exceptionState = nullptr; 1.444 + 1.445 + MOZ_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread); 1.446 + 1.447 + JSD_LOCK_THREADSTATES(jsdc); 1.448 + valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe); 1.449 + JSD_UNLOCK_THREADSTATES(jsdc); 1.450 + 1.451 + if (!valid) 1.452 + return false; 1.453 + 1.454 + AutoPushJSContext cx(jsdthreadstate->context); 1.455 + MOZ_ASSERT(cx); 1.456 + 1.457 + if (eatExceptions) 1.458 + exceptionState = JS_SaveExceptionState(cx); 1.459 + JS_ClearPendingException(cx); 1.460 + jsd_StartingEvalUsingFilename(jsdc, filename); 1.461 + retval = jsdframe->frame.evaluateInStackFrame(cx, bytes, length, filename, lineno, 1.462 + rval); 1.463 + jsd_FinishedEvalUsingFilename(jsdc, filename); 1.464 + if (eatExceptions) 1.465 + JS_RestoreExceptionState(cx, exceptionState); 1.466 + 1.467 + return retval; 1.468 +} 1.469 + 1.470 +JSString* 1.471 +jsd_ValToStringInStackFrame(JSDContext* jsdc, 1.472 + JSDThreadState* jsdthreadstate, 1.473 + JSDStackFrameInfo* jsdframe, 1.474 + jsval val) 1.475 +{ 1.476 + bool valid; 1.477 + JSExceptionState* exceptionState; 1.478 + JSContext *cx = jsdthreadstate->context; 1.479 + 1.480 + JSD_LOCK_THREADSTATES(jsdc); 1.481 + valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe); 1.482 + JSD_UNLOCK_THREADSTATES(jsdc); 1.483 + 1.484 + if( ! valid ) 1.485 + return nullptr; 1.486 + 1.487 + JS::RootedString retval(cx); 1.488 + MOZ_ASSERT(cx); 1.489 + JS::RootedValue v(cx, val); 1.490 + { 1.491 + AutoPushJSContext cx(jsdthreadstate->context); 1.492 + exceptionState = JS_SaveExceptionState(cx); 1.493 + retval = JS::ToString(cx, v); 1.494 + JS_RestoreExceptionState(cx, exceptionState); 1.495 + } 1.496 + 1.497 + return retval; 1.498 +} 1.499 + 1.500 +bool 1.501 +jsd_IsValidThreadState(JSDContext* jsdc, 1.502 + JSDThreadState* jsdthreadstate) 1.503 +{ 1.504 + JSDThreadState *cur; 1.505 + 1.506 + MOZ_ASSERT( JSD_THREADSTATES_LOCKED(jsdc) ); 1.507 + 1.508 + for( cur = (JSDThreadState*)jsdc->threadsStates.next; 1.509 + cur != (JSDThreadState*)&jsdc->threadsStates; 1.510 + cur = (JSDThreadState*)cur->links.next ) 1.511 + { 1.512 + if( cur == jsdthreadstate ) 1.513 + return true; 1.514 + } 1.515 + return false; 1.516 +} 1.517 + 1.518 +bool 1.519 +jsd_IsValidFrameInThreadState(JSDContext* jsdc, 1.520 + JSDThreadState* jsdthreadstate, 1.521 + JSDStackFrameInfo* jsdframe) 1.522 +{ 1.523 + MOZ_ASSERT(JSD_THREADSTATES_LOCKED(jsdc)); 1.524 + 1.525 + if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) ) 1.526 + return false; 1.527 + if( jsdframe->jsdthreadstate != jsdthreadstate ) 1.528 + return false; 1.529 + 1.530 + JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate); 1.531 + JSD_ASSERT_VALID_STACK_FRAME(jsdframe); 1.532 + 1.533 + return true; 1.534 +} 1.535 + 1.536 +static JSContext* 1.537 +_getContextForThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.538 +{ 1.539 + bool valid; 1.540 + JSD_LOCK_THREADSTATES(jsdc); 1.541 + valid = jsd_IsValidThreadState(jsdc, jsdthreadstate); 1.542 + JSD_UNLOCK_THREADSTATES(jsdc); 1.543 + if( valid ) 1.544 + return jsdthreadstate->context; 1.545 + return nullptr; 1.546 +} 1.547 + 1.548 +JSDValue* 1.549 +jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate) 1.550 +{ 1.551 + JSContext* cx; 1.552 + if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate))) 1.553 + return nullptr; 1.554 + 1.555 + JS::RootedValue val(cx); 1.556 + if(JS_GetPendingException(cx, &val)) 1.557 + return jsd_NewValue(jsdc, val); 1.558 + return nullptr; 1.559 +} 1.560 + 1.561 +bool 1.562 +jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate, 1.563 + JSDValue* jsdval) 1.564 +{ 1.565 + JSContext* cx; 1.566 + 1.567 + if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate))) 1.568 + return false; 1.569 + 1.570 + if(jsdval) { 1.571 + JS::RootedValue exn(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval)); 1.572 + JS_SetPendingException(cx, exn); 1.573 + } else { 1.574 + JS_ClearPendingException(cx); 1.575 + } 1.576 + return true; 1.577 +} 1.578 +