@scriptc/compiler 0.1.2 → 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 (206) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +258 -64
  2. package/dist/backend/c/async.d.ts +30 -0
  3. package/dist/backend/c/async.js +224 -0
  4. package/dist/backend/c/async.js.map +1 -1
  5. package/dist/backend/c/c-emitter.d.ts +13 -0
  6. package/dist/backend/c/c-emitter.js +28 -9
  7. package/dist/backend/c/c-emitter.js.map +1 -1
  8. package/dist/backend/c/exprs.d.ts +8 -1
  9. package/dist/backend/c/exprs.js +445 -60
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/shapes.js +15 -13
  12. package/dist/backend/c/shapes.js.map +1 -1
  13. package/dist/backend/c/types.d.ts +4 -0
  14. package/dist/backend/c/types.js +20 -1
  15. package/dist/backend/c/types.js.map +1 -1
  16. package/dist/backend/c/types.test.js +8 -1
  17. package/dist/backend/c/types.test.js.map +1 -1
  18. package/dist/backend/c/walkers.js +32 -11
  19. package/dist/backend/c/walkers.js.map +1 -1
  20. package/dist/backend/json-literal.d.ts +7 -0
  21. package/dist/backend/json-literal.js +17 -0
  22. package/dist/backend/json-literal.js.map +1 -0
  23. package/dist/backend/json-literal.test.d.ts +1 -0
  24. package/dist/backend/json-literal.test.js +17 -0
  25. package/dist/backend/json-literal.test.js.map +1 -0
  26. package/dist/backend/link-plan.d.ts +2 -1
  27. package/dist/backend/link-plan.js +6 -1
  28. package/dist/backend/link-plan.js.map +1 -1
  29. package/dist/backend/llvm/classes.js +8 -7
  30. package/dist/backend/llvm/classes.js.map +1 -1
  31. package/dist/backend/llvm/common.d.ts +4 -0
  32. package/dist/backend/llvm/common.js +6 -0
  33. package/dist/backend/llvm/common.js.map +1 -1
  34. package/dist/backend/llvm/common.test.d.ts +1 -0
  35. package/dist/backend/llvm/common.test.js +9 -0
  36. package/dist/backend/llvm/common.test.js.map +1 -0
  37. package/dist/backend/llvm/dyn.d.ts +4 -0
  38. package/dist/backend/llvm/dyn.js +24 -13
  39. package/dist/backend/llvm/dyn.js.map +1 -1
  40. package/dist/backend/llvm/emitter.js +54 -12
  41. package/dist/backend/llvm/emitter.js.map +1 -1
  42. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  43. package/dist/backend/llvm/expr-bytes.js +8 -8
  44. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  45. package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
  46. package/dist/backend/llvm/expr-callbacks.js +125 -0
  47. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  48. package/dist/backend/llvm/expr-context.d.ts +18 -2
  49. package/dist/backend/llvm/expr-dispatch.js +1 -0
  50. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  51. package/dist/backend/llvm/expr-dynamic.js +9 -0
  52. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  53. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  54. package/dist/backend/llvm/expr-primitives.js +38 -9
  55. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  56. package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
  57. package/dist/backend/llvm/expr-primitives.test.js +38 -0
  58. package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
  59. package/dist/backend/llvm/expr-records.js +3 -3
  60. package/dist/backend/llvm/expr-records.js.map +1 -1
  61. package/dist/backend/llvm/expr-stream-bridges.js +2 -1
  62. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  63. package/dist/backend/llvm/expr-stream-callbacks.d.ts +6 -0
  64. package/dist/backend/llvm/expr-stream-callbacks.js +122 -0
  65. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  66. package/dist/backend/llvm/lib-dispatch.js +22 -0
  67. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  68. package/dist/backend/llvm/lib-filesystem.js +68 -10
  69. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  70. package/dist/backend/llvm/lib-network.js +18 -2
  71. package/dist/backend/llvm/lib-network.js.map +1 -1
  72. package/dist/backend/llvm/lib-process.js +206 -11
  73. package/dist/backend/llvm/lib-process.js.map +1 -1
  74. package/dist/backend/llvm/lib-shared.js +82 -0
  75. package/dist/backend/llvm/lib-shared.js.map +1 -1
  76. package/dist/backend/llvm/lib-stream.js +23 -0
  77. package/dist/backend/llvm/lib-stream.js.map +1 -1
  78. package/dist/backend/llvm/shapes.js +10 -8
  79. package/dist/backend/llvm/shapes.js.map +1 -1
  80. package/dist/backend/llvm/walkers.js +7 -5
  81. package/dist/backend/llvm/walkers.js.map +1 -1
  82. package/dist/backend/native-link-info.d.ts +2 -1
  83. package/dist/backend/native-link-info.js +4 -0
  84. package/dist/backend/native-link-info.js.map +1 -1
  85. package/dist/backend/native-link-info.test.js +24 -1
  86. package/dist/backend/native-link-info.test.js.map +1 -1
  87. package/dist/backend/native-toolchain.d.ts +11 -6
  88. package/dist/backend/native-toolchain.js +30 -13
  89. package/dist/backend/native-toolchain.js.map +1 -1
  90. package/dist/backend/native-toolchain.test.js +36 -1
  91. package/dist/backend/native-toolchain.test.js.map +1 -1
  92. package/dist/backend/runtime-pack-targets.test.js +1 -1
  93. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  94. package/dist/backend/runtime-pack.test.js +29 -10
  95. package/dist/backend/runtime-pack.test.js.map +1 -1
  96. package/dist/backend/targets.d.ts +9 -0
  97. package/dist/backend/targets.js +22 -0
  98. package/dist/backend/targets.js.map +1 -1
  99. package/dist/backend/targets.test.js +13 -1
  100. package/dist/backend/targets.test.js.map +1 -1
  101. package/dist/coverage/surface-manifest.js +9 -0
  102. package/dist/coverage/surface-manifest.js.map +1 -1
  103. package/dist/diagnostics/diagnostic.js +4 -4
  104. package/dist/diagnostics/diagnostic.js.map +1 -1
  105. package/dist/executable/executable-cache.d.ts +3 -0
  106. package/dist/executable/executable-cache.js +4 -0
  107. package/dist/executable/executable-cache.js.map +1 -1
  108. package/dist/executable/executable-cache.test.js +1 -0
  109. package/dist/executable/executable-cache.test.js.map +1 -1
  110. package/dist/frontend/fork-target.d.ts +17 -0
  111. package/dist/frontend/fork-target.js +256 -0
  112. package/dist/frontend/fork-target.js.map +1 -0
  113. package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
  114. package/dist/frontend/lowering/abstract-equality.js +250 -0
  115. package/dist/frontend/lowering/abstract-equality.js.map +1 -0
  116. package/dist/frontend/lowering/containers/bytes.d.ts +0 -4
  117. package/dist/frontend/lowering/containers/bytes.js +112 -28
  118. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  119. package/dist/frontend/lowering/lower-assert.js +87 -12
  120. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  121. package/dist/frontend/lowering/lower-builtins.d.ts +72 -44
  122. package/dist/frontend/lowering/lower-builtins.js +1323 -165
  123. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  124. package/dist/frontend/lowering/lower-calls.d.ts +37 -27
  125. package/dist/frontend/lowering/lower-calls.js +682 -132
  126. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  127. package/dist/frontend/lowering/lower-classes.js +39 -8
  128. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  129. package/dist/frontend/lowering/lower-containers.js +162 -8
  130. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  131. package/dist/frontend/lowering/lower-event-emitter.js +212 -21
  132. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  133. package/dist/frontend/lowering/lower-exprs.js +238 -87
  134. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  135. package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
  136. package/dist/frontend/lowering/lower-inspect.js +8 -1
  137. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  138. package/dist/frontend/lowering/lower-island.d.ts +6 -3
  139. package/dist/frontend/lowering/lower-island.js +165 -6
  140. package/dist/frontend/lowering/lower-island.js.map +1 -1
  141. package/dist/frontend/lowering/lower-modules.d.ts +6 -0
  142. package/dist/frontend/lowering/lower-modules.js +192 -38
  143. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  144. package/dist/frontend/lowering/lower-namespaces.js +7 -0
  145. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  146. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  147. package/dist/frontend/lowering/lower-server.js +130 -27
  148. package/dist/frontend/lowering/lower-server.js.map +1 -1
  149. package/dist/frontend/lowering/lower-stmts.d.ts +5 -4
  150. package/dist/frontend/lowering/lower-stmts.js +141 -21
  151. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  152. package/dist/frontend/lowering/lower-stream.d.ts +3 -0
  153. package/dist/frontend/lowering/lower-stream.js +7 -0
  154. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  155. package/dist/frontend/lowering/lowerer.d.ts +90 -13
  156. package/dist/frontend/lowering/lowerer.js +416 -76
  157. package/dist/frontend/lowering/lowerer.js.map +1 -1
  158. package/dist/frontend/lowering/surfaces.d.ts +31 -3
  159. package/dist/frontend/lowering/surfaces.js +173 -90
  160. package/dist/frontend/lowering/surfaces.js.map +1 -1
  161. package/dist/frontend/npm-static-declarations.d.ts +4 -0
  162. package/dist/frontend/npm-static-declarations.js +83 -14
  163. package/dist/frontend/npm-static-declarations.js.map +1 -1
  164. package/dist/frontend/npm-static-declarations.test.js +33 -2
  165. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  166. package/dist/frontend/npm-static.js +6 -5
  167. package/dist/frontend/npm-static.js.map +1 -1
  168. package/dist/frontend/npm.d.ts +15 -3
  169. package/dist/frontend/npm.js +80 -8
  170. package/dist/frontend/npm.js.map +1 -1
  171. package/dist/frontend/npm.test.js +76 -9
  172. package/dist/frontend/npm.test.js.map +1 -1
  173. package/dist/frontend/program.js +110 -12
  174. package/dist/frontend/program.js.map +1 -1
  175. package/dist/frontend/resolve.d.ts +28 -7
  176. package/dist/frontend/resolve.js +90 -26
  177. package/dist/frontend/resolve.js.map +1 -1
  178. package/dist/frontend/resolve.test.js +21 -1
  179. package/dist/frontend/resolve.test.js.map +1 -1
  180. package/dist/frontend/type-mapper.d.ts +5 -0
  181. package/dist/frontend/type-mapper.js +115 -33
  182. package/dist/frontend/type-mapper.js.map +1 -1
  183. package/dist/index.d.ts +5 -0
  184. package/dist/index.js +30 -3
  185. package/dist/index.js.map +1 -1
  186. package/dist/ir/analysis.js +1 -0
  187. package/dist/ir/analysis.js.map +1 -1
  188. package/dist/ir/ir.d.ts +155 -66
  189. package/dist/ir/ir.js +143 -6
  190. package/dist/ir/ir.js.map +1 -1
  191. package/dist/ir/ir.test.js +14 -1
  192. package/dist/ir/ir.test.js.map +1 -1
  193. package/dist/ir/serialize.d.ts +1 -1
  194. package/dist/ir/serialize.js +1 -1
  195. package/dist/ir/serialize.js.map +1 -1
  196. package/dist/ir/validate.js +242 -18
  197. package/dist/ir/validate.js.map +1 -1
  198. package/dist/library/int-infer.test.js +4 -4
  199. package/dist/library/int-infer.test.js.map +1 -1
  200. package/dist/library/library-cache.d.ts +1 -0
  201. package/dist/library/library-cache.js +1 -0
  202. package/dist/library/library-cache.js.map +1 -1
  203. package/dist/library/library-cache.test.js +18 -5
  204. package/dist/library/library-cache.test.js.map +1 -1
  205. package/package.json +17 -17
  206. package/surface-manifest.json +163 -54
@@ -198,7 +198,24 @@ export interface BuiltinModuleFn {
198
198
  result: IrType;
199
199
  variadicPack?: boolean;
200
200
  defaults?: string[];
201
+ /** The source-level function-value signature. Each admitted entry
202
+ * materializes as an interned zero-capture adapter over the fixed runtime
203
+ * libCall ABI. Optional parameters name the string default selected for
204
+ * omission or explicit undefined; rest parameters pack into one typed
205
+ * array slot. Entries with call-site-specific validation remain absent. */
206
+ valueParams?: BuiltinValueParam[];
201
207
  }
208
+ export type BuiltinValueParam = {
209
+ mode: "required";
210
+ type: IrType;
211
+ } | {
212
+ mode: "optional";
213
+ type: IrType;
214
+ defaultValue: string;
215
+ } | {
216
+ mode: "rest";
217
+ type: IrType;
218
+ };
202
219
  export declare const BUILTIN_MODULE_FNS: Record<string, Record<string, BuiltinModuleFn | undefined> | undefined>;
203
220
  /** Builtin-module CONSTANTS (value reads of named imports): each lowers to
204
221
  * a literal of its value's kind. The bare-module values are the TARGET
@@ -254,6 +271,14 @@ export declare function builtinConstLit(value: string | number | boolean, loc: {
254
271
  start: number;
255
272
  end: number;
256
273
  }): IrExpr;
274
+ /** node:module's builtinModules, BAKED — Node v24's exact list (verbatim
275
+ * order: the bare names, then the node:-prefix-only tails), pinned to
276
+ * the compat target rather than read from the COMPILING host's Node so
277
+ * emitted programs are host-independent (the cache-identity contract).
278
+ * Node ships one frozen singleton; each read here mints a fresh string
279
+ * array — a divergence only mutation could observe, and mutating Node's
280
+ * frozen array throws anyway. */
281
+ export declare const NODE_BUILTIN_MODULES_V24: readonly string[];
257
282
  /** The array-literal read of module.builtinModules — both value paths
258
283
  * (the named-import binding and the namespace member read) mint the
259
284
  * same fresh string[]. */
@@ -288,9 +313,11 @@ export declare function isChildSurfaceMember(lowerer: Lowerer, access: ts.Proper
288
313
  * user's own declaration is in neither, so shadowing never matches. */
289
314
  export declare function isStdlibSymbol(lowerer: Lowerer, symbol: ts.Symbol | undefined): boolean;
290
315
  /** The canonical stdlib-global name `expr` denotes, or null. Three
291
- * spellings reach the same global (Node's own aliasing):
292
- * - the bare identifier (`process`), name + provenance checked;
293
- * - the `global` identifier — Node's alias of globalThis — and
316
+ * spellings reach the same global (Node's own aliasing):
317
+ * - the bare identifier (`process`), name + provenance checked;
318
+ * - the default import from `process`/`node:process`, whose value is
319
+ * exactly the global process object;
320
+ * - the `global` identifier — Node's alias of globalThis — and
294
321
  * `globalThis` itself both canonicalize to "globalThis";
295
322
  * - a property read off globalThis (`globalThis.process`,
296
323
  * `global.process`) — `declare var` globals ARE properties of
@@ -319,6 +346,7 @@ export declare function stdlibGlobalMember(lowerer: Lowerer, access: ts.Property
319
346
  * nothing. Only the globals with lowered member surfaces alias this
320
347
  * way; aliasing, say, `Math` would change nothing (its members lower
321
348
  * by receiver too). Returns true when recognized. */
349
+ export declare function stdlibGlobalAliasNameOf(lowerer: Lowerer, init: ts.Expression | undefined): string | null;
322
350
  export declare function stdlibGlobalAliasDecl(lowerer: Lowerer, nameNode: ts.Node, init: ts.Expression | undefined): boolean;
323
351
  /** True iff the symbol is declared ONLY by the adopted @types/node
324
352
  * surface (no es-lib or shipped-ambient declaration merges in) — chooses
@@ -5,7 +5,7 @@
5
5
  * diagnostic tables, and the "which world declared this symbol" predicates
6
6
  * (ambient scriptc.d.ts / standard lib / @types/node provenance). */
7
7
  import * as ts from "../ts7/adapter.js";
8
- import { BOOL, BYTES_U8, CHILD_T, DYN, F64, FILEHANDLE_T, RUNTIME_ERROR_CLASSES, SPAWNRES_T, STATS_T, STRING, URL_T, VOID, arrayOf } from "../../ir/ir.js";
8
+ import { BOOL, BYTES_U8, CHILD_T, CRYPTOHASH_T, CRYPTOHMAC_T, DYN, F64, FILEHANDLE_T, RUNTIME_ERROR_CLASSES, SPAWNRES_T, STATS_T, STRING, URL_T, VOID, arrayOf } from "../../ir/ir.js";
9
9
  import { isNodeTypesPath, requireSpecOf } from "../program.js";
10
10
  /** Statement-level constructs rejected wholesale, keyed by syntax kind. */
11
11
  export const UNSUPPORTED_STMT = {
@@ -485,6 +485,13 @@ export const STATIC_MATH_FNS = {
485
485
  export const STATIC_NUMBER_METHODS = {
486
486
  toFixed: { fns: ["num.toFixed0", "num.toFixed"], minArgs: 0, maxArgs: 1 },
487
487
  };
488
+ /** The common first-class shape for builtin functions whose supported
489
+ * source signature is already exactly the fixed native ABI. Keeping the
490
+ * opt-in on each table row is deliberate: dispatch sentinels and functions
491
+ * with call-site validation must provide a real adapter instead. */
492
+ function exactValueParams(...types) {
493
+ return types.map((type) => ({ mode: "required", type }));
494
+ }
488
495
  /** The lowerable surface of the supported node builtin modules, keyed by
489
496
  * CANONICAL module name (both "fs" and "node:fs" land on "fs" — see
490
497
  * canonicalBuiltinModule). Like STR_METHODS, membership is only half the
@@ -498,36 +505,40 @@ export const STATIC_NUMBER_METHODS = {
498
505
  * platform's rules on any host). toNamespacedPath is the posix identity
499
506
  * (Node: a non-op on posix systems). */
500
507
  const PATH_MODULE_FNS = {
501
- join: { fn: "path.join", params: [STRING], result: STRING, variadicPack: true },
502
- resolve: { fn: "path.resolve", params: [STRING], result: STRING, variadicPack: true },
503
- normalize: { fn: "path.normalize", params: [STRING], result: STRING },
504
- dirname: { fn: "path.dirname", params: [STRING], result: STRING },
505
- basename: { fn: "path.basename", params: [STRING, STRING], result: STRING, defaults: [""] },
506
- extname: { fn: "path.extname", params: [STRING], result: STRING },
507
- isAbsolute: { fn: "path.isAbsolute", params: [STRING], result: BOOL },
508
- relative: { fn: "path.relative", params: [STRING, STRING], result: STRING },
509
- toNamespacedPath: { fn: "path.toNamespacedPath", params: [STRING], result: STRING },
508
+ join: { fn: "path.join", params: [STRING], result: STRING, variadicPack: true, valueParams: [{ mode: "rest", type: STRING }] },
509
+ resolve: { fn: "path.resolve", params: [STRING], result: STRING, variadicPack: true, valueParams: [{ mode: "rest", type: STRING }] },
510
+ normalize: { fn: "path.normalize", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
511
+ dirname: { fn: "path.dirname", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
512
+ basename: { fn: "path.basename", params: [STRING, STRING], result: STRING, defaults: [""], valueParams: [{ mode: "required", type: STRING }, { mode: "optional", type: STRING, defaultValue: "" }] },
513
+ extname: { fn: "path.extname", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
514
+ isAbsolute: { fn: "path.isAbsolute", params: [STRING], result: BOOL, valueParams: [{ mode: "required", type: STRING }] },
515
+ relative: { fn: "path.relative", params: [STRING, STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }, { mode: "required", type: STRING }] },
516
+ toNamespacedPath: { fn: "path.toNamespacedPath", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
510
517
  };
511
518
  /** The win32 twins (scr_path.c's Node-v24 path.win32 port, byte-for-byte):
512
519
  * "path/win32" everywhere, and the bare-module table when the build
513
520
  * TARGETS win32 — Node on Windows is path.win32. */
514
521
  const PATH_WIN32_MODULE_FNS = {
515
- join: { fn: "path.win32Join", params: [STRING], result: STRING, variadicPack: true },
516
- resolve: { fn: "path.win32Resolve", params: [STRING], result: STRING, variadicPack: true },
517
- normalize: { fn: "path.win32Normalize", params: [STRING], result: STRING },
518
- dirname: { fn: "path.win32Dirname", params: [STRING], result: STRING },
519
- basename: { fn: "path.win32Basename", params: [STRING, STRING], result: STRING, defaults: [""] },
520
- extname: { fn: "path.win32Extname", params: [STRING], result: STRING },
521
- isAbsolute: { fn: "path.win32IsAbsolute", params: [STRING], result: BOOL },
522
- relative: { fn: "path.win32Relative", params: [STRING, STRING], result: STRING },
523
- toNamespacedPath: { fn: "path.win32ToNamespacedPath", params: [STRING], result: STRING },
522
+ join: { fn: "path.win32Join", params: [STRING], result: STRING, variadicPack: true, valueParams: [{ mode: "rest", type: STRING }] },
523
+ resolve: { fn: "path.win32Resolve", params: [STRING], result: STRING, variadicPack: true, valueParams: [{ mode: "rest", type: STRING }] },
524
+ normalize: { fn: "path.win32Normalize", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
525
+ dirname: { fn: "path.win32Dirname", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
526
+ basename: { fn: "path.win32Basename", params: [STRING, STRING], result: STRING, defaults: [""], valueParams: [{ mode: "required", type: STRING }, { mode: "optional", type: STRING, defaultValue: "" }] },
527
+ extname: { fn: "path.win32Extname", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
528
+ isAbsolute: { fn: "path.win32IsAbsolute", params: [STRING], result: BOOL, valueParams: [{ mode: "required", type: STRING }] },
529
+ relative: { fn: "path.win32Relative", params: [STRING, STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }, { mode: "required", type: STRING }] },
530
+ toNamespacedPath: { fn: "path.win32ToNamespacedPath", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
524
531
  };
525
532
  export const BUILTIN_MODULE_FNS = {
526
533
  fs: {
527
534
  readFileSync: { fn: "fs.readFileSync", params: [STRING, STRING], result: STRING },
535
+ // The exact-API subset is first-class. A fixed native ABI is not enough:
536
+ // rows whose Node function has behavior-bearing trailing options remain
537
+ // call-only, or function-width adaptation could silently discard those
538
+ // options before entering the fixed runtime call.
528
539
  writeFileSync: { fn: "fs.writeFileSync", params: [STRING, STRING], result: VOID },
529
540
  appendFileSync: { fn: "fs.appendFileSync", params: [STRING, STRING], result: VOID },
530
- existsSync: { fn: "fs.existsSync", params: [STRING], result: BOOL },
541
+ existsSync: { fn: "fs.existsSync", params: [STRING], result: BOOL, valueParams: exactValueParams(STRING) },
531
542
  mkdirSync: { fn: "fs.mkdirSync", params: [STRING], result: VOID },
532
543
  rmSync: { fn: "fs.rmSync", params: [STRING], result: VOID },
533
544
  rmdirSync: { fn: "fs.rmdirSync", params: [STRING], result: VOID },
@@ -537,9 +548,9 @@ export const BUILTIN_MODULE_FNS = {
537
548
  // accessSync's omitted mode completes to 0 (F_OK) in the special case
538
549
  // in lowerBuiltinModuleCall — string `defaults` can't spell a number.
539
550
  accessSync: { fn: "fs.accessSync", params: [STRING, F64], result: VOID },
540
- unlinkSync: { fn: "fs.unlinkSync", params: [STRING], result: VOID },
541
- chmodSync: { fn: "fs.chmodSync", params: [STRING, F64], result: VOID },
542
- chownSync: { fn: "fs.chownSync", params: [STRING, F64, F64], result: VOID },
551
+ unlinkSync: { fn: "fs.unlinkSync", params: [STRING], result: VOID, valueParams: exactValueParams(STRING) },
552
+ chmodSync: { fn: "fs.chmodSync", params: [STRING, F64], result: VOID, valueParams: exactValueParams(STRING, F64) },
553
+ chownSync: { fn: "fs.chownSync", params: [STRING, F64, F64], result: VOID, valueParams: exactValueParams(STRING, F64, F64) },
543
554
  // The 2-argument form only: Node's mode flags (COPYFILE_EXCL, ...)
544
555
  // land on the arity fence.
545
556
  copyFileSync: { fn: "fs.copyFileSync", params: [STRING, STRING], result: VOID },
@@ -548,18 +559,22 @@ export const BUILTIN_MODULE_FNS = {
548
559
  // adapter. The row still projects the static surface and routes the
549
560
  // dispatch.
550
561
  rename: { fn: "fs.renameCb", params: [], result: VOID },
551
- renameSync: { fn: "fs.renameSync", params: [STRING, STRING], result: VOID },
562
+ renameSync: { fn: "fs.renameSync", params: [STRING, STRING], result: VOID, valueParams: exactValueParams(STRING, STRING) },
552
563
  // statSync's no-follow sibling; stats.isSymbolicLink answers what the
553
564
  // follow-free snapshot saw.
554
565
  lstatSync: { fn: "fs.lstatSync", params: [STRING], result: STATS_T },
566
+ fstatSync: { fn: "fs.fstatSync", params: [F64], result: STATS_T, valueParams: exactValueParams(F64) },
567
+ fchmodSync: { fn: "fs.fchmodSync", params: [F64, F64], result: VOID, valueParams: exactValueParams(F64, F64) },
568
+ fsyncSync: { fn: "fs.fsyncSync", params: [F64], result: VOID, valueParams: exactValueParams(F64) },
569
+ linkSync: { fn: "fs.linkSync", params: [STRING, STRING], result: VOID, valueParams: exactValueParams(STRING, STRING) },
555
570
  // realpath(3) — Node's realpathSync (failures spell syscall "lstat",
556
571
  // Node's own message shape).
557
572
  realpathSync: { fn: "fs.realpathSync", params: [STRING], result: STRING },
558
573
  // The fd pair behind spawn's fd-stdio form (the daemon-log idiom:
559
574
  // openSync(logPath, "a") → spawn stdio ["ignore", fd, fd] →
560
- // closeSync). openSync takes Node's string flags ("r", "w", "a", the
561
- // +/x variants — unknown flags throw Node's TypeError text); the
562
- // numeric-mode third argument fences by arity.
575
+ // closeSync). String flags use the established two-argument path;
576
+ // inline numeric O_* expressions route through openNumericSync, with
577
+ // an optional creation mode as the third argument.
563
578
  openSync: { fn: "fs.openSync", params: [STRING, STRING], result: F64 },
564
579
  // The buffer forms (fd, buffer, offset, length[, position]). The
565
580
  // lowering completes an omitted or literal-null position to -1 (the
@@ -570,7 +585,7 @@ export const BUILTIN_MODULE_FNS = {
570
585
  // overloads lower to separate fixed-width runtime ABIs. As with
571
586
  // readSync, -1 is the current-offset sentinel.
572
587
  writeSync: { fn: "fs.writeSync", params: [F64, BYTES_U8, F64, F64, F64], result: F64 },
573
- closeSync: { fn: "fs.closeSync", params: [F64], result: VOID },
588
+ closeSync: { fn: "fs.closeSync", params: [F64], result: VOID, valueParams: exactValueParams(F64) },
574
589
  // Entirely special-cased (lowerFsWatchCall — the callback needs an
575
590
  // adapter per listener shape); this entry only routes the dispatch.
576
591
  watch: { fn: "fs.watch", params: [], result: VOID },
@@ -585,9 +600,11 @@ export const BUILTIN_MODULE_FNS = {
585
600
  readdir: { fn: "fsp.readdir", params: [STRING], result: { kind: "promise", inner: arrayOf(STRING) } },
586
601
  rm: { fn: "fsp.rm", params: [STRING], result: { kind: "promise", inner: VOID } },
587
602
  stat: { fn: "fsp.stat", params: [STRING], result: { kind: "promise", inner: STATS_T } },
588
- unlink: { fn: "fsp.unlink", params: [STRING], result: { kind: "promise", inner: VOID } },
589
- chmod: { fn: "fsp.chmod", params: [STRING, F64], result: { kind: "promise", inner: VOID } },
590
- rename: { fn: "fsp.rename", params: [STRING, STRING], result: { kind: "promise", inner: VOID } },
603
+ realpath: { fn: "fsp.realpath", params: [STRING], result: { kind: "promise", inner: STRING } },
604
+ lstat: { fn: "fsp.lstat", params: [STRING], result: { kind: "promise", inner: STATS_T } },
605
+ unlink: { fn: "fsp.unlink", params: [STRING], result: { kind: "promise", inner: VOID }, valueParams: exactValueParams(STRING) },
606
+ chmod: { fn: "fsp.chmod", params: [STRING, F64], result: { kind: "promise", inner: VOID }, valueParams: exactValueParams(STRING, F64) },
607
+ rename: { fn: "fsp.rename", params: [STRING, STRING], result: { kind: "promise", inner: VOID }, valueParams: exactValueParams(STRING, STRING) },
591
608
  // open's optional flags/mode completion is special-cased in
592
609
  // lowerBuiltinModuleCall; this row routes all import spellings and
593
610
  // gives coverage the static member.
@@ -605,18 +622,18 @@ export const BUILTIN_MODULE_FNS = {
605
622
  "path/win32": PATH_WIN32_MODULE_FNS,
606
623
  os: {
607
624
  // One platform implementation: os.platform() === process.platform.
608
- platform: { fn: "process.platform", params: [], result: STRING },
609
- homedir: { fn: "os.homedir", params: [], result: STRING },
610
- tmpdir: { fn: "os.tmpdir", params: [], result: STRING },
625
+ platform: { fn: "process.platform", params: [], result: STRING, valueParams: [] },
626
+ homedir: { fn: "os.homedir", params: [], result: STRING, valueParams: [] },
627
+ tmpdir: { fn: "os.tmpdir", params: [], result: STRING, valueParams: [] },
611
628
  // uname(2)'s release field — Node's own implementation.
612
- release: { fn: "os.release", params: [], result: STRING },
629
+ release: { fn: "os.release", params: [], result: STRING, valueParams: [] },
613
630
  // uname(2)'s sysname field ("Darwin", "Linux", "Windows_NT") — the
614
631
  // libFn/runtime pair predates this entry (the portless surface used
615
632
  // them); this row makes the MODULE call reach them (test/common's
616
633
  // isAIX/isIBMi getters are the canonical callers).
617
- type: { fn: "os.type", params: [], result: STRING },
634
+ type: { fn: "os.type", params: [], result: STRING, valueParams: [] },
618
635
  // Total physical memory in bytes — same predating-pair story.
619
- totalmem: { fn: "os.totalmem", params: [], result: F64 },
636
+ totalmem: { fn: "os.totalmem", params: [], result: F64, valueParams: [] },
620
637
  // Entirely special-cased (lowerOsNetworkInterfacesCall): the result is
621
638
  // the call site's mapped Dict<NetworkInterfaceInfo[]> shape, verified
622
639
  // structurally there — this entry only routes the dispatch.
@@ -632,13 +649,38 @@ export const BUILTIN_MODULE_FNS = {
632
649
  // first and the Buffer never materializes there); this entry covers
633
650
  // the bare calls and non-composed uses.
634
651
  randomBytes: { fn: "crypto.randomBytes", params: [F64], result: BYTES_U8 },
652
+ // The crypto utility surface is special-cased for overloads and
653
+ // string/Buffer splits in lowerCryptoModuleCall. These rows carry the
654
+ // canonical signatures for manifest projection and fallback dispatch.
655
+ createHash: { fn: "crypto.hashNew", params: [STRING], result: CRYPTOHASH_T },
656
+ createHmac: { fn: "crypto.hmacNewStr", params: [STRING, STRING], result: CRYPTOHMAC_T },
657
+ hash: { fn: "crypto.hashDigestStr", params: [STRING, STRING, STRING], result: STRING },
658
+ timingSafeEqual: { fn: "crypto.timingSafeEqual", params: [BYTES_U8, BYTES_U8], result: BOOL },
659
+ randomFillSync: { fn: "crypto.randomFill", params: [BYTES_U8, F64, F64], result: BYTES_U8 },
660
+ randomInt: { fn: "crypto.randomInt", params: [F64, F64], result: F64 },
661
+ pbkdf2Sync: { fn: "crypto.pbkdf2", params: [BYTES_U8, BYTES_U8, F64, F64, STRING], result: BYTES_U8 },
662
+ pbkdf2: { fn: "crypto.pbkdf2Cb", params: [], result: VOID },
635
663
  },
636
664
  zlib: {
637
- // Buffer in, Buffer out, Node's default options; string inputs fence
638
- // per site (see the zlib special case in lowerBuiltinModuleCall).
665
+ // The default-options convenience family is special-cased in
666
+ // lowerBuiltinModuleCall: string inputs UTF-8 encode, callback forms
667
+ // carry program-shaped closures, and explicit options fence per site.
639
668
  // native-toolchain.ts links libz only when these appear on the IR.
669
+ deflate: { fn: "zlib.deflateCb", params: [], result: VOID },
640
670
  deflateSync: { fn: "zlib.deflateSync", params: [BYTES_U8], result: BYTES_U8 },
671
+ inflate: { fn: "zlib.inflateCb", params: [], result: VOID },
641
672
  inflateSync: { fn: "zlib.inflateSync", params: [BYTES_U8], result: BYTES_U8 },
673
+ deflateRaw: { fn: "zlib.deflateRawCb", params: [], result: VOID },
674
+ deflateRawSync: { fn: "zlib.deflateRawSync", params: [BYTES_U8], result: BYTES_U8 },
675
+ inflateRaw: { fn: "zlib.inflateRawCb", params: [], result: VOID },
676
+ inflateRawSync: { fn: "zlib.inflateRawSync", params: [BYTES_U8], result: BYTES_U8 },
677
+ gzip: { fn: "zlib.gzipCb", params: [], result: VOID },
678
+ gzipSync: { fn: "zlib.gzipSync", params: [BYTES_U8], result: BYTES_U8 },
679
+ gunzip: { fn: "zlib.gunzipCb", params: [], result: VOID },
680
+ gunzipSync: { fn: "zlib.gunzipSync", params: [BYTES_U8], result: BYTES_U8 },
681
+ unzip: { fn: "zlib.unzipCb", params: [], result: VOID },
682
+ unzipSync: { fn: "zlib.unzipSync", params: [BYTES_U8], result: BYTES_U8 },
683
+ crc32: { fn: "zlib.crc32", params: [], result: F64 },
642
684
  },
643
685
  url: {
644
686
  // fileURLToPath accepts a URL value OR a string — the call lowering
@@ -650,11 +692,13 @@ export const BUILTIN_MODULE_FNS = {
650
692
  child_process: {
651
693
  // spawnSync's and spawn's call completions are entirely special-cased
652
694
  // (an omitted args list completes to an empty string[]; spawnSync
653
- // accepts exactly { encoding: "utf8" } as options, spawn requires
654
- // exactly { stdio: "ignore" } — see lowerBuiltinModuleCall); the
695
+ // accepts its documented literal options, while spawn supports the
696
+ // stdio/detached/env/cwd/windowsHide/shell subset — see
697
+ // lowerBuiltinModuleCall); the
655
698
  // entries carry the canonical shapes.
656
699
  spawnSync: { fn: "cp.spawnSync", params: [STRING, arrayOf(STRING)], result: SPAWNRES_T },
657
700
  spawn: { fn: "cp.spawn", params: [STRING, arrayOf(STRING)], result: CHILD_T },
701
+ fork: { fn: "cp.fork", params: [STRING, arrayOf(STRING)], result: CHILD_T },
658
702
  // execFileSync(file, args?, options?) and execSync(command, options?)
659
703
  // share the cp.execSync runtime entry (execSync sets the shell flag);
660
704
  // both call completions are special-cased in lowerBuiltinModuleCall.
@@ -693,8 +737,8 @@ export const BUILTIN_MODULE_FNS = {
693
737
  decode: { fn: "qs.parse", params: [STRING], result: VOID },
694
738
  stringify: { fn: "qs.stringify", params: [DYN], result: STRING },
695
739
  encode: { fn: "qs.stringify", params: [DYN], result: STRING },
696
- escape: { fn: "qs.escape", params: [STRING], result: STRING },
697
- unescape: { fn: "qs.unescape", params: [STRING], result: STRING },
740
+ escape: { fn: "qs.escape", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
741
+ unescape: { fn: "qs.unescape", params: [STRING], result: STRING, valueParams: [{ mode: "required", type: STRING }] },
698
742
  },
699
743
  // node:readline: createInterface's options are entirely special-cased
700
744
  // (exactly { input: process.stdin, output?: process.stdout } — see
@@ -801,6 +845,8 @@ export const BUILTIN_MODULE_CONSTS = {
801
845
  * (library/fence-eval.ts) and the attestation-parity test. */
802
846
  export const BUILTIN_MODULE_FN_ALIASES = {
803
847
  fs: {
848
+ // Inline numeric O_* flags use a target-neutral runtime entry point.
849
+ openSync: ["fs.openNumericSync"],
804
850
  // The Buffer form (no encoding), the fd forms (readFileSync(fd[,
805
851
  // "utf8"])), and the checked-dynamic encoding form.
806
852
  readFileSync: ["fs.readFileSyncBuf", "fs.readFileSyncBytes", "fs.readFileSyncDyn", "fs.readFdSync", "fs.readFdSyncBytes"],
@@ -830,11 +876,17 @@ export const BUILTIN_MODULE_FN_ALIASES = {
830
876
  readFile: ["fsp.readFileBytes"],
831
877
  // The string-data { mode } options form.
832
878
  writeFile: ["fsp.writeFileMode"],
879
+ // The { withFileTypes: true } Dirent form.
880
+ readdir: ["fsp.readdirTypes"],
833
881
  },
834
882
  crypto: {
835
883
  // The composed randomBytes(n).toString(enc) chain keeps its one-libCall
836
- // lowering (lowerCryptoComposedCall) — same surface, no Buffer.
837
- randomBytes: ["crypto.randomBytesToString"],
884
+ // lowering (lowerCryptoComposedCall), while the callback overload has
885
+ // its own adapter spelling. Both remain the randomBytes surface.
886
+ randomBytes: ["crypto.randomBytesToString", "crypto.randomBytesCb"],
887
+ // Omitting size fills from offset through the rest of the Buffer and
888
+ // uses a separate runtime entry point for Node's exact bounds checks.
889
+ randomFillSync: ["crypto.randomFillRest"],
838
890
  },
839
891
  os: {
840
892
  // lowerOsUserInfoCall assembles the record from scalar libCalls.
@@ -851,6 +903,13 @@ export const AMBIENT_SURFACE_FNS = [
851
903
  fns: ["date.now"],
852
904
  note: "the live clock",
853
905
  },
906
+ {
907
+ id: "stdlib.date.parse",
908
+ kind: "stdlib",
909
+ name: "Date.parse",
910
+ fns: ["date.parse"],
911
+ note: "one date string, using the bounded parser shared with new Date(dateString).getTime()",
912
+ },
854
913
  {
855
914
  id: "stdlib.date.constructor",
856
915
  kind: "stdlib",
@@ -991,6 +1050,13 @@ export const AMBIENT_SURFACE_FNS = [
991
1050
  fns: ["process.exit", "process.exiting"],
992
1051
  note: "process.exit and the process._exiting flag read are one surface",
993
1052
  },
1053
+ {
1054
+ id: "node-builtin.process.exitCode",
1055
+ kind: "node-builtin",
1056
+ name: "process.exitCode",
1057
+ fns: ["process.setExitCode"],
1058
+ note: "numeric writes in statement position set the implicit exit status; process.exit() reads it",
1059
+ },
994
1060
  // ── the tls CA store (lowerTlsCaCall / lowerTlsRootCertificates): the
995
1061
  // host's trust anchors, read and replaced. Dedicated paths, and
996
1062
  // rootCertificates is a VALUE read with no call form at all, so none of
@@ -1098,7 +1164,7 @@ export function builtinConstLit(value, loc) {
1098
1164
  * Node ships one frozen singleton; each read here mints a fresh string
1099
1165
  * array — a divergence only mutation could observe, and mutating Node's
1100
1166
  * frozen array throws anyway. */
1101
- const NODE_BUILTIN_MODULES_V24 = [
1167
+ export const NODE_BUILTIN_MODULES_V24 = [
1102
1168
  "_http_agent", "_http_client", "_http_common", "_http_incoming",
1103
1169
  "_http_outgoing", "_http_server", "_stream_duplex", "_stream_passthrough",
1104
1170
  "_stream_readable", "_stream_transform", "_stream_wrap", "_stream_writable",
@@ -1126,19 +1192,16 @@ export function builtinModulesArrayLit(loc) {
1126
1192
  };
1127
1193
  }
1128
1194
  /** Member-specific hints for RECOGNIZED builtin modules whose member has
1129
- * no lowering. deflateSync/inflateSync lower now (Buffers are real);
1130
- * the rest of the zlib surface points at the lowered pair. */
1131
- const ZLIB_HINT = "deflateSync and inflateSync are the lowered zlib surface";
1132
- /** The loose-equality quartet's shared hint: == coercion has no lowering
1133
- * anywhere in this compiler, and Node itself points at the strict forms. */
1134
- const ASSERT_LOOSE_HINT = "loose == equality has no lowering — the strict forms compare with " +
1135
- "Object.is/structural equality like Node's assert/strict module, where " +
1136
- "equal IS strictEqual";
1195
+ * no lowering. The default-options one-shot zlib/deflate-raw/gzip codecs
1196
+ * lower for strings and Buffers; the remaining surface points at them. */
1197
+ const ZLIB_HINT = "the default-options deflate/inflate, raw, gzip/gunzip, and unzip sync/callback forms plus crc32 are the lowered zlib surface";
1198
+ /** The legacy deep pair remains fenced. The shallow equal/notEqual pair
1199
+ * lowers through the static Abstract Equality kernel in lower-assert. */
1200
+ const ASSERT_LOOSE_DEEP_HINT = "legacy deep equality has no lowering yet — deepStrictEqual and " +
1201
+ "notDeepStrictEqual compare structures with Node's modern semantics";
1137
1202
  const ASSERT_MODULE_HINTS = {
1138
- equal: ASSERT_LOOSE_HINT,
1139
- notEqual: ASSERT_LOOSE_HINT,
1140
- deepEqual: ASSERT_LOOSE_HINT,
1141
- notDeepEqual: ASSERT_LOOSE_HINT,
1203
+ deepEqual: ASSERT_LOOSE_DEEP_HINT,
1204
+ notDeepEqual: ASSERT_LOOSE_DEEP_HINT,
1142
1205
  ifError: "test explicitly instead: assert.strictEqual(err, null) / " +
1143
1206
  "assert.strictEqual(err, undefined)",
1144
1207
  rejects: "await the promise inside assert.throws's callback story instead: " +
@@ -1161,10 +1224,7 @@ export const BUILTIN_MODULE_FENCE_HINTS = {
1161
1224
  AssertionError: ASSERT_MODULE_HINTS["AssertionError"],
1162
1225
  },
1163
1226
  util: {
1164
- promisify: "the one lowered shape is a const binding over child_process.execFile: " +
1165
- "const execFileAsync = promisify(execFile), then call execFileAsync directly",
1166
- // child_process.execFile itself exists to be promisified — the same
1167
- // story from the other end.
1227
+ promisify: "the lowered shapes are const bindings over child_process.execFile and fs.readFile; call the bound function directly",
1168
1228
  },
1169
1229
  "stream/consumers": {
1170
1230
  arrayBuffer: "no free-standing ArrayBuffer value exists here (typed arrays own their storage) — " +
@@ -1174,25 +1234,17 @@ export const BUILTIN_MODULE_FENCE_HINTS = {
1174
1234
  },
1175
1235
  module: {
1176
1236
  createRequire: "the lowered shape is a const binding over createRequire(import.meta.url) (or __filename) " +
1177
- "whose require calls take STATIC string literals — builtins, relative .json documents, " +
1178
- "and installed npm packages (under --dynamic) resolve at build time; " +
1237
+ "whose require calls take STATIC string literals — builtins, project modules (including #imports), " +
1238
+ "relative .json documents, --npm-static packages, and installed npm packages under --dynamic resolve at build time; " +
1179
1239
  "dynamic specifiers cannot exist in a compiled binary's fixed module graph",
1180
- isBuiltin: "builtinModules.includes(name) answers the same question over the baked list " +
1181
- "(strip a node: prefix first; the prefix-only builtins appear with it, as node:test)",
1182
- syncBuiltinESMExports: "a compiled program has no live builtin ESM namespace bindings to synchronize — " +
1183
- "nothing a compiled surface can mutate makes the call observable; remove it",
1240
+ isBuiltin: "the lowered call checks a string against the baked Node v24 list, including bare/node: aliases and prefix-only builtins",
1241
+ syncBuiltinESMExports: "the direct zero-argument call is a no-op because compiled builtin exports are immutable and cannot become stale",
1184
1242
  },
1185
1243
  child_process: {
1186
- execFile: "the callback form has no lowering — promisify it: " +
1187
- "const execFileAsync = promisify(execFile) (from node:util), or use execFileSync",
1244
+ execFile: "the callback forms execFile(file, callback), execFile(file, args, callback), and execFile(file, args, { encoding: 'utf8', maxBuffer: N }, callback) lower; " +
1245
+ "maxBuffer is not enforced by the growing native capture; other options and reached no-callback calls remain fenced, while util.promisify(execFile) retains its wider options slice",
1188
1246
  },
1189
1247
  crypto: {
1190
- createHash: "the one lowered shape is the composed chain " +
1191
- 'createHash("sha256").update(data).digest("hex") — the Hash handle itself has no lowering',
1192
- hash: "the one-shot digest has no lowering — the composed chain " +
1193
- 'createHash("sha256").update(data).digest("hex") is the lowered hashing surface',
1194
- createHmac: "HMAC has no lowering yet — the lowered crypto surface is randomUUID, randomBytes, " +
1195
- 'the createHash("sha256"|"sha1") chain, and the introspection statics',
1196
1248
  ...Object.fromEntries([
1197
1249
  "generateKeyPair", "generateKeyPairSync", "generateKey", "generateKeySync",
1198
1250
  "createPrivateKey", "createPublicKey", "createSecretKey",
@@ -1211,7 +1263,7 @@ export const BUILTIN_MODULE_FENCE_HINTS = {
1211
1263
  "symmetric ciphers need a cipher stack the static runtime does not vendor — " +
1212
1264
  "the lowered crypto surface is hashing, randomness, and the introspection statics",
1213
1265
  ])),
1214
- ...Object.fromEntries(["pbkdf2", "pbkdf2Sync", "scrypt", "scryptSync", "hkdf", "hkdfSync"].map((m) => [
1266
+ ...Object.fromEntries(["scrypt", "scryptSync", "hkdf", "hkdfSync"].map((m) => [
1215
1267
  m,
1216
1268
  "key-derivation functions have no lowering yet — the lowered crypto surface is " +
1217
1269
  "hashing, randomness, and the introspection statics",
@@ -1222,9 +1274,6 @@ export const BUILTIN_MODULE_FENCE_HINTS = {
1222
1274
  "randomBytes, and the createHash chain",
1223
1275
  },
1224
1276
  zlib: {
1225
- gzipSync: ZLIB_HINT,
1226
- gunzipSync: ZLIB_HINT,
1227
- unzipSync: ZLIB_HINT,
1228
1277
  brotliCompressSync: ZLIB_HINT,
1229
1278
  brotliDecompressSync: ZLIB_HINT,
1230
1279
  },
@@ -1454,9 +1503,11 @@ export function isStdlibSymbol(lowerer, symbol) {
1454
1503
  return !!symbol && lowerer.checker.declarationsOf(symbol).some((d) => lowerer.isStdlibFile(d.getSourceFile()));
1455
1504
  }
1456
1505
  /** The canonical stdlib-global name `expr` denotes, or null. Three
1457
- * spellings reach the same global (Node's own aliasing):
1458
- * - the bare identifier (`process`), name + provenance checked;
1459
- * - the `global` identifier — Node's alias of globalThis — and
1506
+ * spellings reach the same global (Node's own aliasing):
1507
+ * - the bare identifier (`process`), name + provenance checked;
1508
+ * - the default import from `process`/`node:process`, whose value is
1509
+ * exactly the global process object;
1510
+ * - the `global` identifier — Node's alias of globalThis — and
1460
1511
  * `globalThis` itself both canonicalize to "globalThis";
1461
1512
  * - a property read off globalThis (`globalThis.process`,
1462
1513
  * `global.process`) — `declare var` globals ARE properties of
@@ -1478,6 +1529,15 @@ export function stdlibGlobalNameOf(lowerer, expr) {
1478
1529
  const alias = lowerer.stdlibGlobalAliases.get(symbol);
1479
1530
  if (alias !== undefined)
1480
1531
  return alias;
1532
+ const decl = lowerer.checker.declarationsOf(symbol)[0];
1533
+ if (decl !== undefined && ts.isImportClause(decl) && decl.name !== undefined) {
1534
+ const importDecl = decl.parent;
1535
+ if (ts.isImportDeclaration(importDecl) && ts.isStringLiteral(importDecl.moduleSpecifier)) {
1536
+ const spec = importDecl.moduleSpecifier.text;
1537
+ if (spec === "process" || spec === "node:process")
1538
+ return "process";
1539
+ }
1540
+ }
1481
1541
  // An IMPORTED binding of a builtin module's re-exported global
1482
1542
  // (`import { Buffer } from "node:buffer"` — Node's module spelling
1483
1543
  // of the same object) resolves through the alias to the fallback
@@ -1526,27 +1586,50 @@ export function stdlibGlobalMember(lowerer, access, name) {
1526
1586
  * nothing. Only the globals with lowered member surfaces alias this
1527
1587
  * way; aliasing, say, `Math` would change nothing (its members lower
1528
1588
  * by receiver too). Returns true when recognized. */
1529
- export function stdlibGlobalAliasDecl(lowerer, nameNode, init) {
1530
- if (!init || !ts.isIdentifier(nameNode))
1531
- return false;
1589
+ export function stdlibGlobalAliasNameOf(lowerer, init) {
1590
+ if (!init)
1591
+ return null;
1592
+ // CommonJS packages commonly guard Node's always-present globals for
1593
+ // browser bundlers (`let p = process || {}`). In the Node execution
1594
+ // model the left object is unconditionally truthy, so the fallback is
1595
+ // never evaluated and the binding is the same global snapshot as the
1596
+ // direct spelling. Keep this deliberately to `||` with a surfaced
1597
+ // stdlib-global left operand; arbitrary capability probes retain their
1598
+ // runtime value semantics.
1599
+ let aliasExpr = init;
1600
+ while (ts.isParenthesizedExpression(aliasExpr))
1601
+ aliasExpr = aliasExpr.expression;
1602
+ if (ts.isBinaryExpression(aliasExpr) &&
1603
+ aliasExpr.operatorToken.kind === ts.SyntaxKind.BarBarToken &&
1604
+ stdlibGlobalNameOf(lowerer, aliasExpr.left) !== null) {
1605
+ aliasExpr = aliasExpr.left;
1606
+ }
1532
1607
  // `const process = require('node:process')`: Node's process MODULE is
1533
1608
  // the global process object (module.exports === globalThis.process),
1534
1609
  // so the binding aliases the global exactly like `const process =
1535
1610
  // globalThis.process`. Preflight admits exactly this shape
1536
1611
  // (processModuleAliasRequire7); commander's lib/command.js opens with
1537
1612
  // it.
1538
- const requireSpec = requireSpecOf(init);
1613
+ const requireSpec = requireSpecOf(aliasExpr);
1539
1614
  const name = requireSpec === "process" || requireSpec === "node:process"
1540
1615
  ? "process"
1541
- : stdlibGlobalNameOf(lowerer, init);
1616
+ : stdlibGlobalNameOf(lowerer, aliasExpr);
1542
1617
  if (name === null)
1543
- return false;
1618
+ return null;
1544
1619
  // Only alias OBJECT-shaped globals whose members lower by receiver
1545
1620
  // identity (process, console, globalThis itself, and perf_hooks'
1546
1621
  // performance — the mockable-clock idiom snapshots it). Function-valued
1547
1622
  // globals (setTimeout) taken as values are a different story — the
1548
1623
  // ordinary value paths (and their fences) apply.
1549
- if (name !== "process" && name !== "console" && name !== "globalThis" && name !== "performance")
1624
+ return name === "process" || name === "console" || name === "globalThis" || name === "performance"
1625
+ ? name
1626
+ : null;
1627
+ }
1628
+ export function stdlibGlobalAliasDecl(lowerer, nameNode, init) {
1629
+ if (!ts.isIdentifier(nameNode))
1630
+ return false;
1631
+ const name = stdlibGlobalAliasNameOf(lowerer, init);
1632
+ if (name === null)
1550
1633
  return false;
1551
1634
  const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
1552
1635
  if (!symbol)