Commit bcad65bf authored by aandrey@chromium.org's avatar aandrey@chromium.org

Fix unhandled promise console message to show stack trace of a DOMException.

BUG=393913
R=pfeldman@chromium.org, yurys@chromium.org

Review URL: https://codereview.chromium.org/660543002

git-svn-id: svn://svn.chromium.org/blink/trunk@183985 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent d6071109
CONSOLE ERROR: line 30: Unhandled promise rejection
Tests unhandled promise that was rejected with a DOM exception.
Set timer for test function.
debugger-uncaught-promise-on-dom-exception.html:10 Console was cleared
debugger-uncaught-promise-on-dom-exception.html:30 Unhandled promise rejection Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of th…}
__proto__: Promise
[[PromiseStatus]]: "rejected"
[[PromiseValue]]: DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
debugger-uncaught-promise-on-dom-exception.html:30 throwDOMException
debugger-uncaught-promise-on-dom-exception.html:21 p_catch
<html>
<head>
<script src="../../../http/tests/inspector/inspector-test.js"></script>
<script src="../../../http/tests/inspector/console-test.js"></script>
<script src="../../../http/tests/inspector/debugger-test.js"></script>
<script>
function testFunction()
{
console.clear();
debugger;
}
function runPromises()
{
var reject;
var p = new Promise(function(res, rej) {
reject = rej;
});
p.catch(function p_catch() {
throwDOMException();
});
reject(new Error("FAIL: Should not be printed to console"));
}
function throwDOMException()
{
var a = document.createElement("div");
var b = document.createElement("div");
a.removeChild(b);
}
function runPromisesFromInspector()
{
// setTimeout to cut off VM call frames from the stack trace.
setTimeout(function timeout() {
runPromises()
}, 0);
}
function test()
{
InspectorTest.setQuiet(true);
InspectorTest.startDebuggerTest(step1);
function step1()
{
InspectorTest.addConsoleViewSniffer(addMessage, true);
InspectorTest.runTestFunctionAndWaitUntilPaused(didPause);
}
function didPause(callFrames, reason, breakpointIds, asyncStackTrace)
{
InspectorTest.evaluateInPage("runPromisesFromInspector()", resumeExecution);
}
function resumeExecution()
{
InspectorTest.resumeExecution();
}
function addMessage(uiMessage)
{
InspectorTest.expandConsoleMessages(dump);
}
function dump()
{
InspectorTest.dumpConsoleMessages(false, false, InspectorTest.textContentWithLineBreaks);
InspectorTest.completeTest();
}
}
</script>
</head>
<body onload="runTest()">
<p>
Tests unhandled promise that was rejected with a DOM exception.
</p>
</body>
</html>
...@@ -256,6 +256,17 @@ static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message) ...@@ -256,6 +256,17 @@ static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message)
if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0)
callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate);
if (!callStack && V8DOMWrapper::isDOMWrapper(message.GetValue())) {
// Try to get the stack from a wrapped exception object (e.g. DOMException).
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(message.GetValue());
v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate));
if (!error.IsEmpty()) {
stackTrace = v8::Exception::GetStackTrace(error);
if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0)
callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate);
}
}
ScriptState* scriptState = ScriptState::from(context); ScriptState* scriptState = ScriptState::from(context);
promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), callStack)); promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), callStack));
} }
......
...@@ -73,6 +73,7 @@ v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const String& ...@@ -73,6 +73,7 @@ v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const String&
ASSERT(!error.IsEmpty()); ASSERT(!error.IsEmpty());
ASSERT(exception->IsObject()); ASSERT(exception->IsObject());
exception->ToObject()->SetAccessor(v8AtomicString(isolate, "stack"), domExceptionStackGetter, domExceptionStackSetter, error); exception->ToObject()->SetAccessor(v8AtomicString(isolate, "stack"), domExceptionStackGetter, domExceptionStackSetter, error);
V8HiddenValue::setHiddenValue(isolate, exception->ToObject(), V8HiddenValue::error(isolate), error);
return exception; return exception;
} }
......
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