From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../tests/debug/Debugger-findScripts-delazify.js | 485 +++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 js/src/jit-test/tests/debug/Debugger-findScripts-delazify.js (limited to 'js/src/jit-test/tests/debug/Debugger-findScripts-delazify.js') diff --git a/js/src/jit-test/tests/debug/Debugger-findScripts-delazify.js b/js/src/jit-test/tests/debug/Debugger-findScripts-delazify.js new file mode 100644 index 0000000000..554b5dd2c8 --- /dev/null +++ b/js/src/jit-test/tests/debug/Debugger-findScripts-delazify.js @@ -0,0 +1,485 @@ +// |jit-test| skip-if: isLcovEnabled() + +// findScript should try to avoid delazifying unnecessarily. + +function newTestcase(code) { + var g = newGlobal({newCompartment: true}); + var dbg = new Debugger(); + var gw = dbg.addDebuggee(g); + + var lines = code.split('\n'); + // Returns the line number of the line with "<= line". + // + 1 for 1-origin. + var line = lines.findIndex(x => x.includes("<= line")) + 1; + + g.eval(code); + + // Functions are relazified, and the top-level script is dropped. + relazifyFunctions(); + + return [dbg, g, line]; +} + +var url = thisFilename(); +var dbg, g, line, scripts; + +// If the specified line is inside the function body, only the function should +// be delazified. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +// <= line +} +function f3() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 1); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f2"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); + +// If the functions starts at the specified line, the function shouldn't be +// the first function to delazify. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3() { // <= line +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 1); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f3"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +// f2 is delazified because f3 cannot be the first function to delazify. +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +// Multiple functions in the specified line, and one of them starts before +// the specified line. +// All functions should be returned, and others shouldn't be delazified. +[dbg, g, line] = newTestcase(` +function f1() {} +function f2() { +} function f3() {} function f4() {} function f5() { // <= line +} +function f6() {} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); +assertEq(g.eval(`isLazyFunction(f5)`), true); +assertEq(g.eval(`isLazyFunction(f6)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 4); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f2,f3,f4,f5"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), false); +assertEq(g.eval(`isLazyFunction(f5)`), false); +assertEq(g.eval(`isLazyFunction(f6)`), true); + +// The same rule should apply to inner functions. +[dbg, g, line] = newTestcase(` +function f1() {} +function f2() { + function g1() { + } + function g2() { + function h1() {} + function h2() { + } function h3() {} function h4() {} function h5() { // <= line + } + function h6() {} + + return [h1, h2, h3, h4, h5, h6]; + } + function g3() { + } + + return [g1, g2, g3]; +} +function f3() {} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 6); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f2,g2,h2,h3,h4,h5"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); +g.eval(`var [g1, g2, g3] = f2();`); +assertEq(g.eval(`isLazyFunction(g1)`), true); +assertEq(g.eval(`isLazyFunction(g2)`), false); +assertEq(g.eval(`isLazyFunction(g3)`), true); +g.eval(`var [h1, h2, h3, h4, h5, h6] = g2();`); +assertEq(g.eval(`isLazyFunction(h1)`), true); +assertEq(g.eval(`isLazyFunction(h2)`), false); +assertEq(g.eval(`isLazyFunction(h3)`), false); +assertEq(g.eval(`isLazyFunction(h4)`), false); +assertEq(g.eval(`isLazyFunction(h5)`), false); +assertEq(g.eval(`isLazyFunction(h6)`), true); + +// The same rule should apply to functions inside parameter expression. +[dbg, g, line] = newTestcase(` +function f1( + a = function g1() {}, + b = function g2() { + }, c = function g3() {}, d = function g4() { // <= line + }, + e = function g5() {}, +) { + return [a, b, c, d, e]; +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 4); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f1,g2,g3,g4"); + +assertEq(g.eval(`isLazyFunction(f1)`), false); + +g.eval(`var [g1, g2, g3, g4, g5] = f1();`); + +assertEq(g.eval(`isLazyFunction(g1)`), true); +assertEq(g.eval(`isLazyFunction(g2)`), false); +assertEq(g.eval(`isLazyFunction(g3)`), false); +assertEq(g.eval(`isLazyFunction(g4)`), false); +assertEq(g.eval(`isLazyFunction(g5)`), true); + +// The same should apply to function inside method with computed property. +[dbg, g, line] = newTestcase(` +var f1, f2, f3; +var O = { + [(f1 = () => 0, "m1")]() { + }, + [(f2 = () => 0, "m2")](p2) { // <= line + }, + [(f3 = () => 0, "m3")]() { + }, +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(O.m2)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(O.m1)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(O.m3)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 2); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f2,"); +// Use parameterNames because displayName isn't set for computed property. +assertEq(scripts.map(s => `${s.displayName}(${s.parameterNames.join(",")})`) + .sort().join(","), "f2(),undefined(p2)"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +// m1 is delazified because f2 cannot be the first function to delazify. +assertEq(g.eval(`isLazyFunction(O.m1)`), false); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(O.m2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(O.m3)`), true); + +[dbg, g, line] = newTestcase(` +var f1, f2, f3; +var O = { + [(f1 = () => 0, "m1")]() { + }, + [(f2 = () => 0 + + 1, "m2")](p2) { // <= line + }, + [(f3 = () => 0, "m3")]() { + }, +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(O.m1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(O.m2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(O.m3)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 2); +assertEq(scripts.map(s => `${s.displayName}(${s.parameterNames.join(",")})`) + .sort().join(","), "f2(),undefined(p2)"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(O.m1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(O.m2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(O.m3)`), true); + +// Class constructor shouldn't be delazified even if methods match. +[dbg, g, line] = newTestcase(` +// Use variable to access across eval. +var C = class { + constructor() { + } + m1() {} + m2() { + } m3() {} m4() { // <= line + } + m5() {} +} +`); + +assertEq(g.eval(`isLazyFunction(C)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m1)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m2)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m3)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m4)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m5)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 3); +assertEq(scripts.map(s => s.displayName).sort().join(","), "m2,m3,m4"); + +assertEq(g.eval(`isLazyFunction(C)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m1)`), true); +assertEq(g.eval(`isLazyFunction(C.prototype.m2)`), false); +assertEq(g.eval(`isLazyFunction(C.prototype.m3)`), false); +assertEq(g.eval(`isLazyFunction(C.prototype.m4)`), false); +assertEq(g.eval(`isLazyFunction(C.prototype.m5)`), true); + +// If the line is placed before sourceStart, the function shouldn't match, +// and the function shouldn't be delazified. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function +// <= line +f3() { +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 0); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +// f2 is delazified because it's the first function before the specified line. +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3 +// <= line +() { +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 0); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +// f2 is delazified because it's the first function before the specified line. +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3 +( // <= line +) { +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 1); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f3"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +// f2 is delazified because it's the first function _before_ the specified line. +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3 +( +// <= line +) { +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 1); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f3"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +// If the specified line is the next line after the function ends, +// nothing should match, but the function should be delazified. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +// <= line +function f3() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 0); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), false); +assertEq(g.eval(`isLazyFunction(f3)`), true); + +// The matching non-lazy script should prevent the previous function's +// delazification. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3() { + // <= line +} +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +// Delazify f3. +g.eval(`f3()`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 1); +assertEq(scripts.map(s => s.displayName).sort().join(","), "f3"); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +// The non-matching non-lazy script should prevent the previous function's +// delazification. +[dbg, g, line] = newTestcase(` +function f1() { +} +function f2() { +} +function f3() { +} +// <= line +function f4() { +} +`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), true); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +// Delazify f3. +g.eval(`f3()`); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); + +scripts = dbg.findScripts({url, line}); +assertEq(scripts.length, 0); + +assertEq(g.eval(`isLazyFunction(f1)`), true); +assertEq(g.eval(`isLazyFunction(f2)`), true); +assertEq(g.eval(`isLazyFunction(f3)`), false); +assertEq(g.eval(`isLazyFunction(f4)`), true); -- cgit v1.2.3