b15c02d0e1
When V8 throws an uncaught exception, we store a JSMessageObject with a stack trace and source positions on the isolate itself. The JSMessageObject can be retrieved by a TryCatch scope and is used by the inspector to provide additional information to the DevTools frontend (besides the exception). Introducing top-level await for REPL mode causes all thrown exceptions to be turned into a rejected promise. The implicit catch block that does this conversion clears the JSMessageObject from the isolate as to not leak memory. This CL preserves the JSMessageObject when the debugger is active and stores the JSMessageObject on the rejected promise itself. The inspector is changed to retrieve the JSMessageObject in the existing catch handler and pass the information along to the frontend. Drive-by: This CL removes a inspector test that made assumptions when a promise is cleaned up by the GC. These assumptions no longer hold since we hold on to the promise longer. Bug: chromium:1021921 Change-Id: Id0380e2cf3bd79aca05191bc4f3c616f6ced8db7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1967375 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Peter Marshall <petermarshall@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#65497}
123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
// 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.
|
|
|
|
// Flags: --expose-gc
|
|
|
|
let {session, contextGroup, Protocol} = InspectorTest.start("Tests that Runtime.awaitPromise works.");
|
|
|
|
contextGroup.addScript(
|
|
`
|
|
var resolveCallback;
|
|
var rejectCallback;
|
|
function createPromise()
|
|
{
|
|
return new Promise((resolve, reject) => { resolveCallback = resolve; rejectCallback = reject });
|
|
}
|
|
|
|
function resolvePromise()
|
|
{
|
|
resolveCallback(239);
|
|
resolveCallback = undefined;
|
|
rejectCallback = undefined;
|
|
}
|
|
|
|
function rejectPromise()
|
|
{
|
|
rejectCallback(239);
|
|
resolveCallback = undefined;
|
|
rejectCallback = undefined;
|
|
}
|
|
|
|
function rejectPromiseWithAnError()
|
|
{
|
|
rejectCallback(new Error('MyError'));
|
|
resolveCallback = undefined;
|
|
rejectCallback = undefined;
|
|
}
|
|
|
|
function throwError()
|
|
{
|
|
throw new Error('MyError');
|
|
}
|
|
|
|
//# sourceURL=test.js`);
|
|
|
|
Protocol.Debugger.enable()
|
|
.then(() => Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }))
|
|
.then(() => testSuite());
|
|
|
|
function testSuite()
|
|
{
|
|
InspectorTest.runTestSuite([
|
|
function testResolvedPromise(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "Promise.resolve(239)"})
|
|
.then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: false, generatePreview: true }))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
},
|
|
|
|
function testRejectedPromise(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "Promise.reject({ a : 1 })"})
|
|
.then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: true, generatePreview: false }))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
},
|
|
|
|
function testRejectedPromiseWithStack(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "createPromise()"})
|
|
.then(result => scheduleRejectAndAwaitPromise(result))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
|
|
function scheduleRejectAndAwaitPromise(result)
|
|
{
|
|
var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId });
|
|
Protocol.Runtime.evaluate({ expression: "rejectPromise()" });
|
|
return promise;
|
|
}
|
|
},
|
|
|
|
function testRejectedPromiseWithError(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "createPromise()"})
|
|
.then(result => scheduleRejectAndAwaitPromise(result))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
|
|
function scheduleRejectAndAwaitPromise(result)
|
|
{
|
|
var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId });
|
|
Protocol.Runtime.evaluate({ expression: "rejectPromiseWithAnError()" });
|
|
return promise;
|
|
}
|
|
},
|
|
|
|
function testPendingPromise(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "createPromise()"})
|
|
.then(result => scheduleFulfillAndAwaitPromise(result))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
|
|
function scheduleFulfillAndAwaitPromise(result)
|
|
{
|
|
var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId });
|
|
Protocol.Runtime.evaluate({ expression: "resolvePromise()" });
|
|
return promise;
|
|
}
|
|
},
|
|
|
|
function testResolvedWithoutArgsPromise(next)
|
|
{
|
|
Protocol.Runtime.evaluate({ expression: "Promise.resolve()"})
|
|
.then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: true, generatePreview: false }))
|
|
.then(result => InspectorTest.logMessage(result))
|
|
.then(() => next());
|
|
}
|
|
]);
|
|
}
|