// The lib-fence battery: everything here TYPECHECKS against the real // standard library (es2023) — the old minimal-ambient world rejected most // of it with "Cannot find name" — and every statement must terminate in a // clean lowering diagnostic (SC2020 for surface with no lowering, a // specific fence otherwise). Never an ICE, never a silent mis-lowering. // Globals as values and calls. (Symbol(desc) itself LOWERS now — the // symbol battery lives in the corpus; what stays fenced is the well-known // surface below.) const iter = Symbol.iterator; const g = globalThis; const nan = NaN; // lowers now — a non-finite numeric literal like Infinity const s5 = String(5); const n5 = Number.NaN; // lowers now, with the other Number constants const isArr = Array.isArray([1]); const merged = Object.assign({}, { a: 1 }); // the empty-target literal-source shape lowers now (it IS the source literal) const aliasedAssign = Object.assign(merged, { b: 2 }); // aliased targets stay fenced (real mutation of a live object) const refl = Reflect.has({ a: 1 }, "a"); const parsedMs = Date.parse; const fmt = new Intl.NumberFormat(); // Constructors. const d = new Date(2024, 0); // the local-time year/month field constructor stays fenced const mutableDate = new Date(0); mutableDate.setUTCFullYear(2024); // mutation is outside the read-only Date slice const sameDate = mutableDate === mutableDate; // scalar storage must not fake object identity const wr = new WeakRef({}); const px = new Proxy({ a: 1 }, {}); const buf = new ArrayBuffer(8); 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.) const agg = new AggregateError([]); const stack = new Error("boom").stack; // Unlowered members on lowered containers. const sinhMethod = Math.sinh; // fixed-arity Math function values now lower // (n-ary Math.min/max LOWER now — the variadic battery lives in the // corpus; the mixed spread/positional list is the form that stays fenced.) const clamped = Math.min(1, ...[2, 3]); const entries = [1, 2].entries(); const arrAt = [1, 2].at(0); const norm = "abc".normalize(); const limited = "a,b,c".split(Math.random() ? "," : /,/, 2); // union separators stay fenced; limits lower const fixed = (1.5).toFixed(); // digit-free toFixed lowers now (the static ties-up integer) const localized = (1234.5).toLocaleString(); // Unlowered call FORMS of lowered members. (push is fully variadic now — // no fenced form remains to pin.) const nums = [1, 2, 3]; const found = nums.indexOf(2, 1); // the fromIndex overload lowers const joined = nums.join(); // the omitted separator lowers nums.forEach((x) => console.log(x), { unused: true }); // thisArg stays fenced const pos = "abc".includes("b", 1); // the position form lowers now (indexOf's clamp) const rev = JSON.parse("1", (_k, v) => v); // (stringify with a null replacer + LITERAL space now lowers — the pretty // battery lives in the corpus; function replacers and non-literal spaces // stay fenced.) const toStringify = { a: 1 }; const replaced = JSON.stringify(toStringify, (_k, v) => v); const width = 2; const spaced = JSON.stringify(toStringify, null, width); // The promise surface beyond await. async function work(): Promise { return 1; } const thened = work().then((v) => v + 1, () => 0); const caught = work().catch(() => 0); const resolved = Promise.resolve(1); // Object.is lowers over one comparable kind; the unlowered forms fence // by name — a validate-first dynamic operand and partially-overlapping // unions needing narrowing. const dynIs = Object.is(JSON.parse("1") as unknown, 1); function pick(a: string | number, b: number | boolean): boolean { return Object.is(a, b); // partially-overlapping unions: narrow first } const picked = pick(1, 2); // Date values deliberately have no tagged-union payload yet. Nullable // Date positions must fence in the frontend instead of reaching a backend // scalar/ref mismatch. function optionalDate(value: Date | undefined): number { return value === undefined ? -1 : value.getTime(); } optionalDate(undefined); function throwDate(): void { throw new Date(0); // the exception cell cannot preserve Date's object kind } throwDate(); function* dateGenerator(): Generator { yield 1; } dateGenerator().throw(new Date(0)); // End of the diagnostic fixture.