JSTrapStatus jsd_CallExecutionHook(JSDContext* jsdc, JSContext *cx, unsigned type, JSD_ExecutionHookProc hook, void* hookData, jsval* rval) { unsigned hookanswer = JSD_HOOK_THROW == type ? JSD_HOOK_RETURN_CONTINUE_THROW : JSD_HOOK_RETURN_CONTINUE; JSDThreadState* jsdthreadstate; if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx))) { if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) || jsdc->flags & JSD_MASK_TOP_FRAME_ONLY || !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME)) { /* * if it's not a throw and it's not an interrupt, * or we're only masking the top frame, * or there are no disabled frames in this stack, * then call out. */ hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval); jsd_DestroyThreadState(jsdc, jsdthreadstate); } } switch(hookanswer) { case JSD_HOOK_RETURN_ABORT: case JSD_HOOK_RETURN_HOOK_ERROR: return JSTRAP_ERROR; case JSD_HOOK_RETURN_RET_WITH_VAL: return JSTRAP_RETURN; case JSD_HOOK_RETURN_THROW_WITH_VAL: return JSTRAP_THROW; case JSD_HOOK_RETURN_CONTINUE: break; case JSD_HOOK_RETURN_CONTINUE_THROW: /* only makes sense for jsd_ThrowHandler (which init'd rval) */ JS_ASSERT(JSD_HOOK_THROW == type); return JSTRAP_THROW; default: JS_ASSERT(0); break; } return JSTRAP_CONTINUE; }
JSBool jsd_CallCallHook (JSDContext* jsdc, JSContext *cx, unsigned type, JSD_CallHookProc hook, void* hookData) { JSBool hookanswer; JSDThreadState* jsdthreadstate; hookanswer = JS_FALSE; if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc, cx))) { hookanswer = hook(jsdc, jsdthreadstate, type, hookData); jsd_DestroyThreadState(jsdc, jsdthreadstate); } return hookanswer; }
JSDThreadState* jsd_NewThreadState(JSDContext* jsdc, JSContext *cx ) { JSDThreadState* jsdthreadstate; JSStackFrame * iter = NULL; JSStackFrame * fp; jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState)); if( ! jsdthreadstate ) return NULL; jsdthreadstate->context = cx; jsdthreadstate->thread = JSD_CURRENT_THREAD(); JS_INIT_CLIST(&jsdthreadstate->stack); jsdthreadstate->stackDepth = 0; JS_BeginRequest(jsdthreadstate->context); while( NULL != (fp = JS_FrameIterator(cx, &iter)) ) { JSScript* script = JS_GetFrameScript(cx, fp); jsuword pc = (jsuword) JS_GetFramePC(cx, fp); /* * don't construct a JSDStackFrame for dummy frames (those without a * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES * isn't set. */ if (JS_GetFrameThis(cx, fp) && ((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) || !JS_IsNativeFrame(cx, fp))) { JSDStackFrameInfo *frame; frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp ); if ((jsdthreadstate->stackDepth == 0 && !frame) || (jsdthreadstate->stackDepth == 1 && frame && frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript))) { /* * if we failed to create the first frame, or the top frame * is not enabled for debugging, fail the entire thread state. */ JS_INIT_CLIST(&jsdthreadstate->links); JS_EndRequest(jsdthreadstate->context); jsd_DestroyThreadState(jsdc, jsdthreadstate); return NULL; } } } JS_EndRequest(jsdthreadstate->context); if (jsdthreadstate->stackDepth == 0) { free(jsdthreadstate); return NULL; } JSD_LOCK_THREADSTATES(jsdc); JS_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates); JSD_UNLOCK_THREADSTATES(jsdc); return jsdthreadstate; }
jsd_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) { JSDContextWrapper* wrapper; JSDContext* jsdc; uintN action = JSD_ERROR_REPORTER_PASS_ALONG; JSD_ErrorReporter errorReporter; void* errorReporterData; jsdc = jsd_JSDContextForJSContext(cx); if( ! jsdc ) { PR_ASSERT(0); return; } wrapper = _jsd_JSDContextWrapperForJSContext(jsdc, cx); if( ! wrapper ) { PR_ASSERT(0); return; } /* local in case hook gets cleared on another thread */ JSD_LOCK(); errorReporter = jsdc->errorReporter; errorReporterData = jsdc->errorReporterData; JSD_UNLOCK(); if( errorReporter && ! JSD_IS_DANGEROUS_THREAD(jsdc) ) action = errorReporter(jsdc, cx, message, report, errorReporterData); switch(action) { case JSD_ERROR_REPORTER_PASS_ALONG: if( wrapper->originalErrorReporter ) wrapper->originalErrorReporter(cx, message, report); break; case JSD_ERROR_REPORTER_RETURN: break; case JSD_ERROR_REPORTER_DEBUG: { JSDThreadState* jsdthreadstate; jsdthreadstate = jsd_NewThreadState(jsdc,cx); if( jsdthreadstate ) { JSD_ExecutionHookProc hook; void* hookData; /* local in case hook gets cleared on another thread */ JSD_LOCK(); hook = jsdc->debugBreakHook; hookData = jsdc->debugBreakHookData; JSD_UNLOCK(); if(hook) hook(jsdc, jsdthreadstate, JSD_HOOK_DEBUG_REQUESTED, hookData); jsd_DestroyThreadState(jsdc, jsdthreadstate); } break; } default: PR_ASSERT(0); break; } }