013e49f73c
To make async/await catch prediction work well, this patch regularizes the exception events sent to DevTools from various places in the Promise lifecycle. The core is that there should be an exception event when the rejection first starts, rather than when it is propagated. - Several cases within Promise code which propagate errors are modified to not trigger a new ExceptionEvent in that case, such as .then on a rejected Promise and returning a rejected Promise from .then, as well as Promise.race and Promise.all. - Make Promise.reject() create an ExceptionEvent, subject to catch prediction based on the Promise stack. This is important so that, e.g., if "await Promise.reject()" will trigger a new throw (rather than a silent rethrow of something that never triggered an event in the first place). BUG=v8:5167 Review-Url: https://codereview.chromium.org/2244003003 Cr-Commit-Position: refs/heads/master@{#38847}
124 lines
2.8 KiB
JavaScript
124 lines
2.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: --allow-natives-syntax --harmony-async-await --expose-debug-as debug
|
|
|
|
Debug = debug.Debug
|
|
|
|
var exception = null;
|
|
var log;
|
|
|
|
function listener(event, exec_state, event_data, data) {
|
|
if (event != Debug.DebugEvent.Exception) return;
|
|
try {
|
|
var line = exec_state.frame(0).sourceLineText();
|
|
var match = /Exception (\w)/.exec(line);
|
|
assertNotNull(match);
|
|
log.push(match[1]);
|
|
} catch (e) {
|
|
exception = e;
|
|
}
|
|
}
|
|
|
|
async function thrower() {
|
|
throw "a"; // Exception a
|
|
}
|
|
|
|
async function caught_throw() {
|
|
try {
|
|
await thrower();
|
|
} catch (e) {
|
|
assertEquals("a", e);
|
|
}
|
|
}
|
|
|
|
|
|
// Caught throw, events on any exception.
|
|
log = [];
|
|
Debug.setListener(listener);
|
|
Debug.setBreakOnException();
|
|
caught_throw();
|
|
%RunMicrotasks();
|
|
Debug.setListener(null);
|
|
Debug.clearBreakOnException();
|
|
assertEquals(["a"], log);
|
|
assertNull(exception);
|
|
|
|
// Caught throw, events on uncaught exception.
|
|
log = [];
|
|
Debug.setListener(listener);
|
|
Debug.setBreakOnUncaughtException();
|
|
caught_throw();
|
|
%RunMicrotasks();
|
|
Debug.setListener(null);
|
|
Debug.clearBreakOnUncaughtException();
|
|
assertEquals([], log);
|
|
assertNull(exception);
|
|
|
|
var reject = Promise.reject("b");
|
|
|
|
async function caught_reject() {
|
|
try {
|
|
await reject;
|
|
} catch (e) {
|
|
assertEquals("b", e);
|
|
}
|
|
}
|
|
|
|
// Caught reject, events on any exception.
|
|
log = [];
|
|
Debug.setListener(listener);
|
|
Debug.setBreakOnException();
|
|
caught_reject();
|
|
%RunMicrotasks();
|
|
Debug.setListener(null);
|
|
Debug.clearBreakOnException();
|
|
assertEquals([], log);
|
|
assertNull(exception);
|
|
|
|
// Caught reject, events on uncaught exception.
|
|
log = [];
|
|
Debug.setListener(listener);
|
|
Debug.setBreakOnUncaughtException();
|
|
caught_reject();
|
|
%RunMicrotasks();
|
|
Debug.setListener(null);
|
|
Debug.clearBreakOnUncaughtException();
|
|
assertEquals([], log);
|
|
assertNull(exception);
|
|
|
|
log = [];
|
|
Debug.setListener(listener);
|
|
Debug.setBreakOnException();
|
|
|
|
// "rethrown" uncaught exceptions in return don't cause another event
|
|
async function propagate_inner() { return thrower(); }
|
|
async function propagate_outer() { return propagate_inner(); }
|
|
|
|
propagate_outer();
|
|
%RunMicrotasks();
|
|
assertEquals(["a"], log);
|
|
assertNull(exception);
|
|
|
|
// Also don't propagate if an await interceded
|
|
log = [];
|
|
async function propagate_await() { await 1; return thrower(); }
|
|
async function propagate_await_outer() { return propagate_await(); }
|
|
propagate_await_outer();
|
|
%RunMicrotasks();
|
|
assertEquals(["a"], log);
|
|
assertNull(exception);
|
|
|
|
Debug.clearBreakOnException();
|
|
Debug.setBreakOnUncaughtException();
|
|
|
|
log = [];
|
|
Promise.resolve().then(() => Promise.reject()).catch(() => log.push("d")); // Exception c
|
|
%RunMicrotasks();
|
|
assertEquals(["d"], log);
|
|
assertNull(exception);
|
|
|
|
Debug.clearBreakOnUncaughtException();
|
|
Debug.setListener(null);
|