@scriptc/compiler 0.0.11 → 0.0.13

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 (97) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +153 -24
  2. package/ambient/scriptc.d.ts +2 -2
  3. package/dist/backend/cc.d.ts +10 -2
  4. package/dist/backend/cc.js +12 -0
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/emission/emit-async.js +1 -1
  7. package/dist/backend/emission/emit-exprs.js +235 -64
  8. package/dist/backend/emission/emit-exprs.js.map +1 -1
  9. package/dist/backend/emission/emit-island.js +1 -1
  10. package/dist/backend/emission/emit-shapes.js +1 -1
  11. package/dist/backend/emission/emit-walkers.d.ts +14 -14
  12. package/dist/backend/emission/emit-walkers.js +44 -44
  13. package/dist/backend/emission/emit-walkers.js.map +1 -1
  14. package/dist/backend/emission/emitter.d.ts +3 -3
  15. package/dist/backend/emission/emitter.js +8 -8
  16. package/dist/backend/emission/may-throw.js +1 -1
  17. package/dist/backend/llvm/dyn.d.ts +10 -10
  18. package/dist/backend/llvm/dyn.js +26 -26
  19. package/dist/backend/llvm/dyn.js.map +1 -1
  20. package/dist/backend/llvm/emitter.js +140 -49
  21. package/dist/backend/llvm/emitter.js.map +1 -1
  22. package/dist/backend/llvm/shapes.js +1 -1
  23. package/dist/backend/llvm/walkers.js +2 -2
  24. package/dist/backend/llvm/walkers.js.map +1 -1
  25. package/dist/diagnostics/diagnostic.d.ts +1 -1
  26. package/dist/diagnostics/diagnostic.js +4 -3
  27. package/dist/diagnostics/diagnostic.js.map +1 -1
  28. package/dist/frontend/lowering/crypto-tables.d.ts +7 -0
  29. package/dist/frontend/lowering/crypto-tables.js +139 -0
  30. package/dist/frontend/lowering/crypto-tables.js.map +1 -0
  31. package/dist/frontend/lowering/lib-boundary.js +5 -5
  32. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  33. package/dist/frontend/lowering/lower-assert.js +12 -12
  34. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  35. package/dist/frontend/lowering/lower-builtins.d.ts +45 -27
  36. package/dist/frontend/lowering/lower-builtins.js +203 -70
  37. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  38. package/dist/frontend/lowering/lower-calls.d.ts +4 -4
  39. package/dist/frontend/lowering/lower-calls.js +74 -66
  40. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  41. package/dist/frontend/lowering/lower-classes.js +41 -7
  42. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  43. package/dist/frontend/lowering/lower-containers.d.ts +5 -5
  44. package/dist/frontend/lowering/lower-containers.js +19 -19
  45. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  46. package/dist/frontend/lowering/lower-emitter.js +2 -2
  47. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  48. package/dist/frontend/lowering/lower-exprs.d.ts +7 -7
  49. package/dist/frontend/lowering/lower-exprs.js +227 -119
  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.js +17 -17
  56. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  57. package/dist/frontend/lowering/lower-namespaces.d.ts +11 -1
  58. package/dist/frontend/lowering/lower-namespaces.js +41 -6
  59. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  60. package/dist/frontend/lowering/lower-server.d.ts +21 -0
  61. package/dist/frontend/lowering/lower-server.js +278 -23
  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 +195 -34
  65. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  66. package/dist/frontend/lowering/lower-stream.js +67 -23
  67. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  68. package/dist/frontend/lowering/lowerer.d.ts +31 -13
  69. package/dist/frontend/lowering/lowerer.js +99 -45
  70. package/dist/frontend/lowering/lowerer.js.map +1 -1
  71. package/dist/frontend/lowering/surfaces.d.ts +6 -0
  72. package/dist/frontend/lowering/surfaces.js +78 -2
  73. package/dist/frontend/lowering/surfaces.js.map +1 -1
  74. package/dist/frontend/program.js +1 -1
  75. package/dist/frontend/shared.js +7 -7
  76. package/dist/frontend/shared.js.map +1 -1
  77. package/dist/frontend/types.d.ts +2 -2
  78. package/dist/frontend/types.js +27 -15
  79. package/dist/frontend/types.js.map +1 -1
  80. package/dist/index.js +44 -8
  81. package/dist/index.js.map +1 -1
  82. package/dist/ir/nodes.d.ts +208 -106
  83. package/dist/ir/nodes.js +100 -22
  84. package/dist/ir/nodes.js.map +1 -1
  85. package/dist/ir/validate.js +96 -38
  86. package/dist/ir/validate.js.map +1 -1
  87. package/dist/library/int-infer.js +13 -0
  88. package/dist/library/int-infer.js.map +1 -1
  89. package/dist/library/profile.d.ts +8 -6
  90. package/dist/library/profile.js.map +1 -1
  91. package/dist/library/sidecar-validate.js +1 -1
  92. package/dist/library/sidecar-validate.js.map +1 -1
  93. package/dist/library/sidecar.d.ts +1 -1
  94. package/dist/library/sidecar.js +20 -7
  95. package/dist/library/sidecar.js.map +1 -1
  96. package/package.json +2 -2
  97. package/surface-manifest.json +289 -4
@@ -17,7 +17,7 @@ import { unsupportedModuleFeatureOf } from "../shared.js";
17
17
  import { fenceEnumObjectValue, lowerEnumAccess } from "./lower-enums.js";
18
18
  import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, contextualUndefReadType, fenceEarlyAliasUse, fenceEarlyNsMemberRef, lowerNsIdentifierValue, nsMemberIdentOf, nsUndefRead, nsWritableTarget } from "./lower-namespaces.js";
19
19
  import { expandoMemberRead, expandoWritableTarget } from "./lower-expando.js";
20
- import { lowerSocketInstanceOf } from "./lower-server.js";
20
+ import { lowerSocketInstanceOf, lowerTlsRootCertificates } from "./lower-server.js";
21
21
  import { findGenericMethodOn, lowerStaticFieldRead } from "./lower-classes.js";
22
22
  import { bindingNeverReassigned, implicitMonoFile, lowerTaggedTemplate, nullishGenericBindingUnitOf, objLitGenericFnInfoOf, objLitGenericFnNodeOf, requireObjLitGenericReceiver } from "./lower-calls.js";
23
23
  import { mixinFnOfCallee } from "./lower-mixins.js";
@@ -222,9 +222,9 @@ function lowerExprInner(L, expr) {
222
222
  // A JS variable INITIALIZER whose BINDING registered as a
223
223
  // checked-dynamic module global (the typedef-annotated
224
224
  // doc-builder consts whose JSDoc types degraded — DYN slots):
225
- // the island build could never land (no engine→DOM crossing
225
+ // the island build could never land (no engine→dyn crossing
226
226
  // exists), so the literal takes its own world's path instead —
227
- // the DOM literal, or a static record the slot converts.
227
+ // the dyn literal, or a static record the slot converts.
228
228
  if (isJsSourceFile(expr.getSourceFile()) &&
229
229
  ts.isVariableDeclaration(expr.parent) &&
230
230
  expr.parent.initializer === expr &&
@@ -239,7 +239,7 @@ function lowerExprInner(L, expr) {
239
239
  // reference degraded to checker-`any` — the tsgo multi-file
240
240
  // value-as-type residue) is not an npm slot: when the literal's
241
241
  // OWN type maps statically, it builds that way — the binding's
242
- // checked-dynamic slot takes the DOM conversion. Genuinely
242
+ // checked-dynamic slot takes the dyn conversion. Genuinely
243
243
  // island slots (npm .d.ts provenance, plain `any`) keep the
244
244
  // native build.
245
245
  if (ctxTs !== undefined && (ctxTs.flags & ts.TypeFlags.Any) === 0) {
@@ -274,13 +274,22 @@ function lowerExprInner(L, expr) {
274
274
  const argsWith = [];
275
275
  const getters = [];
276
276
  let spread = null;
277
- // A MEMBER a JS file cannot lower or marshal (a generic function
278
- // as a value, a signature with checked-dynamic parameters — the
279
- // doc-builder public aggregate's degraded pieces): defer like a
280
- // statement fence — the slot holds a host closure that THROWS the
281
- // captured diagnostic when invoked, so building the aggregate
282
- // compiles and only a CALL through the island stops the run.
283
- const islandMemberFence = (diagsBefore, err, valueNode) => {
277
+ // A MEMBER a JS file cannot lower or marshal: defer like a
278
+ // statement fence, shaped by what the member IS. A FUNCTION-shaped
279
+ // member (a generic function as a value, a signature with
280
+ // checked-dynamic parameters — the doc-builder public aggregate's
281
+ // degraded pieces) becomes a host closure that THROWS the captured
282
+ // diagnostic when invoked — building the aggregate compiles and
283
+ // only a CALL through the island stops the run. A DATA-shaped
284
+ // member must NOT become a callable (the retired fence box's
285
+ // silent wrong answers: typeof said "function", downstream errors
286
+ // blamed the wrong thing — the withPlugins `plugins:` slot), so it
287
+ // defines through the engine's getter machinery instead: READING
288
+ // the member throws the diagnostic — the honest granularity, since
289
+ // using the value is exactly what cannot be answered. `getterName`
290
+ // null keeps the closure shape (function-shaped members, and the
291
+ // conditional-spread arms where getters cannot combine).
292
+ const islandMemberFence = (diagsBefore, err, valueNode, getterName = null) => {
284
293
  if (!(err instanceof PoisonError) ||
285
294
  !isJsSourceFile(expr.getSourceFile()) ||
286
295
  L.diagSink !== null ||
@@ -310,8 +319,33 @@ function lowerExprInner(L, expr) {
310
319
  loc: locOf(valueNode),
311
320
  });
312
321
  const fence = { kind: "closure", fnName, captures: [], type: funcOf([], VOID), loc: locOf(valueNode) };
322
+ if (getterName !== null) {
323
+ getters.push({ name: getterName, fn: L.jsvalIn(fence, valueNode), loc: locOf(valueNode) });
324
+ return null;
325
+ }
313
326
  return L.jsvalIn(fence, valueNode);
314
327
  };
328
+ // The member's SHAPE decides the fence's granularity: syntactic
329
+ // functions and checker-callable values keep the call-time
330
+ // closure; everything else (call results, awaits, data reads —
331
+ // the withPlugins `plugins:` shape) fences at the READ.
332
+ const funcShapedMember = (p) => {
333
+ if (ts.isMethodDeclaration(p))
334
+ return true;
335
+ const src = ts.isPropertyAssignment(p)
336
+ ? p.initializer
337
+ : ts.isShorthandPropertyAssignment(p)
338
+ ? p.name
339
+ : null;
340
+ if (!src || !ts.isExpression(src))
341
+ return true; // unknown form: keep the closure shape
342
+ let inner = src;
343
+ while (ts.isParenthesizedExpression(inner))
344
+ inner = inner.expression;
345
+ if (ts.isArrowFunction(inner) || ts.isFunctionExpression(inner))
346
+ return true;
347
+ return L.checker.getCallSignatures(L.typeOf(src)).length > 0;
348
+ };
315
349
  const pushProp = (name, value, valueNode, into) => {
316
350
  const diagsBefore = L.diags.length;
317
351
  let marshaled;
@@ -319,7 +353,15 @@ function lowerExprInner(L, expr) {
319
353
  marshaled = L.jsvalIn(value, valueNode);
320
354
  }
321
355
  catch (err) {
322
- marshaled = islandMemberFence(diagsBefore, err, valueNode);
356
+ // A value that LOWERED but cannot cross (a promise, a class
357
+ // instance): func-typed values keep the call-time closure;
358
+ // data-shaped values fence at the read (the getter), unless a
359
+ // conditional spread owns the literal (getters cannot combine).
360
+ const asGetter = value.type.kind !== "func" && spread === null;
361
+ const fence = islandMemberFence(diagsBefore, err, valueNode, asGetter ? name.text : null);
362
+ if (fence === null)
363
+ return; // registered as a fence getter — no data property
364
+ marshaled = fence;
323
365
  }
324
366
  for (const args of into) {
325
367
  args.push({
@@ -403,7 +445,11 @@ function lowerExprInner(L, expr) {
403
445
  : null;
404
446
  }
405
447
  catch (err) {
406
- value = islandMemberFence(valueDiagsBefore, err, prop);
448
+ const nameText = name && (ts.isIdentifier(name) || ts.isStringLiteral(name)) ? name.text : null;
449
+ const asGetter = nameText !== null && spread === null && !funcShapedMember(prop);
450
+ value = islandMemberFence(valueDiagsBefore, err, prop, asGetter ? nameText : null);
451
+ if (value === null)
452
+ continue; // registered as a fence getter — no data property
407
453
  }
408
454
  if (value && name && (ts.isIdentifier(name) || ts.isStringLiteral(name))) {
409
455
  pushProp(name, value, prop, [argsWithout, argsWith]);
@@ -494,7 +540,7 @@ function lowerExprInner(L, expr) {
494
540
  }
495
541
  // A checker-narrowed dyn read arrives as a VALIDATED extraction
496
542
  // (maybeNarrow's dynCheck bridge). typeof needs no extraction — the
497
- // DOM kind table answers the question directly, and answers it even
543
+ // dyn kind table answers the question directly, and answers it even
498
544
  // where the flow type lied (the extraction would throw instead) —
499
545
  // so unwrap back to the dyn value and take the dyn.typeof path.
500
546
  if (operand.kind === "dynCheck" && operand.value.type.kind === "dyn") {
@@ -539,7 +585,7 @@ function lowerExprInner(L, expr) {
539
585
  if (operand.type.kind === "dyn") {
540
586
  // Bare typeof on a dyn value: the runtime's kind→string table
541
587
  // (null answers "object", boxed closures "function" — JS-exact
542
- // for every DOM kind; "bigint"/"symbol" have no producers).
588
+ // for every dyn kind; "bigint"/"symbol" have no producers).
543
589
  return { kind: "libCall", fn: "dyn.typeof", args: [operand], type: STRING, loc };
544
590
  }
545
591
  L.unsupported("SC1090", expr, "typeof expressions on statically-typed values");
@@ -549,7 +595,7 @@ function lowerExprInner(L, expr) {
549
595
  return { kind: "selfRef", type: L.ctx.selfType, loc };
550
596
  }
551
597
  // `arguments` in a variadic JS function (the rest-marked form): the
552
- // synthetic trailing DOM-array param — lambdaSignature marked the
598
+ // synthetic trailing dyn-array param — lambdaSignature marked the
553
599
  // type and lowerLambda declared the local.
554
600
  if (expr.text === "arguments" && L.ctx.argumentsLocal) {
555
601
  return { kind: "varRef", localId: L.ctx.argumentsLocal.id, type: DYN, loc };
@@ -618,7 +664,7 @@ function lowerExprInner(L, expr) {
618
664
  // optional/default/rest declarations pass the value fence first.
619
665
  L.noteEdge(sig.name);
620
666
  // dynRest slots stay out of the VALUE type's param list (fn.length
621
- // semantics); the rest marker carries the trailing DOM-array ABI.
667
+ // semantics); the rest marker carries the trailing dyn-array ABI.
622
668
  const funcType = {
623
669
  kind: "func",
624
670
  params: sig.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
@@ -647,10 +693,11 @@ function lowerExprInner(L, expr) {
647
693
  if (acc)
648
694
  return acc;
649
695
  }
650
- // A binding destructured from http2.constants: the baked literal
651
- // (the declaration emitted nothing — http2ConstantsDestructureDecl).
696
+ // A binding destructured from a baked constants object
697
+ // (http2.constants / crypto.constants): the literal — the
698
+ // declaration emitted nothing (builtinConstantsDestructureDecl).
652
699
  {
653
- const h2c = L.http2ConstantBindingOf(expr);
700
+ const h2c = L.builtinConstantBindingOf(expr);
654
701
  if (h2c)
655
702
  return h2c;
656
703
  }
@@ -669,6 +716,14 @@ function lowerExprInner(L, expr) {
669
716
  if (bi.module === "module" && bi.member === "builtinModules") {
670
717
  return builtinModulesArrayLit(loc);
671
718
  }
719
+ // tls.rootCertificates: a runtime-valued module constant (the
720
+ // cached bundled-CA array) — the one member read that lowers
721
+ // to a libCall instead of a baked literal.
722
+ {
723
+ const roots = lowerTlsRootCertificates(L, bi, loc);
724
+ if (roots)
725
+ return roots;
726
+ }
672
727
  // JavaScript sources: a builtin member taken as a bare VALUE is
673
728
  // the same identity-token story as stdlib globals above (the
674
729
  // harness adds worker_threads.Worker to its identity Set).
@@ -999,7 +1054,7 @@ function lowerExprInner(L, expr) {
999
1054
  if (value.type.kind !== "promise") {
1000
1055
  // A CHECKED-DYNAMIC operand (`await v` where v rode an untyped
1001
1056
  // binding — a destructured helper's return, a dyn call result):
1002
- // the runtime decides — a DOM promise adopts (rejections
1057
+ // the runtime decides — a dyn promise adopts (rejections
1003
1058
  // re-throw), anything else takes JS's one-hop non-thenable await
1004
1059
  // and answers itself. Thenable adoption stays unmodeled
1005
1060
  // (SEMANTICS.md).
@@ -1157,9 +1212,9 @@ function lowerExprInner(L, expr) {
1157
1212
  // bound handle).
1158
1213
  if (L.isIslandExpr(expr.expression)) {
1159
1214
  const receiver = L.lowerExpr(expr.expression);
1160
- // The checker said 'any' but the VALUE lives in the DOM (`this`
1215
+ // The checker said 'any' but the VALUE lives in the checked-dynamic tree (`this`
1161
1216
  // in a plain JS function — dyn.this — or a checked-dynamic local
1162
- // behind an any-typed spelling): the property read is the DOM's
1217
+ // behind an any-typed spelling): the property read is the checked-dynamic tree's
1163
1218
  // own keyed read, dyn results and dyn chains exactly like every
1164
1219
  // checked-dynamic member access (a nullish receiver throws V8's
1165
1220
  // catchable TypeError, exactly Node). Never a jsOp over a dyn —
@@ -1401,7 +1456,7 @@ function lowerExprInner(L, expr) {
1401
1456
  L.lowerFsConstantsProperty(expr) ??
1402
1457
  // http2.constants.NGHTTP2_CANCEL (any constants-object spelling):
1403
1458
  // the baked-literal table.
1404
- L.lowerHttp2ConstantsProperty(expr) ??
1459
+ L.lowerBuiltinConstantsProperty(expr) ??
1405
1460
  // Builtin namespace imports (`path.sep`, `os.EOL`,
1406
1461
  // `fs.constants.R_OK` where the root is `import * as ...`): the
1407
1462
  // same constants and per-member fences as named builtin imports.
@@ -1443,14 +1498,14 @@ function lowerExprInner(L, expr) {
1443
1498
  // .length` where the binding is an evolving any[] living as a
1444
1499
  // checked-dynamic global): the stdlib member fence below would blame
1445
1500
  // the unmappable checker type (`any[].length`), but the VALUE is a
1446
- // DOM node — lower the receiver first and read through the DOM keyed
1501
+ // dyn node — lower the receiver first and read through the dyn keyed
1447
1502
  // read (ARR answers length; everything else JS's own-property
1448
1503
  // answer). Mapped receivers keep the fence-first order: their
1449
1504
  // members' gaps are real surface gaps ([1,2].entries), not
1450
1505
  // representation artifacts. `.length` on a receiver whose checker
1451
1506
  // ARRAY type lowers to the checked-dynamic representation —
1452
1507
  // `unknown[]`, the collapsed `(string | object)[]`, and the `any[]`
1453
- // an Array.isArray guard narrows a collapsed union to — is the DOM
1508
+ // an Array.isArray guard narrows a collapsed union to — is the checked-dynamic tree
1454
1509
  // array's OWN length (a keyed read the ARR kind answers exactly),
1455
1510
  // never an `Array.prototype` surface gap; both source languages.
1456
1511
  // Prototype-method VALUE reads (`ps.map` unparenthesized) keep the
@@ -1460,7 +1515,7 @@ function lowerExprInner(L, expr) {
1460
1515
  if ((isJsSourceFile(expr.getSourceFile()) &&
1461
1516
  (L.mapTypeOf(L.typeOf(expr.expression)) === null ||
1462
1517
  // A never-tainted receiver type maps (never rides as f64) but
1463
- // its VALUE lowered checked-dynamic — same DOM read.
1518
+ // its VALUE lowered checked-dynamic — same dyn read.
1464
1519
  neverTaintedJsType(L, expr.expression, L.typeOf(expr.expression)))) ||
1465
1520
  (expr.name.text === "length" &&
1466
1521
  (L.checkerAnyArray(expr.expression) ||
@@ -1571,7 +1626,7 @@ function lowerExprInner(L, expr) {
1571
1626
  // the property and the receiver's type instead of "property access".
1572
1627
  const recvLowered = L.lowerExpr(expr.expression);
1573
1628
  // A dyn receiver — JSON.parse's `any`, or `unknown` the checker
1574
- // narrowed to `object` — reads through the DOM keyed read: member
1629
+ // narrowed to `object` — reads through the dyn keyed read: member
1575
1630
  // or undefined (JS's own-property answer), throwing JS's TypeError
1576
1631
  // on undefined/null receivers unless an earlier `?.` guards the
1577
1632
  // chain. Scalar-narrowed occurrences bridge via maybeNarrow's
@@ -1812,16 +1867,17 @@ export function lowerTernary(L, expr, expected) {
1812
1867
  // tagged element type the checker's own type doesn't spell).
1813
1868
  const own = L.mapTypeOf(L.typeOf(expr));
1814
1869
  const useCtx = (ctxMapped?.kind === "record" || ctxMapped?.kind === "union" || ctxMapped?.kind === "object") &&
1815
- (own === null || (own.kind === "union" && !typeEquals(own, ctxMapped)));
1870
+ (own === null ||
1871
+ (own.kind === "union" && !typeEquals(own, ctxMapped) && !L.inLogicalLeftPosition(expr)));
1816
1872
  // Mixed dyn/unit arms under an unmappable own type (`typeof pkg.name
1817
1873
  // === "string" ? pkg.name : null` — the lowering world types the
1818
1874
  // unknown-receiver read `any`, which a static build cannot hold):
1819
1875
  // dyn represents null and undefined directly, so the ternary stays
1820
- // dyn — a unit arm converts to the DOM unit value (the dynFrom form
1876
+ // dyn — a unit arm converts to the dyn unit value (the dynFrom form
1821
1877
  // the index-signature lowerings already use). A FRESH literal arm
1822
1878
  // (`... ? pkg.scripts : {}` — the default-object idiom) converts the
1823
1879
  // same way when it is JSON-safe: nothing else aliases a literal, so
1824
- // the DOM copy is unobservable.
1880
+ // the dyn copy is unobservable.
1825
1881
  const dynish = (e) => e.type.kind === "dyn" ||
1826
1882
  e.kind === "unitLit" ||
1827
1883
  ((e.kind === "recordLit" || e.kind === "arrayLit") && L.dynConvertible(e.type));
@@ -1907,13 +1963,13 @@ export function maybeNarrow(L, expr, node) {
1907
1963
  (narrowed.kind === "f64" || narrowed.kind === "bool" || narrowed.kind === "string")) {
1908
1964
  return { kind: "dynCheck", value: expr, type: narrowed, loc: expr.loc };
1909
1965
  }
1910
- // An `instanceof Uint8Array` narrow: the DOM's bytes kind, extracted
1966
+ // An `instanceof Uint8Array` narrow: the checked-dynamic tree's bytes kind, extracted
1911
1967
  // with the same validated copy the checked cast uses (a Buffer that
1912
1968
  // crossed in rides the kind too — it IS a Uint8Array in Node).
1913
1969
  if (narrowed?.kind === "bytes" && narrowed.elem === "u8") {
1914
1970
  return { kind: "dynCheck", value: expr, type: narrowed, loc: expr.loc };
1915
1971
  }
1916
- // An `instanceof Error` narrow: the DOM's error encoding rebuilds a
1972
+ // An `instanceof Error` narrow: the checked-dynamic tree's error encoding rebuilds a
1917
1973
  // fresh %Error (name/message/code from the marker object — a COPY,
1918
1974
  // the unknown boundary's stance; SEMANTICS.md 67), validated like
1919
1975
  // every dyn extraction.
@@ -2089,7 +2145,7 @@ export function lowerLooseNullCompare(L, expr, loc) {
2089
2145
  return { kind: "boolLit", value: !negated, type: BOOL, loc };
2090
2146
  }
2091
2147
  if (other.type.kind === "dyn") {
2092
- // `v != null` on unknown: one DOM kind test covers both units.
2148
+ // `v != null` on unknown: one dyn kind test covers both units.
2093
2149
  return {
2094
2150
  kind: "dynTest",
2095
2151
  test: "nullish",
@@ -2248,7 +2304,7 @@ export function lowerNullishCoalesce(L, expr, loc) {
2248
2304
  // runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default;
2249
2305
  // a wrapped island value routes to the engine's test, defensively:
2250
2306
  // the wrap constructor scalar-normalizes engine null/undefined
2251
- // away). Both sides live in the DOM — the right converts through
2307
+ // away). Both sides live in the checked-dynamic tree — the right converts through
2252
2308
  // the usual boundary and evaluates lazily in its branch; a default
2253
2309
  // with no dyn representation keeps the fence.
2254
2310
  const right = L.coerceToExpected(L.lowerExpr(expr.right), DYN);
@@ -2530,7 +2586,7 @@ export function lowerOptionalChain(L, expr) {
2530
2586
  }
2531
2587
  // NUMBER-typed indices (`entries?.[0]`): the property key is
2532
2588
  // ToString(i), exactly JS — the canonical number text answers
2533
- // array indices in the DOM helper, anything else (fractions,
2589
+ // array indices in the dyn helper, anything else (fractions,
2534
2590
  // negatives, NaN) reads as an absent key.
2535
2591
  if (key.type.kind === "f64") {
2536
2592
  const skey = { kind: "toString", operand: key, type: STRING, loc: key.loc };
@@ -2538,12 +2594,12 @@ export function lowerOptionalChain(L, expr) {
2538
2594
  }
2539
2595
  }
2540
2596
  // The METHOD-call step (`rawName?.match(re)` on a dyn value): a
2541
- // nullish receiver short-circuits to the undefined DOM singleton
2597
+ // nullish receiver short-circuits to the undefined dyn singleton
2542
2598
  // (dyn represents undefined directly); anything else runs the
2543
2599
  // VALIDATED dynamic dispatch — the same one the truthy-guarded
2544
2600
  // spelling (`v ? v.match(...) : null`) compiles to, Node-shaped
2545
2601
  // TypeError on a kind mismatch included. The dispatch's static
2546
- // result converts back into the DOM (the chain's checker type is
2602
+ // result converts back into the checked-dynamic tree (the chain's checker type is
2547
2603
  // the error-any world's `any`, so dyn IS its representation).
2548
2604
  if (ts.isCallExpression(expr) &&
2549
2605
  ts.isPropertyAccessExpression(dotNode) &&
@@ -2714,7 +2770,7 @@ export function finishOptionalChain(L, expr, id, receiver, body, loc) {
2714
2770
  }
2715
2771
  // A dyn body (`pricing?.[key]` — an unknown-valued index-signature
2716
2772
  // read) stays dyn: `unknown | undefined` IS unknown, and dyn represents
2717
- // undefined directly (the unit path yields the undefined DOM value).
2773
+ // undefined directly (the unit path yields the undefined dyn value).
2718
2774
  if (body.type.kind === "dyn") {
2719
2775
  return { kind: "optChain", id, receiver, body, type: DYN, loc };
2720
2776
  }
@@ -2770,8 +2826,8 @@ export function ensureBool(L, e, node) {
2770
2826
  return { kind: "toBool", operand: e, type: BOOL, loc: e.loc };
2771
2827
  }
2772
2828
  if (e.type.kind === "dyn") {
2773
- // ToBoolean over the DOM (`if (pkg)` on a JSON.parse result): every
2774
- // DOM kind has a JS-exact answer — the truthy dynTest reads the kind
2829
+ // ToBoolean over the checked-dynamic tree (`if (pkg)` on a JSON.parse result): every
2830
+ // dyn kind has a JS-exact answer — the truthy dynTest reads the kind
2775
2831
  // tag (plus the scalar payload for number/string).
2776
2832
  return { kind: "dynTest", test: "truthy", value: e, type: BOOL, loc: e.loc };
2777
2833
  }
@@ -2797,7 +2853,7 @@ export function ensureBool(L, e, node) {
2797
2853
  L.badType(node, L.typeOf(node));
2798
2854
  }
2799
2855
  /** Truthiness needs a ToBoolean per arm: dyn/caught arms have none (a
2800
- * dynamic ToBoolean over the DOM / the snapshot box) — fence those
2856
+ * dynamic ToBoolean over the checked-dynamic tree / the snapshot box) — fence those
2801
2857
  * unions; every other arm kind is answerable (units false, scalars and
2802
2858
  * strings by value, refs true, jsval by the engine). */
2803
2859
  export function requireTruthyUnion(L, unionId, node) {
@@ -2826,7 +2882,7 @@ export function lowerIntrinsicProperty(L, expr) {
2826
2882
  return null;
2827
2883
  // A never-tainted JS receiver type lowered checked-dynamic
2828
2884
  // (neverTaintedJsType — `cmd.length` on `const cmd = ['pwd', []]`):
2829
- // stand down so the DOM keyed read below the chain answers, instead
2885
+ // stand down so the dyn keyed read below the chain answers, instead
2830
2886
  // of an array libCall over a dyn receiver hitting the boundary fence.
2831
2887
  let kind = neverTaintedJsType(L, expr.expression, L.typeOf(expr.expression))
2832
2888
  ? undefined
@@ -3090,8 +3146,8 @@ export function lowerIntrinsicProperty(L, expr) {
3090
3146
  return { kind: "jsExit", value: read, type: F64, loc: locOf(expr) };
3091
3147
  }
3092
3148
  // A CHECKED-DYNAMIC value behind an array-typed checker spelling
3093
- // (`Object.keys(u).length` — the dyn walk answers a DOM array while
3094
- // tsc spells string[]): the runtime-world dispatch — a DOM keyed
3149
+ // (`Object.keys(u).length` — the dyn walk answers a dyn array while
3150
+ // tsc spells string[]): the runtime-world dispatch — a dyn keyed
3095
3151
  // read validated into the declared number (a lying length throws
3096
3152
  // the catchable TypeError, the dynCheck stance).
3097
3153
  if (receiver.type.kind === "dyn") {
@@ -3134,7 +3190,7 @@ export function lowerArrayLiteral(L, expr, expected) {
3134
3190
  // A JS literal whose OWN inferred type is never-tainted
3135
3191
  // (neverTaintedJsType — the evolving `const gb = []`, the mixed
3136
3192
  // command tuple `['pwd', []]`) carries no element information: route
3137
- // it to the DOM fallback below rather than letting never's f64
3193
+ // it to the checked-dynamic tree fallback below rather than letting never's f64
3138
3194
  // representation build a static number array (a later dyn push would
3139
3195
  // throw "expected number at $, got string"; the tuple's union arm
3140
3196
  // would re-tag as number[] and fence). A REAL slot still wins:
@@ -3264,14 +3320,14 @@ export function lowerArrayLiteral(L, expr, expected) {
3264
3320
  if (!mapped || mapped.kind !== "array") {
3265
3321
  // The JS declaration fallback, literal-side: an element type with no
3266
3322
  // static home (a string | string[] mixed command tuple, an evolving
3267
- // []) builds as a DOM ARRAY — one dyn value whose elements each
3323
+ // []) builds as a dyn ARRAY — one dyn value whose elements each
3268
3324
  // convert through the usual boundary (dynFrom's JSON-safe domain);
3269
3325
  // an element that cannot convert fences per element. length/index
3270
- // reads and dynamic consumers ride the keyed-DOM paths. TS literals
3326
+ // reads and dynamic consumers ride the keyed-dyn paths. TS literals
3271
3327
  // take the same build when the slot ITSELF is checked-dynamic — an
3272
3328
  // `unknown[]` annotation or a collapsed `(string | object)[]` maps
3273
3329
  // to DYN wholesale now (mapType's dyn-element array rule), so the
3274
- // literal IS the DOM array.
3330
+ // literal IS the dyn array.
3275
3331
  if (isJsSourceFile(expr.getSourceFile()) || mapped?.kind === "dyn") {
3276
3332
  const elems = expr.elements.map((el) => {
3277
3333
  if (ts.isSpreadElement(el)) {
@@ -3557,12 +3613,12 @@ function propNameText(L, name) {
3557
3613
  return name.text;
3558
3614
  }
3559
3615
  /** The runtime-keyed JS object literal (a computed key that doesn't fold):
3560
- * builds a DOM object member-by-member. Keys evaluate before their values,
3616
+ * builds a dyn object member-by-member. Keys evaluate before their values,
3561
3617
  * properties in source order — JS's object-literal evaluation exactly.
3562
3618
  * Identifier/string keys are compile-time strings; numeric keys take
3563
3619
  * their canonical number string (`{ 0x10: v }` stores "16" — JS's
3564
3620
  * ToPropertyKey); computed keys evaluate and pass through ToString (the
3565
- * DOM's String() for dyn operands — `{ [field]: v }` where field is a
3621
+ * dyn's String() for dyn operands — `{ [field]: v }` where field is a
3566
3622
  * checked-dynamic param). Values convert through the usual dyn boundary
3567
3623
  * (dynFrom's domain, functions box); a value with no dyn representation
3568
3624
  * fences per property. Spreads, accessors, and methods stay fenced —
@@ -3655,7 +3711,7 @@ export function lowerDynObjectLiteral(L, expr) {
3655
3711
  L.unsupported("SC1101", valueExpr, `holding '${L.fmt(v.type)}' values in a runtime-keyed (computed-key) object literal`);
3656
3712
  }
3657
3713
  catch (err) {
3658
- // A member value the DOM cannot hold — a func whose signature
3714
+ // A member value the checked-dynamic tree cannot hold — a func whose signature
3659
3715
  // cannot box, an island ('any') handle, a record carrying func
3660
3716
  // fields (the export aggregate's typed utilities and npm-handle
3661
3717
  // members): the same call-time fence deferral as an unlowerable
@@ -3725,7 +3781,7 @@ function fenceClosureProbe(L, node, slotType, attempt) {
3725
3781
  return null;
3726
3782
  }
3727
3783
  // The trap's ABI: the field's func slot when one exists; otherwise (the
3728
- // DOM-object literal path — the value boxes into dyn) the all-dyn
3784
+ // dyn-object literal path — the value boxes into dyn) the all-dyn
3729
3785
  // signature of the lambda's own arity, which canBoxFuncIntoDyn always
3730
3786
  // admits.
3731
3787
  const fieldType = slotType !== undefined && slotType.kind === "func"
@@ -3868,7 +3924,7 @@ export function lowerObjectLiteral(L, expr) {
3868
3924
  const loc = locOf(expr);
3869
3925
  // The RUNTIME-KEYED literal (JS): a computed key that doesn't fold to a
3870
3926
  // compile-time string means the literal's shape is not a compile-time
3871
- // fact — no record shape can hold it. The whole literal builds as a DOM
3927
+ // fact — no record shape can hold it. The whole literal builds as a dyn
3872
3928
  // object instead (`{ [field]: criteria, actual: 0, ... }` —
3873
3929
  // test/common's _mustCallInner context), where keys are runtime string
3874
3930
  // values. TypeScript keeps the record world and its fence: this shape
@@ -4117,13 +4173,13 @@ export function lowerObjectLiteral(L, expr) {
4117
4173
  const shapeId = L.shapes.intern(fields.map((f) => ({ name: f.name, type: f.value.type })));
4118
4174
  return { kind: "recordLit", fields, type: { kind: "record", shapeId }, loc };
4119
4175
  }
4120
- // The JS declaration fallback, literal-side (the DOM-array rule's
4176
+ // The JS declaration fallback, literal-side (the checked-dynamic tree-array rule's
4121
4177
  // object form): a literal whose shape has no static home — an
4122
4178
  // unmappable contextual type over unmappable own fields (the
4123
4179
  // PropertyDescriptorMap argument of Object.defineProperties, nested
4124
- // descriptor records with `any` values) — builds as a DOM OBJECT:
4180
+ // descriptor records with `any` values) — builds as a dyn OBJECT:
4125
4181
  // each field converts through the usual dyn boundary, and dynamic
4126
- // consumers ride the keyed-DOM paths. TypeScript keeps the fence.
4182
+ // consumers ride the keyed-dyn paths. TypeScript keeps the fence.
4127
4183
  if ((!mapped || mapped.kind === "dyn") && isJsSourceFile(expr.getSourceFile())) {
4128
4184
  return lowerDynObjectLiteral(L, expr);
4129
4185
  }
@@ -4389,8 +4445,8 @@ export function lowerObjectLiteral(L, expr) {
4389
4445
  const recArm = recArms[0];
4390
4446
  const recTag = def.arms.indexOf(recArm);
4391
4447
  // A checked-dynamic VALUE under the union-mapped checker type
4392
- // (a JS DOM-holding binding): the present/absent desugar tests
4393
- // union tags a DOM box does not carry — fence honestly instead
4448
+ // (a JS dyn-holding binding): the present/absent desugar tests
4449
+ // union tags a dyn box does not carry — fence honestly instead
4394
4450
  // of the validator's ICE.
4395
4451
  const probedSrc = srcLowered ?? probeLower(L, srcNode);
4396
4452
  if (probedSrc?.type.kind === "dyn") {
@@ -4572,11 +4628,11 @@ export function lowerObjectLiteral(L, expr) {
4572
4628
  throw new PoisonError();
4573
4629
  }
4574
4630
  const obj = srcLowered ?? L.lowerExpr(srcNode);
4575
- // A record-mapped CHECKER type whose VALUE lives in the DOM (a
4631
+ // A record-mapped CHECKER type whose VALUE lives in the checked-dynamic tree (a
4576
4632
  // JS file-scope object-literal global): read each field from
4577
- // the DOM (dynKeyGet) and VALIDATE it into the source shape's
4633
+ // the checked-dynamic tree (dynKeyGet) and VALIDATE it into the source shape's
4578
4634
  // field type (dynCheck) — the checked-dynamic member-read
4579
- // discipline. A missing key answers the DOM undefined, exactly
4635
+ // discipline. A missing key answers the dyn undefined, exactly
4580
4636
  // the undefined-armed optional's absent case; a mismatched
4581
4637
  // runtime value throws the catchable TypeError, never a silent
4582
4638
  // wrong copy. Runtime-ADDED keys drop — width subtyping in
@@ -4584,7 +4640,7 @@ export function lowerObjectLiteral(L, expr) {
4584
4640
  let value;
4585
4641
  if (obj.type.kind === "dyn") {
4586
4642
  if (!canDynCheckTo(f.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
4587
- L.unsupported("SC1100", prop, `object spread of a checked-dynamic source whose field '${f.name}' ('${L.fmt(f.type)}') cannot validate out of the DOM (copy the fields explicitly)`);
4643
+ L.unsupported("SC1100", prop, `object spread of a checked-dynamic source whose field '${f.name}' ('${L.fmt(f.type)}') cannot validate out of the checked-dynamic tree (copy the fields explicitly)`);
4588
4644
  }
4589
4645
  value = {
4590
4646
  kind: "dynCheck",
@@ -4723,7 +4779,7 @@ export function lowerObjectLiteral(L, expr) {
4723
4779
  // lowering: a union field with one array-family arm builds the
4724
4780
  // literal AS that arm (lowerExprExpecting's IR-directed rule —
4725
4781
  // the option-table `default: [{ value: [] }]` shape), where the
4726
- // bare lowering would take the JS DOM fallback and fence.
4782
+ // bare lowering would take the JS dyn fallback and fence.
4727
4783
  let init = prop.initializer;
4728
4784
  while (ts.isParenthesizedExpression(init))
4729
4785
  init = init.expression;
@@ -4768,7 +4824,7 @@ export function lowerObjectLiteral(L, expr) {
4768
4824
  }
4769
4825
  if (!fieldType) {
4770
4826
  // Overflow entry: the value flows into the index signature's value
4771
- // slot — dyn slots take a DOM conversion (dynFrom), typed slots the
4827
+ // slot — dyn slots take a dyn conversion (dynFrom), typed slots the
4772
4828
  // ordinary coercion path. Later duplicates override (map semantics
4773
4829
  // are last-write-wins already; a duplicate literal key is a tsc
4774
4830
  // error anyway).
@@ -4810,7 +4866,7 @@ export function lowerObjectLiteral(L, expr) {
4810
4866
  for (const f of shape.fields) {
4811
4867
  if (provided.has(f.name))
4812
4868
  continue;
4813
- // 'unknown' fields complete with the DOM undefined — the absent
4869
+ // 'unknown' fields complete with the dyn undefined — the absent
4814
4870
  // property reads as undefined in Node, and a dyn slot holds
4815
4871
  // exactly that (the options-record call shape against
4816
4872
  // `{ plugins: unknown, ... }` — a JS caller the checker admits).
@@ -5171,7 +5227,7 @@ export function lowerElementAccess(L, expr) {
5171
5227
  // A never-tainted JS receiver type (neverTaintedJsType — `cmd[1]` on
5172
5228
  // `const cmd = ['pwd', []]`, whose binding lowered checked-dynamic)
5173
5229
  // dispatches as unmapped so the dyn-receiver branch below reads
5174
- // through the DOM instead of dynChecking into never's f64 residue.
5230
+ // through the checked-dynamic tree instead of dynChecking into never's f64 residue.
5175
5231
  const receiverIr = neverTaintedJsType(L, expr.expression, L.typeOf(expr.expression))
5176
5232
  ? null
5177
5233
  : L.mapTypeOf(L.typeOf(expr.expression));
@@ -5179,7 +5235,7 @@ export function lowerElementAccess(L, expr) {
5179
5235
  // Dispatch follows the RUNTIME world (383(d)): a checker-'any'
5180
5236
  // receiver whose value LOWERED checked-dynamic (`bag.list[0]` where
5181
5237
  // bag.list is a routed keyed read off a wrapped island value) takes
5182
- // the DOM keyed read below — the routed JSVAL arm reads the real
5238
+ // the dyn keyed read below — the routed JSVAL arm reads the real
5183
5239
  // engine element; a jsval-lowered receiver keeps the island read.
5184
5240
  const recv = L.lowerExpr(expr.expression);
5185
5241
  if (recv.type.kind !== "dyn")
@@ -5258,7 +5314,7 @@ export function lowerElementAccess(L, expr) {
5258
5314
  }
5259
5315
  }
5260
5316
  // `pkg["k"]` / `scripts[name]` / `scopeMatch[1]` on a dyn receiver (a
5261
- // JSON.parse result): the DOM keyed read, exactly the dot form.
5317
+ // JSON.parse result): the dyn keyed read, exactly the dot form.
5262
5318
  // NUMBER-typed indices convert through ToString first — JS property
5263
5319
  // keys are strings, and the canonical number text answers array
5264
5320
  // indices in the helper (fractions, negatives, and NaN read as
@@ -5368,7 +5424,7 @@ export function lowerElementAccess(L, expr) {
5368
5424
  return islandElementRead(L, expr, arr);
5369
5425
  // The checker sees an array but the VALUE lowered checked-dynamic (a
5370
5426
  // jsdoc-typed default export from a .js module — signature 14): the
5371
- // read rides the dynCheck boundary when the array shape is one the DOM
5427
+ // read rides the dynCheck boundary when the array shape is one the checked-dynamic tree
5372
5428
  // can validate, and fences by name when it is not — an arrayGet over a
5373
5429
  // dyn receiver is never emitted (the validator ICE).
5374
5430
  if (arr.type.kind === "dyn") {
@@ -5444,7 +5500,7 @@ function islandElementRead(L, expr, obj) {
5444
5500
  * the index signature's value type (dyn for `unknown`), or its
5445
5501
  * undefined-armed union under noUncheckedIndexedAccess. Every declared
5446
5502
  * field must be able to SURFACE as that type (equal, an arm of it, or —
5447
- * for dyn results — JSON-safe for the DOM conversion); shapes mixing in
5503
+ * for dyn results — JSON-safe for the dyn conversion); shapes mixing in
5448
5504
  * fields outside that stay fenced. Declared-only shapes support reads
5449
5505
  * whose key type proves membership (tsc's keyof check): all fields must
5450
5506
  * share the result type, and a smuggled miss traps. */
@@ -5463,16 +5519,19 @@ export function lowerRecordKeyRead(L, expr, shapeId, shape) {
5463
5519
  // The receiver lowers FIRST (both branches below read it, and JS
5464
5520
  // evaluates the receiver before the key).
5465
5521
  const obj = L.lowerExpr(expr.expression);
5466
- // A record-mapped CHECKER type over a VALUE living in the DOM (a JS
5522
+ // A record-mapped CHECKER type over a VALUE living in the checked-dynamic tree (a JS
5467
5523
  // file-scope object-literal global): the checked-dynamic keyed read —
5468
- // dynKeyGet against the runtime keys (a missing key answers the DOM
5524
+ // dynKeyGet against the runtime keys (a missing key answers the checked-dynamic tree
5469
5525
  // undefined, exactly JS); consumers validate (dynCheck) where a
5470
5526
  // static type is required, the member-read discipline.
5471
5527
  if (obj.type.kind === "dyn") {
5472
5528
  let dk = litKey !== null
5473
5529
  ? { kind: "strLit", value: litKey, type: STRING, loc: locOf(keyNode) }
5474
5530
  : L.lowerExpr(keyNode);
5475
- if (dk.type.kind === "f64")
5531
+ // Number AND checked-dynamic keys ride the JS-exact formatter —
5532
+ // property keys ARE strings (o[k] is o[String(k)] in JS), and a dyn
5533
+ // key (agent.sockets[agent.getName(...)]) stringifies the same way.
5534
+ if (dk.type.kind === "f64" || dk.type.kind === "dyn")
5476
5535
  dk = L.ensureString(dk, keyNode);
5477
5536
  if (dk.type.kind !== "string") {
5478
5537
  L.unsupported("SC1090", keyNode, "indexing records with non-string or non-number keys");
@@ -5574,8 +5633,8 @@ export function recordKeyTypeLiteralText(L, node) {
5574
5633
  }
5575
5634
  /** Can every value a dynamic key can reach (declared fields + the
5576
5635
  * overflow) surface as the read's result type? dyn results need
5577
- * DOM-convertible fields (JSON-safe, with the undefined arm allowed at
5578
- * the top — an optional field's undefined becomes the undefined DOM
5636
+ * dyn-convertible fields (JSON-safe, with the undefined arm allowed at
5637
+ * the top — an optional field's undefined becomes the undefined dyn
5579
5638
  * value, exactly what the missing-key path produces); typed results need
5580
5639
  * each field to be the type itself or one of its arms, and the overflow
5581
5640
  * value to be the type or wrappable into it. */
@@ -5643,7 +5702,7 @@ export function lowerElementWrite(L, expr) {
5643
5702
  if (receiverIr?.kind === "jsval") {
5644
5703
  const obj = L.lowerExpr(target.expression);
5645
5704
  // Dispatch follows the RUNTIME world (383(d)): a checker-'any'
5646
- // receiver whose value LOWERED checked-dynamic takes the DOM keyed
5705
+ // receiver whose value LOWERED checked-dynamic takes the dyn keyed
5647
5706
  // write — the routed JSVAL arm lands it on the real engine object.
5648
5707
  if (obj.type.kind === "dyn") {
5649
5708
  const loc = locOf(expr);
@@ -5670,12 +5729,12 @@ export function lowerElementWrite(L, expr) {
5670
5729
  return { kind: "exprStmt", expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc }, loc };
5671
5730
  }
5672
5731
  // A checked-dynamic receiver TYPE (`unknown[]` and the collapsed
5673
- // `(string | object)[]` map to DYN wholesale now): the DOM keyed
5732
+ // `(string | object)[]` map to DYN wholesale now): the dyn keyed
5674
5733
  // write — dyn.keySet. Number keys canonicalize through the JS-exact
5675
5734
  // formatter; ARR receivers take canonical index keys as element
5676
5735
  // set/extend (undefined-hole padding, JS's length growth exactly),
5677
5736
  // OBJ receivers set the member, and the runtime throws Node's
5678
- // TypeErrors on every other kind. Values convert into the DOM;
5737
+ // TypeErrors on every other kind. Values convert into the checked-dynamic tree;
5679
5738
  // unconvertible ones fence per site (the dynFrom stance).
5680
5739
  if (receiverIr?.kind === "dyn") {
5681
5740
  const obj = L.lowerExpr(target.expression);
@@ -5689,7 +5748,7 @@ export function lowerElementWrite(L, expr) {
5689
5748
  }
5690
5749
  const value = L.coerceToExpected(L.lowerExpr(expr.right), DYN);
5691
5750
  if (value.type.kind !== "dyn") {
5692
- L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic array (the value cannot convert into the DOM)`);
5751
+ L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic array (the value cannot convert into the checked-dynamic tree)`);
5693
5752
  }
5694
5753
  return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [obj, key, value], type: VOID, loc }, loc };
5695
5754
  }
@@ -5729,11 +5788,11 @@ export function lowerElementWrite(L, expr) {
5729
5788
  const loc = locOf(expr);
5730
5789
  return { kind: "exprStmt", expr: { kind: "jsOp", op: "setIdx", args: [obj, key, value], type: VOID, loc }, loc };
5731
5790
  }
5732
- // A record-mapped CHECKER type over a VALUE living in the DOM (a
5791
+ // A record-mapped CHECKER type over a VALUE living in the checked-dynamic tree (a
5733
5792
  // JS file-scope object-literal global): the checked-dynamic keyed
5734
5793
  // write — dyn.keySet (later writes win, insertion order; Node's
5735
5794
  // TypeErrors on non-object receivers), the value converting into
5736
- // the DOM. Literal and runtime keys alike: the DOM's key set is
5795
+ // the checked-dynamic tree. Literal and runtime keys alike: the checked-dynamic tree's key set is
5737
5796
  // open, so no declared-field collision analysis applies.
5738
5797
  if (obj.type.kind === "dyn") {
5739
5798
  const loc = locOf(expr);
@@ -5748,7 +5807,7 @@ export function lowerElementWrite(L, expr) {
5748
5807
  }
5749
5808
  const value = L.coerceToExpected(L.lowerExpr(expr.right), DYN);
5750
5809
  if (value.type.kind !== "dyn") {
5751
- L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the DOM)`);
5810
+ L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the checked-dynamic tree)`);
5752
5811
  }
5753
5812
  return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [obj, key, value], type: VOID, loc }, loc };
5754
5813
  }
@@ -5836,7 +5895,7 @@ export function lowerElementWrite(L, expr) {
5836
5895
  // A LITERAL key naming no declared field is a pure overflow insert
5837
5896
  // — no collision to validate. Runtime keys must be able to collide
5838
5897
  // with every declared field: dyn slots validate through the
5839
- // dynCheck walker (fields must be DOM-convertible — the same
5898
+ // dynCheck walker (fields must be dyn-convertible — the same
5840
5899
  // convertibility the read needs); typed slots write through
5841
5900
  // directly, so every field must BE the index-value type.
5842
5901
  const overflowOnly = litKey !== null;
@@ -5875,7 +5934,7 @@ export function lowerElementWrite(L, expr) {
5875
5934
  // `result[key] = value`): dyn.keySet, exactly the record-mapped dyn
5876
5935
  // arm above — later writes win in insertion order, number keys
5877
5936
  // canonicalize through the JS-exact formatter (ToPropertyKey's string
5878
- // side), index keys on DOM arrays set/extend elements, and non-object
5937
+ // side), index keys on dyn arrays set/extend elements, and non-object
5879
5938
  // receivers throw Node's TypeErrors at runtime. An UNMAPPED checker
5880
5939
  // type (static `any` — mapTypeOf answers null without --dynamic)
5881
5940
  // probes the receiver's own lowered world: a dyn value takes the same
@@ -5898,7 +5957,7 @@ export function lowerElementWrite(L, expr) {
5898
5957
  }
5899
5958
  const value = L.coerceToExpected(L.lowerExpr(expr.right), DYN);
5900
5959
  if (value.type.kind !== "dyn") {
5901
- L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the DOM)`);
5960
+ L.unsupported("SC1101", expr.right, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the checked-dynamic tree)`);
5902
5961
  }
5903
5962
  return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [obj, key, value], type: VOID, loc }, loc };
5904
5963
  }
@@ -5932,7 +5991,7 @@ export function ensureString(L, e, node) {
5932
5991
  if (e.type.kind === "string")
5933
5992
  return e;
5934
5993
  if (e.type.kind === "dyn") {
5935
- // String(u) / `${u}`: a runtime dispatch over the DOM kind — Node's
5994
+ // String(u) / `${u}`: a runtime dispatch over the dyn kind — Node's
5936
5995
  // String() exactly (undefined/null texts, JS number formatting,
5937
5996
  // strings verbatim, arrays via join, objects as "[object Object]").
5938
5997
  return { kind: "toString", operand: e, type: STRING, loc: e.loc };
@@ -6058,7 +6117,7 @@ export function lowerTemplate(L, expr) {
6058
6117
  * documented divergence: a lying cast throws instead of corrupting
6059
6118
  * memory);
6060
6119
  * - dyn → anything else (closures, class instances, void) is rejected:
6061
- * those types cannot be found inside a JSON DOM. */
6120
+ * those types cannot be found inside a JSON dyn. */
6062
6121
  /** `e as T` and the old-style assertion `<T>e` — one node shape (both
6063
6122
  * carry `.type` and `.expression`), one lowering. */
6064
6123
  export function lowerAsExpression(L, expr) {
@@ -6162,7 +6221,7 @@ export function lowerAsExpression(L, expr) {
6162
6221
  return inner; // `as unknown`: erasure
6163
6222
  if (target.kind === "void" || !L.jsonSafe(target)) {
6164
6223
  // Bare undefined-armed targets pass when every OTHER arm is
6165
- // JSON-safe: the DOM holds a first-class undefined value now
6224
+ // JSON-safe: the checked-dynamic tree holds a first-class undefined value now
6166
6225
  // (index-signature overflow reads produce it for missing keys), and
6167
6226
  // the undefined arm matches exactly it — `p[key] as string |
6168
6227
  // undefined` is the missing-key idiom. Parsed JSON still never
@@ -6171,7 +6230,7 @@ export function lowerAsExpression(L, expr) {
6171
6230
  if (target.kind === "union" && L.dynConvertible(target)) {
6172
6231
  return { kind: "dynCheck", value: inner, type: target, loc: locOf(expr) };
6173
6232
  }
6174
- // Uint8Array targets: the DOM carries a bytes kind now (converted
6233
+ // Uint8Array targets: the checked-dynamic tree carries a bytes kind now (converted
6175
6234
  // stdin chunks) — the extraction validates the kind and copies out.
6176
6235
  if (target.kind === "bytes" && target.elem === "u8") {
6177
6236
  return { kind: "dynCheck", value: inner, type: target, loc: locOf(expr) };
@@ -6194,7 +6253,7 @@ export function lowerAsExpression(L, expr) {
6194
6253
  // — the errno-probing idiom): there is nothing to validate (every
6195
6254
  // field is unknown, exactly what the dyn value already answers) and
6196
6255
  // nothing to build — the cast is pure typing, so it ERASES and the
6197
- // reads ride the DOM keyed read.
6256
+ // reads ride the dyn keyed read.
6198
6257
  if (target.kind === "record") {
6199
6258
  const shape = L.shapes.get(target.shapeId);
6200
6259
  if (shape &&
@@ -6355,7 +6414,7 @@ export function lowerBinary(L, expr) {
6355
6414
  }
6356
6415
  // `events.defaultMaxListeners = v` — the module-property write
6357
6416
  // Node validates (validateNumber(n, 'defaultMaxListeners', 0)):
6358
- // the value crosses into the DOM and the runtime ladder throws
6417
+ // the value crosses into the checked-dynamic tree and the runtime ladder throws
6359
6418
  // ERR_INVALID_ARG_TYPE / ERR_OUT_OF_RANGE with Node's exact slot
6360
6419
  // name; valid numbers apply. The expression's value is the RHS
6361
6420
  // (JS's assignment yield).
@@ -6528,8 +6587,8 @@ export function lowerBinary(L, expr) {
6528
6587
  }
6529
6588
  if (left.type.kind === "dyn" || right.type.kind === "dyn") {
6530
6589
  // A checked-dynamic operand (`fn.name || '<anonymous>'` —
6531
- // test/common's _mustCallInner): both sides live in the DOM and
6532
- // the deciding test is ToBoolean over the DOM kind
6590
+ // test/common's _mustCallInner): both sides live in the checked-dynamic tree and
6591
+ // the deciding test is ToBoolean over the dyn kind
6533
6592
  // (scr_dyn_truthy) — JS value semantics exactly, result dyn. The
6534
6593
  // non-dyn side converts through the usual boundary; a value with
6535
6594
  // no dyn representation keeps the fence.
@@ -6566,6 +6625,30 @@ export function lowerBinary(L, expr) {
6566
6625
  // shapes lower through lowerCondition's bool descent instead.
6567
6626
  const target = L.mapTypeOf(L.typeOf(expr));
6568
6627
  if (target?.kind === "union") {
6628
+ // `||` whose left does NOT fit the result union: the checker built
6629
+ // that result by DROPPING the left's falsy arms (`process.env.X ||
6630
+ // null` is `string | null`, `|| 3000` is `string | number` — the
6631
+ // `undefined` is gone from both), so coercing the left eagerly, as
6632
+ // the shared shape below does, retags an arm the test is about to
6633
+ // rule out and throws where Node yields the default. Single-eval
6634
+ // instead: test the left in its OWN union and retag only on the
6635
+ // truthy side, where the dropped arms are unreachable. `&&` keeps
6636
+ // the eager shape — there the falsy left IS the result, so the
6637
+ // checker keeps those arms in the target and they must coerce.
6638
+ if (op === ts.SyntaxKind.BarBarToken && left.type.kind === "union" && !typeEquals(left.type, target)) {
6639
+ const retag = L.unionRetagHelper(left.type.unionId, target.unionId, loc);
6640
+ if (retag) {
6641
+ L.requireTruthyUnion(left.type.unionId, expr);
6642
+ return {
6643
+ kind: "orDefault",
6644
+ left,
6645
+ right: L.coerceInto(expr.right, right, target),
6646
+ retag,
6647
+ type: target,
6648
+ loc,
6649
+ };
6650
+ }
6651
+ }
6569
6652
  L.requireTruthyUnion(target.unionId, expr);
6570
6653
  return {
6571
6654
  kind: "logical",
@@ -6665,7 +6748,7 @@ export function lowerBinary(L, expr) {
6665
6748
  const right = L.lowerExpr(expr.right);
6666
6749
  if (left.type.kind === "dyn" || right.type.kind === "dyn") {
6667
6750
  // The narrowing unit comparisons ARE answerable on unknown: `v ===
6668
- // undefined` / `v !== null` test the DOM node's kind directly, and
6751
+ // undefined` / `v !== null` test the dyn node's kind directly, and
6669
6752
  // tsc's control flow narrows the branches (reads then bridge through
6670
6753
  // maybeNarrow's validated extraction).
6671
6754
  if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
@@ -6685,14 +6768,14 @@ export function lowerBinary(L, expr) {
6685
6768
  }
6686
6769
  // dyn vs SCALAR strict equality (`value !== ""`, `u === 5` — the
6687
6770
  // normalizePricing filter): a guarded kind test + payload compare,
6688
- // JS-exact (strict equality never coerces; a non-matching DOM kind
6771
+ // JS-exact (strict equality never coerces; a non-matching dyn kind
6689
6772
  // answers false). dyn vs dyn keeps the fence below.
6690
6773
  const dynSide = left.type.kind === "dyn" ? left : right;
6691
6774
  const scalarSide = dynSide === left ? right : left;
6692
6775
  if (dynSide.type.kind === "dyn" &&
6693
6776
  (scalarSide.type.kind === "f64" || scalarSide.type.kind === "string" || scalarSide.type.kind === "bool" ||
6694
6777
  // dyn vs dyn (`context.actual !== context.exact` —
6695
- // test/common's exit accounting): the runtime's whole-DOM
6778
+ // test/common's exit accounting): the runtime's whole-dyn
6696
6779
  // strict equality — scalars by value, units by kind,
6697
6780
  // reference kinds by node identity (scr_dyn_strict_eq).
6698
6781
  scalarSide.type.kind === "dyn")) {
@@ -6747,7 +6830,7 @@ export function lowerBinary(L, expr) {
6747
6830
  }
6748
6831
  if (other.type.kind === "string") {
6749
6832
  // String-context `+`: JS's answer is String(unknown) — the
6750
- // JS-exact DOM walker (numbers format, arrays join, objects
6833
+ // JS-exact dyn walker (numbers format, arrays join, objects
6751
6834
  // print [object Object], handles the same) — never a checked
6752
6835
  // cast: `'status ' + res.statusCode` concatenates like Node.
6753
6836
  const strOf = (e) => e.type.kind === "dyn" ? { kind: "toString", operand: e, type: STRING, loc: e.loc } : e;
@@ -6765,7 +6848,7 @@ export function lowerBinary(L, expr) {
6765
6848
  L.anyOpFence(`the '${ts.tokenToString(op) ?? ts.SyntaxKind[op]}' operator`, expr);
6766
6849
  }
6767
6850
  // tsc allows ===/!== on unknown (arithmetic/comparisons it rejects
6768
- // itself); a dynamic equality would need a DOM walk — validate first.
6851
+ // itself); a dynamic equality would need a dyn walk — validate first.
6769
6852
  L.unsupported("SC1100", expr, "operators on 'unknown' values");
6770
6853
  }
6771
6854
  // Operators over 'any' execute in the island with JS-exact semantics
@@ -6932,6 +7015,12 @@ export function lowerBinary(L, expr) {
6932
7015
  typeEquals(idLeft.type, idRight.type)) {
6933
7016
  return { kind: "bin", op: negated ? "!==" : "===", left: idLeft, right: idRight, type: BOOL, loc };
6934
7017
  }
7018
+ // Runtime HANDLES are objects to === too: one handle per socket/
7019
+ // request/response, so pointer identity IS JS's object equality
7020
+ // (`c.pause() === c` — Node's chaining assertions). */
7021
+ if (DYN_HANDLE_KINDS.has(idLeft.type.kind) && typeEquals(idLeft.type, idRight.type)) {
7022
+ return { kind: "bin", op: negated ? "!==" : "===", left: idLeft, right: idRight, type: BOOL, loc };
7023
+ }
6935
7024
  L.unsupported("SC1043", expr);
6936
7025
  break;
6937
7026
  }
@@ -7303,7 +7392,7 @@ export function lowerUnionTypeofTest(L, expr, loc) {
7303
7392
  return null;
7304
7393
  }
7305
7394
  /** `typeof v === "lit"` / `typeof v !== "lit"` where v is `unknown`-typed
7306
- * (dyn): the runtime kind test over the DOM node's tag. Only the kinds a
7395
+ * (dyn): the runtime kind test over the dyn node's tag. Only the kinds a
7307
7396
  * later read can bridge narrow ("string"/"number"/"boolean") plus
7308
7397
  * "undefined" (no payload to read); "object"/"function" tests keep the
7309
7398
  * fence — an object-narrowed `unknown` read has no lowering anyway (a
@@ -7387,7 +7476,7 @@ export function lowerDynTypeofTest(L, expr, loc) {
7387
7476
  loc,
7388
7477
  };
7389
7478
  }
7390
- // `typeof v === "object"`: the DOM answers exactly (object, array,
7479
+ // `typeof v === "object"`: the dyn answers exactly (object, array,
7391
7480
  // bytes, and null kinds — JS's oldest wart preserved). tsc narrows
7392
7481
  // the branch to `object | null`; reads past the narrow take the
7393
7482
  // checked-cast path per site.
@@ -7401,7 +7490,7 @@ export function lowerDynTypeofTest(L, expr, loc) {
7401
7490
  loc,
7402
7491
  };
7403
7492
  }
7404
- // `typeof v === "function"`: a REAL runtime test since the DOM's
7493
+ // `typeof v === "function"`: a REAL runtime test since the checked-dynamic tree's
7405
7494
  // function kind exists (boxed closures — the mustCall guard
7406
7495
  // `if (typeof fn !== 'function') throw` answers honestly).
7407
7496
  if (b.text === "function") {
@@ -7564,7 +7653,7 @@ export function probeLower(L, node) {
7564
7653
  * over a hierarchy class, `typeof` over a primitive), the read bridges
7565
7654
  * with a kind-unchecked `caughtNarrow` extraction (trust-the-checker,
7566
7655
  * exactly like unionNarrow). Every OTHER read is the narrowness fence:
7567
- * the binding's payload is a typed exception snapshot, not a dyn DOM, so
7656
+ * the binding's payload is a typed exception snapshot, not a dyn, so
7568
7657
  * un-narrowed uses have nothing sound to lower to. */
7569
7658
  export function caughtRead(L, node, local, loc) {
7570
7659
  const ref = { kind: "varRef", localId: local.id, type: CAUGHT, loc };
@@ -7580,10 +7669,10 @@ export function caughtRead(L, node, local, loc) {
7580
7669
  }
7581
7670
  }
7582
7671
  // An UN-narrowed use — the occurrence still types `unknown` — converts
7583
- // to a dyn DOM value (`options.onError?.(error)` — the caught snapshot
7672
+ // to a dyn value (`options.onError?.(error)` — the caught snapshot
7584
7673
  // flowing into an unknown slot): the typed→unknown deep-copy stance
7585
7674
  // extended to exception payloads. Error payloads keep their
7586
- // observability (instanceof Error / .message / String() — the DOM's
7675
+ // observability (instanceof Error / .message / String() — the checked-dynamic tree's
7587
7676
  // error encoding); other object payloads are type-erased at runtime and
7588
7677
  // convert to the "[object Object]" approximation — SEMANTICS.md 67.
7589
7678
  if (narrowed?.kind === "dyn") {
@@ -7689,14 +7778,14 @@ export function lowerInstanceOf(L, expr, loc) {
7689
7778
  L.builtinStreamInfoOf(rhsMemberSymbol) ??
7690
7779
  undefined;
7691
7780
  if (!target) {
7692
- // `u instanceof Uint8Array` on an `unknown` value: the DOM carries a
7781
+ // `u instanceof Uint8Array` on an `unknown` value: the checked-dynamic tree carries a
7693
7782
  // bytes kind — one runtime tag test, and tsc's narrowing types the
7694
7783
  // true branch (reads bridge through maybeNarrow's validated
7695
7784
  // extraction, like the typeof tests). Node's Buffer IS a Uint8Array
7696
7785
  // subclass and rides the same bytes kind, so both worlds answer true
7697
7786
  // for Buffer payloads — Node-exact (the bytes kind's other
7698
7787
  // divergences are SEMANTICS.md 45). Catch bindings stay out (their
7699
- // payload is a typed snapshot, not a DOM).
7788
+ // payload is a typed snapshot, not a dyn).
7700
7789
  if (ts.isIdentifier(expr.right) &&
7701
7790
  L.isStdlibGlobal(expr.right, "Uint8Array") &&
7702
7791
  !L.caughtLocalOf(expr.left)) {
@@ -7787,7 +7876,7 @@ export function lowerInstanceOf(L, expr, loc) {
7787
7876
  };
7788
7877
  }
7789
7878
  const left = L.lowerExpr(expr.left);
7790
- // `u instanceof Error` on an `unknown` value: the DOM's error encoding
7879
+ // `u instanceof Error` on an `unknown` value: the checked-dynamic tree's error encoding
7791
7880
  // (the shape caughtToDyn builds for Error payloads — the reserved
7792
7881
  // "%error" marker) answers the test, so a caught Error passed through
7793
7882
  // an unknown slot narrows like Node (`error instanceof Error ?
@@ -7800,7 +7889,7 @@ export function lowerInstanceOf(L, expr, loc) {
7800
7889
  return { kind: "dynTest", test: "error", value: left, type: BOOL, loc };
7801
7890
  }
7802
7891
  // `u instanceof TypeError` (and the other BUILTIN error classes) on a
7803
- // dyn value: the from_error cache holds the DOM↔error identity edge,
7892
+ // dyn value: the from_error cache holds the checked-dynamic tree↔error identity edge,
7804
7893
  // so the runtime resolves the encoding back to its error and asks the
7805
7894
  // vtable's stamped interval — exact for every error that crossed the
7806
7895
  // boundary (a hand-built {%error} literal answers false: subclass
@@ -8031,6 +8120,25 @@ export function lowerInExpression(L, expr, loc) {
8031
8120
  const rIn = lowerRuntimeKeyIn(L, expr, loc);
8032
8121
  if (rIn)
8033
8122
  return rIn;
8123
+ // A runtime key over a CHECKED-DYNAMIC receiver (`name in
8124
+ // agent.sockets` — both sides computed; the checker may type the
8125
+ // receiver as a Dict while the VALUE lives in the checked-dynamic tree, so the
8126
+ // LOWERED type decides): the dyn presence answer, with the key
8127
+ // stringified like every property key (o[k] is o[String(k)] in JS;
8128
+ // `in` shares the coercion).
8129
+ {
8130
+ const probed = probeLower(L, expr.right);
8131
+ if (probed?.type.kind === "dyn") {
8132
+ let k = L.lowerExpr(expr.left); // JS order: the key evaluates first
8133
+ if (k.type.kind === "f64" || k.type.kind === "string" || k.type.kind === "dyn") {
8134
+ k = L.ensureString(k, expr.left);
8135
+ const recvD = L.lowerExpr(expr.right);
8136
+ if (recvD.type.kind === "dyn") {
8137
+ return { kind: "libCall", fn: "dyn.hasKey", args: [recvD, k], type: BOOL, loc };
8138
+ }
8139
+ }
8140
+ }
8141
+ }
8034
8142
  L.unsupported("SC1090", expr.left, "'in' with computed (non-literal) keys (a const whose type is one string literal folds; a string-typed key answers over index-signature record receivers)");
8035
8143
  }
8036
8144
  // A receiver re-read (the static folds below) is safe for plain reads
@@ -8093,7 +8201,7 @@ export function lowerInExpression(L, expr, loc) {
8093
8201
  }
8094
8202
  }
8095
8203
  // A dyn receiver (`"portless" in pkg` after the `typeof pkg ===
8096
- // "object"` guard): own-member presence on the DOM — tsc admits `in`
8204
+ // "object"` guard): own-member presence on the checked-dynamic tree — tsc admits `in`
8097
8205
  // only on object-typed operands, so unit receivers are unreachable.
8098
8206
  if (recv.type.kind === "dyn") {
8099
8207
  return { kind: "dynHasKey", key, value: recv, type: BOOL, loc };
@@ -8831,8 +8939,8 @@ export function lowerUnionProperty(L, expr) {
8831
8939
  // fallback's discipline.
8832
8940
  // A checker-union receiver whose VALUE lowered checked-dynamic (a
8833
8941
  // never-tainted JS chain — `cmd[1].length` on `const cmd = ['pwd',
8834
- // []]`, where the element read stayed a DOM node): read through the
8835
- // DOM keyed read like the unmappable-receiver path below the chain.
8942
+ // []]`, where the element read stayed a dyn node): read through the
8943
+ // dyn keyed read like the unmappable-receiver path below the chain.
8836
8944
  if (value.type.kind === "dyn") {
8837
8945
  const key = { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) };
8838
8946
  return { kind: "dynKeyGet", key, value, type: DYN, loc: locOf(expr) };
@@ -9219,9 +9327,9 @@ export function symbolFieldTarget(L, expr) {
9219
9327
  * tsc-clean (the property types as the setter's param), but Node yields
9220
9328
  * undefined, which these property types cannot represent. */
9221
9329
  export function fieldGetExpr(L, target, loc, blame) {
9222
- // A record-shaped CHECKER target whose receiver VALUE lives in the DOM
9330
+ // A record-shaped CHECKER target whose receiver VALUE lives in the checked-dynamic tree
9223
9331
  // (a JS file-scope object-literal global): the checked-dynamic keyed
9224
- // read — dynKeyGet (a missing key answers the DOM undefined, exactly
9332
+ // read — dynKeyGet (a missing key answers the dyn undefined, exactly
9225
9333
  // JS); consumers validate (dynCheck) where a static type is required.
9226
9334
  if ((target.container === "record" || target.container === "recordOvf") &&
9227
9335
  target.obj.type.kind === "dyn") {
@@ -9302,15 +9410,15 @@ export function fieldGetExpr(L, target, loc, blame) {
9302
9410
  * call). A write to a getter-only property never gets here in a clean
9303
9411
  * program (tsc's TS2540 is the fence); the rejection is the backstop. */
9304
9412
  export function fieldSetStmt(L, target, value, loc, blame) {
9305
- // A record-shaped CHECKER target whose receiver VALUE lives in the DOM:
9413
+ // A record-shaped CHECKER target whose receiver VALUE lives in the checked-dynamic tree:
9306
9414
  // the checked-dynamic keyed write — dyn.keySet (later writes win,
9307
9415
  // insertion order; Node's TypeErrors on non-object receivers), the
9308
- // value converting into the DOM.
9416
+ // value converting into the checked-dynamic tree.
9309
9417
  if ((target.container === "record" || target.container === "recordOvf") &&
9310
9418
  target.obj.type.kind === "dyn") {
9311
9419
  const v = L.coerceToExpected(value, DYN);
9312
9420
  if (v.type.kind !== "dyn") {
9313
- L.unsupported("SC1101", blame, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the DOM)`);
9421
+ L.unsupported("SC1101", blame, `storing '${L.fmt(value.type)}' values in a checked-dynamic object (the value cannot convert into the checked-dynamic tree)`);
9314
9422
  }
9315
9423
  return {
9316
9424
  kind: "exprStmt",
@@ -9398,7 +9506,7 @@ export function lowerPromiseRejectCall(L, call, access) {
9398
9506
  const type = ctxT ? L.mapTypeOf(ctxT) : null;
9399
9507
  const reasonNode = call.arguments[0];
9400
9508
  // A CHECKED-DYNAMIC reason (`Promise.reject(value)` where value rode
9401
- // an untyped binding — the tracingChannel suite's shape): the DOM
9509
+ // an untyped binding — the tracingChannel suite's shape): the checked-dynamic tree
9402
9510
  // value IS the rejection payload (the thrown-dyn representation, so
9403
9511
  // identity survives to catch/unhandledRejection observers), and the
9404
9512
  // result is promise<dyn> when no context names a concrete one.
@@ -9541,7 +9649,7 @@ export function lowerFieldCompound(L, access, op, rhsNode, loc) {
9541
9649
  const concat = {
9542
9650
  kind: "strConcat",
9543
9651
  // String-context read: JS's String(unknown) over the field —
9544
- // the JS-exact DOM walker, never a checked cast.
9652
+ // the JS-exact dyn walker, never a checked cast.
9545
9653
  left: { kind: "toString", operand: read, type: STRING, loc },
9546
9654
  right: rhs,
9547
9655
  type: STRING,