CHAKRA_API JsDiagSetBreakpoint( _In_ unsigned int scriptId, _In_ unsigned int lineNumber, _In_ unsigned int columnNumber, _Out_ JsValueRef *breakpoint) { #ifndef ENABLE_SCRIPT_DEBUGGING return JsErrorCategoryUsage; #else return ContextAPIWrapper_NoRecord<false>([&](Js::ScriptContext* scriptContext) -> JsErrorCode { PARAM_NOT_NULL(breakpoint); *breakpoint = JS_INVALID_REFERENCE; JsrtContext* currentContext = JsrtContext::GetCurrent(); JsrtRuntime* runtime = currentContext->GetRuntime(); ThreadContextScope scope(runtime->GetThreadContext()); if (!scope.IsValid()) { return JsErrorWrongThread; } VALIDATE_IS_DEBUGGING(runtime->GetJsrtDebugManager()); Js::Utf8SourceInfo* utf8SourceInfo = nullptr; for (Js::ScriptContext* currentScriptContext = runtime->GetThreadContext()->GetScriptContextList(); currentScriptContext != nullptr && utf8SourceInfo == nullptr && !currentScriptContext->IsClosed(); currentScriptContext = currentScriptContext->next) { currentScriptContext->MapScript([&](Js::Utf8SourceInfo* sourceInfo) -> bool { if (sourceInfo->GetSourceInfoId() == scriptId) { utf8SourceInfo = sourceInfo; return true; } return false; }); } if (utf8SourceInfo != nullptr && utf8SourceInfo->HasDebugDocument()) { JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager(); Js::DynamicObject* bpObject = jsrtDebugManager->SetBreakPoint(currentContext->GetScriptContext(), utf8SourceInfo, lineNumber, columnNumber); if(bpObject != nullptr) { *breakpoint = bpObject; return JsNoError; } return JsErrorDiagUnableToPerformAction; } return JsErrorDiagObjectNotFound; }); #endif }
CHAKRA_API JsDiagGetBreakpoints( _Out_ JsValueRef *breakpoints) { #ifndef ENABLE_SCRIPT_DEBUGGING return JsErrorCategoryUsage; #else return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode { PARAM_NOT_NULL(breakpoints); *breakpoints = JS_INVALID_REFERENCE; JsrtContext *currentContext = JsrtContext::GetCurrent(); Js::JavascriptArray* bpsArray = currentContext->GetScriptContext()->GetLibrary()->CreateArray(); JsrtRuntime * runtime = currentContext->GetRuntime(); ThreadContextScope scope(runtime->GetThreadContext()); if (!scope.IsValid()) { return JsErrorWrongThread; } JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager(); VALIDATE_IS_DEBUGGING(jsrtDebugManager); for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList(); scriptContext != nullptr && !scriptContext->IsClosed(); scriptContext = scriptContext->next) { jsrtDebugManager->GetBreakpoints(&bpsArray, scriptContext); } *breakpoints = bpsArray; return JsNoError; }); #endif }
/* static */ bool JsrtContext::TrySetCurrent(JsrtContext * context) { Assert(s_tlsSlot != TLS_OUT_OF_INDEXES); ThreadContext * threadContext; //We are not pinning the context after SetCurrentContext, so if the context is not pinned //it might be reclaimed half way during execution. In jsrtshell the runtime was optimized out //at time of JsrtContext::Run by the compiler. //The change is to pin the context at setconcurrentcontext, and unpin the previous one. In //JsDisposeRuntime we'll reject if current context is active, so that will make sure all //contexts are unpinned at time of JsDisposeRuntime. if (context != nullptr) { threadContext = context->GetScriptContext()->GetThreadContext(); if (!ThreadContextTLSEntry::TrySetThreadContext(threadContext)) { return false; } threadContext->GetRecycler()->RootAddRef((LPVOID)context); } else { if (!ThreadContextTLSEntry::ClearThreadContext(true)) { return false; } } JsrtContext* originalContext = (JsrtContext*) TlsGetValue(s_tlsSlot); if (originalContext != nullptr) { originalContext->GetScriptContext()->GetRecycler()->RootRelease((LPVOID) originalContext); } TlsSetValue(s_tlsSlot, context); return true; }