c45a214cb5
This change removes the confusing statement positions that were previously emitted for every binding identifier within both array and object destructurings. These statement positions were reported as breakable positions to the debugger front-end, and during stepping, the debugger would also stop on them. This is confusing and very different from how other expressions work (we don't emit statement positions within expressions normally). Instead we emit expression positions for the binding identifiers, which are used to construct the source positions for stack traces. As a drive by we also add the missing position (and test cases) for sub-patterns. In particular this aligns the stepping and breakpoint behavior around destructuring expressions with that of Firefox DevTools. We also remove the original test cases, introduced with https://codereview.chromium.org/1542813003 and https://codereview.chromium.org/1533313002, which were written as debugger tests, with new inspector tests that also ensure that the call positions are correct. Fixed: chromium:1368444 Bug: v8:811 Doc: http://go/chrome-devtools:destructuring-breakpoints-design Change-Id: I4d53ad059b5eede73abd01d9bc9fdf8263c55c9d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3916453 Reviewed-by: Kim-Anh Tran <kimanh@chromium.org> Commit-Queue: Kim-Anh Tran <kimanh@chromium.org> Auto-Submit: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#83455}
103 lines
3.0 KiB
JavaScript
103 lines
3.0 KiB
JavaScript
// Copyright 2022 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('Tests breakable locations in array destructuring.');
|
|
|
|
const source = `
|
|
function testFunction() {
|
|
var [a, b, c = 4] = generator1();
|
|
[[a, b], c] = generator2();
|
|
[a, ...b] = generator1();
|
|
}
|
|
|
|
function generator1() {
|
|
return {
|
|
[Symbol.iterator]() {
|
|
const it = [1, 2].values();
|
|
return {next() { return it.next(); }};
|
|
}
|
|
};
|
|
}
|
|
|
|
function generator2() {
|
|
return {
|
|
[Symbol.iterator]() {
|
|
const it = [generator1(), 3].values();
|
|
return {next() { return it.next(); }};
|
|
}
|
|
};
|
|
}
|
|
`;
|
|
|
|
const url = 'test.js';
|
|
contextGroup.addScript(source, 0, 0, url);
|
|
session.setupScriptMap();
|
|
|
|
InspectorTest.runAsyncTestSuite([
|
|
async function testBreakLocations() {
|
|
let [, , {params: {scriptId}}] = await Promise.all([
|
|
Protocol.Runtime.enable(),
|
|
Protocol.Debugger.enable(),
|
|
Protocol.Debugger.onceScriptParsed(),
|
|
]);
|
|
let {result: {locations}} = await Protocol.Debugger.getPossibleBreakpoints(
|
|
{start: {lineNumber: 0, columnNumber: 0, scriptId}});
|
|
await session.logBreakLocations(locations);
|
|
await Promise.all([
|
|
Protocol.Debugger.disable(),
|
|
Protocol.Runtime.disable(),
|
|
]);
|
|
},
|
|
|
|
async function testStepping() {
|
|
let [, , {params: {scriptId}}] = await Promise.all([
|
|
Protocol.Runtime.enable(),
|
|
Protocol.Debugger.enable(),
|
|
Protocol.Debugger.onceScriptParsed(),
|
|
]);
|
|
const {breakpointId} = await Protocol.Debugger.setBreakpoint({
|
|
location: {
|
|
scriptId,
|
|
lineNumber: 2,
|
|
}
|
|
});
|
|
const evalPromise =
|
|
Protocol.Runtime.evaluate({expression: 'testFunction()'});
|
|
for (;;) {
|
|
const {method, params} = await Promise.race([
|
|
evalPromise,
|
|
Protocol.Debugger.oncePaused(),
|
|
]);
|
|
if (method !== 'Debugger.paused') {
|
|
break;
|
|
}
|
|
const callFrames = params.callFrames.filter(
|
|
callFrame => callFrame.location.scriptId === scriptId);
|
|
if (callFrames.length === 0) {
|
|
InspectorTest.log('Resuming and finishing...');
|
|
await Protocol.Debugger.resume();
|
|
} else {
|
|
const [{functionName, location}, ...callerFrames] = callFrames;
|
|
InspectorTest.log(`Execution paused in ${functionName}:`);
|
|
await session.logSourceLocation(location);
|
|
for (const {location, functionName} of callerFrames) {
|
|
InspectorTest.log(`Called from ${functionName}:`);
|
|
await session.logSourceLocation(location);
|
|
}
|
|
if (functionName === 'testFunction') {
|
|
await Protocol.Debugger.stepInto();
|
|
} else {
|
|
await Protocol.Debugger.stepOut();
|
|
}
|
|
}
|
|
}
|
|
await Promise.all([
|
|
Protocol.Debugger.removeBreakpoint({breakpointId}),
|
|
Protocol.Debugger.disable(),
|
|
Protocol.Runtime.disable(),
|
|
]);
|
|
}
|
|
]);
|