@scriptc/compiler 0.1.3 → 0.1.4

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 (147) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +200 -51
  2. package/dist/backend/c/async.d.ts +25 -0
  3. package/dist/backend/c/async.js +167 -0
  4. package/dist/backend/c/async.js.map +1 -1
  5. package/dist/backend/c/c-emitter.d.ts +10 -0
  6. package/dist/backend/c/c-emitter.js +14 -2
  7. package/dist/backend/c/c-emitter.js.map +1 -1
  8. package/dist/backend/c/exprs.js +293 -51
  9. package/dist/backend/c/exprs.js.map +1 -1
  10. package/dist/backend/c/types.js +2 -0
  11. package/dist/backend/c/types.js.map +1 -1
  12. package/dist/backend/link-plan.d.ts +2 -1
  13. package/dist/backend/link-plan.js +2 -1
  14. package/dist/backend/link-plan.js.map +1 -1
  15. package/dist/backend/llvm/emitter.js +20 -6
  16. package/dist/backend/llvm/emitter.js.map +1 -1
  17. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  18. package/dist/backend/llvm/expr-bytes.js +8 -8
  19. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  20. package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
  21. package/dist/backend/llvm/expr-callbacks.js +125 -0
  22. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  23. package/dist/backend/llvm/expr-context.d.ts +14 -2
  24. package/dist/backend/llvm/expr-dispatch.js +1 -0
  25. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  26. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  27. package/dist/backend/llvm/expr-primitives.js +30 -9
  28. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  29. package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
  30. package/dist/backend/llvm/expr-primitives.test.js +38 -0
  31. package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
  32. package/dist/backend/llvm/expr-stream-callbacks.d.ts +3 -0
  33. package/dist/backend/llvm/expr-stream-callbacks.js +69 -0
  34. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  35. package/dist/backend/llvm/lib-filesystem.js +68 -10
  36. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  37. package/dist/backend/llvm/lib-network.js +18 -2
  38. package/dist/backend/llvm/lib-network.js.map +1 -1
  39. package/dist/backend/llvm/lib-process.js +156 -6
  40. package/dist/backend/llvm/lib-process.js.map +1 -1
  41. package/dist/backend/llvm/lib-shared.js +36 -0
  42. package/dist/backend/llvm/lib-shared.js.map +1 -1
  43. package/dist/backend/llvm/lib-stream.js +23 -0
  44. package/dist/backend/llvm/lib-stream.js.map +1 -1
  45. package/dist/backend/native-toolchain.d.ts +3 -0
  46. package/dist/backend/native-toolchain.js +3 -1
  47. package/dist/backend/native-toolchain.js.map +1 -1
  48. package/dist/backend/runtime-pack.test.js +28 -10
  49. package/dist/backend/runtime-pack.test.js.map +1 -1
  50. package/dist/backend/targets.d.ts +4 -0
  51. package/dist/backend/targets.js +13 -0
  52. package/dist/backend/targets.js.map +1 -1
  53. package/dist/backend/targets.test.js +8 -1
  54. package/dist/backend/targets.test.js.map +1 -1
  55. package/dist/coverage/surface-manifest.js +8 -0
  56. package/dist/coverage/surface-manifest.js.map +1 -1
  57. package/dist/diagnostics/diagnostic.js +1 -1
  58. package/dist/diagnostics/diagnostic.js.map +1 -1
  59. package/dist/executable/executable-cache.d.ts +2 -0
  60. package/dist/executable/executable-cache.js +3 -0
  61. package/dist/executable/executable-cache.js.map +1 -1
  62. package/dist/frontend/fork-target.d.ts +17 -0
  63. package/dist/frontend/fork-target.js +256 -0
  64. package/dist/frontend/fork-target.js.map +1 -0
  65. package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
  66. package/dist/frontend/lowering/abstract-equality.js +250 -0
  67. package/dist/frontend/lowering/abstract-equality.js.map +1 -0
  68. package/dist/frontend/lowering/lower-assert.js +71 -2
  69. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  70. package/dist/frontend/lowering/lower-builtins.d.ts +50 -23
  71. package/dist/frontend/lowering/lower-builtins.js +939 -106
  72. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  73. package/dist/frontend/lowering/lower-calls.d.ts +29 -21
  74. package/dist/frontend/lowering/lower-calls.js +573 -121
  75. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  76. package/dist/frontend/lowering/lower-classes.js +39 -8
  77. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  78. package/dist/frontend/lowering/lower-containers.js +150 -0
  79. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  80. package/dist/frontend/lowering/lower-event-emitter.js +212 -21
  81. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  82. package/dist/frontend/lowering/lower-exprs.js +135 -83
  83. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  84. package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
  85. package/dist/frontend/lowering/lower-inspect.js +1 -1
  86. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  87. package/dist/frontend/lowering/lower-island.d.ts +6 -3
  88. package/dist/frontend/lowering/lower-island.js +165 -6
  89. package/dist/frontend/lowering/lower-island.js.map +1 -1
  90. package/dist/frontend/lowering/lower-modules.d.ts +6 -0
  91. package/dist/frontend/lowering/lower-modules.js +184 -38
  92. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  93. package/dist/frontend/lowering/lower-namespaces.js +7 -0
  94. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  95. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  96. package/dist/frontend/lowering/lower-server.js +130 -27
  97. package/dist/frontend/lowering/lower-server.js.map +1 -1
  98. package/dist/frontend/lowering/lower-stmts.js +118 -15
  99. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  100. package/dist/frontend/lowering/lower-stream.d.ts +3 -0
  101. package/dist/frontend/lowering/lower-stream.js +7 -0
  102. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  103. package/dist/frontend/lowering/lowerer.d.ts +86 -9
  104. package/dist/frontend/lowering/lowerer.js +412 -72
  105. package/dist/frontend/lowering/lowerer.js.map +1 -1
  106. package/dist/frontend/lowering/surfaces.d.ts +26 -0
  107. package/dist/frontend/lowering/surfaces.js +140 -77
  108. package/dist/frontend/lowering/surfaces.js.map +1 -1
  109. package/dist/frontend/npm-static-declarations.d.ts +4 -0
  110. package/dist/frontend/npm-static-declarations.js +56 -0
  111. package/dist/frontend/npm-static-declarations.js.map +1 -1
  112. package/dist/frontend/npm-static-declarations.test.js +23 -2
  113. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  114. package/dist/frontend/npm-static.js +6 -5
  115. package/dist/frontend/npm-static.js.map +1 -1
  116. package/dist/frontend/npm.d.ts +15 -3
  117. package/dist/frontend/npm.js +80 -8
  118. package/dist/frontend/npm.js.map +1 -1
  119. package/dist/frontend/npm.test.js +76 -9
  120. package/dist/frontend/npm.test.js.map +1 -1
  121. package/dist/frontend/program.js +92 -10
  122. package/dist/frontend/program.js.map +1 -1
  123. package/dist/frontend/resolve.d.ts +6 -0
  124. package/dist/frontend/resolve.js +7 -4
  125. package/dist/frontend/resolve.js.map +1 -1
  126. package/dist/frontend/type-mapper.d.ts +5 -0
  127. package/dist/frontend/type-mapper.js +64 -24
  128. package/dist/frontend/type-mapper.js.map +1 -1
  129. package/dist/index.d.ts +5 -0
  130. package/dist/index.js +24 -3
  131. package/dist/index.js.map +1 -1
  132. package/dist/ir/ir.d.ts +93 -47
  133. package/dist/ir/ir.js +63 -4
  134. package/dist/ir/ir.js.map +1 -1
  135. package/dist/ir/ir.test.js +14 -1
  136. package/dist/ir/ir.test.js.map +1 -1
  137. package/dist/ir/serialize.d.ts +1 -1
  138. package/dist/ir/serialize.js +1 -1
  139. package/dist/ir/serialize.js.map +1 -1
  140. package/dist/ir/validate.js +165 -13
  141. package/dist/ir/validate.js.map +1 -1
  142. package/dist/library/int-infer.test.js +4 -4
  143. package/dist/library/int-infer.test.js.map +1 -1
  144. package/dist/library/library-cache.test.js +5 -5
  145. package/dist/library/library-cache.test.js.map +1 -1
  146. package/package.json +17 -17
  147. package/surface-manifest.json +132 -38
@@ -10,19 +10,76 @@ import { isJsSourceFileName } from "../tsc-codes.js";
10
10
  import { isRelativeSpecifier } from "../workspace-registry.js";
11
11
  import { canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, isCjsJsFile, isJsSourceFile, isRequireStatement, locOf, makeCycleAdmission, orderedImportsOf, resolveImport, resolveNpmImport } from "../program.js";
12
12
  import { invalidJsonModuleDiag, npmEmbedFailedDiag, requiresDynamicImportDiag } from "../../diagnostics/diagnostic.js";
13
- import { BOOL, DYN, JSVAL, RUNTIME_ERROR_CLASSES, STRING, VOID, arrayOf, canConvertToDyn, isUnitType } from "../../ir/ir.js";
14
- import { ENTRY_NAME, PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, newFnCtx, uncheckedOverloadHandleCall } from "./lowerer.js";
15
- import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireSpecOf, isPromisifyCall, textCodecBindingDecl } from "./lower-builtins.js";
16
- import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishGenericBindingUnitOf } from "./lower-calls.js";
13
+ import { BOOL, DYN, F64, JSVAL, RUNTIME_ERROR_CLASSES, STRING, VOID, arrayOf, canConvertToDyn, isUnitType } from "../../ir/ir.js";
14
+ import { ENTRY_NAME, PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, newFnCtx, staticImportNamespaceType, uncheckedOverloadHandleCall } from "./lowerer.js";
15
+ import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireSpecOf, isPromisifyCall, registerBuiltinCallableAlias, textCodecBindingDecl } from "./lower-builtins.js";
16
+ import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishGenericBindingUnitOf, registerOverloadedCallableAlias } from "./lower-calls.js";
17
17
  import { isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
18
18
  import { streamClassAliasDecl } from "./lower-stream.js";
19
- import { stdlibGlobalAliasDecl } from "./surfaces.js";
19
+ import { stdlibGlobalAliasDecl, stdlibGlobalAliasNameOf } from "./surfaces.js";
20
20
  import { collectNamespaceStmt, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
21
21
  import { collectExpandoMembers } from "./lower-expando.js";
22
22
  import { isUnitOnlyTsType, unitOnlyUnion } from "../type-mapper.js";
23
23
  import { decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow } from "./lower-classes.js";
24
24
  import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
25
25
  import { cjsModuleRef, cjsModuleRegistryPrelude } from "./lower-node-module.js";
26
+ import { forkTargetPaths } from "../fork-target.js";
27
+ /** Program modules selected by statically resolved child_process.fork()
28
+ * calls join the compiled graph without becoming startup dependencies of
29
+ * the parent entry. Their guarded init functions are selected by %main only
30
+ * in a re-executed fork child. `targets` is append-only so ids stay stable
31
+ * across the dynamic-import/fork discovery fixpoint. */
32
+ export function appendForkModules(program, order, targets, onCycle) {
33
+ if (order.length === 0)
34
+ return;
35
+ const byPath = new Map(program.getSourceFiles().map((sf) => [resolvePath(sf.fileName), sf]));
36
+ const state = new Map();
37
+ for (const sf of order)
38
+ state.set(sf, "done");
39
+ const added = [];
40
+ const stack = [];
41
+ const staticEdgesOf = (sf) => orderedImportsOf(program, sf).flatMap(({ stmt, dep }) => dep !== null && dep !== sf
42
+ ? [{ dep, stmt: stmt }]
43
+ : []);
44
+ const cycleAdmissionReason = makeCycleAdmission(program, staticEdgesOf);
45
+ const visit = (sf) => {
46
+ const prior = state.get(sf);
47
+ if (prior === "done")
48
+ return;
49
+ state.set(sf, "visiting");
50
+ stack.push(sf.fileName);
51
+ for (const edge of staticEdgesOf(sf)) {
52
+ const edgeState = state.get(edge.dep);
53
+ if (edgeState === "done")
54
+ continue;
55
+ if (edgeState === "visiting") {
56
+ const reason = cycleAdmissionReason(sf, edge);
57
+ if (reason !== null) {
58
+ const cycleStart = stack.indexOf(edge.dep.fileName);
59
+ onCycle([...stack.slice(cycleStart), edge.dep.fileName].join(" → "), reason);
60
+ }
61
+ continue;
62
+ }
63
+ visit(edge.dep);
64
+ }
65
+ stack.pop();
66
+ state.set(sf, "done");
67
+ added.push(sf);
68
+ };
69
+ const knownTargets = new Set(targets);
70
+ for (const path of forkTargetPaths(program, order)) {
71
+ const target = byPath.get(resolvePath(path));
72
+ if (!target || target.isDeclarationFile || target.fileName.endsWith(".json"))
73
+ continue;
74
+ if (!knownTargets.has(target)) {
75
+ knownTargets.add(target);
76
+ targets.push(target);
77
+ }
78
+ visit(target);
79
+ }
80
+ if (added.length > 0)
81
+ order.splice(order.length - 1, 0, ...added);
82
+ }
26
83
  /** Splits each file into function/class declarations and the top-level
27
84
  * statements that form its init body. Node's evaluation order (depth-first
28
85
  * postorder, entry last), computed by preflight. Single-file programs
@@ -382,9 +439,9 @@ export function collectNpmImports(lowerer, parts) {
382
439
  }
383
440
  }
384
441
  }
442
+ for (const fp of parts)
443
+ collectDynamicImports(lowerer, builder, fp.sf);
385
444
  if (builder) {
386
- for (const fp of parts)
387
- collectDynamicImports(lowerer, builder, fp.sf);
388
445
  for (const fp of parts)
389
446
  collectCreateRequires(lowerer, builder, fp.sf);
390
447
  const graph = builder.finish();
@@ -397,11 +454,13 @@ export function collectNpmImports(lowerer, parts) {
397
454
  lowerer.npmLazyTraps = graph.lazyTraps;
398
455
  }
399
456
  }
400
- /** The dynamic-import half of the npm chokepoint (--dynamic only): every
457
+ /** Literal dynamic-import collection: every
401
458
  * `import("literal")` in the file — whatever body it sits in — resolves
402
459
  * and embeds AT COLLECTION time, so the per-site lowering later just
403
460
  * looks its key up (the emitted tables are assembled once, here; a
404
461
  * site lowered in any pass finds its module embedded). Resolution
462
+ * In static builds this records compiled program modules and supported
463
+ * builtins without constructing an npm graph. Dynamic package-resolution
405
464
  * failures and unshimmed builtins are diagnostics HERE, at the import
406
465
  * expression, exactly like static npm imports at their statements; the
407
466
  * lowering poisons those sites without re-reporting. Non-literal
@@ -409,7 +468,7 @@ export function collectNpmImports(lowerer, parts) {
409
468
  * graph is a build-time artifact; there is nothing to embed for a
410
469
  * runtime-computed name). */
411
470
  function collectDynamicImports(lowerer, builder, sf) {
412
- const visit = (node) => {
471
+ ts.walkPreorder(sf, (node) => {
413
472
  if (ts.isCallExpression(node) &&
414
473
  node.expression.kind === ts.SyntaxKind.ImportKeyword &&
415
474
  node.arguments.length >= 1 &&
@@ -417,8 +476,7 @@ function collectDynamicImports(lowerer, builder, sf) {
417
476
  ts.isStringLiteralLike(node.arguments[0])) {
418
477
  const spec = node.arguments[0].text;
419
478
  if (lowerer.externalTypes.has(spec)) {
420
- ts.forEachChild(node, visit);
421
- return;
479
+ return undefined;
422
480
  }
423
481
  const mapKey = `${sf.fileName}\u0000${spec}`;
424
482
  if (!lowerer.dynImports.has(mapKey)) {
@@ -429,9 +487,15 @@ function collectDynamicImports(lowerer, builder, sf) {
429
487
  // .d.mts typing shipped JS is the EMBED case, not this one.
430
488
  const modSym = lowerer.checker.getSymbolAtLocation(node.arguments[0]);
431
489
  const ownModule = modSym !== undefined && lowerer.checker.declarationsOf(modSym).some((d) => ts.isSourceFile(d) && !d.isDeclarationFile);
490
+ const builtin = canonicalBuiltinModule(spec);
432
491
  const res = ownModule
433
492
  ? { kind: "program-module" }
434
- : builder.addDynamicImport(sf.fileName, spec);
493
+ : !lowerer.dynamic && builtin !== null
494
+ ? { kind: "static-builtin", module: builtin }
495
+ : builder?.addDynamicImport(sf.fileName, spec);
496
+ if (res === undefined) {
497
+ return undefined;
498
+ }
435
499
  lowerer.dynImports.set(mapKey, res);
436
500
  if (res.kind === "unsupported-builtin") {
437
501
  lowerer.pushDiag(npmEmbedFailedDiag(`'${spec}' is a Node builtin the island does not provide a shim for`, locOf(node)));
@@ -441,9 +505,8 @@ function collectDynamicImports(lowerer, builder, sf) {
441
505
  }
442
506
  }
443
507
  }
444
- ts.forEachChild(node, visit);
445
- };
446
- visit(sf);
508
+ return undefined;
509
+ });
447
510
  }
448
511
  /** The createRequire half of the npm chokepoint (--dynamic only): every
449
512
  * `require("bare-literal")` through a createRequire binding — whatever
@@ -965,11 +1028,20 @@ export function collectGlobals(lowerer, sf, topStmts) {
965
1028
  // included); unmappable pieces take the JS checked-dynamic
966
1029
  // fallback like every JS binding.
967
1030
  const fnValued = ts.isFunctionExpression(rhs) || ts.isArrowFunction(rhs);
968
- if (cjsScalarLiteral(rhs) || fnValued) {
1031
+ // A factory-returned CommonJS root (`module.exports = make()`)
1032
+ // is a single value just like the scalar/function forms above
1033
+ // when its result has a static or checked-dynamic representation. Register one
1034
+ // snapshot slot keyed by the export-assignment declaration; the
1035
+ // statement lowering evaluates the call exactly once at its
1036
+ // source position and assigns that slot. Unmappable calls retain
1037
+ // the existing statement-level fence.
1038
+ const factoryValued = ts.isCallExpression(rhs);
1039
+ if (cjsScalarLiteral(rhs) || fnValued || factoryValued) {
969
1040
  const diagsBefore = lowerer.diags.length;
970
1041
  try {
971
1042
  const strict = lowerer.typeOf(rhs);
972
- const t = lowerer.mapTypeOf(strict) ?? (fnValued ? dynFallbackType(lowerer, rhs, strict) : null);
1043
+ const t = lowerer.mapTypeOf(strict) ??
1044
+ (fnValued || factoryValued ? dynFallbackType(lowerer, rhs, strict) : null);
973
1045
  if (t && t.kind !== "void") {
974
1046
  const g = { id: `%g.${tag}exports`, name: "exports", type: t, mutable: false };
975
1047
  lowerer.globalsByDeclNode.set(cjs.expr, g);
@@ -1211,6 +1283,13 @@ export function collectGlobals(lowerer, sf, topStmts) {
1211
1283
  if (aliased)
1212
1284
  continue;
1213
1285
  }
1286
+ // An immutable alias of an overloaded declared function is a
1287
+ // compile-time callable projection: calls retain per-site overload
1288
+ // resolution and value reads reuse the source's interned closure.
1289
+ if (isConst && registerOverloadedCallableAlias(lowerer, decl))
1290
+ continue;
1291
+ if (isConst && registerBuiltinCallableAlias(lowerer, decl.name, decl.initializer))
1292
+ continue;
1214
1293
  // `const f = (x) => ...` at file scope of an npm-static JS file
1215
1294
  // whose params are implicit-any: the implicit-monomorphization
1216
1295
  // twin of the generic binding above — no global exists; calls and
@@ -1264,7 +1343,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
1264
1343
  // lowering poisons too, like every collectGlobals failure).
1265
1344
  if (ts.isIdentifier(decl.name) && decl.initializer && isPromisifyCall(lowerer, decl.initializer)) {
1266
1345
  try {
1267
- lowerer.promisifiedExecFileDecl(decl.name, decl.initializer);
1346
+ lowerer.registerPromisifiedBuiltinDecl(decl.name, decl.initializer);
1268
1347
  }
1269
1348
  catch (e) {
1270
1349
  if (!(e instanceof PoisonError))
@@ -1287,6 +1366,12 @@ export function collectGlobals(lowerer, sf, topStmts) {
1287
1366
  // scope — a namespace import in const clothing, same story.
1288
1367
  if (isConst && createRequireNamespaceDecl(lowerer, decl.name, decl.initializer))
1289
1368
  continue;
1369
+ // `const local = require("./local.cjs")` through createRequire:
1370
+ // the binding is static module alias plumbing. Its statement emits
1371
+ // the dependency init at this exact source position; no value slot
1372
+ // represents the namespace object itself.
1373
+ if (isConst && createRequireProgramModuleDecl(lowerer, decl.name, decl.initializer))
1374
+ continue;
1290
1375
  // `const { createSign } = crypto` over a builtin NAMESPACE binding
1291
1376
  // at file scope: alias plumbing like the destructured-require form
1292
1377
  // — no storage (the statement lowering skips by the same test).
@@ -1308,7 +1393,15 @@ export function collectGlobals(lowerer, sf, topStmts) {
1308
1393
  // global snapshot — alias plumbing, no global storage (see
1309
1394
  // stdlibGlobalAliasDecl; the statement lowering skips it by the
1310
1395
  // same test).
1311
- if (isConst && stdlibGlobalAliasDecl(lowerer, decl.name, decl.initializer))
1396
+ const stableStdlibAlias = isConst ||
1397
+ ((list.flags & ts.NodeFlags.Let) !== 0 &&
1398
+ ts.isIdentifier(decl.name) &&
1399
+ stdlibGlobalAliasNameOf(lowerer, decl.initializer) !== null &&
1400
+ (() => {
1401
+ const symbol = lowerer.checker.getSymbolAtLocation(decl.name);
1402
+ return symbol !== undefined && bindingNeverReassigned(lowerer, symbol, decl);
1403
+ })());
1404
+ if (stableStdlibAlias && stdlibGlobalAliasDecl(lowerer, decl.name, decl.initializer))
1312
1405
  continue;
1313
1406
  // Stored default TextEncoder/TextDecoder instances are the same
1314
1407
  // compile-time alias plumbing as their statement lowering: calls
@@ -1437,11 +1530,12 @@ export function collectGlobals(lowerer, sf, topStmts) {
1437
1530
  // production — whatever the checker's namespace type mapped to
1438
1531
  // (lowerVarDecl's rule at module scope; the init body assigns
1439
1532
  // it).
1440
- const handleT = lowerer.dynamic && ts.isIdentifier(decl.name) && nameNode === decl.name
1441
- ? (importCallHandleType(decl.initializer) ??
1442
- // An unchecked-overload call result stores the handle,
1443
- // exactly the local rule (uncheckedOverloadHandleCall).
1444
- (uncheckedOverloadHandleCall(lowerer, decl.initializer) ? JSVAL : null))
1533
+ const handleT = ts.isIdentifier(decl.name) && nameNode === decl.name
1534
+ ? (lowerer.dynamic ? importCallHandleType(decl.initializer) : staticImportNamespaceType(lowerer, decl.initializer)) ??
1535
+ (lowerer.dynamic ?
1536
+ // An unchecked-overload call result stores the handle,
1537
+ // exactly the local rule (uncheckedOverloadHandleCall).
1538
+ (uncheckedOverloadHandleCall(lowerer, decl.initializer) ? JSVAL : null) : null)
1445
1539
  : null;
1446
1540
  let type = handleT ?? lowerer.irTypeOf(nameNode);
1447
1541
  // An evolving-`any` array's DERIVED file-scope binding under
@@ -2007,24 +2101,76 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
2007
2101
  * re-imports, re-requires) into a cache hit. */
2008
2102
  export function buildMain(lowerer) {
2009
2103
  const loc = { file: lowerer.entry.fileName, start: 0, end: 0 };
2010
- const entryInit = lowerer.initNameOf.get(lowerer.entry);
2011
- const isAsync = lowerer.asyncInitFiles.has(lowerer.entry);
2012
- const initCall = entryInit !== undefined
2013
- ? {
2104
+ const body = [...cjsModuleRegistryPrelude(lowerer, loc)];
2105
+ const roots = [lowerer.entry, ...lowerer.forkTargets];
2106
+ const isAsync = roots.some((root) => lowerer.asyncInitFiles.has(root));
2107
+ const callRoot = (root) => {
2108
+ const init = lowerer.initNameOf.get(root);
2109
+ if (init === undefined)
2110
+ return [];
2111
+ const rootAsync = lowerer.asyncInitFiles.has(root);
2112
+ const call = {
2014
2113
  kind: "call",
2015
- callee: entryInit,
2114
+ callee: init,
2016
2115
  args: [],
2017
- type: isAsync ? { kind: "promise", inner: VOID } : VOID,
2116
+ type: rootAsync ? { kind: "promise", inner: VOID } : VOID,
2117
+ loc,
2118
+ };
2119
+ return [{
2120
+ kind: "exprStmt",
2121
+ expr: rootAsync ? { kind: "awaitExpr", value: call, type: VOID, loc } : call,
2122
+ loc,
2123
+ }];
2124
+ };
2125
+ const locals = [];
2126
+ if (lowerer.forkTargets.length === 0) {
2127
+ body.push(...callRoot(lowerer.entry));
2128
+ }
2129
+ else {
2130
+ const targetId = "%forkTarget.0";
2131
+ locals.push({ id: targetId, name: "%forkTarget", type: F64, mutable: false });
2132
+ body.push({
2133
+ kind: "varDecl",
2134
+ localId: targetId,
2135
+ init: {
2136
+ kind: "libCall",
2137
+ fn: "process.forkTarget",
2138
+ args: [{ kind: "numLit", value: lowerer.forkTargets.length, type: F64, loc }],
2139
+ type: F64,
2140
+ loc,
2141
+ },
2018
2142
  loc,
2143
+ });
2144
+ const selector = () => ({ kind: "varRef", localId: targetId, type: F64, loc });
2145
+ let workerBranch = null;
2146
+ for (let id = lowerer.forkTargets.length - 1; id >= 0; id--) {
2147
+ workerBranch = [{
2148
+ kind: "if",
2149
+ cond: {
2150
+ kind: "bin",
2151
+ op: "===",
2152
+ left: selector(),
2153
+ right: { kind: "numLit", value: id, type: F64, loc },
2154
+ type: BOOL,
2155
+ loc,
2156
+ },
2157
+ then: callRoot(lowerer.forkTargets[id]),
2158
+ else_: workerBranch,
2159
+ loc,
2160
+ }];
2019
2161
  }
2020
- : null;
2021
- const body = [...cjsModuleRegistryPrelude(lowerer, loc)];
2022
- if (initCall !== null) {
2023
2162
  body.push({
2024
- kind: "exprStmt",
2025
- expr: isAsync
2026
- ? { kind: "awaitExpr", value: initCall, type: VOID, loc }
2027
- : initCall,
2163
+ kind: "if",
2164
+ cond: {
2165
+ kind: "bin",
2166
+ op: "<",
2167
+ left: selector(),
2168
+ right: { kind: "numLit", value: 0, type: F64, loc },
2169
+ type: BOOL,
2170
+ loc,
2171
+ },
2172
+ then: callRoot(lowerer.entry),
2173
+ else_: workerBranch,
2028
2174
  loc,
2029
2175
  });
2030
2176
  }
@@ -2054,7 +2200,7 @@ export function buildMain(lowerer) {
2054
2200
  name: ENTRY_NAME,
2055
2201
  params: [],
2056
2202
  returnType: VOID,
2057
- locals: [],
2203
+ locals,
2058
2204
  body,
2059
2205
  ...(isAsync ? { async: true } : {}),
2060
2206
  loc,