Merge main

This commit is contained in:
Chris Tate
2026-10-30 03:40:32 -05:00
1032 changed files with 44893 additions and 2937 deletions
+4 -4
View File
@@ -1,7 +1,7 @@
// The assert surface's honest fences: loose deep equality over recursive
// types (equal/notEqual, deepEqual/notDeepEqual and assert/strict's aliases lower),
// reference-equality strictEqual on objects,
// union operands (narrow first), mismatched or uncomparable deep types
// reference-equality strictEqual on objects, union operands with object
// arms (narrow first), mismatched or uncomparable deep types
// (typed arrays, class instances), namespace-object calls, unsupported
// throws/rejects expectations (properties outside the static error
// surface, empty shapes, non-literal objects, doesNotReject shapes —
@@ -19,9 +19,9 @@ assert.notDeepEqual([1], [2]);
const box = { n: 1 };
assert.strictEqual(box, box); // reference equality — deepStrictEqual hint
let maybe: string | undefined = "x";
let maybe: { n: number } | undefined = box;
if ("x".length === 0) maybe = undefined;
assert.strictEqual(maybe, "x"); // union operand — narrow first
assert.strictEqual(maybe, box); // union operand with an object arm — narrow first
const unk: unknown = JSON.parse("{}");
assert.strictEqual(unk, { n: 1 }); // strict + composite static side: reference identity does not survive the unknown boundary
@@ -0,0 +1,11 @@
// Builtins without a lowered value refuse at compile time in TypeScript,
// including as object literal members.
function take(x: unknown): unknown {
return x;
}
const inferred = { json: JSON };
const loose: any = { intl: Intl, proxy: Proxy };
const timers: Record<string, unknown> = { setTimeout };
const list: any[] = [Array, parseInt];
console.log(inferred, loose, timers, list, take(process));
+4 -2
View File
@@ -1,5 +1,7 @@
// Unsupported formatters must reach the Date method diagnostic, including
// names inherited from Object.prototype by the compiler's dispatch table.
// The default-locale toLocaleString()/toLocaleTimeString() lower now
// (scr_intl.c); a locale or options argument still has none.
const date = new Date(0);
date.toLocaleTimeString();
date.toLocaleString();
date.toLocaleDateString();
date.toLocaleString("en-US");
+3 -3
View File
@@ -6,10 +6,10 @@
// trim/pad variants, parseInt, isNaN, the global parseFloat/isFinite and
// Number.parseFloat/Number.parseInt over exactly-typed arguments,
// string-pattern replacement and toPrecision compile statically now and no
// longer appear here; toLocaleString without a locale still has no
// lowering.)
// longer appear here; toLocaleString at an explicit non-en-US locale still
// has no lowering (the default-locale form lowers over ICU).)
const up = Math.cbrt(2);
const tau = Math.PI * 2;
const price = (19.99).toLocaleString();
const price = (19.99).toLocaleString("de-DE");
const n = Number.parseFloat("3.14");
void n;
@@ -1,6 +0,0 @@
import { EventEmitter } from "node:events";
const emitter = new EventEmitter();
const suffix = process.argv[2] ?? "x";
emitter.on(`topic:${suffix}`, () => {});
emitter.listeners("topic:x");
@@ -0,0 +1,25 @@
// Declared-arity narrowing: a function value stored under a type that names
// FEWER parameters than the value's own signature. Node's function object
// still carries every parameter, so a later widened call would pass all of
// its arguments (the surplus must not be dropped); a compiled function value
// is one concrete native ABI, so the narrowing store is refused at every
// observable use instead.
const impl = (text: string, times: number) => text.length * times;
// (1) Narrowing at a binding, then calling through the narrow type.
const narrowed = impl as unknown as (text: string) => number;
console.log(narrowed("abc"));
// (2) The same narrowing in an object literal's member slot, with the member
// read back and widened to the implementation's arity.
interface Sink {
write(text: string): number;
}
function makeWriter(): Sink {
return { write: impl as unknown as (text: string) => number };
}
const sink = makeWriter();
const widened = sink.write as (text: string, times: number) => number;
console.log(widened("abcd", 3));
+14 -3
View File
@@ -19,14 +19,25 @@ console.log(typeof stored);
const flipAlias = flip;
console.log(flipAlias(5));
// Declared inside a function and reading its parameter: instances are
// module functions and cannot capture the enclosing frame.
// Declared inside a function and reading a binding declared AFTER it: a
// call could run before the binding's initializer (a temporal dead zone).
// (Bindings declared before it are supported — copied as trailing
// parameters, or shared through a closure environment when reassigned.)
function outer(base: number): number {
const inner = <T>(x: T): [T, number] => [x, base];
const inner = <T>(x: T): [T, number] => [x, scale];
const scale = base + 1;
return inner(3)[1];
}
console.log(outer(4));
// Declared inside a GENERIC function: the enclosing frame re-lowers per
// instantiation, so the shared instance cannot carry its type argument.
function outerGeneric<U>(seed: U): string {
const inner = <T>(x: T): string => `${String(x)}${String(seed)}`;
return inner(3);
}
console.log(outerGeneric<number>(1));
// Used as a value inside a function: each call of the enclosing function
// makes a new function object (`make() !== make()`), and the compiled
// instances are shared module functions.
+4 -2
View File
@@ -1,5 +1,7 @@
// The native implementation covers Unicode grapheme segmentation.
// The native implementation covers Unicode grapheme segmentation, and ICU
// answers word segmentation; locale negotiation over several tags and
// sentence segmentation stay fenced.
new Intl.Segmenter(["en-US", "de"]);
new Intl.Segmenter(undefined, { granularity: "word" });
new Intl.Segmenter(undefined, { granularity: "word", localeMatcher: "best fit" });
new Intl.Segmenter(undefined, { granularity: "sentence" });
// End of the diagnostic fixture.
+3 -4
View File
@@ -1,8 +1,8 @@
// The Intl surface. What lowers: the COMPOSED en-US NumberFormat forms
// with default options — new Intl.NumberFormat("en-US").format(x) and
// x.toLocaleString("en-US"). Everything else fences by NAME: the
// environment-default locale a compiled binary cannot carry, other
// locales (ICU data the binary does not embed), options bags, formatter
// x.toLocaleString("en-US") — plus the default locale's own forms over ICU
// (x.toLocaleString(), d.toLocaleString()). Everything else fences by
// NAME: other locales (ICU locale negotiation), options bags, formatter
// VALUES, and the rest of the Intl namespace (DurationFormat,
// DateTimeFormat, PluralRules, getCanonicalLocales).
@@ -14,7 +14,6 @@ const hoisted = new Intl.NumberFormat("en-US");
const viaValue = hoisted.format(1234.5);
// toLocaleString's unlowered variants.
const envDefault = (1234.5).toLocaleString();
const german = (1234.5).toLocaleString("de-DE");
const grouped = (1234.5).toLocaleString("en-US", { useGrouping: false });
@@ -0,0 +1,18 @@
// ECMAScript early errors the TypeScript checker does not model: a statement
// list may not declare one lexical name twice, and a lexical name may not be
// `var`-declared in the same list (Block : { StatementList }, and a switch's
// case block is one such list). Both are SC0005/SC0006, reported at
// preflight — the constructs come from Test262's negative-parse suites.
{
class collide {}
async function collide() {}
}
switch (1) {
case 1:
let scoped = 1;
break;
case 2:
var scoped = 2;
break;
}
@@ -0,0 +1,10 @@
// ECMAScript early errors the TypeScript checker does not model: the body of
// a loop, a `with` statement, or an if clause admits only a Statement, and
// Annex B's function-declaration allowance never covers an async function, a
// generator, a class, or a lexical declaration. SC0007, reported at
// preflight — the shapes come from Test262's negative-parse suites.
while (false) function inLoop() {}
l: class inLabel {}
if (true) async function inIf() {}
if (false) il: function labelledInIf() {}
do function* inDoWhile() {} while (false);
@@ -0,0 +1,8 @@
// The strict half of SC0007: Annex B's allowance for a plain function
// declaration in an if/else body or a labelled statement is non-strict code
// only, so a "use strict" prologue takes it away — Node agrees on both
// shapes. The sloppy fixture beside this one pins the refusals that hold in
// both modes.
"use strict";
if (true) function inIf() {}
l: function inLabel() {}
@@ -0,0 +1,20 @@
// Patching a NATIVE host object: Node lets a library swap
// `process.stdout.write`, hand out `process.stdout.write.bind(...)`, or
// redefine a module member with Object.defineProperty. The process output
// stream's write slot is the runtime stream object's, so the assignment and
// the bind compile. A builtin module's exports are direct calls, so those
// forms keep an explicit refusal instead of silently patching nothing. The
// working split: use the module's functions directly.
import * as fs from "node:fs";
export function bindReadFileSync(): typeof fs.readFileSync {
return fs.readFileSync.bind(fs);
}
export function defineReadFileSync(): void {
Object.defineProperty(fs, "readFileSync", { value: () => "" });
}
bindReadFileSync();
defineReadFileSync();
@@ -0,0 +1,5 @@
// Drain registration on the process streams lowers to nothing because a
// synchronous write never asks for a drain; the listener table it would
// fill is not observable, so reading it stays refused.
process.stdout.once("drain", () => {});
console.log(process.stdout.listenerCount("drain"));
+3 -3
View File
@@ -12,9 +12,9 @@ const loose: Loose = { a: 1 };
const picked: PickedA = loose;
console.log(picked);
// A method field whose parameter shapes relate only BIVARIANTLY: neither
// parameter type converts into the other mechanically, so the field does
// not lift.
// A method field whose parameter shapes relate only BIVARIANTLY: the field
// lifts as a checked adapter, so only the console.log below refuses (a
// function value has no inspect lowering).
type SrcM = { m(x: { a: number }): void; extra: number };
type DstM = { m(x: { a: number; b: number }): void };
const srcM: SrcM = {
@@ -0,0 +1,6 @@
// A sloppy-mode implicit-global WRITE in a JavaScript source. Node resolves
// the write by creating a property on the global object — process-wide state
// a native binary has none of — so the write is refused by name (SC1091) and
// names the Node-island route the sloppy semantics need (plan D-2/D-5).
implicitGlobal = 42;
console.log(implicitGlobal);
+1 -1
View File
@@ -38,7 +38,7 @@ 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();
const localized = (1234.5).toLocaleString("de-DE");
// Unlowered call FORMS of lowered members. (push is fully variadic now —
// no fenced form remains to pin.)
const nums = [1, 2, 3];