mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-21 05:50:55 +08:00
- Preserve callback identity, receiver binding, and class references across unions and collections. - Track record field presence independently of undefined values and improve native runtime behavior. - Expand differential coverage and streamline CI bootstrap and compiler rebuild checks.
78 lines
2.8 KiB
TypeScript
78 lines
2.8 KiB
TypeScript
class Counter {
|
|
count = 0;
|
|
notify(): void { this.count++; }
|
|
callback = (n: number): number => { this.count += n; return this.count; };
|
|
}
|
|
const counter = new Counter();
|
|
counter.notify();
|
|
console.log(counter.callback(2), counter.count);
|
|
counter.callback = (n: number): number => n * 3;
|
|
console.log(counter.callback(4), counter.count);
|
|
|
|
const calls: ((n: number) => number)[] = [(n: number): number => n + 1];
|
|
let receivers = 0;
|
|
let indexes = 0;
|
|
function receiver(): ((n: number) => number)[] { receivers++; return calls; }
|
|
function index(): number { indexes++; return 0; }
|
|
function replace(): number { calls[0] = (n: number): number => n + 100; return 5; }
|
|
console.log(receiver()[index()](replace()), calls[0](5), receivers, indexes);
|
|
let effects = 0;
|
|
function effect(): number { effects++; return 1; }
|
|
try { calls[3](effect()); } catch (error) { console.log(error instanceof TypeError, effects); }
|
|
function withReceiver(this: unknown, n: number): number {
|
|
console.log(this === calls);
|
|
return n + 9;
|
|
}
|
|
calls[0] = withReceiver;
|
|
console.log(calls[0](2));
|
|
function capture(this: unknown): () => boolean { return () => this === calls; }
|
|
const captures: (() => () => boolean)[] = [capture];
|
|
const saved = captures[0]();
|
|
console.log(saved());
|
|
const captureCalls: ((same?: unknown) => () => boolean)[] = [];
|
|
function captured(this: unknown, same: unknown = this): () => boolean { return () => this === same; }
|
|
captureCalls.push(captured);
|
|
const check = captureCalls[0]();
|
|
console.log(check());
|
|
function plainReceiver(this: unknown): boolean { return this === undefined; }
|
|
function nestedReceiver(this: unknown): boolean { return plainReceiver(); }
|
|
const nestedCalls: (() => boolean)[] = [nestedReceiver];
|
|
console.log(nestedCalls[0]());
|
|
|
|
interface Callable { notify(): void; }
|
|
function replaceNamed(value: Callable): void {
|
|
value.notify = (): void => { counter.count += 10; };
|
|
}
|
|
replaceNamed(counter);
|
|
counter.notify();
|
|
console.log(counter.count);
|
|
function replaceLiteral(value: Callable): void {
|
|
value["notify"] = (): void => { counter.count += 20; };
|
|
}
|
|
replaceLiteral(counter);
|
|
counter.notify();
|
|
console.log(counter.count);
|
|
function replaceComputed(value: Callable, key: keyof Callable): void {
|
|
value[key] = (): void => { counter.count += 30; };
|
|
}
|
|
replaceComputed(counter, "notify");
|
|
counter.notify();
|
|
console.log(counter.count);
|
|
function replaceReflected(value: Callable): void {
|
|
Object.defineProperty(value, "notify", { value: (): void => { counter.count += 40; } });
|
|
}
|
|
replaceReflected(counter);
|
|
counter.notify();
|
|
console.log(counter.count);
|
|
|
|
class CallbackOwner {
|
|
value = 7;
|
|
callback = (): number => this.value;
|
|
}
|
|
const owner = new CallbackOwner();
|
|
function replaceField(value: CallbackOwner): void {
|
|
value.callback = function (this: CallbackOwner): number { return this.value + 5; };
|
|
}
|
|
replaceField(owner);
|
|
console.log(owner.callback());
|