45026a66ef
Currently, LiveEdit updates the source positions of unchanged SFIs in-place (the SFI could have moved due to other functions changing). This interfere with our plans to re-use ScopeInfo-based blocklists for debug-evaluate. Entries in the global block list cache are keyed by ScopeInfo's source position. Any closure that escaped a debug-evaluate will point to the old ScopeInfo in its context chain and the block lists should stay in-place in case the escaped closure is called again. Rather than updating ScopeInfos in-place, this CL updates the ScopeInfo object wholesale for unchanged SFIs. This is safe todo given that the old and new ScopeInfo are identical modulo source positions. Drive-by: Take the source position of the function token from the `FunctionLiteral` rather than doing a more expensive position translation. Bug: chromium:1363561 Change-Id: I2b8476edd8d7dc4c618e53551aa5692a21d6fb32 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3932724 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#83536}
65 lines
1.9 KiB
JavaScript
65 lines
1.9 KiB
JavaScript
// Copyright 2020 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.
|
|
|
|
const {session, contextGroup, Protocol} =
|
|
InspectorTest.start('Check that setScriptSource doesn\'t affect debug-evaluate block listing');
|
|
|
|
const script = `
|
|
// INSERT NEWLINES HERE
|
|
function f() {
|
|
let a = 3; () => a; // context allocated.
|
|
return function g() {
|
|
let a = 42; // stack-allocated. Shadowing context-allocated from f.
|
|
return function h() {
|
|
// Give h a context.
|
|
let x = 5; () => x;
|
|
return function i() {
|
|
debugger;
|
|
};
|
|
};
|
|
};
|
|
}
|
|
(((f())())())();
|
|
`;
|
|
|
|
const updatedScript = script.replace('// INSERT NEWLINES HERE', '\n\n\n');
|
|
|
|
(async function test() {
|
|
await Protocol.Debugger.enable();
|
|
await Protocol.Runtime.enable();
|
|
const promise = Protocol.Debugger.oncePaused();
|
|
|
|
contextGroup.addScript(script);
|
|
|
|
const { params: { callFrames: [{ callFrameId, functionLocation: { scriptId } }] } } = await promise;
|
|
|
|
// Create a closure that returns `a` and stash it on the global.
|
|
await Protocol.Debugger.evaluateOnCallFrame({
|
|
callFrameId,
|
|
expression: `globalThis['foo'] = () => a;`
|
|
});
|
|
await Protocol.Debugger.resume();
|
|
|
|
// Expect a ReferenceError.
|
|
const { result: { result: result1 } } = await Protocol.Runtime.evaluate({
|
|
expression: 'globalThis.foo();'
|
|
});
|
|
InspectorTest.logMessage(result1);
|
|
|
|
// Move function 'h' but don't change it.
|
|
const { result: { status } } = await Protocol.Debugger.setScriptSource({
|
|
scriptId,
|
|
scriptSource: updatedScript,
|
|
});
|
|
InspectorTest.log(`Debugger.setScriptSource: ${status}`);
|
|
|
|
// Still expect a ReferenceError.
|
|
const { result: { result: result2 } } = await Protocol.Runtime.evaluate({
|
|
expression: 'globalThis.foo();'
|
|
});
|
|
InspectorTest.logMessage(result2);
|
|
|
|
InspectorTest.completeTest();
|
|
})();
|