From ca579641a45bebcd629b2081b101233613375596 Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Thu, 22 Oct 2026 10:04:30 -0500 Subject: [PATCH] Index quoted get: and set: method names under their own keys --- .../lowering/class-dynamic-dispatch.ts | 13 +++++----- .../class-quoted-accessor-keys.mjs.json | 6 +++++ tests/corpus/class-quoted-accessor-keys.mjs | 26 +++++++++++++++++++ .../class-quoted-accessor-keys.mjs.json | 1 + 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 packages/compiler/test/ts7/baselines/order-parity/tests/corpus/class-quoted-accessor-keys.mjs.json create mode 100644 tests/corpus/class-quoted-accessor-keys.mjs create mode 100644 tests/harness/corpus-costs/class-quoted-accessor-keys.mjs.json diff --git a/packages/compiler/src/frontend/lowering/class-dynamic-dispatch.ts b/packages/compiler/src/frontend/lowering/class-dynamic-dispatch.ts index 79deb2aeb..e792de957 100644 --- a/packages/compiler/src/frontend/lowering/class-dynamic-dispatch.ts +++ b/packages/compiler/src/frontend/lowering/class-dynamic-dispatch.ts @@ -477,7 +477,7 @@ interface ReceiverIndex { /** By a method or generic method its base chain declares. */ methods: Map; /** By a method, generic method or accessor its base chain declares (an - * accessor under its property name), or a field it has. */ + * accessor under its key and under its property name), or a field it has. */ members: Map; rooted: number[]; } @@ -504,11 +504,12 @@ function receiverIndex(lowerer: Lowerer, plans: readonly PropertyReceiver[]): Re for (let c: ClassInfo | null = info; c; c = c.base) { for (const name of c.methods.keys()) { add(methods, name, position); - add( - members, - name.startsWith("get:") || name.startsWith("set:") ? name.slice(4) : name, - position, - ); + // A `get:`/`set:` key is an accessor of the property after the + // prefix, or a method whose quoted name has that prefix; the test + // looks up both. + add(members, name, position); + if (name.startsWith("get:") || name.startsWith("set:")) + add(members, name.slice(4), position); } if (c.genericMethods) for (const name of c.genericMethods.keys()) { diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/class-quoted-accessor-keys.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/class-quoted-accessor-keys.mjs.json new file mode 100644 index 000000000..234634ebd --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/class-quoted-accessor-keys.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/class-quoted-accessor-keys.mjs" + ], + "diags": [] +} diff --git a/tests/corpus/class-quoted-accessor-keys.mjs b/tests/corpus/class-quoted-accessor-keys.mjs new file mode 100644 index 000000000..637300b43 --- /dev/null +++ b/tests/corpus/class-quoted-accessor-keys.mjs @@ -0,0 +1,26 @@ +// Methods whose quoted names begin with "get:" or "set:", next to an +// accessor of the property after the prefix, read and called through +// untyped values. +class Quoted { + "get:size"() { + return "method get:size"; + } + "set:size"(value) { + return `method set:size ${value}`; + } + get size() { + return 3; + } +} +class Sized { + constructor() { + this.size = 5; + } +} +const values = [new Quoted(), new Sized(), { "get:size": () => "record get:size", size: 1 }]; +for (const value of values) { + const getter = value["get:size"]; + console.log(typeof getter, getter?.call(value)); + console.log(typeof value["set:size"], value.size); + if (value instanceof Quoted) console.log(value["get:size"](), value["set:size"](7)); +} diff --git a/tests/harness/corpus-costs/class-quoted-accessor-keys.mjs.json b/tests/harness/corpus-costs/class-quoted-accessor-keys.mjs.json new file mode 100644 index 000000000..81da85b90 --- /dev/null +++ b/tests/harness/corpus-costs/class-quoted-accessor-keys.mjs.json @@ -0,0 +1 @@ +{ "plain": 3900, "san": 4000 }