Files
scriptc/tests/diagnostics/assert-fences.ts
T
Chris Tate f521dc91b1 Compile three Node test shapes: a top-level return before declarations, nullable strictEqual operands, and a branch-assigned let
A top-level return in a CommonJS module compiles when declarations follow
it. When the return is taken, only code that already exists can observe the
bindings it skips: functions and classes created before the return, and
function declarations after it. A module where one of them reads a binding
declared after the return, or that assigns exports after it, still stops
with SC1090.

assert.strictEqual and assert.notStrictEqual compare a nullable number,
string or boolean (`number | null`, `string | null`) with a scalar, null or
undefined through the checked-dynamic SameValue compare, which reports
Node's failure messages. notStrictEqual of another nullable value, such as
`child.stdin`, against null or undefined tests the value's tag.

An initializer-less JavaScript `let` whose writes all agree also takes
their type when the writes are calls declared in the standard library, such
as `spawn(...)`, and at file scope. A runtime handle that a closure
captures takes the handle or undefined. Inside a nested function, a member
read on it (`c.address()`, `child.stdin`) reads the handle and throws
Node's TypeError while the binding is still undefined; other reads there
take the checked-dynamic value.
2026-10-29 20:51:09 -05:00

59 lines
3.0 KiB
TypeScript

// 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 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 —
// Node's own TypeError), ifError over uncomparable types, and assert.throws
// as a value. Every reached site terminates in a named
// diagnostic — never a miscompare, never silence.
import assert from "node:assert";
import * as assertNs from "node:assert";
assert.equal(1, 1); // shallow legacy equality lowers for primitives
assert.notEqual(1, 2);
assert.deepEqual([1], [1]); // loose deep equality lowers
assert.notDeepEqual([1], [2]);
const box = { n: 1 };
assert.strictEqual(box, box); // reference equality — deepStrictEqual hint
let maybe: { n: number } | undefined = box;
if ("x".length === 0) maybe = undefined;
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
assert.deepStrictEqual(unk, new Uint8Array([1])); // bytes static side: the dyn copy cannot carry the brand
assert.deepStrictEqual(unk, new Map<string, number>()); // not dyn-convertible
assert.deepStrictEqual([1, 2], ["a", "b"]); // different static types
assert.deepStrictEqual([new Uint8Array([1])], [new Uint8Array([1])]); // NESTED typed arrays fence (no brand in the element type)
class Point {
x: number;
constructor(x: number) {
this.x = x;
}
}
assert.deepStrictEqual(new Point(1), new Point(1)); // class instances fence
assertNs(true); // namespace objects are not callable in Node
assert.throws(() => { throw new Error("x"); }, { errno: -2 }); // properties outside the static error surface
assert.throws(() => { throw new Error("x"); }, {}); // Node rejects the empty shape
// (a convertible record VARIABLE as the expected shape lowers now — the
// errValue key walk; corpus 2556 pins it)
void assert.doesNotReject(async () => {}, { name: "TypeError" }); // Node's own TypeError (function or RegExp only)
assert.ifError(new Map<string, number>()); // no honest ifError rendering for this type
const throwsFn = assert.throws; // assert.throws as a value: it takes the function to run
throwsFn(() => {});
interface Tree { label: string; kids: Tree[] }
const tree: Tree = { label: "t", kids: [] };
assert.deepEqual(tree, tree); // recursive type: the failure message needs a deep copy
const handler = { run: () => 1 };
assert.deepEqual(handler, handler); // functions inside a structure: the boxes carry no source names
assert.partialDeepStrictEqual(tree, { label: "t" }); // recursive type: the failure message needs a deep copy