Commit fab116be authored by jgruber's avatar jgruber Committed by Commit bot

[inspector] Add exception caught/uncaught status to protocol

This adds information about an exception's caught/uncaught status to the
Runtime.paused event in the data parameter:

{
    "method": "Debugger.paused",
    "params": {
        "callFrames": [
	    [...]
        ],
        "data": {
            "description": "666",
            "type": "number",
            "uncaught": true,  <---
            "value": 666
        },
        "hitBreakpoints": [],
        "reason": "exception"
    }
}

BUG=v8:5530

Review-Url: https://codereview.chromium.org/2488733003
Cr-Commit-Position: refs/heads/master@{#40875}
parent fa9e404b
......@@ -1078,7 +1078,8 @@ void V8DebuggerAgentImpl::didParseSource(
V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause(
v8::Local<v8::Context> context, v8::Local<v8::Value> exception,
const std::vector<String16>& hitBreakpoints, bool isPromiseRejection) {
const std::vector<String16>& hitBreakpoints, bool isPromiseRejection,
bool isUncaught) {
JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1);
JavaScriptCallFrame* topCallFrame =
!callFrames.empty() ? callFrames.begin()->get() : nullptr;
......@@ -1120,7 +1121,12 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause(
std::unique_ptr<protocol::Runtime::RemoteObject> obj;
injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false,
&obj);
m_breakAuxData = obj ? obj->serialize() : nullptr;
if (obj) {
m_breakAuxData = obj->serialize();
m_breakAuxData->setBoolean("uncaught", isUncaught);
} else {
m_breakAuxData = nullptr;
}
// m_breakAuxData might be null after this.
}
}
......
......@@ -137,7 +137,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
SkipPauseRequest didPause(v8::Local<v8::Context>,
v8::Local<v8::Value> exception,
const std::vector<String16>& hitBreakpoints,
bool isPromiseRejection);
bool isPromiseRejection, bool isUncaught);
void didContinue();
void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
void willExecuteScript(int scriptId);
......
......@@ -486,7 +486,7 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
v8::Local<v8::Object> executionState,
v8::Local<v8::Value> exception,
v8::Local<v8::Array> hitBreakpointNumbers,
bool isPromiseRejection) {
bool isPromiseRejection, bool isUncaught) {
// Don't allow nested breaks.
if (m_runningNestedMessageLoop) return;
......@@ -509,7 +509,7 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
m_pausedContext = pausedContext;
m_executionState = executionState;
V8DebuggerAgentImpl::SkipPauseRequest result = agent->didPause(
pausedContext, exception, breakpointIds, isPromiseRejection);
pausedContext, exception, breakpointIds, isPromiseRejection, isUncaught);
if (result == V8DebuggerAgentImpl::RequestNoSkip) {
m_runningNestedMessageLoop = true;
int groupId = getGroupId(pausedContext);
......@@ -595,14 +595,19 @@ void V8Debugger::handleV8DebugEvent(
wrapUnique(new V8DebuggerScript(m_isolate, script, inLiveEditScope)),
event == v8::AfterCompile);
} else if (event == v8::Exception) {
v8::Local<v8::Context> context = debuggerContext();
v8::Local<v8::Object> eventData = eventDetails.GetEventData();
v8::Local<v8::Value> exception =
callInternalGetterFunction(eventData, "exception");
v8::Local<v8::Value> promise =
callInternalGetterFunction(eventData, "promise");
bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject();
v8::Local<v8::Value> uncaught =
callInternalGetterFunction(eventData, "uncaught");
bool isUncaught = uncaught->BooleanValue(context).FromJust();
handleProgramBreak(eventContext, eventDetails.GetExecutionState(),
exception, v8::Local<v8::Array>(), isPromiseRejection);
exception, v8::Local<v8::Array>(), isPromiseRejection,
isUncaught);
} else if (event == v8::Break) {
v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()};
v8::Local<v8::Value> hitBreakpoints =
......
......@@ -107,7 +107,8 @@ class V8Debugger {
v8::Local<v8::Object> executionState,
v8::Local<v8::Value> exception,
v8::Local<v8::Array> hitBreakpoints,
bool isPromiseRejection = false);
bool isPromiseRejection = false,
bool isUncaught = false);
static void v8DebugEventCallback(const v8::DebugInterface::EventDetails&);
v8::Local<v8::Value> callInternalGetterFunction(v8::Local<v8::Object>,
const char* functionName);
......
Check that inspector correctly passes caught/uncaught information.
paused in throwCaught
uncaught: false
paused in throwUncaught
uncaught: true
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("Check that inspector correctly passes caught/uncaught information.");
InspectorTest.addScript(
`function throwCaught() { try { throw new Error(); } catch (_) {} }
function throwUncaught() { throw new Error(); }
function schedule(f) { setTimeout(f, 0); }
`);
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({ "state": "all" });
Protocol.Debugger.onPaused(message => {
InspectorTest.log("paused in " + message.params.callFrames[0].functionName);
InspectorTest.log("uncaught: " + message.params.data.uncaught);
Protocol.Debugger.resume();
});
Protocol.Runtime.evaluate({ "expression": "schedule(throwCaught);" })
.then(() => Protocol.Runtime.evaluate(
{ "expression": "schedule(throwUncaught);" }))
.then(() => InspectorTest.completeTest());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment