@scriptc/compiler 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +63 -15
  2. package/ambient/scriptc.d.ts +2 -2
  3. package/dist/backend/cc.d.ts +2 -2
  4. package/dist/backend/emission/emit-async.js +1 -1
  5. package/dist/backend/emission/emit-exprs.js +131 -54
  6. package/dist/backend/emission/emit-exprs.js.map +1 -1
  7. package/dist/backend/emission/emit-island.js +1 -1
  8. package/dist/backend/emission/emit-shapes.js +1 -1
  9. package/dist/backend/emission/emit-walkers.d.ts +14 -14
  10. package/dist/backend/emission/emit-walkers.js +44 -44
  11. package/dist/backend/emission/emit-walkers.js.map +1 -1
  12. package/dist/backend/emission/emitter.d.ts +3 -3
  13. package/dist/backend/emission/emitter.js +33 -9
  14. package/dist/backend/emission/emitter.js.map +1 -1
  15. package/dist/backend/emission/may-throw.js +1 -1
  16. package/dist/backend/llvm/dyn.d.ts +10 -10
  17. package/dist/backend/llvm/dyn.js +26 -26
  18. package/dist/backend/llvm/dyn.js.map +1 -1
  19. package/dist/backend/llvm/emitter.js +156 -47
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/shapes.js +1 -1
  22. package/dist/backend/llvm/walkers.js +2 -2
  23. package/dist/backend/llvm/walkers.js.map +1 -1
  24. package/dist/coverage/surface-manifest.js +16 -2
  25. package/dist/coverage/surface-manifest.js.map +1 -1
  26. package/dist/diagnostics/diagnostic.d.ts +21 -8
  27. package/dist/diagnostics/diagnostic.js +48 -14
  28. package/dist/diagnostics/diagnostic.js.map +1 -1
  29. package/dist/frontend/lowering/lib-boundary.js +5 -5
  30. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  31. package/dist/frontend/lowering/lower-assert.js +12 -12
  32. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  33. package/dist/frontend/lowering/lower-builtins.d.ts +63 -7
  34. package/dist/frontend/lowering/lower-builtins.js +327 -35
  35. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  36. package/dist/frontend/lowering/lower-calls.d.ts +4 -4
  37. package/dist/frontend/lowering/lower-calls.js +104 -70
  38. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  39. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  40. package/dist/frontend/lowering/lower-classes.js +82 -6
  41. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  42. package/dist/frontend/lowering/lower-containers.d.ts +9 -5
  43. package/dist/frontend/lowering/lower-containers.js +88 -26
  44. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  45. package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
  46. package/dist/frontend/lowering/lower-emitter.js +438 -31
  47. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  48. package/dist/frontend/lowering/lower-exprs.d.ts +87 -12
  49. package/dist/frontend/lowering/lower-exprs.js +630 -125
  50. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  51. package/dist/frontend/lowering/lower-inspect.js +5 -5
  52. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  53. package/dist/frontend/lowering/lower-island.js +12 -3
  54. package/dist/frontend/lowering/lower-island.js.map +1 -1
  55. package/dist/frontend/lowering/lower-modules.d.ts +8 -5
  56. package/dist/frontend/lowering/lower-modules.js +157 -63
  57. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  58. package/dist/frontend/lowering/lower-namespaces.d.ts +24 -0
  59. package/dist/frontend/lowering/lower-namespaces.js +158 -16
  60. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  61. package/dist/frontend/lowering/lower-server.js +11 -11
  62. package/dist/frontend/lowering/lower-server.js.map +1 -1
  63. package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
  64. package/dist/frontend/lowering/lower-stmts.js +271 -36
  65. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  66. package/dist/frontend/lowering/lower-stream.js +171 -20
  67. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  68. package/dist/frontend/lowering/lowerer.d.ts +27 -10
  69. package/dist/frontend/lowering/lowerer.js +156 -54
  70. package/dist/frontend/lowering/lowerer.js.map +1 -1
  71. package/dist/frontend/lowering/surfaces.d.ts +44 -0
  72. package/dist/frontend/lowering/surfaces.js +236 -5
  73. package/dist/frontend/lowering/surfaces.js.map +1 -1
  74. package/dist/frontend/npm.d.ts +12 -0
  75. package/dist/frontend/npm.js +30 -0
  76. package/dist/frontend/npm.js.map +1 -1
  77. package/dist/frontend/program.d.ts +25 -0
  78. package/dist/frontend/program.js +145 -136
  79. package/dist/frontend/program.js.map +1 -1
  80. package/dist/frontend/shared.d.ts +1 -1
  81. package/dist/frontend/shared.js +8 -8
  82. package/dist/frontend/shared.js.map +1 -1
  83. package/dist/frontend/types.d.ts +2 -2
  84. package/dist/frontend/types.js +15 -15
  85. package/dist/frontend/types.js.map +1 -1
  86. package/dist/index.d.ts +2 -1
  87. package/dist/index.js +169 -5
  88. package/dist/index.js.map +1 -1
  89. package/dist/ir/nodes.d.ts +174 -106
  90. package/dist/ir/nodes.js +69 -24
  91. package/dist/ir/nodes.js.map +1 -1
  92. package/dist/ir/validate.js +55 -36
  93. package/dist/ir/validate.js.map +1 -1
  94. package/dist/library/fence-eval.js +12 -2
  95. package/dist/library/fence-eval.js.map +1 -1
  96. package/dist/library/int-infer.d.ts +119 -0
  97. package/dist/library/int-infer.js +1314 -0
  98. package/dist/library/int-infer.js.map +1 -0
  99. package/dist/library/int-infer.test.d.ts +1 -0
  100. package/dist/library/int-infer.test.js +279 -0
  101. package/dist/library/int-infer.test.js.map +1 -0
  102. package/dist/library/profile.d.ts +34 -5
  103. package/dist/library/profile.js +77 -13
  104. package/dist/library/profile.js.map +1 -1
  105. package/dist/library/sidecar-validate.js +1 -1
  106. package/dist/library/sidecar-validate.js.map +1 -1
  107. package/dist/library/sidecar.d.ts +24 -1
  108. package/dist/library/sidecar.js +163 -16
  109. package/dist/library/sidecar.js.map +1 -1
  110. package/package.json +2 -2
  111. package/surface-manifest.json +210 -12
@@ -184,11 +184,11 @@ leading?: readonly IrExpr[]): IrExpr[];
184
184
  * `type` has no undefined arm to wrap into. */
185
185
  export declare function wrappedUndefined(L: Lowerer, type: IrType, loc: SrcLoc): IrExpr | null;
186
186
  /** The synthesized argument for an omitted omittable param: the interned
187
- * undefined arm of the param's `T | undefined` ABI union, or the DOM
187
+ * undefined arm of the param's `T | undefined` ABI union, or the checked-dynamic tree
188
188
  * undefined for a checked-dynamic param (`bar?: any`). */
189
189
  /** The "absent argument" value for a param SLOT type, or null when the
190
190
  * slot cannot hold one: the interned undefined arm for undefined-armed
191
- * unions, the DOM undefined for checked-dynamic slots, the engine's own
191
+ * unions, the dyn undefined for checked-dynamic slots, the engine's own
192
192
  * undefined for island slots. Shared by every call-completion loop
193
193
  * (direct calls and calls through func-typed values). */
194
194
  export declare function omittedArgFor(L: Lowerer, type: IrType, loc: SrcLoc): IrExpr | null;
@@ -382,7 +382,7 @@ export declare function lowerCall(L: Lowerer, expr: ts.CallExpression): IrExpr;
382
382
  * - CHECKED-DYNAMIC (dyn spread sources — a JS rest binding, a dyn
383
383
  * value): box the callee (dynFrom; a dyn callee is already boxed),
384
384
  * convert every argument into dyn, and emit the spread-marked dynCall
385
- * — the emitters build one fresh DOM argument array (spreads flatten
385
+ * — the emitters build one fresh dyn argument array (spreads flatten
386
386
  * left-to-right, non-iterables throw V8's TypeError) and apply through
387
387
  * it; the boxed thunk delivers JS arity exactly. Result dyn, checked
388
388
  * per use like every any-origin value.
@@ -404,7 +404,7 @@ export declare function lowerSpreadArgsCall(L: Lowerer, expr: ts.CallExpression,
404
404
  * slots keep completeArgs' same-element spread packing. */
405
405
  export declare function spreadNeedsRuntimeArity(shapes: readonly ParamShape[], argNodes: readonly ts.Expression[]): boolean;
406
406
  /** The SHARED prototype names scr_dyn_invoke dispatches at runtime (the
407
- * subset of DOM_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
407
+ * subset of DYN_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
408
408
  * runtime runs the real method for the receiver's kind, throws Node's
409
409
  * is-not-a-function where the kind's prototype lacks the name, and
410
410
  * fences LOUDLY on real-but-unimplemented pairs. */
@@ -13,7 +13,7 @@ import { NARROW_FIRST, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.
13
13
  import { requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
14
14
  import { mixinFnShapeOf } from "./lower-mixins.js";
15
15
  import { bufEncoding, dynStringReceiver, lowerArrayFromCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerRegexMethodCall, lowerStringMethodCall, lowerTupleReadMethodCall } from "./lower-containers.js";
16
- import { lowerChildStreamMethodCall, lowerDirentMethodCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerWatcherMethodCall } from "./lower-builtins.js";
16
+ import { lowerChildStreamMethodCall, lowerCreateRequireCall, lowerDirentMethodCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerWatcherMethodCall } from "./lower-builtins.js";
17
17
  import { droppableStatic, lowerPromiseAllTupleCall, lowerPromiseRejectCall, probeLower, templateRawTextOf } from "./lower-exprs.js";
18
18
  import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerHttpClientFnCall } from "./lower-server.js";
19
19
  import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall } from "./lower-classes.js";
@@ -85,7 +85,7 @@ export function paramShape(L, param) {
85
85
  const raw = L.irTypeOf(param.name);
86
86
  // A DYNAMIC-TIER pattern source (`function f({} = a)` with
87
87
  // `a: any` — jsval for island values, dyn for the checked-dynamic
88
- // DOM): the slot holds its tier's undefined DIRECTLY, so the ABI
88
+ // dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
89
89
  // is the slot itself — no synthesized union; the prologue tests
90
90
  // undefined at runtime (declareParams).
91
91
  if (raw.kind === "dyn" || raw.kind === "jsval") {
@@ -103,7 +103,7 @@ export function paramShape(L, param) {
103
103
  }
104
104
  if (param.dotDotDotToken) {
105
105
  // A JS rest param with no static element type (`(...args)` — any[]):
106
- // the VARIADIC dyn form. The lifted function takes one trailing DOM
106
+ // the VARIADIC dyn form. The lifted function takes one trailing dyn
107
107
  // ARRAY param the dyn call thunk fills with the call's surplus
108
108
  // arguments; the binding is that array (dynRest — funcType marks
109
109
  // `rest`, and the value only ever calls through the boxed thunk).
@@ -133,7 +133,7 @@ export function paramShape(L, param) {
133
133
  const raw = L.irTypeOf(param.name);
134
134
  // A DYNAMIC-TIER defaulted param (`function f(x = a)` with `a: any`
135
135
  // — tsc types x any; jsval for island values, dyn for the checked-
136
- // dynamic DOM): the slot holds its tier's undefined directly, so
136
+ // dynamic dyn): the slot holds its tier's undefined directly, so
137
137
  // the ABI is the slot itself and the prologue's default test is the
138
138
  // runtime undefined test (declareParams).
139
139
  if (raw.kind === "dyn" || raw.kind === "jsval") {
@@ -169,7 +169,7 @@ export function paramShape(L, param) {
169
169
  if (param.questionToken && !L.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
170
170
  // `x?: unknown` where unknown came from an annotation: undefined is
171
171
  // absorbed into the hole type, so no undefined ARM exists — but a
172
- // checked-dynamic slot holds the DOM undefined directly (`bar?: any`
172
+ // checked-dynamic slot holds the dyn undefined directly (`bar?: any`
173
173
  // — an omitted call passes it, undefinedArgFor), and an island slot
174
174
  // the engine's own undefined likewise (`options?: [string?]` — an
175
175
  // optional-tuple param, jsval-mapped), so dyn and jsval params stay
@@ -243,7 +243,7 @@ leading) {
243
243
  // A missing argument for a CHECKED-DYNAMIC param (an implicit-any
244
244
  // JS signature called short — `mustCall(fn)` with `expected`
245
245
  // omitted): JS fills undefined, and the dyn slot holds exactly
246
- // that — the undefined DOM value. tsc's arity families don't gate
246
+ // that — the undefined dyn value. tsc's arity families don't gate
247
247
  // .js builds (SEMANTICS.md 116), so the completion lands here.
248
248
  if (shape.type.kind === "dyn") {
249
249
  return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
@@ -271,7 +271,7 @@ leading) {
271
271
  else if (restAt >= 0 && shapes[restAt].mode === "dynRest") {
272
272
  // The VARIADIC dyn pack (a JS `...args` with no static element
273
273
  // type, or the synthetic `arguments` slot): surplus arguments
274
- // convert through the dyn boundary into one fresh DOM array —
274
+ // convert through the dyn boundary into one fresh dyn array —
275
275
  // exactly what the boxed call thunk builds for indirect calls.
276
276
  const elems = sources.slice(restAt).map((a) => {
277
277
  if (isIr(a))
@@ -384,11 +384,11 @@ export function wrappedUndefined(L, type, loc) {
384
384
  return wrapped.kind === "unionWrap" ? wrapped : null;
385
385
  }
386
386
  /** The synthesized argument for an omitted omittable param: the interned
387
- * undefined arm of the param's `T | undefined` ABI union, or the DOM
387
+ * undefined arm of the param's `T | undefined` ABI union, or the checked-dynamic tree
388
388
  * undefined for a checked-dynamic param (`bar?: any`). */
389
389
  /** The "absent argument" value for a param SLOT type, or null when the
390
390
  * slot cannot hold one: the interned undefined arm for undefined-armed
391
- * unions, the DOM undefined for checked-dynamic slots, the engine's own
391
+ * unions, the dyn undefined for checked-dynamic slots, the engine's own
392
392
  * undefined for island slots. Shared by every call-completion loop
393
393
  * (direct calls and calls through func-typed values). */
394
394
  export function omittedArgFor(L, type, loc) {
@@ -529,7 +529,7 @@ export function appendImplicitUndefinedReturn(L, body, bodyReturn, loc) {
529
529
  // A DYN body that can complete without returning (a JS function whose
530
530
  // guarded return may not run — mustSucceed's `if (typeof fn ===
531
531
  // 'function') return fn.apply(...)`): JS completes with undefined —
532
- // the undefined DOM value.
532
+ // the undefined dyn value.
533
533
  if (bodyReturn.kind === "dyn") {
534
534
  body.push({
535
535
  kind: "return",
@@ -584,7 +584,7 @@ export function declaredReturnType(L, decl, blame) {
584
584
  // The RECORD twin (the tracing suite's traced closures — `function ()
585
585
  // { return expectedResult; }` infers `{ foo: string }`): JS object
586
586
  // literals are checked-dynamic VALUES, so a record-typed return would
587
- // copy the DOM value into a struct at the return and copy it back out
587
+ // copy the dyn value into a struct at the return and copy it back out
588
588
  // at any dyn boundary — identity lost twice (found.result !==
589
589
  // expectedResult where Node passes the object through). The inferred
590
590
  // shape is inference, not a contract: the return stays checked-
@@ -1332,7 +1332,7 @@ function resolveInferredReturn(L, inst, infer, body, decl) {
1332
1332
  distinct.push(e.stmt.value.type);
1333
1333
  }
1334
1334
  if (distinct.length === 0) {
1335
- final = DYN; // no valued return: JS completes with undefined — the DOM undefined, today's slot
1335
+ final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
1336
1336
  }
1337
1337
  else if (distinct.length === 1) {
1338
1338
  const t = distinct[0];
@@ -1459,7 +1459,7 @@ export function lowerGenericFnValue(L, ref, info) {
1459
1459
  const inst = genericValueInstance(L, ref, info, bindings);
1460
1460
  // The value's type is the completed ABI signature — exact-arity, the
1461
1461
  // declared-function value rule (dynRest slots stay out of the param
1462
- // list; the rest marker carries the trailing DOM-array ABI).
1462
+ // list; the rest marker carries the trailing dyn-array ABI).
1463
1463
  const funcType = {
1464
1464
  kind: "func",
1465
1465
  params: inst.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
@@ -2316,6 +2316,15 @@ export function lowerCall(L, expr) {
2316
2316
  }
2317
2317
  }
2318
2318
  }
2319
+ // `require("spec")` through a createRequire binding (and the inline
2320
+ // `createRequire(import.meta.url)("spec")` spelling — a CallExpression
2321
+ // callee no other dispatch path serves): the static erasure —
2322
+ // builtins/json/npm per lowerCreateRequireCall's arms.
2323
+ {
2324
+ const crServed = lowerCreateRequireCall(L, expr, loc);
2325
+ if (crServed)
2326
+ return crServed;
2327
+ }
2319
2328
  // `process.getuid?.()` — intercepted BEFORE the optional-chain
2320
2329
  // machinery (the member always exists on a POSIX target, so the
2321
2330
  // optional call IS the call; `process.getuid` itself has no value
@@ -2433,7 +2442,7 @@ export function lowerCall(L, expr) {
2433
2442
  // non-format argument: strings VERBATIM, everything else through
2434
2443
  // inspect at the rest-args depth 2 (formatWithOptions) — scalar
2435
2444
  // kinds byte-exactly, boxed functions as [Function: name] /
2436
- // [Function (anonymous)], composites through the dyn DOM walk
2445
+ // [Function (anonymous)], composites through the dyn walk
2437
2446
  // (insp.dyn). Never throws — Node's console.log never does.
2438
2447
  if (lowered.type.kind === "dyn") {
2439
2448
  return {
@@ -2542,10 +2551,10 @@ export function lowerCall(L, expr) {
2542
2551
  }
2543
2552
  return { kind: "libCall", fn: "timers.queueMicrotask", args: [adapted], type: VOID, loc };
2544
2553
  }
2545
- // structuredClone: the JSON-safe + bytes subset over the DOM, deep;
2554
+ // structuredClone: the JSON-safe + bytes subset over the checked-dynamic tree, deep;
2546
2555
  // %DOMException clones through WebIDL serialization (name/message,
2547
2556
  // the code re-derives). Functions/handles throw the spec's catchable
2548
- // DataCloneError; cycles fence (the DOM cannot represent them — Node
2557
+ // DataCloneError; cycles fence (the checked-dynamic tree cannot represent them — Node
2549
2558
  // clones cycles, a documented divergence). Option validation throws
2550
2559
  // Node's exact errors; the zero-argument call Node's
2551
2560
  // ERR_MISSING_ARGS. Provenance-checked like setTimeout.
@@ -2571,7 +2580,7 @@ export function lowerCall(L, expr) {
2571
2580
  const valueNode = expr.arguments[0];
2572
2581
  // A NON-EMPTY transfer array of static values: nothing static is
2573
2582
  // transferable, so the call is Node's DataCloneError — decided here
2574
- // (the list's values need no DOM representation to fail). An EMPTY
2583
+ // (the list's values need no dyn representation to fail). An EMPTY
2575
2584
  // literal transfer list is a no-op member and drops.
2576
2585
  {
2577
2586
  let optNode = expr.arguments[1];
@@ -2602,8 +2611,8 @@ export function lowerCall(L, expr) {
2602
2611
  const value = toDynArg(valueNode);
2603
2612
  const cloned = { kind: "libCall", fn: "dyn.structuredClone", args: [value, optsArg], type: DYN, loc };
2604
2613
  // The declared result is the value's own type (the generic's T):
2605
- // validate the DOM copy back into it when the type can be checked;
2606
- // dyn-typed and unmappable results stay DOM values (JS files).
2614
+ // validate the dyn copy back into it when the type can be checked;
2615
+ // dyn-typed and unmappable results stay dyn values (JS files).
2607
2616
  const resultT = L.mapTypeOf(L.typeOf(expr));
2608
2617
  if (resultT !== null && resultT.kind !== "dyn" && resultT.kind !== "void" &&
2609
2618
  canDynCheckTo(resultT, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
@@ -2709,7 +2718,7 @@ export function lowerCall(L, expr) {
2709
2718
  if (ts.isPropertyAccessExpression(expr.expression) &&
2710
2719
  L.isIslandExpr(expr.expression.expression)) {
2711
2720
  const receiver = L.lowerExpr(expr.expression.expression);
2712
- // A checker-`any` receiver whose VALUE lives in the DOM (a
2721
+ // A checker-`any` receiver whose VALUE lives in the checked-dynamic tree (a
2713
2722
  // checked-dynamic local behind the any-typed spelling — the JS
2714
2723
  // WeakSet placeholder, rest-args arrays): the checked-dynamic
2715
2724
  // method machinery owns it — receiver-kind dispatch, stored-member
@@ -2756,7 +2765,7 @@ export function lowerCall(L, expr) {
2756
2765
  }
2757
2766
  const callee = L.lowerExpr(expr.expression);
2758
2767
  // A checker-`any` callee that LOWERED checked-dynamic (a dyn member
2759
- // chain's stored function): the DOM's own call — dynCall reads and
2768
+ // chain's stored function): the checked-dynamic tree's own call — dynCall reads and
2760
2769
  // calls the stored member with Node's is-not-a-function TypeError
2761
2770
  // on refusal.
2762
2771
  if (callee.type.kind === "dyn") {
@@ -3022,7 +3031,7 @@ export function lowerCall(L, expr) {
3022
3031
  }
3023
3032
  // STATIC atob/btoa (str.atob / str.btoa — scr_string.c; WHATWG
3024
3033
  // forgiving-base64, Node is the oracle). The argument crosses as a
3025
- // DOM value: WebIDL ToString runs in the runtime over the DOM kind
3034
+ // dyn value: WebIDL ToString runs in the runtime over the dyn kind
3026
3035
  // (Node's atob(null) decodes "null"), a malformed input throws the
3027
3036
  // catchable DOMException InvalidCharacterError, and the
3028
3037
  // zero-argument call throws Node's TypeError [ERR_MISSING_ARGS].
@@ -3515,7 +3524,7 @@ export function lowerCall(L, expr) {
3515
3524
  if (callee.type.kind === "dyn") {
3516
3525
  if (expr.arguments.some((a) => ts.isSpreadElement(a))) {
3517
3526
  // The runtime-arity lane: a dyn callee is already boxed — the
3518
- // spread-marked dynCall applies through a fresh DOM argument
3527
+ // spread-marked dynCall applies through a fresh dyn argument
3519
3528
  // array (lowerSpreadArgsCall). Sources outside it keep the fence.
3520
3529
  const spreadServed = lowerSpreadArgsCall(L, expr, callee, loc);
3521
3530
  if (spreadServed)
@@ -3595,7 +3604,7 @@ export function lowerCall(L, expr) {
3595
3604
  // skip — not a shape this surface models; fence.
3596
3605
  for (let i = args.length; i < params.length; i++) {
3597
3606
  // A missing argument completes with the slot's absent value — the
3598
- // interned undefined arm, the DOM undefined for checked-dynamic
3607
+ // interned undefined arm, the dyn undefined for checked-dynamic
3599
3608
  // slots (a JS-inferred wrapper like mustCall's, called short), or
3600
3609
  // the engine undefined for island slots.
3601
3610
  const absent = omittedArgFor(L, params[i], loc);
@@ -3615,7 +3624,7 @@ export function lowerCall(L, expr) {
3615
3624
  * - CHECKED-DYNAMIC (dyn spread sources — a JS rest binding, a dyn
3616
3625
  * value): box the callee (dynFrom; a dyn callee is already boxed),
3617
3626
  * convert every argument into dyn, and emit the spread-marked dynCall
3618
- * — the emitters build one fresh DOM argument array (spreads flatten
3627
+ * — the emitters build one fresh dyn argument array (spreads flatten
3619
3628
  * left-to-right, non-iterables throw V8's TypeError) and apply through
3620
3629
  * it; the boxed thunk delivers JS arity exactly. Result dyn, checked
3621
3630
  * per use like every any-origin value.
@@ -3703,7 +3712,7 @@ export function spreadNeedsRuntimeArity(shapes, argNodes) {
3703
3712
  }
3704
3713
  /** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
3705
3714
  * `ws.packages.filter(...)` — JSON.parse-derived values): validate the
3706
- * receiver's DOM kind, extract, and ride the STATIC method machinery — the
3715
+ * receiver's dyn kind, extract, and ride the STATIC method machinery — the
3707
3716
  * dyn boundary's trust-but-verify stance extended to receivers. The
3708
3717
  * receiver-kind mismatch throws V8's own catchable TypeErrors (nullish:
3709
3718
  * "Cannot read properties of undefined (reading 'replace')"; other kinds:
@@ -3711,14 +3720,14 @@ export function spreadNeedsRuntimeArity(shapes, argNodes) {
3711
3720
  * evaluate, where JS evaluates them first for the non-nullish case
3712
3721
  * (SEMANTICS.md). String methods ride the string/regex intrinsic tables
3713
3722
  * through a validated-string receiver; `.filter` runs the predicate over
3714
- * the DOM array and validated-extracts the survivors into the element type
3723
+ * the dyn array and validated-extracts the survivors into the element type
3715
3724
  * the checker committed the result to. Null when the receiver isn't a dyn
3716
3725
  * value or the method isn't claimable (the method-call fence stays). */
3717
3726
  function lowerDynReceiverMethodCall(L, call, access) {
3718
3727
  if (L.chainBlocked(call, access))
3719
3728
  return null;
3720
3729
  // Only checker-untyped receivers: `any`/`unknown`, or the `any[]` an
3721
- // Array.isArray guard narrows them to (the value is STILL the DOM
3730
+ // Array.isArray guard narrows them to (the value is STILL the checked-dynamic tree
3722
3731
  // array — scalar narrowings bridge through maybeNarrow's dynCheck and
3723
3732
  // take the ordinary typed paths, but there is no static home for an
3724
3733
  // any-elemented array). Typed receivers keep their own lowerings.
@@ -3750,7 +3759,7 @@ function lowerDynReceiverMethodCall(L, call, access) {
3750
3759
  return null;
3751
3760
  // Typed-destination filter first (validated extraction into a real
3752
3761
  // T[]); an untyped destination falls through to the runtime dispatch
3753
- // below (the survivors stay DOM values).
3762
+ // below (the survivors stay dyn values).
3754
3763
  if (access.name.text === "filter") {
3755
3764
  const extracted = lowerDynArrayFilterCall(L, call, access, recv);
3756
3765
  if (extracted)
@@ -3758,10 +3767,10 @@ function lowerDynReceiverMethodCall(L, call, access) {
3758
3767
  }
3759
3768
  if (access.name.text === "flatMap")
3760
3769
  return lowerDynArrayFlatMapCall(L, call, access, recv);
3761
- // String methods claim only names NO other DOM-representable kind's
3770
+ // String methods claim only names NO other dyn-representable kind's
3762
3771
  // prototype declares (Array carries includes/indexOf/slice too): for
3763
3772
  // these, "the receiver is a string, or the call throws V8's TypeError"
3764
- // IS Node's semantics for every possible DOM value. Shared names would
3773
+ // IS Node's semantics for every possible dyn value. Shared names would
3765
3774
  // need a receiver-kind dispatch — they keep the fence.
3766
3775
  if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
3767
3776
  const checked = () => dynStringReceiver(L, recv, access);
@@ -3795,7 +3804,7 @@ function lowerDynReceiverMethodCall(L, call, access) {
3795
3804
  }
3796
3805
  // SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
3797
3806
  // push/slice/join/forEach/map/apply/... dispatch on the receiver's
3798
- // RUNTIME kind — the honest answer for names more than one DOM-
3807
+ // RUNTIME kind — the honest answer for names more than one dyn-
3799
3808
  // representable prototype declares (test/common's mustCall internals:
3800
3809
  // mustCallChecks.push(context), failed.forEach(fn), fn.apply(this,
3801
3810
  // args)). Implemented (kind, name) pairs run JS-exact; real-but-
@@ -3817,18 +3826,18 @@ function lowerDynReceiverMethodCall(L, call, access) {
3817
3826
  loc: locOf(call),
3818
3827
  };
3819
3828
  }
3820
- // Names NO DOM-representable prototype declares: the member can only
3829
+ // Names NO dyn-representable prototype declares: the member can only
3821
3830
  // be an OWN property, so "read the member, call it" IS Node's
3822
- // semantics for every possible DOM value — `handlers.onDone(x)` on a
3831
+ // semantics for every possible dyn value — `handlers.onDone(x)` on a
3823
3832
  // checked-dynamic object calls the stored function (dynKeyGet answers
3824
3833
  // the member or undefined; dynCall throws Node's exact catchable
3825
3834
  // "handlers.onDone is not a function" on a non-function). Prototype
3826
3835
  // names (map/join/hasOwnProperty/call/...) keep the fence: on a real
3827
- // DOM array/string/object Node would run the METHOD, which no stored
3836
+ // dyn array/string/object Node would run the METHOD, which no stored
3828
3837
  // member models. Order note: JS reads the callee before evaluating
3829
3838
  // arguments — dynKeyGet's undefined-receiver TypeError fires first,
3830
3839
  // exactly Node.
3831
- if (DOM_PROTO_METHOD_NAMES.has(access.name.text))
3840
+ if (DYN_PROTO_METHOD_NAMES.has(access.name.text))
3832
3841
  return null;
3833
3842
  // Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
3834
3843
  // machinery's short-circuit semantics — not modeled here yet.
@@ -3848,12 +3857,12 @@ function lowerDynReceiverMethodCall(L, call, access) {
3848
3857
  const args = call.arguments.map((a) => L.lowerExprExpecting(a, DYN));
3849
3858
  return { kind: "dynCall", callee: member, calleeName: access.getText(), args, type: DYN, loc };
3850
3859
  }
3851
- /** Prototype method names of the DOM-representable kinds (String, Array,
3860
+ /** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
3852
3861
  * Object, Function, Number prototypes): a dyn receiver call on one of
3853
3862
  * these could be a REAL method on a real value, which a stored-member
3854
3863
  * read would silently mis-answer — they keep the fence. Everything else
3855
- * is own-property-or-throw for every DOM value (the honest dynCall). */
3856
- const DOM_PROTO_METHOD_NAMES = new Set([
3864
+ * is own-property-or-throw for every dyn value (the honest dynCall). */
3865
+ const DYN_PROTO_METHOD_NAMES = new Set([
3857
3866
  // Object.prototype
3858
3867
  "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf",
3859
3868
  // Function.prototype
@@ -3868,7 +3877,7 @@ const DOM_PROTO_METHOD_NAMES = new Set([
3868
3877
  "toExponential", "toFixed", "toPrecision",
3869
3878
  ]);
3870
3879
  /** The SHARED prototype names scr_dyn_invoke dispatches at runtime (the
3871
- * subset of DOM_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
3880
+ * subset of DYN_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
3872
3881
  * runtime runs the real method for the receiver's kind, throws Node's
3873
3882
  * is-not-a-function where the kind's prototype lacks the name, and
3874
3883
  * fences LOUDLY on real-but-unimplemented pairs. */
@@ -3882,7 +3891,7 @@ export const DYN_DISPATCH_METHODS = new Set([
3882
3891
  // the runtime kind so a boxed IncomingMessage/ServerResponse/Socket
3883
3892
  // routes onto the same entry points the static lowerings use (modeled
3884
3893
  // members) or the loud not-supported ladder (real-but-unmodeled ones).
3885
- // On every other DOM kind they answer exactly what the stored-member
3894
+ // On every other dyn kind they answer exactly what the stored-member
3886
3895
  // path answered (OBJ own members call; the rest throw Node's
3887
3896
  // is-not-a-function).
3888
3897
  "on", "once", "addListener", "removeListener", "off", "removeAllListeners",
@@ -3897,11 +3906,11 @@ export const DYN_DISPATCH_METHODS = new Set([
3897
3906
  // The netServer half of the handle surface (`let server; server =
3898
3907
  // createServer(...)` — the handle lives in a dyn binding whose
3899
3908
  // closures the checker cannot narrow): listen/close dispatch onto the
3900
- // server ops; no other DOM prototype declares either name, so the
3909
+ // server ops; no other dyn prototype declares either name, so the
3901
3910
  // remainder keeps the stored-member answers.
3902
3911
  "listen", "close",
3903
3912
  // Promise.prototype (SCR_DYN_PROMISE receivers): the reaction trio
3904
- // rides the fiber machinery (scr_dyn_promise_then); on every other DOM
3913
+ // rides the fiber machinery (scr_dyn_promise_then); on every other dyn
3905
3914
  // kind then/catch/finally answer the stored-member path (OBJ own
3906
3915
  // members call, the rest throw Node's is-not-a-function).
3907
3916
  "then", "catch", "finally",
@@ -3915,15 +3924,15 @@ export const DYN_DISPATCH_METHODS = new Set([
3915
3924
  "additionalHeaders", "altsvc", "origin",
3916
3925
  ]);
3917
3926
  /** STR_METHODS ∪ the regex-form names, MINUS everything Array (or any
3918
- * other DOM kind's prototype) also declares. */
3927
+ * other dyn kind's prototype) also declares. */
3919
3928
  const DYN_STRING_ONLY_METHODS = new Set([
3920
3929
  "charCodeAt", "charAt", "startsWith", "endsWith", "substring", "repeat",
3921
3930
  "trim", "trimStart", "trimEnd", "split", "padStart", "padEnd",
3922
3931
  "toLowerCase", "toUpperCase", "replace", "replaceAll", "match", "matchAll",
3923
3932
  "search",
3924
3933
  ]);
3925
- /** `Array.isArray(v)` — a real runtime test on `unknown` values (the DOM's
3926
- * array kind: DOM arrays answer true, bytes/objects/scalars false — exactly
3934
+ /** `Array.isArray(v)` — a real runtime test on `unknown` values (the checked-dynamic tree's
3935
+ * array kind: dyn arrays answer true, bytes/objects/scalars false — exactly
3927
3936
  * JS, Uint8Array included), a compile-time constant on statically-typed
3928
3937
  * ones (an `T[]` value IS an array, every other static kind is not; folded
3929
3938
  * only over side-effect-free reads, the `in`-operator discipline; unions
@@ -4658,7 +4667,7 @@ export function lambdaSignature(L, node) {
4658
4667
  // VARIADIC JS functions: a dynRest param (above), or a plain function
4659
4668
  // whose body reads `arguments` (test/common's mustCall wrapper —
4660
4669
  // `function() { ...; return fn.apply(this, arguments); }`). Both mark
4661
- // the func type `rest`: the lifted body takes one trailing DOM-array
4670
+ // the func type `rest`: the lifted body takes one trailing dyn-array
4662
4671
  // param, filled by the boxed call thunk with the call's arguments
4663
4672
  // from index params.length on. `arguments` is only claimed in
4664
4673
  // ZERO-param functions (there it IS the surplus array); alongside
@@ -4678,7 +4687,7 @@ export function lambdaSignature(L, node) {
4678
4687
  shapes,
4679
4688
  funcType: {
4680
4689
  kind: "func",
4681
- // dynRest is EXCLUDED (the boxed thunk fills the trailing DOM
4690
+ // dynRest is EXCLUDED (the boxed thunk fills the trailing dyn
4682
4691
  // array — no spelled slot); islandRest is INCLUDED (the trailing
4683
4692
  // jsval param IS the engine arguments array, the REST host-call
4684
4693
  // adapter's one uniform shape).
@@ -4761,7 +4770,7 @@ export function lowerLambda(L, node) {
4761
4770
  try {
4762
4771
  const { params, prologue } = L.declareParams(node.parameters, shapes);
4763
4772
  // The VARIADIC `arguments` form (rest-marked with no declared rest
4764
- // param): a synthetic trailing DOM-array param carries the call's
4773
+ // param): a synthetic trailing dyn-array param carries the call's
4765
4774
  // arguments; `arguments` reads resolve to it (identifier lowering).
4766
4775
  if (funcType.rest && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
4767
4776
  const argsLocal = L.declareHiddenLocal("%arguments", DYN);
@@ -4866,7 +4875,7 @@ export function lowerLambda(L, node) {
4866
4875
  const first = captured[0];
4867
4876
  const pos = ts.getLineAndCharacterOfPosition(L.program.getSourceFile(first.loc.file) ?? node.getSourceFile(), first.loc.start);
4868
4877
  const params = funcType.params.map((t, i) => ({ localId: `%pf${i}`, name: `%pf${i}`, type: t }));
4869
- // A REST-MARKED value type hides one synthetic trailing DOM-array
4878
+ // A REST-MARKED value type hides one synthetic trailing dyn-array
4870
4879
  // param in the lifted function (the boxed call thunk fills it) —
4871
4880
  // the fence lambda must spell that slot too or the validator's
4872
4881
  // closure-signature check trips (SC9001). Island rest types SPELL
@@ -5093,7 +5102,7 @@ export function lowerPromiseMethodCall(L, call, access) {
5093
5102
  // A TYPED handler on a DYN-settling promise (the tracePromise
5094
5103
  // result's `.then((value) => ...)` — the checker's generic
5095
5104
  // instantiation typed the parameter, but the settled value is a
5096
- // DOM value): box the handler and ride the dyn-handler desugar
5105
+ // dyn value): box the handler and ride the dyn-handler desugar
5097
5106
  // below — its call thunk validates the settled value into the
5098
5107
  // declared parameter type (the per-arg dynCheck), Node's own
5099
5108
  // runtime contract for a value that came off the wire untyped.
@@ -5105,10 +5114,10 @@ export function lowerPromiseMethodCall(L, call, access) {
5105
5114
  }
5106
5115
  // A CHECKED-DYNAMIC handler VALUE (`p.then(common.mustCall())` — the
5107
5116
  // Node-suite wrapper is an untyped rest-args function): the same
5108
- // async desugar with the handler called through the DOM — the
5117
+ // async desugar with the handler called through the checked-dynamic tree — the
5109
5118
  // settled value boxes (dyn passes through; void arrives as JS's
5110
5119
  // explicit undefined argument), the result promise settles with the
5111
- // handler's DOM result. A receiver rejection passes through the
5120
+ // handler's dyn result. A receiver rejection passes through the
5112
5121
  // await like the typed path; the dyn call's own argument checking
5113
5122
  // throws Node's TypeError for non-callables.
5114
5123
  if (cb.type.kind === "dyn") {
@@ -5118,7 +5127,7 @@ export function lowerPromiseMethodCall(L, call, access) {
5118
5127
  if (canConvertToDyn(v.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
5119
5128
  return { kind: "dynFrom", value: v, type: DYN, loc };
5120
5129
  }
5121
- L.unsupported("SC1090", call.arguments[0], `then handlers receiving '${L.fmt(v.type)}' values through an untyped handler (the settled value cannot cross the DOM boundary)`);
5130
+ L.unsupported("SC1090", call.arguments[0], `then handlers receiving '${L.fmt(v.type)}' values through an untyped handler (the settled value cannot cross the checked-dynamic tree boundary)`);
5122
5131
  };
5123
5132
  const resultT = { kind: "promise", inner: DYN };
5124
5133
  const fnName = `%fn${L.lambdaCounter++}_then`;
@@ -5344,8 +5353,8 @@ export function lowerPromiseMethodCall(L, call, access) {
5344
5353
  }
5345
5354
  }
5346
5355
  // .catch on a DYN-SETTLING promise (the tracePromise result's
5347
- // `.catch((e) => ...)`): the rejection reason is a DOM value, so the
5348
- // handler runs through the DOM — a lifted async helper awaits the
5356
+ // `.catch((e) => ...)`): the rejection reason is a dyn value, so the
5357
+ // handler runs through the checked-dynamic tree — a lifted async helper awaits the
5349
5358
  // receiver, passes fulfillments through as dyn, and on rejection
5350
5359
  // calls the boxed handler with caughtToDyn's identity-preserving
5351
5360
  // snapshot (the dyn-then desugar's catch twin).
@@ -5531,7 +5540,7 @@ export function lowerPromiseMethodCall(L, call, access) {
5531
5540
  else if (R.kind === "dyn") {
5532
5541
  // A checked-dynamic result (the dyn-handler .then's promise-of-dyn
5533
5542
  // chained into .catch): falling off the handler's end resolves
5534
- // with the DOM undefined.
5543
+ // with the dyn undefined.
5535
5544
  catchBody.push({ kind: "return", value: dynUndefinedExpr(loc), loc });
5536
5545
  }
5537
5546
  else if (R.kind === "jsval") {
@@ -6263,7 +6272,7 @@ function lowerObjectStaticCall(L, call, access) {
6263
6272
  // REAL prototype semantics: reads delegate LIVE, writes shadow,
6264
6273
  // and inspect renders Node's exact shapes ("[Object: null
6265
6274
  // prototype]" included). null and engine-held (jsval) prototypes
6266
- // route; checked-dynamic (DOM) prototypes keep the named fence —
6275
+ // route; checked-dynamic (dyn) prototypes keep the named fence —
6267
6276
  // their marshal into the engine is a DEEP COPY, so a later
6268
6277
  // prototype mutation would be invisible through the created
6269
6278
  // object where Node delegates live.
@@ -6328,7 +6337,7 @@ function lowerObjectStaticCall(L, call, access) {
6328
6337
  const tProbe = probeLower(L, call.arguments[0]);
6329
6338
  const sProbe = probeLower(L, call.arguments[1]);
6330
6339
  // CHECKED-DYNAMIC target and source (the JS file-scope
6331
- // object-literal identity story): the runtime DOM copy — own
6340
+ // object-literal identity story): the runtime dyn copy — own
6332
6341
  // members of the source land on the target, which returns.
6333
6342
  if (tProbe?.type.kind === "dyn") {
6334
6343
  const loc = locOf(call);
@@ -6363,7 +6372,7 @@ function lowerObjectStaticCall(L, call, access) {
6363
6372
  // `Object.assign(target, ...sources)` over a CHECKED-DYNAMIC target
6364
6373
  // — the n-ary/spread form (`Object.assign({}, ...plugins.map(p =>
6365
6374
  // p.options), coreOptions)`, support.js's option-table merge). The
6366
- // sources pack into one fresh DOM array FIRST — plain sources
6375
+ // sources pack into one fresh dyn array FIRST — plain sources
6367
6376
  // retain in, spread sources flatten through the spread-call walk
6368
6377
  // (V8's exact TypeError texts, the source spelling carried for the
6369
6378
  // nullish form) — so every source evaluates and flattens before any
@@ -6375,7 +6384,7 @@ function lowerObjectStaticCall(L, call, access) {
6375
6384
  // spread copies in at the boundary, the documented aliasing
6376
6385
  // stance); anything else keeps the fence. Targets: dyn values, a
6377
6386
  // FRESH object-literal target (`Object.assign({}, ...)` — no alias
6378
- // exists, so building it as a DOM object instead of a record is
6387
+ // exists, so building it as a dyn object instead of a record is
6379
6388
  // unobservable), or a nullish unit (Node's ToObject TypeError
6380
6389
  // throws at the call, catchably); aliased record targets keep the
6381
6390
  // fence — their identity could not survive the conversion.
@@ -6450,7 +6459,7 @@ function lowerObjectStaticCall(L, call, access) {
6450
6459
  // Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
6451
6460
  // _mustCallInner copying name/length onto the mustCall wrapper): the
6452
6461
  // runtime turns each descriptor's `value` into a plain own property on
6453
- // the DOM node (OBJ members; FUNC nodes carry an own-property table) —
6462
+ // the dyn node (OBJ members; FUNC nodes carry an own-property table) —
6454
6463
  // flags accepted and ignored, accessors throw loudly (SEMANTICS.md).
6455
6464
  // The result is the target, like JS. Typed targets keep the fence:
6456
6465
  // static shapes have no property table to extend.
@@ -6513,7 +6522,7 @@ function lowerObjectStaticCall(L, call, access) {
6513
6522
  const keyNode = call.arguments[1];
6514
6523
  const probed = probeLower(L, recvNode);
6515
6524
  // A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
6516
- // identity story): the runtime DOM probe — OBJ member presence, ARR
6525
+ // identity story): the runtime dyn probe — OBJ member presence, ARR
6517
6526
  // index bounds, Node's ToObject TypeError on nullish.
6518
6527
  if (probed?.type.kind === "dyn") {
6519
6528
  const loc = locOf(call);
@@ -6553,9 +6562,9 @@ function lowerObjectStaticCall(L, call, access) {
6553
6562
  const argNode = call.arguments[0];
6554
6563
  // A CHECKED-DYNAMIC argument — the checker may still spell a record
6555
6564
  // type (the JS file-scope object-literal identity story stores the
6556
- // DOM object), so the LOWERED value's kind is the dispatch: the
6557
- // runtime walks the DOM node's own keys (integer-like keys first,
6558
- // JS's own-key order) and answers a DOM array.
6565
+ // dyn object), so the LOWERED value's kind is the dispatch: the
6566
+ // runtime walks the dyn node's own keys (integer-like keys first,
6567
+ // JS's own-key order) and answers a dyn array.
6559
6568
  {
6560
6569
  const probed = probeLower(L, argNode);
6561
6570
  const isDyn = probed?.type.kind === "dyn";
@@ -6777,7 +6786,7 @@ export function lowerFunction(L, decl) {
6777
6786
  const { params, prologue } = L.declareParams(decl.parameters, sig.params);
6778
6787
  // The synthetic `arguments` slot (a dynRest shape BEYOND the declared
6779
6788
  // parameters — collectSignatureInner appended it): one trailing
6780
- // DOM-array param, resolved by `arguments` reads.
6789
+ // dyn-array param, resolved by `arguments` reads.
6781
6790
  if (sig.params.length > decl.parameters.length && sig.params[sig.params.length - 1].mode === "dynRest") {
6782
6791
  const argsLocal = L.declareHiddenLocal("%arguments", DYN);
6783
6792
  params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
@@ -7128,8 +7137,13 @@ export function nullishValueUnitOf(L, sym) {
7128
7137
  return cached;
7129
7138
  L.nullishBindings.set(sym, null); // cycle guard: self-referential probes answer non-qualifying
7130
7139
  const decl = L.checker.valueDeclarationOf(sym);
7140
+ // Statement-position declarators only: a for-loop head (`for (let x =
7141
+ // null as any; ...)`) declares a LOCAL with per-iteration semantics —
7142
+ // lowerVarDeclList's contract requires a lowered statement for it, so
7143
+ // the no-storage family never claims it.
7131
7144
  if (!decl || !ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) ||
7132
- decl.getSourceFile().isDeclarationFile || decl.initializer === undefined) {
7145
+ decl.getSourceFile().isDeclarationFile || decl.initializer === undefined ||
7146
+ !ts.isVariableStatement(decl.parent.parent)) {
7133
7147
  return null;
7134
7148
  }
7135
7149
  const unit = nullishExprUnitOf(L, decl.initializer);
@@ -7204,8 +7218,21 @@ export function nullishGenericBindingUnitOf(L, sym) {
7204
7218
  if (unit === null)
7205
7219
  return null;
7206
7220
  const mapped = L.mapTypeOf(L.checker.getTypeOfSymbol(sym));
7207
- if (mapped !== null && mapped.kind !== "record")
7208
- return null;
7221
+ if (mapped !== null) {
7222
+ // Only the EMPTY interned shape qualifies among record mappings —
7223
+ // the all-generic-signature interface (`I<A & B>`) whose struct has
7224
+ // no slot at all. A record with DATA fields (`const value: { inner:
7225
+ // number | string } = null as any`) keeps its real storage and
7226
+ // every ordinary lowering: its reads flow through positions (comma
7227
+ // chains, call arguments) the no-storage read paths never claim,
7228
+ // so claiming the binding would fence working programs.
7229
+ if (mapped.kind !== "record")
7230
+ return null;
7231
+ const shape = L.shapes.get(mapped.shapeId);
7232
+ if (!shape || shape.fields.length > 0 || shape.tuple !== undefined || shape.indexValue !== undefined) {
7233
+ return null;
7234
+ }
7235
+ }
7209
7236
  return unit;
7210
7237
  }
7211
7238
  /** True when every write of `sym` in its declaring file is a plain `x =
@@ -7297,6 +7324,13 @@ export function deadUnmappableBinding(L, sym, decl) {
7297
7324
  return true;
7298
7325
  if (!ts.isIdentifier(decl.name))
7299
7326
  return false;
7327
+ // Statement-position declarators only: a for-loop head (`for (let x;
7328
+ // false;) {}`) declares a LOCAL with per-iteration semantics —
7329
+ // lowerVarDeclList's contract requires a lowered statement for it, so
7330
+ // the no-storage family never claims it (catch bindings sit outside a
7331
+ // variable statement too and stay out the same way).
7332
+ if (!ts.isVariableStatement(decl.parent.parent))
7333
+ return false;
7300
7334
  const sf = decl.getSourceFile();
7301
7335
  if (sf.isDeclarationFile || isJsSourceFile(sf))
7302
7336
  return false;