JSBool jsd_SetErrorReporter(JSDContext* jsdc, JSD_ErrorReporter reporter, void* callerdata) { JSD_LOCK(); jsdc->errorReporter = reporter; jsdc->errorReporterData = callerdata; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata) { JSD_LOCK(); if( hook ) *hook = jsdc->scriptHook; if( callerdata ) *callerdata = jsdc->scriptHookData; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable) { JSCompartment* oldCompartment; JSBool rv; oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script); JSD_LOCK(); rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable); JSD_UNLOCK(); JS_LeaveCompartment(jsdc->dumbContext, oldCompartment); return rv; }
JSBool jsd_ClearAllExecutionHooks(JSDContext* jsdc) { JSDScript* jsdscript; JSDScript* iterp = NULL; JSD_LOCK(); while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) ) jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript); JSD_UNLOCK(); return JS_TRUE; }
bool jsd_SetDebuggerHook(JSDContext* jsdc, JSD_ExecutionHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->debuggerHookData = callerdata; jsdc->debuggerHook = hook; JSD_UNLOCK(); return true; }
JSBool jsd_SetThrowHook(JSDContext* jsdc, JSD_ExecutionHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->throwHookData = callerdata; jsdc->throwHook = hook; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_SetFunctionHook(JSDContext* jsdc, JSD_CallHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->functionHookData = callerdata; jsdc->functionHook = hook; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_SetTopLevelHook(JSDContext* jsdc, JSD_CallHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->toplevelHookData = callerdata; jsdc->toplevelHook = hook; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_GetErrorReporter(JSDContext* jsdc, JSD_ErrorReporter* reporter, void** callerdata) { JSD_LOCK(); if( reporter ) *reporter = jsdc->errorReporter; if( callerdata ) *callerdata = jsdc->errorReporterData; JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_SetInterruptHook(JSDContext* jsdc, JSD_ExecutionHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->interruptHookData = callerdata; jsdc->interruptHook = hook; JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc); JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable) { JSCrossCompartmentCall *call; JSBool rv; call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) return JS_FALSE; JSD_LOCK(); rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable); JSD_UNLOCK(); JS_LeaveCrossCompartmentCall(call); return rv; }
void jsd_DestroyScriptHookProc( JSFreeOp *fop, JSScript *script_, void* callerdata ) { JSDScript* jsdscript = NULL; JSDContext* jsdc = (JSDContext*) callerdata; JS::RootedScript script(jsdc->dumbContext, script_); JSD_ScriptHookProc hook; void* hookData; JSD_ASSERT_VALID_CONTEXT(jsdc); if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); if( ! jsdscript ) return; #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: "); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ /* local in case hook gets cleared on another thread */ JSD_LOCK(); hook = (jsdscript->flags & JSD_SCRIPT_CALL_DESTROY_HOOK_BIT) ? jsdc->scriptHook : NULL; hookData = jsdc->scriptHookData; JSD_UNLOCK(); if( hook ) hook(jsdc, jsdscript, JS_FALSE, hookData); JSD_LOCK_SCRIPTS(jsdc); JS_HashTableRemove(jsdc->scriptsTable, (void *)script); JSD_UNLOCK_SCRIPTS(jsdc); #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScriptList(jsdc); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ }
void JS_DLL_CALLBACK jsd_NewScriptHookProc( JSContext *cx, const char *filename, /* URL this script loads from */ uintN lineno, /* line where this script starts */ JSScript *script, JSFunction *fun, void* callerdata ) { JSDScript* jsdscript = NULL; JSDContext* jsdc = (JSDContext*) callerdata; JSD_ScriptHookProc hook; void* hookData; JSD_ASSERT_VALID_CONTEXT(jsdc); if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; #ifdef LIVEWIRE if( 1 == lineno ) jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE ); #endif JSD_LOCK_SCRIPTS(jsdc); jsdscript = _newJSDScript(jsdc, cx, script, fun); JSD_UNLOCK_SCRIPTS(jsdc); if( ! jsdscript ) return; #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScript(jsdc, jsdscript, "***NEW Script: "); _dumpJSDScriptList( jsdc ); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ /* local in case jsdc->scriptHook gets cleared on another thread */ JSD_LOCK(); hook = jsdc->scriptHook; hookData = jsdc->scriptHookData; JSD_UNLOCK(); if( hook ) hook(jsdc, jsdscript, JS_TRUE, hookData); }
void jsd_NewScriptHookProc( JSContext *cx, const char *filename, /* URL this script loads from */ unsigned lineno, /* line where this script starts */ JSScript *script, JSFunction *fun, void* callerdata ) { JSDScript* jsdscript = NULL; JSDContext* jsdc = (JSDContext*) callerdata; JSD_ScriptHookProc hook; void* hookData; JSD_ASSERT_VALID_CONTEXT(jsdc); if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; JSD_LOCK_SCRIPTS(jsdc); jsdscript = _newJSDScript(jsdc, cx, script); JSD_UNLOCK_SCRIPTS(jsdc); if( ! jsdscript ) return; #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScript(jsdc, jsdscript, "***NEW Script: "); _dumpJSDScriptList( jsdc ); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ /* local in case jsdc->scriptHook gets cleared on another thread */ JSD_LOCK(); hook = jsdc->scriptHook; if( hook ) jsdscript->flags = jsdscript->flags | JSD_SCRIPT_CALL_DESTROY_HOOK_BIT; hookData = jsdc->scriptHookData; JSD_UNLOCK(); if( hook ) hook(jsdc, jsdscript, JS_TRUE, hookData); }
JSBool jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript) { JSDExecHook* jsdhook; JSCList* list = &jsdscript->hooks; JSD_LOCK(); while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) ) { JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); } JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script); JSD_UNLOCK(); return JS_TRUE; }
JSDContext* jsd_JSDContextForJSContext(JSContext* context) { JSDContext* iter; JSDContext* jsdc = NULL; JSD_LOCK(); for( iter = (JSDContext*)_jsd_context_list.next; iter != (JSDContext*)&_jsd_context_list; iter = (JSDContext*)iter->links.next ) { if( PR_HashTableLookup(iter->jscontexts, context) ) { jsdc = iter; break; } } JSD_UNLOCK(); return jsdc; }
JSBool jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript) { JSDExecHook* jsdhook; JSCList* list = &jsdscript->hooks; JSD_LOCK(); while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) ) { JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); } /* No cross-compartment call here because we may be in the middle of GC */ JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script); JSD_UNLOCK(); return JS_TRUE; }
JSDContext* jsd_JSDContextForJSContext(JSContext* context) { JSDContext* iter; JSDContext* jsdc = NULL; JSRuntime* runtime = JS_GetRuntime(context); JSD_LOCK(); for( iter = (JSDContext*)_jsd_context_list.next; iter != (JSDContext*)&_jsd_context_list; iter = (JSDContext*)iter->links.next ) { if( runtime == iter->jsrt ) { jsdc = iter; break; } } JSD_UNLOCK(); return jsdc; }
void jsd_JSContextUsed(JSDContext* jsdc, JSContext* context) { JSDContextWrapper* wrapper; PRHashEntry* he; wrapper = _jsd_JSDContextWrapperForJSContext(jsdc, context); if( wrapper ) { /* error reporters are sometimes overwritten by other code... */ JSErrorReporter oldrep = JS_SetErrorReporter(context, jsd_ErrorReporter); if( jsd_ErrorReporter != oldrep ) wrapper->originalErrorReporter = oldrep; return; } /* else... */ wrapper = (JSDContextWrapper*) calloc(1,sizeof(JSDContextWrapper)); if( ! wrapper ) return; JSD_LOCK(); he = PR_HashTableAdd(jsdc->jscontexts, context, wrapper); JSD_UNLOCK(); if( ! he ) { free(wrapper); return; } wrapper->context = context; wrapper->jsdc = jsdc; /* add our error reporter */ wrapper->originalErrorReporter = JS_SetErrorReporter(context, jsd_ErrorReporter); /* add our printer */ /* add our loader */ }
JSTrapStatus jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure) { JSDScript* jsdscript; JSDContext* jsdc = (JSDContext*) closure; JSD_ExecutionHookProc hook; void* hookData; if( ! jsdc || ! jsdc->inited ) return JSTRAP_CONTINUE; if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return JSTRAP_CONTINUE; /* local in case jsdc->interruptHook gets cleared on another thread */ JSD_LOCK(); hook = jsdc->interruptHook; hookData = jsdc->interruptHookData; JSD_UNLOCK(); if (!hook) return JSTRAP_CONTINUE; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr()); JSD_UNLOCK_SCRIPTS(jsdc); if( ! jsdscript ) return JSTRAP_CONTINUE; #ifdef LIVEWIRE if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) ) return JSTRAP_CONTINUE; #endif return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED, hook, hookData, rval); }
static void _destroyJSDContext(JSDContext* jsdc) { JSD_ASSERT_VALID_CONTEXT(jsdc); JSD_LOCK(); JS_REMOVE_LINK(&jsdc->links); JSD_UNLOCK(); jsd_DestroyObjectManager(jsdc); jsd_DestroyAtomTable(jsdc); jsdc->inited = JS_FALSE; /* * We should free jsdc here, but we let it leak in case there are any * asynchronous hooks calling into the system using it as a handle * * XXX we also leak the locks */ JS_DestroyContext(jsdc->dumbContext); jsdc->dumbContext = NULL; }
static JSDContext* _newJSDContext(JSTaskState* jstaskstate, JSD_UserCallbacks* callbacks, void* user) { JSDContext* jsdc = NULL; if( ! jstaskstate ) return NULL; if( ! _validateUserCallbacks(callbacks) ) return NULL; jsdc = (JSDContext*) calloc(1, sizeof(JSDContext)); if( ! jsdc ) goto label_newJSDContext_failure; if( ! JSD_INIT_LOCKS(jsdc) ) goto label_newJSDContext_failure; PR_INIT_CLIST(&jsdc->links); jsdc->jstaskstate = jstaskstate; if( callbacks ) memcpy(&jsdc->userCallbacks, callbacks, callbacks->size); jsdc->user = user; #ifdef JSD_HAS_DANGEROUS_THREAD jsdc->dangerousThread = _dangerousThread; #endif PR_INIT_CLIST(&jsdc->threadsStates); PR_INIT_CLIST(&jsdc->scripts); PR_INIT_CLIST(&jsdc->sources); PR_INIT_CLIST(&jsdc->removedSources); jsdc->sourceAlterCount = 1; jsdc->jscontexts = PR_NewHashTable(256, _hash_root, PR_CompareValues, PR_CompareValues, NULL, NULL); if( ! jsdc->jscontexts ) goto label_newJSDContext_failure; jsdc->dumbContext = JS_NewContext(jsdc->jstaskstate, 256); if( ! jsdc->dumbContext ) goto label_newJSDContext_failure; jsdc->glob = JS_NewObject(jsdc->dumbContext, &global_class, NULL, NULL); if( ! jsdc->glob ) goto label_newJSDContext_failure; if( ! JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob) ) goto label_newJSDContext_failure; jsdc->inited = JS_TRUE; JSD_LOCK(); PR_INSERT_LINK(&jsdc->links, &_jsd_context_list); JSD_UNLOCK(); return jsdc; label_newJSDContext_failure: if( jsdc ) free(jsdc); return NULL; }
static JSDContext* _newJSDContext(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user, JSObject* scopeobj) { JSDContext* jsdc = NULL; JSCrossCompartmentCall *call = NULL; JSBool ok; if( ! jsrt ) return NULL; if( ! _validateUserCallbacks(callbacks) ) return NULL; jsdc = (JSDContext*) calloc(1, sizeof(JSDContext)); if( ! jsdc ) goto label_newJSDContext_failure; if( ! JSD_INIT_LOCKS(jsdc) ) goto label_newJSDContext_failure; JS_INIT_CLIST(&jsdc->links); jsdc->jsrt = jsrt; if( callbacks ) memcpy(&jsdc->userCallbacks, callbacks, callbacks->size); jsdc->user = user; #ifdef JSD_HAS_DANGEROUS_THREAD jsdc->dangerousThread = _dangerousThread; #endif JS_INIT_CLIST(&jsdc->threadsStates); JS_INIT_CLIST(&jsdc->sources); JS_INIT_CLIST(&jsdc->removedSources); jsdc->sourceAlterCount = 1; if( ! jsd_CreateAtomTable(jsdc) ) goto label_newJSDContext_failure; if( ! jsd_InitObjectManager(jsdc) ) goto label_newJSDContext_failure; if( ! jsd_InitScriptManager(jsdc) ) goto label_newJSDContext_failure; jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256); if( ! jsdc->dumbContext ) goto label_newJSDContext_failure; JS_BeginRequest(jsdc->dumbContext); JS_SetOptions(jsdc->dumbContext, JS_GetOptions(jsdc->dumbContext) | JSOPTION_ALLOW_XML); jsdc->glob = JS_NewCompartmentAndGlobalObject(jsdc->dumbContext, &global_class, NULL); if( ! jsdc->glob ) goto label_newJSDContext_failure; call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob); if( ! call ) goto label_newJSDContext_failure; if ( ! JS_AddNamedObjectRoot(jsdc->dumbContext, &jsdc->glob, "JSD context global") ) goto label_newJSDContext_failure; ok = JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob); JS_LeaveCrossCompartmentCall(call); if( ! ok ) goto label_newJSDContext_failure; JS_EndRequest(jsdc->dumbContext); jsdc->data = NULL; jsdc->inited = JS_TRUE; JSD_LOCK(); JS_INSERT_LINK(&jsdc->links, &_jsd_context_list); JSD_UNLOCK(); return jsdc; label_newJSDContext_failure: if( jsdc ) { if ( jsdc->dumbContext && jsdc->glob ) JS_RemoveObjectRootRT(JS_GetRuntime(jsdc->dumbContext), &jsdc->glob); jsd_DestroyObjectManager(jsdc); jsd_DestroyAtomTable(jsdc); if( jsdc->dumbContext ) JS_EndRequest(jsdc->dumbContext); free(jsdc); } return NULL; }
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; } }
JSBool jsd_SetExecutionHook(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc, JSD_ExecutionHookProc hook, void* callerdata) { JSDExecHook* jsdhook; JSBool rv; JSCrossCompartmentCall *call; JSD_LOCK(); if( ! hook ) { jsd_ClearExecutionHook(jsdc, jsdscript, pc); JSD_UNLOCK(); return JS_TRUE; } jsdhook = _findHook(jsdc, jsdscript, pc); if( jsdhook ) { jsdhook->hook = hook; jsdhook->callerdata = callerdata; JSD_UNLOCK(); return JS_TRUE; } /* else... */ jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook)); if( ! jsdhook ) { JSD_UNLOCK(); return JS_FALSE; } jsdhook->jsdscript = jsdscript; jsdhook->pc = pc; jsdhook->hook = hook; jsdhook->callerdata = callerdata; call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) { free(jsdhook); JSD_UNLOCK(); return JS_FALSE; } rv = JS_SetTrap(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc, jsd_TrapHandler, PRIVATE_TO_JSVAL(jsdhook)); JS_LeaveCrossCompartmentCall(call); if ( ! rv ) { free(jsdhook); JSD_UNLOCK(); return JS_FALSE; } JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks); JSD_UNLOCK(); return JS_TRUE; }