f813494fcc
In the parser, we desugar yield* with the help of a regular yield. One particular implementation detail of this desugaring is that when the user calls the generator's throw method, this throws an exception that we immediately catch. This exception should not be visible to the user, but through Devtools' "Pause on Caught Exceptions" feature it used to be. This CL extends the type of catch predictions with a new value for such internal exceptions and uses that for the offending try-catch statement in yield*. It instruments the debugger to _not_ trigger an exception event in that case. R=yangguo@chromium.org TBR=littledan@chromium.org BUG=v8:5218 Review-Url: https://codereview.chromium.org/2203803002 Cr-Commit-Position: refs/heads/master@{#38286}
89 lines
1.5 KiB
JavaScript
89 lines
1.5 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-debug-as debug
|
|
|
|
|
|
Debug = debug.Debug
|
|
|
|
let error = false;
|
|
let uncaught;
|
|
|
|
function listener(event, exec_state, event_data, data) {
|
|
if (event != Debug.DebugEvent.Exception) return;
|
|
try {
|
|
uncaught = event_data.uncaught();
|
|
} catch (e) {
|
|
error = true;
|
|
}
|
|
}
|
|
|
|
Debug.setBreakOnException();
|
|
Debug.setListener(listener);
|
|
|
|
|
|
function assertCaught(f) {
|
|
try {f()} finally {
|
|
assertFalse(uncaught);
|
|
return;
|
|
}
|
|
}
|
|
|
|
function assertUncaught(f) {
|
|
try {f()} finally {
|
|
assertTrue(uncaught);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
assertUncaught(() => {
|
|
for (var a of [1, 2, 3]) {
|
|
throw a
|
|
}
|
|
});
|
|
|
|
assertUncaught(() => {
|
|
for (var a of [1, 2, 3]) {
|
|
try {throw a} finally {}
|
|
}
|
|
});
|
|
|
|
assertCaught(() => {
|
|
for (var a of [1, 2, 3]) {
|
|
try {
|
|
try {throw a} finally {}
|
|
} catch(_) {}
|
|
}
|
|
});
|
|
|
|
assertCaught(() => {
|
|
try {
|
|
for (var a of [1, 2, 3]) {
|
|
try {throw a} finally {}
|
|
}
|
|
} catch(_) {}
|
|
});
|
|
|
|
|
|
// Check that an internal exception in our yield* desugaring is not observable.
|
|
{
|
|
uncaught = null;
|
|
|
|
let iter = {
|
|
next() {return {value:42, done:false}},
|
|
throw() {return {done:true}}
|
|
};
|
|
let iterable = {[Symbol.iterator]() {return iter}};
|
|
function* f() { yield* iterable }
|
|
|
|
let g = f();
|
|
g.next();
|
|
assertEquals({value: undefined, done: true}, g.throw());
|
|
assertNull(uncaught); // No exception event was generated.
|
|
}
|
|
|
|
|
|
assertFalse(error);
|