Files
ladybird/Tests/LibJS/Runtime/var-shadow-in-default-param.js
Andreas Kling a89cfdb1bb LibJS: Propagate captures from nested functions in default expressions
When a nested function (arrow or function expression) inside a default
parameter expression captures a name that also has a body var
declaration, the capture must propagate to the parent scope. Otherwise,
the outer scope optimizes the binding to a local register, making it
invisible to GetBinding at runtime.
2026-02-19 02:45:37 +01:00

117 lines
2.9 KiB
JavaScript

/*
* Copyright (c) 2026, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
describe("var shadowing in default parameter expressions", () => {
test("body var shadows name used in default -- default sees outer scope", () => {
var shadow = "outer";
function f(x = shadow) {
var shadow = "inner";
return x;
}
expect(f()).toBe("outer");
expect(f("explicit")).toBe("explicit");
});
test("multiple defaults referencing same shadowed name", () => {
var v = "outer";
function f(a = v, b = v) {
var v = "inner";
return a + " " + b;
}
expect(f()).toBe("outer outer");
});
test("destructuring default referencing shadowed name", () => {
var obj = { x: 42 };
function f({ x } = obj) {
var obj = { x: 99 };
return x;
}
expect(f()).toBe(42);
});
test("arrow function in default captures outer scope", () => {
var v = "outer";
function f(x = (() => v)()) {
var v = "inner";
return x;
}
expect(f()).toBe("outer");
});
test("function expression in default captures outer scope", () => {
var v = "outer";
function f(
x = (function () {
return v;
})()
) {
var v = "inner";
return x;
}
expect(f()).toBe("outer");
});
test("body vars not referenced in defaults stay optimized", () => {
function f(x = 1) {
var y = 2;
return x + y;
}
expect(f()).toBe(3);
});
test("param re-declared with var in body retains its value", () => {
function f(a = 10) {
var a;
return a;
}
expect(f()).toBe(10);
});
test("default references earlier parameter", () => {
function f(a = 1, b = a) {
var a = 99;
return b;
}
expect(f()).toBe(1);
});
test("body function declaration accessible with defaults", () => {
function f(x = 1) {
var y = 42;
function inner() {
return y;
}
return inner();
}
expect(f()).toBe(42);
});
test("nested function scope with shadowed default", () => {
var v = "outer";
function outer() {
function inner(x = v) {
var v = "inner";
return x;
}
return inner();
}
expect(outer()).toBe("outer");
});
test("helper function call in default with shadowed var", () => {
var arr = [1, 2, 3];
function helper() {
return arr;
}
function f(x = helper()) {
var arr = [4, 5, 6];
return x[0];
}
expect(f()).toBe(1);
});
});