@scriptc/compiler 0.0.0 → 0.0.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 (206) hide show
  1. package/LICENSE +202 -0
  2. package/ambient/package.json +3 -0
  3. package/ambient/scriptc-node-fallback.d.ts +3001 -0
  4. package/ambient/scriptc-overrides.d.ts +95 -0
  5. package/ambient/scriptc.d.ts +74 -0
  6. package/dist/backend/cc.d.ts +169 -0
  7. package/dist/backend/cc.js +897 -0
  8. package/dist/backend/cc.js.map +1 -0
  9. package/dist/backend/emission/emit-async.d.ts +145 -0
  10. package/dist/backend/emission/emit-async.js +996 -0
  11. package/dist/backend/emission/emit-async.js.map +1 -0
  12. package/dist/backend/emission/emit-exprs.d.ts +3 -0
  13. package/dist/backend/emission/emit-exprs.js +5949 -0
  14. package/dist/backend/emission/emit-exprs.js.map +1 -0
  15. package/dist/backend/emission/emit-island.d.ts +45 -0
  16. package/dist/backend/emission/emit-island.js +271 -0
  17. package/dist/backend/emission/emit-island.js.map +1 -0
  18. package/dist/backend/emission/emit-shapes.d.ts +142 -0
  19. package/dist/backend/emission/emit-shapes.js +575 -0
  20. package/dist/backend/emission/emit-shapes.js.map +1 -0
  21. package/dist/backend/emission/emit-stmts.d.ts +78 -0
  22. package/dist/backend/emission/emit-stmts.js +960 -0
  23. package/dist/backend/emission/emit-stmts.js.map +1 -0
  24. package/dist/backend/emission/emit-types.d.ts +65 -0
  25. package/dist/backend/emission/emit-types.js +652 -0
  26. package/dist/backend/emission/emit-types.js.map +1 -0
  27. package/dist/backend/emission/emit-walkers.d.ts +154 -0
  28. package/dist/backend/emission/emit-walkers.js +1587 -0
  29. package/dist/backend/emission/emit-walkers.js.map +1 -0
  30. package/dist/backend/emission/emitter.d.ts +452 -0
  31. package/dist/backend/emission/emitter.js +1249 -0
  32. package/dist/backend/emission/emitter.js.map +1 -0
  33. package/dist/backend/emission/may-throw.d.ts +15 -0
  34. package/dist/backend/emission/may-throw.js +250 -0
  35. package/dist/backend/emission/may-throw.js.map +1 -0
  36. package/dist/backend/llvm/blocks.d.ts +21 -0
  37. package/dist/backend/llvm/blocks.js +68 -0
  38. package/dist/backend/llvm/blocks.js.map +1 -0
  39. package/dist/backend/llvm/classes.d.ts +84 -0
  40. package/dist/backend/llvm/classes.js +438 -0
  41. package/dist/backend/llvm/classes.js.map +1 -0
  42. package/dist/backend/llvm/dyn.d.ts +123 -0
  43. package/dist/backend/llvm/dyn.js +2624 -0
  44. package/dist/backend/llvm/dyn.js.map +1 -0
  45. package/dist/backend/llvm/emitter.d.ts +3 -0
  46. package/dist/backend/llvm/emitter.js +10102 -0
  47. package/dist/backend/llvm/emitter.js.map +1 -0
  48. package/dist/backend/llvm/shapes.d.ts +78 -0
  49. package/dist/backend/llvm/shapes.js +754 -0
  50. package/dist/backend/llvm/shapes.js.map +1 -0
  51. package/dist/backend/llvm/unsupported.d.ts +6 -0
  52. package/dist/backend/llvm/unsupported.js +12 -0
  53. package/dist/backend/llvm/unsupported.js.map +1 -0
  54. package/dist/backend/llvm/walkers.d.ts +58 -0
  55. package/dist/backend/llvm/walkers.js +793 -0
  56. package/dist/backend/llvm/walkers.js.map +1 -0
  57. package/dist/backend/mangle.d.ts +124 -0
  58. package/dist/backend/mangle.js +232 -0
  59. package/dist/backend/mangle.js.map +1 -0
  60. package/dist/coverage/report.d.ts +65 -0
  61. package/dist/coverage/report.js +238 -0
  62. package/dist/coverage/report.js.map +1 -0
  63. package/dist/diagnostics/diagnostic.d.ts +140 -0
  64. package/dist/diagnostics/diagnostic.js +458 -0
  65. package/dist/diagnostics/diagnostic.js.map +1 -0
  66. package/dist/diagnostics/render.d.ts +11 -0
  67. package/dist/diagnostics/render.js +58 -0
  68. package/dist/diagnostics/render.js.map +1 -0
  69. package/dist/frontend/cjs-lexer.d.ts +20 -0
  70. package/dist/frontend/cjs-lexer.js +813 -0
  71. package/dist/frontend/cjs-lexer.js.map +1 -0
  72. package/dist/frontend/lowering/http2-constants.d.ts +1 -0
  73. package/dist/frontend/lowering/http2-constants.js +251 -0
  74. package/dist/frontend/lowering/http2-constants.js.map +1 -0
  75. package/dist/frontend/lowering/lib-boundary.d.ts +6 -0
  76. package/dist/frontend/lowering/lib-boundary.js +143 -0
  77. package/dist/frontend/lowering/lib-boundary.js.map +1 -0
  78. package/dist/frontend/lowering/lower-assert.d.ts +18 -0
  79. package/dist/frontend/lowering/lower-assert.js +1269 -0
  80. package/dist/frontend/lowering/lower-assert.js.map +1 -0
  81. package/dist/frontend/lowering/lower-builtins.d.ts +511 -0
  82. package/dist/frontend/lowering/lower-builtins.js +5249 -0
  83. package/dist/frontend/lowering/lower-builtins.js.map +1 -0
  84. package/dist/frontend/lowering/lower-calls.d.ts +581 -0
  85. package/dist/frontend/lowering/lower-calls.js +6286 -0
  86. package/dist/frontend/lowering/lower-calls.js.map +1 -0
  87. package/dist/frontend/lowering/lower-classes.d.ts +727 -0
  88. package/dist/frontend/lowering/lower-classes.js +4701 -0
  89. package/dist/frontend/lowering/lower-classes.js.map +1 -0
  90. package/dist/frontend/lowering/lower-comptime.d.ts +53 -0
  91. package/dist/frontend/lowering/lower-comptime.js +244 -0
  92. package/dist/frontend/lowering/lower-comptime.js.map +1 -0
  93. package/dist/frontend/lowering/lower-containers.d.ts +486 -0
  94. package/dist/frontend/lowering/lower-containers.js +6345 -0
  95. package/dist/frontend/lowering/lower-containers.js.map +1 -0
  96. package/dist/frontend/lowering/lower-dgram.d.ts +20 -0
  97. package/dist/frontend/lowering/lower-dgram.js +319 -0
  98. package/dist/frontend/lowering/lower-dgram.js.map +1 -0
  99. package/dist/frontend/lowering/lower-emitter.d.ts +10 -0
  100. package/dist/frontend/lowering/lower-emitter.js +688 -0
  101. package/dist/frontend/lowering/lower-emitter.js.map +1 -0
  102. package/dist/frontend/lowering/lower-enums.d.ts +22 -0
  103. package/dist/frontend/lowering/lower-enums.js +235 -0
  104. package/dist/frontend/lowering/lower-enums.js.map +1 -0
  105. package/dist/frontend/lowering/lower-expando.d.ts +35 -0
  106. package/dist/frontend/lowering/lower-expando.js +276 -0
  107. package/dist/frontend/lowering/lower-expando.js.map +1 -0
  108. package/dist/frontend/lowering/lower-exprs.d.ts +524 -0
  109. package/dist/frontend/lowering/lower-exprs.js +8111 -0
  110. package/dist/frontend/lowering/lower-exprs.js.map +1 -0
  111. package/dist/frontend/lowering/lower-generators.d.ts +50 -0
  112. package/dist/frontend/lowering/lower-generators.js +421 -0
  113. package/dist/frontend/lowering/lower-generators.js.map +1 -0
  114. package/dist/frontend/lowering/lower-inspect.d.ts +20 -0
  115. package/dist/frontend/lowering/lower-inspect.js +1074 -0
  116. package/dist/frontend/lowering/lower-inspect.js.map +1 -0
  117. package/dist/frontend/lowering/lower-island.d.ts +108 -0
  118. package/dist/frontend/lowering/lower-island.js +650 -0
  119. package/dist/frontend/lowering/lower-island.js.map +1 -0
  120. package/dist/frontend/lowering/lower-mixins.d.ts +96 -0
  121. package/dist/frontend/lowering/lower-mixins.js +534 -0
  122. package/dist/frontend/lowering/lower-mixins.js.map +1 -0
  123. package/dist/frontend/lowering/lower-modules.d.ts +135 -0
  124. package/dist/frontend/lowering/lower-modules.js +1613 -0
  125. package/dist/frontend/lowering/lower-modules.js.map +1 -0
  126. package/dist/frontend/lowering/lower-namespaces.d.ts +168 -0
  127. package/dist/frontend/lowering/lower-namespaces.js +706 -0
  128. package/dist/frontend/lowering/lower-namespaces.js.map +1 -0
  129. package/dist/frontend/lowering/lower-server.d.ts +90 -0
  130. package/dist/frontend/lowering/lower-server.js +3471 -0
  131. package/dist/frontend/lowering/lower-server.js.map +1 -0
  132. package/dist/frontend/lowering/lower-stmts.d.ts +361 -0
  133. package/dist/frontend/lowering/lower-stmts.js +5341 -0
  134. package/dist/frontend/lowering/lower-stmts.js.map +1 -0
  135. package/dist/frontend/lowering/lower-stream.d.ts +88 -0
  136. package/dist/frontend/lowering/lower-stream.js +1533 -0
  137. package/dist/frontend/lowering/lower-stream.js.map +1 -0
  138. package/dist/frontend/lowering/lower-test.d.ts +27 -0
  139. package/dist/frontend/lowering/lower-test.js +353 -0
  140. package/dist/frontend/lowering/lower-test.js.map +1 -0
  141. package/dist/frontend/lowering/lowerer.d.ts +1748 -0
  142. package/dist/frontend/lowering/lowerer.js +6257 -0
  143. package/dist/frontend/lowering/lowerer.js.map +1 -0
  144. package/dist/frontend/lowering/surfaces.d.ts +272 -0
  145. package/dist/frontend/lowering/surfaces.js +1096 -0
  146. package/dist/frontend/lowering/surfaces.js.map +1 -0
  147. package/dist/frontend/npm-static.d.ts +55 -0
  148. package/dist/frontend/npm-static.js +300 -0
  149. package/dist/frontend/npm-static.js.map +1 -0
  150. package/dist/frontend/npm.d.ts +330 -0
  151. package/dist/frontend/npm.js +1259 -0
  152. package/dist/frontend/npm.js.map +1 -0
  153. package/dist/frontend/program.d.ts +186 -0
  154. package/dist/frontend/program.js +2255 -0
  155. package/dist/frontend/program.js.map +1 -0
  156. package/dist/frontend/provenance-registry.d.ts +48 -0
  157. package/dist/frontend/provenance-registry.js +87 -0
  158. package/dist/frontend/provenance-registry.js.map +1 -0
  159. package/dist/frontend/provenance.d.ts +6 -0
  160. package/dist/frontend/provenance.js +459 -0
  161. package/dist/frontend/provenance.js.map +1 -0
  162. package/dist/frontend/resolve.d.ts +56 -0
  163. package/dist/frontend/resolve.js +682 -0
  164. package/dist/frontend/resolve.js.map +1 -0
  165. package/dist/frontend/shared.d.ts +67 -0
  166. package/dist/frontend/shared.js +241 -0
  167. package/dist/frontend/shared.js.map +1 -0
  168. package/dist/frontend/ts7/adapter.d.ts +7 -0
  169. package/dist/frontend/ts7/adapter.js +54 -0
  170. package/dist/frontend/ts7/adapter.js.map +1 -0
  171. package/dist/frontend/ts7/ast.d.ts +50 -0
  172. package/dist/frontend/ts7/ast.js +211 -0
  173. package/dist/frontend/ts7/ast.js.map +1 -0
  174. package/dist/frontend/ts7/census-check.d.ts +1 -0
  175. package/dist/frontend/ts7/census-check.js +12 -0
  176. package/dist/frontend/ts7/census-check.js.map +1 -0
  177. package/dist/frontend/ts7/checker.d.ts +140 -0
  178. package/dist/frontend/ts7/checker.js +544 -0
  179. package/dist/frontend/ts7/checker.js.map +1 -0
  180. package/dist/frontend/ts7/enums.d.ts +18 -0
  181. package/dist/frontend/ts7/enums.js +43 -0
  182. package/dist/frontend/ts7/enums.js.map +1 -0
  183. package/dist/frontend/ts7/program.d.ts +99 -0
  184. package/dist/frontend/ts7/program.js +278 -0
  185. package/dist/frontend/ts7/program.js.map +1 -0
  186. package/dist/frontend/ts7/world-check.d.ts +3 -0
  187. package/dist/frontend/ts7/world-check.js +34 -0
  188. package/dist/frontend/ts7/world-check.js.map +1 -0
  189. package/dist/frontend/types.d.ts +205 -0
  190. package/dist/frontend/types.js +2485 -0
  191. package/dist/frontend/types.js.map +1 -0
  192. package/dist/index.d.ts +85 -0
  193. package/dist/index.js +429 -0
  194. package/dist/index.js.map +1 -0
  195. package/dist/ir/nodes.d.ts +4334 -0
  196. package/dist/ir/nodes.js +1906 -0
  197. package/dist/ir/nodes.js.map +1 -0
  198. package/dist/ir/serialize.d.ts +4 -0
  199. package/dist/ir/serialize.js +34 -0
  200. package/dist/ir/serialize.js.map +1 -0
  201. package/dist/ir/validate.d.ts +36 -0
  202. package/dist/ir/validate.js +4885 -0
  203. package/dist/ir/validate.js.map +1 -0
  204. package/package.json +30 -6
  205. package/README.md +0 -3
  206. package/index.js +0 -2
@@ -0,0 +1,4334 @@
1
+ /** Byte-offset span in the original source file. */
2
+ export interface SrcLoc {
3
+ file: string;
4
+ start: number;
5
+ end: number;
6
+ }
7
+ /** The typed-array element kinds with a runtime representation: exactly
8
+ * the constructors real CLI code reaches (Uint8Array/Buffer, Uint32Array,
9
+ * Int32Array — the Atomics.wait sleep idiom's array — Float32Array). The
10
+ * other TypedArray flavors stay frontend-fenced. */
11
+ export type IrBytesElem = "u8" | "u32" | "i32" | "f32";
12
+ export type IrType = {
13
+ kind: "f64";
14
+ } | {
15
+ kind: "string";
16
+ } | {
17
+ kind: "bool";
18
+ } | {
19
+ kind: "array";
20
+ elem: IrType;
21
+ }
22
+ /** ES `Map<K, V>` — heap, refcounted, insertion-ordered hash map with ONE
23
+ * runtime representation (ScrMap) and type-directed key/value handling,
24
+ * exactly the array pattern (never per-instantiation structs). Keys are
25
+ * f64 or string (SameValueZero); values are f64, string, bool, record,
26
+ * object, union, or array — anything isRefCounted or scalar EXCEPT
27
+ * func/promise/dyn/jsval/map (frontend-fenced, validator-checked). */
28
+ | {
29
+ kind: "map";
30
+ key: IrType;
31
+ value: IrType;
32
+ }
33
+ /** ES `Set<T>` — heap, refcounted, insertion-ordered. Map's sibling with
34
+ * the value slot removed: ONE runtime representation (the backend lowers
35
+ * sets onto the map runtime with a constant unit value), elements are
36
+ * exactly Map's KEY types — f64 or string, SameValueZero. Same container
37
+ * fences as map (no union arms, no array elements, no map values, no sets
38
+ * of sets, not JSON-safe) and never cycle-capable: elements are scalars
39
+ * or strings, which cannot point back. */
40
+ | {
41
+ kind: "set";
42
+ elem: IrType;
43
+ }
44
+ /** A regular expression — heap, refcounted, IMMUTABLE. No lastIndex
45
+ * statefulness exists: /g and /y are supported only inside
46
+ * replace/replaceAll/split (where the iteration is internal), and test()
47
+ * on them is rejected. Every regex value today originates from a literal,
48
+ * which backends intern as ONE immortal static per (pattern, flags) pair
49
+ * — bytecode compiles lazily at first use, is never freed, and the RC
50
+ * audit ignores immortals. Deliberately narrower than string: no array
51
+ * elements, no map keys/values, no union arms (a regex arm would have no
52
+ * narrowing test), not JSON-safe. */
53
+ | {
54
+ kind: "regex";
55
+ }
56
+ /** A typed array / Node Buffer (Uint8Array, Uint32Array, Float32Array;
57
+ * Buffer IS a Uint8Array subclass and shares the u8 kind) — heap,
58
+ * refcounted, MUTABLE, fixed-length, with ONE runtime representation
59
+ * (ScrBytes) that OWNS its storage: no views exist — subarray()/slice()
60
+ * both COPY (documented divergence for subarray), `.buffer`/
61
+ * `.byteOffset`/DataView are frontend-fenced. Element reads widen to
62
+ * f64; writes coerce JS-exactly (ToUint8/ToUint32 modular truncation,
63
+ * double→float rounding). OOB element access traps like arrays. Allowed
64
+ * as array elements and union arms (tag-based narrowing, like url);
65
+ * fenced out of map keys/values, set elements, and JSON. Holds only raw
66
+ * bytes — never part of a cycle, no trace. */
67
+ | {
68
+ kind: "bytes";
69
+ elem: IrBytesElem;
70
+ }
71
+ /** A WHATWG URL instance (scr_url.c): heap, refcounted, IMMUTABLE — the
72
+ * parsed components are frozen at construction, so getters are pure
73
+ * reads (the mutating lib setters are fenced). Constructed by `new URL`
74
+ * and url.pathToFileURL libCalls. Holds only strings — never part of a
75
+ * cycle, no trace. Allowed as a union arm (narrowing is tag-based, like
76
+ * object arms); fenced out of array elements, map keys/values, and JSON
77
+ * like regex. */
78
+ | {
79
+ kind: "url";
80
+ }
81
+ /** A URLSearchParams instance (scr_url.c): heap, refcounted, MUTABLE —
82
+ * an ordered list of decoded (name, value) string pairs. Standalone
83
+ * (`new URLSearchParams(...)`) or the LIVE view of a URL's query
84
+ * (`u.searchParams` — cached on the URL, mutations re-serialize into
85
+ * the URL's query so href reflects immediately). Holds only strings
86
+ * plus at most the owning-URL edge (the URL never points back
87
+ * owningly) — never part of a cycle, no trace. Same container rules
88
+ * as url: union arms fine, arrays/maps/JSON fenced. */
89
+ | {
90
+ kind: "searchParams";
91
+ }
92
+ /** An ES symbol value (scr_symbol.c — linked only when the IR uses the
93
+ * symbol surface): heap, refcounted, IMMUTABLE — a runtime-unique
94
+ * IDENTITY whose pointer is the identity (`===` is a pointer compare;
95
+ * equal descriptions are still distinct symbols, JS exactly). Holds at
96
+ * most two strings (description + Symbol.for registry key) — never part
97
+ * of a cycle, no trace. Constructed by `Symbol(desc?)` and
98
+ * `Symbol.for(key)`; typeof answers "symbol"; truthiness is constant
99
+ * true (every symbol is truthy). Allowed as union arms (tag-based
100
+ * narrowing — `typeof u === "symbol"` is the test, like url), array
101
+ * elements (SCR_ELEM_REF identity semantics, the child precedent), and
102
+ * Set elements (identity hashing, SCR_MAP_KEY_REF — the netServer
103
+ * precedent); fenced out of map keys/values and JSON (JSON.stringify
104
+ * drops symbols in Node — silent divergence banned, reject instead).
105
+ * Property KEYS stay frontend-fenced: static record/class shapes have
106
+ * no symbol-keyed storage. */
107
+ | {
108
+ kind: "symbol";
109
+ }
110
+ /** An fs.Stats instance (statSync / fs.promises.stat): heap, refcounted,
111
+ * IMMUTABLE — a snapshot of stat(2) results. Holds no references —
112
+ * never part of a cycle, no trace. Same container rules as url: union
113
+ * arms fine, arrays/maps/JSON fenced. */
114
+ | {
115
+ kind: "stats";
116
+ }
117
+ /** A child_process.spawnSync result (scr_child.c): heap, refcounted,
118
+ * IMMUTABLE — the reaped child's status plus its captured utf8 stdout/
119
+ * stderr. Holds only strings — never part of a cycle, no trace. Same
120
+ * container rules as stats. */
121
+ | {
122
+ kind: "spawnRes";
123
+ }
124
+ /** A child_process.spawn handle (scr_child.c): heap, refcounted, the
125
+ * ONE mutable builtin value kind — the event loop reaps the child and
126
+ * fires its registered listeners (scr_async.c polls at quiescence).
127
+ * Holds closures until the terminal event fires, then drops them (the
128
+ * registry releases every listener at reap, so a listener capturing its
129
+ * own child never cycles past reap — and every child IS reaped before
130
+ * loop exit, Node's keep-alive semantics). Lean allocation, no trace:
131
+ * the pre-reap closure edges are guaranteed dropped. Same container
132
+ * rules as stats: union arms fine, arrays/maps/JSON fenced. */
133
+ | {
134
+ kind: "child";
135
+ }
136
+ /** A node:net server handle (scr_net.c — linked only when the IR uses
137
+ * the net surface). Heap, refcounted, MUTABLE like child: the event
138
+ * loop's net hook accepts connections and fires its listeners.
139
+ * Listeners are held only until the handle settles ('close' fired, or
140
+ * the exit-time cleanup) — the child ownership story, so lean
141
+ * allocation, no trace header. Same container rules as child: union
142
+ * arms fine, arrays/maps/JSON fenced. */
143
+ | {
144
+ kind: "netServer";
145
+ }
146
+ /** A node:net socket handle (accepted connection or net.connect
147
+ * client) — the same runtime story as netServer. */
148
+ | {
149
+ kind: "netSocket";
150
+ } | {
151
+ kind: "http2Session";
152
+ } | {
153
+ kind: "http2Stream";
154
+ }
155
+ /** A node:dgram socket handle (scr_dgram.c — linked only when the IR
156
+ * uses the dgram/dns surface). Heap, refcounted, MUTABLE like
157
+ * netSocket: the loop's dgram hook delivers datagrams and fires its
158
+ * listeners. Listeners are held only until the handle settles ('close'
159
+ * fired, or the exit-time cleanup) — the netSocket ownership story, so
160
+ * lean allocation, no trace header. Same container rules: union arms
161
+ * fine, arrays/maps/JSON fenced. */
162
+ | {
163
+ kind: "dgramSocket";
164
+ }
165
+ /** A node:test TestContext handle (scr_test.c — linked only when the
166
+ * IR uses the node:test surface). Heap, refcounted, no cycles (the
167
+ * runner tree owns the children; the parent edge is a borrowed
168
+ * back-pointer): a lean handle like dgramSocket. Test bodies receive
169
+ * it as their parameter; t.test/t.skip/t.todo/t.diagnostic lower to
170
+ * test.* libCalls on it. */
171
+ | {
172
+ kind: "testCtx";
173
+ }
174
+ /** A node:http server request (scr_http.c — the parsed head + the body
175
+ * event lists; listeners drop when the body completes, the same
176
+ * settle-releases-listeners story). http.Server itself is a netServer. */
177
+ | {
178
+ kind: "httpReq";
179
+ }
180
+ /** A node:http server response (the header list + framing state; holds
181
+ * the socket, never listeners — lean, no trace). */
182
+ | {
183
+ kind: "httpRes";
184
+ }
185
+ /** A node:http CLIENT request handle (http.request/http.get — the
186
+ * outbound head + body framing state over a net client socket, with the
187
+ * response/error/timeout/close listener lists; listeners drop at
188
+ * settlement like every other handle). The RESPONSE it delivers is an
189
+ * httpReq — IncomingMessage is one type in Node too. */
190
+ | {
191
+ kind: "httpClientReq";
192
+ }
193
+ /** A piped child-output stream (child.stdout / child.stderr — spawn
194
+ * with stdio ["ignore", "pipe", "pipe"]; scr_child.c). Heap, refcounted,
195
+ * MUTABLE like child: the loop's reap pass services the pipe and fires
196
+ * 'data'/'end' listeners, which drop at EOF (the settle-releases-
197
+ * listeners story), so lean allocation, no trace header. Same container
198
+ * rules as child: union arms fine (the checker's `Readable | null`),
199
+ * arrays/maps/JSON fenced. */
200
+ | {
201
+ kind: "childStream";
202
+ }
203
+ /** A process output stream as a FIRST-CLASS value (process.stdout /
204
+ * process.stderr flowing into a `NodeJS.WritableStream` slot — the
205
+ * prefixStream idiom). Representation is the raw FD as a double (1 or
206
+ * 2): a SCALAR kind like f64 — no heap, no refcount, boxes ride
207
+ * SCR_BOX_F64. Truthiness is object-true (Node's streams are objects).
208
+ * The lowered surface is write(string); everything else fences. */
209
+ | {
210
+ kind: "procStream";
211
+ }
212
+ /** An fs.FSWatcher handle (scr_watch.c — linked only when the IR uses
213
+ * fs.watch). Heap, refcounted, MUTABLE like child: the event loop's
214
+ * watch hook drains the unit's kqueue (EVFILT_VNODE) and fires its
215
+ * listeners. Listeners are held only until close() (or the exit-time
216
+ * cleanup) — the child ownership story, so lean allocation, no trace
217
+ * header. Same container rules as child: union arms fine (the
218
+ * `FSWatcher | null` polling-fallback local), arrays/maps/JSON fenced. */
219
+ | {
220
+ kind: "fsWatcher";
221
+ }
222
+ /** A tls.SecureContext handle (scr_tls.c): heap, refcounted, IMMUTABLE —
223
+ * a parsed cert/key pair (tls.createSecureContext({ cert, key })) that
224
+ * an SNI callback answers per-servername. Holds no references — never
225
+ * part of a cycle, no trace. Union arms fine (the `ctx?: SecureContext`
226
+ * callback parameter is the `SecureContext | undefined` union); allowed
227
+ * as a Map VALUE (the per-hostname context cache) like child; fenced out
228
+ * of array elements and JSON like the other opaque handles. */
229
+ | {
230
+ kind: "secureCtx";
231
+ }
232
+ /** Heap, refcounted closure. `rest` marks a VARIADIC JS function (a
233
+ * `...args` rest parameter, or a zero-param function body reading
234
+ * `arguments` — test/common's mustCall wrapper): the lifted function
235
+ * takes one extra trailing `ScrDyn *` param — a DOM ARRAY carrying the
236
+ * call's arguments from index params.length on — which the dyn call
237
+ * thunk builds per call. `params` stays the DECLARED (non-rest) list
238
+ * (fn.length semantics). Rest-marked values are only ever CALLED
239
+ * through the dyn boundary (boxed thunks); direct static calls box
240
+ * first (lower-calls). */
241
+ | {
242
+ kind: "func";
243
+ params: IrType[];
244
+ ret: IrType;
245
+ rest?: true;
246
+ } | {
247
+ kind: "object";
248
+ className: string;
249
+ }
250
+ /** The class STATIC side as a value — `typeof C`, the type of the class
251
+ * name itself and of `new (…) => T` constructor-typed slots. Runtime
252
+ * representation is the per-class IMMORTAL class object (ScrClassObj:
253
+ * preorder interval, construct thunk, .name string) emitted once per
254
+ * classRef-referenced class — so identity `===` is one pointer compare
255
+ * and retains/releases are no-ops on the immortal (the regex-literal
256
+ * discipline; isRefCounted says true for container/RC uniformity).
257
+ * Values of `classval:C` are C's class object or a STRICT DESCENDANT's —
258
+ * the object kind's nominal, upcast-only story — and every legal flow
259
+ * preserves the constructor ABI (upcast requires the descendant's
260
+ * completed ctor signature to equal C's), which is what makes `newValue`
261
+ * completion against C's one signature sound. Allowed in locals,
262
+ * globals, params, returns, class/record fields, capture boxes, array
263
+ * elements, Map VALUES, and union arms; fenced out of Map keys, Set
264
+ * elements, JSON, dyn/jsval conversion, and ToString. */
265
+ | {
266
+ kind: "classval";
267
+ className: string;
268
+ }
269
+ /** Structural record shape (object literal / interface / type alias over
270
+ * data properties). `shapeId` indexes IrModule.records; the frontend
271
+ * interns shapes structurally, so equal shapeId ⇔ equal shape and
272
+ * typeEquals may compare ids alone. Heap, refcounted, monomorphic. */
273
+ | {
274
+ kind: "record";
275
+ shapeId: string;
276
+ }
277
+ /** Tagged union (`A | B`). `unionId` indexes IrModule.unions; the frontend
278
+ * interns unions structurally (canonical identity = the sorted arm list),
279
+ * so equal unionId ⇔ equal arm set and typeEquals may compare ids alone.
280
+ * Values are heap, refcounted, IMMUTABLE tagged boxes: a runtime tag (the
281
+ * arm's index in the canonical order) plus one payload slot. */
282
+ | {
283
+ kind: "union";
284
+ unionId: string;
285
+ }
286
+ /** A dynamic value — the type of `unknown` (JSON.parse results and
287
+ * unknown-typed locals/params/returns). Runtime representation is a
288
+ * refcounted JSON DOM tree (ScrDyn). Deliberately NARROW: a dyn value can
289
+ * be stored in locals/globals, passed as a param/call arg, returned,
290
+ * validated with a checked cast (`dynCheck`), CALLED (`dynCall` — the
291
+ * DOM's function kind, boxed closures with per-call argument checks),
292
+ * and captured by closures (an untraced obj-box: cycles through dyn are
293
+ * never collected, SEMANTICS.md); it can NOT ride record/class fields,
294
+ * array elements, union arms, or the exception cell, and every other
295
+ * operation on it (property access, arithmetic, truthiness, `===`,
296
+ * console.log, ...) is frontend-rejected with a "validate with 'as
297
+ * <type>' first" hint — or, in JavaScript sources, met with per-site
298
+ * checked lowerings (SEMANTICS.md 115-117). */
299
+ | {
300
+ kind: "dyn";
301
+ }
302
+ /** An island value handle — the type of `any` under --dynamic. Runtime
303
+ * representation is a refcounted cell (ScrJsval) owning one embedded-
304
+ * engine value. Same deliberate NARROWNESS as dyn (locals/globals/
305
+ * params/args/returns only — never record/class fields, array elements,
306
+ * union arms, or capture boxes), but the OPPOSITE operational stance:
307
+ * where every operation on dyn is frontend-rejected, operations on
308
+ * jsval compile to engine calls (jsOp) with JS-exact semantics, and
309
+ * exits back to static types are validated (jsExit). Exists only when
310
+ * the frontend runs with the dynamic option; static builds never see
311
+ * this kind. */
312
+ | {
313
+ kind: "jsval";
314
+ }
315
+ /** A catch binding — the type of `catch (e)`'s local, and NOTHING else
316
+ * (never params, returns, fields, arms, elements, globals, captures).
317
+ * Runtime representation is a refcounted snapshot box (ScrCaught) holding
318
+ * the taken exception: a kind tag plus the payload. Even NARROWER than
319
+ * dyn: the only expressions a caught value may appear in are `caughtTest`
320
+ * (kind/instanceof tests), `caughtNarrow` (checker-trusted extraction
321
+ * under a proven test), and the `rethrow` statement — the frontend
322
+ * rejects every other use with the narrowing hint. */
323
+ | {
324
+ kind: "caught";
325
+ } | {
326
+ kind: "promise";
327
+ inner: IrType;
328
+ }
329
+ /** A sync generator object (`function*`'s result — scr_async.c's ScrGen):
330
+ * heap, refcounted, MUTABLE — a paused fiber plus the typed value
331
+ * channels. `yieldT` is what `yield e` sends OUT (never yields → the
332
+ * frontend picks the channel off the declared/inferred Generator type;
333
+ * a generator that never yields still carries the type's slot), `retT`
334
+ * what `return v` completes with (VOID when the type carries no return
335
+ * value — the done result's value is then the undefined arm), `nextT`
336
+ * what `.next(v)` sends IN (the yield expression's result type). Lean
337
+ * allocation, NO cycle header: a suspended fiber's stack is untraceable
338
+ * by construction, so a generator captured into a cycle its own locals
339
+ * hold is a documented leak (the abandoned-fiber audit note covers
340
+ * generators still suspended at exit). Fenced out of union arms (no
341
+ * narrowing test — the map/set rule), map keys/values, set elements,
342
+ * array elements, and JSON. */
343
+ | {
344
+ kind: "generator";
345
+ yieldT: IrType;
346
+ retT: IrType;
347
+ nextT: IrType;
348
+ }
349
+ /** The `undefined` unit type — a payload-less arm kind. Representable
350
+ * ONLY as a union arm (`string | undefined`) or as the type of a
351
+ * `unitLit` on its way into a `unionWrap`; it can never stand alone in
352
+ * locals, globals, record/class fields, array elements, params, or
353
+ * returns (the frontend maps standalone `undefined` to void in return
354
+ * position and rejects it in value position — see mapType). A union
355
+ * instance holding a unit arm carries the tag and NO payload; backends
356
+ * may intern ONE immortal instance per (union, tag). */
357
+ | {
358
+ kind: "undefinedT";
359
+ }
360
+ /** The `null` unit type — same fences and representation as undefinedT.
361
+ * Unlike undefinedT it is JSON-representable: JSON `null` matches a
362
+ * nullT arm in dynCheck, and a null-armed union stringifies as `null`. */
363
+ | {
364
+ kind: "nullT";
365
+ } | {
366
+ kind: "void";
367
+ };
368
+ /** The ref kinds whose values are JS OBJECTS for truthiness: always true
369
+ * ([] and {} included) — toBool accepts them (the operand still evaluates;
370
+ * the test is constant), and per-union truthiness helpers answer their
371
+ * arms with `true`. */
372
+ export declare const REF_TRUTHY_KINDS: ReadonlySet<string>;
373
+ export declare const F64: IrType;
374
+ export declare const BYTES_U8: IrType;
375
+ export declare const STRING: IrType;
376
+ export declare const BOOL: IrType;
377
+ export declare const REGEX: IrType;
378
+ export declare const URL_T: IrType;
379
+ export declare const SEARCH_PARAMS_T: IrType;
380
+ export declare const SYMBOL_T: IrType;
381
+ export declare const STATS_T: IrType;
382
+ export declare const SPAWNRES_T: IrType;
383
+ export declare const CHILD_T: IrType;
384
+ export declare const NETSERVER_T: IrType;
385
+ export declare const NETSOCKET_T: IrType;
386
+ export declare const HTTP2SESSION_T: IrType;
387
+ export declare const HTTP2STREAM_T: IrType;
388
+ export declare const DGRAMSOCK_T: IrType;
389
+ export declare const TESTCTX_T: IrType;
390
+ export declare const HTTPREQ_T: IrType;
391
+ export declare const HTTPRES_T: IrType;
392
+ export declare const HTTPCLIENTREQ_T: IrType;
393
+ export declare const SECURECTX_T: IrType;
394
+ export declare const FSWATCHER_T: IrType;
395
+ export declare const CHILDSTREAM_T: IrType;
396
+ export declare const PROCSTREAM_T: IrType;
397
+ export declare const VOID: IrType;
398
+ export declare const DYN: IrType;
399
+ export declare const JSVAL: IrType;
400
+ export declare const CAUGHT: IrType;
401
+ export declare const UNDEFINED_T: IrType;
402
+ export declare const NULL_T: IrType;
403
+ /** True for the payload-less unit kinds (`undefined`/`null`). Unit values
404
+ * exist only inside unions: a unit-armed union instance is tag-only, so
405
+ * wrapping allocates no payload, narrowing to a unit arm produces no value
406
+ * (the frontend never emits it), and releasing has nothing to release. */
407
+ export declare function isUnitType(t: IrType): boolean;
408
+ export declare function arrayOf(elem: IrType): IrType;
409
+ export declare function bytesOf(elem: IrBytesElem): IrType;
410
+ export declare function mapOf(key: IrType, value: IrType): IrType;
411
+ export declare function setOf(elem: IrType): IrType;
412
+ /** The Map KEY fence: string (content) or number (SameValueZero) — the two
413
+ * kinds a hash of the VALUE is honest for. Booleans, objects, and the rest
414
+ * of JS's anything-goes keys stay out. Shared by the frontend's
415
+ * type mapping/diagnostics and the validator. Set ELEMENTS use the same
416
+ * fence: a set is hashed storage of its elements exactly as a map is of
417
+ * its keys (isSupportedSetElem is this predicate under its own name). */
418
+ export declare function isSupportedMapKey(t: IrType): boolean;
419
+ /** The Set ELEMENT fence — Map's key fence plus the refcounted HANDLE
420
+ * kinds stored under identity hashing (SameValueZero for JS objects IS
421
+ * reference identity, so a Set of server handles — portless's auxiliary-
422
+ * server registry — is honest hashed storage; SCR_MAP_KEY_REF in the
423
+ * runtime). netServer is the one handle admitted so far: it drops its
424
+ * listener closures at close, so a set-in-listener cycle is temporary —
425
+ * the child precedent's story. Symbols are identity values by DESIGN —
426
+ * SameValueZero on a symbol IS pointer identity, so a Set of symbols (the
427
+ * sentinel-registry idiom) is the same honest hashed storage with no
428
+ * cycle risk at all (symbols hold only strings). */
429
+ export declare function isSupportedSetElem(t: IrType): boolean;
430
+ /** The Map VALUE fence: scalars plus every refcounted kind EXCEPT
431
+ * func/promise/dyn/jsval (and map itself — no maps of maps).
432
+ * Record/object/union values can point back at the map holding them, which
433
+ * is exactly why ref-valued maps are cycle-capable (see the backend's
434
+ * cycle analysis and docs/memory.md). Shared frontend/validator. */
435
+ export declare function isSupportedMapValue(t: IrType): boolean;
436
+ /** The INDEX-SIGNATURE value fence (`{ [k: string]: V }` shapes): the map
437
+ * VALUE kinds — the overflow portion IS a string-keyed map — plus dyn
438
+ * (`unknown`, an unknown-valued pricing-table shape: overflow reads surface ordinary
439
+ * dyn values validated by the usual checked casts). Shared frontend
440
+ * (mapType) / validator. */
441
+ export declare function isSupportedIndexValue(t: IrType): boolean;
442
+ export declare function funcOf(params: IrType[], ret: IrType): IrType;
443
+ /** Canonical, injective text form of an IrType — the building block of
444
+ * shape/union identity keys, generic-function instantiation keys, and the
445
+ * backend's per-type helper interning (jsonStringify/dynCheck walkers).
446
+ * Nested records/unions are represented by their (already interned, already
447
+ * canonical) shapeId/unionId, so keys stay finite and comparable. Lives in
448
+ * the IR (not the frontend) because both ends need it. */
449
+ export declare function typeKey(t: IrType): string;
450
+ export declare function typeEquals(a: IrType, b: IrType): boolean;
451
+ /** True for types whose values are heap-allocated and reference-counted.
452
+ * The single dispatch point for the backend's RC machinery: retains,
453
+ * releases, frame/scope tracking, and NULL-initialized locals all key off
454
+ * this — adding a refcounted kind must not grow new per-kind checks outside
455
+ * the type-directed helpers. */
456
+ export declare function isRefCounted(t: IrType): boolean;
457
+ export interface IrModule {
458
+ /** Bumped on any breaking IR change; serialize.ts refuses mismatches. */
459
+ irVersion: 1;
460
+ sourceFile: string;
461
+ functions: IrFunction[];
462
+ /** Class shapes. Constructors and methods are ordinary module functions
463
+ * named `%Class.constructor` / `%Class.method` whose first param is
464
+ * `this`. Dispatch is static by default; single inheritance (`base`)
465
+ * routes the calls that can actually reach an override through per-class
466
+ * vtables (`virtualCall`) — everything else stays a direct `call`. */
467
+ classes?: IrClassDef[];
468
+ /** Module-level variables (file-scope `const`/`let` of every source
469
+ * file). Stable storage for the whole program: cross-module live
470
+ * bindings, and functions can reference them directly (no capture —
471
+ * globals are never boxed). Initialized by assignments inside the
472
+ * per-file `%init.<i>` functions; ids live in a distinct "%g." namespace so
473
+ * they can never collide with function-local ids. */
474
+ globals?: IrGlobal[];
475
+ /** The embedded npm runtime graph (--dynamic builds with npm imports):
476
+ * every reached module's SOURCE, keyed by resolved path, plus the
477
+ * (importer, specifier) → target edges the island's module loader and
478
+ * require shim resolve against. Emitted as static strings — binaries
479
+ * never read node_modules at runtime. Edge targets are module keys or
480
+ * "node:*" builtins (island-shimmed). */
481
+ embedded?: {
482
+ /** `esm` (CommonJS modules only) is the synthesized ESM facade the
483
+ * island loader evaluates when an ES module imports the CJS file:
484
+ * default plus the named exports LEXED from the source at build time
485
+ * (cjs-lexer.ts — the compiler's port of Node's vendored CJS lexer). */
486
+ modules: {
487
+ key: string;
488
+ source: string;
489
+ format: "esm" | "cjs" | "json";
490
+ esm?: string;
491
+ }[];
492
+ /** `kind` picks Node's "exports" condition set per CALL FORM: one
493
+ * (from, specifier) can name a dual package's ESM entry behind an
494
+ * "import" edge AND its CJS entry behind a "require" edge; "any"
495
+ * serves both lookups (relative files, builtins). */
496
+ edges: {
497
+ from: string;
498
+ specifier: string;
499
+ to: string;
500
+ kind: "any" | "import" | "require";
501
+ }[];
502
+ };
503
+ /** Record shapes, in first-seen (`r0`, `r1`, ...) order. Fields are in
504
+ * CANONICAL order (sorted by name) — the shape's identity; a `recordLit`'s
505
+ * fields stay in source order (evaluation order) independently. The
506
+ * frontend guarantees structural dedup: no two entries share a canonical
507
+ * field list. Backends emit one struct per shape, exactly like classes. */
508
+ records?: IrRecordShape[];
509
+ /** Tagged unions, in first-seen (`u0`, `u1`, ...) order. `arms` are in
510
+ * CANONICAL order (sorted by typeKey) — the union's identity; the arm's
511
+ * INDEX in this list is its runtime tag. The frontend guarantees
512
+ * structural dedup and that arms are pairwise-distinct IR types, none of
513
+ * them void/func/union (the unit kinds undefinedT/nullT ARE valid arms —
514
+ * union membership is the only place they exist). */
515
+ unions?: IrUnionDef[];
516
+ /** Name of the synthetic function holding top-level statements. */
517
+ entry: string;
518
+ }
519
+ export interface IrClassDef {
520
+ name: string;
521
+ /** The JS-observable `.name` of the class (the runtime class object's
522
+ * name string, and what `C.name` folds to). Differs from `name` because
523
+ * IR names are program-qualified (`%m1.C`, `%cx…` for class
524
+ * expressions); jsName follows NamedEvaluation — the declared name, the
525
+ * binding name for `const x = class {}`, or "" for truly anonymous
526
+ * expressions. Absent on the runtime-provided defs (never valuable). */
527
+ jsName?: string;
528
+ /** RUNTIME-PROVIDED class (the builtin Error hierarchy): the struct, RC
529
+ * helpers, and vtable live in the runtime (ScrError / scr_error_*), so
530
+ * backends emit no definitions for it — only the preorder-interval
531
+ * stamping in main() (the intervals are program-dependent; see
532
+ * RUNTIME_ERROR_CLASSES). User subclasses are ordinary emitted classes
533
+ * whose layout prefix embeds ScrError's fields. */
534
+ runtime?: true;
535
+ /** Base class name (single inheritance, `extends`). A class is IN A
536
+ * HIERARCHY when it has a base or is some class's base; hierarchy classes
537
+ * carry a vtable word after `rc` (backends), standalone classes are laid
538
+ * out exactly as before inheritance existed. */
539
+ base?: string;
540
+ /** ALL fields in layout order: the base chain's fields first — an
541
+ * IDENTICAL prefix, so an upcast is a pointer reinterpret and base-field
542
+ * offsets agree through any static type — then this class's own fields.
543
+ * The validator enforces the prefix property. */
544
+ fields: {
545
+ name: string;
546
+ type: IrType;
547
+ }[];
548
+ /** Method names DECLARED on this class (not inherited), in declaration
549
+ * order. Every entry EXCEPT the ones listed in `abstractMethods` has a
550
+ * module function `%<name>.<method>`; the backend derives vtable layout
551
+ * and devirtualization from these plus the base links (a method
552
+ * overridden nowhere keeps direct static calls). Accessors appear as
553
+ * `get:<prop>` / `set:<prop>` entries — names no user identifier can
554
+ * spell — and behave as ordinary methods here. */
555
+ methods?: string[];
556
+ /** Declared `abstract class` — never instantiated (tsc rejects `new` on
557
+ * it, including through class values), so its own vtable entries for
558
+ * abstract slots may stay empty. */
559
+ abstract?: true;
560
+ /** The subset of `methods` declared `abstract` (bodies are type-world):
561
+ * no module function exists for them. They still declare vtable slots —
562
+ * the slot's ABI signature comes from any concrete override (the
563
+ * frontend's override-exactness rule makes every implementation ABI-
564
+ * identical), and tsc guarantees each instantiable class in the
565
+ * declaring subtree implements them. */
566
+ abstractMethods?: string[];
567
+ /** GENERIC-CLASS INSTANTIATIONS only (`Box%0` for `Box<number>` — the
568
+ * generic-fn mangle): the FAMILY class's IR name — the synthetic,
569
+ * never-constructed ancestor registered under the generic class's own
570
+ * name that every instantiation extends. JS has ONE `Box` at runtime, so
571
+ * the instantiation's emitted CLASS OBJECT carries the family's preorder
572
+ * interval (instanceof through a class value answers for the whole
573
+ * family, exactly Node); everything else about the instantiation is an
574
+ * ordinary class. The validator checks the family is an ancestor. */
575
+ genericOf?: string;
576
+ loc: SrcLoc;
577
+ }
578
+ /** The runtime-provided error classes, keyed by IR class name. The names
579
+ * are '%'-prefixed ('%' cannot appear in a TS identifier, so a user's own
580
+ * `class Error` can never collide). `lib` is the standard-library name the
581
+ * frontend recognizes; `kind` is the runtime's SCR_ERR_* index (backends
582
+ * stamp scr_error_vts[kind] and pick constructor kinds by it). Every
583
+ * emitted module carries all four class defs (flagged `runtime`) so the
584
+ * program's preorder numbering always covers them — the runtime's own
585
+ * throws (JSON/dynCheck/regex) mint instances of these classes whether or
586
+ * not user code mentions Error. */
587
+ export declare const RUNTIME_ERROR_CLASSES: ReadonlyMap<string, {
588
+ lib: string;
589
+ kind: number;
590
+ base: string | null;
591
+ }>;
592
+ /** The runtime-provided node:events EventEmitter class (ScrEmitter /
593
+ * scr_emitter_*, scr_events_emitter.c — link-gated by moduleUsesEmitter,
594
+ * so unlike the error classes its def rides a module only when the
595
+ * program touches the surface). The '%' name keeps it clear of user
596
+ * identifiers, exactly like the error classes. Backends emit no struct/
597
+ * RC/vtable for it; user subclasses embed the ScrEmitter prefix (the
598
+ * registry pointer and the display-name slot, stamped by the emitted
599
+ * allocation) and main() stamps the runtime vtable's preorder interval.
600
+ * The emitter hierarchy is UNCONDITIONALLY cycle-capable: the registry
601
+ * owns listener closures, whatever the subclass fields say. */
602
+ export declare const RUNTIME_EMITTER_CLASS = "%EventEmitter";
603
+ /** The runtime-provided node:stream classes (ScrStream / scr_stream_*,
604
+ * scr_stream.c — link-gated by moduleUsesStream). They root at the
605
+ * emitter class (base chains below), so the emitter method surface and
606
+ * upcasts apply unchanged; every instance shares ONE runtime layout (the
607
+ * ScrEmitter prefix plus a lazily-allocated stream-state pointer), so a
608
+ * Duplex upcast to Readable is the usual pointer reinterpret. `sides`
609
+ * names which halves the class carries — the lowering admits readable
610
+ * members on "r"-siders, writable members on "w"-siders. User `extends`
611
+ * compiles (phase 2): subclass structs embed the full ScrStream prefix
612
+ * (registry, display name, state pointer — one slot past the emitter
613
+ * prefix), construction runs the emitted allocation then a stream .init
614
+ * libCall at super(options), and overridden underscore methods bind as
615
+ * synthesized wrapper closures dispatching through the vtable; main()
616
+ * stamps each runtime vtable's preorder interval like the emitter's. */
617
+ export declare const RUNTIME_STREAM_CLASSES: ReadonlyMap<string, {
618
+ lib: string;
619
+ base: string;
620
+ sides: "r" | "w" | "rw";
621
+ }>;
622
+ export interface IrRecordShape {
623
+ /** Frontend-assigned shape id (`r0`, `r1`, ...). */
624
+ id: string;
625
+ /** Sorted by field name (canonical order). Types are never void. */
626
+ fields: {
627
+ name: string;
628
+ type: IrType;
629
+ }[];
630
+ /** A TUPLE shape (`[string, number]`): fields are exactly "0".."n-1" —
631
+ * one per position, arity = fields.length. Same struct/RC/trace emission
632
+ * as any record; the flag changes the SURFACE (literal-index access,
633
+ * constant length, JSON as an array with exact-arity validation) and is
634
+ * part of the shape's interned identity, keeping tuples distinct from
635
+ * numeric-keyed object records (which serialize as objects). */
636
+ tuple?: true;
637
+ /** A STRING INDEX SIGNATURE's value type (`{ input?: string;
638
+ * [key: string]: unknown }`, `Record<string, string>`): the shape is a
639
+ * HYBRID — declared fields keep their static struct slots (field access
640
+ * stays a struct read), and undeclared keys live in an OVERFLOW map the
641
+ * struct embeds (string-keyed, insertion-ordered, values uniformly this
642
+ * type). Part of the interned identity: `{a: string}` with and without
643
+ * an index signature are distinct shapes. `unknown` values are `dyn`
644
+ * (the ONE position besides locals/params where dyn rides a container —
645
+ * internal to the shape, reads surface it as an ordinary dyn value);
646
+ * otherwise the supported value kinds mirror map values. Never combined
647
+ * with `tuple`. dynCheck against such a shape CAPTURES undeclared keys
648
+ * into the overflow (width tolerance becomes width capture — see
649
+ * dynCheck), and JSON serialization appends overflow entries after the
650
+ * declared fields in insertion order. */
651
+ indexValue?: IrType;
652
+ /** Field names in FIRST-SEEN declaration order (the checker's property
653
+ * order of the first ts.Type interned to this shape) — metadata, NOT
654
+ * part of the interned identity: a later structurally-equal type with a
655
+ * different member order shares the shape and the first one's order.
656
+ * JSON.stringify, Object.keys/values/entries, record→DOM conversion,
657
+ * and util.inspect all emit this order; JS's per-object insertion order
658
+ * matches it whenever objects are constructed in declaration order
659
+ * (SEMANTICS.md 36 documents the divergence when they are not).
660
+ * Absent on tuples (positional by construction). Names the shape's
661
+ * fields carry that declaredOrder OMITS are internal '%'-fields (Dirent's
662
+ * %dtype) — hidden from every key-order surface, JSON included. */
663
+ declaredOrder?: string[];
664
+ }
665
+ /** Object-literal ACCESSOR properties (`{ get x() {...}, set x(v) {...} }`)
666
+ * live on the shape as reserved '%'-fields holding closures: `%get:x` a
667
+ * `() => T` invoked once per property READ (side effects and all — JS's
668
+ * evaluation), `%set:x` a `(v: T) => void` invoked per WRITE. The property
669
+ * name itself has NO data slot. Like every '%'-field the slots stay out of
670
+ * declaredOrder — and because the slot types are funcs, accessor-carrying
671
+ * shapes are never JSON-safe or dyn-convertible; the enumeration surfaces
672
+ * Node would answer differently (Object.keys includes accessor names,
673
+ * values/entries and spread invoke the getters) fence by name at their
674
+ * lowerings. */
675
+ export declare function accessorSlotProp(fieldName: string): {
676
+ kind: "get" | "set";
677
+ prop: string;
678
+ } | null;
679
+ /** True when the shape carries at least one accessor slot (see
680
+ * accessorSlotProp) — the predicate behind every enumeration-surface
681
+ * fence. */
682
+ export declare function shapeHasAccessorSlots(shape: IrRecordShape): boolean;
683
+ export interface IrUnionDef {
684
+ /** Frontend-assigned union id (`u0`, `u1`, ...). */
685
+ id: string;
686
+ /** ≥2 pairwise-distinct arm types in canonical (typeKey-sorted) order;
687
+ * an arm's index here is its runtime tag. Never void/func/union; the
688
+ * unit kinds (undefinedT/nullT) are payload-less arms. */
689
+ arms: IrType[];
690
+ }
691
+ export interface IrFunction {
692
+ /** Original TS name (mangling is a backend concern). Lifted lambdas get
693
+ * synthetic '%'-prefixed names ('%' can't appear in a TS identifier). */
694
+ name: string;
695
+ params: IrParam[];
696
+ returnType: IrType;
697
+ /** All locals including params, pre-collected and scope-flat: ids are
698
+ * unique per function ("x.0", "x.1" for shadowing). The frontend resolves
699
+ * lexical scoping; backends and future SSA both want exactly this. */
700
+ locals: IrLocal[];
701
+ /** Present on lifted functions that capture enclosing bindings: the boxed
702
+ * variables received through the closure environment, in caps[] order.
703
+ * Each is also listed in `locals` (with boxed: true); it is NOT a param. */
704
+ captures?: IrParam[];
705
+ /** Async: the body runs on a fiber; `returnType` is the INNER type T (a
706
+ * `return v` fulfills with v) while call sites receive Promise<T>. */
707
+ async?: true;
708
+ /** Generator (`function*`): the body runs on a fiber created SUSPENDED
709
+ * (nothing runs until the first `.next()`); `returnType` is the
710
+ * generator's TReturn (VOID when it carries no value — `return;`
711
+ * completes with the undefined arm) while call sites receive the
712
+ * generator type `{ yieldT, retT: returnType, nextT }` from an emitted
713
+ * spawn wrapper that only allocates. `yieldT` is what `yield e` sends
714
+ * out, `nextT` what `.next(v)` sends in (the yield expression's result
715
+ * type). Mutually exclusive with `async` (async generators are fenced). */
716
+ generator?: {
717
+ yieldT: IrType;
718
+ nextT: IrType;
719
+ };
720
+ body: IrStmt[];
721
+ loc: SrcLoc;
722
+ }
723
+ export interface IrParam {
724
+ localId: string;
725
+ name: string;
726
+ type: IrType;
727
+ }
728
+ export interface IrGlobal {
729
+ /** "%g.<qualifier>.<name>" — distinct namespace from local ids. */
730
+ id: string;
731
+ name: string;
732
+ type: IrType;
733
+ mutable: boolean;
734
+ }
735
+ export interface IrLocal {
736
+ id: string;
737
+ name: string;
738
+ type: IrType;
739
+ mutable: boolean;
740
+ /** Captured by a nested function: the variable lives in a refcounted box
741
+ * (a shared binding — mutations are visible through every capture). All
742
+ * access, including in the declaring function, goes through the box. */
743
+ boxed?: true;
744
+ /** A forward-captured const (a function declared BEFORE the const it
745
+ * captures): the box is allocated TDZ-empty at scope entry (a `varDecl`
746
+ * with `init: null`) so earlier closures can capture it, and the source
747
+ * declaration initializes it via `assign`. Every read tests the box —
748
+ * empty throws JS's catchable ReferenceError ("Cannot access 'name'
749
+ * before initialization"), exactly Node's temporal dead zone. Always
750
+ * paired with `boxed`; restricted to pointer-backed types (the NULL slot
751
+ * IS the TDZ sentinel). Capture entries inherit the flag. */
752
+ tdz?: true;
753
+ }
754
+ export type IrStmt =
755
+ /** First initialization of a local at its source position. `init: null`
756
+ * means "declared, uninitialized" (`let x: number;`) — the local must be
757
+ * `mutable`. SOUNDNESS: tsc strict-mode definite-assignment analysis
758
+ * (TS2454 "used before being assigned") rejects any READ before an
759
+ * assignment on every path, so backends never need a runtime
760
+ * initialized-check; refcounted locals simply stay NULL until the first
761
+ * `assign`. */
762
+ {
763
+ kind: "varDecl";
764
+ localId: string;
765
+ init: IrExpr | null;
766
+ loc: SrcLoc;
767
+ } | {
768
+ kind: "assign";
769
+ localId: string;
770
+ value: IrExpr;
771
+ loc: SrcLoc;
772
+ } | {
773
+ kind: "exprStmt";
774
+ expr: IrExpr;
775
+ loc: SrcLoc;
776
+ } | {
777
+ kind: "if";
778
+ cond: IrExpr;
779
+ then: IrStmt[];
780
+ else_: IrStmt[] | null;
781
+ loc: SrcLoc;
782
+ }
783
+ /** `labels` (here and on doWhile/for/forOf/switch/block): the JS label
784
+ * names of the enclosing `lbl:` statements, outermost first — the targets
785
+ * a labeled `break lbl`/`continue lbl` names. A statement without labels
786
+ * omits the field. The frontend attaches labels only to constructs a
787
+ * labeled jump can bind to (loops, switch, and the block wrapper it puts
788
+ * around every other labeled statement form); label RESOLUTION is done by
789
+ * matching a jump's `label` against the innermost enclosing statement
790
+ * whose `labels` contains it (names are unique per nesting chain — tsc
791
+ * rejects duplicate labels). */
792
+ | {
793
+ kind: "while";
794
+ cond: IrExpr;
795
+ body: IrStmt[];
796
+ labels?: string[];
797
+ loc: SrcLoc;
798
+ }
799
+ /** `do { body } while (cond)`: body executes at least once; the condition
800
+ * (bool-typed, truthiness pre-wrapped like while) evaluates after each
801
+ * pass. `continue` jumps to the CONDITION, not the top of the body. */
802
+ | {
803
+ kind: "doWhile";
804
+ body: IrStmt[];
805
+ cond: IrExpr;
806
+ labels?: string[];
807
+ loc: SrcLoc;
808
+ }
809
+ /** JS-exact switch. The discriminant evaluates exactly once; case `test`
810
+ * expressions evaluate lazily IN SOURCE ORDER (a test after the matching
811
+ * one never evaluates), compared against the discriminant with strict
812
+ * equality (f64/bool: `===`; string: content equality). `test: null` is
813
+ * the default clause — it may appear in any position: it is entered only
814
+ * after every test misses, but execution FALLS THROUGH case bodies in
815
+ * source order (default's included) until a `break` or the end. The whole
816
+ * case-body sequence is ONE lexical scope (a `let` in one case is visible
817
+ * in later cases). `break` inside binds to the switch; `continue` binds to
818
+ * the enclosing loop. Discriminant and tests share one IR kind:
819
+ * f64, string, or bool. */
820
+ | {
821
+ kind: "switch";
822
+ disc: IrExpr;
823
+ cases: {
824
+ test: IrExpr | null;
825
+ body: IrStmt[];
826
+ }[];
827
+ labels?: string[];
828
+ loc: SrcLoc;
829
+ } | {
830
+ kind: "for";
831
+ init: IrStmt | null;
832
+ cond: IrExpr | null;
833
+ update: IrStmt | null;
834
+ body: IrStmt[];
835
+ labels?: string[];
836
+ loc: SrcLoc;
837
+ }
838
+ /** Element write `a[i] = v` — statement-only, like `assign`. Valid indices
839
+ * are [0, length]; i == length appends (JS would create a hole past that —
840
+ * scriptc traps instead, see SEMANTICS.md). Ownership of a refcounted
841
+ * value MOVES into the array; the replaced element is released. */
842
+ | {
843
+ kind: "arraySet";
844
+ arr: IrExpr;
845
+ index: IrExpr;
846
+ value: IrExpr;
847
+ loc: SrcLoc;
848
+ }
849
+ /** Typed-array element write `b[i] = v` — arraySet's sibling for bytes
850
+ * receivers: statement-only, receiver and index like bytesIntrinsic
851
+ * `get` (any invalid index TRAPS — JS would ignore the write, a
852
+ * documented divergence), value an f64 coerced per the element kind
853
+ * (ToUint8/ToUint32 modular truncation, double→float rounding). Unlike
854
+ * arraySet there is NO append at i == len: typed arrays are
855
+ * fixed-length. */
856
+ | {
857
+ kind: "bytesSet";
858
+ arr: IrExpr;
859
+ index: IrExpr;
860
+ value: IrExpr;
861
+ loc: SrcLoc;
862
+ }
863
+ /** `for (const x of arr)`: iterates by ascending index, re-reading the
864
+ * length each iteration (JS-exact for arrays). `localId` is a fresh const
865
+ * binding per iteration holding the element (for refcounted elements: an
866
+ * owned +1 reference, released when the iteration's scope exits). */
867
+ | {
868
+ kind: "forOf";
869
+ localId: string;
870
+ iterable: IrExpr;
871
+ body: IrStmt[];
872
+ labels?: string[];
873
+ loc: SrcLoc;
874
+ } | {
875
+ kind: "return";
876
+ value: IrExpr | null;
877
+ loc: SrcLoc;
878
+ }
879
+ /** Field write `obj.f = v` — statement-only, like `assign`/`arraySet`.
880
+ * Evaluation order: obj, then value. The old value is released; ownership
881
+ * of a refcounted new value MOVES into the object. */
882
+ | {
883
+ kind: "fieldSet";
884
+ obj: IrExpr;
885
+ className: string;
886
+ field: string;
887
+ value: IrExpr;
888
+ loc: SrcLoc;
889
+ }
890
+ /** Record field write `r.f = v` — mirrors `fieldSet` exactly (evaluation
891
+ * order obj then value; old value released; refcounted new value moved
892
+ * in), with a shape id in place of a class name. */
893
+ | {
894
+ kind: "recordSet";
895
+ obj: IrExpr;
896
+ shapeId: string;
897
+ field: string;
898
+ value: IrExpr;
899
+ loc: SrcLoc;
900
+ }
901
+ /** Dynamic-keyed record write `r[k] = v` — index-signature shapes only.
902
+ * `value` has the index signature's value type (dyn included). Declared
903
+ * keys write THROUGH to the struct slot: a dyn value validates against
904
+ * the field's type first (the dynCheck walker — a mismatched write
905
+ * throws the catchable TypeError instead of corrupting the slot; JS
906
+ * would store anything, a documented divergence), non-dyn values store
907
+ * directly (their type equals the field's by the index-signature
908
+ * consistency rule). Undeclared keys insert/replace in the overflow map
909
+ * (insertion order preserved, exactly Map). Evaluation order: obj, key,
910
+ * value. Ownership of a refcounted value MOVES in; replaced values are
911
+ * released. MAY THROW when the shape has dyn-valued declared fields to
912
+ * validate (the emitted helper is in the may-throw seed set then).
913
+ * `overflowOnly` (a LITERAL key naming no declared field): a pure
914
+ * overflow insert — no declared collision exists, so no validation, no
915
+ * throw, and declared fields need not take the index-value type. */
916
+ | {
917
+ kind: "recordKeySet";
918
+ obj: IrExpr;
919
+ shapeId: string;
920
+ key: IrExpr;
921
+ value: IrExpr;
922
+ overflowOnly?: true;
923
+ loc: SrcLoc;
924
+ }
925
+ /** Statement-position `delete obj[k]` on a PURE index-signature shape
926
+ * (no declared fields — the frontend fences hybrids: a struct slot
927
+ * cannot be removed): drop the overflow entry, releasing its key and
928
+ * value — exactly a Map delete, insertion order of survivors kept.
929
+ * Deleting an absent key is a no-op, like JS. Evaluation order: obj,
930
+ * key; both borrowed. Never throws. */
931
+ | {
932
+ kind: "recordKeyDelete";
933
+ obj: IrExpr;
934
+ shapeId: string;
935
+ key: IrExpr;
936
+ loc: SrcLoc;
937
+ }
938
+ /** Unlabeled: `break` binds to the innermost enclosing loop OR switch
939
+ * (labeled BLOCK targets are skipped); `continue` to the innermost
940
+ * enclosing loop, skipping any switches in between (validated). With
941
+ * `label`: the jump binds to the innermost enclosing statement whose
942
+ * `labels` contains it — any labeled loop/switch/block for `break`, a
943
+ * labeled loop for `continue` (`continue` re-enters at the loop's own
944
+ * continue point: the condition for while/doWhile, the update for
945
+ * for/forOf). The frontend guarantees the label resolves (tsc validates
946
+ * label targets); the validator re-checks. */
947
+ | {
948
+ kind: "break";
949
+ label?: string;
950
+ loc: SrcLoc;
951
+ } | {
952
+ kind: "continue";
953
+ label?: string;
954
+ loc: SrcLoc;
955
+ }
956
+ /** A bare lexical block `{ ... }` — its own scope. `labels` makes it a
957
+ * labeled-break target (`lbl: { ... break lbl; ... }` and the wrapper
958
+ * the frontend puts around labeled non-loop statements). */
959
+ | {
960
+ kind: "block";
961
+ body: IrStmt[];
962
+ labels?: string[];
963
+ loc: SrcLoc;
964
+ }
965
+ /** `throw v`. Any non-void value type can be thrown; ownership of a
966
+ * refcounted value MOVES into the runtime's exception cell. Terminates
967
+ * the path like `return`: control unwinds to the innermost enclosing
968
+ * tryCatch handler, or out of the function (backends release the frames
969
+ * and scopes the unwind exits — exactly the release-on-jump discipline). */
970
+ | {
971
+ kind: "throw";
972
+ value: IrExpr;
973
+ loc: SrcLoc;
974
+ }
975
+ /** A DEFERRED compile fence (JavaScript sources only): the statement's
976
+ * construct has no static lowering, and JS carries no annotations to
977
+ * change that — so the fence fires when the statement RUNS instead of
978
+ * failing the build (the JS-input design: inference gaps land where
979
+ * `any` lands — honest fences, never silent misbehavior). Executing it
980
+ * throws a catchable Error whose message names the construct and whose
981
+ * `code` carries the SC diagnostic code; unwinds exactly like `throw`.
982
+ * TypeScript sources produce it only as the tsc-unreachable fallthrough
983
+ * trap (appendImplicitUndefinedReturn's SC9002) — their construct fences
984
+ * stay compile errors. */
985
+ | {
986
+ kind: "runtimeFence";
987
+ code: string;
988
+ message: string;
989
+ loc: SrcLoc;
990
+ }
991
+ /** Rethrow of a catch binding (`throw e` where e is the binding):
992
+ * re-raises the SAVED exception exactly — kind and payload preserved,
993
+ * payload retained (the binding stays live until its scope exits).
994
+ * Terminates the path like `throw`. */
995
+ | {
996
+ kind: "rethrow";
997
+ localId: string;
998
+ loc: SrcLoc;
999
+ }
1000
+ /** `try { } catch (e)? { } finally { }`. At least one of
1001
+ * catchBody/finallyBody is present. `catchBody` runs iff the try body
1002
+ * raised; entering it TAKES the exception (the pending flag clears).
1003
+ * With `catchLocalId` null (bindingless `catch { }`) the payload is
1004
+ * discarded; with a binding, the payload MOVES into a fresh caught
1005
+ * snapshot box bound to that local (declared in `locals` with the
1006
+ * `caught` type), scoped to the catch body. `finallyBody` runs on normal
1007
+ * completion AND on the exception path (after catch, or with the
1008
+ * exception still pending when there is no catch — it keeps propagating
1009
+ * after the finally completes; a throw inside the finally replaces it).
1010
+ * A `return` inside tryBody/catchBody additionally runs the finally on
1011
+ * its way out (the backend's PENDING-RETURN path: the value is computed
1012
+ * and snapshotted FIRST, every crossed finally runs inner-to-outer, then
1013
+ * the function returns — finally mutations of returned locals are
1014
+ * invisible, Node-exact; a throw inside such a finally replaces the
1015
+ * pending return, releasing the snapshot). The frontend still rejects
1016
+ * break/continue crossing a try-with-finally and ANY jump out of a
1017
+ * finally body, so normal, exception, and pending-return are the only
1018
+ * completions a finally sees; plain try/catch has no such restriction
1019
+ * (jumps out release the try scopes like any other jump). Each body is
1020
+ * its own lexical scope. */
1021
+ | {
1022
+ kind: "tryCatch";
1023
+ tryBody: IrStmt[];
1024
+ catchBody: IrStmt[] | null;
1025
+ catchLocalId: string | null;
1026
+ finallyBody: IrStmt[] | null;
1027
+ loc: SrcLoc;
1028
+ };
1029
+ /** The complete array method/property surface (mirrors ambient/scriptc.d.ts).
1030
+ * `map`/`filter`/`forEach` are NOT here: the frontend desugars them to
1031
+ * synthetic loop functions over existing nodes (see docs/ir.md). */
1032
+ /** `slice` is JS-exact shallow copy (ToIntegerOrInfinity indices, negatives
1033
+ * from the end, clamping; omitted args omitted from `args` — backends fill
1034
+ * 0 / +Infinity, the strIntrinsic convention); ref elements retain into
1035
+ * the fresh array. */
1036
+ export type IrArrIntrinsicMethod = "length" | "push" | "pushSpread" | "pop" | "indexOf" | "includes" | "join" | "slice" | "shift" | "splice";
1037
+ /** The Map method/property surface (mirrors ambient/scriptc.d.ts) plus the
1038
+ * iteration primitives behind the forEach desugar. `forEach` itself is NOT
1039
+ * here — like array map/filter/forEach it desugars in the frontend to a
1040
+ * synthetic loop function whose body walks the dense entries array with
1041
+ * `iterCount`/`iterLive`/`iterKey`/`iterValue` (indices stay stable under
1042
+ * callback mutation because the runtime never compacts between
1043
+ * `iterEnter`/`iterExit` — live-iteration semantics, Node-exact). The iter*
1044
+ * members are compiler-internal: no ambient declaration reaches them. */
1045
+ export type IrMapIntrinsicMethod = "get" | "set" | "has" | "delete" | "size" | "clear" | "iterCount" | "iterLive" | "iterKey" | "iterValue" | "iterEnter" | "iterExit";
1046
+ /** The Set method/property surface — Map's minus get/set/iterValue (there
1047
+ * is no value slot; `add` fills set's role) plus `add`. `forEach` desugars
1048
+ * in the frontend exactly like Map's, over the same iteration primitives —
1049
+ * iterKey doubles as the element read (JS's Set forEach passes the element
1050
+ * as both `value` and `key`). */
1051
+ export type IrSetIntrinsicMethod = "add" | "has" | "delete" | "size" | "clear" | "iterCount" | "iterLive" | "iterKey" | "iterEnter" | "iterExit"
1052
+ /** `[...set]` and friends: drain the live entries into a FRESH elem[]
1053
+ * in insertion order (tombstones skipped — the same walk the forEach
1054
+ * desugar does, folded into one runtime call; no user code runs during
1055
+ * the drain, so live-iteration rules are moot). Receiver borrowed;
1056
+ * the array is owned (+1), string elements retained into it. */
1057
+ | "toArray";
1058
+ /** The complete string method/property surface (mirrors ambient/scriptc.d.ts).
1059
+ * toLowerCase/toUpperCase are the one lre-backed pair (ECMA Default Case
1060
+ * Conversion via libunicode's tables — scr_regex.c): their presence sets
1061
+ * the regex LINK flag like a regex literal does (moduleUsesRegex).
1062
+ * `split` is the STRING-separator form (regex separators are
1063
+ * regexIntrinsic), no limit: args[0] the separator, result a fresh +1
1064
+ * string[] — the empty separator splits per UTF-16 code unit (astral
1065
+ * halves become U+FFFD, divergence 2). `padStart`/`padEnd` take (target
1066
+ * length, fill) — the frontend completes an omitted fill to " ", Node's
1067
+ * default. `trimStart`/`trimEnd` are trim's one-sided halves. */
1068
+ export type IrStrIntrinsicMethod = "length" | "charCodeAt" | "charAt" | "indexOf" | "includes" | "startsWith" | "endsWith" | "slice" | "substring" | "repeat" | "trim" | "trimStart" | "trimEnd" | "split" | "padStart" | "padEnd" | "toLowerCase" | "toUpperCase" | "isWellFormed" | "toWellFormed" | "cpAt";
1069
+ /** The typed-array/Buffer method surface (bytesIntrinsic). Receiver/arg
1070
+ * conventions (validated): `length`/`byteLength` are property reads → f64;
1071
+ * `get` takes one f64 index → f64 (trap on any invalid index, like
1072
+ * arrayGet — the write side is the bytesSet STATEMENT); `slice` takes
1073
+ * 0–2 f64 relative indices (omitted args are OMITTED from `args`, like
1074
+ * strIntrinsic — backends fill start 0 / end +Infinity) → a fresh
1075
+ * same-elem bytes COPY (`subarray` lowers here too: copying is the
1076
+ * documented divergence); `setFrom` (`dst.set(src, offset?)`) takes a
1077
+ * same-elem bytes src and an optional f64 offset (omitted = 0) → void,
1078
+ * THROWS Node's RangeError on overflow (may-throw seed); `toString` takes
1079
+ * one string encoding arg (the frontend completes an omitted one to
1080
+ * "utf8" and fences non-literal / unsupported encodings; u8 receivers
1081
+ * only) → owned +1 string, never throws; the numeric families (u8
1082
+ * receivers only) carry their KIND as args[0], always a strLit the
1083
+ * backend maps to the runtime's tag: `readNum` [kind, offset] /
1084
+ * `writeNum` [kind, value, offset] cover the fixed widths (kind "u8",
1085
+ * "i8", then "u16be"/"u16le"-style width+endian tokens through "f64le");
1086
+ * `readNumVar` [kind, offset, byteLength] / `writeNumVar` [kind, value,
1087
+ * offset, byteLength] are the variable-width read/writeUIntLE family
1088
+ * (kind "ube"/"ule"/"ibe"/"ile"). All four THROW Node's RangeErrors on
1089
+ * bad values/offsets/byteLengths (may-throw seeds); writes return
1090
+ * offset + width. Receivers and args are BORROWED; refcounted
1091
+ * results are owned (+1).
1092
+ *
1093
+ * The DataView surface rides the same node (DataView maps to bytes<u8> —
1094
+ * at runtime a borrowed VIEW aliasing its owner's storage, so no aliasing
1095
+ * divergence exists): `byteOffset` is a property read → f64 (0 for owners,
1096
+ * the view's offset for a DataView); `dataViewNew` (`new
1097
+ * DataView(x.buffer, byteOffset?, byteLength?)`) takes the BYTES value x
1098
+ * as the receiver (the frontend peels the syntactic `.buffer`) and 0–2
1099
+ * f64 args (omitted args OMITTED, like slice) → a fresh bytes<u8> view
1100
+ * retaining x's owner, THROWS Node's RangeErrors on bad indices; the
1101
+ * `dvGet*` getters take one f64 byte offset plus, on the multi-byte kinds,
1102
+ * an optional bool littleEndian (omitted = big-endian, the JS default) →
1103
+ * f64, THROWING Node's constant "Offset is outside the bounds of the
1104
+ * DataView" RangeError on any bad offset. `dvGetBigUint64Number`/
1105
+ * `dvGetBigInt64Number` are the COMPOSED `Number(view.getBigUint64(...))`
1106
+ * lowerings — the bare bigint-returning calls are fenced, the wrapped
1107
+ * form converts the 8-byte integer to double exactly as Number(bigint). */
1108
+ export type IrBytesIntrinsicMethod = "length" | "byteLength" | "get" | "slice" | "setFrom" | "toString" | "readNum" | "writeNum" | "readNumVar" | "writeNumVar"
1109
+ /** The comparison/search/mutation surface (u8 receivers only; see the
1110
+ * runtime contract): `equals` [bytes] → bool (never throws);
1111
+ * `compareBuf` [bytes, 0-4 f64 index args — omitted args OMITTED,
1112
+ * Node skips their validation] → f64, THROWS; `indexOf`/`lastIndexOf`
1113
+ * [bytes needle, f64 align (2 = utf16le's even-offset stride), f64
1114
+ * byteOffset?] → f64 and `includes` → bool, never throw (byteOffset
1115
+ * coerces; omitted = Node's search-everything default); the *Num
1116
+ * flavors take [f64 value, f64 byteOffset?] (the value wraps & 0xFF);
1117
+ * `fill` [bytes pattern, 0-2 f64s] / `fillNum`
1118
+ * [f64, 0-2 f64s] / `fillStr` [string, strLit enc, 0-2 f64s] → the
1119
+ * RECEIVER (+1, chaining), THROW; `copy` [bytes target, 0-3 f64s] →
1120
+ * f64 copied count, THROWS; `swap16/32/64` [] → the receiver (+1,
1121
+ * in-place), THROW; `writeStr` [string, strLit enc, f64 offset, f64
1122
+ * length?] → f64 bytes written, THROWS. */
1123
+ | "equals" | "compareBuf" | "indexOf" | "lastIndexOf" | "includes" | "indexOfNum" | "lastIndexOfNum" | "includesNum" | "fill" | "fillNum" | "fillStr" | "copy" | "swap16" | "swap32" | "swap64" | "writeStr" | "byteOffset" | "dataViewNew" | "dvGetUint8" | "dvGetInt8" | "dvGetUint16" | "dvGetInt16" | "dvGetUint32" | "dvGetInt32" | "dvGetFloat32" | "dvGetFloat64" | "dvGetBigUint64Number" | "dvGetBigInt64Number";
1124
+ /** The bytesIntrinsic methods that can raise a catchable error — backends'
1125
+ * may-throw analyses seed on these exactly like MAY_THROW_LIB_FNS. */
1126
+ export declare const MAY_THROW_BYTES_METHODS: ReadonlySet<IrBytesIntrinsicMethod>;
1127
+ /** The regex operation surface. Receiver/arg conventions (validated):
1128
+ * `test` takes a regex receiver and one string arg (bool result); `source`
1129
+ * and `flags` are property reads on a regex receiver (owned string result);
1130
+ * `replace`/`replaceAll`/`split` take a STRING receiver with args[0] the
1131
+ * regex and (for the replaces) args[1] the replacement template — string
1132
+ * replacements only, function replacements are checker-rejected (the
1133
+ * ambient overloads accept only strings). `replaceAll` THROWS Node's
1134
+ * TypeError when the regex lacks /g and `split` THROWS on a pattern with
1135
+ * capture groups (JS would splice the captured values into the result) —
1136
+ * both catchable: backends' may-throw analyses must seed on these two
1137
+ * methods like a `throw`. */
1138
+ /** `match` takes a STRING receiver with args[0] the regex (non-g/y — the
1139
+ * frontend fences literal g/y flags; a g-flagged value reaching the
1140
+ * runtime aborts like test()) and produces the PROGRAM-DEPENDENT
1141
+ * `string[] | null` union: the matched slice [whole, ...captures] wrapped
1142
+ * into the array arm, or the interned null-arm instance for no match. A
1143
+ * NONPARTICIPATING capture holds "" where Node's slot is undefined
1144
+ * (SEMANTICS.md divergence). Never throws. */
1145
+ export type IrRegexIntrinsicMethod = "test" | "match"
1146
+ /** `s.matchAll(re)` — every match as its honest string[] slice (match's
1147
+ * rule), drained EAGERLY into a fresh string[][]: the lazy iterator is
1148
+ * unobservable across the lowered surface (strings are immutable; the
1149
+ * spec clones the regex at the call, so lastIndex games can't reach the
1150
+ * drain either). Non-global regexes THROW Node's exact TypeError
1151
+ * (catchable — replaceAll's stance). */
1152
+ | "matchAll"
1153
+ /** matchAll's companion-index form (the for-of-over-matchAll desugar):
1154
+ * args[1] is a number[] the drain ALSO fills with each match's UTF-16
1155
+ * start index — the row's `.index`, always present (every drained row
1156
+ * matched). Same result and throw contract as matchAll. */
1157
+ | "matchAllInto"
1158
+ /** `s.search(re)` — the first match's UTF-16 index, or -1. Symbol.search
1159
+ * neither reads nor writes lastIndex (a fresh exec from position 0), so
1160
+ * no g/y fence applies: /g is irrelevant and /y anchors at 0 — exactly
1161
+ * Node. Never throws. */
1162
+ | "search" | "source" | "flags" | "replace" | "replaceAll" | "split";
1163
+ /** The complete standard-library surface (mirrors ambient/scriptc.d.ts: the
1164
+ * `process` and `JSON` globals and `declare module "node:fs"`). A closed
1165
+ * union — every member has a signature in the validator's LIB_FN_SIGS and a
1166
+ * scr_* implementation in the runtime (scr_lib.c / scr_json.c). fs.*
1167
+ * failures and json.parse syntax errors THROW (catchable, via the runtime
1168
+ * exception cell); process.* members never throw. JSON.stringify is NOT a
1169
+ * libCall — it lowers to the type-directed `jsonStringify` node below.
1170
+ * island.eval (the internal __island_eval testing hook) exists only in
1171
+ * --dynamic builds — the frontend rejects it otherwise, so backends may
1172
+ * assume the island runtime is linked when they see it; island exceptions
1173
+ * bridge into the exception cell as catchable strings (may-throw). */
1174
+ export type IrLibFn = "island.eval"
1175
+ /** Load an embedded npm package's runtime entry in the island (cached by
1176
+ * the engine's module registry) and take one export: args are the entry
1177
+ * KEY (an embedded module's key, from IrModule.embedded) and the export
1178
+ * name — "default" for default imports, "*" for the namespace object.
1179
+ * --dynamic only, like island.eval; result is an owned jsval. May throw
1180
+ * (a package's top-level code can), bridged catchably. */
1181
+ | "island.import"
1182
+ /** Dynamic `import(spec)`: load a module through the island's module
1183
+ * system — an embedded module's key or a builtin shim's "node:x" key —
1184
+ * and answer an ENGINE promise of its namespace object (always a
1185
+ * promise, never a throw: load and evaluation failures REJECT it,
1186
+ * Node's shape). The frontend wraps the result in jsBridgePromise, so
1187
+ * awaiting parks the fiber and a rejection crosses catchably. --dynamic
1188
+ * only; result is an owned jsval holding the engine promise. */
1189
+ | "island.importDyn"
1190
+ /** A checked cast the boundary can never satisfy, DEFERRED to runtime:
1191
+ * `islandValue as Promise<T>` — the value is an ENGINE promise and T
1192
+ * has no validated exit (Node-typed async APIs put class-shaped
1193
+ * interfaces there), so instead of refusing the build the cast throws a
1194
+ * catchable TypeError AT THE CAST naming the target type (args: the
1195
+ * island value — evaluated, borrowed — and the type name). The result
1196
+ * type is the cast's mapped target (a typed dummy; the exception is
1197
+ * pending). Documented divergence: JS `as` never checks — like the dyn
1198
+ * boundary, a conversion that cannot happen throws instead of lying.
1199
+ * --dynamic only. */
1200
+ | "island.castFail" | "json.parse"
1201
+ /** Keyed WRITE on a dyn DOM value — `h.onDone = cb` / `h["k"] = v` on a
1202
+ * checked-dynamic object (args: receiver, key string, value — all
1203
+ * borrowed; the runtime copies the key and retains the value in). An
1204
+ * OBJ receiver sets the member (later writes win, insertion order
1205
+ * preserved — JS exactly); undefined/null throws Node's catchable
1206
+ * "Cannot set properties of undefined (setting 'k')"; every other kind
1207
+ * throws Node's STRICT-mode "Cannot create property 'k' on <kind>"
1208
+ * (sloppy mode would silently ignore — suite tests are 'use strict';
1209
+ * SEMANTICS.md notes the sloppy divergence: loud, never silent). Void
1210
+ * result; in the may-throw seed set. */
1211
+ | "dyn.keySet"
1212
+ /** Object.defineProperties over DOM values (args: target, descriptors —
1213
+ * both borrowed dyn; result: the target, +1 — JS's return value).
1214
+ * Value descriptors become plain own properties on OBJ and FUNC targets
1215
+ * (writable/enumerable/configurable accepted and IGNORED — DOM
1216
+ * properties are plain data properties, SEMANTICS.md); get/set
1217
+ * descriptors and non-object targets/descriptors throw catchably
1218
+ * (Node's TypeError texts; accessors the loud unsupported Error). In
1219
+ * the may-throw seed set. */
1220
+ | "dyn.defineProps"
1221
+ /** Bare `typeof v` on a dyn value AS A STRING (arg: the dyn value,
1222
+ * borrowed; result: an owned string) — the DOM kind's JS answer:
1223
+ * undefined→"undefined", null/object/array/bytes→"object" (JS's oldest
1224
+ * wart preserved), boolean/number/string by kind, function→"function".
1225
+ * Never throws. */
1226
+ | "dyn.typeof"
1227
+ /** toString() on a checked-dynamic receiver: runtime kind dispatch
1228
+ * (bytes decode per the literal encoding — utf8 default; strings,
1229
+ * numbers, booleans, arrays, objects answer JS-exactly; undefined and
1230
+ * null throw the catchable TypeError). */
1231
+ | "dyn.toString" | "fs.readFileSync"
1232
+ /** readFileSync(path) — the Buffer read (+1 bytes); throws catchably
1233
+ * like the utf8 form. */
1234
+ | "fs.readFileSyncBuf"
1235
+ /** readFileSync(path, enc) with a RUNTIME encoding (an untyped JS
1236
+ * parameter): undefined/null answer Buffers, utf8 a string, other real
1237
+ * encodings fence loudly, unknown names throw ERR_UNKNOWN_ENCODING. */
1238
+ | "fs.readFileSyncDyn" | "fs.writeFileSync" | "fs.appendFileSync" | "fs.existsSync" | "fs.mkdirSync" | "fs.rmSync" | "fs.rmdirSync" | "fs.readdirSync"
1239
+ /** node:path (scr_path.c ports BOTH of Node's implementations
1240
+ * function-by-function): the `path.*` family is posix, the
1241
+ * `path.win32*` family is Node v24's path.win32 byte-for-byte — the
1242
+ * frontend binds the bare module to the TARGET platform's family
1243
+ * (Node on Windows IS path.win32) and the path.posix / path.win32
1244
+ * namespaces to their own family everywhere. join and resolve take ONE
1245
+ * string[] arg — the frontend packs the variadic call's arguments into
1246
+ * an array literal. basename always receives its suffix (the frontend
1247
+ * completes an omitted one with "", a Node no-op). toNamespacedPath is
1248
+ * the posix identity and the win32 \\?\-prefixer. None of these throw;
1249
+ * the resolves consult the process cwd like Node's. */
1250
+ | "path.join" | "path.resolve" | "path.normalize" | "path.dirname" | "path.basename" | "path.extname" | "path.isAbsolute" | "path.relative" | "path.toNamespacedPath" | "path.win32Join" | "path.win32Resolve" | "path.win32Normalize" | "path.win32Dirname" | "path.win32Basename" | "path.win32Extname" | "path.win32IsAbsolute" | "path.win32Relative" | "path.win32ToNamespacedPath"
1251
+ /** node:os: homedir is $HOME else getpwuid(3); tmpdir is Node's env
1252
+ * cascade ($TMPDIR/$TMP/$TEMP else /tmp, one trailing slash trimmed).
1253
+ * os.platform() lowers to process.platform — one implementation. */
1254
+ | "os.homedir"
1255
+ /** os.release(): uname(2)'s release field — Node's own implementation
1256
+ * (the kernel version string, e.g. "24.6.0" on macOS 15). Interned; +1
1257
+ * per read. Never throws. */
1258
+ | "os.release"
1259
+ /** The os.userInfo() field trio (uv_os_get_passwd's slices): pw_name,
1260
+ * pw_shell, pw_dir — the PASSWD homedir, not os.homedir's $HOME-first
1261
+ * cascade (Node's own split). The frontend assembles the UserInfo
1262
+ * record from these plus getuid/getgid. +1 fresh strings; a passwd
1263
+ * lookup failure aborts (Node throws a system error there — no
1264
+ * compiled program path reaches it for the running uid). */
1265
+ | "os.userName" | "os.userShell" | "os.userHomedir" | "os.tmpdir"
1266
+ /** os.networkInterfaces(): getifaddrs(3) → the Dict<NetworkInterfaceInfo[]>
1267
+ * record, built inline by the emitter from a runtime snapshot (scr_lib.c).
1268
+ * The result type is the CALL SITE's mapped @types/node shape — a pure
1269
+ * index-signature record whose value is `Info[] | undefined`, Info a
1270
+ * two-record union (IPv4: scopeid `number | undefined` holding undefined;
1271
+ * IPv6: scopeid number) — verified structurally by the frontend. Rows
1272
+ * match libuv's filter (IFF_UP && IFF_RUNNING, AF_INET/AF_INET6; loopback
1273
+ * = internal; MACs from the interface's link-level sibling entry, zeros
1274
+ * when absent; cidr from the netmask's contiguous prefix, the null arm
1275
+ * when it is missing or non-contiguous). Key/row order follows the OS's
1276
+ * getifaddrs enumeration — Node itself does not guarantee an order.
1277
+ * Fresh +1 record; never throws (a getifaddrs failure yields {}). */
1278
+ | "os.networkInterfaces"
1279
+ /** `Math.max(...xs)` / `Math.min(...xs)` over one spread number[]
1280
+ * (scr_number.c): the JS fold exactly — any NaN element poisons the
1281
+ * result, ±0 order by the JS comparison (max prefers +0, min prefers
1282
+ * -0), and the empty array yields -Infinity / +Infinity like the
1283
+ * zero-argument calls. Borrows the array; never throws. */
1284
+ | "math.maxArr" | "math.minArr"
1285
+ /** `fs.readdirSync(path, { withFileTypes: true })` — Dirent rows over
1286
+ * one readdir pass (scr_lib.c's scandir snapshot; DT_UNKNOWN falls back
1287
+ * to lstat, Node's getDirents rule). The result type is the call site's
1288
+ * interned Dirent record array (name, parentPath, hidden %dtype in
1289
+ * libuv's UV_DIRENT encoding) — verified by the frontend; the emitter
1290
+ * assembles the rows from the snapshot. OS order, no "."/"..". Throws
1291
+ * Node's scandir errno error (may-throw seed set); fresh +1 array. */
1292
+ | "fs.readdirTypesSync"
1293
+ /** `Math.floor(x)` — C floor() IS the JS operation (NaN/±0/±Infinity
1294
+ * pass through bit-exactly). Never throws. */
1295
+ | "math.floor"
1296
+ /** `Math.min(a, b)` / `Math.max(a, b)` — the two-argument scalar forms
1297
+ * (scr_lib.c), JS-exact like the Arr folds: NaN poisons, max prefers +0
1298
+ * over -0 (min the reverse). C fmin/fmax are NOT these (they drop NaN).
1299
+ * Never throw. */
1300
+ | "math.min" | "math.max"
1301
+ /** `Math.random()` — a uniform double in [0,1) with the spec's 53-bit
1302
+ * granularity, drawn from arc4random_buf (the CSPRNG behind the crypto
1303
+ * lowerings). Same distribution as Node, NECESSARILY different sequence
1304
+ * (SEMANTICS.md 62 — no seeded sequence exists to match). Never throws. */
1305
+ | "math.random"
1306
+ /** Math.abs (C fabs — IS the JS operation) and Math.round (scr_lib.c:
1307
+ * ECMA half-toward-+Infinity with the exact-fraction comparison — C
1308
+ * round() is half-away-from-zero and floor(x+0.5) drifts at the
1309
+ * epsilon boundary). Borrow nothing; never throw. */
1310
+ | "math.abs" | "math.round"
1311
+ /** The static global parsers/tests (scr_string.c). num.parseInt is
1312
+ * ECMA-262 19.2.5 exactly — JS whitespace, sign, ToInt32 radix (the
1313
+ * frontend completes an omitted radix to 0 = the spec's "undefined":
1314
+ * base 10 with the 0x hex escape), longest digit prefix, and the exact
1315
+ * mathematical value correctly rounded (u64 fast path, bignum beyond —
1316
+ * overflow is ±Infinity). num.isNaN is the NaN self-test on an
1317
+ * already-number argument (tsc pins the argument to number, so no
1318
+ * ToNumber coercion exists to model). Borrow; never throw. */
1319
+ | "num.parseInt" | "num.isNaN"
1320
+ /** ES parseFloat (scr_string.c): the longest StrDecimalLiteral prefix
1321
+ * of the trimmed input (no hex, "Infinity" exact-case), NaN when none —
1322
+ * ECMA-262 19.2.4 over a string argument (non-string arguments keep the
1323
+ * fence: Node would ToNumber-coerce). Borrows; never throws. */
1324
+ | "num.parseFloat" | "num.fromString"
1325
+ /** The static URI component codecs (scr_string.c), ECMA-262 Encode/
1326
+ * Decode with the component sets over the runtime's UTF-8 strings.
1327
+ * str.encodeUriComponent percent-encodes every byte outside the
1328
+ * unreserved component set (ALPHA/DIGIT/- _ . ! ~ * ' ( )) as uppercase
1329
+ * %XX — the spec's per-code-point UTF-8 encoding IS a byte scan here —
1330
+ * and never throws (the spec's URIError case is an unpaired surrogate,
1331
+ * which cannot exist in well-formed UTF-8). str.decodeUriComponent
1332
+ * decodes %XX escapes bytewise (raw non-escape bytes copy through) and
1333
+ * requires the escaped bytes to form strictly valid UTF-8 (overlong
1334
+ * forms, surrogate code points, and >U+10FFFF refused, per UTF8-decode
1335
+ * without replacement); bad hex or an invalid sequence THROWS the
1336
+ * spec's URIError ("URI malformed"), catchable. Borrow; results +1. */
1337
+ | "str.encodeUriComponent" | "str.decodeUriComponent"
1338
+ /** RegExp.escape (ES2025): per-code-point EncodeForRegExpEscape —
1339
+ * leading ASCII alphanumeric hex-escapes, syntax characters and '/'
1340
+ * take a backslash, other punctuators/whitespace/line terminators
1341
+ * hex-escape, the rest passes through. Total; borrows; result +1. */
1342
+ | "regexp.escape"
1343
+ /** encodeURI: the same Encode() keeping the reserved set and '#'
1344
+ * unescaped — total like the component encoder. Borrow; result +1. */
1345
+ | "str.encodeUri"
1346
+ /** The WHATWG base64 globals (scr_string.c), Node-global since v16.
1347
+ * Arguments are borrowed DOM values — WebIDL ToString runs in the
1348
+ * runtime over the DOM kind (String(null) is "null": the html spec's
1349
+ * coercion, which Node's atob(null) exercises). str.atob decodes
1350
+ * forgiving-base64 (ASCII whitespace stripped, %4==0 strips up to two
1351
+ * '=', %4==1 refuses, leftover bits discarded) into the latin1 code
1352
+ * points as a string; a malformed input THROWS the catchable
1353
+ * DOMException InvalidCharacterError ("The string to be decoded is not
1354
+ * correctly encoded."). str.btoa encodes the string's code points as
1355
+ * base64; any code point over U+00FF THROWS InvalidCharacterError
1356
+ * ("Invalid character"). str.b64Missing is the zero-argument call of
1357
+ * either: always throws Node's TypeError [ERR_MISSING_ARGS] "The
1358
+ * \"input\" argument must be specified". Results +1. */
1359
+ | "str.atob" | "str.btoa" | "str.b64Missing"
1360
+ /** The fraction-digits-free Number.prototype formatters (scr_lib.c),
1361
+ * JS-exact: num.toExponential is toExponential() with the spec's
1362
+ * "as many digits as necessary" — the shortest correctly-rounded
1363
+ * mantissa, d[.ddd]e±X with no exponent zero-padding ("7e+0"); NaN and
1364
+ * ±Infinity answer their texts. num.toFixed0 is toFixed() at 0 digits —
1365
+ * the spec's closest-integer pick with ties toward +∞ on the magnitude
1366
+ * ("-2.5" → "-3"), |x| ≥ 1e21 falling back to ToString, and the "-0"
1367
+ * result for negative fractions rounding to zero. The explicit-digits
1368
+ * forms keep their island lowering. Results +1; never throw. */
1369
+ | "num.toExponential" | "num.toFixed0"
1370
+ /** `delete process.env[NAME]` — unsetenv(3): the mutation is visible to
1371
+ * every later read (process.envGet asks getenv fresh) and inherited by
1372
+ * spawned children, exactly Node. Statement position only (JS's boolean
1373
+ * result is constant true there). Borrows the name; never throws. */
1374
+ | "process.envUnset"
1375
+ /** node:url + the URL class (scr_url.c). url.new parses one absolute
1376
+ * URL string into an immutable URL value (+1) — invalid input THROWS a
1377
+ * catchable TypeError ("Invalid URL"), like Node's constructor. The
1378
+ * getters (borrowed receiver, +1 string) never throw; url.href doubles
1379
+ * as toString(). fileURLToPath has one libFn per receiver form (URL
1380
+ * value / string) — both THROW Node's TypeErrors on non-file schemes,
1381
+ * encoded slashes, and non-empty hosts. url.pathToFileURL resolves the
1382
+ * path (getcwd) and never throws. */
1383
+ | "url.new" | "url.protocol" | "url.host" | "url.hostname" | "url.pathname" | "url.href" | "url.fileURLToPathUrl" | "url.fileURLToPathStr" | "url.pathToFileURL"
1384
+ /** pathToFileURL under a win32 TARGET: the same scr_url_from_path call
1385
+ * (the runtime selects the win32 arm by _WIN32), but a distinct IR name
1386
+ * because that arm THROWS for malformed UNC inputs — may-throw seeds on
1387
+ * it while posix pathToFileURL emission stays byte-identical. */
1388
+ | "url.pathToFileURLWin32"
1389
+ /** URLSearchParams (scr_url.c — always linked with the url unit).
1390
+ * Construction: sp.new (empty), sp.parse (one borrowed init string —
1391
+ * a single leading '?' strips, Node's constructor), sp.copy (snapshot
1392
+ * of another list), sp.fromPairs (a string[][] value — THROWS Node's
1393
+ * ERR_INVALID_TUPLE TypeError on a non-[name, value] row; the one
1394
+ * throwing entry in the family), sp.with (the record-literal init
1395
+ * desugar: append one pair, answer the same list +1 — chains fold
1396
+ * `new URLSearchParams({...})` into nested calls). url.searchParams
1397
+ * answers the URL's LIVE cached view (+1, one identity per URL);
1398
+ * url.search is the WHATWG search getter ("" for no/empty query).
1399
+ * Methods mirror the WHATWG surface: sp.get answers +1-or-NULL (the
1400
+ * sym.desc union pattern, null arm), sp.getAll a fresh string[];
1401
+ * sp.append/sp.set/sp.delete/sp.deleteValue/sp.sort mutate and
1402
+ * re-serialize a live view's URL query; sp.has/sp.hasValue answer
1403
+ * bools; sp.size/sp.toString are pure reads. sp.keyAt/sp.valAt are
1404
+ * the for-of/forEach desugar's index reads (live — the loop re-reads
1405
+ * sp.size each pass). */
1406
+ | "sp.new" | "sp.parse" | "sp.copy" | "sp.fromPairs" | "sp.with" | "url.searchParams" | "url.search" | "sp.get" | "sp.getAll" | "sp.append" | "sp.set" | "sp.delete" | "sp.deleteValue" | "sp.has" | "sp.hasValue" | "sp.sort" | "sp.size" | "sp.toString" | "sp.keyAt" | "sp.valAt"
1407
+ /** ES Symbol values (scr_symbol.c — link-gated by moduleUsesSymbol).
1408
+ * sym.new: `Symbol(desc)` — a fresh runtime-unique identity (+1) whose
1409
+ * one arg is the description string (borrowed); sym.newAnon is the
1410
+ * description-less `Symbol()` form. sym.for: the Symbol.for global
1411
+ * registry — one interned symbol per key (borrowed), +1 on every call.
1412
+ * sym.toString: "Symbol(desc)" (+1 string; "Symbol()" when absent).
1413
+ * sym.desc / sym.keyFor answer the interned `string | undefined` union
1414
+ * (the runtime returns +1-or-NULL; the backend builds the union arms —
1415
+ * the child.stdout pattern). None of these throw. */
1416
+ | "sym.new" | "sym.newAnon" | "sym.for" | "sym.keyFor" | "sym.desc" | "sym.toString"
1417
+ /** fs.statSync → a Stats value (may throw, like the other sync fs
1418
+ * calls); the stats.* getters are pure reads on it. */
1419
+ | "fs.statSync" | "stats.isFile" | "stats.isDirectory" | "stats.size"
1420
+ /** child_process.spawnSync (scr_child.c): posix_spawn + waitpid + piped
1421
+ * utf8 capture — cmd borrowed, args one borrowed string[] (the frontend
1422
+ * completes an omitted list to an empty literal), result an owned (+1)
1423
+ * spawnRes. NEVER throws: spawn failure (nonexistent binary, EACCES) is
1424
+ * data, like Node's error property — status null and empty outputs
1425
+ * (SEMANTICS.md documents the divergence from Node's null stdout).
1426
+ * The getters are pure reads: status is the interned `number | null`
1427
+ * union (null = spawn failure or signal death, type-directed
1428
+ * construction in the backend like process.envGet); stdout/stderr are
1429
+ * +1 strings. */
1430
+ | "cp.spawnSync" | "spawnRes.status" | "spawnRes.stdout" | "spawnRes.stderr"
1431
+ /** Node's spawn-failure carrier `error?: Error`: a fresh +1 %Error
1432
+ * ("spawnSync <file> ENOENT", `code` stamped) when the spawn itself
1433
+ * failed, the interned undefined arm otherwise — the result type is the
1434
+ * call site's `Error | undefined` union, constructed type-directedly in
1435
+ * the backend (the envGet convention). Never throws. */
1436
+ | "spawnRes.error"
1437
+ /** child_process.spawn (scr_child.c + the scr_async.c loop): posix_spawnp
1438
+ * with stdio "ignore" (all three fds on /dev/null — the only supported
1439
+ * stdio; "pipe"/"inherit" are frontend-fenced), the child registered
1440
+ * with the event loop, which polls waitpid(WNOHANG) at quiescence like
1441
+ * timers (kqueue is the follow-up; SEMANTICS.md documents the polling).
1442
+ * NEVER throws: spawn failure defers to the "error" event, Node-exact
1443
+ * (the error message is Node's "spawn <cmd> <ERRNO-NAME>"; an "error"
1444
+ * event with no listener prints it and exits 1 like an EventEmitter).
1445
+ * cmd/args borrowed; result an owned (+1) child handle. The loop will
1446
+ * not exhaust while any spawned child is unreaped — Node's keep-alive.
1447
+ *
1448
+ * child.onExit / child.onError — `child.on("exit"|"error", cb)`: the
1449
+ * receiver is borrowed, the CALLBACK MOVES into the child's listener
1450
+ * registry (released after the terminal event fires, or at reap for
1451
+ * the event that never fires). Both are void (chaining is fenced).
1452
+ * onExit's third emitted ingredient is an ADAPTER the backend interns
1453
+ * per callback shape: the runtime invokes adapter(cb, has_code, code)
1454
+ * and the adapter builds the `number | null` union (tags are program-
1455
+ * dependent) or ignores the code for a zero-param callback. onError's
1456
+ * adapters are runtime-provided (zero-param, or the %Error one-param
1457
+ * shape — scr_error_new needs no program types). "exit" fires once
1458
+ * with the code (f64 arm) or null (signal death); "error" fires only
1459
+ * for spawn failure, exactly Node's split. */
1460
+ | "cp.spawn" | "child.onExit" | "child.onError"
1461
+ /** The ChildProcess lifecycle members (scr_child.c), Node's shapes
1462
+ * exactly (SEMANTICS.md has the pinned matrix). child.pid is the
1463
+ * checker's `number | undefined` (undefined = spawn failure) and
1464
+ * child.exitCode its `number | null` (null while running and after a
1465
+ * signal death; -errno once a spawn failure settled) — both unions are
1466
+ * type-directed constructions in the backend over a has/get runtime
1467
+ * pair, the spawnRes.status pattern. child.killed is Node's
1468
+ * sent-a-signal flag. child.kill sends while the child is un-reaped
1469
+ * (false after — Node's null-handle answer) and THROWS the
1470
+ * Unknown-signal TypeError on bad names (may-throw); killNum passes
1471
+ * numbers through (0 probes; never throws). child.unref drops the
1472
+ * child from the loop's keep-alive set — it is still reaped while the
1473
+ * loop runs for other reasons, and one the loop never reaps is left to
1474
+ * the OS at exit. All receivers borrowed. */
1475
+ | "child.pid" | "child.exitCode" | "child.killed" | "child.kill" | "child.killNum" | "child.unref"
1476
+ /** The piped-output streams (stdio mode 3 — scr_child.c's stream
1477
+ * slice). child.stdout/child.stderr answer the checker's
1478
+ * `Readable | null` union (type-directed construction in the backend
1479
+ * over the +1-or-NULL runtime pair — the child.pid pattern with a ref
1480
+ * arm). stream.onData/onEnd register 'data'/'end' listeners (receiver
1481
+ * borrowed, CALLBACK MOVES, trailing once-flag, void — chaining
1482
+ * fenced): 'data' fires one Buffer chunk per read (zero-param and
1483
+ * Buffer-param adapters are runtime-provided; a union-param listener —
1484
+ * ngrok's `Buffer | string` — gets a compiler-emitted adapter wrapping
1485
+ * the chunk at its Buffer arm), 'end' fires once at EOF, always BEFORE
1486
+ * the child's 'exit' (the pinned ordering). A flowing stream keeps the
1487
+ * loop alive: usesTimers. */
1488
+ | "child.stdout" | "child.stderr" | "stream.onData" | "stream.onEnd"
1489
+ /** The first-class WritableStream write (`output.write(line)` — the
1490
+ * prefixStream idiom): the receiver IS the fd scalar (process.stdout/
1491
+ * stderr reads mint 1/2), dispatched onto the exact stdoutWrite/
1492
+ * stderrWrite paths so buffering and ordering stay identical. Data
1493
+ * borrowed; the bool is Node's always-true backpressure signal. */
1494
+ | "procStream.write"
1495
+ /** node:net (scr_net.c — linked, and scr_net_install() emitted, only
1496
+ * when one of these appears on the IR; moduleUsesNet is the switch).
1497
+ * Receivers are borrowed; CALLBACKS MOVE into the handle's listener
1498
+ * registry and are released at settlement (the child.onExit story).
1499
+ * All listener registrations carry a trailing BOOL once-flag (`on` vs
1500
+ * `once`) and are void — chaining is fenced. None of these throw:
1501
+ * listen/connect failures are the async 'error' event, like Node.
1502
+ *
1503
+ * net.createServer's optional connection handler and the
1504
+ * serverOnConnection listeners take the runtime-provided adapters
1505
+ * (zero-param, or the one-param socket shape); sockOnData's adapters
1506
+ * are the stdin pair's shapes (zero-param / bytes chunk); the error
1507
+ * events reuse the child %Error adapters. net.listen/net.listenCb bind
1508
+ * NOW and defer 'listening' to the next loop turn (Node's next-tick
1509
+ * emit); net.serverPort is the composed `server.address().port` read.
1510
+ * net.connect's host argument is a string ("localhost" pins to
1511
+ * 127.0.0.1 — SEMANTICS.md); the connect callback is once('connect'). */
1512
+ | "net.createServer" | "net.createServerCb" | "net.listen" | "net.listenCb"
1513
+ /** listen({ port, host, ipv6Only }[, cb]) — the explicit-interface bind
1514
+ * (portless's listenOnProxyInterface): args [server, port, host,
1515
+ * ipv6Only]. host is an IP literal string ("" = the host-less
1516
+ * dual-stack any default); ipv6Only sets IPV6_V6ONLY before the bind.
1517
+ * Failures are the async 'error', message in Node's listen shape with
1518
+ * the requested host. Never throws. */
1519
+ | "net.listenOpts" | "net.listenOptsCb" | "net.serverPort"
1520
+ /** server.address() as the full AddressInfo record (the dgram.address
1521
+ * materialization pattern: the emitter builds the record from the three
1522
+ * runtime reads; the frontend pinned the shape). Never throws — before
1523
+ * listen it answers the any-form defaults with port 0 where Node
1524
+ * answers null (the serverPort stance). */
1525
+ | "net.serverAddress" | "net.serverClose" | "net.serverCloseCb"
1526
+ /** The close-override pair (the portless close-proxy idiom).
1527
+ * serverCloseBind is `wrapper.close.bind(wrapper)` as a VALUE: a
1528
+ * compiler-emitted closure over the server whose invocation runs the
1529
+ * REAL close (scr_net_server_close_direct — never the override), so
1530
+ * the override body's `origClose(cb)` cannot recurse; its callback
1531
+ * argument (the `((err?: Error) => void) | undefined` union) registers
1532
+ * as a once-'close' listener, a one-param callback wrapped by an
1533
+ * emitted zero-arg trampoline firing the undefined arm (a clean close
1534
+ * carries no error). serverSetCloseOverride is `wrapper.close = fn`:
1535
+ * the override MOVES in behind an emitted zero-arg wrapper (it invokes
1536
+ * the user function with the undefined-arm callback — tags are program
1537
+ * data), and server.close() consults it before closing. */
1538
+ | "net.serverCloseBind" | "net.serverSetCloseOverride" | "net.serverOnError" | "net.serverOnClose" | "net.serverOnConnection"
1539
+ /** 'secureConnection' — the TLS server's deferred 'connection' list
1540
+ * (handshake-completion timing); on a server without deferred
1541
+ * connections (a plain net server) the registration never fires,
1542
+ * exactly Node's split. */
1543
+ | "net.serverOnSecureConnection" | "net.connect" | "net.connectCb"
1544
+ /** connect({ port, host, autoSelectFamily: true, lookup }) — the
1545
+ * caller-resolver dial (portless's createLoopbackConnection): args
1546
+ * [port, host, lookup]. The runtime creates the (connecting) socket
1547
+ * handle, invokes the lookup as Node does — lookup(hostname, options,
1548
+ * callback), options crossing as the dyn undefined — and the answer
1549
+ * closure (an emitter-synthesized per-shape thunk over a boxed socket,
1550
+ * the SNI-answer pattern) dials the answered addresses IN ORDER: each
1551
+ * connect failure tries the next, the LAST failure's message is the
1552
+ * socket's 'error' (Node's autoSelectFamily aggregate is a documented
1553
+ * divergence), and a lookup error surfaces as the deferred socket
1554
+ * 'error'. A synchronous throw INSIDE the lookup propagates out of the
1555
+ * connect call (may-throw seed). */
1556
+ | "net.connectLookup" | "net.sockWrite" | "net.sockWriteBytes" | "net.sockEnd" | "net.sockEndStr" | "net.sockEndBytes"
1557
+ /** write/end with a CHECKED-DYNAMIC chunk (an untyped JS payload into a
1558
+ * typed socket): the runtime dispatches STR/BYTES and throws Node's
1559
+ * ERR_INVALID_ARG_TYPE chunk TypeError on any other kind. */
1560
+ | "net.sockWriteDyn" | "net.sockEndDyn" | "net.sockDestroy" | "net.sockPipe"
1561
+ /** socket.pipe(res) — raw socket chunks into a ServerResponse body
1562
+ * (the extended-CONNECT bridge leg): each chunk is a body write (the
1563
+ * response's own framing applies); source EOF end()s the response,
1564
+ * pipe's default. Borrows both. Never throws. */
1565
+ | "net.sockPipeRes" | "net.sockOnData" | "net.sockOnEnd" | "net.sockOnClose" | "net.sockOnError" | "net.sockOnConnect"
1566
+ /** node:dgram + node:dns (scr_dgram.c — linked, and
1567
+ * scr_dgram_install() emitted, only when one of these appears on the
1568
+ * IR; moduleUsesDgram is the switch — dns.lookup rides the same unit).
1569
+ * The net listener discipline verbatim: receivers borrowed, CALLBACKS
1570
+ * MOVE into the handle's registry and release at settlement, `on` vs
1571
+ * `once` is the trailing bool, registrations are void. bind/connect
1572
+ * bind NOW and defer 'listening'/'connect' to the next loop turn (the
1573
+ * net.listen story); their optional-host completions are ""
1574
+ * (bind → 0.0.0.0) and "127.0.0.1" (connect — udp4's Node default).
1575
+ * bind/connect/send/close/address THROW Node's state errors ("Socket
1576
+ * is already bound", "Already connected", "Not running") — may-throw
1577
+ * seeded. dgram.address returns the AddressInfo RECORD (the frontend
1578
+ * pins the {address, family, port} shape; the emitter builds it from
1579
+ * runtime parts). onMessage adapters are emitted per rinfo record
1580
+ * shape (the child.onExit precedent); onError reuses the child %Error
1581
+ * adapters. dns.lookup resolves via getaddrinfo AT CALL TIME and
1582
+ * defers the callback to the next turn (SEMANTICS.md documents the
1583
+ * blocking divergence); its per-union adapter builds the
1584
+ * `Error | null` first argument. */
1585
+ | "dgram.createSocket" | "dgram.bind" | "dgram.bindCb" | "dgram.connect" | "dgram.connectCb" | "dgram.sendStr" | "dgram.sendBytes" | "dgram.address" | "dgram.close" | "dgram.closeCb" | "dgram.unref" | "dgram.ref" | "dgram.onMessage" | "dgram.onError" | "dgram.onListening" | "dgram.onClose" | "dgram.onConnect" | "dns.lookup"
1586
+ /** node:test (scr_test.c — linked only when one of these appears on
1587
+ * the IR; moduleUsesNodeTest is the switch, and the main epilogue asks
1588
+ * scr_test_exit_code() for the process's exit status). Strings are
1589
+ * BORROWED, callbacks MOVE. register/suite/hook attach to the runner
1590
+ * tree (register: name, mode 0|1|2 run/skip/todo, directive message ""
1591
+ * = none, cb or absent via registerEmpty, flags 1 async | 2 takes-ctx
1592
+ * | 4 only, "file:line:col"); suite runs its body AT registration
1593
+ * (Node's collection phase). sub is t.test — runs the subtest INLINE
1594
+ * on the runner fiber and returns the settled promise the await
1595
+ * consumes. ctxSkip/ctxTodo mark the running test; ctxDiagnostic
1596
+ * queues an ℹ line; ctxName reads t.name. Every registration keeps
1597
+ * the loop-run emitted (usesTimers) so the runner fiber drains. */
1598
+ | "test.register" | "test.registerEmpty" | "test.suite" | "test.hook" | "test.sub" | "test.subEmpty" | "test.ctxSkip" | "test.ctxTodo" | "test.ctxDiagnostic" | "test.ctxName"
1599
+ /** node:http, the server slice (scr_http.c over scr_net.c — linked
1600
+ * only when these appear on the IR; moduleUsesHttpServer is the
1601
+ * switch, and any http.* libCall also counts as net use so scr_net.c
1602
+ * links and installs). http.createServer's handler MOVES in and takes
1603
+ * the runtime adapters for its (req, res) / (req) / () shapes; req
1604
+ * body listeners follow the net.sockOnData story (bytes chunks, once
1605
+ * flags); reqHeader answers the interned `string | undefined` union
1606
+ * exactly like process.envGet; the res writers are borrowed-argument
1607
+ * voids with Node's framing decided in the runtime (Content-Length
1608
+ * for end-before-head, chunked after an explicit writeHead/write). */
1609
+ | "http.createServer"
1610
+ /** http.createServer() / http.Server() with no handler — the
1611
+ * on("request") route; createServerOpts is the (options[, listener])
1612
+ * overload's twin carrying the two lowered parser flags
1613
+ * (requireHostHeader: false is already this parser's behavior;
1614
+ * joinDuplicateHeaders joins repeated request-header reads ", "). */
1615
+ | "http.createServerEmpty" | "http.serverJoinDupHeaders"
1616
+ /** server.on("listening", cb) — the deferred listen-callback list. */
1617
+ | "net.serverOnListening"
1618
+ /** The ServerResponse member surface: statusCode/statusMessage reads
1619
+ * and assignments (Node's writable properties), the header CRUD trio
1620
+ * (getHeader answers `string | undefined` like reqHeader), and
1621
+ * end(cb)'s finish slot (resOnFinish registers, the end call follows —
1622
+ * the callback fires deferred, Node's 'finish' emit). writeHead's
1623
+ * statusMessage forms compose in interned helpers: resStatusMsgSet
1624
+ * then the ordinary writeHead entry. */
1625
+ | "http.resStatusGet" | "http.resStatusSet" | "http.resStatusMsgGet" | "http.resStatusMsgSet" | "http.resGetHeader" | "http.resHasHeader" | "http.resRemoveHeader" | "http.resOnFinish" | "http.reqUrl" | "http.reqMethod" | "http.reqHeader" | "http.reqOnData" | "http.reqOnEnd" | "http.resSetHeader" | "http.resWriteHead" | "http.resWriteHeadN" | "http.resWrite" | "http.resWriteBytes" | "http.resEnd" | "http.resEndStr" | "http.resEndBytes"
1626
+ /** The checked-dynamic chunk twins (the net.sockWriteDyn story). */
1627
+ | "http.resWriteDyn" | "http.resEndDyn" | "http.resHeadersSent"
1628
+ /** The server-surface member follow-ups: reqStatusCode answers the
1629
+ * interned `number | undefined` union (negative = the undefined arm —
1630
+ * a SERVER request, where Node's statusCode is undefined; every client
1631
+ * response carries a real status); reqSocket is the underlying
1632
+ * connection (+1, the same handle net.connect would give);
1633
+ * sockRemoteAddress answers `string | undefined` (NULL after the fd
1634
+ * closed, Node's destroyed-socket undefined; a dual-stack accept of an
1635
+ * IPv4 peer reads "::ffff:a.b.c.d" like Node). reqResume/reqDestroy and
1636
+ * the req error/close listener slots complete the IncomingMessage
1637
+ * surface portless's client responses use; resDestroy/resOnClose and
1638
+ * resWriteHeadPairs ([k0,v0,k1,v1,...] — the env.pairs helper's flat
1639
+ * shape) complete ServerResponse. sockSetTimeout arms the idle
1640
+ * EVFILT_TIMER ('timeout' fires after ms of inactivity, once per idle
1641
+ * period, never destroying the socket — Node's semantics). */
1642
+ | "http.reqStatusCode" | "http.reqSocket" | "http.reqResume"
1643
+ /** req.rawHeaders — [name, value, name, value, ...] in arrival order,
1644
+ * names in their ORIGINAL case (Node's shape); a fresh string[] per
1645
+ * read. reqStatusMessage answers the interned `string | undefined`
1646
+ * union — the reason phrase on client responses ("" when the status
1647
+ * line carried none), the undefined arm on server requests (the
1648
+ * statusCode split). sockDestroyed is socket.destroyed — true once the
1649
+ * fd is gone (destroy() or full close). */
1650
+ | "http.reqRawHeaders" | "http.reqStatusMessage"
1651
+ /** The `{ ...req.headers }` snapshot feed: [lowercased name, value,
1652
+ * ...] pairs in arrival order — the interned %headers.snapshot helper
1653
+ * builds the record over it, exactly the process.envPairs pattern. */
1654
+ | "http.reqHeaderPairs" | "net.sockDestroyed"
1655
+ /** socket.writable — the write half is open: no end() yet, no FIN sent,
1656
+ * fd alive (connecting sockets answer true; writes queue). Node's
1657
+ * stream flag. Borrows; never throws. */
1658
+ | "net.sockWritable"
1659
+ /** The 'upgrade' events, both sides (SEMANTICS.md — the WebSocket
1660
+ * proxying surface): serverOnUpgrade registers (req, socket, head)
1661
+ * listeners fired INSTEAD of 'request' for Connection: upgrade
1662
+ * requests (the parser steps aside; the socket is raw; `head` carries
1663
+ * bytes past the request head; no listener = the socket destroys,
1664
+ * Node's default). clientOnUpgrade is the client twin: a 101 response
1665
+ * fires (res, socket, head) INSTEAD of 'response'. */
1666
+ | "http.serverOnUpgrade" | "http.clientOnUpgrade"
1667
+ /** server.on("connect", ...) — HTTP CONNECT tunneling, the 'upgrade'
1668
+ * machinery's twin: (req, socket, head) fired INSTEAD of 'request' for
1669
+ * CONNECT-method requests (no listener = the socket destroys, Node's
1670
+ * default). The h2 compat server's 'connect' (portless's RFC 8441
1671
+ * handler) only ever sees the HTTP/1.1 arm under the allowHTTP1
1672
+ * lowering, so a listener whose second parameter is a UNION with a
1673
+ * netSocket arm takes the socket wrapped at that arm (an emitted
1674
+ * per-shape adapter — the tags are program data). */
1675
+ | "http.serverOnConnect"
1676
+ /** req.pipe(dest) — the IncomingMessage body streaming into a
1677
+ * ServerResponse (the proxy's response leg), a ClientRequest (the
1678
+ * request-body forward), or a raw socket (the upgrade-rejection leg);
1679
+ * chunk-for-chunk, natural end ends the destination (Node's pipe
1680
+ * default; no backpressure — divergence 54's stream model). */
1681
+ | "http.reqPipeRes" | "http.reqPipeClient" | "http.reqPipeSock" | "http.reqDestroy" | "http.reqOnError" | "http.reqOnClose" | "http.reqOnAborted" | "http.reqHttpVersion" | "http.reqHttpVersionMajor" | "http.reqHttpVersionMinor" | "http.reqAborted" | "http.reqComplete" | "http.resDestroy" | "http.resOnClose" | "http.resWriteHeadPairs"
1682
+ /** writeHead(status, headers) with a checked-dynamic headers value —
1683
+ * the runtime OBJ walk (string/number values; loud fences otherwise;
1684
+ * may throw). */
1685
+ | "http.resWriteHeadDyn" | "net.sockSetTimeout"
1686
+ /** setEncoding('utf8') — 'data' delivers strings inside the chunk-encoding window; other real encodings fence loudly, unknown names throw ERR_UNKNOWN_ENCODING (may throw). */
1687
+ | "net.sockSetEncoding" | "http.reqSetEncoding" | "net.sockOnTimeout" | "net.sockRemoteAddress"
1688
+ /** The paused-mode demux surface (portless's first-byte TLS peek:
1689
+ * once('readable') + read(1) + unshift + emit('connection')).
1690
+ * sockOnReadable registers a zero-param listener (a consumer: arrived
1691
+ * bytes buffer instead of flowing, and EOF announces too); sockRead
1692
+ * answers `Buffer | null` (exactly n buffered bytes, or null — Node's
1693
+ * less-than-n answer; n <= 0 drains everything); sockUnshift returns
1694
+ * bytes to the front of the stream; serverEmitConnection routes a
1695
+ * socket into another server's protocol layer (a TLS target's
1696
+ * 'connection' waits for its handshake). */
1697
+ | "net.sockOnReadable" | "net.sockRead" | "net.sockUnshift" | "net.serverEmitConnection"
1698
+ /** node:http, the CLIENT slice (http.request/http.get over the net
1699
+ * client machinery): request/requestCb take (host, port, path, method,
1700
+ * timeoutMs, headerPairs, autoEnd[, responseCb]) — headerPairs is the
1701
+ * flat [k0,v0,...] array (empty for none), autoEnd true is http.get's
1702
+ * eager end(). The handle owns one dialed connection (NO pooling — the
1703
+ * wire still carries Node's exact head: user headers, then Host,
1704
+ * Connection: keep-alive, and the framing header; the socket closes
1705
+ * when the response completes). The response delivered to responseCb /
1706
+ * 'response' listeners IS an httpReq (IncomingMessage), status and
1707
+ * headers parsed from the wire, body via reqOnData/reqOnEnd. Errors are
1708
+ * Node-shaped ('connect ECONNREFUSED ip:port', 'socket hang up') and
1709
+ * fire 'error' then 'close'; an unhandled 'error' exits 1 like every
1710
+ * net handle. clientWrite before end commits to chunked framing unless
1711
+ * the caller set content-length; clientEnd(data) before any write sends
1712
+ * Content-Length exactly like Node. */
1713
+ | "http.request" | "http.requestCb"
1714
+ /** The createConnection form (the proxy's own dialer): args are
1715
+ * (connCb, path, method, timeout, headers, autoEnd[, cb]) — connCb is
1716
+ * a `() => net.Socket` closure the runtime invokes ONCE, synchronously
1717
+ * (Node's onSocket timing); everything else matches http.request. The
1718
+ * Host header defaults to "localhost" — a headers.host entry wins
1719
+ * verbatim, the proxy shape. */
1720
+ | "http.requestConn" | "http.requestConnCb"
1721
+ /** node:tls + node:https (scr_tls.c over scr_net.c/scr_http.c, with
1722
+ * the vendored mbedTLS archive — linked only when one of these appears
1723
+ * on the IR; moduleUsesTls is the switch, and every tls/https libCall
1724
+ * also counts as net AND http use so both units link and install).
1725
+ * tls.createServer takes (cert, key[, handler]) — cert/key are PEM
1726
+ * strings or Buffers (the emitter passes data+len for either); the
1727
+ * handler is Node's 'secureConnection' (fires post-handshake with a
1728
+ * socket that behaves exactly like a net socket, the same adapters as
1729
+ * net.createServer). https.createServer is (cert, key, handler) with
1730
+ * the http request-handler adapters. https.request/requestCb extend
1731
+ * the http client row with (…, rejectUnauthorized: bool, ca: PEM
1732
+ * string/Buffer — "" for none) and default port 443; everything else
1733
+ * (write/end/destroy/events, the response surface) IS the http client
1734
+ * surface — the handles are the same kinds. */
1735
+ | "tls.createServer" | "tls.createServerCb"
1736
+ /** RUNTIME options records (the divergence-66 stance): the *Dyn
1737
+ * creators take a checked-dynamic (dyn) options value whose members
1738
+ * read at runtime — cert/key extract like the literal path, members
1739
+ * whose literal forms fence THROW the catchable fence at runtime, and
1740
+ * undocumented keys drop like Node drops them. tls.pemDyn is the
1741
+ * literal walk's runtime-valued cert/key extraction: (value, whatLit)
1742
+ * → PEM bytes (strings/Buffers/one-element arrays of those) or the
1743
+ * thrown fence. All of them may throw. */
1744
+ | "tls.pemDyn" | "tls.createServerDyn" | "tls.createServerDynCb" | "https.createServerDyn" | "https.createServerDynCb"
1745
+ /** tls.connect — the TLS client socket: (port, host, opts[, cb]) where
1746
+ * port -1 reads options.port, host "" reads options.host, and opts is
1747
+ * the runtime (dyn) options record (rejectUnauthorized/ca/servername
1748
+ * implemented; other documented members throw the runtime fence). The
1749
+ * callback fires post-handshake — Node's secureConnect timing. */
1750
+ | "tls.connect" | "tls.connectCb"
1751
+ /** The TLSSocket member surface on the socket kind: authorized (bool —
1752
+ * Node's verify verdict), authorizationError (the verify-failure CODE
1753
+ * STRING or null), the 'secureConnect' registration (a TLS socket's
1754
+ * conn list fires at establishment; plain sockets never fire it), and
1755
+ * the 'session' registration (fires once with the serialized session —
1756
+ * a Buffer; the received-ticket event). */
1757
+ | "tls.sockAuthorized" | "tls.sockAuthError" | "tls.sockOnSecureConnect" | "tls.sockOnSession"
1758
+ /** tls.createSecureContext({ cert, key }) — parses the PEM pair into an
1759
+ * opaque SecureContext handle (secureCtx kind) for SNI callbacks to
1760
+ * answer with; cert/key are PEM strings or Buffers like createServer's. */
1761
+ | "tls.createSecureContext" | "https.createServer" | "https.request" | "https.requestCb"
1762
+ /** A call through a `const requestFn = tls ? https.request :
1763
+ * http.request` binding — the module-function-as-value ternary between
1764
+ * the two known clients: the https.request row with a leading `secure`
1765
+ * bool that picks the dial at RUNTIME (true = the TLS client, exactly
1766
+ * https.request; false = the plain client, exactly http.request —
1767
+ * rejectUnauthorized/ca ignored there like Node ignores TLS options on
1768
+ * http.request). The "https." prefix keeps the TLS unit linked. */
1769
+ | "https.requestFn" | "https.requestFnCb"
1770
+ /** node:http2, the compatibility slice (SEMANTICS.md divergence 57):
1771
+ * createSecureServer is the https server WITHOUT an eager handler —
1772
+ * the same scr_https_create_server with a NULL closure (ALPN
1773
+ * advertises http/1.1 only; every connection serves HTTP/1.1).
1774
+ * serverOnRequest installs 'request' listeners after creation (the
1775
+ * http adapters pick the (req, res)/(req)/() shape; a once flag rides
1776
+ * along; on a server with no HTTP parser the registration is dead
1777
+ * weight, like Node's never-fired 'request' on a net server).
1778
+ * serverOnSessionError evaluates and releases its callback — no h2
1779
+ * session ever exists, so the event NEVER fires. */
1780
+ | "http2.createSecureServer"
1781
+ /** createSecureServer with an SNI callback: args are (cert, key, sniCb)
1782
+ * where sniCb is the JS SNICallback — a `(servername, cb) => void`
1783
+ * closure, or the `SNICallback | undefined` union from the conditional-
1784
+ * spread spelling (`...(x ? { SNICallback: x } : {})`; the emitter
1785
+ * unwraps the union — the undefined arm means "no callback", exactly
1786
+ * the no-SNI server). The runtime parses each connection's ClientHello
1787
+ * for the server_name extension BEFORE the TLS handshake begins, calls
1788
+ * the callback with (servername, answer-closure), and resumes the
1789
+ * handshake when the answer arrives — cb(err) tears the socket down
1790
+ * silently (Node's 'tlsClientError' default), cb(null, ctx) serves
1791
+ * ctx's cert/key, cb(null, undefined) serves the default pair. */
1792
+ | "http2.createSecureServerSni"
1793
+ /** The REAL h2-over-TLS server (createSecureServer WITHOUT allowHTTP1):
1794
+ * scr_http2_create_secure_server — the h2c session machinery behind an
1795
+ * mbedTLS handshake whose ALPN advertises h2 alone (an http/1.1-only
1796
+ * client fails the handshake with no_application_protocol, Node's
1797
+ * h2-only split). args are (cert, key) — PEM strings or Buffers. */
1798
+ | "http2.createSecureServerH2" | "http.serverOnRequest" | "http2.serverOnSessionError"
1799
+ /** The guarded h2-only stream call (`req.stream?.on(...)`): stream is
1800
+ * undefined on every connection the allowHTTP1 lowering accepts, so
1801
+ * the optional chain short-circuits — a VOID no-op the emitter drops
1802
+ * (statement position enforced by the frontend). */
1803
+ | "http2.streamNoop"
1804
+ /** The UNGUARDED h2-only stream call (`req.stream.on(...)`): stream is
1805
+ * undefined on every connection the allowHTTP1 lowering accepts — and
1806
+ * on every HTTP/1.1 connection of Node's own allowHTTP1 server — so the
1807
+ * call IS Node's member read on undefined: throws the exact catchable
1808
+ * TypeError ("Cannot read properties of undefined (reading 'on')").
1809
+ * One arg: the read member's name (a string literal). Never returns. */
1810
+ | "http2.streamUndefCall"
1811
+ /** node:http2, the REAL h2c surface (scr_http2.c — frame codec + HPACK
1812
+ * over the net loop; the design note atop that file has the story).
1813
+ * Sessions and streams are first-class handle kinds; 'stream'/'response'
1814
+ * payloads cross as flat [name, value, ...] pairs arrays and an EMITTED
1815
+ * adapter closure builds the program-side headers record (the response
1816
+ * :status rides separately as a number). */
1817
+ | "http2.createServer" | "http2.createServerReq" | "http2.serverOnStream" | "http2.serverOnSession"
1818
+ /** connect(authority[, listener]) — h2c prior knowledge; the listener
1819
+ * closure (if any) is the 'connect' once-listener. */
1820
+ | "http2.connect" | "http2.connectCb"
1821
+ /** session.request(pairs?, endStream) — endStream is a tri-state f64:
1822
+ * -1 the method's payload-meaningless default, 0/1 explicit. */
1823
+ | "http2.sessionRequest" | "http2.sessionClose" | "http2.sessionCloseCb" | "http2.sessionDestroy" | "http2.sessionOnClose" | "http2.sessionOnError" | "http2.sessionOnConnect" | "http2.sessionOnStream" | "http2.sessionOnGoaway" | "http2.sessionSettings0" | "http2.sessionSettings" | "http2.sessionSettingsDynCb" | "http2.sessionSettingsCb0" | "http2.sessionOnSettingsDyn" | "http2.sessionOnSettings0" | "http2.sessionSettingsGet" | "http2.sessionPendingSettingsAck" | "http2.getDefaultSettings" | "http2.sessionClosed" | "http2.sessionDestroyed" | "http2.sessionEncrypted" | "http2.sessionType" | "http2.sessionAlpn" | "http2.sessionSocket"
1824
+ /** stream.respond(pairs?, endStream) — the server answer. */
1825
+ | "http2.streamRespond" | "http2.streamWrite" | "http2.streamWriteBytes" | "http2.streamEnd" | "http2.streamEndStr" | "http2.streamEndBytes" | "http2.streamClose" | "http2.streamCloseCb" | "http2.streamDestroy" | "http2.streamSetEncoding" | "http2.streamSetEncodingRet" | "http2.streamResume" | "http2.streamPause" | "http2.streamOnData" | "http2.streamOnEnd" | "http2.streamOnClose" | "http2.streamOnAborted" | "http2.streamOnError" | "http2.streamOnResponse" | "http2.streamId" | "http2.streamRstCode" | "http2.streamDestroyed" | "http2.streamClosed" | "http2.streamAborted" | "http2.streamPending" | "http2.streamSession"
1826
+ /** socket.encrypted — `boolean | undefined`: the true arm iff the
1827
+ * socket carries a TLS transport (Node types `encrypted: true` on
1828
+ * TLSSocket; plain sockets answer undefined — the proxy.ts isEncrypted
1829
+ * idiom reads it through a cast). */
1830
+ | "net.sockEncrypted" | "http.clientWrite" | "http.clientWriteBytes" | "http.clientEnd" | "http.clientEndStr" | "http.clientEndBytes"
1831
+ /** The checked-dynamic chunk twins (the net.sockWriteDyn story). */
1832
+ | "http.clientWriteDyn" | "http.clientEndDyn"
1833
+ /** request/get with a URL-STRING first argument: the runtime parses it
1834
+ * (WHATWG) and dials — throws catchably on an unparsable input or a
1835
+ * non-http scheme. */
1836
+ | "http.requestUrl" | "http.requestUrlCb" | "http.clientDestroy" | "http.clientDestroyed" | "http.clientOnResponse" | "http.clientOnError" | "http.clientOnTimeout" | "http.clientOnClose"
1837
+ /** fs/promises (scr_lib.c over scr_async.c's settled minting): the SAME
1838
+ * sync syscalls, wrapped in an ALREADY-SETTLED promise — failure
1839
+ * REJECTS (catchable at the await) instead of throwing, so none of
1840
+ * these are in the may-throw seed. readFile is utf8-fenced like
1841
+ * readFileSync. The non-interleaving divergence is documented in
1842
+ * SEMANTICS.md. */
1843
+ /** node:crypto, the string-producing slice: randomUUID (never throws)
1844
+ * and the COMPOSED randomBytes(n).toString("hex"|"base64") — one
1845
+ * libCall, the Buffer never escapes (bare randomBytes is fenced).
1846
+ * randomBytesToString THROWS Node's RangeError on out-of-range sizes. */
1847
+ | "crypto.randomUUID" | "crypto.randomBytesToString"
1848
+ /** The COMPOSED hash chain createHash(alg).update(data).digest(enc)
1849
+ * fused into one call — the Hash handle never materializes. Args are
1850
+ * (alg, data, enc); alg is "sha256" | "sha1" and enc "hex" | "base64",
1851
+ * both compile-time literals (frontend-fenced). Strings hash their
1852
+ * UTF-8 bytes (Node's default input encoding); the bytes form hashes a
1853
+ * Buffer/typed array's bytes. Pure; never throw. */
1854
+ | "crypto.hashDigestStr" | "crypto.hashDigestBytes"
1855
+ /** crypto.randomBytes(n) → a real u8 Buffer (+1). THROWS Node's
1856
+ * RangeError on out-of-range sizes, exactly like the composed
1857
+ * randomBytesToString (which keeps its one-libCall lowering — the two
1858
+ * coexist: the composed form never materializes the Buffer). */
1859
+ | "crypto.randomBytes"
1860
+ /** The Buffer statics with fixed (always-u8) signatures. fromStr is
1861
+ * `Buffer.from(string, enc)` — the frontend completes an omitted
1862
+ * encoding to "utf8" and fences non-literal/unsupported ones; hex and
1863
+ * base64 decode Node-leniently, so it never throws. concat takes ONE
1864
+ * bytes<u8>[] arg (the list) and returns a fresh copy. `Buffer.from(u8)`
1865
+ * and `Buffer.alloc(n)` need no libFn — they lower to bytesNew. */
1866
+ | "buffer.fromStr" | "buffer.concat"
1867
+ /** Buffer.byteLength(string, enc) — enc a NORMALIZED literal like
1868
+ * fromStr's — and Buffer.isEncoding(name) over a runtime string
1869
+ * (case-insensitive against Node's alias set). Pure; never throw. */
1870
+ | "buffer.byteLenStr" | "buffer.isEncoding"
1871
+ /** Buffer.concat(list, totalLength): the concatenation truncated or
1872
+ * zero-padded to the total. THROWS Node's 'length' RangeError on a
1873
+ * negative/non-integer total (may-throw seed). */
1874
+ | "buffer.concatLen"
1875
+ /** The Buffer forms of the fs quartet: readFileSync(path) with NO
1876
+ * encoding → bytes<u8> (+1), writeFileSync(path, bytes), and the
1877
+ * fs/promises readFile(path) no-encoding form (an already-settled
1878
+ * promise, rejecting on failure like the other fsp members). The sync
1879
+ * pair THROWS catchably on failure exactly like the utf8 forms. */
1880
+ | "fs.readFileSyncBytes" | "fs.writeFileSyncBytes" | "fsp.readFileBytes"
1881
+ /** node:zlib (scr_zlib.c — cc.ts compiles/links it ONLY when these
1882
+ * appear on the IR, the regex/libcurl gating precedent): deflateSync/
1883
+ * inflateSync over u8 bytes with Node's default options. deflate never
1884
+ * throws (OOM aborts); inflate of corrupt input THROWS Node's error
1885
+ * catchably. */
1886
+ | "zlib.deflateSync" | "zlib.inflateSync"
1887
+ /** The Buffer overloads of the raw stream writes — same streams and
1888
+ * buffering as process.stdoutWrite/stderrWrite, constantly true. */
1889
+ | "process.stdoutWriteBytes" | "process.stderrWriteBytes" | "fsp.readFile" | "fsp.writeFile" | "fsp.mkdir"
1890
+ /** The fs/promises option/member tail the certs pipeline uses: mkdir's
1891
+ * literal { recursive?, mode? } options (the mkdirSync matrix behind
1892
+ * settled promises), unlink, chmod. Failures REJECT (catchable at the
1893
+ * await), like the rest of the fsp family. */
1894
+ | "fsp.mkdirMode" | "fsp.mkdirRecursive" | "fsp.mkdirRecursiveMode" | "fsp.unlink" | "fsp.chmod" | "fsp.readdir" | "fsp.rm" | "fsp.stat" | "process.argv" | "process.platform"
1895
+ /** getenv(3): one string key arg → the interned `string | undefined`
1896
+ * union (present: +1 string wrapped into the string arm; absent: the
1897
+ * interned undefined-arm instance). BOTH source forms — `process.env.FOO`
1898
+ * and `process.env[expr]` — lower here. Purely static; never throws. */
1899
+ | "process.envGet"
1900
+ /** setenv(3): (name, value) string args → void. Later envGet reads and
1901
+ * spawned children observe the write, like Node (values are strings —
1902
+ * the frontend fences non-string RHS). Never throws. */
1903
+ | "process.envSet"
1904
+ /** The whole environment as alternating [k0, v0, k1, v1, ...] strings in
1905
+ * environ order — the raw material of the process.env SNAPSHOT record
1906
+ * (the frontend's interned %env.snapshot helper keyed-writes the pairs
1907
+ * into a fresh `{ [k: string]: string | undefined }` record). Fresh +1
1908
+ * array; never throws. */
1909
+ | "process.envPairs" | "process.exit" | "process.cwd"
1910
+ /** getpid(2) / getuid(2): zero args → f64. POSIX-only target, so both
1911
+ * always answer (the checker's `getuid?` optionality covers Windows —
1912
+ * `process.getuid?.()` lowers as the plain call). Never throw. */
1913
+ | "process.pid" | "process.getuid" | "process.getgid"
1914
+ /** The ambient receiver — JS `this` in a plain (non-method) function
1915
+ * body: the innermost binding the current firing/dispatch window
1916
+ * pushed (Node's listener receiver, a dyn OBJ method's object, an
1917
+ * apply/call thisArg), or the undefined DOM singleton with none bound
1918
+ * (the strict-mode plain-call answer, the old constant). Zero args →
1919
+ * dyn (+1). Never throws. */
1920
+ | "dyn.this"
1921
+ /** process.execPath: the compiled binary's own resolved absolute path
1922
+ * (one interned string, +1 per read) — the honest answer where Node's
1923
+ * is the node executable's (SEMANTICS.md divergence 12). Never throws. */
1924
+ | "process.execPath"
1925
+ /** process.arch: the compiled binary's OWN architecture ("arm64",
1926
+ * "x64") — Node's answer for its own build on the same machine.
1927
+ * Interned; +1 per read. Never throws. */
1928
+ | "process.arch"
1929
+ /** process.versions.node: the runtime's Node COMPATIBILITY TARGET —
1930
+ * there is no Node under the binary, so this reports the version whose
1931
+ * semantics the runtime implements (SEMANTICS.md divergence 60, the
1932
+ * execPath stance). Interned; +1 per read. Never throws. */
1933
+ | "process.versionsNode" | "process.versionsOpenssl"
1934
+ /** umask(2): arg < 0 reads without setting (umask has no read-only form
1935
+ * — set 0, restore); otherwise sets and answers the PREVIOUS mask.
1936
+ * Never throws. */
1937
+ | "process.umask"
1938
+ /** chdir(2) — throws Node's fs-shaped error (ENOENT/EACCES/ENOTDIR,
1939
+ * syscall "chdir") on failure. */
1940
+ | "process.chdir"
1941
+ /** process._exiting: true once the exit sequence began (exit listeners
1942
+ * running) — the runtime flag scr_run_exit_listeners/process.exit set.
1943
+ * Never throws. */
1944
+ | "process.exiting"
1945
+ /** os.type(): uname(2)'s sysname ("Darwin", "Linux"; "Windows_NT" on
1946
+ * win32) — Node's uv_os_uname answer. Interned per call; never throws. */
1947
+ | "os.type"
1948
+ /** os.totalmem(): total physical memory in bytes. Never throws. */
1949
+ | "os.totalmem"
1950
+ /** net's process-wide happy-eyeballs attempt budget (Node's default
1951
+ * 250ms): one runtime double in the core unit, so reading/writing it
1952
+ * never forces the net unit into the link. Never throw. */
1953
+ | "net.getAutoSelTimeout" | "net.setAutoSelTimeout"
1954
+ /** realpath(3) with Node's error shape (syscall "lstat" in the message,
1955
+ * Node's own spelling for realpathSync failures). +1 fresh string. */
1956
+ | "fs.realpathSync"
1957
+ /** kill(2) with Node's exact semantics and error shapes: the pid must be
1958
+ * an int32 (else the ERR_INVALID_ARG_TYPE TypeError text), the named
1959
+ * form resolves Node's signal-name table (unknown names throw the
1960
+ * ERR_UNKNOWN_SIGNAL TypeError), an omitted signal completes to
1961
+ * "SIGTERM" in the frontend, signal 0 probes, and a kill(2) failure
1962
+ * throws Node's `kill ESRCH`/`kill EPERM` Error. Result is Node's
1963
+ * constant true. */
1964
+ | "process.kill" | "process.killNum"
1965
+ /** execFileSync/execSync as ONE entry (args: cmd, argv, shell, input,
1966
+ * cwd, hasEnv, envPairs, timeoutMs, stdoutMode, stderrMode — see
1967
+ * scr_runtime.h). Throws Node's exact errors: "Command failed: <cmd>"
1968
+ * (+ captured stderr) on non-zero exit or signal death, "spawnSync
1969
+ * <file> ENOENT" on spawn failure, "spawnSync <file> ETIMEDOUT" after
1970
+ * the SIGTERM timeout. Result is the captured utf8 stdout (+1). */
1971
+ | "cp.execSync"
1972
+ /** The promisified-execFile capture (args: cmd, argv, cwd, hasEnv,
1973
+ * envPairs, timeoutMs): the same exec core in the async shape — both
1974
+ * streams captured, no echo, Node's ASYNC messages on the throw paths
1975
+ * ("Command failed: <cmd>\n<stderr>" with the unconditional newline,
1976
+ * "spawn <file> ENOENT" with .code, timeouts reporting as ordinary
1977
+ * SIGTERM command failures — never ETIMEDOUT). Result reuses the
1978
+ * ScrSpawnRes container (+1; stdout/stderr strings, status unused).
1979
+ * Called only from the frontend's interned %execFileAsync ASYNC helper,
1980
+ * whose fiber turns the throw into the rejection. */
1981
+ | "cp.execCapture"
1982
+ /** The raw byte writes: one borrowed string arg → bool (constantly true
1983
+ * — Node's backpressure signal never fires on these synchronous writes).
1984
+ * stdoutWrite shares console.log's stream AND buffer, so interleaved
1985
+ * output keeps source order; stderrWrite is unbuffered like Node's
1986
+ * stderr. No newline, no formatting, never throws. */
1987
+ | "process.stdoutWrite" | "process.stderrWrite" | "timers.setTimeout"
1988
+ /** The repeating timer pair. setInterval takes (callback, ms) like
1989
+ * setTimeout and RETURNS the f64 handle the fallback declarations
1990
+ * promise (ids start at 1, so truthiness narrowing works); the loop
1991
+ * owns the callback until clearInterval removes the entry (eagerly — a
1992
+ * live interval keeps the loop alive, a cleared one releases it, like
1993
+ * Node). Neither throws; a throw ESCAPING an interval callback ends the
1994
+ * program like a setTimeout throw. */
1995
+ | "timers.setInterval" | "timers.clearInterval"
1996
+ /** setTimeout WITH a clear handle (the f64 id) — the clearable/unref-able
1997
+ * one-shot; clearTimeout cancels it, .unref() drops it from loop
1998
+ * liveness. The plain timers.setTimeout stays the handle-less
1999
+ * fire-and-forget. */
2000
+ | "timers.setTimeoutHandle" | "timers.clearTimeout"
2001
+ /** Timeout.unref()/ref()/hasRef() — loop-liveness bookkeeping over the
2002
+ * handle id. unref/ref RETURN the handle (f64) for chaining; hasRef
2003
+ * returns bool. */
2004
+ | "timers.unref" | "timers.ref" | "timers.hasRef"
2005
+ /** Timeout.refresh() — re-arm to now + the original delay (from the
2006
+ * heap or from inside the firing callback; a one-shot that fired on an
2007
+ * earlier turn is gone and no-ops — documented divergence). Returns
2008
+ * the handle for chaining like unref/ref. */
2009
+ | "timers.refresh"
2010
+ /** setImmediate/clearImmediate — Node's check phase: callbacks run
2011
+ * once per loop turn AFTER due timers, FIFO, and immediates queued
2012
+ * mid-phase wait for the next turn. setImmediate returns the f64
2013
+ * handle (its own id space — clearTimeout of an Immediate no-ops,
2014
+ * like Node); the Immediate ref trio mirrors the Timeout one (an
2015
+ * unref'd pending immediate neither keeps the loop alive nor fires
2016
+ * once nothing reffed remains). */
2017
+ | "timers.setImmediate" | "timers.clearImmediate" | "timers.immediateUnref" | "timers.immediateRef" | "timers.immediateHasRef"
2018
+ /** queueMicrotask (scr_async.c): the callback enters the SAME FIFO
2019
+ * promise continuations ride — one microtask order, like V8's queue —
2020
+ * and a throw is an UNCAUGHT exception (never a rejection).
2021
+ * timers.queueMicrotask takes an owned zero-param closure and never
2022
+ * throws; the Dyn form (checked-dynamic arguments — the mustCall
2023
+ * wrapper, the suite's invalid-input probes) throws Node's
2024
+ * ERR_INVALID_ARG_TYPE synchronously on a non-function value and calls
2025
+ * the function with zero arguments at drain. */
2026
+ | "timers.queueMicrotask" | "timers.queueMicrotaskDyn"
2027
+ /** The tolerated non-handle clear (`clearTimeout(null)`,
2028
+ * `clearInterval({})`, zero-argument forms): Node silently ignores
2029
+ * anything that is not a live handle — a VOID no-op the emitter drops
2030
+ * (only syntactically side-effect-free arguments take this path). */
2031
+ | "timers.clearNoop"
2032
+ /** process.nextTick(cb, ...args) — the user tick queue. args: [cb
2033
+ * (() => void; trailing call arguments ride the timer surface's
2034
+ * interned dyn thunk)]. Ticks drain BEFORE promise jobs at every loop
2035
+ * checkpoint, to joint exhaustion with them (Node's tick-then-
2036
+ * microtask order); ticks enqueued by station listeners run at the
2037
+ * NEXT checkpoint (the stream-tick station divergence, SEMANTICS.md).
2038
+ * Pending ticks are always-ready work — the loop neither sleeps nor
2039
+ * exits while any exist; ticks scheduled from 'exit' listeners never
2040
+ * run (Node). The enqueue itself never throws. */
2041
+ | "process.nextTick"
2042
+ /** The process introspection statics. uptime: seconds since the
2043
+ * binary's own start (fractional — a load-time monotonic anchor).
2044
+ * availableMemory/constrainedMemory: libuv's numbers (free-ish bytes;
2045
+ * the cgroup cap or 0). cpuUser/cpuSystem (+ threadCpu twins): the
2046
+ * process/thread CPU clocks in microseconds — the frontend composes
2047
+ * the {user, system} records. The *Diff forms answer current − prev
2048
+ * for one field; cpuPrevValidate throws Node's ERR_INVALID_ARG_VALUE
2049
+ * RangeError for negative/non-finite prev fields (user first, then
2050
+ * system — Node's order; MAY THROW). rusage(idx): one
2051
+ * process.resourceUsage() field by canonical index (Node's units).
2052
+ * activeResources: the loop's own bookkeeping — 'Timeout' per armed
2053
+ * (or firing, uncleared) timer, 'Immediate' per queued unfired
2054
+ * immediate; unmodeled resource kinds are absent (SEMANTICS.md). */
2055
+ | "process.uptime" | "process.availableMemory" | "process.constrainedMemory" | "process.cpuUser" | "process.cpuSystem" | "process.cpuUserDiff" | "process.cpuSystemDiff" | "process.threadCpuUser" | "process.threadCpuSystem" | "process.threadCpuUserDiff" | "process.threadCpuSystemDiff" | "process.cpuPrevValidate" | "process.rusage" | "process.activeResources"
2056
+ /** Process signal events — process.on/once/off("SIGINT" | "SIGTERM").
2057
+ * args: [signo f64 (the frontend bakes the POSIX number), cb, once
2058
+ * bool] for on; [signo, cb] for off (cb borrowed, removed by pointer
2059
+ * identity — Node's removeListener contract). Handlers run as
2060
+ * macrotasks at loop turns; watching replaces the default disposition
2061
+ * and removing the last listener restores it; signal listeners never
2062
+ * keep the loop alive (Node). Zero-param callbacks only (the ambient
2063
+ * shape). Never throw. */
2064
+ | "process.onSignal" | "process.offSignal"
2065
+ /** The process 'exit' event — process.on/once/off("exit"). args: [cb,
2066
+ * once bool] / [cb]. Listeners run SYNCHRONOUSLY at termination
2067
+ * (normal exit, process.exit(), the uncaught/unhandled exit-1 paths)
2068
+ * with the exit code; anything they schedule never runs, like Node.
2069
+ * Callback shapes: () => void or (code: number) => void — the emitter
2070
+ * picks the runtime adapter. Never throw. */
2071
+ | "process.onExit" | "process.offExit"
2072
+ /** process.stdin listener registration — stdin.on/once("data" | "end" |
2073
+ * "error", cb). args: [cb, once bool]. data callbacks: () => void or
2074
+ * (chunk: Uint8Array) => void; end: () => void; error: () => void or
2075
+ * (err: Error) => void (the child error adapters are reused). While a
2076
+ * data listener (or a parked for-await chunk promise) exists, stdin
2077
+ * keeps the loop alive — Node's flowing-stdin keep-alive. Never
2078
+ * throw. */
2079
+ | "stdin.onData" | "stdin.onEnd" | "stdin.onError"
2080
+ /** The for-await chunk source over process.stdin: no args, result
2081
+ * Promise<Uint8Array> (+1). Fulfills with the next arrived chunk; the
2082
+ * EMPTY bytes value is the done sentinel (POSIX reads never deliver
2083
+ * empty data chunks), which the for-await desugar turns into loop
2084
+ * exit. Never throws itself; awaiting it re-throws nothing (stdin
2085
+ * errors surface through 'error' listeners, not the iterator). */
2086
+ | "stdin.nextChunk"
2087
+ /** The runtime-provided Error hierarchy's entry points (scr_error.c).
2088
+ * error.new: one borrowed string arg (the message), result an owned (+1)
2089
+ * builtin error instance — the result TYPE names which builtin class
2090
+ * (backends derive the runtime kind from it). error.ctor: the
2091
+ * super(message) call of an `extends Error` constructor — borrowed
2092
+ * receiver (already allocated by the derived class's new) + borrowed
2093
+ * message, void; the receiver's type names the builtin class whose name
2094
+ * field to stamp. error.toString: borrowed `%Error`-typed receiver, +1
2095
+ * string in Node's "name: message" shape. None of the three throws. */
2096
+ | "error.new"
2097
+ /** A read of a `declare`d const NOTHING defines (the bundler-define
2098
+ * pattern — __VERSION__): always throws the catchable ReferenceError
2099
+ * Node raises at the access ("<name> is not defined"). args[0] is the
2100
+ * name; the result type is the read's declared type (a typed dummy the
2101
+ * unwind abandons — the value never exists). */
2102
+ | "global.undefRead"
2103
+ /** `X.name` through a class VALUE (scr_object.c): args[0] is a borrowed
2104
+ * classval; the result is the class object's stored .name string,
2105
+ * retained (+1 — the string is an interned immortal, so the retain is a
2106
+ * no-op, kept for ownership uniformity). Never throws. A direct
2107
+ * `C.name` on the class name itself folds to a strLit instead. */
2108
+ | "class.name" | "error.ctor" | "error.toString"
2109
+ /** `new DOMException(message?, nameOrOptions?)` (scr_error.c): both args
2110
+ * are borrowed DOM values (the lowering passes the DOM undefined for an
2111
+ * absent argument, so WebIDL's optionality lives in one place). The
2112
+ * runtime ToStrings the message ("" for absent/undefined), resolves the
2113
+ * name — absent/undefined → "Error", a non-null object → ToString of its
2114
+ * `name` member plus the `cause` own-property record, anything else →
2115
+ * ToString — and stamps the legacy code from the WebIDL name table (0
2116
+ * off-table). Result is an owned (+1) %DOMException. Never throws (DOM
2117
+ * ToString is total). */
2118
+ | "error.newDom"
2119
+ /** DOMException's own read surface (scr_error.c; %DOMException receivers
2120
+ * only — borrowed). domCode: the legacy numeric code. domHasCause: the
2121
+ * options form's own-property record (`'cause' in e`). domCause: the
2122
+ * cause value, +1 (the DOM undefined when absent — matching Node's
2123
+ * undefined read). None throws. */
2124
+ | "error.domCode" | "error.domHasCause" | "error.domCause"
2125
+ /** structuredClone of a %DOMException receiver (scr_error.c): WebIDL
2126
+ * serialization — name/message copy, the legacy code re-derives, cause
2127
+ * does not serialize. args are the borrowed receiver and the borrowed
2128
+ * options DOM value (the DOM undefined when absent — the shared
2129
+ * validation throws Node's exact option errors; any non-empty transfer
2130
+ * list throws DataCloneError, nothing static is transferable). Result
2131
+ * +1 %DOMException. */
2132
+ | "error.domClone"
2133
+ /** `d instanceof TypeError` (and the other BUILTIN error classes) on a
2134
+ * checked-dynamic value (scr_json.c): the from_error cache holds the
2135
+ * DOM↔error identity edge, so the test resolves the runtime error and
2136
+ * asks its vtable's stamped preorder interval — exact for every error
2137
+ * that crossed the boundary. A DOM object that never came from an
2138
+ * error (a hand-built {%error} literal) answers false: subclass
2139
+ * identity is unknowable there (the root keeps dynTest's marker
2140
+ * answer). args are the borrowed dyn and the SCR_ERR_* kind literal.
2141
+ * Never throws. */
2142
+ | "dyn.errInstanceof"
2143
+ /** Object.keys/values/entries over a CHECKED-DYNAMIC receiver
2144
+ * (scr_json.c): the runtime walks the DOM node's own members in JS
2145
+ * own-key order (array-index keys ascending first, then insertion
2146
+ * order) and answers a DOM array (entries: an array of [key, value]
2147
+ * pairs; values RETAIN the member nodes — reference semantics, like
2148
+ * JS). Strings/arrays/bytes answer their index keys; other scalars an
2149
+ * empty array; null/undefined throw Node's catchable TypeError
2150
+ * ("Cannot convert undefined or null to object"). */
2151
+ | "dyn.objKeys" | "dyn.objValues" | "dyn.objEntries"
2152
+ /** structuredClone over the DOM (scr_json.c): the JSON-safe subset plus
2153
+ * bytes (a fresh copy — a Buffer clones as a plain Uint8Array, like
2154
+ * Node), deep. Functions and handle kinds throw the spec's catchable
2155
+ * DataCloneError; CYCLES throw the scriptc fence (the DOM cannot
2156
+ * represent them — Node clones cycles; documented divergence). The
2157
+ * options DOM value validates with Node's exact errors (dictionary
2158
+ * conversion, the transfer-sequence member; any non-empty transfer
2159
+ * list throws DataCloneError). dyn.cloneMissing is the zero-argument
2160
+ * call: always throws Node's TypeError [ERR_MISSING_ARGS] with Node's
2161
+ * own (verbatim, doubly-wrapped) message. */
2162
+ | "dyn.structuredClone" | "dyn.cloneMissing"
2163
+ /** `new RegExp(pattern, flags?)` (scr_regex.c): a heap regex over the
2164
+ * same libregexp engine the literals use. The pattern compiles EAGERLY
2165
+ * so an invalid pattern (or an unknown flag letter) throws Node's
2166
+ * catchable SyntaxError at construction — Node's message shape with
2167
+ * libregexp's detail text (approximate fidelity; e.name exact). An
2168
+ * empty pattern stores the spec's "(?:)" source. Both args borrowed
2169
+ * strings (the lowering completes an absent flags to ""); result +1.
2170
+ * The result TYPE is the regex kind, so the link switch pulls the
2171
+ * engine exactly like a literal. */
2172
+ | "regex.new"
2173
+ /** structuredClone with a NON-EMPTY transfer array of static values:
2174
+ * nothing static is transferable, so the call always throws Node's
2175
+ * catchable DataCloneError ("Found invalid value in transferList.") —
2176
+ * lowered directly (the list's values need no DOM representation to
2177
+ * fail). */
2178
+ | "dyn.cloneTransferFail"
2179
+ /** node:events EventEmitter (scr_events_emitter.c, link-gated by
2180
+ * moduleUsesEmitter). The receiver of every instance form is a borrowed
2181
+ * emitter-hierarchy object (`%EventEmitter` or a user subclass — the
2182
+ * backend reinterprets to ScrEmitter*, the identical prefix); event
2183
+ * names are borrowed strings (compile-time literals — the frontend
2184
+ * fences non-literals and unifies each event's argument tuple program-
2185
+ * wide). The chaining forms (on/off/removeAll/setMax) return the
2186
+ * receiver +1 typed as its static class, Node's `return this`.
2187
+ *
2188
+ * emitter.new: `new EventEmitter()` → a +1 bare emitter. emitter.ctor:
2189
+ * super() into the prefix of an emitted subclass (borrowed receiver,
2190
+ * void — allocation already initialized the prefix). emitter.on:
2191
+ * (recv, name, cb /moves/, once, prepend) — the backend synthesizes the
2192
+ * per-signature va_list invoke adapter from the cb's func type.
2193
+ * emitter.emit: (recv, name, ...tuple) — VARIADIC, the one libCall
2194
+ * whose arg count exceeds its signature; args are borrowed, result is
2195
+ * the had-listeners bool. emitter.emitError: emit('error', err) —
2196
+ * throws err when unhandled. count/countFn/names/listeners/getMax/
2197
+ * setMax/setDefaultMax/getDefaultMax are the introspection surface. */
2198
+ | "emitter.new" | "emitter.ctor" | "emitter.on" | "emitter.off" | "emitter.checkListener" | "emitter.onDyn" | "emitter.offDyn" | "emitter.removeAll" | "emitter.emit" | "emitter.emitError" | "emitter.count" | "emitter.countFn" | "emitter.names" | "emitter.listeners" | "emitter.setMax" | "emitter.getMax"
2199
+ /** Stream-'data' registration twins of emitter.on/onDyn (same args):
2200
+ * chosen at registration sites whose receiver is stream-rooted, so the
2201
+ * backend emits DATA thunks — the runtime's 'data' emission carries
2202
+ * BOTH payload slots (bytes, string; exactly one non-NULL — encoded
2203
+ * streams deliver strings), and the thunk unwraps the listener's
2204
+ * declared side (typed) or boxes by tag (dyn). emitter.emitData is the
2205
+ * user-emit form: (recv, name, chunk) with a bytes OR string chunk. */
2206
+ | "emitter.onData" | "emitter.onDataDyn" | "emitter.emitData" | "emitter.setDefaultMax" | "emitter.getDefaultMax"
2207
+ /** node:stream (scr_stream.c, link-gated by moduleUsesStream — which
2208
+ * implies the emitter unit: stream events dispatch through the embedded
2209
+ * ScrEmitter registry). Receivers are borrowed stream-class objects
2210
+ * (`%Readable`/`%Writable`/`%Duplex`/`%Transform`/`%PassThrough` — one
2211
+ * runtime layout, reinterpreted by side).
2212
+ *
2213
+ * Constructors (`readable.new` et al): args are [hwmR, hwmW, flags]
2214
+ * followed by the PRESENT user callbacks in canonical order (read,
2215
+ * write, final, destroy, transform, flush — the flags f64 is a bitmask
2216
+ * naming which follow; absent ones emit NULL). Every callback closure
2217
+ * MOVES and carries a leading `this` param (the stream), invoked
2218
+ * through compiler-emitted adapters. Results are +1.
2219
+ *
2220
+ * readable.push / readable.pushStr / readable.pushNull: Node's push —
2221
+ * buffers or delivers (bytes chunk borrowed; string converted utf8);
2222
+ * returns the below-hwm answer. readable.read: (recv, size — -1 for
2223
+ * absent) → Buffer|null union. pause/resume return recv +1 (`this`);
2224
+ * isPaused answers the flag. readable.pipe: (recv, dst, end) → dst +1,
2225
+ * fires 'pipe' on dst; readable.unpipe (recv[, dst]) → recv +1.
2226
+ * writable.write/writeStr: (recv, chunk[, cb]) → below-hwm bool (cb
2227
+ * MOVES when present, called after the user write completes).
2228
+ * writable.end: (recv, flags[, chunk][, cb]) → recv +1. cork/uncork are
2229
+ * void. stream.destroy/destroyErr: (recv[, err]) → recv +1.
2230
+ * stream.prop: (recv, name-literal) → the flag/number the name asks
2231
+ * for; stream.errored → Error|null union; readable.flowing →
2232
+ * bool|null union. All may leave a listener's exception pending
2233
+ * (dispatch runs user code synchronously, like emit). */
2234
+ | "readable.new" | "writable.new" | "duplex.new" | "transform.new" | "passthrough.new"
2235
+ /** Subclass initialization (`super(options?)` in a user `extends
2236
+ * Readable` constructor): same tail as the `.new` forms, prefixed with
2237
+ * the BORROWED receiver (the emitted subclass allocation — vtable and
2238
+ * display name stamped, state NULL until here). Overridden underscore
2239
+ * methods arrive as synthesized wrapper closures dispatching through
2240
+ * the vtable. Void result. */
2241
+ | "readable.init" | "writable.init" | "duplex.init" | "transform.init" | "passthrough.init"
2242
+ /** The dyn-options twins (a checked-dynamic options record — the JS
2243
+ * lane's `super(options)` forwarding and `new Readable(dynVar)`): the
2244
+ * option walk runs at RUNTIME with Node's reading rules. newDyn:
2245
+ * (optsDyn) → the fresh stream; initDyn: (recv, optsDyn, flags,
2246
+ * ...fallback wrapper closures in canonical order — the flags literal
2247
+ * names which ride, exactly the .init callback ABI). MAY THROW (a
2248
+ * consumed-but-unlowered option is the compile fence's runtime twin). */
2249
+ /** stream.finished(s, cb) — the callback form: the watcher fires once
2250
+ * at the terminal point with the finish status; the result is the +1
2251
+ * cleanup closure. stream.pipeline(count, s1..sn, cb): chains pipes,
2252
+ * propagates the first error by destroying the rest, calls cb after the
2253
+ * last 'close'; answers the destination +1. The Dyn twins take the
2254
+ * callback as a checked-dynamic VALUE (mustCall wrappers). */
2255
+ | "stream.finished" | "stream.finishedDyn" | "stream.pipeline" | "stream.pipelineDyn" | "readable.newDyn" | "writable.newDyn" | "duplex.newDyn" | "transform.newDyn" | "passthrough.newDyn" | "readable.initDyn" | "writable.initDyn" | "duplex.initDyn" | "transform.initDyn" | "passthrough.initDyn" | "readable.push" | "readable.pushStr" | "readable.pushNull" | "readable.pushU" | "readable.pushDyn" | "readable.unshift" | "readable.unshiftStr" | "readable.read" | "readable.pause" | "readable.resume" | "readable.setEncoding"
2256
+ /** for-await over a readable (the desugared loop's per-pass promise):
2257
+ * +1 promise of the next chunk — buffered content, the EOF sentinel
2258
+ * (empty Buffer / dyn undefined), or a rejection with the stream's
2259
+ * error. The Dyn twin boxes chunks by runtime tag (the JS lane).
2260
+ * readable.fromArr is Readable.from(array): a fully-seeded object-
2261
+ * entry stream (one whole chunk per element; strings per the flag). */
2262
+ | "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"
2263
+ /** The underscore-method assignment surface (`r._read = fn` after
2264
+ * construction — Node's own-property shadow of the prototype method):
2265
+ * args [stream receiver (borrowed), callback closure (+1 moves)]. The
2266
+ * runtime slot the matching option callback fills swaps its closure
2267
+ * and invoke thunk; the next dispatch uses it (Node's timing). The
2268
+ * setters themselves never throw. */
2269
+ | "stream.setRead" | "stream.setWrite" | "stream.setFinal" | "stream.setDestroy" | "stream.setTransform" | "stream.setFlush"
2270
+ /** NodeJS.ErrnoException's `.code` read: borrowed error-hierarchy
2271
+ * receiver → the interned `string | undefined` union (type-directed
2272
+ * construction in the backend, the process.envGet pattern) — the errno
2273
+ * name where a throw site stamped one (fs, exec spawn/timeout,
2274
+ * process.kill, the spawn 'error' event), the undefined arm everywhere
2275
+ * else. Never throws. */
2276
+ | "error.code"
2277
+ /** node:assert (scr_assert.c; assert.match in scr_regex.c — every call
2278
+ * site carries a regex value, so the regex link switch is already on).
2279
+ * Failures throw a catchable AssertionError — a runtime %Error whose
2280
+ * name is "AssertionError" and whose code slot is "ERR_ASSERTION" — so
2281
+ * `instanceof Error`, `.name`, `.message`, and `.code` all answer like
2282
+ * Node's. Generated messages are Node's assertion_error.js scalar forms
2283
+ * byte-exactly (the short `a !== b` form, the stacked `+ actual
2284
+ * - expected` diff with the string `^` indicator, the inline-vs-block
2285
+ * not-equal split); composite deep failures carry the header line
2286
+ * without the rendered inspect diff (documented divergence).
2287
+ *
2288
+ * assert.ok: (pass, message) — the frontend computed the truthiness AND
2289
+ * the full message (the user's, or the compile-time source-text form —
2290
+ * assert.fail lowers here too with pass=false). assert.eqF64/eqStr/
2291
+ * eqBool: (a, b, negated, deep, msg, hasMsg) — Object.is comparison,
2292
+ * covering strictEqual/notStrictEqual and the scalar deepStrictEqual
2293
+ * pair; msg is a typed dummy ("" literal) when hasMsg is false (Node
2294
+ * distinguishes an omitted message from an empty one per operator).
2295
+ * assert.deepResult: (equal, negated, msg, hasMsg) — the verdict of a
2296
+ * frontend-synthesized structural comparison, turned into Node's throw.
2297
+ * assert.sameValue: Object.is over doubles (the deep-equal helpers'
2298
+ * number leaf; never throws). assert.match: (s, regex, negated, msg,
2299
+ * hasMsg) — a fresh exec from index 0. assert.throwsNone: (rejection,
2300
+ * ename, hasEname, msg, hasMsg) — the "Missing expected
2301
+ * exception|rejection" throw of assert.throws/rejects whose callback
2302
+ * returned (fulfilled) normally, with Node's ` (${expected.name})`
2303
+ * detail when the expected class or shape carries a name.
2304
+ * assert.throwsMismatch: (expectedName, error) — the wrong-class throw
2305
+ * of the assert.throws(fn, ErrorClass) form. assert.eqSym:
2306
+ * (a, b, negated, deep, msg, hasMsg) — strict equality over symbol
2307
+ * values, pointer identity with v24's "Symbol(desc)" stacked-diff
2308
+ * messages (scr_symbol.c, the assert.match pattern — symbol-typed
2309
+ * slots already flip the symbol link switch). assert.eqDyn:
2310
+ * (a, b, negated, deep, msg, hasMsg) — the whole quartet over
2311
+ * checked-dynamic operands (both slots dyn; the frontend boxes a
2312
+ * static side with dynFrom first): SameValue for the strict pair over
2313
+ * the DOM kinds (boxed-closure identity for functions), the structural
2314
+ * DOM walk for the deep pair, with assertion_error.js's messages —
2315
+ * scalar forms byte-exact, composites rendered compact:false/sorted
2316
+ * through the DOM and diffed with the real myers line printer.
2317
+ *
2318
+ * The assert.throws(fn, {name/code/message}) shape check
2319
+ * (expectedException over the static error surface): shapeBegin
2320
+ * stashes the caught error, shapeStr/shapeRe add one expected key each
2321
+ * (key ids 0 code / 1 message / 2 name; shapeRe lives in scr_regex.c —
2322
+ * its regex argument flips the regex link switch — and tests eagerly
2323
+ * so scr_assert.c stays libregexp-free), then shapeEnd throws Node's
2324
+ * deep-equal Comparison diff BYTE-EXACTLY (the bounded key set makes
2325
+ * the rendering enumerable) or the custom message.
2326
+ * assert.throwsRegex: (regex, error, msg, hasMsg) — the
2327
+ * assert.throws(fn, /re/) check over String(error), Node's
2328
+ * regex-mismatch message. assert.regexErrTest: doesNotReject's silent
2329
+ * regex predicate over String(error) (never throws).
2330
+ * assert.unwantedRejection: (error, msg, hasMsg) — doesNotReject's
2331
+ * "Got unwanted rejection" throw.
2332
+ * assert.ifErrorErr/F64/Str/Bool: assert.ifError's per-type throws
2333
+ * ("ifError got unwanted exception: " + the error's message/name or
2334
+ * the value's inspection) — the frontend routes null/undefined to a
2335
+ * no-op and everything else here (Node throws for falsy values too).
2336
+ * All arguments are borrowed. */
2337
+ | "assert.ok" | "assert.eqF64" | "assert.eqStr" | "assert.eqBool" | "assert.eqSym" | "assert.eqDyn" | "assert.deepResult" | "assert.sameValue" | "assert.match" | "assert.throwsNone" | "assert.throwsMismatch" | "assert.throwsRegex" | "assert.shapeBegin" | "assert.shapeStr" | "assert.shapeRe" | "assert.shapeEnd" | "assert.regexErrTest" | "assert.unwantedRejection"
2338
+ /** Node's expectsError over an error-INSTANCE expected (assert.throws/
2339
+ * rejects second argument): walk the expected DOM error's keys (name,
2340
+ * message, code — the %error marker skipped) and deep-compare each
2341
+ * against the caught value's; a mismatch throws the deep-equal
2342
+ * AssertionError (scr_assert.c). MAY THROW by design. */
2343
+ | "assert.expectsErrDyn" | "assert.ifErrorErr" | "assert.ifErrorF64" | "assert.ifErrorStr" | "assert.ifErrorBool" | "assert.ifErrorDyn" | "assert.refEqBytes" | "assert.refEqFn" | "assert.bytesDeepEq"
2344
+ /** util.inspect (scr_inspect.c — its own link switch, moduleUsesInspect):
2345
+ * the runtime half of the static rendering. Scalar formatters return +1
2346
+ * strings (insp.f64: JS ToString except -0; insp.str: the quoting
2347
+ * ladder + line splitting; insp.regex: /source/flags; insp.buffer:
2348
+ * <Buffer aa ..>). insp.error renders the STACKLESS [Name: message]
2349
+ * form with the code slot as its one property. insp.dyn walks the
2350
+ * checked-dynamic DOM entirely in the runtime (its shape lives in the
2351
+ * value); insp.dynS is format's %s twin (dyn strings pass verbatim).
2352
+ * insp.jsval ([value, recurse, depth], --dynamic only) renders the
2353
+ * island scalars and THROWS a catchable TypeError on composites (the
2354
+ * may-throw seed set). begin/entry/moreItems/end drive the frame
2355
+ * engine from the compiler-synthesized per-type traversal helpers
2356
+ * (%util.insp.N — the deepStrictEqual precedent). */
2357
+ | "insp.f64"
2358
+ /** util.format %j over a checked-dynamic argument: the runtime DOM
2359
+ * walk (JS-exact stringify; root undefined/function prints
2360
+ * "undefined"; a handle in the tree throws the loud fence). */
2361
+ | "insp.jsonDyn" | "insp.str" | "insp.regex" | "insp.buffer" | "insp.error" | "insp.dyn" | "insp.dynS" | "insp.jsval" | "insp.begin" | "insp.entry" | "insp.key" | "insp.moreItems" | "insp.end"
2362
+ /** node:string_decoder's utf8 StringDecoder (scr_string.c): the decoder
2363
+ * value is a one-field record whose f64 PACKS the pending partial
2364
+ * sequence (count + up to 3 raw bytes — Node buffers at most 3 for
2365
+ * every encoding); the frontend's interned %strdec helpers thread it,
2366
+ * with the decoder's CANONICAL encoding name first, through these pure
2367
+ * functions. write: (enc, pending, chunk) → the decoded complete
2368
+ * prefix of pending+chunk (+1); next: (enc, pending, chunk) → the
2369
+ * packed NEW pending; end: (enc, pending) → the buffered partial's
2370
+ * flush (+1). Node-exact per encoding (oracle-pinned); none throws. */
2371
+ | "strdec.write" | "strdec.next" | "strdec.end"
2372
+ /** node:readline's question/close slice (scr_readline.c, linked under
2373
+ * the events gate — these fns imply moduleUsesProcessEvents). The
2374
+ * interface value is an f64 handle (the Timeout-id precedent).
2375
+ * rl.create: [] → f64 — createInterface({ input: process.stdin,
2376
+ * output: process.stdout }), registering the unit's shared stdin
2377
+ * consumer (an OPEN interface keeps the loop alive until close/EOF,
2378
+ * Node's semantics). rl.question: [handle, query, cb] — writes the
2379
+ * query to stdout (Node writes under pipes too) and delivers the next
2380
+ * line's text through a backend-picked adapter (zero-param or
2381
+ * (answer: string)); THROWS Node's "readline was closed" on a closed
2382
+ * interface (may-throw). rl.close: [handle] — fires 'close' listeners
2383
+ * SYNCHRONOUSLY (Node's inline emit) and detaches the consumer (the
2384
+ * loop stops waiting on fd 0). rl.onClose: [handle, cb] — a zero-arg
2385
+ * listener (moves); stdin EOF closes every open interface with the
2386
+ * buffered partial line DISCARDED, like Node. */
2387
+ | "rl.create" | "rl.question" | "rl.close" | "rl.onClose"
2388
+ /** node:timers/promises — the promisified pair (scr_async.c, beside
2389
+ * the timer heap they ride): tp.setTimeout: [ms] → a pending void
2390
+ * promise a one-shot heap timer fulfills (the loop's timer phase, FIFO
2391
+ * against equal deadlines like Node); tp.setImmediate: [] → the same
2392
+ * through the immediate queue (fires before due timers of later loop
2393
+ * turns, Node's check phase). Neither throws. */
2394
+ | "tp.setTimeout" | "tp.setImmediate"
2395
+ /** node:diagnostics_channel (scr_dc.c, linked when any dc.* appears —
2396
+ * the zlib gating precedent): a process-global name→channel registry;
2397
+ * channel values are f64 handles (types.ts maps Channel to F64, the
2398
+ * readline.Interface pattern). Subscribers are DOM function values —
2399
+ * identity-compared by unsubscribe, called (message, name) by publish
2400
+ * over a SNAPSHOT of the list (a subscriber unsubscribing itself
2401
+ * mid-publish still lets its siblings fire, Node's behavior). dc.publish
2402
+ * MAY THROW: a subscriber's throw propagates out of publish (catchable
2403
+ * there) where Node routes it to triggerUncaughtException — the
2404
+ * documented divergence. subscribe/unsubscribe throw Node's
2405
+ * ERR_INVALID_ARG_TYPE TypeError for non-function subscribers. */
2406
+ | "dc.channel" | "dc.subscribe" | "dc.unsubscribe" | "dc.hasSubscribers" | "dc.publish" | "dc.chanSubscribe" | "dc.chanUnsubscribe" | "dc.chanHasSubscribers" | "dc.chanName"
2407
+ /** TracingChannel (dc.tracingChannel): a registry entry of the five
2408
+ * event channels, an f64 handle like Channel (types.ts). tcSubscribe/
2409
+ * tcUnsubscribe walk a DOM handlers object's five event keys (truthy
2410
+ * non-function slots throw the per-channel ERR_INVALID_ARG_TYPE);
2411
+ * tcTraceSync/tcTraceCallback/tcTracePromise run Node's publish choreography in C over
2412
+ * DOM values (fn, ctx, thisArg, args-array) with thisArg bound as the
2413
+ * ambient receiver — the traced call's throw and any subscriber throw
2414
+ * both propagate (MAY THROW). tcTraceCallback wraps args[position] in a
2415
+ * native error/result + asyncStart/asyncEnd publisher and throws Node's
2416
+ * TypeError when that slot is not callable. tracingChannelOf is the
2417
+ * five-Channel collection form of the constructor. */
2418
+ /** setImmediate as a first-class DOM value (scr_async.c): a minted dyn
2419
+ * callable scheduling args[0](args[1..]) on the immediate queue — the
2420
+ * Node-suite traceCallback shape (`traceCallback(setImmediate, ...)`).
2421
+ * Calling it validates the callback (the dyn call machinery); minting
2422
+ * never throws. */
2423
+ | "timers.setImmediateFnValue"
2424
+ /** `new Promise(setImmediate)` (the Node-suite early-exit shape): a
2425
+ * fresh promise an immediate fulfills with the undefined DOM value —
2426
+ * the executor IS setImmediate, so resolve rides the immediate queue
2427
+ * (scr_async.c). Never throws. */
2428
+ | "timers.immediatePromise" | "dc.tracingChannel" | "dc.tracingChannelOf" | "dc.tcChannel" | "dc.tcHasSubscribers" | "dc.tcSubscribe" | "dc.tcUnsubscribe" | "dc.tcTraceSync" | "dc.tcTraceCallback"
2429
+ /** tracePromise (scr_dc.c): start publish, the traced call, a wrap of
2430
+ * non-promise results, the end publish, and a REACTION FIBER that
2431
+ * awaits the traced promise and publishes asyncStart/asyncEnd (error
2432
+ * first on rejection) before settling the returned promise<dyn> with
2433
+ * the passed-through outcome. MAY THROW (the traced call and the
2434
+ * synchronous publishes). */
2435
+ | "dc.tcTracePromise"
2436
+ /** AsyncLocalStorage (node:async_hooks — scr_async.c): stores are f64
2437
+ * handles; contexts are immutable fiber-carried snapshots (spawned
2438
+ * fibers inherit the spawner's — Node's init-time capture). run/exit
2439
+ * enter (or clear) the store, call the DOM function with forwarded
2440
+ * arguments, and restore (the finally); getStore answers the current
2441
+ * DOM value or undefined; enterWith installs with no restore point.
2442
+ * run/exit MAY THROW (the callback's own throws propagate). */
2443
+ /** `await v` over a checked-dynamic VALUE (scr_async.c): a DOM promise
2444
+ * adopts (rejections re-throw — MAY THROW), anything else takes JS's
2445
+ * one-microtask non-thenable await and answers itself. Only emitted
2446
+ * inside async bodies (the frontend's isAsync gate). */
2447
+ | "async.awaitDyn"
2448
+ /** The bare one-microtask hop (scr_await_hop): `await v` over a typed
2449
+ * NON-promise value — JS awaits non-thenables through exactly one
2450
+ * microtask turn and yields the value itself. Never throws. */
2451
+ | "async.hop" | "als.new" | "als.get" | "als.run" | "als.exitRun" | "als.enterWith" | "als.disable"
2452
+ /** Channel.bindStore/unbindStore/runStores (scr_dc.c): the
2453
+ * AsyncLocalStorage integration — set-semantics bindings per store,
2454
+ * runStores entering every bound store with transform(data) around the
2455
+ * publish and the callback (MAY THROW: transforms, subscribers, and
2456
+ * the callback all run). */
2457
+ | "dc.chanBindStore" | "dc.chanUnbindStore" | "dc.chanRunStores"
2458
+ /** process warnings (scr_lib.c): onWarning/offWarning register DOM
2459
+ * listeners; emitWarning applies Node's full argument grammar over the
2460
+ * call's DOM argument vector (ERR_INVALID_ARG_TYPE TypeErrors — MAY
2461
+ * THROW; a listener throw propagates too) and always prints Node's
2462
+ * stderr report. Emission is synchronous (SEMANTICS.md). */
2463
+ | "process.onWarning" | "process.offWarning" | "process.emitWarning"
2464
+ /** process.on('unhandledRejection', fn): registers a DOM listener the
2465
+ * loop-end report dispatches per never-observed rejection — (reason,
2466
+ * promise) — instead of printing and exiting 1 (scr_async.c). Throws
2467
+ * Node's ERR_INVALID_ARG_TYPE on a non-function. */
2468
+ | "process.onUnhandledRejection"
2469
+ /** The Number statics with a static C implementation (scr_lib.c): one
2470
+ * f64 arg → bool, JS-exact BY CONSTRUCTION — Number.isFinite/isNaN/
2471
+ * isInteger/isSafeInteger never coerce, and the frontend routes only
2472
+ * f64-typed arguments here (other static types fence). None throws. */
2473
+ | "number.isFinite" | "number.isNaN" | "number.isInteger" | "number.isSafeInteger"
2474
+ /** Date, the composed slice (scr_lib.c). Date VALUES have no
2475
+ * representation — exactly `Date.now()` and the composed
2476
+ * `new Date(ms?).toISOString()` forms lower. date.now is Node's integer
2477
+ * milliseconds since epoch (never throws); date.toISOString formats one
2478
+ * f64 millisecond time value with Node's exact rules (UTC,
2479
+ * YYYY-MM-DDTHH:mm:ss.sssZ, expanded ±YYYYYY years outside 0–9999,
2480
+ * ToInteger truncation of fractional ms) and THROWS Node's "Invalid
2481
+ * time value" RangeError on NaN / out-of-range input (may-throw seed).
2482
+ * Results: f64 / owned (+1) string. */
2483
+ | "date.now" | "date.toISOString"
2484
+ /** The composed `new Date(dateString).getTime()` read: one borrowed
2485
+ * string, f64 milliseconds since epoch. The parsed grammar is BOUNDED
2486
+ * (documented divergence — V8's parser accepts far more): the ASN.1
2487
+ * validity shape X509Certificate.validFrom/validTo answer ("Jul 1
2488
+ * 00:00:00 2026 GMT" — the portless cert-expiry read), and ECMA's own
2489
+ * date-time string format (YYYY-MM-DD[THH:mm[:ss[.sss]]][Z|±HH:MM] —
2490
+ * date-only forms are UTC, exactly the spec). Anything else is NaN,
2491
+ * Node's invalid-date getTime. Never throws. */
2492
+ | "date.parseGetTime"
2493
+ /** `Date.UTC(...)` — seven f64 arguments (the frontend completes the
2494
+ * spec's defaults for omitted trailing parts: month 0, date 1, time
2495
+ * parts 0), the spec's MakeDay/MakeTime/TimeClip exactly: 0–99 years
2496
+ * map to 1900+year, out-of-range months/dates roll over, non-finite
2497
+ * parts and out-of-range results answer NaN. Never throws. */
2498
+ | "date.utc"
2499
+ /** The fs option forms and friends (scr_lib.c), all throwing catchably
2500
+ * like the rest of sync fs. mkdirRecursiveSync is Node's recursive
2501
+ * algorithm (try mkdir, EEXIST-dir is fine, ENOENT creates the parent
2502
+ * first — errors report Node's errno at Node's path, EEXIST at a file
2503
+ * target, ENOTDIR at the full path past a file); the first-created-dir
2504
+ * return value has no lowering (statement position only, frontend-
2505
+ * fenced). rmOptsSync is rmSync with (recursive, force) bools: force
2506
+ * swallows ENOENT, recursive removes trees post-order, a directory
2507
+ * without recursive throws the EISDIR-worded error (divergence 13's
2508
+ * wording note). mkdtempSync appends the six X's and returns the
2509
+ * created path (+1). accessSync takes the F_OK/R_OK/W_OK/X_OK bits as
2510
+ * one f64 (the frontend bakes fs.constants.* as literals and completes
2511
+ * an omitted mode to 0). readFdSync/readFdSyncBytes are the
2512
+ * readFileSync(fd[, "utf8"]) forms — a read(2) loop to EOF on the fd
2513
+ * (the stdin path); errors carry Node's no-path message shape. */
2514
+ | "fs.mkdirRecursiveSync" | "fs.rmOptsSync"
2515
+ /** rmOptsSync's maxRetries/retryDelay form (path, recursive, force,
2516
+ * maxRetries, retryDelay): Node's linear-backoff retry on
2517
+ * EBUSY/EMFILE/ENFILE/ENOTEMPTY/EPERM — the tmpdir-harness shape
2518
+ * rmSync(p, { maxRetries: 3, recursive: true, force: true }). */
2519
+ | "fs.rmRetrySync" | "fs.mkdtempSync" | "fs.accessSync" | "fs.readFdSync" | "fs.readFdSyncBytes"
2520
+ /** isatty(3) over an fd literal (0/1/2 — process.stdin/stdout/stderr
2521
+ * .isTTY reads). A real boolean: false where Node's non-TTY streams
2522
+ * expose undefined (documented divergence). Never throws. */
2523
+ | "process.isTTY"
2524
+ /** process.stdin.destroy(): a deliberate no-op (no stream machinery
2525
+ * exists to tear down; documented in SEMANTICS.md). */
2526
+ | "process.stdinDestroy"
2527
+ /** process.stdin.setRawMode(mode) — one borrowed bool arg, void. On a
2528
+ * TTY stdin: termios raw mode on/off (libuv's UV_TTY_MODE_RAW flag set,
2529
+ * the mode Node's setRawMode(true) applies; false restores the entry
2530
+ * state). On a NON-TTY stdin Node's process.stdin has no such method at
2531
+ * all, so the call throws Node's exact catchable TypeError
2532
+ * ("process.stdin.setRawMode is not a function") — the may-throw seed
2533
+ * carries it. */
2534
+ | "process.stdinSetRawMode"
2535
+ /** Terminal width over an fd literal (1/2 — process.stdout/stderr
2536
+ * .columns): ioctl(TIOCGWINSZ). The result is the module's interned
2537
+ * `number | undefined` union — a non-TTY stream (or an ioctl refusal)
2538
+ * yields the undefined arm, exactly Node's missing `.columns`. Never
2539
+ * throws. */
2540
+ | "process.columns"
2541
+ /** String surface with scr_lib.c implementations. fromCharCode takes
2542
+ * ONE f64[] arg (the frontend packs plain arguments into an array
2543
+ * literal, or forwards a whole-array spread — the path.join
2544
+ * convention) and builds the string from UTF-16 code units: each code
2545
+ * goes through ToUint16, adjacent surrogate pairs combine into one
2546
+ * code point, and LONE surrogates become U+FFFD (divergence 1's
2547
+ * storage policy — printed output still matches Node byte-for-byte).
2548
+ * lastIndexOf is the one-argument form: the LAST occurrence as a
2549
+ * UTF-16 index (-1 when absent; the empty needle finds the length,
2550
+ * per spec). Borrowed args; +1 string / plain f64; neither throws. */
2551
+ | "string.fromCharCode" | "string.lastIndexOf"
2552
+ /** String.raw(template, ...subs): the raw literals array (a string[]
2553
+ * read off the template record) interleaved with the PRE-STRINGIFIED
2554
+ * substitutions (the frontend applies the static ToString and packs
2555
+ * them into one string[] literal) — extra substitutions drop, missing
2556
+ * ones skip, the spec's loop exactly (scr_array.c). Borrowed args;
2557
+ * +1 string; never throws. */
2558
+ | "string.raw"
2559
+ /** WHATWG TextDecoder.decode over u8 bytes (scr_bytes.c): utf-8 with
2560
+ * default options — the same maximal-subpart replacement decode as
2561
+ * Buffer.toString("utf8"), with the leading BOM stripped (the one
2562
+ * behavioral difference; ignoreBOM defaults to false). Only the
2563
+ * COMPOSED `new TextDecoder().decode(bytes)` form lowers — decoder
2564
+ * values have no representation. TextEncoder.encode needs no libFn:
2565
+ * `new TextEncoder().encode(s)` lowers to buffer.fromStr(s, "utf8")
2566
+ * (identical bytes — ScrStr storage is well-formed UTF-8). Borrowed
2567
+ * arg; owned (+1) string; never throws. */
2568
+ | "text.decode"
2569
+ /** The wider sync fs slice (scr_lib.c), all throwing catchably with
2570
+ * Node's errno message shapes and `.code` stamped like the rest of
2571
+ * sync fs. unlink/chmod/chown wrap the syscalls 1:1 (Node reports the
2572
+ * syscall's own name). copyFileSync copies contents into a fresh (or
2573
+ * truncated) destination carrying the SOURCE's mode (libuv's
2574
+ * uv_fs_copyfile behavior); its errors carry BOTH paths — Node's
2575
+ * "copyfile 'src' -> 'dest'". lstatSync is statSync without following
2576
+ * a trailing symlink (Node reports lstat); stats.isSymbolicLink /
2577
+ * stats.mtimeMs are pure reads on the widened snapshot (mtimeMs is
2578
+ * milliseconds with the nanosecond fraction, Node's arithmetic).
2579
+ * writeFileModeSync is writeFileSync(path, data, { mode }): the mode
2580
+ * applies at CREATION only (open(2) with O_CREAT, umask applying),
2581
+ * exactly Node — an existing file keeps its permissions. mkdirModeSync
2582
+ * / mkdirRecursiveModeSync are the mkdirSync option forms with an
2583
+ * explicit mode (the recursive walk passes it to every directory it
2584
+ * creates, like Node's). */
2585
+ | "fs.unlinkSync" | "fs.chmodSync" | "fs.chownSync" | "fs.copyFileSync" | "fs.lstatSync"
2586
+ /** fs.openSync(path, flags) → the raw fd as f64, and fs.closeSync(fd)
2587
+ * — the pair behind spawn's fd-stdio form. flags is Node's string
2588
+ * grammar ("r", "w", "a" and the +/x variants; unknown flags throw
2589
+ * Node's ERR_INVALID_ARG_VALUE TypeError text). Both throw Node-shaped
2590
+ * fs errors (openSync ENOENT/EACCES..., closeSync EBADF). */
2591
+ | "fs.openSync" | "fs.readSync" | "fs.closeSync"
2592
+ /** fs.watch(path, listener?) → an FSWatcher handle (scr_watch.c —
2593
+ * linked, and scr_watch_install() emitted, only when these appear on
2594
+ * the IR; moduleUsesFsWatch is the switch). The path opens NOW —
2595
+ * failure throws Node's fs error synchronously ("ENOENT: ..., watch
2596
+ * 'x'", the polling-fallback catch shape) — and the unit's kqueue
2597
+ * (EVFILT_VNODE) delivers "rename"/"change" through the loop's watch
2598
+ * hook. The callback (nullable) MOVES in with an adapter per listener
2599
+ * shape (zero-param, or the (eventType: string) form — runtime-
2600
+ * provided); an open watcher keeps the loop alive until watcher.close()
2601
+ * (idempotent, receiver borrowed, statement position only). */
2602
+ | "fs.watch" | "fs.watchCb" | "watcher.close"
2603
+ /** The composed `new crypto.X509Certificate(data).fingerprint` read
2604
+ * (scr_lib.c — no certificate handle exists): the SHA-1 of the DER,
2605
+ * uppercase colon-separated, over PEM or raw-DER Buffer input; other
2606
+ * inputs throw Node's ERR_OSSL_PEM_NO_START_LINE Error (may-throw). */
2607
+ | "crypto.x509Fingerprint" | "crypto.x509FingerprintStr"
2608
+ /** The certificate's Validity window (validFrom / validTo reads —
2609
+ * scr_lib.c's minimal ASN.1 walk to the TBSCertificate validity
2610
+ * SEQUENCE): UTCTime and GeneralizedTime render in Node's exact
2611
+ * ASN1_TIME_print shape ("Jul 1 00:00:00 2026 GMT" — %2d space-padded
2612
+ * day). Same input contract and PEM error as the fingerprint pair
2613
+ * (may-throw). */
2614
+ | "crypto.x509ValidFrom" | "crypto.x509ValidFromStr" | "crypto.x509ValidTo" | "crypto.x509ValidToStr" | "stats.isSymbolicLink" | "stats.mtimeMs" | "fs.writeFileModeSync" | "fs.mkdirModeSync" | "fs.mkdirRecursiveModeSync"
2615
+ /** spawnSync with options (scr_child.c): the cp.spawnSync core plus the
2616
+ * option slice portless-class CLIs pass — timeout (killSignal fires at
2617
+ * the deadline and the result carries error: ETIMEDOUT + the signal,
2618
+ * Node's shape), killSignal (a signal NAME; "" = the SIGTERM default),
2619
+ * and per-fd stdio modes (in: 0 /dev/null, 1 ignore, 2 inherit; out/
2620
+ * err: 0 capture, 1 ignore → "", 2 inherit → ""). NEVER throws — spawn
2621
+ * failure and timeout are data on the result, like Node's error
2622
+ * property. spawnRes.signal is the result's termination signal as the
2623
+ * call site's `Signals | null` union (null = exited normally or spawn
2624
+ * failure), constructed type-directedly like spawnRes.status. */
2625
+ | "cp.spawnSyncOpts"
2626
+ /** cp.spawnSyncOpts with the stdio carried as a RUNTIME string —
2627
+ * "pipe" | "ignore" | "inherit", proven by the call site's TYPE (the
2628
+ * defaultRunner idiom `stdio: options?.stdio ?? "pipe"`); the runtime
2629
+ * maps the value to the three modes. Args (cmd, argv, timeout,
2630
+ * killSignal, stdio). Never throws, like the other spawnSync forms. */
2631
+ | "cp.spawnSyncStdioStr" | "spawnRes.signal"
2632
+ /** spawn with options (scr_child.c): the cp.spawn core plus PER-SLOT
2633
+ * stdio — args are (cmd, argv, inMode, outMode, errMode, outFd, errFd,
2634
+ * detached, hasEnv, envPairs, cwd); modes 0 ignore (/dev/null), 1
2635
+ * inherit, 2 fd (out/err only — the fd dup2s into the child's slot,
2636
+ * Node's stdio fd form; the daemon-log idiom ["ignore", logFd, logFd]).
2637
+ * detached is POSIX_SPAWN_SETSID (the child gets its own session and
2638
+ * process group, Node's semantics), env is a REPLACEMENT ([k,v,...]
2639
+ * pairs like cp.execSync's), cwd ""=inherit. Same event/loop story as
2640
+ * cp.spawn. */
2641
+ | "cp.spawnOpts"
2642
+ /** Atomics.wait(int32Array, idx, expected, timeoutMs) → "not-equal"
2643
+ * when the element differs from `expected`, else a real nanosleep for
2644
+ * the timeout and "timed-out" (scr_lib.c). scriptc has no threads —
2645
+ * no other agent can ever notify, so for every compilable program this
2646
+ * IS the spec's behavior, and "ok" is unreachable; the frontend
2647
+ * REQUIRES the timeout argument (an infinite wait here is a certain
2648
+ * deadlock, fenced). The SharedArrayBuffer the lib types demand exists
2649
+ * only syntactically (new Int32Array(new SharedArrayBuffer(n)) lowers
2650
+ * to a plain i32 typed array — sharing is unobservable without
2651
+ * threads; SEMANTICS.md documents the stance). Never throws; +1 string
2652
+ * result. */
2653
+ | "atomics.wait";
2654
+ /** Numeric binary ops. The bitwise six (`&`/`|`/`^`/`<<`/`>>`/`>>>`) have
2655
+ * JS ToInt32/ToUint32 semantics — operands convert (NaN/±Infinity → 0,
2656
+ * truncate, wrap mod 2^32), the operation runs in 32-bit space (shift
2657
+ * counts mask to 5 bits), and the result returns to f64 (`>>>` as Uint32,
2658
+ * the rest as Int32) — backends emit the scr_bit_* runtime helpers. */
2659
+ export type IrNumBinOp = "+" | "-" | "*" | "/" | "%" | "**" | "&" | "|" | "^" | "<<" | ">>" | ">>>" | "<" | "<=" | ">" | ">=" | "===" | "!==";
2660
+ export type IrStrCmpOp = "<" | "<=" | ">" | ">=";
2661
+ export type IrExpr = {
2662
+ kind: "numLit";
2663
+ value: number;
2664
+ type: IrType;
2665
+ loc: SrcLoc;
2666
+ } | {
2667
+ kind: "strLit";
2668
+ value: string;
2669
+ type: IrType;
2670
+ loc: SrcLoc;
2671
+ } | {
2672
+ kind: "boolLit";
2673
+ value: boolean;
2674
+ type: IrType;
2675
+ loc: SrcLoc;
2676
+ }
2677
+ /** An `undefined` or `null` literal; `type` is the matching unit kind.
2678
+ * Valid ONLY as the immediate value of a `unionWrap` (the frontend's slot
2679
+ * coercion wraps it with the unit arm's tag) — unit types have no
2680
+ * standalone runtime value, so a bare unitLit anywhere else is a
2681
+ * validator error and an emitter bug. */
2682
+ | {
2683
+ kind: "unitLit";
2684
+ unit: "undefined" | "null";
2685
+ type: IrType;
2686
+ loc: SrcLoc;
2687
+ } | {
2688
+ kind: "varRef";
2689
+ localId: string;
2690
+ type: IrType;
2691
+ loc: SrcLoc;
2692
+ }
2693
+ /** Numeric operands; comparisons yield bool. `===`/`!==` additionally
2694
+ * accept two same-typed arrays: reference identity (pointer compare),
2695
+ * matching JS object equality — and two same-typed CLASS VALUES, where
2696
+ * the pointer compare IS class identity (one immortal object per
2697
+ * class). */
2698
+ | {
2699
+ kind: "bin";
2700
+ op: IrNumBinOp;
2701
+ left: IrExpr;
2702
+ right: IrExpr;
2703
+ type: IrType;
2704
+ loc: SrcLoc;
2705
+ }
2706
+ /** `~` is JS bitwise NOT: ToInt32 the operand, complement, back to f64. */
2707
+ | {
2708
+ kind: "unary";
2709
+ op: "-" | "!" | "~";
2710
+ operand: IrExpr;
2711
+ type: IrType;
2712
+ loc: SrcLoc;
2713
+ }
2714
+ /** `x++` / `x--` / `++x` / `--x` in EXPRESSION position over an f64 local
2715
+ * or module global: reads the binding, writes the binding ±1, and yields
2716
+ * the OLD value (postfix, prefix=false) or the NEW value (prefix=true) —
2717
+ * JS-exact for typed-number receivers (no ToNumber coercion can be
2718
+ * observed). Statement-position ++/-- keeps its historic `assign`
2719
+ * desugar; this node exists for value positions (`arr[i++]`, `{ index:
2720
+ * jobIndex++ }`). Type is always f64. */
2721
+ | {
2722
+ kind: "incDec";
2723
+ op: "+" | "-";
2724
+ prefix: boolean;
2725
+ localId: string;
2726
+ type: IrType;
2727
+ loc: SrcLoc;
2728
+ }
2729
+ /** `--obj.f` / `obj.f++` in EXPRESSION position over a CLASS field: one
2730
+ * receiver evaluation, read-modify-write of the field, yielding the OLD
2731
+ * (postfix) or NEW (prefix) value — countdown.js's `if (--this.limit ===
2732
+ * 0)`. f64 fields compute in place (JS-exact); fieldDyn marks a
2733
+ * CHECKED-DYNAMIC field (a JS implicit-any ctor assignment): the number
2734
+ * validates OUT of the box (dynCheck's catchable TypeError on
2735
+ * non-numbers — the documented dyn arithmetic stance, never a silent
2736
+ * ToNumber), computes, and boxes back into the slot (old box released
2737
+ * after the unlink, like fieldSet). Type is always f64. */
2738
+ | {
2739
+ kind: "fieldIncDec";
2740
+ op: "+" | "-";
2741
+ prefix: boolean;
2742
+ obj: IrExpr;
2743
+ className: string;
2744
+ field: string;
2745
+ fieldDyn: boolean;
2746
+ type: IrType;
2747
+ loc: SrcLoc;
2748
+ }
2749
+ /** `x = e` in EXPRESSION position over a local or module global: evaluates
2750
+ * `value` once, writes the binding, and yields the assigned value — JS
2751
+ * evaluation order (`while ((idx = s.indexOf("\n")) !== -1)`). The type is
2752
+ * the binding's type (the frontend coerces the RHS into it, exactly like
2753
+ * statement-position `assign`). Statement position keeps the `assign`
2754
+ * statement; this node exists for value positions. */
2755
+ | {
2756
+ kind: "assignExpr";
2757
+ localId: string;
2758
+ value: IrExpr;
2759
+ type: IrType;
2760
+ loc: SrcLoc;
2761
+ }
2762
+ /** JS ToBoolean: f64 is false iff 0, -0, or NaN; string is false iff empty.
2763
+ * Operand is f64|string (bool needs no conversion) or a UNION — the ARM
2764
+ * value's ToBoolean via a per-union interned helper (unit arms false;
2765
+ * f64/string/bool arms per-value; ref arms — arrays, records, objects,
2766
+ * functions, maps, sets, promises, ... — always true; jsval arms ask the
2767
+ * engine). Result is bool. */
2768
+ | {
2769
+ kind: "toBool";
2770
+ operand: IrExpr;
2771
+ type: IrType;
2772
+ loc: SrcLoc;
2773
+ }
2774
+ /** Distinct from `bin`: short-circuits, and has JS value semantics — the
2775
+ * result is the deciding operand itself (`a && b` ≡ `toBool(a) ? b : a`),
2776
+ * not a bool. Operands and result share one kind: f64, string, bool, or
2777
+ * one UNION type (the deciding test is the union's per-arm ToBoolean; the
2778
+ * frontend pre-coerces plain arm operands into the union, so both sides
2779
+ * arrive union-typed). */
2780
+ | {
2781
+ kind: "logical";
2782
+ op: "&&" | "||";
2783
+ left: IrExpr;
2784
+ right: IrExpr;
2785
+ type: IrType;
2786
+ loc: SrcLoc;
2787
+ } | {
2788
+ kind: "strConcat";
2789
+ left: IrExpr;
2790
+ right: IrExpr;
2791
+ type: IrType;
2792
+ loc: SrcLoc;
2793
+ } | {
2794
+ kind: "strEq";
2795
+ negated: boolean;
2796
+ left: IrExpr;
2797
+ right: IrExpr;
2798
+ type: IrType;
2799
+ loc: SrcLoc;
2800
+ } | {
2801
+ kind: "strCmp";
2802
+ op: IrStrCmpOp;
2803
+ left: IrExpr;
2804
+ right: IrExpr;
2805
+ type: IrType;
2806
+ loc: SrcLoc;
2807
+ }
2808
+ /** f64|bool → string, JS-exact (Number::toString / "true"/"false").
2809
+ * Union operands dispatch through the per-union ToString helper (arms
2810
+ * fenced to unit/string/f64/bool by the frontend); a CAUGHT operand is
2811
+ * `String(e)` over the exception snapshot (scr_caught_to_string). */
2812
+ | {
2813
+ kind: "toString";
2814
+ operand: IrExpr;
2815
+ type: IrType;
2816
+ loc: SrcLoc;
2817
+ }
2818
+ /** Lazily-branched conditional: exactly one arm evaluates. */
2819
+ | {
2820
+ kind: "ternary";
2821
+ cond: IrExpr;
2822
+ then: IrExpr;
2823
+ else_: IrExpr;
2824
+ type: IrType;
2825
+ loc: SrcLoc;
2826
+ }
2827
+ /** Nullish coalescing `a ?? b` — `logical`'s lazily-branched shape with
2828
+ * the left's runtime TAG against its unit arms as the test instead of
2829
+ * ToBoolean (JS-exact: ONLY null/undefined take the right side — 0, "",
2830
+ * and false do not). `left` is a unit-armed union; `right` evaluates
2831
+ * lazily, only when the tag IS a unit arm, and has the node's type.
2832
+ * Exactly two result shapes exist (frontend-enforced, validated):
2833
+ * pass-through — `type` equals `left.type` and the non-unit left value is
2834
+ * the result box itself — and narrowed — the union has ONE non-unit arm,
2835
+ * `type` equals it, and the payload is extracted unionNarrow-style (+1
2836
+ * for ref kinds) under the checker's proof that the tag matches. Unions
2837
+ * with several non-unit arms narrowing to a sub-union are fenced. */
2838
+ | {
2839
+ kind: "nullish";
2840
+ left: IrExpr;
2841
+ right: IrExpr;
2842
+ type: IrType;
2843
+ loc: SrcLoc;
2844
+ }
2845
+ /** `u || d` where u is a union and the checker types the RESULT as u's
2846
+ * single non-unit arm (`value || null`-style picks resolved to a plain
2847
+ * default: `marker() || "default"`): evaluate u exactly ONCE, ToBoolean
2848
+ * of the ARM value (the per-union truthy helper — unit arms falsy,
2849
+ * ""/0/NaN/false falsy, object arms truthy), extract the arm when
2850
+ * truthy (+1 for ref kinds — the only truthy values live in that arm),
2851
+ * evaluate d lazily otherwise. JS value semantics exactly; `nullish`'s
2852
+ * sibling with truthiness in place of the unit-tag test. */
2853
+ | {
2854
+ kind: "orDefault";
2855
+ left: IrExpr;
2856
+ right: IrExpr;
2857
+ type: IrType;
2858
+ loc: SrcLoc;
2859
+ }
2860
+ /** Optional chaining `a?.b` / `a?.m(...)` / `f?.()` / `a?.[i]` — the
2861
+ * `nullish` test inverted: `receiver` is a unit-armed union with exactly
2862
+ * ONE non-unit arm, evaluated exactly once; when its runtime tag is a
2863
+ * unit arm the result is the interned undefined arm of `type` (JS-exact:
2864
+ * a null receiver still yields undefined) and `body` never evaluates —
2865
+ * argument side effects included. Otherwise the narrowed receiver binds
2866
+ * to `id` (read via chainRecv inside `body`, +1 per read for ref kinds)
2867
+ * and `body` produces the result: `type` when non-void (an
2868
+ * undefined-armed union; the frontend pre-wraps the member value into
2869
+ * it), or nothing (`type` void — the `cb?.()` statement form, where the
2870
+ * checker's `void | undefined` maps to void). */
2871
+ | {
2872
+ kind: "optChain";
2873
+ id: string;
2874
+ receiver: IrExpr;
2875
+ body: IrExpr;
2876
+ type: IrType;
2877
+ loc: SrcLoc;
2878
+ }
2879
+ /** The narrowed receiver inside an enclosing optChain's `body`, by the
2880
+ * chain's `id` — typed as the union's single non-unit arm; each read is
2881
+ * +1 for ref kinds (a borrowed bind temp backs it). Valid nowhere else
2882
+ * (validated against the active-chain stack). */
2883
+ | {
2884
+ kind: "chainRecv";
2885
+ id: string;
2886
+ type: IrType;
2887
+ loc: SrcLoc;
2888
+ }
2889
+ /** String method/property with UTF-16 (JS-exact) index semantics. Optional
2890
+ * arguments are OMITTED from `args` (never encoded as non-finite literals —
2891
+ * the IR must stay JSON-safe); backends fill the defaults: indexOf position
2892
+ * 0, slice start 0, slice end +Infinity. */
2893
+ | {
2894
+ kind: "strIntrinsic";
2895
+ method: IrStrIntrinsicMethod;
2896
+ receiver: IrExpr;
2897
+ args: IrExpr[];
2898
+ type: IrType;
2899
+ loc: SrcLoc;
2900
+ }
2901
+ /** A regex literal `/ab+c/gi`. `pattern` is the text between the slashes
2902
+ * exactly as written (escapes UNprocessed — the regex engine parses them),
2903
+ * `flags` the trailing flags in source order (alphabet fenced to gimsuy by
2904
+ * the frontend). Backends intern ONE immortal static per (pattern, flags)
2905
+ * pair — like string literals, so repeated evaluation is free and
2906
+ * `re === re` would hold — and compile the pattern lazily at first use
2907
+ * (a pattern the engine rejects aborts with a clear message; Node throws
2908
+ * SyntaxError at parse time — documented divergence). Result is +1 (a
2909
+ * no-op retain on the immortal). */
2910
+ | {
2911
+ kind: "regexLit";
2912
+ pattern: string;
2913
+ flags: string;
2914
+ type: IrType;
2915
+ loc: SrcLoc;
2916
+ }
2917
+ /** The strings object of a tagged template `tag\`a${x}b\`` — the COOKED
2918
+ * span texts. `key` is a per-SITE identity (the spec canonicalizes the
2919
+ * template object per template-literal occurrence, so two sites with
2920
+ * identical text are DISTINCT objects while one site evaluated twice is
2921
+ * the SAME object — the memoizing-tag idiom): backends intern ONE
2922
+ * immortal static string array per key, like regex literals. `type` is
2923
+ * always string[]. Result is +1 (a no-op retain on the immortal).
2924
+ * Divergences live at the frontend: the array is not frozen (a tag
2925
+ * mutating its readonly parameter would diverge — tsc rejects the
2926
+ * spelling) and `.raw` does not exist on it (reads fence by name;
2927
+ * String.raw itself lowers separately, splicing raw text directly). */
2928
+ | {
2929
+ kind: "templateStrings";
2930
+ key: string;
2931
+ cooked: string[];
2932
+ type: IrType;
2933
+ loc: SrcLoc;
2934
+ }
2935
+ /** A regex operation (see IrRegexIntrinsicMethod for the surface and the
2936
+ * receiver/arg conventions). The receiver and args are BORROWED;
2937
+ * string/array results are owned (+1). `replaceAll` and `split` MAY THROW
2938
+ * catchable TypeErrors (backends seed their may-throw analyses on them);
2939
+ * `test` on a g/y-flagged regex aborts at runtime (the frontend rejects
2940
+ * the literal-receiver cases it can see at compile time). */
2941
+ | {
2942
+ kind: "regexIntrinsic";
2943
+ method: IrRegexIntrinsicMethod;
2944
+ receiver: IrExpr;
2945
+ args: IrExpr[];
2946
+ type: IrType;
2947
+ loc: SrcLoc;
2948
+ }
2949
+ /** Array literal `[a, b, c]`, spreads included (`[...xs, b]`). `type` is
2950
+ * the array type; every element's type is `type.elem` EXCEPT positions
2951
+ * listed in `spreads`, whose expressions are same-typed ARRAYS copied
2952
+ * element-by-element at construction (JS-exact: a fresh array, source
2953
+ * untouched). Allocates; the result is owned (+1); ownership of
2954
+ * refcounted plain elements MOVES into the array, spread sources are
2955
+ * BORROWED (their elements copy in retained). */
2956
+ | {
2957
+ kind: "arrayLit";
2958
+ elems: IrExpr[];
2959
+ spreads?: number[];
2960
+ type: IrType;
2961
+ loc: SrcLoc;
2962
+ }
2963
+ /** Mapper-less `Array.from({ length: n })` — a length-n array of ABSENT
2964
+ * slots: unions carrying an undefined arm hold the interned undefined
2965
+ * instance (reads are JS-exact), every other refcounted element kind
2966
+ * holds NULL — a slot that MUST be assigned before it is read (the
2967
+ * pMap/allSettled fill-by-index pattern; reads of unassigned slots trap
2968
+ * where Node yields undefined — SEMANTICS.md 46). Scalar elements have
2969
+ * no absent value and are fenced by the frontend. The bound is ToLength
2970
+ * via the `i <= n - 1` loop form (fractions truncate; negative/NaN give
2971
+ * an empty array). Allocates; the result is owned (+1). */
2972
+ | {
2973
+ kind: "arrayNewLen";
2974
+ length: IrExpr;
2975
+ type: IrType;
2976
+ loc: SrcLoc;
2977
+ }
2978
+ /** Element read `a[i]`. Index is f64; a non-integer or out-of-bounds index
2979
+ * traps at runtime (JS returns undefined — documented divergence). For
2980
+ * refcounted elements the result is a fresh owned (+1) reference. */
2981
+ | {
2982
+ kind: "arrayGet";
2983
+ arr: IrExpr;
2984
+ index: IrExpr;
2985
+ type: IrType;
2986
+ loc: SrcLoc;
2987
+ }
2988
+ /** Array method/property on an array receiver: `length` (f64), `push`
2989
+ * (VARIADIC like JS — zero or more elem-typed args; every argument
2990
+ * evaluates before any appends, then each appends in order; returns the
2991
+ * new length as f64, the unchanged length for the zero-argument call —
2992
+ * ownership of refcounted args MOVES into the array), `pushSpread` (`a.push(...src)`:
2993
+ * one arg of the RECEIVER's own array type, BORROWED — its elements
2994
+ * append in order, count snapshotted first so `a.push(...a)` duplicates
2995
+ * exactly like JS; returns the new length), `pop` (returns elem — traps on an
2996
+ * empty array; ownership moves OUT to the caller), `indexOf` (one
2997
+ * elem-typed arg, BORROWED; strict equality — NaN never matches; → f64),
2998
+ * `includes` (one elem-typed arg, borrowed; SameValueZero — NaN DOES
2999
+ * match; → bool), `join` (one string arg, borrowed; f64/bool/string
3000
+ * elements only — validated; → owned string), `shift` (zero args; JS
3001
+ * shift exactly — undefined on an empty array, else the first element
3002
+ * out with the tail sliding down; the result type is the interned
3003
+ * `elem | undefined` union — union ELEMENTS are frontend-fenced, so the
3004
+ * arms never collide; ref ownership moves out into the box), and
3005
+ * `splice` (the REMOVAL forms only — one or two f64 args, Node's
3006
+ * relative/clamped start and clamped count, an omitted count removes to
3007
+ * the end [backends fill +Infinity, the slice convention]; the result is
3008
+ * a fresh +1 array of the removed elements IN ORDER, their ownership
3009
+ * MOVED from the receiver; insertion forms are frontend-fenced). */
3010
+ | {
3011
+ kind: "arrIntrinsic";
3012
+ method: IrArrIntrinsicMethod;
3013
+ receiver: IrExpr;
3014
+ args: IrExpr[];
3015
+ type: IrType;
3016
+ loc: SrcLoc;
3017
+ }
3018
+ /** Typed-array / Buffer construction — `new Uint8Array(x)`,
3019
+ * `Buffer.from(u8 | number[])`, `Buffer.alloc(n)`. `type` is the bytes
3020
+ * type; the SOURCE's static type picks the form:
3021
+ * - null — `new Uint8Array()`: a fresh zero-length buffer. Never throws.
3022
+ * - f64 — a zero-filled buffer of that length (ToIndex: NaN → 0,
3023
+ * truncate; a negative/huge result THROWS Node's "Invalid typed array
3024
+ * length" RangeError catchably — backends' may-throw analyses seed on
3025
+ * bytesNew with a non-bytes, non-array source).
3026
+ * - bytes (same elem — frontend-fenced) — an independent COPY. Never
3027
+ * throws.
3028
+ * - array of f64 — a per-element-coerced copy (ToUint8/ToUint32/float).
3029
+ * Never throws.
3030
+ * The source is BORROWED; the result is owned (+1). */
3031
+ | {
3032
+ kind: "bytesNew";
3033
+ source: IrExpr | null;
3034
+ type: IrType;
3035
+ loc: SrcLoc;
3036
+ }
3037
+ /** Typed-array/Buffer method or property on a bytes receiver — see
3038
+ * IrBytesIntrinsicMethod for the surface and conventions. Methods in
3039
+ * MAY_THROW_BYTES_METHODS raise catchable RangeErrors (may-throw
3040
+ * seeds); `get` traps on invalid indices instead (the array runtime's
3041
+ * discipline — never catchable). */
3042
+ | {
3043
+ kind: "bytesIntrinsic";
3044
+ method: IrBytesIntrinsicMethod;
3045
+ receiver: IrExpr;
3046
+ args: IrExpr[];
3047
+ type: IrType;
3048
+ loc: SrcLoc;
3049
+ }
3050
+ /** `new Map<K, V>()` — allocate an empty map. `type` is the map type
3051
+ * (key/value fences already enforced by the frontend); the result is
3052
+ * owned (+1). `seed` carries the entries of the SUPPORTED seeded form —
3053
+ * `new Map([[k, v], ...])`, an array literal of pair literals at the
3054
+ * construction site — lowered pairwise (each key K-typed, each value
3055
+ * V-typed, source order; a repeated key overwrites like set()). The
3056
+ * entries array itself never exists at runtime: backends construct the
3057
+ * empty map and set() each pair. Tuple-array VALUE seeds desugar in the
3058
+ * frontend to a construct-and-set loop (lowerMapSeedArrayNew) and never
3059
+ * reach this node; other argument shapes (iterables, another Map) stay
3060
+ * frontend-fenced. */
3061
+ | {
3062
+ kind: "mapNew";
3063
+ seed?: {
3064
+ key: IrExpr;
3065
+ value: IrExpr;
3066
+ }[];
3067
+ type: IrType;
3068
+ loc: SrcLoc;
3069
+ }
3070
+ /** Map method/property on a map receiver (`type` of the receiver is the
3071
+ * map; K/V below are its key/value types): `get` (one K arg, borrowed →
3072
+ * the interned `V | undefined` union, owned +1 — the undefined arm is the
3073
+ * miss; because `undefined` sorts LAST in canonical arm order, a union V
3074
+ * keeps its tags and the stored box IS the result), `set` (K borrowed,
3075
+ * V moves in; replacing releases the old value; → void — the ambient
3076
+ * declares void, not the JS `this`, so chaining is a type error), `has`
3077
+ * (K borrowed → bool, SameValueZero), `delete` (K borrowed → bool;
3078
+ * releases the entry), `size` (→ f64 live count), `clear` (→ void), and
3079
+ * the desugar-internal iteration primitives: `iterCount` (→ f64, dense
3080
+ * entries INCLUDING tombstones — re-read each pass so callback appends
3081
+ * are visited), `iterLive` (f64 index → bool), `iterKey` (f64 index → K,
3082
+ * +1 for strings), `iterValue` (f64 index → V, +1 for ref kinds),
3083
+ * `iterEnter`/`iterExit` (→ void, bracket a forEach loop: no compaction
3084
+ * while the depth is nonzero). The receiver is borrowed. */
3085
+ | {
3086
+ kind: "mapIntrinsic";
3087
+ method: IrMapIntrinsicMethod;
3088
+ receiver: IrExpr;
3089
+ args: IrExpr[];
3090
+ type: IrType;
3091
+ loc: SrcLoc;
3092
+ }
3093
+ /** `new Set<T>()` — allocate an empty set. `type` is the set type (the
3094
+ * element fence already enforced by the frontend); the result is owned
3095
+ * (+1). `seed` carries the SUPPORTED seeded form — `new Set(values)`
3096
+ * where values is any T[]-typed expression (literal or variable; T
3097
+ * already a legal element type) — one borrowed array whose elements
3098
+ * add() in order (duplicates collapse, first insertion position wins,
3099
+ * SameValueZero — exactly JS). Non-array seeds (another Set, general
3100
+ * iterables) stay frontend-fenced. */
3101
+ | {
3102
+ kind: "setNew";
3103
+ seed?: IrExpr;
3104
+ type: IrType;
3105
+ loc: SrcLoc;
3106
+ }
3107
+ /** Set method/property on a set receiver (`type` of the receiver is the
3108
+ * set; T below is its element type): `add` (one T arg, borrowed — the
3109
+ * runtime retains stored strings; → void, the JS `this` result is
3110
+ * frontend-fenced like Map set's chaining), `has`/`delete` (T borrowed →
3111
+ * bool, SameValueZero), `size` (→ f64 live count), `clear` (→ void), and
3112
+ * the desugar-internal iteration primitives with mapIntrinsic's exact
3113
+ * contract — `iterKey` reads the ELEMENT (f64 index → T, +1 for
3114
+ * strings); there is no iterValue. The receiver is borrowed. */
3115
+ | {
3116
+ kind: "setIntrinsic";
3117
+ method: IrSetIntrinsicMethod;
3118
+ receiver: IrExpr;
3119
+ args: IrExpr[];
3120
+ type: IrType;
3121
+ loc: SrcLoc;
3122
+ }
3123
+ /** Call of a user function declared in this module, by name. */
3124
+ | {
3125
+ kind: "call";
3126
+ callee: string;
3127
+ args: IrExpr[];
3128
+ type: IrType;
3129
+ loc: SrcLoc;
3130
+ }
3131
+ /** Closure creation: a function value over `fnName` (a module function),
3132
+ * capturing the listed boxed locals of the CREATING function (localIds,
3133
+ * in the callee's captures[] order). The result is owned (+1); the closure
3134
+ * itself retains each captured box. A reference to a top-level declared
3135
+ * function lowers to a zero-capture closure — backends must intern that
3136
+ * case so `f === f` is true (JS function identity). */
3137
+ | {
3138
+ kind: "closure";
3139
+ fnName: string;
3140
+ captures: string[];
3141
+ type: IrType;
3142
+ loc: SrcLoc;
3143
+ }
3144
+ /** Indirect call of a func-typed value. Args follow `call`'s convention
3145
+ * (callee owns its params, callers pass +1). The callee expression is an
3146
+ * ordinary owned temp, released at statement end. */
3147
+ | {
3148
+ kind: "callValue";
3149
+ callee: IrExpr;
3150
+ args: IrExpr[];
3151
+ type: IrType;
3152
+ loc: SrcLoc;
3153
+ }
3154
+ /** The currently-executing closure, as a value (+1). Valid only inside a
3155
+ * lifted function. Exists so a named nested function can recurse on itself
3156
+ * WITHOUT capturing its own binding — a box holding its own closure would
3157
+ * be a reference cycle, which naive RC can never free. */
3158
+ | {
3159
+ kind: "selfRef";
3160
+ type: IrType;
3161
+ loc: SrcLoc;
3162
+ }
3163
+ /** `yield e` — only inside generator functions (validated). Stores the
3164
+ * operand in the generator's out-slot (moved in, typed `yieldT`; null =
3165
+ * `yield;`, the undefined arm — the frontend guarantees yieldT admits
3166
+ * it) and switches back to the resumer; the expression's value is the
3167
+ * NEXT `.next(v)` argument (typed `nextT`, +1 for refcounted kinds).
3168
+ * MAY-THROW SEED: a consumer `.throw(e)` surfaces here as the pending
3169
+ * exception (catchable by the body's own try/catch), and `.return(v)`
3170
+ * as the GENRET sentinel — pending like an exception, it unwinds
3171
+ * through finally blocks but must NOT be taken by catch handlers
3172
+ * (backends emit a sentinel re-unwind prologue at catch entry inside
3173
+ * generator bodies; scr_exc_genret_pending answers it). */
3174
+ | {
3175
+ kind: "yieldExpr";
3176
+ value: IrExpr | null;
3177
+ type: IrType;
3178
+ loc: SrcLoc;
3179
+ }
3180
+ /** One consumer resume of a generator: `g.next(arg)`, `g.return(arg)`,
3181
+ * `g.throw(arg)`, and the for-of/yield* desugars. `gen` is a borrowed
3182
+ * generator-typed temp. `arg` is the sent value (moves in): next's
3183
+ * TNext (null = valueless resume — only when nextT is the undefined
3184
+ * unit or dyn), return's TReturn (null = `.return()`, the undefined
3185
+ * done-value), throw's payload (any throwable type — the throw
3186
+ * statement's operand contract). Result is the interned IteratorResult
3187
+ * record `{ done: bool, value: V }` (+1) where V is the canonical union
3188
+ * of yieldT, retT (when it carries a value), and undefined — collapsed
3189
+ * when one member survives. Semantics per mode on an UNSTARTED /
3190
+ * SUSPENDED / DONE generator: next runs the body to its next
3191
+ * suspension or completion / return completes without running the body
3192
+ * unless suspended (then the GENRET unwind runs finallys; a finally
3193
+ * yield answers done:false and parks the return value) / throw on a
3194
+ * non-suspended generator marks it done and re-throws at the call site.
3195
+ * MAY-THROW SEED: a body exception (or the injected throw) propagates
3196
+ * into the caller synchronously. */
3197
+ | {
3198
+ kind: "genResume";
3199
+ mode: "next" | "return" | "throw";
3200
+ gen: IrExpr;
3201
+ arg: IrExpr | null;
3202
+ type: IrType;
3203
+ loc: SrcLoc;
3204
+ }
3205
+ /** Await a promise: parks the current fiber until it settles; a rejected
3206
+ * promise re-throws into the awaiter (may-throw seed). Result is the
3207
+ * promise's inner value (+1 for refcounted kinds). Only inside async fns. */
3208
+ | {
3209
+ kind: "awaitExpr";
3210
+ value: IrExpr;
3211
+ type: IrType;
3212
+ loc: SrcLoc;
3213
+ }
3214
+ /** Await of a promise-or-absent union (`Promise<T> | undefined`, the
3215
+ * mapped `Promise<T> | void`): `value` is a union whose arm `promiseTag`
3216
+ * is a promise and whose other arms are all units. The promise arm awaits
3217
+ * like awaitExpr (parks, re-throws rejections — may-throw seed); a unit
3218
+ * arm takes exactly ONE microtask hop (JS: await of a non-thenable) and
3219
+ * yields itself. `type` is void when the promise's inner is void and the
3220
+ * only unit arm is undefined; otherwise the interned union of the inner
3221
+ * type and the unit arms (+1). Only inside async fns. */
3222
+ | {
3223
+ kind: "awaitUnionExpr";
3224
+ value: IrExpr;
3225
+ promiseTag: number;
3226
+ type: IrType;
3227
+ loc: SrcLoc;
3228
+ }
3229
+ /** `new Promise<T>((resolve) => ...)`: creates a pending promise and runs
3230
+ * the executor synchronously with a resolve closure; an executor throw
3231
+ * rejects the promise (JS-exact). Result +1. */
3232
+ | {
3233
+ kind: "newPromise";
3234
+ executor: IrExpr;
3235
+ type: IrType;
3236
+ loc: SrcLoc;
3237
+ }
3238
+ /** `Promise.withResolvers<T>()`: a pending promise plus its runtime
3239
+ * resolve/reject closures (the newPromise pieces without an executor),
3240
+ * assembled into the record `{ promise, resolve, reject }` — `type` is
3241
+ * that record; the shape's promise field carries T, resolve is
3242
+ * (T) => void (() => void for void T), reject is (%Error) => void.
3243
+ * Result +1; never throws. */
3244
+ | {
3245
+ kind: "promiseWithResolvers";
3246
+ type: IrType;
3247
+ loc: SrcLoc;
3248
+ }
3249
+ /** `new C(args)`: allocate (fields zeroed), then call `%C.constructor`
3250
+ * with the new object as arg 0 (retained — the ctor owns and releases its
3251
+ * `this` param like any callee). Result is owned (+1). */
3252
+ | {
3253
+ kind: "new";
3254
+ className: string;
3255
+ args: IrExpr[];
3256
+ type: IrType;
3257
+ loc: SrcLoc;
3258
+ }
3259
+ /** The class itself as a value: a pointer to `className`'s immortal
3260
+ * class object (type `classval:className`, +1 — a no-op retain on the
3261
+ * immortal, kept for the uniform owned-temp discipline, the regexLit
3262
+ * pattern). The frontend notes an edge to `%className.constructor` at
3263
+ * every classRef, so a value's construct thunk always has a constructor
3264
+ * to call; backends emit class objects (and thunks) for exactly the
3265
+ * classes some classRef in the module names. */
3266
+ | {
3267
+ kind: "classRef";
3268
+ className: string;
3269
+ type: IrType;
3270
+ loc: SrcLoc;
3271
+ }
3272
+ /** `new X(args)` through a class VALUE: call the class object's
3273
+ * construct thunk. `callee` is classval-typed; args are completed
3274
+ * against `%<callee.className>.constructor`'s ABI — sound because every
3275
+ * legal classval flow preserves the constructor ABI (the upcast rule) —
3276
+ * and follow `call`'s ownership (callee owns, +1 in). `type` is
3277
+ * `object:<callee.className>` (a runtime descendant rides the ordinary
3278
+ * upcast story); result owned (+1). May throw whenever constructors may
3279
+ * (backends treat it like an indirect call). */
3280
+ | {
3281
+ kind: "newValue";
3282
+ callee: IrExpr;
3283
+ args: IrExpr[];
3284
+ type: IrType;
3285
+ loc: SrcLoc;
3286
+ }
3287
+ /** `x instanceof X` with a DYNAMIC right-hand side (a classval-typed
3288
+ * value): the preorder-interval check with the interval loaded from the
3289
+ * class object — `vt(x)->pre` within `[X->pre, X->post]`. The frontend
3290
+ * emits this only when the operand's static class and the target
3291
+ * classval's class are both hierarchy members (the operand carries a
3292
+ * vt; a standalone target has exactly one possible runtime value and
3293
+ * folds statically instead). Operands borrowed; result bool. */
3294
+ | {
3295
+ kind: "instanceOfValue";
3296
+ value: IrExpr;
3297
+ classValue: IrExpr;
3298
+ type: IrType;
3299
+ loc: SrcLoc;
3300
+ }
3301
+ /** Implicit widening of a derived-class value into a base-class slot
3302
+ * (`type` is the base; the operand's class is a strict descendant).
3303
+ * Prefix layout makes this a pointer reinterpret: SAME object, no RC
3304
+ * traffic — ownership of the operand transfers to the result. Also
3305
+ * widens CLASS VALUES (`classval:D` into `classval:C`): the identical
3306
+ * pointer, type-only — legal exactly when D strictly descends from C
3307
+ * AND the two constructors' completed ABIs are equal (param-wise
3308
+ * typeEquals; validator-enforced), the invariant `newValue` completion
3309
+ * rests on. */
3310
+ | {
3311
+ kind: "upcast";
3312
+ value: IrExpr;
3313
+ type: IrType;
3314
+ loc: SrcLoc;
3315
+ }
3316
+ /** Implicit widening of a promise value into a VOID-promise slot (an
3317
+ * inferred Promise<never>/Promise<void> return whose body built a
3318
+ * concrete-inner promise — `return Promise.reject(value)` typed
3319
+ * promise<dyn>). One C representation (ScrPromise*), so this is a
3320
+ * type-only reinterpret: awaiting through the slot ignores the
3321
+ * fulfillment payload (scr_await_void) and rejections flow untyped.
3322
+ * Ownership of the operand transfers to the result, like upcast. */
3323
+ | {
3324
+ kind: "promiseVoidWiden";
3325
+ value: IrExpr;
3326
+ type: IrType;
3327
+ loc: SrcLoc;
3328
+ }
3329
+ /** Checker-trusted narrowing of a base-class value to a subclass (`type`
3330
+ * is the subclass). The frontend emits this only where tsc's control-flow
3331
+ * narrowing has already proven the dynamic class (an `instanceof` guard)
3332
+ * — the same trust-the-checker contract as unionNarrow: no runtime check,
3333
+ * a pointer reinterpret with ownership transferring like upcast. */
3334
+ | {
3335
+ kind: "downcast";
3336
+ value: IrExpr;
3337
+ type: IrType;
3338
+ loc: SrcLoc;
3339
+ }
3340
+ /** `x instanceof C` where x's static class and C are both in extends-
3341
+ * hierarchies: an O(1) preorder-interval check against the vtable the
3342
+ * value carries (`C.pre <= vt(x)->pre <= C.post`). Statically-decided
3343
+ * cases (standalone classes, and always-true/unrelated combinations)
3344
+ * never reach the IR — the frontend folds them. The operand is borrowed;
3345
+ * the result is a plain bool. */
3346
+ | {
3347
+ kind: "instanceOf";
3348
+ value: IrExpr;
3349
+ className: string;
3350
+ type: IrType;
3351
+ loc: SrcLoc;
3352
+ }
3353
+ /** Method call that must dispatch on the receiver's DYNAMIC class:
3354
+ * `className` is the receiver's static class, `args[0]` the receiver
3355
+ * (typed exactly `object:className`), and some strict subclass overrides
3356
+ * `method` — the backend calls through the vtable slot of the method's
3357
+ * root-most declaring class. Monomorphic calls (no override reachable
3358
+ * from the static class) stay ordinary `call` nodes — whole-program
3359
+ * devirtualization is the frontend's job. Ownership follows `call`:
3360
+ * callees own their params, callers pass +1. */
3361
+ | {
3362
+ kind: "virtualCall";
3363
+ className: string;
3364
+ method: string;
3365
+ args: IrExpr[];
3366
+ type: IrType;
3367
+ loc: SrcLoc;
3368
+ }
3369
+ /** Field read `obj.f`. Refcounted fields come out retained (+1). */
3370
+ | {
3371
+ kind: "fieldGet";
3372
+ obj: IrExpr;
3373
+ className: string;
3374
+ field: string;
3375
+ type: IrType;
3376
+ loc: SrcLoc;
3377
+ }
3378
+ /** Record literal `{ a: 1, b: "x" }`. `type` is the record type; `fields`
3379
+ * are in SOURCE order (JS evaluates property values in source order) and
3380
+ * cover the shape's fields exactly once each (validated — a source literal
3381
+ * omitting OPTIONAL fields reaches the IR already completed: the frontend
3382
+ * appends the wrapped undefined arm for each omitted one). Allocates
3383
+ * (fields zeroed) and returns owned (+1); ownership of refcounted field
3384
+ * values MOVES into the record. */
3385
+ /** Entries flagged `overflow` are UNDECLARED keys of an index-signature
3386
+ * shape (their values have the shape's indexValue type — dyn included);
3387
+ * they insert into the overflow map in list order, interleaved with the
3388
+ * declared writes (one list keeps JS source-order evaluation). */
3389
+ /** Entries flagged `drop` are fields the shape MAPPING dropped (the
3390
+ * PromiseSettledResult honest subset — SEMANTICS.md 46): the value
3391
+ * expression still evaluates in its source-order slot (the awaited
3392
+ * mapper in `{ status: "fulfilled", value: await fn(...) }` must run and
3393
+ * may throw), but nothing is stored — the emitter releases the result
3394
+ * with the statement frame. Any value type is legal here, void included
3395
+ * (an awaited Promise<void>). */
3396
+ | {
3397
+ kind: "recordLit";
3398
+ fields: {
3399
+ name: string;
3400
+ value: IrExpr;
3401
+ overflow?: true;
3402
+ drop?: true;
3403
+ }[];
3404
+ type: IrType;
3405
+ loc: SrcLoc;
3406
+ }
3407
+ /** Record field read `r.f` — mirrors `fieldGet`: refcounted fields come
3408
+ * out retained (+1). */
3409
+ | {
3410
+ kind: "recordGet";
3411
+ obj: IrExpr;
3412
+ shapeId: string;
3413
+ field: string;
3414
+ type: IrType;
3415
+ loc: SrcLoc;
3416
+ }
3417
+ /** Dynamic-keyed record read `r[k]` (string key, evaluated at runtime).
3418
+ * Declared fields are tried FIRST (an emitted string-switch — field
3419
+ * access exactness is preserved: a declared name always answers from the
3420
+ * struct slot), then the overflow map on index-signature shapes. `type`
3421
+ * is the CHECKER's type for the access: the index signature's value type
3422
+ * (dyn for `unknown`; with noUncheckedIndexedAccess, its
3423
+ * `V | undefined` union). A MISSING key produces: the undefined DOM
3424
+ * singleton when `type` is dyn; the undefined arm when `type` is an
3425
+ * undefined-armed union; otherwise a TRAP — the checker claimed V and no
3426
+ * undefined is representable (the array OOB policy; on declared-only
3427
+ * shapes tsc's keyof check makes the trap unreachable without an `as`
3428
+ * smuggle). Declared-field values surface as `type`: V-typed fields read
3429
+ * directly, dyn results build a DOM COPY of the field value (the dynFrom
3430
+ * conversion — deep for composites, documented), union results wrap.
3431
+ * The key and object are borrowed; refcounted results are owned (+1).
3432
+ * `overflowOnly` (set when the key is a LITERAL that names no declared
3433
+ * field): the read touches only the overflow map — declared fields need
3434
+ * not surface as `type`, and the emitted helper skips the string-switch. */
3435
+ | {
3436
+ kind: "recordKeyGet";
3437
+ obj: IrExpr;
3438
+ shapeId: string;
3439
+ key: IrExpr;
3440
+ overflowOnly?: true;
3441
+ type: IrType;
3442
+ loc: SrcLoc;
3443
+ }
3444
+ /** Static value → dyn DOM conversion (`type` is always dyn): the operand
3445
+ * (a JSON-safe type — f64/string/bool/record/array/union, validated)
3446
+ * converts to a fresh DOM tree, DEEP-COPYING composites (the jsMarshal
3447
+ * aliasing stance; a dyn value can never alias static storage). An
3448
+ * undefined-armed union's undefined arm becomes the undefined DOM
3449
+ * singleton. A FUNCTION operand (canBoxFuncIntoDyn — the mustCall shape:
3450
+ * a typed closure flowing into an untyped JS helper's implicit-any
3451
+ * param) BOXES instead of copying: the DOM's function kind carries the
3452
+ * retained closure, a compiled per-signature call thunk (per-argument
3453
+ * dynCheck into the declared param types, result dynFrom'd back — JS
3454
+ * arity: extras ignored, missing args are the undefined DOM value and
3455
+ * must satisfy the param's type or the thunk throws the catchable
3456
+ * TypeError), the interned signature key (dynCheck's exact-unwrap fast
3457
+ * path), and `fnName` — the best-effort static spelling for inspect
3458
+ * ([Function: name]) and Node-shaped call errors. The operand is
3459
+ * borrowed; the result is owned (+1). Never throws. */
3460
+ | {
3461
+ kind: "dynFrom";
3462
+ value: IrExpr;
3463
+ fnName?: string;
3464
+ type: IrType;
3465
+ loc: SrcLoc;
3466
+ }
3467
+ /** CALLING a dyn DOM value — `fn(a, b)` where fn is checked-dynamic (an
3468
+ * implicit-any JS binding, a dyn record member, a dynKeyGet result).
3469
+ * Arguments are ALREADY dyn-typed (typed values box through dynFrom at
3470
+ * the call's coercion — function args included); `type` is always dyn.
3471
+ * A non-function callee kind throws the catchable Node-shaped TypeError
3472
+ * "`calleeName` is not a function" BEFORE evaluating no arguments —
3473
+ * actually args evaluate first, source order, then the callee kind is
3474
+ * tested (JS evaluates callee before args, but the callee EXPRESSION
3475
+ * already evaluated; only the callability test is deferred — Node's
3476
+ * message exactly). A function callee calls through the boxed thunk:
3477
+ * per-arg validation against the boxed signature (mismatches throw the
3478
+ * path-annotated TypeError), result converted back to dyn. Callee and
3479
+ * args are borrowed; the result is owned (+1). MAY THROW. */
3480
+ | {
3481
+ kind: "dynCall";
3482
+ callee: IrExpr;
3483
+ calleeName: string;
3484
+ args: IrExpr[];
3485
+ type: IrType;
3486
+ loc: SrcLoc;
3487
+ }
3488
+ /** Prototype-method DISPATCH on a dyn receiver — `recv.m(...)` where `m`
3489
+ * is a name a DOM-representable prototype declares (Array/String/
3490
+ * Function shared names: push, slice, join, forEach, map, apply, ...),
3491
+ * so a stored-member read would silently mis-answer real methods. The
3492
+ * runtime (scr_dyn_invoke) dispatches on the receiver's KIND:
3493
+ * implemented (kind, name) pairs run JS-exact semantics; a real-but-
3494
+ * unimplemented method throws a LOUD "not supported yet" Error; a name
3495
+ * the kind's prototype lacks throws Node's catchable "<calleeName> is
3496
+ * not a function"; OBJ receivers call the own member (own properties
3497
+ * shadow prototypes in JS too); undefined/null receivers throw Node's
3498
+ * "Cannot read properties of ...". Arguments are already dyn.
3499
+ * `calleeName` is the source spelling for the error texts. Receiver and
3500
+ * args are borrowed; the result is owned (+1). MAY THROW. */
3501
+ | {
3502
+ kind: "dynInvoke";
3503
+ recv: IrExpr;
3504
+ method: string;
3505
+ calleeName: string;
3506
+ args: IrExpr[];
3507
+ type: IrType;
3508
+ loc: SrcLoc;
3509
+ }
3510
+ /** A DOM ARRAY built element-by-element (JS mixed-element literals —
3511
+ * `['pwd', []]` — and evolving `[]` declarations): each element is
3512
+ * already a dyn value; the result owns them. Never throws. */
3513
+ | {
3514
+ kind: "dynArrLit";
3515
+ elems: IrExpr[];
3516
+ type: IrType;
3517
+ loc: SrcLoc;
3518
+ }
3519
+ /** A DOM OBJECT built member-by-member. With no `fields` it is the empty
3520
+ * object (the JS stand-in for opaque container values — `new WeakMap()`
3521
+ * in harness code: the value exists for identity; every reached METHOD
3522
+ * use meets its own fence). With `fields` it is a JS object literal whose
3523
+ * keys are RUNTIME values (the computed-key idiom `{ [field]: criteria,
3524
+ * actual: 0 }` in test/common's _mustCallInner): each entry's key is a
3525
+ * string-typed expression (identifier/string keys lower to strLits;
3526
+ * computed keys evaluate their expression and pass through ToString —
3527
+ * JS's ToPropertyKey on the string side), each value is already dyn, and
3528
+ * entries evaluate key-then-value in SOURCE order (JS's object-literal
3529
+ * evaluation order; later duplicate keys win, insertion order preserved —
3530
+ * the DOM's own set semantics). Keys and values are borrowed (the member
3531
+ * retains the value in). Never throws itself. */
3532
+ | {
3533
+ kind: "dynObjLit";
3534
+ fields?: {
3535
+ key: IrExpr;
3536
+ value: IrExpr;
3537
+ }[];
3538
+ type: IrType;
3539
+ loc: SrcLoc;
3540
+ }
3541
+ /** Runtime kind test on a dyn DOM value — the narrowing tests tsc's
3542
+ * control flow understands on `unknown`: `typeof v === "string" |
3543
+ * "number" | "boolean" | "undefined"` and the unit comparisons `v ===
3544
+ * undefined` / `v === null` (`"nullish"` is the LOOSE `v == null` pair —
3545
+ * undefined or null in one test), and `v instanceof Uint8Array`
3546
+ * (`"bytes"` — the DOM's bytes kind; Node's Buffer IS a Uint8Array
3547
+ * subclass and both worlds answer true for it, SEMANTICS.md 45), plus
3548
+ * the two object-family tests: `"object"` is `typeof v === "object"`
3549
+ * exactly (true for the DOM's object, array, bytes, AND null kinds —
3550
+ * JS's oldest wart preserved), `"array"` is `Array.isArray(v)` (the
3551
+ * array kind alone), and `"truthy"` is ToBoolean over the whole DOM
3552
+ * (`if (v)` on unknown): undefined/null false, bool by value, number
3553
+ * falsy exactly for 0, -0, and NaN, string falsy exactly when empty,
3554
+ * object/array/bytes always true — JS-exact for every kind. A pure
3555
+ * kind-tag compare against the DOM node's kind (truthy also reads the
3556
+ * scalar payload); the operand is
3557
+ * borrowed, nothing allocates, never throws. Result is bool. Narrowed
3558
+ * READS afterwards bridge through `dynCheck` extraction
3559
+ * (trust-but-VERIFY: unlike unionNarrow, a read reached with a lying
3560
+ * kind throws instead of misreading the payload). `"error"` is
3561
+ * `v instanceof Error` on an unknown value: true exactly for the DOM's
3562
+ * error encoding — an object carrying the reserved "%error" key, the
3563
+ * shape caughtToDyn builds for Error payloads (SEMANTICS.md 67) — so a
3564
+ * caught Error passed through an unknown slot answers true like Node;
3565
+ * dynCheck against %Error extracts it. `"function"` is `typeof v ===
3566
+ * "function"` — true exactly for the DOM's function kind (boxed
3567
+ * closures); function values are truthy and answer FALSE to the
3568
+ * `"object"` test, JS-exact. */
3569
+ | {
3570
+ kind: "dynTest";
3571
+ test: "string" | "number" | "boolean" | "undefined" | "null" | "nullish" | "bytes" | "object" | "array" | "truthy" | "error" | "function";
3572
+ negated?: true;
3573
+ value: IrExpr;
3574
+ type: IrType;
3575
+ loc: SrcLoc;
3576
+ }
3577
+ /** Keyed read on a dyn DOM value — `pkg.name` / `pkg["k"]` / the
3578
+ * `pkg?.scripts` chain step on a JSON.parse result. `key` is
3579
+ * string-typed (a strLit for the dot form); `type` is always dyn. An
3580
+ * OBJ receiver answers the member (+1) or the undefined singleton (the
3581
+ * own-property answer — prototype members like `toString` answer
3582
+ * undefined, SEMANTICS.md); ARR answers `length` and canonical
3583
+ * in-range indices, STR answers `length` (UTF-16-exact), both
3584
+ * undefined otherwise; NUM/BOOL/BYTES answer undefined. An
3585
+ * undefined/null receiver THROWS the catchable Node-shaped TypeError
3586
+ * ("Cannot read properties of undefined (reading 'k')") — unless
3587
+ * `optional` is set (a `?.` step, or a later step of a chain whose
3588
+ * earlier `?.` guards it): then it answers the undefined singleton,
3589
+ * JS's short-circuit. Receiver and key are borrowed; the result is
3590
+ * owned (+1). */
3591
+ | {
3592
+ kind: "dynKeyGet";
3593
+ key: IrExpr;
3594
+ optional?: true;
3595
+ value: IrExpr;
3596
+ type: IrType;
3597
+ loc: SrcLoc;
3598
+ }
3599
+ /** `"k" in pkg` on a dyn DOM receiver (literal keys only): OBJ answers
3600
+ * own-member presence (a member holding the undefined value still
3601
+ * answers true — the DOM stores presence, unlike the record form's
3602
+ * SEMANTICS.md 55 stance), ARR answers true for "length" and canonical
3603
+ * in-range indices, everything else answers false (tsc admits `in`
3604
+ * only on object-typed operands, so unit receivers — where JS throws —
3605
+ * are checker-unreachable and answer false). Borrowed operand, no
3606
+ * allocation, never throws. Result is bool. */
3607
+ | {
3608
+ kind: "dynHasKey";
3609
+ key: string;
3610
+ negated?: true;
3611
+ value: IrExpr;
3612
+ type: IrType;
3613
+ loc: SrcLoc;
3614
+ }
3615
+ /** Strict equality between a dyn DOM value and a SCALAR-typed value
3616
+ * (`v !== ""`, `v === 5` — one side `unknown`, the other f64/string/
3617
+ * bool): a guarded kind test plus payload compare — true exactly when
3618
+ * the DOM holds that scalar kind AND the payloads are strictly equal
3619
+ * (C == for numbers: NaN false, ±0 equal — JS-exact; bytewise for
3620
+ * strings). `left`/`right` keep SOURCE order (evaluation order is
3621
+ * JS's); at least one side is dyn-typed — BOTH-dyn compares run the
3622
+ * runtime's whole-DOM strict equality (scr_dyn_strict_eq: scalars by
3623
+ * value, units by kind, reference kinds by node identity — JS-exact
3624
+ * within the DOM's aliasing story). Both operands are borrowed,
3625
+ * nothing allocates, never throws. Result is bool. */
3626
+ | {
3627
+ kind: "dynScalarEq";
3628
+ left: IrExpr;
3629
+ right: IrExpr;
3630
+ negated?: true;
3631
+ type: IrType;
3632
+ loc: SrcLoc;
3633
+ }
3634
+ /** Statements inside an expression: `stmts` run in order, then `result`
3635
+ * is the expression's value — the lift behind assignment-as-expression
3636
+ * forms whose statement lowering needs temps and writes (destructuring
3637
+ * assignments in value position, keyed dyn writes yielding the RHS).
3638
+ * `type` IS result's type. Restricted on purpose: stmts must be
3639
+ * straight-line (varDecl/assign/exprStmt/field-and-record writes — no
3640
+ * control flow, no jumps; the validator enforces the subset), and any
3641
+ * varDecl-introduced local is a function local like every hidden temp. */
3642
+ | {
3643
+ kind: "seqExpr";
3644
+ stmts: IrStmt[];
3645
+ result: IrExpr;
3646
+ type: IrType;
3647
+ loc: SrcLoc;
3648
+ }
3649
+ /** RequireObjectCoercible with V8's destructuring TypeError: throws
3650
+ * "Cannot destructure 'SPELLING' as it is undefined." (or "…null.") on
3651
+ * a nullish value — the property form "Cannot destructure property
3652
+ * 'FIRSTPROP' of 'SPELLING' …" when `firstProp` is set (V8 names the
3653
+ * pattern's first property) — and yields the value unchanged otherwise.
3654
+ * `spelling` is the RHS's compile-time source spelling. Value and type
3655
+ * are dyn (the DOM helper) or jsval (the island's prelude guard —
3656
+ * engine-thrown, catchable like every boundary throw). */
3657
+ | {
3658
+ kind: "dynDestrCheck";
3659
+ value: IrExpr;
3660
+ spelling: string;
3661
+ firstProp?: string;
3662
+ type: IrType;
3663
+ loc: SrcLoc;
3664
+ }
3665
+ /** GetIterator + the first `count` steps, as array destructuring sees
3666
+ * it. Over a DOM value: arrays step by index, strings by code point,
3667
+ * Buffers by byte; everything else throws V8's exact "<desc> is not
3668
+ * iterable (cannot read property Symbol(Symbol.iterator))" TypeError.
3669
+ * Over an island (jsval) value the engine runs the REAL iterator
3670
+ * protocol (user iterables included, IteratorClose per spec) behind the
3671
+ * same V8 message for non-iterables. The result is a FRESH array (DOM
3672
+ * or engine, matching the operand) of exactly `count` elements
3673
+ * (undefined-padded past the end) — the empty pattern passes count 0
3674
+ * and uses only the validation. Value is borrowed; the result is owned
3675
+ * (+1). */
3676
+ | {
3677
+ kind: "dynIterN";
3678
+ value: IrExpr;
3679
+ count: number;
3680
+ type: IrType;
3681
+ loc: SrcLoc;
3682
+ }
3683
+ /** The OVERFLOW key list of an index-signature record, in JS OWN-KEY
3684
+ * order (canonical array indices ascending first, then insertion order —
3685
+ * the runtime's scr_map_keys_js_order): a fresh string[] snapshot, the
3686
+ * iteration surface behind Object.keys/values/entries over hybrid
3687
+ * shapes. `obj` must be a record whose shape carries an indexValue; the
3688
+ * receiver is borrowed, the array is owned (+1). Declared fields are NOT
3689
+ * listed (they never live in the overflow map — the lowering prepends
3690
+ * them from the shape). Never throws. */
3691
+ | {
3692
+ kind: "recordOvfKeys";
3693
+ obj: IrExpr;
3694
+ shapeId: string;
3695
+ type: IrType;
3696
+ loc: SrcLoc;
3697
+ }
3698
+ /** Union construction: wrap an arm value into a fresh tagged box (the
3699
+ * frontend inserts these wherever a `B` flows into an `A | B` slot).
3700
+ * `tag` is the arm's index in the union's canonical arm list; `value` has
3701
+ * exactly that arm's type; `type` is the union. Allocates, returns owned
3702
+ * (+1); ownership of a refcounted payload MOVES into the union. Unions are
3703
+ * immutable once constructed. */
3704
+ | {
3705
+ kind: "unionWrap";
3706
+ unionId: string;
3707
+ tag: number;
3708
+ value: IrExpr;
3709
+ type: IrType;
3710
+ loc: SrcLoc;
3711
+ }
3712
+ /** Runtime test on a catch binding (`value` is a caught-typed varRef,
3713
+ * borrowed). The primitive tests ("string"/"number"/"boolean") compare
3714
+ * the snapshot's kind tag — exactly what `typeof e === "..."` observes;
3715
+ * "instanceof" requires `className` (a hierarchy class) and tests an OBJ
3716
+ * payload's vtable preorder against its interval (false for every other
3717
+ * payload kind). `negated` flips the result (the `!==` spelling). */
3718
+ | {
3719
+ kind: "caughtTest";
3720
+ value: IrExpr;
3721
+ test: "string" | "number" | "boolean" | "instanceof";
3722
+ className?: string;
3723
+ negated?: boolean;
3724
+ type: IrType;
3725
+ loc: SrcLoc;
3726
+ }
3727
+ /** Checker-trusted extraction of a catch binding's payload as `type` —
3728
+ * the caught analog of unionNarrow: the frontend emits this only where
3729
+ * tsc's control-flow narrowing has already proven the matching test
3730
+ * (`e instanceof C` / `typeof e === "string"`), so the read is
3731
+ * kind-UNCHECKED at runtime. `type` is f64, bool, string, or a
3732
+ * hierarchy-class object; refcounted results come out retained (+1). */
3733
+ | {
3734
+ kind: "caughtNarrow";
3735
+ value: IrExpr;
3736
+ type: IrType;
3737
+ loc: SrcLoc;
3738
+ }
3739
+ /** CHECKED extraction of a catch binding's payload as a hierarchy-class
3740
+ * instance — the caught analog of dynCheck, emitted for `e as C` casts
3741
+ * on catch bindings (the `(err as Error).message` idiom): an OBJ payload
3742
+ * inside C's preorder interval extracts (+1); every other payload THROWS
3743
+ * a catchable TypeError naming the class. Node's `as` is erasure — the
3744
+ * checked cast is the documented trust-but-verify stance for dynamic
3745
+ * values, extended to exception payloads. `type` is C's object type;
3746
+ * may-throw seeds like dynCheck. */
3747
+ | {
3748
+ kind: "caughtCheck";
3749
+ value: IrExpr;
3750
+ className: string;
3751
+ type: IrType;
3752
+ loc: SrcLoc;
3753
+ }
3754
+ /** A catch binding flowing into an `unknown` slot (`options.onError?.(e)`
3755
+ * — the caught snapshot converting to a dyn DOM value, the typed→unknown
3756
+ * deep-copy stance extended to exception payloads, SEMANTICS.md 67).
3757
+ * Runtime dispatch on the snapshot's kind: string/number/boolean payloads
3758
+ * become the exact DOM scalars; an Error-family OBJ payload becomes the
3759
+ * DOM's error encoding — an object with the reserved "%error" marker key
3760
+ * plus "name"/"message" (and "code" when stamped), so `instanceof Error`
3761
+ * (dynTest "error"), the %Error dynCheck extraction, and String() answer
3762
+ * like Node; every other payload (records, arrays, closures, unions,
3763
+ * non-Error hierarchy objects — type-erased at runtime) becomes an EMPTY
3764
+ * DOM object: truthy, typeof "object", fields unreadable — the
3765
+ * "[object Object]" approximation, documented. `value` is a caught-typed
3766
+ * varRef (borrowed); `type` is dyn; the result is a fresh tree (+1),
3767
+ * never aliasing the payload. Never throws. */
3768
+ | {
3769
+ kind: "caughtToDyn";
3770
+ value: IrExpr;
3771
+ type: IrType;
3772
+ loc: SrcLoc;
3773
+ }
3774
+ /** Union payload extraction, tag-UNCHECKED: `value` is union-typed,
3775
+ * `type` is arms[tag], and the backend reads the payload assuming the tag
3776
+ * — SOUNDNESS RESTS ON tsc's control-flow narrowing (the frontend emits
3777
+ * this only where the checker has already narrowed the expression to that
3778
+ * arm; see docs/ir.md). Refcounted payloads come out retained (+1). */
3779
+ | {
3780
+ kind: "unionNarrow";
3781
+ unionId: string;
3782
+ tag: number;
3783
+ value: IrExpr;
3784
+ type: IrType;
3785
+ loc: SrcLoc;
3786
+ }
3787
+ /** Discriminant read `r.kind` on a union receiver: every arm is a
3788
+ * record/class possessing field `field` with the SAME primitive IR type
3789
+ * (f64|string|bool — `type`). Backends switch on the runtime tag and read
3790
+ * the field from the concretely-typed payload; string results come out
3791
+ * retained (+1). Composes with existing `strEq`/`bin`/`switch` nodes for
3792
+ * the narrowing tests themselves. */
3793
+ | {
3794
+ kind: "unionDisc";
3795
+ unionId: string;
3796
+ field: string;
3797
+ value: IrExpr;
3798
+ type: IrType;
3799
+ loc: SrcLoc;
3800
+ }
3801
+ /** Keyed read `r.f` / `r[k]` on a union receiver whose arms answer
3802
+ * DIFFERENT (but joinable) types — the unionDisc generalization for
3803
+ * index-signature and optional-chain shapes (`env.PORTLESS_PORT` on
3804
+ * `ProcessEnv | Record<string, string>`, the tail read of
3805
+ * `loaded?.config.script`). `key` is a string-typed expression (a strLit
3806
+ * for dot access), evaluated ONCE before the tag switch. `type` is the
3807
+ * JOIN of the per-arm answers (each arm's declared answer is `type`
3808
+ * itself or one of its arms). Per arm, the backend answers: a record arm
3809
+ * with the key as a DECLARED field (literal keys only) reads the slot
3810
+ * and wraps into `type` when needed; a record arm with an index
3811
+ * signature goes through the per-(shape, type) keyed-read helper (the
3812
+ * recordKeyGet machinery — missing keys yield the undefined arm of
3813
+ * `type`, or trap when `type` has none, the same policy as the
3814
+ * single-record read); a UNIT arm (undefined/null — reachable only
3815
+ * through optional-chain tails, where JS answers undefined) yields the
3816
+ * interned undefined arm of `type`. The receiver and key are borrowed;
3817
+ * refcounted results are owned (+1). Never throws (a smuggled miss
3818
+ * traps in the helper). */
3819
+ | {
3820
+ kind: "unionKeyGet";
3821
+ unionId: string;
3822
+ key: IrExpr;
3823
+ value: IrExpr;
3824
+ type: IrType;
3825
+ loc: SrcLoc;
3826
+ }
3827
+ /** Union tag test: true iff `value`'s runtime tag equals `tag` (negated:
3828
+ * differs). The narrowing test for UNIT arms — the frontend lowers
3829
+ * `v === undefined` / `v !== null` on a union-typed v here (tsc's
3830
+ * control-flow narrowing then types the branches, and reads inside them
3831
+ * bridge via unionNarrow as usual). Composes like unionDisc: the result
3832
+ * is a plain bool for if/while/ternary/! to consume. The union operand is
3833
+ * an ordinary borrowed temp; no ownership changes. */
3834
+ | {
3835
+ kind: "unionIsTag";
3836
+ unionId: string;
3837
+ tag: number;
3838
+ negated: boolean;
3839
+ value: IrExpr;
3840
+ type: IrType;
3841
+ loc: SrcLoc;
3842
+ }
3843
+ /** `===`/`!==` between two values of the SAME union: JS-exact strict
3844
+ * equality of the ARM values via a per-union interned helper — different
3845
+ * tags are never equal (distinct types, and null !== undefined), unit
3846
+ * arms of equal tag are equal, f64 arms compare with C `==` (NaN !== NaN,
3847
+ * +0 === -0), string arms compare bytes, bool arms compare values, and
3848
+ * ref arms (arrays, records, objects, functions, maps, sets, ...) compare
3849
+ * POINTER IDENTITY — exactly JS object equality. A union-vs-plain-arm
3850
+ * comparison (`u === "text"`) arrives here after the frontend wraps the
3851
+ * plain side (payload identity is preserved by the wrap, so ref-arm
3852
+ * semantics stay JS-exact). Operands are borrowed; result is a plain
3853
+ * bool. `negated` is the `!==` spelling. */
3854
+ | {
3855
+ kind: "unionEq";
3856
+ unionId: string;
3857
+ negated: boolean;
3858
+ left: IrExpr;
3859
+ right: IrExpr;
3860
+ type: IrType;
3861
+ loc: SrcLoc;
3862
+ }
3863
+ /** Backend-special-cased operations. console.log: f64/string/bool args,
3864
+ * void. console.error (console.warn lowers here too — Node's warn IS
3865
+ * error): the same args and formatting, written to STDERR; stdout
3866
+ * flushes first so merged (2>&1) output keeps source order.
3867
+ * promise.race: every arg is a PROMISE (the array literal's
3868
+ * entries, lowered individually — the array never materializes), the
3869
+ * type is the checker's combined result promise; the backend emits a
3870
+ * fresh promise plus one scr_promise_race_add per entry with an
3871
+ * interned per-(entry-inner → result-inner) adapter (raceAdapterFor) —
3872
+ * same-type entries share the runtime's copy adapter, arm entries wrap
3873
+ * into the result union, sub-union entries re-tag arm-wise. First
3874
+ * settle wins; rejections copy raw and count handled on the entry.
3875
+ * promise.reject: one %Error-rooted arg (the reason — rejection
3876
+ * payloads share the thrown-Error representation), type is the
3877
+ * context-named result promise; the backend mints a fresh promise and
3878
+ * rejects it through the exception cell (scr_throw_obj +
3879
+ * scr_promise_reject_pending), so the result enters the unhandled
3880
+ * ledger until observed, exactly like a reject() call.
3881
+ * promise.resolve: zero args (Promise<void>) or one PLAIN value of the
3882
+ * result's inner type (promise arguments never reach here — the
3883
+ * frontend returns them as-is, the spec's native-promise identity;
3884
+ * thenables and promise-armed unions fence); the backend mints a fresh
3885
+ * promise and fulfills it immediately per the inner kind. */
3886
+ | {
3887
+ kind: "intrinsic";
3888
+ name: "console.log" | "console.error" | "promise.race" | "promise.all" | "promise.reject" | "promise.resolve";
3889
+ args: IrExpr[];
3890
+ type: IrType;
3891
+ loc: SrcLoc;
3892
+ }
3893
+ /** Standard-library call (`process` members, node:fs functions). `fn` is a
3894
+ * closed union; arg/result types are fixed per member (validated against
3895
+ * LIB_FN_SIGS). Property READS (`process.argv`, `process.platform`) are
3896
+ * zero-arg libCalls. Args are BORROWED by the operation (frame temps
3897
+ * release at statement end); refcounted results come back owned (+1) —
3898
+ * `process.argv` returns +1 on ONE interned array (JS identity:
3899
+ * `process.argv === process.argv` is true; mutations persist across
3900
+ * reads), everything else is fresh. fs.* members can throw (catchable
3901
+ * string payloads formatted like Node's messages) — backends must consult
3902
+ * the may-throw seed set (MAY_THROW_LIB_FNS) in their analysis and emit
3903
+ * pending checks; process.* members never throw. `process.exit` flushes
3904
+ * stdout and terminates the process without running exit handlers. */
3905
+ | {
3906
+ kind: "libCall";
3907
+ fn: IrLibFn;
3908
+ args: IrExpr[];
3909
+ type: IrType;
3910
+ loc: SrcLoc;
3911
+ }
3912
+ /** `JSON.stringify(v)` — type-DIRECTED serialization: `value`'s static IR
3913
+ * type must be JSON-safe (f64/string/bool/record/array/union of those,
3914
+ * recursively — validated), and backends emit one serializer per type used
3915
+ * in stringify position (interned, like the array-HOF desugars) instead of
3916
+ * walking any runtime tag. Output is Node-compatible byte-for-byte with
3917
+ * ONE documented divergence: record fields serialize in canonical (sorted)
3918
+ * order, not insertion order (SEMANTICS.md). NaN/±Infinity stringify as
3919
+ * `null` and -0 as `0`, exactly like JS; a record field holding the
3920
+ * undefined arm of its union (an optional field) is DROPPED from the
3921
+ * output — Node's rule for undefined-valued properties. The value is
3922
+ * BORROWED; the result string is owned (+1). Never throws. */
3923
+ | {
3924
+ kind: "jsonStringify";
3925
+ value: IrExpr;
3926
+ type: IrType;
3927
+ loc: SrcLoc;
3928
+ }
3929
+ /** The dynamic-boundary check — a CHECKED cast `dynValue as T`: validate
3930
+ * the dyn value's JSON DOM against `type` (a non-dyn, JSON-representable
3931
+ * IR type) and BUILD the typed value (+1), or THROW a catchable
3932
+ * TypeError-flavored, path-annotated string ("TypeError: expected number
3933
+ * at $.items[2].price, got string") through the exception cell. Semantics:
3934
+ * numbers/strings/bools match strictly (no coercions); records are
3935
+ * WIDTH-TOLERANT (extra JSON keys are ignored — this is check-and-extract,
3936
+ * not shape equality; missing or wrong-typed fields throw, EXCEPT that a
3937
+ * missing key for an undefined-armed union field — an optional field —
3938
+ * builds the interned undefined arm instead); arrays check every element;
3939
+ * unions try arms in canonical order and the first FULL match wins (no
3940
+ * match → throw; an undefined arm matches no DOM value); JSON null matches
3941
+ * exactly the nullT arm of a union target (bare null targets cannot
3942
+ * exist). MAY THROW:
3943
+ * backends' may-throw analyses must treat it like a `throw` statement.
3944
+ * The dyn operand is borrowed; the result is owned (+1). This is
3945
+ * scriptc-specific behavior — JS `as` never checks (SEMANTICS.md
3946
+ * documents it as the headline divergence: a lying cast throws instead of
3947
+ * corrupting memory). */
3948
+ | {
3949
+ kind: "dynCheck";
3950
+ value: IrExpr;
3951
+ type: IrType;
3952
+ loc: SrcLoc;
3953
+ }
3954
+ /** Static → island marshal (--dynamic builds only). `value`'s type is
3955
+ * f64/string/bool (marshaled by value) or a JSON-safe composite
3956
+ * (record/array/union — marshaled as a DEEP COPY through the emitted
3957
+ * type-directed JSON serializer and the engine's JSON parser; the
3958
+ * aliasing divergence is documented in SEMANTICS.md). Result is an
3959
+ * owned (+1) jsval; the operand is borrowed. Never throws. */
3960
+ | {
3961
+ kind: "jsMarshal";
3962
+ value: IrExpr;
3963
+ type: IrType;
3964
+ loc: SrcLoc;
3965
+ }
3966
+ /** An operation on island values (--dynamic builds only), executed by
3967
+ * the embedded engine with JS-exact semantics (coercions come from
3968
+ * pinned prelude closures, not C reimplementations). `args` are
3969
+ * jsval-typed and borrowed. Result `type` per op: arithmetic
3970
+ * (add/sub/mul/div/mod/pow), unary neg/plus, getProp/getIdx,
3971
+ * callMethod/callFn/globalGet → jsval (+1); comparisons
3972
+ * (lt/le/gt/ge/eq/neq), truthy, not → bool; typeof, toStr → string (+1);
3973
+ * setProp/setIdx → void. `name` carries the property/method identifier
3974
+ * for getProp/setProp/callMethod/globalGet, absent otherwise. MAY THROW
3975
+ * (engine
3976
+ * exceptions bridge into the exception cell, catchably) — backends'
3977
+ * may-throw analyses must seed on every jsOp like a `throw`. */
3978
+ | {
3979
+ kind: "jsOp";
3980
+ op: IrJsOp;
3981
+ name?: string;
3982
+ args: IrExpr[];
3983
+ type: IrType;
3984
+ loc: SrcLoc;
3985
+ }
3986
+ /** Island → static validated exit (--dynamic builds only): `value` is
3987
+ * jsval-typed, `type` is the static target. STRICT for primitives (a
3988
+ * non-number refuses to exit as number — no coercion); composite
3989
+ * targets round-trip through the engine's JSON.stringify and the
3990
+ * existing dynCheck walker for the target (width-tolerant records,
3991
+ * path-annotated failures — identical semantics to `dyn as T`). MAY
3992
+ * THROW a catchable TypeError-shaped string. The operand is borrowed;
3993
+ * the result is owned (+1) for refcounted targets. */
3994
+ | {
3995
+ kind: "jsExit";
3996
+ value: IrExpr;
3997
+ type: IrType;
3998
+ loc: SrcLoc;
3999
+ }
4000
+ /** Island → static PROMISE bridge (--dynamic builds only): `value` is a
4001
+ * jsval whose declared type is Promise<T> (a package call's promise —
4002
+ * it lives in the engine); the result is a fresh pending static promise
4003
+ * the engine promise settles. `type` is promise-of-jsval (the settled
4004
+ * engine value crosses as a retained handle; typed uses exit like any
4005
+ * jsval) or promise-of-void (T mapped to void — nothing to carry).
4006
+ * Fulfillment wakes parked awaiters through the ready queue; rejection
4007
+ * crosses like a bridged exception (engine Errors become real static
4008
+ * Errors) and re-throws at the await or enters the unhandled ledger.
4009
+ * Bridging one engine promise twice makes two independent static
4010
+ * observers of the same settlement — semantically equivalent, slightly
4011
+ * redundant (SEMANTICS.md). Operand borrowed; result +1. MAY THROW
4012
+ * only on an engine-level surprise minting the subscription — backends
4013
+ * seed may-throw and emit the pending check like other island ops. */
4014
+ | {
4015
+ kind: "jsBridgePromise";
4016
+ value: IrExpr;
4017
+ type: IrType;
4018
+ loc: SrcLoc;
4019
+ };
4020
+ /** The island operation set. Grouped by result type — see the jsOp node
4021
+ * doc. A closed union: every member has a lowering rule in the frontend,
4022
+ * a validation rule, and a scr_jsval_* implementation in scr_island.c. */
4023
+ export type IrJsOp = "add" | "sub" | "mul" | "div" | "mod" | "pow" | "neg" | "plus" | "lt" | "le" | "gt" | "ge" | "eq" | "neq"
4024
+ /** `v instanceof C` where BOTH sides are island values (a package-
4025
+ * exported class as the RHS): the spec's InstanceofOperator in the
4026
+ * engine, Symbol.hasInstance included; a non-object RHS throws the
4027
+ * engine's own TypeError, bridged catchably. */
4028
+ | "instanceOf" | "truthy" | "not" | "typeof" | "toStr" | "getProp" | "setProp" | "getIdx" | "setIdx" | "callMethod" | "callFn"
4029
+ /** `new X(...)` where X is jsval-typed (package-declared classes):
4030
+ * JS_CallConstructor — args are the callee then the constructor
4031
+ * arguments, mirroring callFn. */
4032
+ | "construct"
4033
+ /** A member of the engine's global object by name (Math, parseFloat, ...)
4034
+ * — the receiver/callee for the island-backed ambient surface. Zero args;
4035
+ * `name` carries the global's identifier. May-throw for uniformity with
4036
+ * the other engine entries (the emitter's pending check runs after it). */
4037
+ | "globalGet"
4038
+ /** Island-native literals: an object literal / array literal whose
4039
+ * contextual type is `any` builds directly in the engine — objLit args
4040
+ * are alternating key/value jsvals (keys are marshaled strings), arrLit
4041
+ * args are the elements. Never throw. */
4042
+ | "objLit" | "arrLit"
4043
+ /** The engine's own undefined / null as island values (zero args, never
4044
+ * throw): the unit arms of a union marshaling IN (`string | undefined`
4045
+ * into an 'any' slot — the undefined arm IS the engine undefined), and
4046
+ * conceptually the unit path of `x?.y` on 'any' (the emitter inlines
4047
+ * that one). */
4048
+ | "undefLit" | "nullLit"
4049
+ /** GetIterator over an island value — the for-of head over 'any' (the
4050
+ * engine's own protocol lookup; V8's not-iterable TypeError on refusal).
4051
+ * The loop drives next() through callMethod and reads value/done with
4052
+ * getProp/truthy. */
4053
+ | "iterNew"
4054
+ /** `o.name?.(...)` — the optional METHOD call on an island receiver: a
4055
+ * nullish member answers the engine's undefined, anything else calls
4056
+ * with `this = o` (JS-exact; non-callables throw in the engine). */
4057
+ | "optCallMethod";
4058
+ /** Result-type rule for each island op (the validator enforces it; the
4059
+ * frontend constructs nodes with exactly these). */
4060
+ export declare function jsOpResultKind(op: IrJsOp): "jsval" | "bool" | "string" | "void";
4061
+ /** True when a type is a union with an undefined arm — the optional-flavored
4062
+ * slot marker shared by the frontend (record literals may omit such fields)
4063
+ * and backends (JSON serializers DROP such fields when they hold undefined,
4064
+ * dynCheck builders produce the undefined arm for a MISSING key). Note the
4065
+ * question is about the TYPE, not a declaration's `?:` token: without
4066
+ * exactOptionalPropertyTypes, `{a?: string}` and `{a: string | undefined}`
4067
+ * are the same shape and behave identically — which is exactly Node's rule
4068
+ * (JSON.stringify drops ANY undefined-valued field, declared optional or
4069
+ * not). */
4070
+ export declare function isUndefinedArmedUnion(t: IrType, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4071
+ /** True when a type is JSON-representable — the shared fence for
4072
+ * `jsonStringify` (what can be serialized) and `dynCheck` (what a dyn value
4073
+ * can be validated against): f64, string, bool, records, arrays, and unions
4074
+ * of those, recursively. Closures, class instances, dyn itself, and void are
4075
+ * not JSON. Registry lookups are parameters because the frontend holds
4076
+ * registries and the validator/backend hold maps; recursive shapes/unions
4077
+ * cannot exist (the frontend rejects them), so the recursion terminates. */
4078
+ export declare function isJsonSafeType(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4079
+ /** THE island boundary predicate: true when a static type can cross into
4080
+ * the island (jsMarshal — primitives by value, composites as deep JSON
4081
+ * copies) and back out (jsExit — strict primitive extraction, composites
4082
+ * through the dynCheck walker). Primitives are JSON-safe, so the rule
4083
+ * coincides with isJsonSafeType; it has its own name because the boundary
4084
+ * is its own concept — the frontend's implicit coercions, the explicit-cast
4085
+ * lowering, and the validator's jsMarshal/jsExit rules all ask this ONE
4086
+ * question, and the boundary rejection messages describe exactly this set. */
4087
+ export declare function canCrossIslandBoundary(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4088
+ /** True for a closure type that can cross INTO the island as a host
4089
+ * function: every parameter jsval (the engine's arguments pass through as
4090
+ * handles — no per-type extraction exists inside a host call) and the
4091
+ * result jsval, void, or a primitive (which marshals back by value —
4092
+ * `(x) => x * 2` on an 'any' x infers a number return). Contextual typing
4093
+ * produces exactly this shape for callbacks passed to package APIs
4094
+ * (`.action((a, b) => ...)` against `(...args: any[]) => void`). Arity is
4095
+ * capped by the runtime's host-call argument buffer (scr_island.c). */
4096
+ export declare const MAX_ISLAND_CALLBACK_ARITY = 16;
4097
+ export declare function canMarshalFuncIntoIsland(t: IrType): boolean;
4098
+ /** Parameter types a TYPED closure may declare when it crosses INTO the
4099
+ * island as a host function: jsval params take the engine argument as a
4100
+ * handle (the all-'any' shape above); every other admitted type converts
4101
+ * AT CALL TIME through the validated-exit machinery — strict primitives,
4102
+ * JSON round-trip composites (the dynCheck walker: width-tolerant records,
4103
+ * path-annotated failures). On top of the jsExit set, a bare `T | undefined`
4104
+ * union is admitted here — an absent or undefined engine argument takes the
4105
+ * undefined arm, exactly the missing-optional-field rule (and exactly the
4106
+ * commander case: `.action((text: string | undefined, opts) => ...)` sees
4107
+ * undefined when the command argument is omitted). */
4108
+ export declare function isIslandCallbackParamType(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4109
+ /** Classify a typed island callback's RETURN for adapter synthesis: sync
4110
+ * kinds marshal back by value ('void'|'jsval'|'f64'|'bool'|'string' — the
4111
+ * canMarshalFuncIntoIsland set), 'json' marshals a JSON-safe composite
4112
+ * through the type-directed serializer + engine parse (the jsMarshal
4113
+ * composite path — commander's option-argument collectors return arrays
4114
+ * this way), and a Promise of the by-value kinds wraps as an engine
4115
+ * promise settled when the scriptc promise settles (async callbacks —
4116
+ * the `.action(async ...)` case). Null for anything else (Promise of
4117
+ * composites: still fenced). */
4118
+ export declare function islandCallbackRet(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): {
4119
+ async: boolean;
4120
+ tag: "void" | "jsval" | "f64" | "bool" | "string" | "json";
4121
+ } | null;
4122
+ /** The TYPED extension of canMarshalFuncIntoIsland (a strict superset):
4123
+ * closures whose params are per-argument-convertible at call time
4124
+ * (isIslandCallbackParamType) and whose return classifies
4125
+ * (islandCallbackRet). Same arity cap — the runtime's host-call argument
4126
+ * buffer. Closures taking closures and 'unknown'-typed params stay fenced
4127
+ * (no per-type extraction exists for them inside a host call). */
4128
+ export declare function canMarshalTypedFuncIntoIsland(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4129
+ /** The runtime HANDLE kinds that cross the checked-dynamic boundary as
4130
+ * the DOM's HANDLE kind (SCR_DYN_HANDLE): boxed by REFERENCE (identity —
4131
+ * stateful I/O objects never copy), unboxed by tag check, members
4132
+ * dispatched at runtime onto the same entry points the static lowerings
4133
+ * use. The set is deliberately the handles whose member surfaces have
4134
+ * complete static lowerings (the http/net receiver surface —
4135
+ * `server.on('request', mustCall((req, res) => ...))` is the canonical
4136
+ * crossing); other handle kinds keep the honest cannot-box fence. Each
4137
+ * entry carries the runtime tag spelling and the class display name
4138
+ * (dynCheck's "expected IncomingMessage ..." texts). */
4139
+ export declare const DYN_HANDLE_KINDS: ReadonlyMap<string, {
4140
+ tag: string;
4141
+ cls: string;
4142
+ }>;
4143
+ /** A static type that CONVERTS into a dyn DOM value — the dynFrom domain:
4144
+ * JSON-safe data, bytes<u8> (payload copied), undefined-armed unions of
4145
+ * JSON-safe arms, boxable function types, and the runtime HANDLE kinds
4146
+ * (boxed by reference — DYN_HANDLE_KINDS). */
4147
+ export declare function canConvertToDyn(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4148
+ /** A type a dyn value can be VALIDATED into — the dynCheck domain:
4149
+ * JSON-safe data, bytes<u8> (a fresh copy out), the %Error extraction,
4150
+ * undefined-armed unions of JSON-safe arms, adaptable function types,
4151
+ * and the runtime HANDLE kinds (a tag-checked reference unwrap —
4152
+ * DYN_HANDLE_KINDS). */
4153
+ export declare function canDynCheckTo(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4154
+ /** A closure type that can BOX into the DOM's function kind (dynFrom):
4155
+ * every param dyn or dynCheckable (the thunk validates dyn arguments into
4156
+ * them), return void, dyn, or dyn-convertible (the thunk converts it
4157
+ * back). */
4158
+ export declare function canBoxFuncIntoDyn(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4159
+ /** A closure type a dyn function value can ADAPT to (dynCheck): every
4160
+ * param dyn or dyn-convertible (the adapter converts typed arguments into
4161
+ * dyn), return void, dyn, or dynCheckable (the adapter validates the dyn
4162
+ * result). */
4163
+ export declare function canAdaptDynFuncTo(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4164
+ /** The MARSHAL-direction boundary (jsMarshal): everything that can cross
4165
+ * out and back (canCrossIslandBoundary) plus qualifying closures — those
4166
+ * enter as host functions but never EXIT (jsExit keeps the narrower
4167
+ * predicate). */
4168
+ export declare function canMarshalIntoIsland(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4169
+ /** The EXIT-direction boundary (jsExit): everything round-trippable
4170
+ * (canCrossIslandBoundary) plus BARE undefined/null-armed unions whose
4171
+ * data arms are all JSON-safe — the engine's undefined takes the
4172
+ * undefined arm before the JSON detour (JSON cannot spell undefined, and
4173
+ * bare undefined-armed unions are JSON-unsafe for exactly that reason),
4174
+ * null and data ride the round trip into the union's dynCheck. The
4175
+ * package-API shape `result.headers` : `Record<string, string> |
4176
+ * undefined` is the motivating case. */
4177
+ export declare function canExitIslandToType(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): boolean;
4178
+ /** True when the module contains any regex construct — a regexLit /
4179
+ * regexIntrinsic node or a regex-typed slot anywhere. This is the link
4180
+ * switch that pulls scr_regex.c + the vendored libregexp into the binary
4181
+ * (cc.ts); regex-free programs keep the historical command line. A generic
4182
+ * JSON walk: `kind` discriminants live only on IR objects, so user string
4183
+ * VALUES can never false-positive. */
4184
+ export declare function moduleUsesRegex(mod: IrModule): boolean;
4185
+ /** True when the embedded npm graph references fetch — the link switch
4186
+ * that pulls scr_fetch.c + its socket/tls/zlib dependencies into the binary (cc.ts) and
4187
+ * has the emitted main call scr_fetch_install. A word-boundary scan over
4188
+ * the embedded SOURCES, erring toward linking: a false positive costs one
4189
+ * dylib reference; a false negative would leave embedded code without the
4190
+ * global at runtime. Static builds and fetch-free graphs keep their exact
4191
+ * historical link lines. */
4192
+ export declare function moduleUsesFetch(mod: IrModule): boolean;
4193
+ /** True when the module uses the process-events surface — the link switch
4194
+ * that pulls scr_events.c into the binary and has the emitted main call
4195
+ * scr_events_install (cc.ts + emitter; the scr_regex/scr_fetch/scr_zlib
4196
+ * gating precedent). Event-free programs pay zero bytes and keep their
4197
+ * exact link line. Same generic-walk shape as moduleUsesRegex. */
4198
+ export declare function moduleUsesProcessEvents(mod: IrModule): boolean;
4199
+ /** True when the module uses the node:events EventEmitter surface — the
4200
+ * link switch that pulls scr_events_emitter.c into the binary (cc.ts; the
4201
+ * scr_events.c gating precedent, but pure data structure: no install, no
4202
+ * loop hooks). Two signals: the `%EventEmitter` class def rides the
4203
+ * module (any emitter-typed value or `extends EventEmitter` subclass
4204
+ * references it, and the emitted RC/trace helpers call scr_emitter_*),
4205
+ * or an emitter.* libCall survived (the defaultMaxListeners statics carry
4206
+ * no emitter-typed value). Emitter-free programs pay zero bytes and keep
4207
+ * their exact link line. */
4208
+ export declare function moduleUsesEmitter(mod: IrModule): boolean;
4209
+ /** True when the program touches the node:stream surface (scr_stream.c —
4210
+ * the moduleUsesEmitter story: the class defs ride the module whenever a
4211
+ * stream-typed value exists, and every stream libCall names its unit).
4212
+ * Stream programs always use the emitter unit too — the stream class
4213
+ * defs pull `%EventEmitter` through their base chain, so
4214
+ * moduleUsesEmitter answers true whenever this does. Stream-free
4215
+ * programs pay zero bytes and keep their exact link line. */
4216
+ export declare function moduleUsesStream(mod: IrModule): boolean;
4217
+ /** True when the embedded npm graph has an edge into `builtin` — the
4218
+ * island shim needs the corresponding native bridge linked (zlib's is
4219
+ * the first; the emitted main installs it before any island entry). */
4220
+ export declare function moduleEmbedsBuiltin(mod: IrModule, builtin: string): boolean;
4221
+ /** Embedded module texts at least this long are DEFLATE-compressed into
4222
+ * the emitted C (emit-island.ts; each stays plain when deflate does not
4223
+ * shrink it) and inflated lazily by the island's module loader at first
4224
+ * load. Below it the zlib round trip cannot pay for itself. */
4225
+ export declare const NPM_COMPRESS_MIN = 1024;
4226
+ /** True when the emitted npm tables will carry compressed module text —
4227
+ * the SAME candidate test emit-island.ts compresses by, so index.ts's
4228
+ * zlib link switch and emitter.ts's inflater installation stay in
4229
+ * lockstep with the emission (a candidate whose deflate happens not to
4230
+ * shrink stays plain; the installed inflater is then just unused). */
4231
+ export declare function moduleEmbedsCompressedNpm(mod: IrModule): boolean;
4232
+ /** True when the module contains any zlib libCall (the static lowering)
4233
+ * OR the embedded npm graph imports node:zlib (the island shim) — the
4234
+ * link switch that pulls scr_zlib.c + the system libz into the binary
4235
+ * (cc.ts); zlib-free programs keep their exact link line. Same
4236
+ * generic-walk shape as moduleUsesRegex: `kind`/`fn` discriminants live
4237
+ * only on IR objects. */
4238
+ export declare function moduleUsesZlib(mod: IrModule): boolean;
4239
+ /** True when the module contains any dc.* libCall — the link switch that
4240
+ * pulls scr_dc.c (the diagnostics_channel registry and pub/sub) into the
4241
+ * binary (cc.ts). Channel-free binaries keep their exact size class.
4242
+ * Same walk shape as moduleUsesZlib. */
4243
+ export declare function moduleUsesDc(mod: IrModule): boolean;
4244
+ /** True when the module contains any assert libCall — the link switch
4245
+ * that pulls scr_assert.c into the binary (cc.ts). scr_regex.c calls the
4246
+ * assert throw/inspect helpers (assert.match lives there), so the regex
4247
+ * switch also pulls scr_assert.c; assert-free, regex-free binaries keep
4248
+ * the historical command line and size. Same walk shape as
4249
+ * moduleUsesZlib. */
4250
+ export declare function moduleUsesAssert(mod: IrModule): boolean;
4251
+ /** True when the module contains any dynInvoke node or dyn.defineProps
4252
+ * libCall — the link switch that pulls scr_dyn_invoke.c (the prototype-
4253
+ * method dispatch on dyn receivers, plus scr_dyn_display and
4254
+ * scr_dyn_define_props) into the binary (cc.ts; the assert gating
4255
+ * precedent — dispatch-free binaries keep their exact size class). Same
4256
+ * walk shape as moduleUsesZlib. */
4257
+ export declare function moduleUsesDynInvoke(mod: IrModule): boolean;
4258
+ /** True when the module contains any insp libCall — the link switch that
4259
+ * pulls scr_inspect.c into the binary (cc.ts; the assert gating
4260
+ * precedent — inspect-free binaries keep the historical command line and
4261
+ * size class). Same walk shape as moduleUsesZlib. */
4262
+ /** True when the module needs scr_async_dyn.c — the checked-dynamic
4263
+ * async surfaces (DOM-promise then/catch/finally reactions, await of a
4264
+ * dyn value, `new Promise(setImmediate)`, AsyncLocalStorage, the
4265
+ * unhandledRejection/warning process events). Also pulled by the
4266
+ * dynInvoke and dc gates (their TUs call into this one) — cc.ts. Same
4267
+ * walk shape as moduleUsesZlib. */
4268
+ export declare function moduleUsesDynAsync(mod: IrModule): boolean;
4269
+ export declare function moduleUsesInspect(mod: IrModule): boolean;
4270
+ /** True when the module contains any net libCall — the link switch that
4271
+ * pulls scr_net.c into the binary and has the emitted main call
4272
+ * scr_net_install (cc.ts + emitter; the scr_events gating precedent).
4273
+ * Net-free programs pay zero bytes and keep their exact link line. Same
4274
+ * generic-walk shape as moduleUsesZlib. */
4275
+ export declare function moduleUsesNet(mod: IrModule): boolean;
4276
+ /** True when the module contains any sym.* libCall or a symbol-kind type
4277
+ * anywhere in the IR — the link switch that pulls scr_symbol.c into the
4278
+ * binary (cc.ts; the scr_net gating precedent — no install call, the
4279
+ * Symbol.for registry initializes lazily). The TYPE check matters like
4280
+ * net's: a symbol-typed local whose initializer compiled to a runtime
4281
+ * fence still emits release calls that need the unit linked. Symbol-free
4282
+ * programs pay zero bytes and keep their exact link line. */
4283
+ export declare function moduleUsesSymbol(mod: IrModule): boolean;
4284
+ /** True when the module uses the URLSearchParams surface — sp.* libCalls,
4285
+ * the url.searchParams getter, or a searchParams-kind type anywhere on
4286
+ * the IR (a fenced statement can leave a typed local whose release call
4287
+ * still needs the unit linked) — the link switch that pulls
4288
+ * scr_url_params.c into the binary (the moduleUsesSymbol precedent: pure
4289
+ * data structure, no loop hooks, cross-compiles everywhere). sp-free
4290
+ * programs keep their exact link line; scr_url.c itself stays
4291
+ * always-linked and never references the unit. */
4292
+ export declare function moduleUsesSearchParams(mod: IrModule): boolean;
4293
+ /** True when the module contains any fs.watch/watcher.* libCall — the
4294
+ * link switch that pulls scr_watch.c into the binary and has the emitted
4295
+ * main call scr_watch_install (cc.ts + emitter; the scr_net gating
4296
+ * precedent). Watch-free programs pay zero bytes and keep their exact
4297
+ * link line. Same generic-walk shape as moduleUsesZlib. */
4298
+ export declare function moduleUsesFsWatch(mod: IrModule): boolean;
4299
+ /** True when the module contains any test.* libCall or a testCtx handle
4300
+ * type — the link switch that pulls scr_test.c into the binary and has
4301
+ * the emitted main return scr_test_exit_code() after the loop drains
4302
+ * (cc.ts + emitter; the moduleUsesDgram shape). Test-free programs pay
4303
+ * zero bytes and keep their exact link line. */
4304
+ export declare function moduleUsesNodeTest(mod: IrModule): boolean;
4305
+ /** True when the module contains any dgram.* or dns.* libCall — the
4306
+ * link switch that pulls scr_dgram.c into the binary and has the emitted
4307
+ * main call scr_dgram_install (cc.ts + emitter; the scr_net gating
4308
+ * precedent — dns.lookup lives in the same unit, so either prefix
4309
+ * answers). Dgram-free programs pay zero bytes and keep their exact link
4310
+ * line. Same generic-walk shape as moduleUsesZlib. */
4311
+ export declare function moduleUsesDgram(mod: IrModule): boolean;
4312
+ /** True when the module contains any http.* libCall — the link switch
4313
+ * that pulls scr_http.c into the binary (cc.ts; moduleUsesNet already
4314
+ * answers true for these, so scr_net.c comes along). */
4315
+ export declare function moduleUsesHttpServer(mod: IrModule): boolean;
4316
+ /** True when the module uses the REAL h2 surface (scr_http2.c): any core
4317
+ * http2.* libCall, or an h2 handle type left behind by a fenced statement
4318
+ * (its emitted release call needs the unit — the moduleUsesNet story). */
4319
+ export declare function moduleUsesHttp2(mod: IrModule): boolean;
4320
+ /** True when the module contains any tls.* or https.* libCall — the link
4321
+ * switch that pulls scr_tls.c and the vendored mbedTLS archive into the
4322
+ * binary (cc.ts; moduleUsesNet and moduleUsesHttpServer already answer
4323
+ * true for these, so scr_net.c and scr_http.c come along). TLS-free
4324
+ * programs keep their exact link line and never build mbedTLS. */
4325
+ export declare function moduleUsesTls(mod: IrModule): boolean;
4326
+ /** The may-throw seed: libCall members that can raise. Every fs.* member
4327
+ * EXCEPT existsSync (which, like Node's, swallows errors and returns false)
4328
+ * throws a catchable error on failure; json.parse throws a catchable
4329
+ * SyntaxError-shaped string on malformed input; process.* members never
4330
+ * throw. Backends' may-throw analyses must treat a function containing one
4331
+ * of these as throwing, exactly like a `throw` statement (and must ALSO
4332
+ * seed on `dynCheck` and `awaitExpr` nodes, which throw on validation
4333
+ * failure / promise rejection). */
4334
+ export declare const MAY_THROW_LIB_FNS: ReadonlySet<IrLibFn>;