Admit direct arguments reads in Test262 scripts

This commit is contained in:
Chris Tate
2026-09-28 09:34:19 -05:00
parent f1a1f059c7
commit df2cc5dd8f
5 changed files with 117 additions and 1 deletions
+12
View File
@@ -73,6 +73,18 @@ test("receiver-bound this is admitted without adapting script-level this", () =>
}
});
test("arguments reads are admitted only for indexed and length access inside a function", () => {
for (const [body, expected] of [
["function f() { return arguments.length === 1 && arguments[0] === 3; } assert(f(3));", undefined],
["function f() { return arguments; }", "host:arguments"],
["function f() { return Array.isArray(arguments); }", "host:arguments"],
["assert.sameValue(arguments.length, 0);", "host:arguments"],
]) {
const text = source("description: arguments", body!);
expect(exclusion(text, metadata(text), "strict")).toBe(expected);
}
});
test("negative parse cases require the compiler's matching source diagnostic", () => {
const text = source("negative: {phase: parse, type: SyntaxError}", "$DONOTEVALUATE();\nconst = ;");
expect(exclusion(text, metadata(text), "strict")).toBeUndefined();
+14 -1
View File
@@ -95,6 +95,14 @@ function hasOwnThisBinding(node) {
return false;
}
function argumentsOwner(node) {
for (let parent = node.parent; parent; parent = parent.parent) {
if (ts.isArrowFunction(parent)) continue;
if (ts.isFunctionLike(parent) && parent.body) return parent;
}
return undefined;
}
// The first static profile adapts scripts to standalone strict modules. Be
// conservative about observable global-script semantics and helper reflection.
// Exclusions are runner limitations, never implementation support claims.
@@ -111,7 +119,7 @@ export function exclusion(source, meta, variant) {
if (unsupportedIncludes.length) return `harness-includes:${unsupportedIncludes.join(",")}`;
const sf = ts.createSourceFile("test.js", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
let reason;
const forbidden = new Set(["$262", "$DONE", "$DONOTEVALUATE", "globalThis", "eval", "Function", "print", "process", "require", "arguments"]);
const forbidden = new Set(["$262", "$DONE", "$DONOTEVALUATE", "globalThis", "eval", "Function", "print", "process", "require"]);
if (variant === "sloppy") for (const name of ["module", "exports", "__dirname", "__filename"]) forbidden.add(name);
if (meta.flags.includes("async")) forbidden.delete("$DONE");
const visit = (node) => {
@@ -121,6 +129,11 @@ export function exclusion(source, meta, variant) {
reason = "host:script-environment";
} else if (ts.isIdentifier(node) && forbidden.has(node.text)) {
reason = `host:${node.text}`;
} else if (ts.isIdentifier(node) && node.text === "arguments" &&
(!argumentsOwner(node) ||
!(ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node && node.parent.name.text === "length") &&
!(ts.isElementAccessExpression(node.parent) && node.parent.expression === node))) {
reason = "host:arguments";
} else if (ts.isIdentifier(node) && node.text === "assert") {
const parent = node.parent;
if (ts.isCallExpression(parent) && parent.expression === node) {
+4
View File
@@ -168,6 +168,8 @@
"test/built-ins/String/prototype/trim/15.5.4.20-2-47.js",
"test/built-ins/String/prototype/trim/15.5.4.20-2-50.js",
"test/built-ins/String/prototype/trim/15.5.4.20-2-6.js",
"test/language/arguments-object/func-decl-args-trailing-comma-null.js",
"test/language/arguments-object/func-expr-args-trailing-comma-undefined.js",
"test/language/expressions/addition/S11.6.1_A4_T1.js",
"test/language/expressions/addition/S11.6.1_A4_T2.js",
"test/language/expressions/addition/S11.6.1_A4_T3.js",
@@ -372,6 +374,8 @@
"test/built-ins/String/prototype/trim/15.5.4.20-2-47.js": "3e1a745af465177a96a29601e56299afc044060dbc2ac3061a59032be451cfde",
"test/built-ins/String/prototype/trim/15.5.4.20-2-50.js": "38b84997faa99e422408917eeac7f3575bd6064b429ea390a9d041fd77fce532",
"test/built-ins/String/prototype/trim/15.5.4.20-2-6.js": "3d5857f24117f65f07a70edd0d254dfa07f593c76effed94500847ccf8564c06",
"test/language/arguments-object/func-decl-args-trailing-comma-null.js": "80aecea8edd0d7bac1ddcfcd6cb97dc9a513b25a9283bb9cedd21fd77dd64d50",
"test/language/arguments-object/func-expr-args-trailing-comma-undefined.js": "cf39515a9031db4c81db231a157516bdc97617c392e4ef28890b2ae74777a99e",
"test/language/expressions/addition/S11.6.1_A4_T1.js": "12928eb319dcf0cc785e399580effb0b7495709296dce9c0a58e8408616a959f",
"test/language/expressions/addition/S11.6.1_A4_T2.js": "aee914241b607f56a98de04492f2d580e7bc69cca232af679d0c02b7025cc06b",
"test/language/expressions/addition/S11.6.1_A4_T3.js": "987b1c3cf66b6bbb2f6d8aaf6d1435cb1238b19132fa861a91aa2c35085d229d",
@@ -0,0 +1,43 @@
// This file was procedurally generated from the following sources:
// - src/arguments/args-trailing-comma-null.case
// - src/arguments/default/func-decl.template
/*---
description: A trailing comma after null should not increase the arguments.length (function declaration)
esid: sec-arguments-exotic-objects
flags: [generated]
info: |
9.4.4 Arguments Exotic Objects
Most ECMAScript functions make an arguments object available to their code. Depending upon the
characteristics of the function definition, its arguments object is either an ordinary object
or an arguments exotic object.
Trailing comma in the arguments list
Left-Hand-Side Expressions
Arguments :
( )
( ArgumentList )
( ArgumentList , )
ArgumentList :
AssignmentExpression
... AssignmentExpression
ArgumentList , AssignmentExpression
ArgumentList , ... AssignmentExpression
---*/
var callCount = 0;
// Stores a reference `ref` for case evaluation
function ref() {
assert.sameValue(arguments.length, 2);
assert.sameValue(arguments[0], 42);
assert.sameValue(arguments[1], null);
callCount = callCount + 1;
}
ref(42, null,);
assert.sameValue(callCount, 1, 'function invoked exactly once');
@@ -0,0 +1,44 @@
// This file was procedurally generated from the following sources:
// - src/arguments/args-trailing-comma-undefined.case
// - src/arguments/default/func-expr.template
/*---
description: A trailing comma after undefined should not increase the arguments.length (function expression)
esid: sec-arguments-exotic-objects
flags: [generated]
info: |
9.4.4 Arguments Exotic Objects
Most ECMAScript functions make an arguments object available to their code. Depending upon the
characteristics of the function definition, its arguments object is either an ordinary object
or an arguments exotic object.
Trailing comma in the arguments list
Left-Hand-Side Expressions
Arguments :
( )
( ArgumentList )
( ArgumentList , )
ArgumentList :
AssignmentExpression
... AssignmentExpression
ArgumentList , AssignmentExpression
ArgumentList , ... AssignmentExpression
---*/
var callCount = 0;
// Stores a reference `ref` for case evaluation
var ref;
ref = function() {
assert.sameValue(arguments.length, 2);
assert.sameValue(arguments[0], 42);
assert.sameValue(arguments[1], undefined);
callCount = callCount + 1;
};
ref(42, undefined,);
assert.sameValue(callCount, 1, 'function invoked exactly once');