@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
@@ -98,7 +98,7 @@ export declare function hoistVarBinding(L: Lowerer, symbol: ts.Symbol, nameNode:
98
98
  * such reads `undefined`, never a TDZ error, so the hoisted slot must
99
99
  * hold `undefined` from function entry — which is only honest for
100
100
  * undefined-armed union types (the interned arm) and checked-dynamic
101
- * bindings (the DOM undefined). Everything else returns false
101
+ * bindings (the dyn undefined). Everything else returns false
102
102
  * and the reference lands on the named fence in rejectUnresolvedSymbol:
103
103
  * a slot of a narrower type has no bit pattern for the `undefined` Node
104
104
  * would yield if the capture ran early, and guessing "it won't" is the
@@ -10,7 +10,7 @@ import { enforceLibBoundary } from "./lib-boundary.js";
10
10
  import { cjsExportAssignmentOf, cjsExportDiscardReason, cjsExportTargetLiteral, isCjsJsFile, isJsSourceFile, locOf, requireSpecOf } from "../program.js";
11
11
  import { COMPOUND_ASSIGN_OPS, STR_METHODS, UNSUPPORTED_STMT, isStdlibMember, sideEffectFreeOptionValue, stdlibGlobalAliasDecl, stdlibGlobalNameOf } from "./surfaces.js";
12
12
  import { isProvenanceSourceFile } from "../provenance-registry.js";
13
- import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget } from "./lower-namespaces.js";
13
+ import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget, trapDeclRootOf } from "./lower-namespaces.js";
14
14
  import { expandoWritableTarget, lowerExpandoAssignStmt } from "./lower-expando.js";
15
15
  import { lowerForOfArrayIter, lowerForOfMap, lowerForOfSearchParams, lowerForOfSet, objectIterOverIndexShape, strCharsCall } from "./lower-containers.js";
16
16
  import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishExprUnitOf, nullishGenericBindingUnitOf, recordKeysArrayCall } from "./lower-calls.js";
@@ -18,9 +18,9 @@ import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
18
18
  import { genericIfaceBindingKeepsClass } from "./lower-classes.js";
19
19
  import { lowerStreamUnderscoreAssign, streamClassAliasDecl, streamSidesOf } from "./lower-stream.js";
20
20
  import { lowerHttpResPropertyAssignment, lowerServerCloseOverrideAssignment } from "./lower-server.js";
21
- import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf } from "./lower-builtins.js";
21
+ import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl } from "./lower-builtins.js";
22
22
  import { lowerEnumDeclaration } from "./lower-enums.js";
23
- import { abstractPropertyDeclOf, aliasTypeofNarrows, probeLower, pureReemittable, symbolFieldInfo } from "./lower-exprs.js";
23
+ import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerGroupsProjection, matchResultNamedGroupsOf, probeLower, pureReemittable, symbolFieldInfo } from "./lower-exprs.js";
24
24
  import { checkerPanicDiag, isCheckerPanic, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
25
25
  import { isUnitOnlyTsType, unitOnlyUnion } from "../types.js";
26
26
  import { canonicalBuiltinModule, isRelativeSpecifier } from "../shared.js";
@@ -486,7 +486,7 @@ export function hoistVarBinding(L, symbol, nameNode) {
486
486
  const local = { id: `${name}.${count}`, name, type, mutable: true };
487
487
  L.ctx.locals.push(local);
488
488
  L.ctx.scopes[0].set(symbol, local);
489
- // A checked-dynamic slot holds the DOM undefined (a NULL dyn is a
489
+ // A checked-dynamic slot holds the dyn undefined (a NULL dyn is a
490
490
  // trap); everything else rides unassignedSlotInit (interned union arm,
491
491
  // engine undefined for jsval).
492
492
  const wrapped = type.kind === "dyn" ? dynUndefinedExpr(locOf(nameNode)) : L.unassignedSlotInit(type, locOf(nameNode));
@@ -502,7 +502,7 @@ export function hoistVarBinding(L, symbol, nameNode) {
502
502
  * such reads `undefined`, never a TDZ error, so the hoisted slot must
503
503
  * hold `undefined` from function entry — which is only honest for
504
504
  * undefined-armed union types (the interned arm) and checked-dynamic
505
- * bindings (the DOM undefined). Everything else returns false
505
+ * bindings (the dyn undefined). Everything else returns false
506
506
  * and the reference lands on the named fence in rejectUnresolvedSymbol:
507
507
  * a slot of a narrower type has no bit pattern for the `undefined` Node
508
508
  * would yield if the capture ran early, and guessing "it won't" is the
@@ -536,7 +536,7 @@ export function predeclareForwardVar(L, symbol) {
536
536
  const ctx = owner.ctx;
537
537
  // Only a slot that can hold `undefined` can carry the pre-
538
538
  // initialization reads: an undefined-armed union (the interned arm),
539
- // a checked-dynamic binding (the DOM undefined), or a jsval 'any'
539
+ // a checked-dynamic binding (the dyn undefined), or a jsval 'any'
540
540
  // binding (the engine's undefined).
541
541
  const type = varBindingType(L, nameNode);
542
542
  if (!type)
@@ -757,7 +757,7 @@ export function lowerStmt(L, stmt) {
757
757
  // A bare `return;` in a union-returning function yields undefined
758
758
  // (JS), which the undefined arm carries — tsc only allows the bare
759
759
  // form when the return type includes undefined/void. A CHECKED-
760
- // DYNAMIC return slot holds the DOM undefined directly (the
760
+ // DYNAMIC return slot holds the dyn undefined directly (the
761
761
  // appendImplicitUndefinedReturn rule). What remains is JS-only —
762
762
  // a JSDoc return claim the body contradicts (ms's parse: `@return
763
763
  // {Number}` with a bare early `return;`): no undefined fits the
@@ -819,11 +819,11 @@ export function lowerStmt(L, stmt) {
819
819
  const value = L.lowerExpr(stmt.expression);
820
820
  if (value.type.kind === "void")
821
821
  L.badType(stmt.expression, L.typeOf(stmt.expression));
822
- // A dyn throw rides the REF cell arm (scr_throw_ref over the DOM
822
+ // A dyn throw rides the REF cell arm (scr_throw_ref over the checked-dynamic tree
823
823
  // node — identity preserved through catch bindings, caughtToDyn
824
824
  // passes it back by reference). The JS-lane traced-call shape:
825
- // `throw err` where err arrived as a DOM argument. instanceof
826
- // narrowing over the payload stays false (the DOM's %error encoding
825
+ // `throw err` where err arrived as a dyn argument. instanceof
826
+ // narrowing over the payload stays false (the checked-dynamic tree's %error encoding
827
827
  // is not a hierarchy object — SEMANTICS.md).
828
828
  return { kind: "throw", value, loc: locOf(stmt) };
829
829
  }
@@ -1018,7 +1018,7 @@ export function lowerDestructuringDecl(L, decl, isLet) {
1018
1018
  let init = L.lowerExpr(decl.initializer);
1019
1019
  // A TS `any`-origin source whose lowered value is NOT a destructurable
1020
1020
  // shape (`var { x } = <any>0` — the cast erases to the f64; a dyn
1021
- // value — the DOM has no destructure): JS reads the properties off
1021
+ // value — the checked-dynamic tree has no destructure): JS reads the properties off
1022
1022
  // whatever the value is (a number answers undefined) — engine
1023
1023
  // semantics, the dynamic-family fence. Record and array sources fall
1024
1024
  // through to their lowerings, island handles to theirs (--dynamic
@@ -1103,6 +1103,39 @@ export function lowerDestructuringDecl(L, decl, isLet) {
1103
1103
  init = { kind: "unionNarrow", unionId: init.type.unionId, tag, value: uref, type: arm, loc };
1104
1104
  }
1105
1105
  }
1106
+ // `const { groups } = re.exec(s)!` / `const { groups: { year } } = m`
1107
+ // — every pattern element binds `groups` off a MATCH SLICE whose
1108
+ // regex is statically known: the slice has no record shape of its
1109
+ // own, so the groups projection (lowerGroupsProjection — the same
1110
+ // record `m.groups` reads produce) wraps one level in a synthesized
1111
+ // `{ groups: ... }` record and the ordinary record destructure below
1112
+ // serves the pattern — aliases and nested patterns included. Only
1113
+ // named-group regexes take the wrap: a group-less regex destructures
1114
+ // `groups: undefined` in Node (a nested pattern then throws), which
1115
+ // the fence reports honestly instead.
1116
+ if (ts.isObjectBindingPattern(decl.name) &&
1117
+ decl.name.elements.length > 0 &&
1118
+ isMatchSliceType(L, init.type) &&
1119
+ decl.name.elements.every((el) => {
1120
+ if (el.dotDotDotToken !== undefined || el.name === undefined)
1121
+ return false;
1122
+ const prop = el.propertyName;
1123
+ if (prop === undefined)
1124
+ return ts.isIdentifier(el.name) && el.name.text === "groups";
1125
+ return (ts.isIdentifier(prop) || ts.isStringLiteral(prop)) && prop.text === "groups";
1126
+ })) {
1127
+ const groups = matchResultNamedGroupsOf(L, decl.initializer);
1128
+ if (groups !== null && groups.length > 0) {
1129
+ const proj = lowerGroupsProjection(L, init, groups, loc);
1130
+ const outerShape = L.shapes.intern([{ name: "groups", type: proj.type }], false, undefined, ["groups"]);
1131
+ init = {
1132
+ kind: "recordLit",
1133
+ fields: [{ name: "groups", value: proj }],
1134
+ type: { kind: "record", shapeId: outerShape },
1135
+ loc,
1136
+ };
1137
+ }
1138
+ }
1106
1139
  const tmp = L.declareHiddenLocal("%destr", init.type);
1107
1140
  out.push({ kind: "varDecl", localId: tmp.id, init, loc });
1108
1141
  // V8's destructuring TypeError spells STATIC sources: an identifier
@@ -1243,16 +1276,16 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
1243
1276
  L.lowerBindingPattern(pattern, () => ({ kind: "varRef", localId: chars.id, type: charsT, loc }), charsT, isLet, out);
1244
1277
  return;
1245
1278
  }
1246
- // DYN sources (`const [a, b] = d` over a DOM value, `([_, code]) =>`
1279
+ // DYN sources (`const [a, b] = d` over a dyn value, `([_, code]) =>`
1247
1280
  // params destructuring dyn callback arguments — the suite harness's
1248
1281
  // _expectWarning shapes): the source packs ONCE through the spread
1249
1282
  // walk (dyn.iterPack — arrays element-by-element, strings by code
1250
1283
  // point, bytes by byte; every other kind throws V8's destructuring
1251
1284
  // TypeError, the compile-time spelling when the source has one),
1252
1285
  // then positions bind the pack's index keys as dyn values — reads
1253
- // past the end bind undefined, exactly JS. Defaults fire on the DOM
1286
+ // past the end bind undefined, exactly JS. Defaults fire on the checked-dynamic tree
1254
1287
  // undefined (JS's rule); rest elements keep the fence (surplus
1255
- // packing over the DOM needs a slice the IR does not spell yet).
1288
+ // packing over the checked-dynamic tree needs a slice the IR does not spell yet).
1256
1289
  if (srcType.kind === "dyn") {
1257
1290
  const loc = locOf(pattern);
1258
1291
  const pack = L.declareHiddenLocal("%dpack", DYN);
@@ -1283,14 +1316,14 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
1283
1316
  loc: elLoc,
1284
1317
  };
1285
1318
  if (el.initializer) {
1286
- // The default fires exactly on the DOM undefined (JS's rule),
1287
- // its value converting into the DOM like any dyn-slot value.
1319
+ // The default fires exactly on the dyn undefined (JS's rule),
1320
+ // its value converting into the checked-dynamic tree like any dyn-slot value.
1288
1321
  const rl = L.declareHiddenLocal("%delem", DYN);
1289
1322
  out.push({ kind: "varDecl", localId: rl.id, init: value, loc: elLoc });
1290
1323
  const ref = () => ({ kind: "varRef", localId: rl.id, type: DYN, loc: elLoc });
1291
1324
  const dflt = L.coerceToExpected(L.lowerExpr(el.initializer), DYN);
1292
1325
  if (dflt.type.kind !== "dyn") {
1293
- L.unsupported("SC1031", el.initializer, `defaults of '${L.fmt(dflt.type)}' type over checked-dynamic sources (the value cannot convert into the DOM)`);
1326
+ L.unsupported("SC1031", el.initializer, `defaults of '${L.fmt(dflt.type)}' type over checked-dynamic sources (the value cannot convert into the checked-dynamic tree)`);
1294
1327
  }
1295
1328
  value = {
1296
1329
  kind: "ternary",
@@ -1586,6 +1619,29 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
1586
1619
  continue;
1587
1620
  }
1588
1621
  const fieldType = shape.fields.find((f) => f.name === propName)?.type;
1622
+ if (!fieldType && shape.indexValue !== undefined && !shape.tuple) {
1623
+ // An UNDECLARED key of an INDEX-SIGNATURE shape (`const { m, n, p }
1624
+ // = ....groups` over `{ [key: string]: string }` — the groups
1625
+ // record, `Record<string, T>` tables generally): the overflow-map
1626
+ // read, exactly the dot access's recordKeyGet — a missing key
1627
+ // traps when the value type carries no undefined arm (the checker
1628
+ // claimed V), or binds the undefined arm (where a default applies
1629
+ // like any field's).
1630
+ const loc = locOf(el);
1631
+ let value = {
1632
+ kind: "recordKeyGet",
1633
+ obj: srcRef(),
1634
+ shapeId: srcType.shapeId,
1635
+ key: { kind: "strLit", value: propName, type: STRING, loc },
1636
+ overflowOnly: true,
1637
+ type: shape.indexValue,
1638
+ loc,
1639
+ };
1640
+ if (el.initializer)
1641
+ value = applyBindingDefault(L, el, value);
1642
+ L.bindPatternTarget(el.name, value, isLet, out);
1643
+ continue;
1644
+ }
1589
1645
  if (!fieldType) {
1590
1646
  // The pattern names a field the source SHAPE does not carry —
1591
1647
  // `for (let {x = 1} of [{}])` (signature 08): tsc types the binding
@@ -2481,7 +2537,7 @@ export function bindPatternTarget(L, name, value, isLet, out) {
2481
2537
  // a pattern binding whose VALUE lowered checked-dynamic stays dyn
2482
2538
  // where the checker spells an island-world type (`function f({
2483
2539
  // plugins = [] } = {})` over a JSDoc '(string | object)[]=' member —
2484
- // the read is a DOM keyed read whose members may be wrapped island
2540
+ // the read is a dyn keyed read whose members may be wrapped island
2485
2541
  // values) or a type with no mapping at all (the varDecl rule's
2486
2542
  // unmappable-declared-type stance, `string | object` bindings
2487
2543
  // included). Marshaling here would fence or deep-copy; the value's
@@ -2566,8 +2622,10 @@ export function lowerVarDecl(L, decl, isLet) {
2566
2622
  // statement lowers to exactly that throw; the binding registers as a
2567
2623
  // trap (references lower to the same never-reached shape), and no
2568
2624
  // storage or type mapping is needed for a value that never exists.
2569
- if (decl.initializer !== undefined) {
2570
- const root = ambientUndefVarRootOf(L, decl.initializer);
2625
+ // Written bindings keep ordinary storage (trapDeclRootOf) — the
2626
+ // initializer read still lowers to the root's throw below.
2627
+ {
2628
+ const root = trapDeclRootOf(L, decl);
2571
2629
  if (root !== null) {
2572
2630
  for (const nameNode of boundIdentifiersOf(decl.name)) {
2573
2631
  const sym = L.checker.getSymbolAtLocation(nameNode);
@@ -2631,6 +2689,17 @@ export function lowerVarDecl(L, decl, isLet) {
2631
2689
  // skipped its global by the same test).
2632
2690
  if (builtinMemberRequireDecl(decl.name, decl.initializer))
2633
2691
  return null;
2692
+ // `const require = createRequire(import.meta.url)` — compile-time
2693
+ // plumbing: each call through the binding resolves per site
2694
+ // (lowerCreateRequireCall); no storage, no code (collectGlobals
2695
+ // skipped its global by the same test).
2696
+ if (!isLet && createRequireBindingDecl(L, decl.name, decl.initializer))
2697
+ return null;
2698
+ // `const fs = require("node:fs")` through that binding — a builtin
2699
+ // namespace import in const clothing: alias plumbing, no storage
2700
+ // (builtinNamespaceModuleOf resolves member uses).
2701
+ if (!isLet && createRequireNamespaceDecl(L, decl.name, decl.initializer))
2702
+ return null;
2634
2703
  // `const { NGHTTP2_CANCEL } = http2.constants` — a destructure over
2635
2704
  // the baked constants table: alias plumbing, no storage (uses read
2636
2705
  // their literals via http2ConstantBindingOf; collectGlobals skipped
@@ -2721,7 +2790,7 @@ export function lowerVarDecl(L, decl, isLet) {
2721
2790
  // a loop — must NOT reset the persisting binding.
2722
2791
  if (isVarDeclared(decl))
2723
2792
  return null;
2724
- // Checked-dynamic globals hold the DOM undefined from their
2793
+ // Checked-dynamic globals hold the dyn undefined from their
2725
2794
  // declaration statement on; unions and jsval ride
2726
2795
  // unassignedSlotInit's arms.
2727
2796
  const wrapped = g.type.kind === "dyn" ? dynUndefinedExpr(locOf(decl)) : L.unassignedSlotInit(g.type, locOf(decl));
@@ -2776,7 +2845,7 @@ export function lowerVarDecl(L, decl, isLet) {
2776
2845
  const local = L.declareLocal(decl.name, decl.name.text, type, isLet);
2777
2846
  // tsc's definite-assignment analysis never guards `any` reads, so
2778
2847
  // uninitialized bindings must hold their world's undefined, never
2779
- // NULL: unions the interned arm, dyn the DOM undefined, jsval the
2848
+ // NULL: unions the interned arm, dyn the dyn undefined, jsval the
2780
2849
  // engine's — all readable immediately, exactly Node.
2781
2850
  const init = type.kind === "dyn" ? dynUndefinedExpr(locOf(decl)) : L.unassignedSlotInit(type, locOf(decl));
2782
2851
  return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
@@ -2800,7 +2869,7 @@ export function lowerVarDecl(L, decl, isLet) {
2800
2869
  }
2801
2870
  // A dyn initializer under an unmappable declared type (`const ws =
2802
2871
  // pkg.workspaces` — the lowering world types the unknown-receiver read
2803
- // `any`, which a static build cannot hold): the VALUE is a DOM
2872
+ // `any`, which a static build cannot hold): the VALUE is a dyn
2804
2873
  // subtree, so the local stays dyn — later narrowing tests and checked
2805
2874
  // casts read it like any JSON.parse result.
2806
2875
  // `const p = import("./m")` / `const ns = await import("./m")`: the
@@ -2825,7 +2894,7 @@ export function lowerVarDecl(L, decl, isLet) {
2825
2894
  // the island-HANDLE local rule's mirror): a binding whose
2826
2895
  // INITIALIZER lowered checked-dynamic stays dyn even where the
2827
2896
  // checker spells 'any' (`const parsers = options.parsers ?? {}` over
2828
- // an 'object'-typed bag — the read is a DOM keyed read). Marshaling
2897
+ // an 'object'-typed bag — the read is a dyn keyed read). Marshaling
2829
2898
  // into the engine here would deep-copy data and sever aliasing; the
2830
2899
  // value's world is the honest dispatch, and every use site already
2831
2900
  // handles dyn (validated exits, routed engine ops for wrapped
@@ -2852,7 +2921,7 @@ export function lowerVarDecl(L, decl, isLet) {
2852
2921
  // pushes of anything non-numeric would fence and typed exits would
2853
2922
  // mismatch the checker's evolved reads downstream. The binding is
2854
2923
  // checked-dynamic instead (the `let x = {}` stance, and lower-modules'
2855
- // file-scope evolving-array rule): pushes ride the DOM array, typed
2924
+ // file-scope evolving-array rule): pushes ride the dyn array, typed
2856
2925
  // exits dynCheck.
2857
2926
  if ((type === null || type.kind === "array") && isJsSourceFile(decl.getSourceFile())) {
2858
2927
  let initExpr = decl.initializer;
@@ -2931,6 +3000,15 @@ export function lowerVarDecl(L, decl, isLet) {
2931
3000
  // bridge is an independent observer of the same settlement).
2932
3001
  if (init.type.kind === "jsval" && type.kind === "promise")
2933
3002
  type = JSVAL;
3003
+ // An island value under an `any[]`-declared LOCAL spelling stays an
3004
+ // island HANDLE too (the runtime-world rule): the jsval-element-array
3005
+ // exit is a CALL-boundary conversion (the loadPlugins param ABI) —
3006
+ // converting a local would strand the engine's own prototypes
3007
+ // (join/map/... on a native handle-element array), where the handle
3008
+ // routes every use engine-side.
3009
+ if (init.type.kind === "jsval" && type.kind === "array" && type.elem.kind === "jsval") {
3010
+ type = JSVAL;
3011
+ }
2934
3012
  // A STATIC array of island HANDLES under an unannotated declared type
2935
3013
  // spelling evolved elements (`const kept = fns.filter(...)` over an
2936
3014
  // evolving-`any` receiver — the handle-element lowering keeps the
@@ -3647,7 +3725,12 @@ export function lowerExprStatement(L, expr) {
3647
3725
  ts.isExpressionStatement(stmtNode) &&
3648
3726
  ts.isSourceFile(stmtNode.parent) &&
3649
3727
  isJsSourceFile(stmtNode.parent);
3650
- if (requireSpecOf(expr) !== null && ts.isCallExpression(expr) && ts.isIdentifier(expr.expression)) {
3728
+ if (requireSpecOf(expr) !== null &&
3729
+ ts.isCallExpression(expr) &&
3730
+ ts.isIdentifier(expr.expression) &&
3731
+ // A binding NAMED require made by createRequire is not the CJS
3732
+ // global — the expression path owns it (lowerCreateRequireCall).
3733
+ createRequireCalleeFileOf(L, expr.expression) === null) {
3651
3734
  const sf = expr.getSourceFile();
3652
3735
  // A bare require of a package NOTHING INSTALLED resolves, in ANY
3653
3736
  // CommonJS JS file (the export-assignment spellings tsgo marks
@@ -3773,7 +3856,7 @@ export function lowerExprStatement(L, expr) {
3773
3856
  const loc = locOf(expr);
3774
3857
  // Dispatch follows the RUNTIME world (383(d)): a checker-'any'
3775
3858
  // receiver whose value LOWERED checked-dynamic (`bag.nested.x
3776
- // = v` behind an 'object'-typed bag) takes the DOM keyed
3859
+ // = v` behind an 'object'-typed bag) takes the dyn keyed
3777
3860
  // write — the routed JSVAL arm lands it on the real engine
3778
3861
  // object.
3779
3862
  if (obj.type.kind === "dyn") {
@@ -3870,7 +3953,7 @@ export function lowerExprStatement(L, expr) {
3870
3953
  }
3871
3954
  // `h.onDone = cb` on a CHECKED-DYNAMIC receiver (a JS `let h =
3872
3955
  // {}` evolving object, an implicit-any param, a dyn member
3873
- // chain): the DOM keyed write — the value converts INTO dyn
3956
+ // chain): the dyn keyed write — the value converts INTO dyn
3874
3957
  // (closures box), the runtime sets the member on OBJ receivers
3875
3958
  // and throws Node's TypeErrors on the rest. The receiver is
3876
3959
  // PROBED (probeLower) and claimed exactly when it lowers to
@@ -3890,7 +3973,7 @@ export function lowerExprStatement(L, expr) {
3890
3973
  }
3891
3974
  // `events.defaultMaxListeners = v` in STATEMENT position — the
3892
3975
  // module-property write Node validates (the lowerBinary
3893
- // expression twin): the value crosses into the DOM, the runtime
3976
+ // expression twin): the value crosses into the checked-dynamic tree, the runtime
3894
3977
  // ladder throws Node's exact errors, valid numbers apply.
3895
3978
  if (!expr.left.questionDotToken && expr.left.name.text === "defaultMaxListeners") {
3896
3979
  const bi = L.builtinMemberOf(expr.left);
@@ -4194,7 +4277,7 @@ function lowerCompoundToTarget(L, expr, compound, target) {
4194
4277
  isJsSourceFile(expr.getSourceFile())) {
4195
4278
  // JS any-origin operands: check to number and compute natively
4196
4279
  // (the binary-operator stance) — the dyn target takes the result
4197
- // back through the usual DOM conversion.
4280
+ // back through the usual dyn conversion.
4198
4281
  const checkNum = (e) => e.type.kind === "dyn" ? { kind: "dynCheck", value: e, type: F64, loc: e.loc } : e;
4199
4282
  const computed = { kind: "bin", op: compound, left: checkNum(read), right: checkNum(rhs), type: F64, loc };
4200
4283
  value = target.type.kind === "dyn" ? { kind: "dynFrom", value: computed, type: DYN, loc } : computed;
@@ -5026,7 +5109,7 @@ function destructAssignPiece(L, prop, islandSource) {
5026
5109
  // keys resolve statically (the record path's rule) — the keyed read
5027
5110
  // below takes the folded name. A RUNTIME-valued key over an ISLAND
5028
5111
  // source reads through the engine's own indexing at the element's
5029
- // pattern position (`({ [key]: w } = src)`); over the DOM the fence
5112
+ // pattern position (`({ [key]: w } = src)`); over the checked-dynamic tree the fence
5030
5113
  // stays.
5031
5114
  const folded = patternKeyNameOf(L, prop.name);
5032
5115
  if (folded === null) {
@@ -5476,12 +5559,12 @@ export function lowerForOf(L, stmt) {
5476
5559
  if (iterable.type.kind === "jsval") {
5477
5560
  return lowerForOfIsland(L, stmt, iterable, labels);
5478
5561
  }
5479
- // A CHECKED-DYNAMIC iterable (`unknown[]` and the collapsed
5480
- // `(string | object)[]` are DOM values now, so the TYPE maps —
5481
- // badType would tell a stale component story): the OPERATION is
5482
- // the gap — name it, with the validated-cast escape hatch.
5562
+ // A CHECKED-DYNAMIC iterable (`unknown[]`, the collapsed
5563
+ // `(string | object)[]`, JSON-parsed values, wrapped engine
5564
+ // values): the source packs ONCE through the spread walk and a
5565
+ // hidden index loop binds each element as a dyn value.
5483
5566
  if (iterable.type.kind === "dyn") {
5484
- L.unsupported("SC1090", stmt.expression, "for-of over checked-dynamic ('unknown') values (validate into a typed array first — `u as string[]` — or index with a counted loop: length and element reads compile)");
5567
+ return lowerForOfDyn(L, stmt, iterable, labels);
5485
5568
  }
5486
5569
  if (iterable.type.kind !== "array") {
5487
5570
  L.badType(stmt.expression, L.typeOf(stmt.expression));
@@ -5854,6 +5937,158 @@ function lowerForOfClassIterator(L, stmt, iterable, cit, labels) {
5854
5937
  * (break/return out of a partial iteration calling it.return()) is NOT
5855
5938
  * run — a divergence only a custom island iterator with a return()
5856
5939
  * method can observe. */
5940
+ /** For-of over a CHECKED-DYNAMIC iterable: the source packs ONCE
5941
+ * through the spread walk (dyn.iterPack — dyn arrays element-by-
5942
+ * element, strings by code point, bytes by byte; a WRAPPED engine
5943
+ * value drains through the ENGINE's own iterator protocol via the
5944
+ * iter_drain arm; every other kind throws V8's not-iterable
5945
+ * TypeError, the identifier spelling when the head has one), then a
5946
+ * hidden index loop binds each element as a dyn value. The pack is an
5947
+ * eager SNAPSHOT (the matchAll stance): body mutations of a dyn-array
5948
+ * source don't extend the iteration where JS's live array iterator
5949
+ * would — documented divergence; engine sources drain through their
5950
+ * own protocol, so generators/Maps/Sets step exactly once like Node. */
5951
+ function lowerForOfDyn(L, stmt, iterable, labels) {
5952
+ const loc = locOf(stmt);
5953
+ const head = stmt.expression;
5954
+ // V8's for-of CallPrinter spellings: named sources (identifiers and
5955
+ // plain property chains) read "<src> is not iterable", call heads
5956
+ // with a nameable callee "<callee> is not a function or its return
5957
+ // value is not iterable"; everything else keeps the runtime kind
5958
+ // wording. The runtime uses the spelling VERBATIM when non-empty.
5959
+ const headText = (e) => {
5960
+ if (ts.isIdentifier(e))
5961
+ return e.text;
5962
+ if (ts.isPropertyAccessExpression(e) && !e.questionDotToken && ts.isIdentifier(e.name)) {
5963
+ const base = headText(e.expression);
5964
+ return base !== null ? `${base}.${e.name.text}` : null;
5965
+ }
5966
+ return null;
5967
+ };
5968
+ const headName = headText(head);
5969
+ const calleeName = ts.isCallExpression(head) ? headText(head.expression) : null;
5970
+ const spell = headName !== null
5971
+ ? `${headName} is not iterable`
5972
+ : calleeName !== null
5973
+ ? `${calleeName} is not a function or its return value is not iterable`
5974
+ : "";
5975
+ const pack = L.declareHiddenLocal("%dofpack", DYN);
5976
+ const idx = L.declareHiddenLocal("%dofi", F64);
5977
+ idx.mutable = true;
5978
+ const packRef = () => ({ kind: "varRef", localId: pack.id, type: DYN, loc });
5979
+ const iRef = () => ({ kind: "varRef", localId: idx.id, type: F64, loc });
5980
+ const elemInit = () => ({ kind: "libCall", fn: "dyn.arrAt", args: [packRef(), iRef()], type: DYN, loc });
5981
+ L.scopes.push(new Map());
5982
+ try {
5983
+ const binds = [];
5984
+ if (!ts.isVariableDeclarationList(stmt.initializer)) {
5985
+ // Pre-declared heads: identifier targets assign the existing
5986
+ // binding once per pass (JS's shared-binding rule); literal
5987
+ // patterns run the destructuring-assignment machinery over the
5988
+ // dyn element; member targets keep the fence.
5989
+ let target = stmt.initializer;
5990
+ while (ts.isParenthesizedExpression(target))
5991
+ target = target.expression;
5992
+ const tmp = L.declareHiddenLocal("%vof", DYN);
5993
+ binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
5994
+ const elemRef = { kind: "varRef", localId: tmp.id, type: DYN, loc };
5995
+ if (ts.isArrayLiteralExpression(target) || ts.isObjectLiteralExpression(target)) {
5996
+ binds.push(lowerDestructuringAssign(L, target, elemRef, target, loc));
5997
+ }
5998
+ else if (ts.isIdentifier(target) && L.resolveWritable(target)) {
5999
+ const writable = L.resolveWritable(target);
6000
+ binds.push({
6001
+ kind: "assign",
6002
+ localId: writable.id,
6003
+ value: L.coerceInto(target, elemRef, writable.type),
6004
+ loc,
6005
+ });
6006
+ }
6007
+ else {
6008
+ L.unsupported("SC1090", stmt.initializer, "for-of over a pre-declared variable (declare the loop variable in the loop: for (const x of ...))");
6009
+ }
6010
+ }
6011
+ else {
6012
+ const list = stmt.initializer;
6013
+ if ((list.flags & ts.NodeFlags.Using) !== 0) {
6014
+ L.unsupported("SC1090", list, "'using' declarations (dispose-at-scope-exit semantics)");
6015
+ }
6016
+ const isLet = (list.flags & ts.NodeFlags.Let) !== 0 || (list.flags & ts.NodeFlags.BlockScoped) === 0;
6017
+ const decl = list.declarations[0];
6018
+ if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
6019
+ const tmp = L.declareHiddenLocal("%destr", DYN);
6020
+ binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
6021
+ L.lowerBindingPattern(decl.name, () => ({ kind: "varRef", localId: tmp.id, type: DYN, loc }), DYN, isLet, binds);
6022
+ }
6023
+ else if (ts.isIdentifier(decl.name)) {
6024
+ const varTarget = forOfVarTarget(L, decl);
6025
+ if (varTarget) {
6026
+ // `for (var x of d)`: the element mechanics stay on a hidden
6027
+ // per-iteration local; the body opens by assigning the ONE
6028
+ // hoisted var binding (the array head's rule).
6029
+ const tmp = L.declareHiddenLocal("%vof", DYN);
6030
+ binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
6031
+ binds.push({
6032
+ kind: "assign",
6033
+ localId: varTarget.id,
6034
+ value: L.coerceInto(decl.name, { kind: "varRef", localId: tmp.id, type: DYN, loc }, varTarget.type),
6035
+ loc,
6036
+ });
6037
+ }
6038
+ else {
6039
+ const local = L.declareLocal(decl.name, decl.name.text, DYN, isLet);
6040
+ binds.push({ kind: "varDecl", localId: local.id, init: elemInit(), loc });
6041
+ }
6042
+ }
6043
+ else {
6044
+ L.unsupported("SC1031", decl.name);
6045
+ }
6046
+ }
6047
+ const body = L.inCtl("loop", () => L.lowerScopedBlock(stmt.statement), labels);
6048
+ return {
6049
+ kind: "block",
6050
+ body: [
6051
+ {
6052
+ kind: "varDecl",
6053
+ localId: pack.id,
6054
+ init: {
6055
+ kind: "libCall",
6056
+ fn: "dyn.iterPack",
6057
+ args: [iterable, { kind: "strLit", value: spell, type: STRING, loc }],
6058
+ type: DYN,
6059
+ loc,
6060
+ },
6061
+ loc,
6062
+ },
6063
+ {
6064
+ kind: "for",
6065
+ init: { kind: "varDecl", localId: idx.id, init: { kind: "numLit", value: 0, type: F64, loc }, loc },
6066
+ cond: {
6067
+ kind: "bin",
6068
+ op: "<",
6069
+ left: iRef(),
6070
+ right: { kind: "libCall", fn: "dyn.arrLen", args: [packRef()], type: F64, loc },
6071
+ type: BOOL,
6072
+ loc,
6073
+ },
6074
+ update: {
6075
+ kind: "assign",
6076
+ localId: idx.id,
6077
+ value: { kind: "bin", op: "+", left: iRef(), right: { kind: "numLit", value: 1, type: F64, loc }, type: F64, loc },
6078
+ loc,
6079
+ },
6080
+ body: [...binds, ...body],
6081
+ ...(labels && { labels }),
6082
+ loc,
6083
+ },
6084
+ ],
6085
+ loc,
6086
+ };
6087
+ }
6088
+ finally {
6089
+ L.scopes.pop();
6090
+ }
6091
+ }
5857
6092
  function lowerForOfIsland(L, stmt, iterable, labels) {
5858
6093
  const loc = locOf(stmt);
5859
6094
  if (!ts.isVariableDeclarationList(stmt.initializer)) {