mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-22 05:59:31 +08:00
- Keep generic bindings and short-circuit writes scoped to their native execution context. - Compile Map and Set copies, tuple callbacks and searches, and string-pattern replacement. - Exercise production frontend registries without Node and preserve mutation, identity, and evaluation order.
97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
export {};
|
|
|
|
let effects = "";
|
|
function rhs(value: number): number { effects += "R"; return value; }
|
|
let number = 0;
|
|
console.log(number &&= rhs(1), number, effects);
|
|
console.log(number ||= rhs(2), number, effects);
|
|
console.log(number ||= rhs(3), number, effects);
|
|
console.log(number &&= rhs(4), number, effects);
|
|
number = NaN;
|
|
console.log(number ||= rhs(5), number, effects);
|
|
number = -0;
|
|
console.log(number &&= rhs(6), Object.is(number, -0), effects);
|
|
|
|
let text = "";
|
|
console.log(text ||= "filled", text);
|
|
console.log(text &&= "changed", text);
|
|
let flag = false;
|
|
console.log(flag &&= true, flag);
|
|
console.log(flag ||= true, flag);
|
|
console.log(flag &&= false, flag);
|
|
|
|
function optional(value: string | undefined): string | undefined {
|
|
value &&= "changed";
|
|
console.log("and", value);
|
|
value ||= "default";
|
|
return value;
|
|
}
|
|
console.log(optional(undefined), optional(""), optional("present"));
|
|
|
|
// Evaluation of the reference precedes its single read. The setter runs
|
|
// only when the selected branch actually assigns, and the result is the
|
|
// RHS value even when the setter stores a different value.
|
|
class Cell {
|
|
stored = 0;
|
|
get value(): number { effects += "G"; return this.stored; }
|
|
set value(value: number) { effects += "S"; this.stored = value + 10; }
|
|
}
|
|
const cell = new Cell();
|
|
function receiver(): Cell { effects += "O"; return cell; }
|
|
effects = "";
|
|
console.log(receiver().value &&= rhs(1), cell.stored, effects);
|
|
effects = "";
|
|
console.log(receiver().value ||= rhs(2), cell.stored, effects);
|
|
effects = "";
|
|
console.log(receiver().value ||= rhs(3), cell.stored, effects);
|
|
effects = "";
|
|
console.log(receiver().value &&= rhs(4), cell.stored, effects);
|
|
|
|
const values = [0, 2];
|
|
function array(): number[] { effects += "A"; return values; }
|
|
function key(value: number): number { effects += "K"; return value; }
|
|
effects = "";
|
|
console.log(array()[key(0)] ||= rhs(7), values[0], effects);
|
|
effects = "";
|
|
console.log(array()[key(1)] &&= rhs(8), values[1], effects);
|
|
effects = "";
|
|
console.log(array()[key(9)] &&= rhs(9), values.length, effects);
|
|
effects = "";
|
|
console.log(array()[key(9)] ||= rhs(10), values.length, effects);
|
|
|
|
// The receiver remains the one evaluated before the RHS changes its alias.
|
|
let active = [0];
|
|
const original = active;
|
|
function replace(): number { active = [20]; return 30; }
|
|
console.log(active[0] ||= replace(), original[0], active[0]);
|
|
|
|
function captured(): void {
|
|
let value = "";
|
|
const fill = (): string => value ||= "capture";
|
|
console.log(fill(), fill(), value);
|
|
}
|
|
captured();
|
|
|
|
function fail(): number { effects += "T"; throw new Error("rhs"); }
|
|
let preserved = 0;
|
|
effects = "";
|
|
try { preserved ||= fail(); }
|
|
catch (error) { if (error instanceof Error) console.log(error.message); }
|
|
console.log(preserved, effects);
|
|
preserved = 2;
|
|
effects = "";
|
|
console.log(preserved ||= fail(), effects);
|
|
|
|
// A forward captured binding still checks TDZ before deciding whether to
|
|
// evaluate the RHS. Neither logical operator can initialize its empty box.
|
|
function forward(): void {
|
|
const write = (): void => { value ||= rhs(40); };
|
|
effects = "";
|
|
try { write(); }
|
|
catch (error) { if (error instanceof Error) console.log(error.name, effects); }
|
|
let value = 0;
|
|
write();
|
|
console.log(value, effects);
|
|
}
|
|
forward();
|