v8/test/inspector/debugger/value-unavailable-scopes.js
Simon Zünd 85561d6616 [debug] Only apply TDZ 'value unavailable' logic for let/const
This CL refines https://crrev.com/c/3829539 to only apply to let and
const declared variables. `var`s should stay `undefined`.

R=jarin@chromium.org

Bug: chromium:1328681
Change-Id: I35778c89fb04439348a4f6aebcdeb2db6234f9d0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3848960
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82640}
2022-08-23 07:19:34 +00:00

130 lines
3.5 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.
// Flags: --allow-natives-syntax --experimental-value-unavailable
let {session, contextGroup, Protocol} =
InspectorTest.start('Test scopes with unavailable values');
contextGroup.addScript(`
function tdz() {
debugger;
const x = 2 ?? y + x;
let y = x + 1;
return y;
}
function opt() {
function optimizedOut(x, stop) {
let y = x + 1;
let z = y + 1;
if (stop) {
debugger;
}
return z;
}
%PrepareFunctionForOptimization(optimizedOut);
optimizedOut(1, false);
optimizedOut(2, false);
%OptimizeFunctionOnNextCall(optimizedOut);
optimizedOut(3, false);
return optimizedOut(1, true);
}
function unusedValInTdz() {
debugger;
let y = 1;
}
function varStaysUndefined() {
debugger;
var y = 42;
}
`);
async function findLocalVariable(name, scopeChain) {
for (const scope of scopeChain) {
if (scope.type !== 'local') continue;
const {result: {result: variables}} =
await Protocol.Runtime.getProperties({objectId: scope.object.objectId});
const variable = variables.find(variable => variable.name === name);
if (!variable) {
InspectorTest.log(`FAIL: variable ${name} not found in local scope`);
}
return variable;
}
}
Protocol.Debugger.onPaused(async ({ params: { callFrames: [{ scopeChain }] } }) => {
const variable = await findLocalVariable('y', scopeChain);
if ('value' in variable || 'get' in variable || 'set' in variable) {
InspectorTest.log(
'FAIL: variable y was expected to be reported as <value_unavailable>');
} else {
InspectorTest.log(
'variable y correctly reported as <value_unavailable>');
}
await Protocol.Debugger.resume();
});
InspectorTest.runAsyncTestSuite([
async function testTemporalDeadZone() {
await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
]);
await Protocol.Runtime.evaluate({expression: 'tdz()'});
await Promise.all([
Protocol.Runtime.disable(),
Protocol.Debugger.disable(),
]);
},
async function testOptimizedOut() {
await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
]);
await Protocol.Runtime.evaluate({expression: 'opt()'});
await Promise.all([
Protocol.Runtime.disable(),
Protocol.Debugger.disable(),
]);
},
async function testUnusedValueInTdz() {
await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
]);
await Protocol.Runtime.evaluate({expression: 'unusedValInTdz()'});
await Promise.all([
Protocol.Runtime.disable(),
Protocol.Debugger.disable(),
]);
},
async function testVarStaysUndefined() {
await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
]);
Protocol.Runtime.evaluate({ expression: 'varStaysUndefined()' });
const { params: { callFrames: [{ scopeChain }] } } = await Protocol.Debugger.oncePaused();
const variable = await findLocalVariable('y', scopeChain);
if ('value' in variable && variable.value.type === 'undefined') {
InspectorTest.log('variable y correctly reported as <undefined>');
} else {
InspectorTest.log('FAIL: variable y was expected to be reported as <undefined>');
}
await Protocol.Debugger.resume();
await Promise.all([
Protocol.Runtime.disable(),
Protocol.Debugger.disable(),
]);
},
]);