testShapesStaySmall
Shapes stay small, being kept with every version of their definition: a class itself (typeof Stream) is
described by name, not by its statics, which can hold the class again (as Node's stream.Duplex.Duplex does), and
a shape too big to be worth comparing is opaque.
import { analyzeFile } from "#codebase/tcmts/core/analyze"; import assert from "node:assert/strict"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; export const testShapesStaySmall = () => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), "tcm shape ")); fs.writeFileSync(path.join(dir, "package.json"), JSON.stringify({ type: "module" })); const file = path.join(dir, "shapes.ts"); const statics = ["A", "B", "C", "D", "E", "F", "G", "H"].map( (n) => `static ${n}: typeof Stream;`, ); fs.writeFileSync( file, `export class Stream { ${statics.join(" ")} } export const streams = (): Map<string, typeof Stream> => new Map(); export const big = ${JSON.stringify("x".repeat(70_000))}; `, ); const { defs, errors, diagnostics } = analyzeFile(file, { cacheDir: path.join(dir, ".tcm", "cache"), resolveName: (name) => { throw new Error(`unknown ${name}`); }, }); assert.deepEqual([...errors, ...diagnostics.map((d) => d.message)], []); const shape = (name: string) => JSON.stringify(defs.find((d) => d.nameHint === name)!.shape); const stream = defs.find((d) => d.nameHint === "Stream")!.hash; assert.equal( shape("streams"), JSON.stringify([ { k: "fn", params: [], ret: { k: "named", name: "Map", args: [ { k: "prim", name: "string" }, { k: "named", name: "typeof", args: [{ k: "ref", hash: stream, args: [] }] }, ], }, }, ]), ); assert.equal(shape("big"), JSON.stringify([{ k: "opaque" }])); }