@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
@@ -2,10 +2,16 @@
2
2
  * crypto, child_process spawn/spawnSync and child/stats/spawn-result
3
3
  * methods), JSON.parse/stringify, process properties/methods and
4
4
  * process.env access, and console.log detection. */
5
+ import { readFileSync } from "node:fs";
5
6
  import { builtinModules } from "node:module";
7
+ import { dirname, resolve } from "node:path";
6
8
  import * as ts from "../ts7/adapter.js";
7
- import { dynUndefinedExpr, ladderFenceExpr, nodeThrowExpr, own } from "./lowerer.js";
9
+ import { PoisonError, dynUndefinedExpr, ladderFenceExpr, nodeThrowExpr, own } from "./lowerer.js";
8
10
  import { canonicalBuiltinModule, isJsSourceFile, locOf, requireSpecOf } from "../program.js";
11
+ import { isRelativeSpecifier } from "../shared.js";
12
+ import { probeNodeRequireRefusal } from "../npm.js";
13
+ import { isNpmStaticPackage } from "../npm-static.js";
14
+ import { invalidJsonModuleDiag, requiresDynamicImportDiag } from "../../diagnostics/diagnostic.js";
9
15
  import { builtinModuleFnOf, FS_READDIR_DOCUMENTED_OPTIONS, FS_WATCH_DOCUMENTED_OPTIONS, FS_WRITE_FILE_DOCUMENTED_OPTIONS, QS_PARSE_DOCUMENTED_OPTIONS, QS_STRINGIFY_DOCUMENTED_OPTIONS, READLINE_DOCUMENTED_OPTIONS, builtinConstLit, fenceOrDropOptionKey, isChildSurfaceMember, } from "./surfaces.js";
10
16
  import { conditionalSpreadOf, lowerDynObjectLiteral } from "./lower-exprs.js";
11
17
  import { HTTP2_CONSTANTS } from "./http2-constants.js";
@@ -132,9 +138,17 @@ export function builtinMemberRequireDecl(nameNode, init) {
132
138
  export function builtinNamespaceDestructureModuleOf(L, decl) {
133
139
  if (decl.name === undefined || !ts.isObjectBindingPattern(decl.name) || decl.initializer === undefined)
134
140
  return null;
135
- if (!ts.isIdentifier(decl.initializer))
136
- return null;
137
- const module = L.builtinNamespaceModuleOf(decl.initializer);
141
+ // `const { join } = require("node:path")` through a createRequire
142
+ // binding: the call IS the namespace — same table keying.
143
+ let module = null;
144
+ const init = stripTypeCasts(decl.initializer);
145
+ if (ts.isCallExpression(init)) {
146
+ const cr = createRequireSpecOf(L, init);
147
+ module = cr !== null && cr.spec !== null ? canonicalBuiltinModule(cr.spec) : null;
148
+ }
149
+ else if (ts.isIdentifier(init)) {
150
+ module = L.builtinNamespaceModuleOf(init);
151
+ }
138
152
  if (module === null)
139
153
  return null;
140
154
  for (const el of decl.name.elements) {
@@ -145,6 +159,223 @@ export function builtinNamespaceDestructureModuleOf(L, decl) {
145
159
  }
146
160
  return module;
147
161
  }
162
+ /* ── node:module — createRequire's static erasure ─────────────────────
163
+ * The config/version-reading pattern real CLIs ship:
164
+ * import { createRequire } from "node:module";
165
+ * const require = createRequire(import.meta.url);
166
+ * const pkg = require("../package.json");
167
+ * A compiled program's module graph is fixed at build time, so the
168
+ * indirection ERASES where the required specifier is a static string
169
+ * literal naming something the compiler already handles: a builtin (the
170
+ * binding is a namespace import in const clothing), a relative .json
171
+ * document (the file bakes and parses like JSON.parse of its text), or
172
+ * an installed npm package (the island's require-condition entry under
173
+ * --dynamic). Dynamic specifiers and other targets fence by name. */
174
+ /** Strips the type-only wrappers the require pattern rides in typed
175
+ * code (`require("node:os") as typeof import("node:os")` — the
176
+ * fallback declarations answer `unknown`, so the cast IS the idiom),
177
+ * plus parens, legacy assertions, and non-null suffixes. */
178
+ export function stripTypeCasts(e) {
179
+ let cur = e;
180
+ while (ts.isParenthesizedExpression(cur) || ts.isAsExpression(cur) ||
181
+ ts.isTypeAssertion(cur) || ts.isNonNullExpression(cur)) {
182
+ cur = cur.expression;
183
+ }
184
+ return cur;
185
+ }
186
+ /** The `createRequire(<base>)` call over the node:module import binding
187
+ * with a supported base — import.meta.url, import.meta.filename, or
188
+ * __filename, every spelling of "this file" — or null. The base never
189
+ * LOWERS (import.meta has no value representation): it only names the
190
+ * file whose directory anchors the returned require's relative
191
+ * resolution, and every supported spelling names the call's own file. */
192
+ export function createRequireBaseCallOf(L, expr) {
193
+ const e = stripTypeCasts(expr);
194
+ if (!ts.isCallExpression(e) || e.questionDotToken)
195
+ return null;
196
+ if (!ts.isIdentifier(e.expression))
197
+ return null;
198
+ const bi = builtinImportOf(L, e.expression);
199
+ if (!bi || bi.module !== "module" || bi.member !== "createRequire")
200
+ return null;
201
+ if (e.arguments.length !== 1)
202
+ return null;
203
+ const base = stripTypeCasts(e.arguments[0]);
204
+ if (ts.isIdentifier(base) && base.text === "__filename")
205
+ return e;
206
+ if (ts.isPropertyAccessExpression(base) &&
207
+ !base.questionDotToken &&
208
+ ts.isMetaProperty(base.expression) &&
209
+ base.expression.keywordToken === ts.SyntaxKind.ImportKeyword &&
210
+ (base.name.text === "url" || base.name.text === "filename")) {
211
+ return e;
212
+ }
213
+ return null;
214
+ }
215
+ /** True for `const require = createRequire(import.meta.url)` — the
216
+ * binding is compile-time plumbing (each call through it resolves per
217
+ * site) with no storage and no code; both declaration walks skip by
218
+ * this test. A reassignable (let/var) binding never matches — callers
219
+ * gate on constness like the other alias decls. */
220
+ export function createRequireBindingDecl(L, nameNode, init) {
221
+ if (!ts.isIdentifier(nameNode) || init === undefined)
222
+ return false;
223
+ return createRequireBaseCallOf(L, init) !== null;
224
+ }
225
+ /** The declaring source file when `callee` denotes a createRequire-made
226
+ * require: a CONST binding over createRequire(import.meta.url) (the
227
+ * binding's own file anchors resolution) or the inline
228
+ * `createRequire(import.meta.url)(...)` spelling (the call's file).
229
+ * Null off the pattern, so call chains keep trying. */
230
+ export function createRequireCalleeFileOf(L, callee) {
231
+ const e = stripTypeCasts(callee);
232
+ if (ts.isCallExpression(e)) {
233
+ return createRequireBaseCallOf(L, e) !== null ? e.getSourceFile() : null;
234
+ }
235
+ if (!ts.isIdentifier(e))
236
+ return null;
237
+ const symbol = L.checker.getSymbolAtLocation(e);
238
+ const decl = symbol ? L.checker.declarationsOf(symbol)[0] : undefined;
239
+ if (!decl || !ts.isVariableDeclaration(decl) || decl.initializer === undefined)
240
+ return null;
241
+ if (!ts.isVariableDeclarationList(decl.parent) || (decl.parent.flags & ts.NodeFlags.Const) === 0)
242
+ return null;
243
+ return createRequireBaseCallOf(L, decl.initializer) !== null ? decl.getSourceFile() : null;
244
+ }
245
+ /** The static require of `R("spec")` through a createRequire binding:
246
+ * the literal specifier plus the file anchoring relative resolution.
247
+ * Null when the callee is not a createRequire-made require; a matching
248
+ * callee with a non-literal (or missing) specifier answers spec null,
249
+ * so the call lowering fences by name instead of falling through to
250
+ * the generic call paths. */
251
+ export function createRequireSpecOf(L, call) {
252
+ if (call.questionDotToken)
253
+ return null;
254
+ const baseFile = createRequireCalleeFileOf(L, call.expression);
255
+ if (baseFile === null)
256
+ return null;
257
+ if (call.arguments.length !== 1)
258
+ return { spec: null, baseFile };
259
+ const a = call.arguments[0];
260
+ return { spec: ts.isStringLiteralLike(a) ? a.text : null, baseFile };
261
+ }
262
+ /** True for `const fs = require("node:fs")` through a createRequire
263
+ * binding — a builtin namespace import in const clothing: alias
264
+ * plumbing with no storage (uses resolve through
265
+ * builtinNamespaceModuleOf's createRequire arm); both declaration
266
+ * walks skip by this test. */
267
+ export function createRequireNamespaceDecl(L, nameNode, init) {
268
+ if (!ts.isIdentifier(nameNode) || init === undefined)
269
+ return false;
270
+ const call = stripTypeCasts(init);
271
+ if (!ts.isCallExpression(call))
272
+ return false;
273
+ const cr = createRequireSpecOf(L, call);
274
+ return cr !== null && cr.spec !== null && canonicalBuiltinModule(cr.spec) !== null;
275
+ }
276
+ /** `require("spec")` through a createRequire binding — the erasure per
277
+ * target. Builtins are reached here only OUTSIDE the const-namespace-
278
+ * binding shape (that declaration erases; member uses resolve through
279
+ * the namespace tables) and fence toward it. A relative .json document
280
+ * bakes: the file's text validates as JSON at compile time and the
281
+ * call lowers to json.parse over the baked literal — JSON.parse's
282
+ * checked-dynamic `unknown` stance, and exactly Node's value (require
283
+ * of JSON IS JSON.parse of the file; the per-call re-parse forgoes
284
+ * Node's module-cache identity, unobservable without mutation). A bare
285
+ * specifier NOTHING installed resolves compiles to Node's catchable
286
+ * MODULE_NOT_FOUND throw (the optional-dependency try/require
287
+ * pattern); an installed package loads through the island's
288
+ * require-condition entry under --dynamic (collectCreateRequires
289
+ * embedded it) and reports the requires-dynamic diagnostic in a static
290
+ * build. Null when the callee is not a createRequire require. */
291
+ export function lowerCreateRequireCall(L, call, loc) {
292
+ const cr = createRequireSpecOf(L, call);
293
+ if (cr === null)
294
+ return null;
295
+ if (cr.spec === null) {
296
+ L.noLowering("createRequire's require with this argument shape", call, "the compiled module graph is fixed at build time — the one lowered form is require(\"<static string literal>\")");
297
+ }
298
+ const spec = cr.spec;
299
+ if (canonicalBuiltinModule(spec) !== null) {
300
+ L.unsupported("SC1090", call, `module namespace objects as values (bind it first: const m = require("${spec}"), then access members through the binding)`);
301
+ }
302
+ if (spec.startsWith("#")) {
303
+ L.noLowering(`createRequire's require of the '${spec}' project import`, call, "imports-field specifiers have no require lowering yet — import the target statically");
304
+ }
305
+ if (isRelativeSpecifier(spec) || spec.startsWith("/")) {
306
+ if (!spec.endsWith(".json")) {
307
+ L.noLowering(`createRequire's require of '${spec}'`, call, "relative requires lower for .json documents only — a program module is a static import");
308
+ }
309
+ const abs = spec.startsWith("/")
310
+ ? spec
311
+ : resolve(dirname(cr.baseFile.fileName), spec);
312
+ let text = null;
313
+ try {
314
+ text = readFileSync(abs, "utf8");
315
+ }
316
+ catch {
317
+ /* the fence below speaks */
318
+ }
319
+ if (text === null) {
320
+ L.noLowering(`createRequire's require of '${spec}' (no file at ${abs})`, call, "the required document resolves at build time — check the path against the requiring file");
321
+ }
322
+ try {
323
+ JSON.parse(text);
324
+ }
325
+ catch (e) {
326
+ L.pushDiag(invalidJsonModuleDiag(abs, e instanceof Error ? e.message : String(e), loc));
327
+ throw new PoisonError();
328
+ }
329
+ return {
330
+ kind: "libCall",
331
+ fn: "json.parse",
332
+ args: [{ kind: "strLit", value: text, type: STRING, loc }],
333
+ type: DYN,
334
+ loc,
335
+ };
336
+ }
337
+ // Bare package specifiers. --npm-static opt-ins are program modules —
338
+ // their exports bind through static imports, not a require value.
339
+ const pkgName = spec.startsWith("@")
340
+ ? spec.split("/").slice(0, 2).join("/")
341
+ : spec.split("/")[0];
342
+ if (isNpmStaticPackage(pkgName)) {
343
+ L.noLowering(`createRequire's require of the --npm-static package '${pkgName}'`, call, "the opted-in package compiles as program modules — import it statically");
344
+ }
345
+ const refusal = probeNodeRequireRefusal(cr.baseFile.fileName, spec);
346
+ if (refusal !== null) {
347
+ // Node's require-site MODULE_NOT_FOUND, catchable — the compiled
348
+ // expression IS that throw (the typed dummy is abandoned by the
349
+ // pending check's unwind).
350
+ return nodeThrowExpr(0, "MODULE_NOT_FOUND", refusal.message, DYN, loc);
351
+ }
352
+ if (!L.dynamic) {
353
+ L.pushDiag(requiresDynamicImportDiag(pkgName, loc));
354
+ throw new PoisonError();
355
+ }
356
+ const res = L.createRequireImports.get(`${cr.baseFile.fileName}\u0000${spec}`);
357
+ if (res === undefined) {
358
+ // Collection never saw the site (a shape this walk and that walk
359
+ // disagree on) — fence rather than mis-embed.
360
+ L.noLowering(`createRequire's require of '${spec}'`, call, undefined);
361
+ }
362
+ if (res === "")
363
+ throw new PoisonError(); // reported at collection
364
+ // A CJS facade's default IS module.exports (Node's require answer);
365
+ // an ESM-resolved entry answers its namespace (Node's require(esm)).
366
+ const exportName = res.format === "esm" ? "*" : "default";
367
+ return {
368
+ kind: "libCall",
369
+ fn: "island.import",
370
+ args: [
371
+ { kind: "strLit", value: res.entryKey, type: STRING, loc },
372
+ { kind: "strLit", value: exportName, type: STRING, loc },
373
+ { kind: "strLit", value: spec, type: STRING, loc },
374
+ ],
375
+ type: JSVAL,
376
+ loc,
377
+ };
378
+ }
148
379
  /** True when `node` denotes the http2.constants OBJECT — any of its
149
380
  * spellings: `http2.constants` through a namespace/require binding, a
150
381
  * destructured or member-bound `constants` alias from the http2 module,
@@ -356,7 +587,7 @@ function optionMember(p) {
356
587
  * utimes family runs on its time arguments: finite numbers pass
357
588
  * (negatives answer now/1000, Node's shape), numeric STRINGS coerce
358
589
  * through ToNumber's loose-equality gate, everything else throws
359
- * Node's exact ERR_INVALID_ARG_TYPE. The argument crosses as a DOM
590
+ * Node's exact ERR_INVALID_ARG_TYPE. The argument crosses as a dyn
360
591
  * value so the runtime renders the Received tail. Null when this is
361
592
  * not that call (the table fence stays for other shapes). */
362
593
  export function lowerFsToUnixTimestampCall(L, expr, bi, loc) {
@@ -374,7 +605,7 @@ export function lowerFsToUnixTimestampCall(L, expr, bi, loc) {
374
605
  /** The fs validation-ladder spoke (checked-dynamic lane, JS sources
375
606
  * only — TypeScript keeps its compile fences): implemented-namespace
376
607
  * calls whose misuse Node rejects with typed errors lower to fs.*Chk
377
- * libCalls that replicate the validation ladder over DOM values and
608
+ * libCalls that replicate the validation ladder over dyn values and
378
609
  * throw Node's exact ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE /
379
610
  * ERR_OUT_OF_RANGE — the honest tail (the real operation where one
380
611
  * exists, the compiler-rendered SC2020 fence otherwise) runs only
@@ -388,7 +619,7 @@ export function lowerFsLadderCall(L, expr, bi, loc) {
388
619
  const args = expr.arguments;
389
620
  if (args.some(ts.isSpreadElement))
390
621
  return null;
391
- // Every ladder argument crosses as a DOM value; an argument that
622
+ // Every ladder argument crosses as a dyn value; an argument that
392
623
  // cannot leaves the historical fence in place.
393
624
  const dynArg = (node) => {
394
625
  if (!node)
@@ -426,7 +657,7 @@ export function lowerFsLadderCall(L, expr, bi, loc) {
426
657
  // false THROUGH it, and the answer is asynchronous.
427
658
  // A provably-non-file `new URL('<literal>')` path (the suite's
428
659
  // https://foo probe): Node answers false through the callback
429
- // synchronously — the DOM has no URL kind, so the path slot
660
+ // synchronously — the checked-dynamic tree has no URL kind, so the path slot
430
661
  // carries the unvalidatable token instead (construction of a
431
662
  // parseable literal is effect-free; file: URLs keep the fence —
432
663
  // they would need the real path conversion).
@@ -548,7 +779,7 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
548
779
  }
549
780
  // node:querystring — parse/stringify are entirely special-cased (the
550
781
  // sep/eq/options completions, parse's call-site-shaped dictionary
551
- // result, stringify's DOM-crossing object argument); decode/encode
782
+ // result, stringify's dyn-crossing object argument); decode/encode
552
783
  // are Node's own aliases of the pair (`const decode = parse` in the
553
784
  // module source) and take the same lowerings. escape/unescape ride
554
785
  // the generic table tail below.
@@ -586,7 +817,7 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
586
817
  }
587
818
  }
588
819
  // node:diagnostics_channel — the module-level pub/sub surface. The
589
- // subscriber arguments box into the DOM (dyn) so JS harness wrappers
820
+ // subscriber arguments box into the checked-dynamic tree (dyn) so JS harness wrappers
590
821
  // (test/common's mustCall — a rest-args function value) and typed
591
822
  // closures both cross; publish and the Channel methods lower in
592
823
  // lowerDcChannelMethodCall over the f64 channel handle.
@@ -2253,7 +2484,7 @@ function isReadlineTyped(L, node) {
2253
2484
  function dcChannelNameArg(L, node) {
2254
2485
  return L.lowerExprExpecting(node, STRING);
2255
2486
  }
2256
- /** A diagnostics_channel subscriber as a DOM value: dyn callables pass
2487
+ /** A diagnostics_channel subscriber as a dyn value: dyn callables pass
2257
2488
  * through (test/common's mustCall wrapper — an untyped JS function
2258
2489
  * value), boxable typed closures ride dynFrom. Identity is preserved
2259
2490
  * either way, so unsubscribe(fn) finds the subscribe(fn) entry. */
@@ -2275,14 +2506,14 @@ function dcSubscriberArg(L, node) {
2275
2506
  canBoxFuncIntoDyn(cb.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
2276
2507
  return { kind: "dynFrom", value: cb, type: DYN, loc: locOf(node) };
2277
2508
  }
2278
- L.unsupported("SC1090", node, `channel subscribers of type '${L.fmt(cb.type)}' (subscribers cross as DOM functions — parameters must be dyn-representable)`);
2509
+ L.unsupported("SC1090", node, `channel subscribers of type '${L.fmt(cb.type)}' (subscribers cross as dyn functions — parameters must be dyn-representable)`);
2279
2510
  }
2280
- /** A published message as a DOM value: dyn passes through, everything
2511
+ /** A published message as a dyn value: dyn passes through, everything
2281
2512
  * in the dynFrom domain (JSON-safe data, bytes, %Error, boxable
2282
2513
  * functions, handle kinds) boxes; the rest fences with the domain named. */
2283
2514
  function dcMessageArg(L, node) {
2284
2515
  // An explicit `undefined` argument (tracePromise(fn, ctx, undefined,
2285
- // ...args) — Node's own no-this spelling) is the undefined DOM value,
2516
+ // ...args) — Node's own no-this spelling) is the undefined dyn value,
2286
2517
  // exactly what an omitted slot defaults to.
2287
2518
  if (ts.isIdentifier(node) && node.text === "undefined") {
2288
2519
  return dynUndefinedExpr(locOf(node));
@@ -2293,7 +2524,7 @@ function dcMessageArg(L, node) {
2293
2524
  if (canConvertToDyn(msg.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
2294
2525
  return { kind: "dynFrom", value: msg, type: DYN, loc: locOf(node) };
2295
2526
  }
2296
- L.unsupported("SC1090", node, `publishing '${L.fmt(msg.type)}' messages (messages cross as DOM values — JSON-safe data, Uint8Array, errors, and functions)`);
2527
+ L.unsupported("SC1090", node, `publishing '${L.fmt(msg.type)}' messages (messages cross as dyn values — JSON-safe data, Uint8Array, errors, and functions)`);
2297
2528
  }
2298
2529
  /** True when `node`'s checker type is diagnostics_channel's Channel
2299
2530
  * (stdlib provenance plus the ambient module, the readline.Interface
@@ -2334,7 +2565,7 @@ export function lowerDcChannelMethodCall(L, call, access) {
2334
2565
  // bindStore(store[, transform]) / unbindStore(store) / runStores(data,
2335
2566
  // fn[, thisArg[, ...args]]): the AsyncLocalStorage integration — the
2336
2567
  // store argument is the ALS f64 handle; the transform crosses as a
2337
- // DOM function (absent = identity, the undefined DOM value); runStores
2568
+ // dyn function (absent = identity, the undefined dyn value); runStores
2338
2569
  // enters the bound stores, publishes inside them, and forwards
2339
2570
  // this/arguments to fn exactly like the trace calls.
2340
2571
  if ((name === "bindStore" || name === "unbindStore") &&
@@ -2377,7 +2608,7 @@ function isAlsTyped(L, node) {
2377
2608
  }
2378
2609
  /** Method calls on AsyncLocalStorage receivers: run(store, fn, ...args),
2379
2610
  * exit(fn, ...args), getStore(), enterWith(store), disable() — over the
2380
- * f64 store handle (als.* libCalls; values cross as DOM values). Null
2611
+ * f64 store handle (als.* libCalls; values cross as dyn values). Null
2381
2612
  * for non-ALS receivers. */
2382
2613
  export function lowerAlsMethodCall(L, call, access) {
2383
2614
  if (call.questionDotToken || access.questionDotToken)
@@ -2447,8 +2678,8 @@ function isDcTracingChannelTyped(L, node) {
2447
2678
  L.isStdlibFile(d.getSourceFile()));
2448
2679
  }
2449
2680
  const DC_TRACE_EVENTS = ["start", "end", "asyncStart", "asyncEnd", "error"];
2450
- /** A TracingChannel handlers object as a DOM value: dyn passes through;
2451
- * an INLINE object literal of plain event-name properties builds the DOM
2681
+ /** A TracingChannel handlers object as a dyn value: dyn passes through;
2682
+ * an INLINE object literal of plain event-name properties builds the checked-dynamic tree
2452
2683
  * object member-by-member (each value through the message conversion —
2453
2684
  * closures box by identity, so unsubscribe still matches), covering the
2454
2685
  * `{ start: () => {} }` spelling whose record type (function members)
@@ -2477,7 +2708,7 @@ function dcHandlersArg(L, node) {
2477
2708
  }
2478
2709
  return dcMessageArg(L, node);
2479
2710
  }
2480
- /** A trace-call argument list's tail as ONE DOM array (dynArrLit over
2711
+ /** A trace-call argument list's tail as ONE dyn array (dynArrLit over
2481
2712
  * per-element conversions). Spread arguments fence — the built array
2482
2713
  * must mirror the call site's argument vector exactly. */
2483
2714
  function dcTraceArgsArr(L, args, loc) {
@@ -2490,9 +2721,9 @@ function dcTraceArgsArr(L, args, loc) {
2490
2721
  return { kind: "dynArrLit", elems, type: DYN, loc };
2491
2722
  }
2492
2723
  /** Method calls on TracingChannel receivers: subscribe/unsubscribe over
2493
- * a DOM handlers object, traceSync/traceCallback through the runtime's
2724
+ * a dyn handlers object, traceSync/traceCallback through the runtime's
2494
2725
  * publish choreography (dc.tcTraceSync/dc.tcTraceCallback — fn, context,
2495
- * thisArg, and the argument vector all cross as DOM values; context
2726
+ * thisArg, and the argument vector all cross as dyn values; context
2496
2727
  * defaults to a fresh `{}` and thisArg to undefined, Node's defaults),
2497
2728
  * and tracePromise through the reaction-fiber choreography
2498
2729
  * (dc.tcTracePromise — the result is the reaction promise, typed
@@ -2763,7 +2994,7 @@ export function strdecHelper(L, op, shapeId, loc) {
2763
2994
  }
2764
2995
  /** `JSON.parse(text)` / `JSON.stringify(value)`.
2765
2996
  * - parse → a may-throw `libCall` producing a dyn value (the runtime JSON
2766
- * DOM); malformed input throws a catchable SyntaxError-shaped string.
2997
+ * dyn); malformed input throws a catchable SyntaxError-shaped string.
2767
2998
  * The divergence override types the one-argument form `unknown`; the
2768
2999
  * lib's reviver form typechecks (returning `any`) and is fenced here.
2769
3000
  * - stringify → the type-DIRECTED `jsonStringify` node: the lib
@@ -2817,8 +3048,8 @@ export function lowerJsonMethodCall(L, call, access) {
2817
3048
  }
2818
3049
  // A dyn ROOT (`JSON.stringify(u)` over unknown / `{}` / `Object` /
2819
3050
  // `object` slots, the JSON.parse round-trip) serializes with the
2820
- // runtime's DOM walker instead of a type-directed serializer — the
2821
- // DOM is JSON-representable by construction (non-JSON values fenced
3051
+ // runtime's dyn walker instead of a type-directed serializer — the
3052
+ // dyn is JSON-representable by construction (non-JSON values fenced
2822
3053
  // at their conversion INTO the slot). Two edges, both documented:
2823
3054
  // a root the stringify drops (runtime undefined) produces the TEXT
2824
3055
  // "undefined" where Node produces the undefined VALUE (tsc's own lib
@@ -3159,7 +3390,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
3159
3390
  // One name/value slot, WHATWG USVString rules: statically-string
3160
3391
  // arguments lower directly; a symbol can never convert (V8's
3161
3392
  // TypeError, statically decided); everything else crosses into the
3162
- // DOM and coerces at runtime with the object protocol (a user
3393
+ // dyn and coerces at runtime with the object protocol (a user
3163
3394
  // toString/valueOf runs and its throw propagates).
3164
3395
  const strArg = (i) => {
3165
3396
  const node = args[i];
@@ -3171,7 +3402,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
3171
3402
  }
3172
3403
  let v;
3173
3404
  if (ts.isObjectLiteralExpression(node)) {
3174
- // Object literals take the DOM literal path directly (method
3405
+ // Object literals take the dyn literal path directly (method
3175
3406
  // members box as dyn functions — the typed record fence never
3176
3407
  // applies to the coercion probes).
3177
3408
  v = lowerDynObjectLiteral(L, node);
@@ -3184,7 +3415,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
3184
3415
  v = { kind: "dynFrom", value: raw, type: DYN, loc: raw.loc };
3185
3416
  }
3186
3417
  else if (raw.type.kind === "record") {
3187
- // A RECORD-represented value that cannot cross into the DOM (a
3418
+ // A RECORD-represented value that cannot cross into the checked-dynamic tree (a
3188
3419
  // func-carrying shape — the throwing-toString probes): run
3189
3420
  // ToPrimitive's string hint STATICALLY. A zero-parameter
3190
3421
  // toString func member is called (its throw propagates); a
@@ -3199,7 +3430,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
3199
3430
  tsMember.type.kind === "func" &&
3200
3431
  tsMember.type.params.length === 0 &&
3201
3432
  L.dynConvertible(tsMember.type)) {
3202
- // Box just the toString member into a fresh DOM carrier and
3433
+ // Box just the toString member into a fresh dyn carrier and
3203
3434
  // run the protocol at runtime — the boxed call propagates its
3204
3435
  // throw, string answers convert, and a bare (void) return is
3205
3436
  // ToString(undefined), all through one path.
@@ -3215,11 +3446,11 @@ export function lowerSearchParamsMethodCall(L, call, access) {
3215
3446
  };
3216
3447
  }
3217
3448
  else {
3218
- L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the DOM — narrow unions first)");
3449
+ L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the checked-dynamic tree — narrow unions first)");
3219
3450
  }
3220
3451
  }
3221
3452
  else {
3222
- L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the DOM — narrow unions first)");
3453
+ L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the checked-dynamic tree — narrow unions first)");
3223
3454
  }
3224
3455
  }
3225
3456
  return { kind: "libCall", fn: "dyn.toStringCoerce", args: [v], type: STRING, loc };
@@ -4321,7 +4552,7 @@ export function lowerQuerystringParseCall(L, call, loc) {
4321
4552
  return { kind: "libCall", fn: "qs.parse", args: [str, sep, eq, maxKeys], type: result, loc };
4322
4553
  }
4323
4554
  /** querystring.stringify / querystring.encode: the object crosses as a
4324
- * DOM value (dynFrom — JSON-safe records and, in JS sources, dyn values
4555
+ * dyn value (dynFrom — JSON-safe records and, in JS sources, dyn values
4325
4556
  * directly) and Node's encodeStringified rules run in the runtime
4326
4557
  * (scr_qs_stringify), so arrays expand to repeated keys and
4327
4558
  * null/undefined values are empty. The default encoder is the one
@@ -4613,7 +4844,7 @@ export function lowerProcessMethodCall(L, call, access) {
4613
4844
  // (test-event-emitter-special-event-names.js's process.on).
4614
4845
  const SIGNALS = { SIGINT: 2, SIGTERM: 15 };
4615
4846
  const signo = event !== null ? own(SIGNALS, event) : undefined;
4616
- // 'unhandledRejection': the listener crosses as a DOM function and
4847
+ // 'unhandledRejection': the listener crosses as a dyn function and
4617
4848
  // the loop-end report dispatches it (reason, promise) per
4618
4849
  // never-observed rejection instead of printing and exiting 1
4619
4850
  // (scr_async.c; the end-of-turn timing is a SEMANTICS.md
@@ -4625,7 +4856,7 @@ export function lowerProcessMethodCall(L, call, access) {
4625
4856
  const cb = dcSubscriberArg(L, call.arguments[1]);
4626
4857
  return { kind: "libCall", fn: "process.onUnhandledRejection", args: [cb], type: VOID, loc };
4627
4858
  }
4628
- // 'warning': the listener crosses as a DOM function; emitWarning
4859
+ // 'warning': the listener crosses as a dyn function; emitWarning
4629
4860
  // and the runtime deprecation sites dispatch synchronously
4630
4861
  // (SEMANTICS.md). off/removeListener remove by closure identity.
4631
4862
  if (event === "warning" && (member === "on" || isOff)) {
@@ -4700,7 +4931,7 @@ export function lowerProcessMethodCall(L, call, access) {
4700
4931
  }
4701
4932
  return { kind: "libCall", fn: "process.onExit", args: [cb, onceArg], type: VOID, loc };
4702
4933
  }
4703
- // process.emitWarning(...): the argument vector crosses as ONE DOM
4934
+ // process.emitWarning(...): the argument vector crosses as ONE dyn
4704
4935
  // array and the runtime applies Node's full grammar (string or Error
4705
4936
  // warning; type/ctor/options second; code/ctor third — wrong kinds
4706
4937
  // throw ERR_INVALID_ARG_TYPE). A single SPREAD of a checked-dynamic
@@ -5365,9 +5596,70 @@ export function lowerPromiseStaticCall(L, call, access) {
5365
5596
  };
5366
5597
  return { kind: "intrinsic", name: "promise.all", args: [entriesArr], type: resultT, loc };
5367
5598
  }
5599
+ // MIXED entries where some entry is already an ISLAND value (the
5600
+ // withPlugins shape: Promise.all([loadBuiltinPlugins(),
5601
+ // loadPlugins(plugins)]) with an 'any'-typed loader): the
5602
+ // ENGINE's own Promise.all runs — island entries pass through,
5603
+ // STATIC promises cross as real engine thenables (the reverse
5604
+ // bridge, payload-domain gated), plain values marshal per the
5605
+ // boundary — and the combined result stays an island value
5606
+ // (awaiting it rides the island→static promise bridge; element
5607
+ // reads are the routed keyed ops). All-static tuples keep the
5608
+ // typed fence hint below. --dynamic only by construction: jsval
5609
+ // entries exist only there.
5610
+ if (elems.some((e) => e.type.kind === "jsval")) {
5611
+ const diagsBefore = L.diags.length;
5612
+ try {
5613
+ const marshaled = argNode.elements.map((el, i) => L.jsvalIn(elems[i], el));
5614
+ return {
5615
+ kind: "jsOp",
5616
+ op: "callMethod",
5617
+ name: "all",
5618
+ args: [
5619
+ { kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc },
5620
+ { kind: "jsOp", op: "arrLit", args: marshaled, type: JSVAL, loc },
5621
+ ],
5622
+ type: JSVAL,
5623
+ loc,
5624
+ };
5625
+ }
5626
+ catch (err) {
5627
+ // An entry outside every crossing domain: drop the boundary
5628
+ // diagnostics and let the shape fence below name the fix.
5629
+ if (!(err instanceof PoisonError))
5630
+ throw err;
5631
+ L.diags.splice(diagsBefore);
5632
+ }
5633
+ }
5368
5634
  L.noLowering("Promise.all over this argument shape", argNode, "the entries must share ONE promise type — Promise.all([p, q]) lowers when p and q are the same Promise<T>");
5369
5635
  }
5370
5636
  const entries = L.lowerExpr(argNode);
5637
+ // A NON-literal island argument (`Promise.all(plugins.map((p) =>
5638
+ // loadPlugin(p)))` — the loadPlugins shape, where the checker
5639
+ // spells `any[]`): the ENGINE's own Promise.all runs over the
5640
+ // marshaled array (an 'any' value passes through; an `any[]` value
5641
+ // lifts per element by reference), the result staying an island
5642
+ // value the static side awaits through the island→static bridge.
5643
+ if (entries.type.kind === "jsval" ||
5644
+ (entries.type.kind === "array" && entries.type.elem.kind === "jsval")) {
5645
+ const diagsBefore = L.diags.length;
5646
+ try {
5647
+ const arg = L.jsvalIn(entries, argNode);
5648
+ return {
5649
+ kind: "jsOp",
5650
+ op: "callMethod",
5651
+ name: "all",
5652
+ args: [{ kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc }, arg],
5653
+ type: JSVAL,
5654
+ loc,
5655
+ };
5656
+ }
5657
+ catch (err) {
5658
+ if (!(err instanceof PoisonError))
5659
+ throw err;
5660
+ L.diags.splice(diagsBefore);
5661
+ }
5662
+ }
5371
5663
  if (entries.type.kind !== "array" || entries.type.elem.kind !== "promise") {
5372
5664
  // The heterogeneous-literal case: the checker's tuple overload
5373
5665
  // types the literal as a TUPLE of promises (a tuple-flagged record