Open anba opened 4 years ago
JIT interactions may also lead to more issues. For example in V8, f1
starts to have different results when jitted:
function assertEq(a, e, i) {
if (!Object.is(a, e)) {
throw new Error(`${a} != ${e} at iteration ${i}`);
}
}
// - Modifies a parameter.
// - Doesn't explicitly refer to the implicit `arguments` binding.
function f1(a) {
assertEq(f1.arguments[0], 0, i);
a = 1;
assertEq(f1.arguments[0], 1, i);
}
for (var i = 0; i < 10_000_000; ++i) {
f1(0);
}
Interesting. At this point, I wonder whether it is better to leave some parts of Function.prototype.arguments
as implementation-defined.
Yes, I think I kind of agree to leave it implementation-defined for now. Maybe we can align implementations at a later time.
I've also added another test case (f4
) to cover closed over bindings.
I wonder whether there are situations where implementations are not even able to recover some parameter value, either original or current?
I've compiled your test cases (including the “jit interaction” one) in tests-arguments-wild.html
Interestingly, the outcome is different in Safari when the web inspector is closed or when it is open. When it is open, f1.arguments[0]
reflects the original value passed to the function (and all tests are passed).
I’ve updated analysis.md#value-returned-by-arguments with the results of the tests. For convenience, I write them also in this comment:
Each integer-indexed value of the object returned by f.arguments
reflects:
In the most basic cases, semantics (B) is chosen. The implementation switches to semantics (A) if any of the following condition is satifsied:
arguments
binding in the function code;I think default parameters will also trigger case (A).
Firefox and Chrome also use (B) when the function contains a with-statement, for example with({});
, whereas Safari uses (A).
Firefox may also use (B) even though arguments
is mentioned, for example when delete arguments
occurs in the function. Safari and Chrome use (A) in that case.
The first edition of ECMA-262, describes a mechanism for “provid[ing] compatibility with a form of program syntax that is now discouraged: to access the arguments object for function f within the body of f by using the expression f.arguments” (page 34, section 10.1.6); that is, f.arguments
was supposed to give access to the same object as arguments
, which followed semantics (B).
Apparently, implementations have found convenient to take liberties with the original definition of f.arguments
, one of them is to switch to semantics (A) in various cases.
I wonder if, as of today, it is web-compatible to unconditionally switch to (A)?
From Value returned by .arguments:
This doesn't match the behaviour observable in JSC, V8, and SpiderMonkey.
Results for the below test case:
Function
f1
in JSC, V8, and SpiderMonkey:=>
.arguments
reflects the current parameter value, not the original value passed to the function.Function
f2
in JSC, V8, and SpiderMonkey:=>
.arguments
reflects the original value passed to the function. (This matches the current proposal spec text.)Function
f3
in JSC and V8:=>
.arguments
reflects the original value passed to the function. (This matches the current proposal spec text.)Function
f3
in SpiderMonkey:=>
.arguments
reflects the current parameter value, not the original value passed to the function.Function
f4
in JSC, V8, and SpiderMonkey:=>
.arguments
reflects the original value passed to the function. (This matches the current proposal spec text.)Test case: