@scriptc/compiler 0.0.36 → 0.1.2

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 (256) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +52 -22
  2. package/ambient/scriptc-overrides.d.ts +0 -7
  3. package/ambient/scriptc.d.ts +3 -2
  4. package/dist/backend/build-cache.js.map +1 -1
  5. package/dist/backend/c/async.js +24 -2
  6. package/dist/backend/c/async.js.map +1 -1
  7. package/dist/backend/c/c-emitter.d.ts +22 -10
  8. package/dist/backend/c/c-emitter.js +60 -15
  9. package/dist/backend/c/c-emitter.js.map +1 -1
  10. package/dist/backend/c/exprs.js +289 -55
  11. package/dist/backend/c/exprs.js.map +1 -1
  12. package/dist/backend/c/island.js.map +1 -1
  13. package/dist/backend/c/may-throw.js +3 -0
  14. package/dist/backend/c/may-throw.js.map +1 -1
  15. package/dist/backend/c/stmts.d.ts +3 -5
  16. package/dist/backend/c/stmts.js +76 -17
  17. package/dist/backend/c/stmts.js.map +1 -1
  18. package/dist/backend/c/types.js.map +1 -1
  19. package/dist/backend/c/walkers.js +36 -12
  20. package/dist/backend/c/walkers.js.map +1 -1
  21. package/dist/backend/external-c.d.ts +33 -0
  22. package/dist/backend/external-c.js +51 -0
  23. package/dist/backend/external-c.js.map +1 -0
  24. package/dist/backend/link-plan.d.ts +37 -0
  25. package/dist/backend/link-plan.js +26 -0
  26. package/dist/backend/link-plan.js.map +1 -0
  27. package/dist/backend/linker.d.ts +22 -0
  28. package/dist/backend/linker.js +236 -0
  29. package/dist/backend/linker.js.map +1 -0
  30. package/dist/backend/llvm/blocks.js.map +1 -1
  31. package/dist/backend/llvm/dyn.js +63 -3
  32. package/dist/backend/llvm/dyn.js.map +1 -1
  33. package/dist/backend/llvm/emitter.js +132 -26
  34. package/dist/backend/llvm/emitter.js.map +1 -1
  35. package/dist/backend/llvm/expr-async.js +85 -3
  36. package/dist/backend/llvm/expr-async.js.map +1 -1
  37. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  38. package/dist/backend/llvm/expr-calls.js.map +1 -1
  39. package/dist/backend/llvm/expr-containers.js +68 -54
  40. package/dist/backend/llvm/expr-containers.js.map +1 -1
  41. package/dist/backend/llvm/expr-context.d.ts +2 -1
  42. package/dist/backend/llvm/expr-control.js.map +1 -1
  43. package/dist/backend/llvm/expr-dispatch.js +2 -0
  44. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  45. package/dist/backend/llvm/expr-dynamic.js +6 -3
  46. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  47. package/dist/backend/llvm/expr-island.js.map +1 -1
  48. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  49. package/dist/backend/llvm/expr-primitives.js +20 -0
  50. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  51. package/dist/backend/llvm/expr-records.js.map +1 -1
  52. package/dist/backend/llvm/expr-stream-bridges.js +245 -10
  53. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  54. package/dist/backend/llvm/lib-dispatch.js +2 -0
  55. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  56. package/dist/backend/llvm/lib-shared.js +18 -0
  57. package/dist/backend/llvm/lib-shared.js.map +1 -1
  58. package/dist/backend/llvm/lib-stream.js +6 -3
  59. package/dist/backend/llvm/lib-stream.js.map +1 -1
  60. package/dist/backend/llvm/split.js.map +1 -1
  61. package/dist/backend/llvm/unsupported.js.map +1 -1
  62. package/dist/backend/llvm/walkers.js +31 -4
  63. package/dist/backend/llvm/walkers.js.map +1 -1
  64. package/dist/backend/native-codegen.d.ts +8 -1
  65. package/dist/backend/native-codegen.js +39 -25
  66. package/dist/backend/native-codegen.js.map +1 -1
  67. package/dist/backend/native-codegen.test.js +44 -4
  68. package/dist/backend/native-codegen.test.js.map +1 -1
  69. package/dist/backend/native-link-info.d.ts +1 -1
  70. package/dist/backend/native-link-info.js +42 -18
  71. package/dist/backend/native-link-info.js.map +1 -1
  72. package/dist/backend/native-toolchain.js.map +1 -1
  73. package/dist/backend/native-toolchain.test.js +5 -1
  74. package/dist/backend/native-toolchain.test.js.map +1 -1
  75. package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
  76. package/dist/backend/runtime-pack-targets.test.js +54 -0
  77. package/dist/backend/runtime-pack-targets.test.js.map +1 -0
  78. package/dist/backend/runtime-pack.d.ts +5 -30
  79. package/dist/backend/runtime-pack.js +46 -141
  80. package/dist/backend/runtime-pack.js.map +1 -1
  81. package/dist/backend/runtime-pack.test.js +49 -14
  82. package/dist/backend/runtime-pack.test.js.map +1 -1
  83. package/dist/backend/targets.d.ts +63 -17
  84. package/dist/backend/targets.js +251 -35
  85. package/dist/backend/targets.js.map +1 -1
  86. package/dist/backend/targets.test.js +27 -5
  87. package/dist/backend/targets.test.js.map +1 -1
  88. package/dist/backend/vendor-archives.js.map +1 -1
  89. package/dist/compat/fetch-profile.js +4 -2
  90. package/dist/compat/fetch-profile.js.map +1 -1
  91. package/dist/coverage/report.js.map +1 -1
  92. package/dist/coverage/surface-manifest.js +22 -1
  93. package/dist/coverage/surface-manifest.js.map +1 -1
  94. package/dist/diagnostics/diagnostic.d.ts +6 -5
  95. package/dist/diagnostics/diagnostic.js +7 -6
  96. package/dist/diagnostics/diagnostic.js.map +1 -1
  97. package/dist/diagnostics/render.js.map +1 -1
  98. package/dist/ffi/ffi-manifest.js.map +1 -1
  99. package/dist/frontend/cjs-lexer.js.map +1 -1
  100. package/dist/frontend/dts-paths.js.map +1 -1
  101. package/dist/frontend/input-tracker.d.ts +10 -0
  102. package/dist/frontend/input-tracker.js +26 -3
  103. package/dist/frontend/input-tracker.js.map +1 -1
  104. package/dist/frontend/input-tracker.test.js +8 -1
  105. package/dist/frontend/input-tracker.test.js.map +1 -1
  106. package/dist/frontend/lib-contract.js.map +1 -1
  107. package/dist/frontend/lowering/array-values.d.ts +12 -0
  108. package/dist/frontend/lowering/array-values.js +76 -0
  109. package/dist/frontend/lowering/array-values.js.map +1 -0
  110. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  111. package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
  112. package/dist/frontend/lowering/containers/bytes.js +1021 -0
  113. package/dist/frontend/lowering/containers/bytes.js.map +1 -0
  114. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
  115. package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
  116. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
  117. package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
  118. package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
  119. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
  120. package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
  121. package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
  122. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
  123. package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
  124. package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
  125. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
  126. package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
  127. package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
  128. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
  129. package/dist/frontend/lowering/lib-boundary.js +7 -2
  130. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  131. package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
  132. package/dist/frontend/lowering/lower-array-sort.js +619 -0
  133. package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
  134. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  135. package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
  136. package/dist/frontend/lowering/lower-async-iteration.js +657 -0
  137. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
  138. package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
  139. package/dist/frontend/lowering/lower-builtins.js +379 -48
  140. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  141. package/dist/frontend/lowering/lower-calls.d.ts +16 -8
  142. package/dist/frontend/lowering/lower-calls.js +667 -91
  143. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  144. package/dist/frontend/lowering/lower-classes.d.ts +7 -13
  145. package/dist/frontend/lowering/lower-classes.js +128 -35
  146. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  147. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  148. package/dist/frontend/lowering/lower-containers.d.ts +1 -47
  149. package/dist/frontend/lowering/lower-containers.js +779 -2038
  150. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  151. package/dist/frontend/lowering/lower-event-emitter.js +51 -5
  152. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  153. package/dist/frontend/lowering/lower-exprs.d.ts +4 -78
  154. package/dist/frontend/lowering/lower-exprs.js +1128 -2409
  155. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  156. package/dist/frontend/lowering/lower-generators.d.ts +18 -3
  157. package/dist/frontend/lowering/lower-generators.js +145 -9
  158. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  159. package/dist/frontend/lowering/lower-inspect.js +50 -36
  160. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  161. package/dist/frontend/lowering/lower-island.d.ts +11 -4
  162. package/dist/frontend/lowering/lower-island.js +47 -10
  163. package/dist/frontend/lowering/lower-island.js.map +1 -1
  164. package/dist/frontend/lowering/lower-modules.js +52 -15
  165. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  166. package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
  167. package/dist/frontend/lowering/lower-node-module.js +302 -0
  168. package/dist/frontend/lowering/lower-node-module.js.map +1 -0
  169. package/dist/frontend/lowering/lower-server.js +11 -1
  170. package/dist/frontend/lowering/lower-server.js.map +1 -1
  171. package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
  172. package/dist/frontend/lowering/lower-stmts.js +811 -314
  173. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  174. package/dist/frontend/lowering/lower-stream.js +4 -4
  175. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  176. package/dist/frontend/lowering/lowerer.d.ts +109 -34
  177. package/dist/frontend/lowering/lowerer.js +1225 -62
  178. package/dist/frontend/lowering/lowerer.js.map +1 -1
  179. package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
  180. package/dist/frontend/lowering/optional-arguments.js +57 -0
  181. package/dist/frontend/lowering/optional-arguments.js.map +1 -0
  182. package/dist/frontend/lowering/surfaces.d.ts +10 -2
  183. package/dist/frontend/lowering/surfaces.js +15 -3
  184. package/dist/frontend/lowering/surfaces.js.map +1 -1
  185. package/dist/frontend/npm-static-declarations.d.ts +35 -0
  186. package/dist/frontend/npm-static-declarations.js +506 -0
  187. package/dist/frontend/npm-static-declarations.js.map +1 -0
  188. package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
  189. package/dist/frontend/npm-static-declarations.test.js +122 -0
  190. package/dist/frontend/npm-static-declarations.test.js.map +1 -0
  191. package/dist/frontend/npm-static.d.ts +2 -0
  192. package/dist/frontend/npm-static.js +26 -10
  193. package/dist/frontend/npm-static.js.map +1 -1
  194. package/dist/frontend/npm.d.ts +60 -0
  195. package/dist/frontend/npm.js +38 -4
  196. package/dist/frontend/npm.js.map +1 -1
  197. package/dist/frontend/npm.test.d.ts +1 -0
  198. package/dist/frontend/npm.test.js +50 -0
  199. package/dist/frontend/npm.test.js.map +1 -0
  200. package/dist/frontend/program.d.ts +3 -2
  201. package/dist/frontend/program.js +495 -68
  202. package/dist/frontend/program.js.map +1 -1
  203. package/dist/frontend/resolve.d.ts +10 -2
  204. package/dist/frontend/resolve.js +90 -14
  205. package/dist/frontend/resolve.js.map +1 -1
  206. package/dist/frontend/resolve.test.js +4 -1
  207. package/dist/frontend/resolve.test.js.map +1 -1
  208. package/dist/frontend/runtime-resolve.d.ts +22 -0
  209. package/dist/frontend/runtime-resolve.js +101 -0
  210. package/dist/frontend/runtime-resolve.js.map +1 -0
  211. package/dist/frontend/runtime-resolve.test.d.ts +1 -0
  212. package/dist/frontend/runtime-resolve.test.js +18 -0
  213. package/dist/frontend/runtime-resolve.test.js.map +1 -0
  214. package/dist/frontend/ts7/adapter.js +12 -13
  215. package/dist/frontend/ts7/adapter.js.map +1 -1
  216. package/dist/frontend/ts7/ast.js.map +1 -1
  217. package/dist/frontend/ts7/census-check.js +3 -3
  218. package/dist/frontend/ts7/census-check.js.map +1 -1
  219. package/dist/frontend/ts7/checker.d.ts +3 -0
  220. package/dist/frontend/ts7/checker.js +12 -3
  221. package/dist/frontend/ts7/checker.js.map +1 -1
  222. package/dist/frontend/ts7/enums.js.map +1 -1
  223. package/dist/frontend/ts7/program-adapter.js +42 -3
  224. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  225. package/dist/frontend/type-mapper.js +120 -7
  226. package/dist/frontend/type-mapper.js.map +1 -1
  227. package/dist/index.d.ts +3 -3
  228. package/dist/index.js +50 -28
  229. package/dist/index.js.map +1 -1
  230. package/dist/ir/analysis.js.map +1 -1
  231. package/dist/ir/ir.d.ts +125 -41
  232. package/dist/ir/ir.js +82 -31
  233. package/dist/ir/ir.js.map +1 -1
  234. package/dist/ir/serialize.d.ts +1 -1
  235. package/dist/ir/serialize.js +1 -1
  236. package/dist/ir/validate.js +127 -95
  237. package/dist/ir/validate.js.map +1 -1
  238. package/dist/library/cache-primitives.js.map +1 -1
  239. package/dist/library/cache-reset.test.js.map +1 -1
  240. package/dist/library/compiler-self-identity.js.map +1 -1
  241. package/dist/library/fence-eval.js +3 -1
  242. package/dist/library/fence-eval.js.map +1 -1
  243. package/dist/library/int-infer.js +12 -1
  244. package/dist/library/int-infer.js.map +1 -1
  245. package/dist/library/int-infer.test.js +4 -4
  246. package/dist/library/int-infer.test.js.map +1 -1
  247. package/dist/library/library-cache.test.js +5 -5
  248. package/dist/library/library-profile.js.map +1 -1
  249. package/dist/library/sidecar-validate.js.map +1 -1
  250. package/dist/library/sidecar.js.map +1 -1
  251. package/dist/startup-cache.d.ts +9 -1
  252. package/dist/startup-cache.js +16 -1
  253. package/dist/startup-cache.js.map +1 -1
  254. package/dist/wasi-paths.js.map +1 -1
  255. package/package.json +18 -5
  256. package/surface-manifest.json +64 -8
package/dist/ir/ir.d.ts CHANGED
@@ -359,6 +359,7 @@ export type IrType = {
359
359
  * array elements, and JSON. */
360
360
  | {
361
361
  kind: "generator";
362
+ async?: true;
362
363
  yieldT: IrType;
363
364
  retT: IrType;
364
365
  nextT: IrType;
@@ -389,11 +390,11 @@ interface IrKindSet<K extends IrType["kind"]> extends ReadonlySet<IrType["kind"]
389
390
  * every other handle has pointer representation. */
390
391
  declare const HANDLE_KIND_LIST: readonly ["stats", "fileHandle", "spawnRes", "child", "netServer", "netSocket", "http2Session", "http2Stream", "dgramSocket", "testCtx", "httpReq", "httpRes", "httpClientReq", "secureCtx", "fsWatcher", "childStream", "procStream"];
391
392
  export type HandleKind = typeof HANDLE_KIND_LIST[number];
392
- export declare const HANDLE_KINDS: IrKindSet<"fileHandle" | "stats" | "spawnRes" | "child" | "netServer" | "netSocket" | "http2Session" | "http2Stream" | "dgramSocket" | "testCtx" | "httpReq" | "httpRes" | "httpClientReq" | "childStream" | "procStream" | "fsWatcher" | "secureCtx">;
393
+ export declare const HANDLE_KINDS: IrKindSet<"child" | "childStream" | "dgramSocket" | "fileHandle" | "fsWatcher" | "http2Session" | "http2Stream" | "httpClientReq" | "httpReq" | "httpRes" | "netServer" | "netSocket" | "procStream" | "secureCtx" | "spawnRes" | "stats" | "testCtx">;
393
394
  /** The IR kinds represented as pointers in both native backends. */
394
395
  declare const POINTER_KIND_LIST: readonly ["string", "array", "map", "set", "regex", "bytes", "url", "searchParams", "symbol", "stats", "fileHandle", "spawnRes", "child", "netServer", "netSocket", "http2Session", "http2Stream", "dgramSocket", "testCtx", "httpReq", "httpRes", "httpClientReq", "secureCtx", "fsWatcher", "childStream", "func", "object", "classval", "record", "union", "dyn", "jsval", "caught", "promise", "generator"];
395
396
  export type PointerKind = typeof POINTER_KIND_LIST[number];
396
- export declare const POINTER_KINDS: IrKindSet<"string" | "symbol" | "object" | "map" | "bytes" | "regex" | "fileHandle" | "searchParams" | "array" | "set" | "url" | "stats" | "spawnRes" | "child" | "netServer" | "netSocket" | "http2Session" | "http2Stream" | "dgramSocket" | "testCtx" | "httpReq" | "httpRes" | "httpClientReq" | "childStream" | "fsWatcher" | "secureCtx" | "func" | "jsval" | "classval" | "record" | "union" | "dyn" | "caught" | "promise" | "generator">;
397
+ export declare const POINTER_KINDS: IrKindSet<"array" | "bytes" | "caught" | "child" | "childStream" | "classval" | "dgramSocket" | "dyn" | "fileHandle" | "fsWatcher" | "func" | "generator" | "http2Session" | "http2Stream" | "httpClientReq" | "httpReq" | "httpRes" | "jsval" | "map" | "netServer" | "netSocket" | "object" | "promise" | "record" | "regex" | "searchParams" | "secureCtx" | "set" | "spawnRes" | "stats" | "string" | "symbol" | "testCtx" | "union" | "url">;
397
398
  /** Runtime RC symbol stem for each IR type kind. An empty stem means the
398
399
  * kind is scalar/unit or uses an emitted per-shape helper (object/record).
399
400
  * Keeping this exhaustive makes a new runtime handle kind a compile error
@@ -519,7 +520,7 @@ export declare function typeEquals(a: IrType, b: IrType): boolean;
519
520
  export declare function isRefCounted(t: IrType): boolean;
520
521
  export interface IrModule {
521
522
  /** Bumped on any breaking IR change; serialize.ts refuses mismatches. */
522
- irVersion: 6;
523
+ irVersion: 8;
523
524
  sourceFile: string;
524
525
  functions: IrFunction[];
525
526
  /** Class shapes. Constructors and methods are ordinary module functions
@@ -945,7 +946,9 @@ export interface IrFunction {
945
946
  * Each is also listed in `locals` (with boxed: true); it is NOT a param. */
946
947
  captures?: IrParam[];
947
948
  /** Async: the body runs on a fiber; `returnType` is the INNER type T (a
948
- * `return v` fulfills with v) while call sites receive Promise<T>. */
949
+ * `return v` fulfills with v) while ordinary call sites receive
950
+ * Promise<T>. With `generator` present, call sites receive the lazy
951
+ * async-generator object instead. */
949
952
  async?: true;
950
953
  /** Async module initializers only: a module-global Promise<T> slot where
951
954
  * the spawn wrapper caches its first evaluation promise. Every later
@@ -958,17 +961,21 @@ export interface IrFunction {
958
961
  * becomes the runtime cycle root. Dynamic imports wait on this shared
959
962
  * completion verdict instead of a build-time-selected member. */
960
963
  asyncCycleCacheGlobal?: string;
961
- /** Generator (`function*`): the body runs on a fiber created SUSPENDED
964
+ /** Generator (`function*` / `async function*`): the body runs on a fiber created SUSPENDED
962
965
  * (nothing runs until the first `.next()`); `returnType` is the
963
966
  * generator's TReturn (VOID when it carries no value — `return;`
964
967
  * completes with the undefined arm) while call sites receive the
965
- * generator type `{ yieldT, retT: returnType, nextT }` from an emitted
968
+ * generator type `{ async?, yieldT, retT: returnType, nextT }` from an emitted
966
969
  * spawn wrapper that only allocates. `yieldT` is what `yield e` sends
967
970
  * out, `nextT` what `.next(v)` sends in (the yield expression's result
968
- * type). Mutually exclusive with `async` (async generators are fenced). */
971
+ * type). `async` alongside this field marks an async generator: its
972
+ * resume methods queue requests and return promises. */
969
973
  generator?: {
970
974
  yieldT: IrType;
971
975
  nextT: IrType;
976
+ resultType: IrType & {
977
+ kind: "record";
978
+ };
972
979
  };
973
980
  body: IrStmt[];
974
981
  loc: SrcLoc;
@@ -1089,9 +1096,9 @@ export type IrStmt =
1089
1096
  loc: SrcLoc;
1090
1097
  }
1091
1098
  /** Element write `a[i] = v` — statement-only, like `assign`. Valid indices
1092
- * are [0, length]; i == length appends (JS would create a hole past that —
1093
- * scriptc traps instead, see SEMANTICS.md). Ownership of a refcounted
1094
- * value MOVES into the array; the replaced element is released. */
1099
+ * are canonical array indices; writes beyond length grow the array and
1100
+ * leave the intervening positions as holes. Ownership of a refcounted value
1101
+ * MOVES into the array; the replaced element is released. */
1095
1102
  | {
1096
1103
  kind: "arraySet";
1097
1104
  arr: IrExpr;
@@ -1099,6 +1106,29 @@ export type IrStmt =
1099
1106
  value: IrExpr;
1100
1107
  loc: SrcLoc;
1101
1108
  }
1109
+ /** Writable `a.length = n`: growth creates holes and truncation releases
1110
+ * removed reference elements. Invalid array lengths raise a catchable
1111
+ * RangeError from the runtime. */
1112
+ | {
1113
+ kind: "arraySetLength";
1114
+ arr: IrExpr;
1115
+ length: IrExpr;
1116
+ loc: SrcLoc;
1117
+ }
1118
+ /** Write an explicit present `undefined` state without shrinking length. */
1119
+ | {
1120
+ kind: "arraySetUndefined";
1121
+ arr: IrExpr;
1122
+ index: IrExpr;
1123
+ loc: SrcLoc;
1124
+ }
1125
+ /** Delete an indexed/property slot without changing Array.length. */
1126
+ | {
1127
+ kind: "arrayDelete";
1128
+ arr: IrExpr;
1129
+ index: IrExpr;
1130
+ loc: SrcLoc;
1131
+ }
1102
1132
  /** Typed-array element write `b[i] = v` — arraySet's sibling for bytes
1103
1133
  * receivers: statement-only, receiver and index like bytesIntrinsic
1104
1134
  * `get` (any invalid index TRAPS — JS would ignore the write, a
@@ -1260,23 +1290,19 @@ export type IrStmt =
1260
1290
  * completion AND on the exception path (after catch, or with the
1261
1291
  * exception still pending when there is no catch — it keeps propagating
1262
1292
  * after the finally completes; a throw inside the finally replaces it).
1263
- * A `return` inside tryBody/catchBody additionally runs the finally on
1264
- * its way out (the backend's PENDING-RETURN path: the value is computed
1265
- * and snapshotted FIRST, every crossed finally runs inner-to-outer, then
1266
- * the function returns — finally mutations of returned locals are
1267
- * invisible, Node-exact; a throw inside such a finally replaces the
1268
- * pending return, releasing the snapshot). The frontend still rejects
1269
- * break/continue crossing a try-with-finally and ANY jump out of a
1270
- * finally body, so normal, exception, and pending-return are the only
1271
- * completions a finally sees; plain try/catch has no such restriction
1272
- * (jumps out release the try scopes like any other jump). Each body is
1273
- * its own lexical scope. */
1293
+ * Every abrupt completion crossing the region runs the finally
1294
+ * inner-to-outer. Return values are snapshotted first; break/continue
1295
+ * retain their resolved targets; and a completion raised inside the
1296
+ * finally replaces the pending one. Each body is its own lexical scope. */
1274
1297
  | {
1275
1298
  kind: "tryCatch";
1276
1299
  tryBody: IrStmt[];
1277
1300
  catchBody: IrStmt[] | null;
1278
1301
  catchLocalId: string | null;
1279
1302
  finallyBody: IrStmt[] | null;
1303
+ /** Resource-management cleanup: if the guarded body and cleanup both
1304
+ * throw, raise a SuppressedError instead of replacing the first error. */
1305
+ suppressFinallyErrors?: true;
1280
1306
  loc: SrcLoc;
1281
1307
  };
1282
1308
  /** The complete array method/property surface (mirrors ambient/scriptc.d.ts).
@@ -1286,12 +1312,19 @@ export type IrStmt =
1286
1312
  * from the end, clamping; omitted args omitted from `args` — backends fill
1287
1313
  * 0 / +Infinity, the strIntrinsic convention); ref elements retain into
1288
1314
  * the fresh array. */
1289
- export type IrArrIntrinsicMethod = "length" | "push" | "pushSpread" | "unshift" | "unshiftSpread" | "pop" | "indexOf" | "includes" | "join" | "slice" | "shift" | "splice" | "reverse"
1315
+ export type IrArrIntrinsicMethod = "length" | "push" | "pushSpread" | "concatSpread" | "unshift" | "unshiftSpread" | "pop" | "indexOf" | "includes"
1316
+ /** Internal sparse traversal: the first present index at/after start,
1317
+ * or length when the remaining positions are holes. */
1318
+ | "nextPresent" | "join" | "slice" | "shift" | "splice" | "reverse"
1290
1319
  /** ES2023 copying methods. `toSpliced` receives [start, deleteCount,
1291
1320
  * itemsArray], with omitted arguments completed by the frontend;
1292
1321
  * `with` receives [index, value] and throws Node's catchable RangeError
1293
1322
  * when the relative index is out of range. */
1294
- | "toReversed" | "toSpliced" | "with";
1323
+ | "toReversed" | "toSpliced"
1324
+ /** `.with()` replacement carrying present undefined while retaining the
1325
+ * scalar array payload ABI; it has the same catchable index validation as
1326
+ * the typed replacement forms. */
1327
+ | "withUndefined" | "with";
1295
1328
  /** Array intrinsics whose runtime implementation can raise a catchable
1296
1329
  * exception (rather than the static tier's deliberate index traps). */
1297
1330
  export declare const MAY_THROW_ARR_METHODS: ReadonlySet<IrArrIntrinsicMethod>;
@@ -1548,7 +1581,11 @@ export type IrLibFn =
1548
1581
  * (bytes decode per the literal encoding — utf8 default; strings,
1549
1582
  * numbers, booleans, arrays, objects answer JS-exactly; undefined and
1550
1583
  * null throw the catchable TypeError). */
1551
- | "dyn.toString" | "fs.readFileSync"
1584
+ | "dyn.toString"
1585
+ /** Engine-free CommonJS module graph. Module values are scalar f64
1586
+ * handles; generated startup defines the registry, init wrappers update
1587
+ * loading/cache state, and the read surface answers Node's live metadata. */
1588
+ | "module.registryInit" | "module.define" | "module.enter" | "module.link" | "module.finish" | "module.fail" | "module.filename" | "module.id" | "module.path" | "module.paths" | "module.children" | "module.parent" | "module.loaded" | "module.cacheGet" | "module.cacheHas" | "module.cacheKeys" | "fs.readFileSync"
1552
1589
  /** readFileSync(path) — the Buffer read (+1 bytes); throws catchably
1553
1590
  * like the utf8 form. */
1554
1591
  | "fs.readFileSyncBuf"
@@ -2825,7 +2862,11 @@ export type IrLibFn =
2825
2862
  * error. The Dyn twin boxes chunks by runtime tag (the JS lane).
2826
2863
  * readable.fromArr is Readable.from(array): a fully-seeded object-
2827
2864
  * entry stream (one whole chunk per element; strings per the flag). */
2828
- | "readable.nextChunk" | "readable.nextChunkDyn" | "readable.fromArr" | "readable.isPaused" | "readable.pipe" | "readable.unpipe" | "readable.flowing" | "writable.write" | "writable.writeStr" | "writable.writeU" | "writable.writeDyn" | "writable.end" | "writable.cork" | "writable.uncork" | "stream.destroy" | "stream.destroyErr" | "stream.prop" | "stream.errored"
2865
+ | "readable.nextChunk" | "readable.nextChunkDyn" | "readable.fromArr" | "readable.isPaused" | "readable.pipe" | "readable.unpipe" | "readable.flowing" | "writable.write" | "writable.writeStr" | "writable.writeU" | "writable.writeDyn" | "writable.end" | "writable.cork" | "writable.uncork" | "stream.destroy" | "stream.destroyErr"
2866
+ /** AsyncIteratorClose for Readable[Symbol.asyncIterator](): destroy with
2867
+ * Node's AbortError/ABORT_ERR payload while the iterator's internal error
2868
+ * consumer prevents an unhandled-error crash. */
2869
+ | "stream.iteratorClose" | "stream.prop" | "stream.errored"
2829
2870
  /** The underscore-method assignment surface (`r._read = fn` after
2830
2871
  * construction — Node's own-property shadow of the prototype method):
2831
2872
  * args [stream receiver (borrowed), callback closure (+1 moves)]. The
@@ -3593,9 +3634,9 @@ export type IrExpr =
3593
3634
  type: IrType;
3594
3635
  loc: SrcLoc;
3595
3636
  }
3596
- /** Element read `a[i]`. Index is f64; a non-integer or out-of-bounds index
3597
- * traps at runtime (JS returns undefined — documented divergence). For
3598
- * refcounted elements the result is a fresh owned (+1) reference. */
3637
+ /** Element read `a[i]`. Index is f64; the low-level accessors require a
3638
+ * proven present slot and trap on a hole. For refcounted elements the result
3639
+ * is a fresh owned (+1) reference. */
3599
3640
  | {
3600
3641
  kind: "arrayGet";
3601
3642
  arr: IrExpr;
@@ -3603,6 +3644,25 @@ export type IrExpr =
3603
3644
  type: IrType;
3604
3645
  loc: SrcLoc;
3605
3646
  }
3647
+ /** Presence query for an array index. Invalid/non-index keys and holes
3648
+ * answer false without reading the slot; present undefined answers true.
3649
+ * The ordinary-read lowering must use arrayState before selecting its
3650
+ * undefined arm. */
3651
+ | {
3652
+ kind: "arrayHas";
3653
+ arr: IrExpr;
3654
+ index: IrExpr;
3655
+ type: IrType;
3656
+ loc: SrcLoc;
3657
+ }
3658
+ /** Array slot state as f64: HOLE=0, VALUE=1, UNDEFINED=2. */
3659
+ | {
3660
+ kind: "arrayState";
3661
+ arr: IrExpr;
3662
+ index: IrExpr;
3663
+ type: IrType;
3664
+ loc: SrcLoc;
3665
+ }
3606
3666
  /** Array method/property on an array receiver: `length` (f64), `push`
3607
3667
  * (VARIADIC like JS — zero or more elem-typed args; every argument
3608
3668
  * evaluates before any appends, then each appends in order; returns the
@@ -3613,8 +3673,8 @@ export type IrExpr =
3613
3673
  * exactly like JS; returns the new length), `unshift` (the matching
3614
3674
  * variadic front insertion; all arguments evaluate before mutation and
3615
3675
  * ref ownership moves in), `unshiftSpread` (one borrowed same-typed array,
3616
- * with self-spread snapshot semantics), `pop` (returns elem — traps on an
3617
- * empty array; ownership moves OUT to the caller), `indexOf` (one
3676
+ * with self-spread snapshot semantics), `pop` (returns `elem | undefined`
3677
+ * and leaves an empty array unchanged; ownership moves OUT to the caller), `indexOf` (one
3618
3678
  * elem-typed arg, BORROWED; strict equality — NaN never matches; → f64),
3619
3679
  * `includes` (one elem-typed arg, borrowed; SameValueZero — NaN DOES
3620
3680
  * match; → bool), `join` (one string arg, borrowed; f64/bool/string
@@ -3810,6 +3870,7 @@ export type IrExpr =
3810
3870
  | {
3811
3871
  kind: "yieldExpr";
3812
3872
  value: IrExpr | null;
3873
+ awaited?: true;
3813
3874
  type: IrType;
3814
3875
  loc: SrcLoc;
3815
3876
  }
@@ -3828,8 +3889,9 @@ export type IrExpr =
3828
3889
  * unless suspended (then the GENRET unwind runs finallys; a finally
3829
3890
  * yield answers done:false and parks the return value) / throw on a
3830
3891
  * non-suspended generator marks it done and re-throws at the call site.
3831
- * MAY-THROW SEED: a body exception (or the injected throw) propagates
3832
- * into the caller synchronously. */
3892
+ * Sync generators return that record directly and propagate body errors
3893
+ * synchronously. Async generators return Promise<record>; requests queue,
3894
+ * and body errors reject the corresponding promise. */
3833
3895
  | {
3834
3896
  kind: "genResume";
3835
3897
  mode: "next" | "return" | "throw";
@@ -4109,12 +4171,13 @@ export type IrExpr =
4109
4171
  * TypeError), the interned signature key (dynCheck's exact-unwrap fast
4110
4172
  * path), and `fnName` — the best-effort static spelling for inspect
4111
4173
  * ([Function: name]) and Node-shaped call errors. The operand is
4112
- * borrowed; the result is owned (+1). Never throws. `liveRef` is the
4113
- * narrow Web-platform exception for record/array/bytes values (including
4114
- * mutable arms selected at runtime from a union) whose API contract
4115
- * exposes the same reference again (stream chunks and abort reasons): it
4116
- * emits a typed capsule with a live materializer instead of the ordinary
4117
- * deep copy. */
4174
+ * borrowed; the result is owned (+1). Never throws. Program class
4175
+ * instances always use a typed capsule so an exact checked cast recovers
4176
+ * the original identity. `liveRef` requests the same capsule form for
4177
+ * record/array/bytes values (including mutable arms selected at runtime
4178
+ * from a union) whose Web API contract exposes the reference again, such
4179
+ * as stream chunks and abort reasons; ordinary JSON-shaped values retain
4180
+ * the documented deep-copy boundary. */
4118
4181
  | {
4119
4182
  kind: "dynFrom";
4120
4183
  value: IrExpr;
@@ -4817,6 +4880,11 @@ export declare function isUndefinedArmedUnion(t: IrType, getUnion: (unionId: str
4817
4880
  * every reachable constituent is; a cyclic VALUE of such a type throws
4818
4881
  * Node's circular-structure TypeError at runtime instead. */
4819
4882
  export declare function isJsonSafeType(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4883
+ /** The JSON.stringify-only domain additionally admits undefined arms in
4884
+ * array and tuple positions, where Node emits null. A bare undefined-armed
4885
+ * root remains outside the domain because JSON.stringify returns the
4886
+ * undefined value instead of a string. */
4887
+ export declare function isJsonStringifySafeType(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4820
4888
  /** THE island boundary predicate: true when a static type can cross into
4821
4889
  * the island (jsMarshal — primitives by value, composites as deep JSON
4822
4890
  * copies) and back out (jsExit — strict primitive extraction, composites
@@ -4881,10 +4949,22 @@ export declare const DYN_HANDLE_KINDS: ReadonlyMap<string, {
4881
4949
  tag: string;
4882
4950
  cls: string;
4883
4951
  }>;
4952
+ /** A class value that crosses an `unknown` slot as a compiler-owned typed
4953
+ * reference. %Error keeps its dedicated error encoding; every other class
4954
+ * preserves the original object identity and exposes a materialized own-field
4955
+ * view only when a checked-dynamic operation actually needs one. */
4956
+ export declare function isDynTypedRefType(t: IrType): t is Extract<IrType, {
4957
+ kind: "object";
4958
+ }>;
4959
+ /** Whether a class layout field is an ECMAScript own enumerable property.
4960
+ * `#private` slots and `%`-prefixed compiler storage exist only in the native
4961
+ * layout; TypeScript `private`/`protected` fields keep ordinary names and are
4962
+ * observable properties at runtime. */
4963
+ export declare function isClassOwnEnumerableFieldName(name: string): boolean;
4884
4964
  /** A static type that CONVERTS into a dyn value — the dynFrom domain:
4885
- * JSON-safe data, bytes<u8> (payload copied), undefined-armed unions of
4886
- * JSON-safe arms, boxable function types, and the runtime HANDLE kinds
4887
- * (boxed by reference — DYN_HANDLE_KINDS). */
4965
+ * JSON-safe data, bytes<u8> (payload copied), identity-preserving class
4966
+ * references, undefined-armed unions of those arms, boxable function types,
4967
+ * and the runtime HANDLE kinds (boxed by reference — DYN_HANDLE_KINDS). */
4888
4968
  export declare function canConvertToDyn(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4889
4969
  /** A type a dyn value can be VALIDATED into — the dynCheck domain:
4890
4970
  * JSON-safe data, bytes<u8> (a fresh copy out), the %Error extraction,
@@ -5026,6 +5106,10 @@ export declare function moduleUsesDynInvoke(mod: IrModule): boolean;
5026
5106
  * walk shape as moduleUsesZlib. */
5027
5107
  export declare function moduleUsesDynAsync(mod: IrModule): boolean;
5028
5108
  export declare function moduleUsesInspect(mod: IrModule): boolean;
5109
+ /** True when the module reaches child_process or carries one of its runtime
5110
+ * handle/result types. Besides the existing link consequence, this gates the
5111
+ * checked-dynamic ChildProcess handle table installed from scr_child.c. */
5112
+ export declare function moduleUsesChildProcess(mod: IrModule): boolean;
5029
5113
  /** True when the module contains any net libCall — the link switch that
5030
5114
  * pulls scr_net.c into the binary and has the emitted main call
5031
5115
  * scr_net_install (native-toolchain.ts + emitter; the scr_events gating precedent).
package/dist/ir/ir.js CHANGED
@@ -366,7 +366,7 @@ export function typeKey(t) {
366
366
  case "promise":
367
367
  return `promise<${typeKey(t.inner)}>`;
368
368
  case "generator":
369
- return `generator<${typeKey(t.yieldT)},${typeKey(t.retT)},${typeKey(t.nextT)}>`;
369
+ return `${t.async ? "async-generator" : "generator"}<${typeKey(t.yieldT)},${typeKey(t.retT)},${typeKey(t.nextT)}>`;
370
370
  default: {
371
371
  const _exhaustive = t;
372
372
  void _exhaustive;
@@ -406,6 +406,7 @@ export function typeEquals(a, b) {
406
406
  return b.kind === "promise" && typeEquals(a.inner, b.inner);
407
407
  if (a.kind === "generator") {
408
408
  return (b.kind === "generator" &&
409
+ (a.async === true) === (b.async === true) &&
409
410
  typeEquals(a.yieldT, b.yieldT) &&
410
411
  typeEquals(a.retT, b.retT) &&
411
412
  typeEquals(a.nextT, b.nextT));
@@ -548,6 +549,7 @@ export function shapeHasAccessorSlots(shape) {
548
549
  * exception (rather than the static tier's deliberate index traps). */
549
550
  export const MAY_THROW_ARR_METHODS = new Set([
550
551
  "with",
552
+ "withUndefined",
551
553
  ]);
552
554
  /** The bytesIntrinsic methods that can raise a catchable error — backends'
553
555
  * may-throw analyses seed on these exactly like MAY_THROW_LIB_FNS. */
@@ -667,17 +669,19 @@ export function isUndefinedArmedUnion(t, getUnion) {
667
669
  * every reachable constituent is; a cyclic VALUE of such a type throws
668
670
  * Node's circular-structure TypeError at runtime instead. */
669
671
  export function isJsonSafeType(t, getRecord, getUnion) {
670
- return isJsonSafeAt(t, getRecord, getUnion, false, new Set());
671
- }
672
- /** The recursion behind isJsonSafeType. `inRecordField` is the ONE position
673
- * where an undefined arm is JSON-representable: an undefined-armed union as
674
- * a record field (the `a?: T` spelling) serializes by DROPPING the field
675
- * when it holds undefined and validates a MISSING key as the undefined arm
676
- * — both exactly Node. Everywhere else (a bare `T | undefined` value,
677
- * stringified whole or cast to) exactness is unreachable: Node's stringify
678
- * of bare undefined is not a string at all, and JSON text can never contain
679
- * a value that matches the arm. */
680
- function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
672
+ return isJsonSafeAt(t, getRecord, getUnion, false, false, new Set());
673
+ }
674
+ /** The JSON.stringify-only domain additionally admits undefined arms in
675
+ * array and tuple positions, where Node emits null. A bare undefined-armed
676
+ * root remains outside the domain because JSON.stringify returns the
677
+ * undefined value instead of a string. */
678
+ export function isJsonStringifySafeType(t, getRecord, getUnion) {
679
+ return isJsonSafeAt(t, getRecord, getUnion, true, false, new Set());
680
+ }
681
+ /** The recursion shared by checked JSON conversion and stringification.
682
+ * Ordinary record fields always admit undefined by dropping the key. Array
683
+ * and tuple slots admit it only for stringification, which writes null. */
684
+ function isJsonSafeAt(t, getRecord, getUnion, stringify, undefinedAllowed, visiting) {
681
685
  if (HANDLE_KINDS.has(t.kind))
682
686
  return false;
683
687
  switch (t.kind) {
@@ -686,7 +690,7 @@ function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
686
690
  case "bool":
687
691
  return true;
688
692
  case "array":
689
- return isJsonSafeAt(t.elem, getRecord, getUnion, false, visiting);
693
+ return isJsonSafeAt(t.elem, getRecord, getUnion, stringify, stringify, visiting);
690
694
  case "record": {
691
695
  const shape = getRecord(t.shapeId);
692
696
  if (!shape)
@@ -697,10 +701,7 @@ function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
697
701
  if (visiting.has(t.shapeId))
698
702
  return true;
699
703
  visiting.add(t.shapeId);
700
- // TUPLE positions are array slots, not droppable object keys: an
701
- // undefined-armed position would stringify as `null` in JS (not
702
- // drop), so tuples keep the array rule for their fields.
703
- if (!shape.fields.every((f) => isJsonSafeAt(f.type, getRecord, getUnion, !shape.tuple, visiting))) {
704
+ if (!shape.fields.every((f) => isJsonSafeAt(f.type, getRecord, getUnion, stringify, !shape.tuple || stringify, visiting))) {
704
705
  return false;
705
706
  }
706
707
  // Overflow values sit in record-key position too: dyn is JSON-safe
@@ -708,7 +709,7 @@ function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
708
709
  // like any undefined-valued key), everything else follows the
709
710
  // record-field rule.
710
711
  if (shape.indexValue && shape.indexValue.kind !== "dyn") {
711
- return isJsonSafeAt(shape.indexValue, getRecord, getUnion, true, visiting);
712
+ return isJsonSafeAt(shape.indexValue, getRecord, getUnion, stringify, true, visiting);
712
713
  }
713
714
  return true;
714
715
  }
@@ -716,11 +717,11 @@ function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
716
717
  const def = getUnion(t.unionId);
717
718
  if (!def)
718
719
  return false;
719
- const key = `${t.unionId}:${inRecordField}`;
720
+ const key = `${t.unionId}:${stringify}:${undefinedAllowed}`;
720
721
  if (visiting.has(key))
721
722
  return true; // the recursive knot, union-flavored
722
723
  visiting.add(key);
723
- return def.arms.every((a) => isJsonSafeAt(a, getRecord, getUnion, inRecordField, visiting));
724
+ return def.arms.every((a) => a.kind === "undefinedT" ? undefinedAllowed : isJsonSafeAt(a, getRecord, getUnion, stringify, undefinedAllowed, visiting));
724
725
  }
725
726
  case "func":
726
727
  case "object":
@@ -756,12 +757,10 @@ function isJsonSafeAt(t, getRecord, getUnion, inRecordField, visiting) {
756
757
  case "generator":
757
758
  case "void":
758
759
  return false;
759
- // Representable exactly as a union arm in record-field position (the
760
- // optional-field story above); bare undefined-armed unions stay fenced
761
- // out of both stringify and dynCheck (narrow with '!== undefined'
762
- // first, or model absence with a null arm).
760
+ // Record fields drop undefined. Stringification also represents it in
761
+ // array and tuple slots as null; bare roots remain fenced.
763
762
  case "undefinedT":
764
- return inRecordField;
763
+ return undefinedAllowed;
765
764
  // JSON null ↔ the nullT arm: null-armed unions stringify (`null`) and
766
765
  // validate (a JSON null matches exactly the nullT arm).
767
766
  case "nullT":
@@ -918,6 +917,7 @@ export function canMarshalTypedFuncIntoIsland(t, getRecord, getUnion) {
918
917
  * entry carries the runtime tag spelling and the class display name
919
918
  * (dynCheck's "expected IncomingMessage ..." texts). */
920
919
  export const DYN_HANDLE_KINDS = new Map([
920
+ ["child", { tag: "SCR_DYNH_CHILD", cls: "ChildProcess" }],
921
921
  ["httpReq", { tag: "SCR_DYNH_HTTP_REQ", cls: "IncomingMessage" }],
922
922
  ["httpRes", { tag: "SCR_DYNH_HTTP_RES", cls: "ServerResponse" }],
923
923
  ["netSocket", { tag: "SCR_DYNH_NET_SOCKET", cls: "Socket" }],
@@ -926,10 +926,24 @@ export const DYN_HANDLE_KINDS = new Map([
926
926
  ["http2Stream", { tag: "SCR_DYNH_H2_STREAM", cls: "Http2Stream" }],
927
927
  ["httpClientReq", { tag: "SCR_DYNH_HTTP_CLIENT", cls: "ClientRequest" }],
928
928
  ]);
929
+ /** A class value that crosses an `unknown` slot as a compiler-owned typed
930
+ * reference. %Error keeps its dedicated error encoding; every other class
931
+ * preserves the original object identity and exposes a materialized own-field
932
+ * view only when a checked-dynamic operation actually needs one. */
933
+ export function isDynTypedRefType(t) {
934
+ return t.kind === "object" && !RUNTIME_ERROR_CLASSES.has(t.className);
935
+ }
936
+ /** Whether a class layout field is an ECMAScript own enumerable property.
937
+ * `#private` slots and `%`-prefixed compiler storage exist only in the native
938
+ * layout; TypeScript `private`/`protected` fields keep ordinary names and are
939
+ * observable properties at runtime. */
940
+ export function isClassOwnEnumerableFieldName(name) {
941
+ return !name.startsWith("#") && !name.startsWith("%");
942
+ }
929
943
  /** A static type that CONVERTS into a dyn value — the dynFrom domain:
930
- * JSON-safe data, bytes<u8> (payload copied), undefined-armed unions of
931
- * JSON-safe arms, boxable function types, and the runtime HANDLE kinds
932
- * (boxed by reference — DYN_HANDLE_KINDS). */
944
+ * JSON-safe data, bytes<u8> (payload copied), identity-preserving class
945
+ * references, undefined-armed unions of those arms, boxable function types,
946
+ * and the runtime HANDLE kinds (boxed by reference — DYN_HANDLE_KINDS). */
933
947
  export function canConvertToDyn(t, getRecord, getUnion) {
934
948
  if (isJsonSafeType(t, getRecord, getUnion))
935
949
  return true;
@@ -947,6 +961,8 @@ export function canConvertToDyn(t, getRecord, getUnion) {
947
961
  // listener boundary (a mustCall-wrapped handler receiving the payload).
948
962
  if (t.kind === "object" && t.className === "%Error")
949
963
  return true;
964
+ if (isDynTypedRefType(t))
965
+ return true;
950
966
  if (t.kind === "func")
951
967
  return canBoxFuncIntoDyn(t, getRecord, getUnion);
952
968
  if (DYN_HANDLE_KINDS.has(t.kind))
@@ -964,12 +980,14 @@ export function canConvertToDyn(t, getRecord, getUnion) {
964
980
  }
965
981
  if (t.kind === "union") {
966
982
  const def = getUnion(t.unionId);
967
- // JSON-safe arms box as before; BOXABLE FUNCTION arms join them (the
983
+ // JSON-safe arms box as before; BOXABLE FUNCTION and PROMISE arms join them (the
968
984
  // invalid-input probes iterate `[1, null, () => {}, true]` — the
969
985
  // union's func arm crosses through the checked-dynamic function
970
986
  // boundary exactly like a bare func dynFrom).
971
987
  return !!def && def.arms.every((a) => a.kind === "undefinedT" || isJsonSafeType(a, getRecord, getUnion) ||
972
- (a.kind === "func" && canBoxFuncIntoDyn(a, getRecord, getUnion)));
988
+ isDynTypedRefType(a) || DYN_HANDLE_KINDS.has(a.kind) ||
989
+ (a.kind === "func" && canBoxFuncIntoDyn(a, getRecord, getUnion)) ||
990
+ (a.kind === "promise" && canConvertToDyn(a, getRecord, getUnion)));
973
991
  }
974
992
  return false;
975
993
  }
@@ -1186,7 +1204,8 @@ export function moduleUsesCopying(mod) {
1186
1204
  if (node.kind === "arrIntrinsic" &&
1187
1205
  (node.method === "toReversed" ||
1188
1206
  node.method === "toSpliced" ||
1189
- node.method === "with")) {
1207
+ node.method === "with" ||
1208
+ node.method === "withUndefined")) {
1190
1209
  found = true;
1191
1210
  return;
1192
1211
  }
@@ -1595,6 +1614,36 @@ export function moduleUsesInspect(mod) {
1595
1614
  visit(mod);
1596
1615
  return found;
1597
1616
  }
1617
+ /** True when the module reaches child_process or carries one of its runtime
1618
+ * handle/result types. Besides the existing link consequence, this gates the
1619
+ * checked-dynamic ChildProcess handle table installed from scr_child.c. */
1620
+ export function moduleUsesChildProcess(mod) {
1621
+ let found = false;
1622
+ const visit = (v) => {
1623
+ if (found || v === null || typeof v !== "object")
1624
+ return;
1625
+ if (Array.isArray(v)) {
1626
+ for (const item of v)
1627
+ visit(item);
1628
+ return;
1629
+ }
1630
+ const node = v;
1631
+ if (node.kind === "libCall" &&
1632
+ typeof node.fn === "string" &&
1633
+ (node.fn.startsWith("cp.") || node.fn.startsWith("child.") || node.fn.startsWith("spawnRes."))) {
1634
+ found = true;
1635
+ return;
1636
+ }
1637
+ if (node.kind === "child" || node.kind === "childStream" || node.kind === "spawnRes") {
1638
+ found = true;
1639
+ return;
1640
+ }
1641
+ for (const key of Object.keys(v))
1642
+ visit(v[key]);
1643
+ };
1644
+ visit(mod);
1645
+ return found;
1646
+ }
1598
1647
  /** True when the module contains any net libCall — the link switch that
1599
1648
  * pulls scr_net.c into the binary and has the emitted main call
1600
1649
  * scr_net_install (native-toolchain.ts + emitter; the scr_events gating precedent).
@@ -2378,6 +2427,7 @@ export const MAY_THROW_LIB_FNS = new Set([
2378
2427
  "writable.uncork",
2379
2428
  "stream.destroy",
2380
2429
  "stream.destroyErr",
2430
+ "stream.iteratorClose",
2381
2431
  // setMaxListeners(n) throws Node's ERR_OUT_OF_RANGE RangeError for
2382
2432
  // negative/NaN arguments; the static form's default-max write validates
2383
2433
  // identically (Node's validateNumber(n, "setMaxListeners", 0)).
@@ -2505,6 +2555,7 @@ export const MAY_THROW_LIB_FNS = new Set([
2505
2555
  "fs.statSync",
2506
2556
  "crypto.randomBytesToString",
2507
2557
  "crypto.randomBytes",
2558
+ "buffer.concat",
2508
2559
  "buffer.concatLen",
2509
2560
  // The checked-dynamic compare/equals validators: Node's argument
2510
2561
  // ladders throw ERR_INVALID_ARG_TYPE / ERR_OUT_OF_RANGE catchably.