예제 #1
0
CHAKRA_API JsDiagStartDebugging(
    _In_ JsRuntimeHandle runtimeHandle,
    _In_ JsDiagDebugEventCallback debugEventCallback,
    _In_opt_ void* callbackState)
{
#ifndef ENABLE_SCRIPT_DEBUGGING
    return JsErrorCategoryUsage;
#else
    return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {

        VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);

        PARAM_NOT_NULL(debugEventCallback);

        JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
        ThreadContext * threadContext = runtime->GetThreadContext();

        VALIDATE_RUNTIME_STATE_FOR_START_STOP_DEBUGGING(threadContext);

        if (runtime->GetJsrtDebugManager() != nullptr && runtime->GetJsrtDebugManager()->IsDebugEventCallbackSet())
        {
            return JsErrorDiagAlreadyInDebugMode;
        }

        // Create the debug object to save callback function and data
        runtime->EnsureJsrtDebugManager();

        JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();

        jsrtDebugManager->SetDebugEventCallback(debugEventCallback, callbackState);

        if (threadContext->GetDebugManager() != nullptr)
        {
            threadContext->GetDebugManager()->SetLocalsDisplayFlags(Js::DebugManager::LocalsDisplayFlags::LocalsDisplayFlags_NoGroupMethods);
        }

        for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
        scriptContext != nullptr && !scriptContext->IsClosed();
            scriptContext = scriptContext->next)
        {
            Assert(!scriptContext->IsScriptContextInDebugMode());

            Js::DebugContext* debugContext = scriptContext->GetDebugContext();

            if (debugContext->GetHostDebugContext() == nullptr)
            {
                debugContext->SetHostDebugContext(jsrtDebugManager);
            }

            HRESULT hr;
            if (FAILED(hr = scriptContext->OnDebuggerAttached()))
            {
                Debugger_AttachDetach_unrecoverable_error(hr); // Inconsistent state, we can't continue from here
                return JsErrorFatal;
            }

            // ScriptContext might get closed in OnDebuggerAttached
            if (!scriptContext->IsClosed())
            {
                Js::ProbeContainer* probeContainer = debugContext->GetProbeContainer();
                probeContainer->InitializeInlineBreakEngine(jsrtDebugManager);
                probeContainer->InitializeDebuggerScriptOptionCallback(jsrtDebugManager);
            }
        }

        return JsNoError;
    });
#endif
}
예제 #2
0
CHAKRA_API JsDiagSetStepType(
    _In_ JsDiagStepType stepType)
{
#ifndef ENABLE_SCRIPT_DEBUGGING
    return JsErrorCategoryUsage;
#else
    return ContextAPIWrapper_NoRecord<true>([&](Js::ScriptContext * scriptContext) -> JsErrorCode {

        JsrtContext *currentContext = JsrtContext::GetCurrent();
        JsrtRuntime* runtime = currentContext->GetRuntime();

        VALIDATE_RUNTIME_IS_AT_BREAK(runtime);

        JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();

        VALIDATE_IS_DEBUGGING(jsrtDebugManager);

        if (stepType == JsDiagStepTypeStepIn)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_INTO);
        }
        else if (stepType == JsDiagStepTypeStepOut)
        {
           jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OUT);
        }
        else if (stepType == JsDiagStepTypeStepOver)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OVER);
        }
        else if (stepType == JsDiagStepTypeStepBack)
        {
#if ENABLE_TTD
            ThreadContext* threadContext = runtime->GetThreadContext();
            if(!threadContext->IsRuntimeInTTDMode())
            {
                //Don't want to fail hard when user accidentally clicks this so pring message and step forward
                fprintf(stderr, "Must be in replay mode to use reverse-step - launch with \"--replay-debug\" flag in Node.");
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OVER);
            }
            else
            {
                threadContext->TTDExecutionInfo->SetPendingTTDStepBackMove();

                //don't worry about BP suppression because we are just going to throw after we return
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
#else
            return JsErrorInvalidArgument;
#endif
        }
        else if (stepType == JsDiagStepTypeReverseContinue)
        {
#if ENABLE_TTD
            ThreadContext* threadContext = runtime->GetThreadContext();
            if(!threadContext->IsRuntimeInTTDMode())
            {
                //Don't want to fail hard when user accidentally clicks this so pring message and step forward
                fprintf(stderr, "Must be in replay mode to use reverse-continue - launch with \"--replay-debug\" flag in Node.");
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
            else
            {
                threadContext->TTDExecutionInfo->SetPendingTTDReverseContinueMove(JsTTDMoveMode::JsTTDMoveScanIntervalForContinue);

                //don't worry about BP suppression because we are just going to throw after we return
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
#else
            return JsErrorInvalidArgument;
#endif
        }
        else if (stepType == JsDiagStepTypeContinue)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
        }

        return JsNoError;
    });
#endif
}