53fc4807cd
Previously we'd allow to replace the source of functions that are on the current execution stack under certain conditions, but this has resulted in an endless stream of bugs due to weird edge cases, and so we're now limiting LiveEdit to functions that don't have any activation (including not a suspended generator / async function activation). We might eventually add the ability to LiveEdit functions with activations and have them "upgrade upon next invocation", but that doesn't seem to be an extremely important use case right now. Fixed: chromium:1195927 Change-Id: I87a45ba4d0ddcfbf867bd4e73738d76b2d789e04 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2846892 Auto-Submit: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#74249}
89 lines
2.0 KiB
JavaScript
89 lines
2.0 KiB
JavaScript
// Copyright 2015 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.
|
|
|
|
// Test that live-editing a frame above one that uses new.target succeeds.
|
|
// Flags: --allow-natives-syntax
|
|
|
|
Debug = debug.Debug;
|
|
var wrapper_calls = 0;
|
|
var construct_calls = 0;
|
|
var exceptions = 0;
|
|
var results = [];
|
|
var replace_again;
|
|
|
|
eval(`
|
|
function LogNewTarget(arg) {
|
|
construct_calls++;
|
|
results.push(new.target);
|
|
}
|
|
function Wrapper() {
|
|
wrapper_calls++;
|
|
ReplaceOnce();
|
|
new LogNewTarget(true);
|
|
}
|
|
`);
|
|
|
|
function ExecuteInDebugContext(f) {
|
|
var result;
|
|
var exception = null;
|
|
Debug.setListener(function(event) {
|
|
if (event == Debug.DebugEvent.Break) {
|
|
try {
|
|
result = f();
|
|
} catch (e) {
|
|
// Rethrow this exception later.
|
|
exception = e;
|
|
}
|
|
}
|
|
});
|
|
debugger;
|
|
Debug.setListener(null);
|
|
if (exception !== null) throw exception;
|
|
return result;
|
|
}
|
|
|
|
function Replace(fun, original, patch) {
|
|
ExecuteInDebugContext(function() {
|
|
var change_log = [];
|
|
try {
|
|
%LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
|
|
} catch (e) {
|
|
exceptions++;
|
|
}
|
|
});
|
|
}
|
|
|
|
function ReplaceOnce(x) {
|
|
if (replace_again) {
|
|
replace_again = false;
|
|
Replace(Wrapper, "true", "false");
|
|
}
|
|
}
|
|
|
|
function Revert() {
|
|
Replace(Wrapper, "false", "true");
|
|
}
|
|
|
|
replace_again = true;
|
|
ReplaceOnce();
|
|
Wrapper();
|
|
Revert();
|
|
assertEquals(1, construct_calls);
|
|
assertEquals(1, wrapper_calls);
|
|
assertEquals(0, exceptions); // Replace succeeds
|
|
assertEquals([LogNewTarget], results);
|
|
|
|
Wrapper();
|
|
assertEquals(2, construct_calls);
|
|
assertEquals(2, wrapper_calls);
|
|
assertEquals(0, exceptions); // Replace succeeds
|
|
assertEquals([LogNewTarget, LogNewTarget], results);
|
|
|
|
replace_again = true;
|
|
Wrapper();
|
|
assertEquals(3, construct_calls);
|
|
assertEquals(3, wrapper_calls);
|
|
assertEquals(1, exceptions); // Replace failed
|
|
assertEquals([LogNewTarget, LogNewTarget, LogNewTarget], results);
|