v8/test/inspector/debugger/stepping-async-generator.js
Benedikt Meurer 887bacacb0 [debug] Consistent Step-In behavior for generator functions.
This change addresses inconsistencies wrt. to stepping into generator
functions and breaking on the implicit initial yield. The new behavior
is the following:

 1. Stepping into a generator function doesn't trigger "generator
    stepping", but rather pauses right before the initial yield
    (assuming there a no non-simple parameters in between).
 2. When paused on the initial yield and stepping into or over, we also
    don't turn on "generator stepping" immediately, but rather return to
    the caller and only enter "generator stepping" on SuspendGenerator
    bytecodes that correspond to `yield`s or `await`s in the source
    code.

This matches the stepping behavior of regular functions more closely and
seems like a good compromise.

Fixed: chromium:901814
Change-Id: Ifc6c174011df1afea183e2c6ec21de27d72b17a7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2949099
Commit-Queue: Yang Guo <yangguo@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75066}
2021-06-10 07:49:04 +00:00

88 lines
3.3 KiB
JavaScript

// Copyright 2021 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.
let {session, contextGroup, Protocol} = InspectorTest.start('Async generator stepping');
const url = 'stepping-async-generator.js';
contextGroup.addScript(`
async function* generator() {
var a = 42;
yield a;
}
function callGenerator() {
return generator();
}
`, 0, 0, url);
session.setupScriptMap();
InspectorTest.runAsyncTestSuite([
async function testStepOverFromInitialYield() {
await Promise.all([Protocol.Debugger.enable(), Protocol.Runtime.enable()]);
InspectorTest.log(`Setting breakpoint on implicit initial yield`);
const {result: {breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
url,
lineNumber: 1,
columnNumber: 0,
})
InspectorTest.log(`Calling callGenerator()`);
const pausedPromise = Protocol.Debugger.oncePaused();
const evalPromise = Protocol.Runtime.evaluate({expression: 'callGenerator()'});
const {method, params} = await Promise.race([pausedPromise, evalPromise]);
if (method === 'Debugger.paused') {
await session.logSourceLocation(params.callFrames[0].location);
InspectorTest.log('Stepping over while paused on the initial yield');
const [{params: {callFrames:[{location}]}}] = await Promise.all([
Protocol.Debugger.oncePaused(),
Protocol.Debugger.stepOver(),
]);
await session.logSourceLocation(location);
await Promise.all([Protocol.Debugger.resume(), evalPromise]);
} else {
InspectorTest.log('Did not pause');
}
await Protocol.Debugger.removeBreakpoint({breakpointId});
await Promise.all([Protocol.Debugger.disable(), Protocol.Runtime.disable()]);
},
async function testStepIntoInitialYield() {
await Promise.all([Protocol.Debugger.enable(), Protocol.Runtime.enable()]);
InspectorTest.log(`Setting breakpoint on call to generator()`);
const {result: {breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
url,
lineNumber: 5,
columnNumber: 0,
})
InspectorTest.log(`Calling callGenerator()`);
const pausedPromise = Protocol.Debugger.oncePaused();
const evalPromise = Protocol.Runtime.evaluate({expression: 'callGenerator()'});
const {method, params} = await Promise.race([pausedPromise, evalPromise]);
if (method === 'Debugger.paused') {
await session.logSourceLocation(params.callFrames[0].location);
InspectorTest.log('Stepping into the generator()');
let [{params: {callFrames:[{location}]}}] = await Promise.all([
Protocol.Debugger.oncePaused(),
Protocol.Debugger.stepInto(),
]);
await session.logSourceLocation(location);
InspectorTest.log('Stepping into while paused on the initial yield');
([{params: {callFrames:[{location}]}}] = await Promise.all([
Protocol.Debugger.oncePaused(),
Protocol.Debugger.stepInto(),
]));
await session.logSourceLocation(location);
await Promise.all([Protocol.Debugger.resume(), evalPromise]);
} else {
InspectorTest.log('Did not pause');
}
await Protocol.Debugger.removeBreakpoint({breakpointId});
await Promise.all([Protocol.Debugger.disable(), Protocol.Runtime.disable()]);
}
]);