Files
scriptc/tests/corpus/2456-private-async-methods.ts
Chris Tate f94067ec7e The #private-members chain: fields, methods, accessors, generators
- Privates ride the ordinary member maps under their unspellable spelled names; a subclass redeclaring an inherited private name is fenced, so base-chain walks ARE lexical resolution and privates never enter vtables — JS's no-dynamic-dispatch semantics by construction.
- Private GENERATOR methods compose the generator machinery with this as param 0 through the gen-spawn wrapper (the vtable problem that keeps public generator methods fenced does not exist for privates); async and generic privates ride their existing static-dispatch machinery.
- Private statics lower as module globals/functions through the declaring class's own name; subclass-named and class-value receivers fence (JS brands the declaring constructor alone).
- '#x in obj' lowers as instanceof-the-declarer: static folds at/below and disjoint, the vtable interval test when the declarer sits below the receiver's static class, and unions of decided class arms collapse to tag tests; unknown/generic/static brands fence with pointed hints.
- util.inspect omits private fields exactly like Node (an all-private class prints 'C {}'); corpus 2450-2457 pin every form differentially on both backends, diagnostics private-members pins the fences.
2026-07-23 02:42:10 -05:00

41 lines
1.5 KiB
TypeScript

// Async #private methods: the body is an async IrFunction entered through its fiber spawn wrapper with `this` as param 0 — dispatch was already static for privates, so the async-method machinery composes unchanged. Await chains through private helpers, private async calling private sync AND a private generator, and interleaved instances all match Node's ordering.
class Pipeline {
#name: string;
#stages: string[] = [];
constructor(name: string) {
this.#name = name;
}
#stamp(s: string): string {
this.#stages.push(s);
return `${this.#name}.${s}`;
}
async #fetch(key: string): Promise<string> {
return this.#stamp(`fetch(${key})`);
}
async #transform(raw: string): Promise<string> {
const upper = raw.toUpperCase();
return this.#stamp("transform") + ":" + upper;
}
*#audit(): Generator<string, void, undefined> {
for (const s of this.#stages) yield s;
}
async run(key: string): Promise<string> {
const raw = await this.#fetch(key);
const out = await this.#transform(raw);
let audit = "";
for (const s of this.#audit()) audit += `[${s}]`;
return `${out} ${audit}`;
}
}
async function main(): Promise<void> {
const p1 = new Pipeline("p1");
const p2 = new Pipeline("p2");
console.log(await p1.run("a"));
console.log(await p2.run("b"));
// Interleaving: both fibers started before either awaits completion.
const [c, d] = await Promise.all([p1.run("c"), p2.run("d")]);
console.log(c);
console.log(d);
}
void main();