Admit receiver-bound this in static Test262 scripts (#495)

* Admit receiver-bound this in static Test262 scripts

* Refresh Set seed diagnostic snapshot
This commit is contained in:
Chris Tate
2026-09-27 15:36:42 -05:00
committed by GitHub
parent d714819bbf
commit 13234396c2
8 changed files with 242 additions and 11 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ const sameDate = mutableDate === mutableDate; // scalar storage must not fake ob
const wm = new WeakMap();
const px = new Proxy({ a: 1 }, {});
const buf = new ArrayBuffer(8);
const st = new Set(new Set([1, 2])); // array seeds lower; Set/iterable seeds stay fenced
const st = new Set(new Set([1, 2])); // string and array seeds lower; Set-valued seeds stay fenced
// (new Error / TypeError / RangeError / SyntaxError now LOWER — the error
// battery lives in the corpus; what stays fenced is the rest of the family
// and the unlowered members of lowered error objects.)
@@ -114,7 +114,7 @@ stdlib-fence.ts:29:7 - error SC2020: 'ArrayBuffer' is part of the standard libra
28 | const px = new Proxy({ a: 1 }, {});
29 | const buf = new ArrayBuffer(8);
| ^~~
30 | const st = new Set(new Set([1, 2])); // array seeds lower; Set/iterable seeds stay fenced
30 | const st = new Set(new Set([1, 2])); // string and array seeds lower; Set-valued seeds stay fenced
hint: no free-standing ArrayBuffer value exists — typed arrays own their storage (new Uint8Array(n) allocates; new Uint8Array(new ArrayBuffer(n)) erases the buffer into the view)
@@ -123,18 +123,18 @@ stdlib-fence.ts:29:13 - error SC2020: 'new ArrayBuffer' is part of the standard
28 | const px = new Proxy({ a: 1 }, {});
29 | const buf = new ArrayBuffer(8);
| ^~~~~~~~~~~~~~~~~~
30 | const st = new Set(new Set([1, 2])); // array seeds lower; Set/iterable seeds stay fenced
30 | const st = new Set(new Set([1, 2])); // string and array seeds lower; Set-valued seeds stay fenced
hint: no free-standing ArrayBuffer value exists — typed arrays own their storage: allocate the view directly (new Uint8Array(n)), or erase a fresh buffer into one (new Uint8Array(new ArrayBuffer(n)), new DataView(new ArrayBuffer(n), ...))
stdlib-fence.ts:30:12 - error SC2020: 'new Set(values)' is part of the standard library types but has no scriptc lowering yet
29 | const buf = new ArrayBuffer(8);
30 | const st = new Set(new Set([1, 2])); // array seeds lower; Set/iterable seeds stay fenced
30 | const st = new Set(new Set([1, 2])); // string and array seeds lower; Set-valued seeds stay fenced
| ^~~~~~~~~~~~~~~~~~~~~~~~
31 | // (new Error / TypeError / RangeError / SyntaxError now LOWER — the error
hint: construct the Set empty and add() each value — only an array or fixed tuple of already-legal elements (string or number) seeds a Set
hint: construct the Set empty and add() each value — only a string, array, or fixed tuple of already-legal elements (string or number) seeds a Set
stdlib-fence.ts:34:7 - error SC2020: 'AggregateError' is part of the standard library types but has no scriptc lowering yet
+20 -1
View File
@@ -47,13 +47,32 @@ test("unsupported execution requirements and assertion reflection remain exclusi
expect(exclusion(text, metadata(text), "strict")).toBeUndefined();
expect(exclusion(text, metadata(text), "sloppy")).toBeUndefined();
const scriptGlobal = source("description: script global", "assert.sameValue((function () { return this; })(), globalThis);");
expect(exclusion(scriptGlobal, metadata(scriptGlobal), "sloppy")).toBe("host:script-environment");
expect(exclusion(scriptGlobal, metadata(scriptGlobal), "sloppy")).toBe("host:globalThis");
const commonJsGlobal = source("description: CommonJS global", "assert.sameValue(module.exports, {});");
expect(exclusion(commonJsGlobal, metadata(commonJsGlobal), "sloppy")).toBe("host:module");
const asyncText = source("flags: [async]", "Promise.resolve().then(() => $DONE());");
expect(exclusion(asyncText, metadata(asyncText), "strict")).toBeUndefined();
});
test("receiver-bound this is admitted without adapting script-level this", () => {
for (const [body, expected] of [
["class C { read() { return this.value; } }", undefined],
["class C { read() { return () => this.value; } }", undefined],
["class C { value = this; }", undefined],
["class C { static { this.value = 1; } }", undefined],
["function read() { return this; }", undefined],
["const read = () => this;", "host:script-environment"],
["assert.sameValue(this, undefined);", "host:script-environment"],
["class C { [this.key]() {} }", "host:script-environment"],
["class C extends this.Base {}", "host:script-environment"],
] as const) {
const text = source("description: this binding", body);
for (const variant of ["strict", "sloppy"] as const) {
expect(exclusion(text, metadata(text), variant), `${variant}: ${body}`).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();
+13 -5
View File
@@ -84,6 +84,17 @@ export function variants(meta) {
return ["sloppy", "strict"];
}
function hasOwnThisBinding(node) {
let child = node;
for (let parent = node.parent; parent; child = parent, parent = parent.parent) {
if (ts.isArrowFunction(parent)) continue;
if (ts.isFunctionLike(parent) && child === parent.body) return true;
if (ts.isPropertyDeclaration(parent) && child === parent.initializer) return true;
if (ts.isClassStaticBlockDeclaration(parent) && child === parent.body) return true;
}
return false;
}
// 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.
@@ -105,11 +116,8 @@ export function exclusion(source, meta, variant) {
if (meta.flags.includes("async")) forbidden.delete("$DONE");
const visit = (node) => {
if (reason) return;
if (variant === "sloppy" && node.kind === ts.SyntaxKind.ThisKeyword) {
reason = "host:script-environment";
return;
}
if (node.kind === ts.SyntaxKind.ThisKeyword || node.kind === ts.SyntaxKind.ImportKeyword || ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
if ((node.kind === ts.SyntaxKind.ThisKeyword && !hasOwnThisBinding(node)) ||
node.kind === ts.SyntaxKind.ImportKeyword || ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
reason = "host:script-environment";
} else if (ts.isIdentifier(node) && forbidden.has(node.text)) {
reason = `host:${node.text}`;
+6
View File
@@ -176,6 +176,9 @@
"test/language/expressions/class/elements/fields-string-name-propname-constructor.js",
"test/language/expressions/function/dflt-params-duplicates.js",
"test/language/statements/class/class-name-ident-static.js",
"test/language/statements/class/elements/private-accessor-name/inst-private-name-ZWNJ.js",
"test/language/statements/class/elements/private-field-as-arrow-function.js",
"test/language/statements/class/elements/regular-definitions-rs-privatename-identifier-initializer.js",
"test/language/statements/const/dstr/ary-ptrn-elem-ary-elem-init.js",
"test/language/statements/const/dstr/ary-ptrn-elem-id-init-exhausted.js",
"test/language/statements/const/dstr/ary-ptrn-elem-id-init-fn-name-arrow.js",
@@ -370,6 +373,9 @@
"test/language/expressions/class/elements/fields-string-name-propname-constructor.js": "70bce532b9f18d8795e9ea5d640bdd063004ce873d614cca05d8071aa615a605",
"test/language/expressions/function/dflt-params-duplicates.js": "243c05deb19b7d54a13d4f69059a8fb8d55911f066b5cc0ae14cfc41503c28ae",
"test/language/statements/class/class-name-ident-static.js": "04d24cb0b646cf244fdde005cf3c6ecf6ae82897265ab3e1fe5cab7a4d6f6a64",
"test/language/statements/class/elements/private-accessor-name/inst-private-name-ZWNJ.js": "32add15642ac1c1f8867fd66e72f2643d78aa0abcecc1a92d1467c710ee3f425",
"test/language/statements/class/elements/private-field-as-arrow-function.js": "1f1816c812604cc4aa23446b063bae8858287646ec43df4cfd076f11510ec6a1",
"test/language/statements/class/elements/regular-definitions-rs-privatename-identifier-initializer.js": "a9920a5506cadfef3ad399bb07826345913df62e7f73616f4024df82bbeffbf1",
"test/language/statements/const/dstr/ary-ptrn-elem-ary-elem-init.js": "00f23ce81293acc6bd718a5a0de431928ed18db45c7ce849a0f76c365bc1ec9a",
"test/language/statements/const/dstr/ary-ptrn-elem-id-init-exhausted.js": "73e765928b855ea0f89bd159a317ec212179260523d444e38b3518c8ac6c1681",
"test/language/statements/const/dstr/ary-ptrn-elem-id-init-fn-name-arrow.js": "086210fc19498dad9b760b90398a3b46b366f3c4d4ee184200136641752ba832",
@@ -0,0 +1,78 @@
// This file was procedurally generated from the following sources:
// - src/accessor-names/private-name-ZWNJ.case
// - src/accessor-names/private/cls-private-decl-inst.template
/*---
description: Private IdentifierName - ZWNJ (Class declaration, private instance method)
features: [class, class-methods-private]
flags: [generated]
info: |
ClassElement :
MethodDefinition
static MethodDefinition
FieldDefinition ;
;
FieldDefinition :
ClassElementName Initializer _opt
ClassElementName :
PropertyName
PrivateName
PrivateName ::
# IdentifierName
Initializer :
= AssignmentExpression
IdentifierName ::
IdentifierStart
IdentifierName IdentifierPart
IdentifierStart ::
UnicodeIDStart
$
_
\ UnicodeEscapeSequence
IdentifierPart::
UnicodeIDContinue
$
\ UnicodeEscapeSequence
<ZWNJ> <ZWJ>
UnicodeIDStart::
any Unicode code point with the Unicode property "ID_Start"
UnicodeIDContinue::
any Unicode code point with the Unicode property "ID_Continue"
NOTE 3
The sets of code points with Unicode properties "ID_Start" and
"ID_Continue" include, respectively, the code points with Unicode
properties "Other_ID_Start" and "Other_ID_Continue".
---*/
var stringSet;
class C {
get #ZW_‌_NJ() { return 'get string'; }
set #ZW_‌_NJ(param) { stringSet = param; }
getPrivateReference() {
return this.#ZW_‌_NJ;
}
setPrivateReference(value) {
this.#ZW_‌_NJ = value;
}
};
var inst = new C();
assert.sameValue(inst.getPrivateReference(), 'get string');
inst.setPrivateReference('set string');
assert.sameValue(stringSet, 'set string');
@@ -0,0 +1,33 @@
// This file was procedurally generated from the following sources:
// - src/class-elements/private-field-as-arrow-function.case
// - src/class-elements/default/cls-decl.template
/*---
description: Calling arrow function returned from private field access (field definitions in a class declaration)
esid: prod-FieldDefinition
features: [class-fields-private, arrow-function, class]
flags: [generated]
info: |
Updated Productions
CallExpression[Yield, Await]:
CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
SuperCall[?Yield, ?Await]
CallExpression[?Yield, ?Await]Arguments[?Yield, ?Await]
CallExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]]
CallExpression[?Yield, ?Await].IdentifierName
CallExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await]
CallExpression[?Yield, ?Await].PrivateName
---*/
class C {
#m = () => 'test262';
method() {
return this.#m();
}
}
let c = new C();
assert.sameValue(c.method(), 'test262');
@@ -0,0 +1,87 @@
// This file was procedurally generated from the following sources:
// - src/class-elements/rs-privatename-identifier-initializer.case
// - src/class-elements/productions/cls-decl-regular-definitions.template
/*---
description: Valid PrivateName (regular fields defintion)
esid: prod-FieldDefinition
features: [class-fields-private, class, class-fields-public]
flags: [generated]
info: |
ClassElement :
MethodDefinition
static MethodDefinition
FieldDefinition ;
;
FieldDefinition :
ClassElementName Initializer _opt
ClassElementName :
PropertyName
PrivateName
PrivateName ::
# IdentifierName
IdentifierName ::
IdentifierStart
IdentifierName IdentifierPart
IdentifierStart ::
UnicodeIDStart
$
_
\ UnicodeEscapeSequence
IdentifierPart::
UnicodeIDContinue
$
\ UnicodeEscapeSequence
<ZWNJ> <ZWJ>
UnicodeIDStart::
any Unicode code point with the Unicode property "ID_Start"
UnicodeIDContinue::
any Unicode code point with the Unicode property "ID_Continue"
NOTE 3
The sets of code points with Unicode properties "ID_Start" and
"ID_Continue" include, respectively, the code points with Unicode
properties "Other_ID_Start" and "Other_ID_Continue".
---*/
class C {
#$ = 1; #_ = 1; #\u{6F} = 1; #\u2118 = 1; #ZW_\u200C_NJ = 1; #ZW_\u200D_J = 1
$() {
return this.#$;
}
_() {
return this.#_;
}
\u{6F}() {
return this.#\u{6F};
}
\u2118() {
return this.#\u2118;
}
ZW_\u200C_NJ() {
return this.#ZW_\u200C_NJ;
}
ZW_\u200D_J() {
return this.#ZW_\u200D_J;
}
}
var c = new C();
assert.sameValue(c.$(), 1);
assert.sameValue(c._(), 1);
assert.sameValue(c.\u{6F}(), 1);
assert.sameValue(c.\u2118(), 1);
assert.sameValue(c.ZW_\u200C_NJ(), 1);
assert.sameValue(c.ZW_\u200D_J(), 1);