@scriptc/compiler 0.0.10 → 0.0.11

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 (78) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +54 -9
  2. package/dist/backend/emission/emit-exprs.js +34 -2
  3. package/dist/backend/emission/emit-exprs.js.map +1 -1
  4. package/dist/backend/emission/emitter.js +25 -1
  5. package/dist/backend/emission/emitter.js.map +1 -1
  6. package/dist/backend/llvm/emitter.js +59 -4
  7. package/dist/backend/llvm/emitter.js.map +1 -1
  8. package/dist/coverage/surface-manifest.js +16 -2
  9. package/dist/coverage/surface-manifest.js.map +1 -1
  10. package/dist/diagnostics/diagnostic.d.ts +20 -7
  11. package/dist/diagnostics/diagnostic.js +44 -11
  12. package/dist/diagnostics/diagnostic.js.map +1 -1
  13. package/dist/frontend/lowering/lower-builtins.d.ts +56 -0
  14. package/dist/frontend/lowering/lower-builtins.js +235 -4
  15. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  16. package/dist/frontend/lowering/lower-calls.js +38 -4
  17. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  18. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  19. package/dist/frontend/lowering/lower-classes.js +51 -1
  20. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  21. package/dist/frontend/lowering/lower-containers.d.ts +4 -0
  22. package/dist/frontend/lowering/lower-containers.js +69 -7
  23. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  24. package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
  25. package/dist/frontend/lowering/lower-emitter.js +436 -29
  26. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  27. package/dist/frontend/lowering/lower-exprs.d.ts +80 -5
  28. package/dist/frontend/lowering/lower-exprs.js +472 -13
  29. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  30. package/dist/frontend/lowering/lower-modules.d.ts +8 -5
  31. package/dist/frontend/lowering/lower-modules.js +141 -47
  32. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  33. package/dist/frontend/lowering/lower-namespaces.d.ts +14 -0
  34. package/dist/frontend/lowering/lower-namespaces.js +122 -15
  35. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  36. package/dist/frontend/lowering/lower-stmts.js +80 -6
  37. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  38. package/dist/frontend/lowering/lower-stream.js +113 -6
  39. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  40. package/dist/frontend/lowering/lowerer.d.ts +17 -0
  41. package/dist/frontend/lowering/lowerer.js +105 -17
  42. package/dist/frontend/lowering/lowerer.js.map +1 -1
  43. package/dist/frontend/lowering/surfaces.d.ts +44 -0
  44. package/dist/frontend/lowering/surfaces.js +234 -3
  45. package/dist/frontend/lowering/surfaces.js.map +1 -1
  46. package/dist/frontend/npm.d.ts +12 -0
  47. package/dist/frontend/npm.js +30 -0
  48. package/dist/frontend/npm.js.map +1 -1
  49. package/dist/frontend/program.d.ts +25 -0
  50. package/dist/frontend/program.js +144 -135
  51. package/dist/frontend/program.js.map +1 -1
  52. package/dist/frontend/shared.d.ts +1 -1
  53. package/dist/frontend/shared.js +1 -1
  54. package/dist/frontend/shared.js.map +1 -1
  55. package/dist/index.d.ts +2 -1
  56. package/dist/index.js +137 -4
  57. package/dist/index.js.map +1 -1
  58. package/dist/ir/nodes.d.ts +64 -8
  59. package/dist/ir/nodes.js +21 -3
  60. package/dist/ir/nodes.js.map +1 -1
  61. package/dist/ir/validate.js +11 -2
  62. package/dist/ir/validate.js.map +1 -1
  63. package/dist/library/fence-eval.js +12 -2
  64. package/dist/library/fence-eval.js.map +1 -1
  65. package/dist/library/int-infer.d.ts +119 -0
  66. package/dist/library/int-infer.js +1301 -0
  67. package/dist/library/int-infer.js.map +1 -0
  68. package/dist/library/int-infer.test.d.ts +1 -0
  69. package/dist/library/int-infer.test.js +279 -0
  70. package/dist/library/int-infer.test.js.map +1 -0
  71. package/dist/library/profile.d.ts +32 -5
  72. package/dist/library/profile.js +77 -13
  73. package/dist/library/profile.js.map +1 -1
  74. package/dist/library/sidecar.d.ts +23 -0
  75. package/dist/library/sidecar.js +150 -16
  76. package/dist/library/sidecar.js.map +1 -1
  77. package/package.json +2 -2
  78. package/surface-manifest.json +208 -10
@@ -19,14 +19,15 @@ import { arrayOf, BOOL, canAdaptDynFuncTo, canConvertToDyn, canCrossIslandBounda
19
19
  import { provenanceActive } from "../provenance-registry.js";
20
20
  import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
21
21
  import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../types.js";
22
- import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
22
+ import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
23
23
  import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules } from "./lower-modules.js";
24
24
  import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorMessageArg, lowerNew, accessorCall } from "./lower-classes.js";
25
25
  import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mixins.js";
26
26
  import { bindingNeverReassigned, bodyReadsArguments, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction } from "./lower-calls.js";
27
27
  import { lowerArrayMethodCall, lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn, lowerRegexMethodCall, lowerStringMethodCall } from "./lower-containers.js";
28
28
  import { lowerStreamModuleCall } from "./lower-stream.js";
29
- import { builtinImportOf, lowerBuiltinModuleCall, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, promisifiedExecFileDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerFsConstantsProperty, lowerHttp2ConstantsProperty, http2ConstantBindingOf, http2ConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
29
+ import { lowerEmitOverrideSpec } from "./lower-emitter.js";
30
+ import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, promisifiedExecFileDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerFsConstantsProperty, lowerHttp2ConstantsProperty, http2ConstantBindingOf, http2ConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
30
31
  import { isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerDynamicImportCall, lowerFetchCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
31
32
  import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty } from "./lower-server.js";
32
33
  import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
@@ -148,8 +149,24 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
148
149
  const dynamic = options.dynamic ?? false;
149
150
  const targetPlatform = options.targetPlatform ?? process.platform;
150
151
  const startupCrash = options.startupCrash ?? null;
152
+ // --dynamic: modules reachable only through dynamic import() of the
153
+ // program's own files join the compiled graph here, ONCE, before any
154
+ // pass constructs (nothing calls their %init at startup — the import()
155
+ // site's namespace builder does, on the engine microtask, Node's
156
+ // evaluation point for them). Inadmissible static cycles inside the
157
+ // added subgraph are minted here and handed to the EMIT pass: the
158
+ // discovery pass's diagnostics are discarded by design, and after this
159
+ // extension of the shared array no later pass re-walks the subgraph.
160
+ const dynamicCycleDiags = [];
161
+ if (dynamic) {
162
+ appendDynamicImportModules(program, moduleOrder, (cycle, reason) => {
163
+ dynamicCycleDiags.push(unsupportedDiag("SC1016", { file: entry.fileName, start: 0, end: 0 }, `circular imports (${cycle}; ${reason})`));
164
+ });
165
+ }
151
166
  const reachable = new Lowerer(program, entry, moduleOrder, dynamic, { targetPlatform }).discover(options.libRoots);
152
167
  const emit = new Lowerer(program, entry, moduleOrder, dynamic, { reachable, targetPlatform, startupCrash });
168
+ for (const d of dynamicCycleDiags)
169
+ emit.pushDiag(d);
153
170
  const result = emit.run();
154
171
  if (options.coverage !== true)
155
172
  return result;
@@ -583,6 +600,13 @@ export class Lowerer {
583
600
  /** Synthetic array-HOF loop functions (map/filter/forEach desugar),
584
601
  * interned per method + element/callback-result type: key → fn name. */
585
602
  arrHofHelpers = new Map();
603
+ /** Emit-override specializations (`%C.emit:<event>` — lower-emitter.ts's
604
+ * emit-overrides block): interned names, the drive-loop queue, and the
605
+ * currently-lowering specialization's context (the super-forward
606
+ * interception reads it). */
607
+ emitSpecDone = new Set();
608
+ emitSpecQueue = [];
609
+ emitSpecCtx = null;
586
610
  /** Width-coercion helpers (%rec.width.N / %arr.width.N), interned per
587
611
  * (from, to) shape pair — see widthCoerce. */
588
612
  widthHelpers = new Map();
@@ -704,6 +728,12 @@ export class Lowerer {
704
728
  * `fileName\u0000specifier` (collectDynamicImports fills it during npm
705
729
  * collection; lowerDynamicImportCall reads it per site). */
706
730
  dynImports = new Map();
731
+ /** createRequire-require resolutions of BARE npm specifiers, keyed
732
+ * `fileName\u0000specifier` (collectCreateRequires fills it during npm
733
+ * collection under --dynamic — the require-condition entry key plus its
734
+ * embedded format; lowerCreateRequireCall reads it per site; "" marks a
735
+ * failed resolution already reported at collection). */
736
+ createRequireImports = new Map();
707
737
  /** Module → the name of its synthesized namespace-BUILDER function
708
738
  * (lowerOwnModuleImport): every `import()` of the same program module
709
739
  * shares one builder. */
@@ -892,16 +922,12 @@ export class Lowerer {
892
922
  // lowering, long after the constructor completes.
893
923
  isProgramFile: (sf) => this.fileTag.has(sf),
894
924
  };
895
- // --dynamic: modules reachable only through dynamic import() of the
896
- // program's own files join the compiled graph (nothing calls their
897
- // %init at startup — the import() site's namespace builder does, on
898
- // the engine microtask, which is Node's evaluation point for them).
899
- // Mutates the SHARED moduleOrder array; idempotent across passes.
900
- if (dynamic) {
901
- appendDynamicImportModules(program, this.moduleOrder, (cycle) => {
902
- this.pushDiag(unsupportedDiag("SC1016", { file: entry.fileName, start: 0, end: 0 }, `circular imports (${cycle})`));
903
- });
904
- }
925
+ // --dynamic: modules reachable only through dynamic import() joined
926
+ // moduleOrder BEFORE any pass constructed — lowerToIr runs
927
+ // appendDynamicImportModules once on the shared array (a per-pass run
928
+ // here minted cycle refusals into the DISCOVERY pass, whose
929
+ // diagnostics are discarded by design, and the extended order left
930
+ // nothing for the emit pass to re-detect).
905
931
  this.moduleOrder.forEach((sf, i) => {
906
932
  this.fileTag.set(sf, sf === entry ? "" : `%m${i}.`);
907
933
  });
@@ -1410,9 +1436,11 @@ export class Lowerer {
1410
1436
  let ec = 0;
1411
1437
  let gc = 0;
1412
1438
  let gi = 0;
1439
+ let es = 0;
1413
1440
  while (ec < this.exprClasses.length ||
1414
1441
  gc < this.genericClassInstances.length ||
1415
- gi < this.instantiationQueue.length) {
1442
+ gi < this.instantiationQueue.length ||
1443
+ es < this.emitSpecQueue.length) {
1416
1444
  while (ec < this.exprClasses.length) {
1417
1445
  functions.push(...this.lowerClassMembers(this.exprClasses[ec++]));
1418
1446
  }
@@ -1433,6 +1461,20 @@ export class Lowerer {
1433
1461
  throw e;
1434
1462
  }
1435
1463
  }
1464
+ // Emit-override specializations queued by the emit sites above (a
1465
+ // body can queue more — the super-forward chain — and generic
1466
+ // instances of its own; the joint fixpoint covers both).
1467
+ while (es < this.emitSpecQueue.length) {
1468
+ try {
1469
+ const fn = lowerEmitOverrideSpec(this, this.emitSpecQueue[es++]);
1470
+ if (fn)
1471
+ functions.push(fn);
1472
+ }
1473
+ catch (e) {
1474
+ if (!(e instanceof PoisonError))
1475
+ throw e;
1476
+ }
1477
+ }
1436
1478
  }
1437
1479
  }
1438
1480
  // Lambdas lifted while lowering any of the above (plus synthetic
@@ -1750,9 +1792,11 @@ export class Lowerer {
1750
1792
  // the joint fixpoint).
1751
1793
  let instLowered = 0;
1752
1794
  let clsInstLowered = 0;
1795
+ let specLowered = 0;
1753
1796
  const drainInstances = () => {
1754
1797
  while (instLowered < this.instantiationQueue.length ||
1755
- clsInstLowered < this.genericClassInstances.length) {
1798
+ clsInstLowered < this.genericClassInstances.length ||
1799
+ specLowered < this.emitSpecQueue.length) {
1756
1800
  while (instLowered < this.instantiationQueue.length) {
1757
1801
  const { info, inst } = this.instantiationQueue[instLowered++];
1758
1802
  // Body-level poisons skip the instance here too (the emit pass
@@ -1769,6 +1813,18 @@ export class Lowerer {
1769
1813
  while (clsInstLowered < this.genericClassInstances.length) {
1770
1814
  this.lowerClassMembers(this.genericClassInstances[clsInstLowered++]);
1771
1815
  }
1816
+ // Emit-override specialization bodies fire edges of their own
1817
+ // (the super-forward chain, closures, generic calls) — lower them
1818
+ // for discovery exactly like generic instances.
1819
+ while (specLowered < this.emitSpecQueue.length) {
1820
+ try {
1821
+ lowerEmitOverrideSpec(this, this.emitSpecQueue[specLowered++]);
1822
+ }
1823
+ catch (e) {
1824
+ if (!(e instanceof PoisonError))
1825
+ throw e;
1826
+ }
1827
+ }
1772
1828
  }
1773
1829
  };
1774
1830
  parts.forEach((fp) => {
@@ -6311,7 +6367,12 @@ export class Lowerer {
6311
6367
  // out-of-block read would split the variable in two) — vars take the
6312
6368
  // standard path and its own fences.
6313
6369
  (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.BlockScoped) !== 0 &&
6314
- islandCandidate(decl.initializer)) {
6370
+ islandCandidate(decl.initializer) &&
6371
+ // createRequire's plumbing decls are COMPILE-TIME erasures (the
6372
+ // require binding and its builtin-namespace bindings) — never
6373
+ // island values; the standard path's skips own them.
6374
+ !createRequireBindingDecl(this, decl.name, decl.initializer) &&
6375
+ !createRequireNamespaceDecl(this, decl.name, decl.initializer)) {
6315
6376
  const mapped = this.mapTypeOf(this.typeOf(decl.name));
6316
6377
  const handleOnly = mapped === null ||
6317
6378
  (mapped.kind !== "jsval" &&
@@ -6702,10 +6763,21 @@ export class Lowerer {
6702
6763
  if (!decl)
6703
6764
  return null;
6704
6765
  // The CommonJS twin: `const fs = require("fs")` binds the same
6705
- // namespace surface as `import * as fs from "node:fs"`.
6766
+ // namespace surface as `import * as fs from "node:fs"` — and the
6767
+ // createRequire spelling (`const fs = require("node:fs")` through a
6768
+ // createRequire binding, the fallback-typed cast idiom stripped)
6769
+ // binds it too.
6706
6770
  if (ts.isVariableDeclaration(decl) && ts.isIdentifier(decl.name) && decl.initializer) {
6707
6771
  const spec = requireSpecOf(decl.initializer);
6708
- return spec !== null ? canonicalBuiltinModule(spec) : null;
6772
+ if (spec !== null)
6773
+ return canonicalBuiltinModule(spec);
6774
+ const init = stripTypeCasts(decl.initializer);
6775
+ if (ts.isCallExpression(init)) {
6776
+ const cr = createRequireSpecOf(this, init);
6777
+ if (cr !== null && cr.spec !== null)
6778
+ return canonicalBuiltinModule(cr.spec);
6779
+ }
6780
+ return null;
6709
6781
  }
6710
6782
  // A DESTRUCTURED sub-namespace binding — `const { promises } =
6711
6783
  // fs` / `= require('fs')`: the member is itself a supported module
@@ -6738,6 +6810,17 @@ export class Lowerer {
6738
6810
  if (spec !== null)
6739
6811
  return canonicalBuiltinModule(spec);
6740
6812
  }
6813
+ // The createRequire spelling of the same inline form:
6814
+ // `require("node:path").join(...)` through a createRequire binding
6815
+ // (the fallback-typed cast idiom strips: `(require("x") as T).m`).
6816
+ {
6817
+ const inner = stripTypeCasts(expr);
6818
+ if (ts.isCallExpression(inner)) {
6819
+ const cr = createRequireSpecOf(this, inner);
6820
+ if (cr !== null && cr.spec !== null)
6821
+ return canonicalBuiltinModule(cr.spec);
6822
+ }
6823
+ }
6741
6824
  if (ts.isIdentifier(expr)) {
6742
6825
  const symbol = this.checker.getSymbolAtLocation(expr);
6743
6826
  const decl = symbol ? this.checker.declarationsOf(symbol)[0] : undefined;
@@ -6884,6 +6967,11 @@ export class Lowerer {
6884
6967
  const c = builtinModuleConstOf(this, bi.module, bi.member);
6885
6968
  if (c !== undefined)
6886
6969
  return builtinConstLit(c, loc);
6970
+ // module.builtinModules through a namespace binding — the baked
6971
+ // Node v24 list, a fresh string[] per read.
6972
+ if (bi.module === "module" && bi.member === "builtinModules") {
6973
+ return builtinModulesArrayLit(loc);
6974
+ }
6887
6975
  if (bi.member === "constants" && bi.module === "fs") {
6888
6976
  // A bare `fs.constants` read (not one of the baked bits above).
6889
6977
  this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, and X_OK are the lowered constants");