@loopdive/js2 0.57.0

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 (233) hide show
  1. package/CHANGELOG.md +1425 -0
  2. package/LICENSE +189 -0
  3. package/README.md +451 -0
  4. package/dist/checker/index.d.ts +117 -0
  5. package/dist/checker/language-service.d.ts +39 -0
  6. package/dist/checker/node-capability-map.d.ts +63 -0
  7. package/dist/checker/type-mapper.d.ts +84 -0
  8. package/dist/cjs-rewrite.d.ts +19 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +363 -0
  11. package/dist/codegen/accessor-driver.d.ts +97 -0
  12. package/dist/codegen/any-helpers.d.ts +72 -0
  13. package/dist/codegen/array-element-typing.d.ts +46 -0
  14. package/dist/codegen/array-holes.d.ts +69 -0
  15. package/dist/codegen/array-methods.d.ts +68 -0
  16. package/dist/codegen/array-object-proto.d.ts +64 -0
  17. package/dist/codegen/array-reduce-fusion.d.ts +31 -0
  18. package/dist/codegen/array-to-primitive.d.ts +28 -0
  19. package/dist/codegen/async-cps.d.ts +239 -0
  20. package/dist/codegen/async-scheduler.d.ts +349 -0
  21. package/dist/codegen/binary-ops.d.ts +78 -0
  22. package/dist/codegen/binding-info.d.ts +31 -0
  23. package/dist/codegen/builtin-scaffold.d.ts +98 -0
  24. package/dist/codegen/builtin-static-globals.d.ts +8 -0
  25. package/dist/codegen/builtin-tags.d.ts +189 -0
  26. package/dist/codegen/case-convert-native.d.ts +12 -0
  27. package/dist/codegen/case-tables.d.ts +4 -0
  28. package/dist/codegen/class-bodies.d.ts +41 -0
  29. package/dist/codegen/class-member-keys.d.ts +33 -0
  30. package/dist/codegen/class-to-primitive.d.ts +39 -0
  31. package/dist/codegen/closed-method-dispatch.d.ts +42 -0
  32. package/dist/codegen/closures.d.ts +285 -0
  33. package/dist/codegen/coercion-engine.d.ts +154 -0
  34. package/dist/codegen/coercion-plan.d.ts +29 -0
  35. package/dist/codegen/context/bodies.d.ts +4 -0
  36. package/dist/codegen/context/create-context.d.ts +4 -0
  37. package/dist/codegen/context/errors.d.ts +39 -0
  38. package/dist/codegen/context/locals.d.ts +69 -0
  39. package/dist/codegen/context/source-pos.d.ts +5 -0
  40. package/dist/codegen/context/speculative.d.ts +95 -0
  41. package/dist/codegen/context/types.d.ts +1936 -0
  42. package/dist/codegen/custom-iterable.d.ts +34 -0
  43. package/dist/codegen/dataview-native.d.ts +51 -0
  44. package/dist/codegen/date-parse-native.d.ts +13 -0
  45. package/dist/codegen/dead-elimination.d.ts +26 -0
  46. package/dist/codegen/declarations.d.ts +147 -0
  47. package/dist/codegen/deno-api.d.ts +11 -0
  48. package/dist/codegen/destructuring-params.d.ts +102 -0
  49. package/dist/codegen/dyn-read.d.ts +26 -0
  50. package/dist/codegen/eval-tiering.d.ts +19 -0
  51. package/dist/codegen/expressions/assignment.d.ts +61 -0
  52. package/dist/codegen/expressions/builtins.d.ts +26 -0
  53. package/dist/codegen/expressions/calls-closures.d.ts +54 -0
  54. package/dist/codegen/expressions/calls-guards.d.ts +49 -0
  55. package/dist/codegen/expressions/calls-optional.d.ts +4 -0
  56. package/dist/codegen/expressions/calls.d.ts +83 -0
  57. package/dist/codegen/expressions/eval-inline.d.ts +24 -0
  58. package/dist/codegen/expressions/extern.d.ts +67 -0
  59. package/dist/codegen/expressions/fnctor-prototype.d.ts +52 -0
  60. package/dist/codegen/expressions/helpers.d.ts +212 -0
  61. package/dist/codegen/expressions/identifiers.d.ts +57 -0
  62. package/dist/codegen/expressions/late-imports.d.ts +81 -0
  63. package/dist/codegen/expressions/logical-ops.d.ts +18 -0
  64. package/dist/codegen/expressions/misc.d.ts +27 -0
  65. package/dist/codegen/expressions/new-super.d.ts +25 -0
  66. package/dist/codegen/expressions/promise-subclass.d.ts +38 -0
  67. package/dist/codegen/expressions/proto-override.d.ts +63 -0
  68. package/dist/codegen/expressions/unary-updates.d.ts +21 -0
  69. package/dist/codegen/expressions/unary.d.ts +6 -0
  70. package/dist/codegen/expressions.d.ts +31 -0
  71. package/dist/codegen/fallback-telemetry.d.ts +53 -0
  72. package/dist/codegen/fixups.d.ts +80 -0
  73. package/dist/codegen/fmod.d.ts +10 -0
  74. package/dist/codegen/fnctor-escape-gate.d.ts +92 -0
  75. package/dist/codegen/function-body.d.ts +52 -0
  76. package/dist/codegen/generators-native.d.ts +92 -0
  77. package/dist/codegen/helpers/body-references-own-this.d.ts +22 -0
  78. package/dist/codegen/helpers/body-uses-arguments.d.ts +12 -0
  79. package/dist/codegen/helpers/is-strict-function.d.ts +52 -0
  80. package/dist/codegen/host-import-allowlist.d.ts +140 -0
  81. package/dist/codegen/index.d.ts +500 -0
  82. package/dist/codegen/ir-tail-call.d.ts +8 -0
  83. package/dist/codegen/iterator-native.d.ts +44 -0
  84. package/dist/codegen/json-codec-native.d.ts +78 -0
  85. package/dist/codegen/json-runtime.d.ts +35 -0
  86. package/dist/codegen/json-standalone.d.ts +25 -0
  87. package/dist/codegen/linear-uint8-analysis.d.ts +46 -0
  88. package/dist/codegen/linear-uint8-arena.d.ts +7 -0
  89. package/dist/codegen/linear-uint8-codegen.d.ts +103 -0
  90. package/dist/codegen/linear-uint8-signatures.d.ts +26 -0
  91. package/dist/codegen/literals.d.ts +115 -0
  92. package/dist/codegen/map-runtime.d.ts +142 -0
  93. package/dist/codegen/math-helpers.d.ts +7 -0
  94. package/dist/codegen/member-get-dispatch.d.ts +42 -0
  95. package/dist/codegen/member-set-dispatch.d.ts +28 -0
  96. package/dist/codegen/native-proto.d.ts +98 -0
  97. package/dist/codegen/native-regex.d.ts +158 -0
  98. package/dist/codegen/native-strings.d.ts +146 -0
  99. package/dist/codegen/new-target.d.ts +30 -0
  100. package/dist/codegen/node-fs-api.d.ts +47 -0
  101. package/dist/codegen/number-format-native.d.ts +9 -0
  102. package/dist/codegen/number-ryu.d.ts +27 -0
  103. package/dist/codegen/object-ops.d.ts +94 -0
  104. package/dist/codegen/object-runtime.d.ts +171 -0
  105. package/dist/codegen/parse-number-native.d.ts +10 -0
  106. package/dist/codegen/peephole.d.ts +6 -0
  107. package/dist/codegen/property-access.d.ts +294 -0
  108. package/dist/codegen/raw-wasi-api.d.ts +13 -0
  109. package/dist/codegen/regex/bytecode.d.ts +140 -0
  110. package/dist/codegen/regex/casefold.d.ts +41 -0
  111. package/dist/codegen/regex/compile.d.ts +51 -0
  112. package/dist/codegen/regex/parse.d.ts +76 -0
  113. package/dist/codegen/regex/unicode.d.ts +42 -0
  114. package/dist/codegen/regex/vm.d.ts +24 -0
  115. package/dist/codegen/regexp-standalone.d.ts +350 -0
  116. package/dist/codegen/registry/error-types.d.ts +38 -0
  117. package/dist/codegen/registry/imports.d.ts +46 -0
  118. package/dist/codegen/registry/types.d.ts +59 -0
  119. package/dist/codegen/set-algebra.d.ts +17 -0
  120. package/dist/codegen/set-runtime.d.ts +74 -0
  121. package/dist/codegen/shared.d.ts +111 -0
  122. package/dist/codegen/stack-balance.d.ts +43 -0
  123. package/dist/codegen/statements/control-flow.d.ts +25 -0
  124. package/dist/codegen/statements/destructuring.d.ts +177 -0
  125. package/dist/codegen/statements/exceptions.d.ts +11 -0
  126. package/dist/codegen/statements/functions.d.ts +1 -0
  127. package/dist/codegen/statements/index.d.ts +1 -0
  128. package/dist/codegen/statements/loops.d.ts +7 -0
  129. package/dist/codegen/statements/nested-declarations.d.ts +78 -0
  130. package/dist/codegen/statements/shared.d.ts +38 -0
  131. package/dist/codegen/statements/tdz.d.ts +43 -0
  132. package/dist/codegen/statements/variables.d.ts +3 -0
  133. package/dist/codegen/statements.d.ts +9 -0
  134. package/dist/codegen/string-builder.d.ts +131 -0
  135. package/dist/codegen/string-ops.d.ts +87 -0
  136. package/dist/codegen/struct-accessor-closure.d.ts +36 -0
  137. package/dist/codegen/symbol-native.d.ts +55 -0
  138. package/dist/codegen/temporal-native.d.ts +8 -0
  139. package/dist/codegen/timsort.d.ts +2 -0
  140. package/dist/codegen/type-coercion.d.ts +123 -0
  141. package/dist/codegen/typeof-delete.d.ts +38 -0
  142. package/dist/codegen/uri-encoding-native.d.ts +33 -0
  143. package/dist/codegen/value-tags.d.ts +74 -0
  144. package/dist/codegen/walk-instructions.d.ts +20 -0
  145. package/dist/codegen/weak-collections-runtime.d.ts +16 -0
  146. package/dist/codegen/with-scope.d.ts +106 -0
  147. package/dist/codegen-linear/c-abi.d.ts +74 -0
  148. package/dist/codegen-linear/context.d.ts +86 -0
  149. package/dist/codegen-linear/index.d.ts +28 -0
  150. package/dist/codegen-linear/layout.d.ts +39 -0
  151. package/dist/codegen-linear/runtime.d.ts +161 -0
  152. package/dist/codegen-linear/simd.d.ts +7 -0
  153. package/dist/compiler/define-substitution.d.ts +27 -0
  154. package/dist/compiler/early-errors/assignment.d.ts +26 -0
  155. package/dist/compiler/early-errors/context.d.ts +17 -0
  156. package/dist/compiler/early-errors/duplicates.d.ts +20 -0
  157. package/dist/compiler/early-errors/index.d.ts +11 -0
  158. package/dist/compiler/early-errors/labels.d.ts +13 -0
  159. package/dist/compiler/early-errors/module-rules.d.ts +36 -0
  160. package/dist/compiler/early-errors/node-checks.d.ts +7 -0
  161. package/dist/compiler/early-errors/predicates.d.ts +140 -0
  162. package/dist/compiler/early-errors/tdz.d.ts +17 -0
  163. package/dist/compiler/import-manifest.d.ts +18 -0
  164. package/dist/compiler/output.d.ts +46 -0
  165. package/dist/compiler/validation.d.ts +45 -0
  166. package/dist/compiler.d.ts +48 -0
  167. package/dist/define-substitution-BcUeKC2A.js +109 -0
  168. package/dist/emit/binary.d.ts +50 -0
  169. package/dist/emit/c-header.d.ts +23 -0
  170. package/dist/emit/canonical-recgroup.d.ts +86 -0
  171. package/dist/emit/encoder.d.ts +28 -0
  172. package/dist/emit/object.d.ts +14 -0
  173. package/dist/emit/opcodes.d.ts +464 -0
  174. package/dist/emit/sourcemap.d.ts +33 -0
  175. package/dist/emit/wat.d.ts +6 -0
  176. package/dist/env.d.ts +46 -0
  177. package/dist/import-resolver.d.ts +68 -0
  178. package/dist/index.d.ts +486 -0
  179. package/dist/index.js +755 -0
  180. package/dist/ir/alloc-registry.d.ts +75 -0
  181. package/dist/ir/analysis/encoding.d.ts +38 -0
  182. package/dist/ir/analysis/escape.d.ts +32 -0
  183. package/dist/ir/analysis/lattice.d.ts +72 -0
  184. package/dist/ir/analysis/ownership.d.ts +31 -0
  185. package/dist/ir/analysis/stack-alloc.d.ts +20 -0
  186. package/dist/ir/backend/bytecode-emitter.d.ts +237 -0
  187. package/dist/ir/backend/bytecode-vm.d.ts +74 -0
  188. package/dist/ir/backend/emitter.d.ts +121 -0
  189. package/dist/ir/backend/handles.d.ts +133 -0
  190. package/dist/ir/backend/legality.d.ts +9 -0
  191. package/dist/ir/backend/linear-emitter.d.ts +41 -0
  192. package/dist/ir/backend/wasmgc-emitter.d.ts +43 -0
  193. package/dist/ir/builder.d.ts +401 -0
  194. package/dist/ir/from-ast.d.ts +192 -0
  195. package/dist/ir/index.d.ts +16 -0
  196. package/dist/ir/integration.d.ts +27 -0
  197. package/dist/ir/lower.d.ts +203 -0
  198. package/dist/ir/nodes.d.ts +1452 -0
  199. package/dist/ir/passes/alloc-discipline.d.ts +19 -0
  200. package/dist/ir/passes/constant-fold.d.ts +7 -0
  201. package/dist/ir/passes/dead-code.d.ts +18 -0
  202. package/dist/ir/passes/inline-small.d.ts +7 -0
  203. package/dist/ir/passes/monomorphize.d.ts +21 -0
  204. package/dist/ir/passes/simplify-cfg.d.ts +19 -0
  205. package/dist/ir/passes/tagged-union-types.d.ts +45 -0
  206. package/dist/ir/passes/tagged-unions.d.ts +22 -0
  207. package/dist/ir/propagate.d.ts +135 -0
  208. package/dist/ir/select.d.ts +81 -0
  209. package/dist/ir/types.d.ts +832 -0
  210. package/dist/ir/verify-alloc.d.ts +18 -0
  211. package/dist/ir/verify.d.ts +7 -0
  212. package/dist/link/index.d.ts +11 -0
  213. package/dist/link/isolation.d.ts +24 -0
  214. package/dist/link/linker.d.ts +37 -0
  215. package/dist/link/reader.d.ts +158 -0
  216. package/dist/link/resolver.d.ts +19 -0
  217. package/dist/optimize.d.ts +54 -0
  218. package/dist/optimize.js +262 -0
  219. package/dist/position-map.d.ts +64 -0
  220. package/dist/process-stdin-prelude.d.ts +16 -0
  221. package/dist/resolve.d.ts +82 -0
  222. package/dist/runtime/builtins.d.ts +1 -0
  223. package/dist/runtime-C-4q_KwU.js +164438 -0
  224. package/dist/runtime-containment.d.ts +6 -0
  225. package/dist/runtime-eval.d.ts +132 -0
  226. package/dist/runtime-instantiate.d.ts +16 -0
  227. package/dist/runtime.d.ts +128 -0
  228. package/dist/runtime.js +12 -0
  229. package/dist/shape-inference.d.ts +20 -0
  230. package/dist/treeshake.d.ts +17 -0
  231. package/dist/ts-api.d.ts +30 -0
  232. package/dist/wit-generator.d.ts +18 -0
  233. package/package.json +187 -0
@@ -0,0 +1,1936 @@
1
+ import { ts } from '../../ts-api.js';
2
+ import { FieldDef, Instr, LocalDef, SourcePos, ValType, WasmModule } from '../../ir/types.js';
3
+ import { StandaloneRegExpEngineConfig } from '../regexp-standalone.js';
4
+ import { ObjectRuntimeTypes } from '../object-runtime.js';
5
+ import { FallbackCounts } from '../fallback-telemetry.js';
6
+ export interface CodegenError {
7
+ message: string;
8
+ line: number;
9
+ column: number;
10
+ /**
11
+ * #1921 — the compile-failure gate keys on this field, not on a magic
12
+ * `"Codegen error:"` message prefix.
13
+ *
14
+ * - `"error"` (the default for {@link reportError} / {@link reportErrorNoNode})
15
+ * fails the build (`success: false`).
16
+ * - `"warning"` is non-blocking and used by the IR-fallback channel for
17
+ * "we tried the IR path, it didn't fit, the legacy body still works" events.
18
+ * - `"degrade"` is a *deliberate* compile-with-fallback-value diagnostic: the
19
+ * expression compiled to a placeholder (stack-balancer hole, identity bind,
20
+ * etc.) and the build is intentionally allowed to succeed. Each degrade site
21
+ * must reference a tracking issue, mirroring the host-import allowlist
22
+ * discipline.
23
+ *
24
+ * An omitted severity is treated as `"error"` by the gate (see
25
+ * `isFatalCodegenDiagnostic` in src/compiler.ts) so that a forgotten
26
+ * classification fails loudly instead of silently degrading.
27
+ */
28
+ severity?: "error" | "warning" | "degrade";
29
+ }
30
+ /** Result returned by generateModule / generateMultiModule. */
31
+ export interface CodegenResult {
32
+ module: WasmModule;
33
+ errors: CodegenError[];
34
+ /**
35
+ * #2089 — silent-fallback telemetry counters captured during this codegen
36
+ * run (per class → per site → count). Surfaced so the gate
37
+ * (`scripts/check-codegen-fallbacks.ts`) can aggregate structured counts
38
+ * rather than parsing warning strings. Optional so existing callers that
39
+ * destructure `{ module, errors }` are unaffected.
40
+ */
41
+ fallbackCounts?: FallbackCounts;
42
+ }
43
+ /** Public options for backend code generation. */
44
+ export interface CodegenOptions {
45
+ /** Whether to generate source positions for source map */
46
+ sourceMap?: boolean;
47
+ /** Fast mode: i32 default numbers */
48
+ fast?: boolean;
49
+ /** Use WasmGC-native strings instead of wasm:js-string imports */
50
+ nativeStrings?: boolean;
51
+ /** #1588 PR-B: dual i8/i16 string storage (default false → byte-identical). */
52
+ utf8Storage?: boolean;
53
+ /** Test-only: emit `__test_str_from_externref` / `__test_str_to_externref` exports (#1187). */
54
+ testRuntime?: boolean;
55
+ /** WASI target: emit WASI imports (fd_write, proc_exit) instead of JS host imports */
56
+ wasi?: boolean;
57
+ /**
58
+ * #2524 / #2633 — route std-IO through a separately compiled, linkable
59
+ * `node:fs` shim instead of inlining the `wasi_snapshot_preview1.fd_read`/
60
+ * `fd_write` glue. When set (WASI only), the user module imports
61
+ * `readSync`/`writeSync` plus its linear memory from `node:fs` and carries NO
62
+ * `wasi_snapshot_preview1` import for the stream IO path; console.log /
63
+ * process.std*.write lower to `writeSync(1|2, …)`. `node-fs.wasm` implements
64
+ * the interface over WASI. The bespoke `js2wasm:node-process` shim was retired
65
+ * (#2633). Default off — the inline fd_read/fd_write path stays as fallback.
66
+ */
67
+ linkNodeShims?: boolean;
68
+ /** Standalone target (#1470): pure WasmGC, no JS host imports and no WASI
69
+ * runtime. Implies `nativeStrings: true` and refuses to emit any
70
+ * `wasm:js-string` namespace or `env::__concat_*` / `__extern_toString` /
71
+ * `__unbox_string` JS-host string imports. Used so the compiled module is
72
+ * runnable under pure-Wasm engines (wasmtime, wasmer) without a JS host. */
73
+ standalone?: boolean;
74
+ /**
75
+ * Experimental: route a narrow set of functions through the middle-end IR
76
+ * (see `src/ir/`). Defaults to **on** since #1131 (the front-end driver
77
+ * passes `experimentalIR !== false`); pass `false` to force the legacy
78
+ * direct-emission path (bit-by-bit divergence tests or emergency revert).
79
+ */
80
+ experimentalIR?: boolean;
81
+ /**
82
+ * #2089 — count silent codegen fallbacks via `reportSilentFallback` and, when
83
+ * set, surface each as a warning diagnostic. Used by
84
+ * `scripts/check-codegen-fallbacks.ts`. Default off (counts are still kept;
85
+ * only the warning emission is gated).
86
+ */
87
+ trackSilentFallbacks?: boolean;
88
+ /** Node builtin modules detected during import preprocessing (#1044) */
89
+ nodeBuiltins?: import('../../import-resolver.js').NodeBuiltinImport[];
90
+ /** Set of function names imported from node:fs (detected pre-preprocessing).
91
+ * Used by both the WASI fs syscall path (#1035) and the JS-host fs imports (#1491). */
92
+ wasiNodeFsFuncs?: Set<string>;
93
+ /** (#2657) Set of LOCAL names imported from `"wasi_snapshot_preview1"`
94
+ * (detected pre-preprocessing). The raw-WASI fd_read/fd_write passthrough
95
+ * binds these identifiers directly to the WASI import funcs — the most honest
96
+ * pure-WASI-P1 expression, no `node:fs` surface (loopdive/js2#389). */
97
+ wasiRawImports?: Set<string>;
98
+ /** (#2657) Set of LOCAL names imported from `"wasm:memory"` — js2wasm's inline
99
+ * linear-memory access intrinsics (`store32`/`load32`/`store8`/`load8`). These
100
+ * lower to a single WASM memory op (NOT imports); they let a raw-WASI module
101
+ * lay out its iovec + result slot without a GC roundtrip. Honestly namespaced
102
+ * away from `wasi_snapshot_preview1` (no host provides them). */
103
+ wasiMemAccessors?: Set<string>;
104
+ /** Allow `node:fs` JS-host imports for non-WASI targets (#1491). Default: false. */
105
+ allowFs?: boolean;
106
+ /**
107
+ * Enforce dual-mode discipline (#1524): when set, `addImport` rejects any
108
+ * JS-host `env` import that is not on the
109
+ * `src/codegen/host-import-allowlist.ts` baseline. WASI builds enable this
110
+ * by default unless `allowHostImports` is set. Set this directly via
111
+ * `--no-host-imports` on the CLI or `strictNoHostImports: true` in
112
+ * `CompileOptions`.
113
+ */
114
+ strictNoHostImports?: boolean;
115
+ /** JSX runtime import detected during preprocessing (#1540). */
116
+ jsxRuntime?: import('../../import-resolver.js').JsxRuntimeImport;
117
+ /**
118
+ * (#2119) Infer ES-module strictness (→ unmapped `arguments`) from a genuine
119
+ * top-level `import`/`export`. Default `true`. The test262 harness sets this
120
+ * `false` for script tests so its synthetic `export function test()` wrapper
121
+ * does not unmap sloppy (`noStrict`) arguments. See `CompileOptions`.
122
+ */
123
+ inferModuleStrictArguments?: boolean;
124
+ }
125
+ /** Info about an externally declared class. */
126
+ export interface ExternClassInfo {
127
+ importPrefix: string;
128
+ namespacePath: string[];
129
+ className: string;
130
+ constructorParams: ValType[];
131
+ methods: Map<string, {
132
+ params: ValType[];
133
+ results: ValType[];
134
+ requiredParams: number;
135
+ }>;
136
+ properties: Map<string, {
137
+ type: ValType;
138
+ readonly: boolean;
139
+ }>;
140
+ }
141
+ /** Info about an optional parameter. */
142
+ export interface OptionalParamInfo {
143
+ index: number;
144
+ type: ValType;
145
+ /** If the default is a compile-time constant, its value is stored here. */
146
+ constantDefault?: {
147
+ kind: "f64";
148
+ value: number;
149
+ } | {
150
+ kind: "i32";
151
+ value: number;
152
+ };
153
+ /** True when the default is a non-constant expression (needs callee-side evaluation). */
154
+ hasExpressionDefault?: boolean;
155
+ }
156
+ /** Info about a rest parameter. */
157
+ export interface RestParamInfo {
158
+ /** Index of the rest parameter in the original TS signature */
159
+ restIndex: number;
160
+ /** Element type of the rest array (e.g. f64 for number[]) */
161
+ elemType: ValType;
162
+ /** Array type index in the module types */
163
+ arrayTypeIdx: number;
164
+ /** Vec struct type index wrapping the array */
165
+ vecTypeIdx: number;
166
+ }
167
+ /** Metadata for a function eligible for call-site inlining. */
168
+ export interface InlinableFunctionInfo {
169
+ /** The compiled body instructions (shallow copy, safe to re-emit) */
170
+ body: Instr[];
171
+ /** Number of parameters */
172
+ paramCount: number;
173
+ /** Parameter types (for allocating temp locals) */
174
+ paramTypes: ValType[];
175
+ /** Return type (null = void) */
176
+ returnType: ValType | null;
177
+ }
178
+ /** Metadata for a closure stored in a local variable. */
179
+ export interface ClosureInfo {
180
+ /** Type index of the closure struct */
181
+ structTypeIdx: number;
182
+ /** Type index of the inner function type (for call_ref) */
183
+ funcTypeIdx: number;
184
+ /** Return type of the closure */
185
+ returnType: ValType | null;
186
+ /** Parameter types of the closure (excluding the closure struct self param) */
187
+ paramTypes: ValType[];
188
+ }
189
+ /** Metadata for a generator lowered to an in-module WasmGC state machine (#680). */
190
+ export interface NativeGeneratorInfo {
191
+ /** Source-level generator function name. */
192
+ functionName: string;
193
+ /**
194
+ * Original declaration; used to emit the resume function lazily. (#2571) A
195
+ * class / object-literal generator method is a `ts.MethodDeclaration`; it
196
+ * shares `.body` / `.parameters` / `.asteriskToken` with FunctionDeclaration,
197
+ * and the native lowering treats an instance method's `this` as a synthetic
198
+ * leading param (see `registerNativeGenerator`).
199
+ */
200
+ decl: ts.FunctionDeclaration | ts.MethodDeclaration;
201
+ /**
202
+ * (#2571) When `decl` is a non-static instance generator METHOD, the receiver
203
+ * is threaded as a synthetic leading param named `"this"` (state field
204
+ * `param_this`). `synthesizedThis` records that the param model has one extra
205
+ * leading entry beyond `decl.parameters` so the factory reads `local.get 0`
206
+ * (the `this` wasm param) into `param_this`. Free functions / static methods
207
+ * leave this `false` (no synthetic param) — byte-identical to pre-#2571.
208
+ */
209
+ synthesizedThis?: boolean;
210
+ /** Per-generator state struct type index. */
211
+ stateTypeIdx: number;
212
+ /** Shared IteratorResult-like struct type index. */
213
+ resultTypeIdx: number;
214
+ /** Absolute function index for the generated resume function, once emitted. */
215
+ resumeFuncIdx?: number;
216
+ /** Parameter names copied into the state struct at construction time. */
217
+ paramNames: string[];
218
+ /** Parameter value types copied into the state struct at construction time. */
219
+ paramTypes: ValType[];
220
+ /** Field index where captured params start in the state struct. */
221
+ paramFieldOffset: number;
222
+ /** Field index for the value passed to `.next(value)`. */
223
+ sentFieldIdx: number;
224
+ /** Field index for resume mode: 0 = next, 1 = return. */
225
+ modeFieldIdx: number;
226
+ /** Field index for the value passed to `.return(value)`. */
227
+ abruptFieldIdx: number;
228
+ /** Function-local names spilled into the state struct across suspensions. */
229
+ spillNames: string[];
230
+ /** Field index where spilled locals start in the state struct. */
231
+ spillFieldOffset: number;
232
+ /** Number of top-level yield suspension points. */
233
+ yieldCount: number;
234
+ /** Terminal state value. */
235
+ doneState: number;
236
+ /**
237
+ * (#2171) ValType of the generator's yielded values. `{kind:"f64"}` for the
238
+ * numeric path (default); the native-string ref for a generator whose yields
239
+ * are all strings. The result struct's `value` field and the for-of / .next()
240
+ * extraction read this. Mixed / object yields are not yet supported (the plan
241
+ * bails before a generator with disagreeing yield types is registered).
242
+ */
243
+ elemValType: ValType;
244
+ /**
245
+ * (#2170) `yield*` delegation slots, in source `siteIndex` order. Each slot is
246
+ * a mutable `ref null $InnerState` field in the state struct that persists the
247
+ * inner generator's state across the outer generator's host re-entries.
248
+ * `innerName` resolves to the inner's `NativeGeneratorInfo` at emit time.
249
+ */
250
+ delegationSlots?: {
251
+ fieldIdx: number;
252
+ innerName: string;
253
+ }[];
254
+ }
255
+ export type NullishExclusion = "null" | "undefined" | "nullish";
256
+ export interface NullGuardFact {
257
+ varName: string;
258
+ narrowedBranch: "then" | "else";
259
+ excludes: NullishExclusion;
260
+ provesNonNull: boolean;
261
+ }
262
+ /**
263
+ * #2682: a recognised canonical string-read loop. `dataLocal` holds the
264
+ * (non-null) `ref $__str_data` i16 array of the once-flattened receiver and
265
+ * `offLocal` its i32 byte offset; `recvName`/`indexName` are the loop-invariant
266
+ * receiver and the in-bounds-proven induction variable. See
267
+ * `FunctionContext.hoistedCharReads`.
268
+ */
269
+ export interface HoistedCharRead {
270
+ recvName: string;
271
+ indexName: string;
272
+ dataLocal: number;
273
+ offLocal: number;
274
+ }
275
+ /** Per-function context. */
276
+ export interface FunctionContext {
277
+ /** Function name */
278
+ name: string;
279
+ /** Parameters (these are the first N locals) */
280
+ params: {
281
+ name: string;
282
+ type: ValType;
283
+ }[];
284
+ /** Additional locals declared in the body */
285
+ locals: LocalDef[];
286
+ /** All local names → index (params first, then locals) */
287
+ localMap: Map<string, number>;
288
+ /** Return type */
289
+ returnType: ValType | null;
290
+ /** Accumulated body instructions */
291
+ body: Instr[];
292
+ /** Block depth for br labels */
293
+ blockDepth: number;
294
+ /** Break label depth stack */
295
+ breakStack: number[];
296
+ /** Continue label depth stack */
297
+ continueStack: number[];
298
+ /** Map from label name to break/continue stack indices for labeled break/continue */
299
+ labelMap: Map<string, {
300
+ breakIdx: number;
301
+ continueIdx: number;
302
+ }>;
303
+ /** Depth for `return` inside generator body -- adjusted by loop/block nesting */
304
+ generatorReturnDepth?: number;
305
+ /** Map from variable name → ref cell info (for mutable closure captures) */
306
+ boxedCaptures?: Map<string, {
307
+ refCellTypeIdx: number;
308
+ valType: ValType;
309
+ }>;
310
+ /** Whether this function is a class constructor (for new.target support) */
311
+ isConstructor?: boolean;
312
+ /** Whether this constructor belongs to a class declared with `extends`. Spec §10.2.1.3
313
+ * step 13c requires a derived constructor that returns a non-object, non-undefined
314
+ * value to throw TypeError instead of silently coercing and null-dereffing. */
315
+ isDerivedConstructor?: boolean;
316
+ /** Whether this function is a generator (function*) */
317
+ isGenerator?: boolean;
318
+ /**
319
+ * (#2007/#1448) Set once a closure-allocating array method
320
+ * (`map`/`filter`/`flatMap`/`forEach`/`reduce`/`find`/`sort`) has been
321
+ * lowered in this function body. The standalone vec-concat join fast-path
322
+ * (`tryCompileNativeVecConcatOperand`) reads it: once such a method has
323
+ * emitted its closure setup, a LATE `number_toString` registration triggered
324
+ * by the join would `addUnionImports`-shift and corrupt the already-emitted
325
+ * closure code (a pre-existing hazard `a.join(",")` also exhibits). So the
326
+ * join falls back to `$__any_to_string` ("[object Object]", the baseline
327
+ * behaviour) when this flag is set — no regression.
328
+ */
329
+ emittedClosureArrayMethod?: boolean;
330
+ /**
331
+ * (#1042) True while {@link emitAsyncStateMachine} is driving an async
332
+ * function body through the CPS transform. Read by the `AwaitExpression`
333
+ * dispatcher in expressions.ts to decide between the legacy pass-through and
334
+ * a continuation split. Inert in #1042 PR1 (the activation hook is unwired
335
+ * and `ASYNC_CPS_ENABLED` is false), so it stays undefined/false and the
336
+ * emitted Wasm is byte-identical.
337
+ */
338
+ asyncCpsActive?: boolean;
339
+ /** Set of variable names that are read-only bindings (e.g. named function expression name) */
340
+ readOnlyBindings?: Set<string>;
341
+ /** Set of variable names that are const bindings — assignment throws TypeError at runtime */
342
+ constBindings?: Set<string>;
343
+ /** Stack of saved body arrays for addUnionImports index shifting */
344
+ savedBodies: Instr[][];
345
+ /**
346
+ * Raw `__argc` cached at function entry for parameter defaults. Defaults need
347
+ * to clear the global before initializer expressions can make nested calls;
348
+ * `arguments` construction reuses this local when both features are present.
349
+ */
350
+ argcCachedLocal?: number;
351
+ /** Set of function names successfully hoisted during THIS function body's hoisting pass */
352
+ hoistedFuncs?: Set<string>;
353
+ /** Enclosing class name — propagated to closures for super keyword resolution */
354
+ enclosingClassName?: string;
355
+ /**
356
+ * (#1395) True when compiling a static class member context (static field
357
+ * initializer, static method body, or a closure spawned from inside one).
358
+ * In a static context, `this` resolves to the class constructor object
359
+ * (the `__class_<Name>` singleton), NOT to a per-instance struct. Per
360
+ * ECMA-262 §15.7.1.1 step 5.b, DefineField is called with the class as
361
+ * receiver for static fields, so `this` inside `static f = () => this`
362
+ * is the class itself. Propagated through closure spawning the same way
363
+ * `enclosingClassName` is.
364
+ */
365
+ isStaticContext?: boolean;
366
+ /**
367
+ * (#1636-S1) True only for closure bodies that can be dispatched from the
368
+ * host via `__call_fn_method_N` (lifted free closures and anonymous
369
+ * callbacks passed to e.g. `JSON.stringify`'s replacer / a value's
370
+ * `toJSON`). Those dispatchers install the host-supplied receiver into the
371
+ * `__current_this` module global before the inner `call_ref`, so the
372
+ * closure's `this` must read that global when it has no other binding.
373
+ *
374
+ * Named function declarations, methods, and constructors are NOT dispatched
375
+ * through `__call_fn_method_N` — they are called directly via `call $f`,
376
+ * where `__current_this` is never installed for them. They must keep the
377
+ * spec-correct `undefined` (strict) / globalObject (sloppy) `this`, so they
378
+ * must NOT read `__current_this`. The flag gates the fallback to exactly the
379
+ * bodies that can observe a host-installed receiver. Without it, every
380
+ * `this` in a free function in any module that emits a closure regressed to
381
+ * the global's `ref.null.extern` initial value (#1636-S1 regression: 171
382
+ * test262 failures in `function-code/10.4.3-1-*` and `Array/prototype/*`).
383
+ */
384
+ readsCurrentThis?: boolean;
385
+ /** Set of variable names known to be non-null in the current scope (type narrowing) */
386
+ narrowedNonNull?: Set<string>;
387
+ /** Const boolean aliases for null guards, e.g. `const ok = x !== null`. */
388
+ nullGuardAliases?: Map<string, NullGuardFact>;
389
+ /** Variables narrowed through a const boolean null-guard alias in the active branch. */
390
+ aliasedNullGuardNonNull?: Set<string>;
391
+ /**
392
+ * Set of "arrayVar:indexVar" keys where bounds checks can be elided.
393
+ * Populated when a for-loop condition guarantees indexVar < arrayVar.length.
394
+ */
395
+ safeIndexedArrays?: Set<string>;
396
+ /**
397
+ * #2682: per-loop proofs for the canonical string-read hot loop
398
+ * `for (let i = 0; i < recv.length; i++) … recv.charCodeAt(i) …`.
399
+ *
400
+ * Keyed by the (loop-invariant) string receiver identifier name. When an
401
+ * entry is present, the loop has been recognised by
402
+ * `detectCanonicalCharReadLoop` (statements/loops.ts): the receiver was
403
+ * flattened ONCE before the loop and its `.data`/`.off` descriptor hoisted
404
+ * into the listed locals, and `i` is PROVEN in-bounds (`0 <= i < len`) at
405
+ * every body point (init >= 0, strict `<`, monotonic step, `i`/`recv` not
406
+ * mutated, no capturing closure). `recv.charCodeAt(i)` reads then lower to a
407
+ * direct i32 `array.get_u(dataLocal, offLocal + i)` with NO per-call flatten,
408
+ * NO struct.get reload, and NO OOB/NaN branch (the branch is dead under the
409
+ * proof — byte-identical to the guarded read). Native-string mode only.
410
+ * Scoped save/restore around the loop body exactly like `safeIndexedArrays`.
411
+ */
412
+ hoistedCharReads?: Map<string, HoistedCharRead>;
413
+ /**
414
+ * #1120: Set of let/const locals whose lifecycle is fully constrained
415
+ * to int32 by explicit `| 0` (or other bitwise) coercion. These get
416
+ * allocated as i32 instead of f64, and the binary-op layer can use
417
+ * native i32 arithmetic for `(a + b) | 0`-style updates without the
418
+ * heavy f64 -> ToInt32 -> f64 round-trip.
419
+ */
420
+ i32CoercedLocals?: Set<string>;
421
+ /**
422
+ * #1197: Set of let/const locals declared as `number[]` whose element
423
+ * storage can safely lower to `i32` instead of `f64` (every write site is
424
+ * provably i32-shaped, every use is a whitelisted access pattern, no
425
+ * closure capture). The variable-declaration codegen consults this set
426
+ * to pick the `__vec_i32` vec type at allocation time.
427
+ */
428
+ i32SpecializedArrays?: Set<string>;
429
+ /**
430
+ * Free list for temporary locals, keyed by ValType key string.
431
+ * Used by allocTempLocal/releaseTempLocal to reuse locals of the same type.
432
+ */
433
+ tempFreeList?: Map<string, number[]>;
434
+ /**
435
+ * Stack of statically-proven `with` scopes (#1387). Each entry is a closed
436
+ * object-literal target compiled into a local. Identifier lowering consults
437
+ * this stack innermost-first and rewrites proven own-property bindings to
438
+ * direct struct field access.
439
+ */
440
+ withScopes?: ({
441
+ kind: "static";
442
+ localIdx: number;
443
+ structTypeIdx: number;
444
+ fields: FieldDef[];
445
+ blockedNames: Set<string>;
446
+ } | {
447
+ kind: "dynamic";
448
+ localIdx: number;
449
+ blockedNames: Set<string>;
450
+ })[];
451
+ /** Map from let/const local variable name → local index of its i32 TDZ flag (0 = uninitialized) */
452
+ tdzFlagLocals?: Map<string, number>;
453
+ /**
454
+ * (#2200 Annex B B.3.3 Phase 1) Block-nested `function F` declarations whose
455
+ * web-compat outer var-binding is *cancelled* by an intervening lexical
456
+ * (`let`/`const`/class) shadow or a same-named parameter. Maps the function
457
+ * name → the source-position range(s) of the block(s) that declare it. A read
458
+ * of `F` OUTSIDE every such block must NOT resolve to the block-local function
459
+ * (it has no outer binding) and instead throws ReferenceError; a read INSIDE
460
+ * the declaring block still resolves normally. Normally empty — the read-site
461
+ * guard in `compileIdentifier` is gated on `.has(name)`, so non-Annex-B
462
+ * modules stay byte-identical.
463
+ */
464
+ annexBCancelled?: Map<string, Array<{
465
+ start: number;
466
+ end: number;
467
+ }>>;
468
+ /**
469
+ * (#2200 Annex B B.3.3 Phase 2) Block-nested `function F` declarations that ARE
470
+ * eligible for the web-compat outer var-binding (no cancelling shadow/param).
471
+ * The outer binding is pre-allocated as a TDZ var (`localMap[F]` + a
472
+ * `tdzFlagLocals[F]` flag, zero-init = uninitialised); it is assigned the
473
+ * function value + flag←1 at the declaration's textual position (so it only
474
+ * initialises when control reaches the block). Membership gates the
475
+ * declaration-site init and the `typeof F` runtime-flag branch; normally empty,
476
+ * so non-Annex-B function decls are byte-identical.
477
+ */
478
+ annexBOuterBindings?: Set<string>;
479
+ /**
480
+ * For TDZ flag locals that have been boxed in an i32 ref cell so that
481
+ * mutations propagate to closures that captured the flag (#1177).
482
+ *
483
+ * Each entry records the ref-cell struct type idx and the local index of
484
+ * the ref-cell ref. Once a name is in this map, ALL set/get of its TDZ
485
+ * flag must go through `struct.get` / `struct.set` on the ref cell —
486
+ * `emitLocalTdzCheck` and `emitLocalTdzInit` detect this map before
487
+ * falling back to raw i32 local access.
488
+ *
489
+ * Note: when an entry exists here, `tdzFlagLocals[name]` continues to
490
+ * point at the SAME local index (the boxed ref-cell ref local). We
491
+ * preserve the old map so call-site checks (calls.ts) keep firing.
492
+ */
493
+ boxedTdzFlags?: Map<string, {
494
+ refCellTypeIdx: number;
495
+ localIdx: number;
496
+ }>;
497
+ /**
498
+ * Stack of catch rethrow info. Each entry tracks a catch variable name and the
499
+ * current depth (number of block-like structures) from the catch boundary.
500
+ */
501
+ catchRethrowStack?: {
502
+ varName: string;
503
+ depth: number;
504
+ }[];
505
+ /**
506
+ * Stack of pending finally blocks. When a return/break/continue exits a try
507
+ * block that has a finally clause, the finally instructions must be inlined
508
+ * before the control-flow transfer.
509
+ */
510
+ finallyStack?: {
511
+ cloneFinally: () => Instr[];
512
+ breakStackLen: number;
513
+ continueStackLen: number;
514
+ /**
515
+ * Clone the finally body and bump every `br`/`br_if`/`br_table` in it that
516
+ * targets a label OUTSIDE the finally body by `extraDepth`. The pre-compiled
517
+ * finally was lowered at the try-frame depth (+1); inlining it at an
518
+ * abrupt-completion site nested deeper than the try frame (inside an
519
+ * `if`/`switch`/inner-`try` within the try) requires bumping those
520
+ * outer-targeting branches by the extra nesting delta. (#2061)
521
+ */
522
+ cloneFinallyAtDepth: (extraDepth: number) => Instr[];
523
+ /**
524
+ * Snapshot of `breakStack` taken when this entry was pushed (i.e. at the
525
+ * try-frame depth). At an inline site the nesting delta is
526
+ * `current breakStack value − this snapshot value` for any outer label
527
+ * (every label op bumps all outer entries uniformly, so the delta is the
528
+ * same across entries). (#2061)
529
+ */
530
+ breakDepthBaseline: number[];
531
+ /** Snapshot of `continueStack` at push time — see `breakDepthBaseline`. (#2061) */
532
+ continueDepthBaseline: number[];
533
+ }[];
534
+ /**
535
+ * Number of enclosing `try` blocks WITH a catch clause currently being
536
+ * compiled. Wasm `return_call` replaces the caller frame, so a callee's
537
+ * throw would unwind past the enclosing handler — the tail-call rewrite
538
+ * must be suppressed while this is > 0, exactly like `finallyStack`
539
+ * suppresses it for pending finally blocks. (#1972)
540
+ */
541
+ tryCatchDepth?: number;
542
+ /**
543
+ * Pending writeback instructions for mutable callback captures (#859).
544
+ */
545
+ pendingCallbackWritebacks?: Instr[];
546
+ /**
547
+ * Persistent writeback instructions for getter/setter callbacks (#929).
548
+ * Unlike pendingCallbackWritebacks (one-shot), these are re-emitted after
549
+ * every call expression so that mutations from deferred callback invocations
550
+ * (e.g. Object.defineProperty getter called later by Object.defineProperties)
551
+ * are reflected in the outer scope's local variables.
552
+ */
553
+ persistentCallbackWritebacks?: Instr[];
554
+ /**
555
+ * Mapped arguments info for non-strict functions with simple parameters (#849).
556
+ */
557
+ mappedArgsInfo?: {
558
+ argsLocalIdx: number;
559
+ arrTypeIdx: number;
560
+ vecTypeIdx: number;
561
+ paramCount: number;
562
+ paramOffset: number;
563
+ paramTypes: ValType[];
564
+ /**
565
+ * Argument indices whose param↔arguments mapping has been severed at
566
+ * compile time (#1511). Per ECMA-262 §10.4.4.2, a `defineProperty` that
567
+ * makes a mapped slot non-writable (or turns it into an accessor) or a
568
+ * `delete arguments[i]` removes the link: later parameter writes must no
569
+ * longer reflect into `arguments[i]` and vice-versa. The mapped-sync
570
+ * emitters consult this set and skip severed indices. Populated lazily
571
+ * during body codegen — order matters, since the emitters read it live.
572
+ */
573
+ unmappedIndices?: Set<number>;
574
+ /**
575
+ * Argument indices made non-configurable via a statically-resolvable
576
+ * `Object.defineProperty(arguments, "<i>", { configurable: false })`
577
+ * (#2667). Per ECMA-262 §10.4.4.5 + OrdinaryDelete, `delete arguments[i]`
578
+ * on a non-configurable index must return `false` and leave the property
579
+ * (and its param mapping) intact. The delete emitter consults this set so
580
+ * the statically-known case reports the spec-correct result without a
581
+ * runtime descriptor-sidecar round-trip. Populated lazily during body
582
+ * codegen; read live, so codegen order matters.
583
+ */
584
+ nonConfigurableIndices?: Set<number>;
585
+ /**
586
+ * Argument indices made non-writable via a statically-resolvable
587
+ * `Object.defineProperty(arguments, "<i>", { writable: false })` (#2667).
588
+ * Per ECMA-262 §10.4.4.2, a non-writable data property rejects later
589
+ * `arguments[i] = x` writes (and the write-back into the param). The
590
+ * element-assignment emitter consults this set to drop such writes.
591
+ * (Setting `writable:false` also severs the param↔arguments map, so the
592
+ * index is additionally added to `unmappedIndices`.)
593
+ */
594
+ nonWritableIndices?: Set<number>;
595
+ };
596
+ /**
597
+ * #1210: bindings detected as `let s = ""; for (...) s += <expr>` builders
598
+ * whose storage should be rewritten to a doubling i16-array buffer at
599
+ * compile time. Populated by `detectStringBuilders` during the
600
+ * function-body pre-scan, BEFORE `hoistLetConstWithTdz` runs (so the
601
+ * hoist pass can skip pre-allocating these decls' locals).
602
+ */
603
+ pendingStringBuilders?: Set<ts.VariableDeclaration>;
604
+ /**
605
+ * #1761: presize info for those `pendingStringBuilders` whose final length
606
+ * is a provably runtime-known linear function of a loop bound. Keyed by the
607
+ * same declaration node. When present at the init site, the buffer is
608
+ * allocated once at `bound * unitsPerIter` and the append sites drop the
609
+ * per-append cap-check. Populated by `detectStringBuilders` (presize out-param).
610
+ */
611
+ stringBuilderPresize?: Map<ts.VariableDeclaration, {
612
+ boundExpr: ts.Expression;
613
+ unitsPerIter: number;
614
+ }>;
615
+ /**
616
+ * #1210: live string-builder bindings keyed by binding name. While
617
+ * present, `s += <expr>` routes to `compileStringBuilderAppend`
618
+ * (in-place buffer write), and identifier reads materialize a fresh
619
+ * `$NativeString` view of the current buffer state via
620
+ * `emitStringBuilderRead`.
621
+ */
622
+ stringBuilders?: Map<string, {
623
+ bufLocalIdx: number;
624
+ lenLocalIdx: number;
625
+ capLocalIdx: number;
626
+ materializedLocalIdx: number;
627
+ presized?: boolean;
628
+ }>;
629
+ /**
630
+ * #1886 Slice B — live linear-backed `Uint8Array` buffers in this function. A
631
+ * buffer proven linear-safe by the #1886 analysis
632
+ * (`ctx.linearUint8.safeBindings`) is represented as a `(ptr, len)` pair of
633
+ * i32 locals instead of a GC vec, so `buf[i]`, `buf.length`, and
634
+ * `process.std*.{read,write}(buf)` operate on linear memory with zero
635
+ * GC↔linear copies. Absent entry ⇒ the binding uses the existing GC-vec path
636
+ * unchanged.
637
+ *
638
+ * #2045: keyed by the binding's `ts.Symbol`, NOT by identifier text. A
639
+ * name-keyed registry was scope-blind — a linear param `buf` plus an
640
+ * inner-block `const buf = new Uint8Array(...)` (a distinct symbol with the
641
+ * same name) collided, so element access addressed the wrong buffer in both
642
+ * shadowing directions (silent corruption). Symbol identity is scope-correct.
643
+ */
644
+ linearU8Buffers?: Map<ts.Symbol, {
645
+ ptrLocalIdx: number;
646
+ lenLocalIdx: number;
647
+ }>;
648
+ /** #1886 — function-entry arena mark for rewinding short-lived linear-U8 locals. */
649
+ linearU8ArenaMarkLocalIdx?: number;
650
+ /**
651
+ * #2660 PART-1 — the WasmGC struct name (`__fnctor_<Name>` / class-struct key
652
+ * in `ctx.structMap`) that a lifted method's `this` receiver resolves to, when
653
+ * statically known. Populated by the #2681 syntactic prototype-alias resolver
654
+ * (`resolveLiftedMethodThisStruct`, owned by the PART-2 dispatch slice) when a
655
+ * function is lowered as a `Class.prototype.m = function(){}` (or aliased
656
+ * `var pp = Class.prototype; pp.m = …`) method, so the dynamic `this.<field>`
657
+ * read/write/compound dispatch can pin to that one struct instead of the
658
+ * open-scan `findAlternateStructsForField`.
659
+ *
660
+ * **Read by `resolveReceiverStruct` case (1)** (the analysis-layer provider in
661
+ * `fnctor-escape-gate.ts`). **INERT in PART-1**: this slice only DECLARES the
662
+ * field; nothing in PART-1 sets it and `resolveReceiverStruct` is not yet
663
+ * called by any lowering, so emitted Wasm is byte-identical. PART-2 wires the
664
+ * setter + the consuming read/write/compound emitters.
665
+ */
666
+ thisStructName?: string;
667
+ }
668
+ /** Context shared across all codegen. */
669
+ export interface CodegenContext {
670
+ mod: WasmModule;
671
+ checker: ts.TypeChecker;
672
+ /** Map from function name to its absolute index (imports + locals) */
673
+ funcMap: Map<string, number>;
674
+ /** Map from struct/interface name to type index */
675
+ structMap: Map<string, number>;
676
+ /** Reverse map from type index to struct/interface name (O(1) reverse lookup) */
677
+ typeIdxToStructName: Map<number, string>;
678
+ /** Map from struct name to field info */
679
+ structFields: Map<string, FieldDef[]>;
680
+ /** Number of imported functions */
681
+ numImportFuncs: number;
682
+ /** wasm:js-string import indices — separate from funcMap to prevent
683
+ * user-defined functions from shadowing them (#1072). */
684
+ jsStringImports: Map<string, number>;
685
+ /** Current function context (set during function compilation) */
686
+ currentFunc: FunctionContext | null;
687
+ /** Stack of parent function contexts saved during nested closure compilation. */
688
+ funcStack: FunctionContext[];
689
+ /** Errors accumulated during codegen */
690
+ errors: CodegenError[];
691
+ /**
692
+ * #2089 — silent-fallback telemetry counters (per class → per site → count).
693
+ * Populated by `reportSilentFallback` (fallback-telemetry.ts) at instrumented
694
+ * fallback sites; aggregated by `scripts/check-codegen-fallbacks.ts` into the
695
+ * baseline. Phase 0 is pure telemetry — no behavior depends on these counts.
696
+ */
697
+ fallbackCounts: FallbackCounts;
698
+ /**
699
+ * #2089 — when true, every `reportSilentFallback` also pushes a warning
700
+ * diagnostic (in addition to counting). Off by default; the gate script and
701
+ * `JS2WASM_LOG_CODEGEN_FALLBACKS=1` turn it on.
702
+ */
703
+ trackSilentFallbacks?: boolean;
704
+ /** (#2119) Infer module-strictness (→ unmapped arguments) from a genuine
705
+ * top-level import/export. Default true; test262 script tests pass false. */
706
+ inferModuleStrictArguments?: boolean;
707
+ /**
708
+ * #1923 — captured IR post-claim demotions (build/verify/lower/backend-
709
+ * legality failures on a function the selector claimed, which fall back to
710
+ * legacy through the warning channel). Always collected (cheap), mirroring
711
+ * `fallbackCounts`; surfaced on `CompileResult.irPostClaimErrors` for the
712
+ * ratchet gate. Each entry carries the IR integration error's `kind` and the
713
+ * function/message.
714
+ */
715
+ irPostClaimErrors: {
716
+ kind: string;
717
+ func: string;
718
+ message: string;
719
+ }[];
720
+ /** Last AST node with a valid source position — used as fallback for error reporting
721
+ * when the immediate node lacks source file context (synthetic/detached nodes). */
722
+ lastKnownNode: ts.Node | null;
723
+ /** Registry of external declared classes */
724
+ externClasses: Map<string, ExternClassInfo>;
725
+ /** #1238 — pseudo-extern-class registry for built-ins like String / Array
726
+ * that don't have host-import-backed constructors / methods. These exist
727
+ * purely as metadata for the IR's method-dispatch lookup
728
+ * (`resolveMethodDispatchTarget`). They are NOT consumed by
729
+ * `compileNewExpression`, `collectUsedExternImports`, the `__new_<name>`
730
+ * interceptor, or the `mod.externClasses` populator — keeping them out
731
+ * of `ctx.externClasses` ensures legacy code paths for `new Array(...)`
732
+ * / `new String(...)` are unchanged. Downstream slices (#1232, #1233)
733
+ * consult this map via `getPseudoExternClassInfo`. */
734
+ pseudoExternClasses: Map<string, ExternClassInfo>;
735
+ /** Optional parameter info per function */
736
+ funcOptionalParams: Map<string, OptionalParamInfo[]>;
737
+ /** Map from anonymous ts.Type → generated struct name */
738
+ anonTypeMap: Map<ts.Type, string>;
739
+ /** Counter for generating anonymous struct names */
740
+ anonTypeCounter: number;
741
+ /** Map from string literal value → import func name */
742
+ stringLiteralMap: Map<string, string>;
743
+ /** Map from import name → string literal value (for .d.ts comments) */
744
+ stringLiteralValues: Map<string, string>;
745
+ /** Counter for string literal imports */
746
+ stringLiteralCounter: number;
747
+ /**
748
+ * #1463 — Source text per function declaration, keyed by function name.
749
+ * Populated in `collectDeclarations` from `stmt.getText(sourceFile)` so
750
+ * `Function.prototype.toString` can return spec-compliant source instead
751
+ * of the `function () { [native code] }` placeholder for identifier-typed
752
+ * receivers (`add.toString()` where `add` is a top-level declaration).
753
+ * Not populated for class methods, arrow functions, or expressions —
754
+ * those still fall back to the placeholder.
755
+ */
756
+ funcSourceText: Map<string, string>;
757
+ /** Map from string literal value → global import index */
758
+ stringGlobalMap: Map<string, number>;
759
+ /** Number of imported globals (string constants) */
760
+ numImportGlobals: number;
761
+ /** Whether wasm:js-string imports have been registered */
762
+ hasStringImports: boolean;
763
+ /** Map from "EnumName.Member" → numeric value */
764
+ enumValues: Map<string, number>;
765
+ /** Map from "EnumName.Member" → string value (for string enums) */
766
+ enumStringValues: Map<string, string>;
767
+ /** Map from element kind (e.g. "f64") → registered array type index */
768
+ arrayTypeMap: Map<string, number>;
769
+ /** Map from element kind (e.g. "f64") → registered vec struct type index */
770
+ vecTypeMap: Map<string, number>;
771
+ /**
772
+ * Per-export TypedArray classification populated during user-function
773
+ * declaration emission (#1700). Read by the runtime `wrapExports` to
774
+ * marshal `Uint8Array` params/results across the JS↔Wasm boundary.
775
+ */
776
+ exportSignatures: Map<string, import('../../ir/types.js').ExportSignature>;
777
+ /** Map from className → parent className (for inheritance chain walk) */
778
+ externClassParent: Map<string, string>;
779
+ /** Map from global name (e.g. "document") → import info */
780
+ declaredGlobals: Map<string, {
781
+ type: ValType;
782
+ funcIdx: number;
783
+ }>;
784
+ /** Counter for generated callback functions (__cb_0, __cb_1, ...) */
785
+ callbackCounter: number;
786
+ /** Map from captured variable name → global index in mod.globals */
787
+ capturedGlobals: Map<string, number>;
788
+ /** Captured globals whose type was widened from ref to ref_null for null init */
789
+ capturedGlobalsWidened: Set<string>;
790
+ /** Set of class names (local classes compiled to Wasm GC structs) */
791
+ classSet: Set<string>;
792
+ /**
793
+ * (#2023) `new.target` support. When the program references `new.target`
794
+ * anywhere, a single mutable i32 module global holds the class-id of the
795
+ * class named at the *outermost* `new` site (set/restored around each `new`
796
+ * call; `super()` deliberately leaves it untouched so it reflects the
797
+ * derived-most constructor). `classNewTargetIds` assigns each local class a
798
+ * stable 1-based i32 id so `new.target === SomeClass` lowers to an i32
799
+ * compare against this global. `newTargetGlobalIdx` is the global's index
800
+ * (undefined until allocated). Gated on `usesNewTarget` so programs without
801
+ * `new.target` emit none of this machinery.
802
+ */
803
+ usesNewTarget: boolean;
804
+ newTargetGlobalIdx: number | undefined;
805
+ classNewTargetIds: Map<string, number>;
806
+ /**
807
+ * (#2001 S1) Sparse-array hole support. Set by the `scanForArrayHoles`
808
+ * pre-scan when the program contains any array-literal elision
809
+ * (`OmittedExpression`). Gates the `$Hole → undefined` read-boundary guard at
810
+ * every externref-element vec read / join site, so a hole-bearing literal in
811
+ * one function and a `a[i]` read in another agree regardless of compilation
812
+ * order. Clear — the common case — keeps every array read byte-identical.
813
+ */
814
+ usesArrayHoles: boolean;
815
+ /**
816
+ * (#2083) Set true the first time `getOrRegisterVecType` is asked for a vec
817
+ * type from a genuine usage site (an array literal, array method, for-of over
818
+ * an array, TypedArray, etc.) — i.e. the module materialises at least one
819
+ * array value that may cross the JS↔Wasm boundary. The two pre-registrations
820
+ * in `createCodegenContext` (`externref`/`f64`, baked in for type-index
821
+ * stability) are excluded via `suppressVecUsageFlag`, so this stays false for
822
+ * arith-/string-only modules with no arrays. Gates the host-glue vec exports
823
+ * (`__vec_len`/`__vec_get`/`__vec_push`/`__vec_pop`/`__vec_mut_supported`/
824
+ * `__is_vec`) so they no longer leak into every module (#2083). The host
825
+ * runtime guards every `exports.__vec_*` access with a `typeof === "function"`
826
+ * check, so their absence is safe.
827
+ */
828
+ usesVecValue: boolean;
829
+ /**
830
+ * (#2083) When true, `getOrRegisterVecType` does NOT flip `usesVecValue`.
831
+ * Set only for the duration of the two pre-registration calls in
832
+ * `createCodegenContext` (the `externref`/`f64` type-index-stability stubs),
833
+ * which are not real array usage.
834
+ */
835
+ suppressVecUsageFlag: boolean;
836
+ /**
837
+ * (#2001 S1) Type index of the `$Hole` zero-field sentinel struct, and the
838
+ * absolute index of the immutable `$__hole` singleton global. Registered
839
+ * lazily + once by `ensureHoleType` during body compilation (after class
840
+ * collection, per `project_type_index_shift_and_deadelim`). `-1` / `undefined`
841
+ * until first use; pruned by dead-elimination when no hole literal is stored.
842
+ */
843
+ holeTypeIdx: number;
844
+ holeGlobalIdx: number | undefined;
845
+ /**
846
+ * (#2580 M0) Value-rep dynamic-read substrate. Set true by a call site that
847
+ * needs the runtime property-presence read primitives (`__dyn_has` /
848
+ * `__dyn_get`) — e.g. M1's `any`-receiver `.length`. Gates
849
+ * `ensureDynReadHelpers`: when clear (the common case AND all of M0, which adds
850
+ * NO call sites), the helpers are never emitted, so a hole/dynamic-free module
851
+ * is byte-identical. The two helpers dispatch the #1852 boxed `$AnyValue`
852
+ * family by tag (0 null / 1 undefined / 2 i32 / 3 f64 / 4 bool / 5 string /
853
+ * 6 GC-ref → `$Object`/`$Vec`).
854
+ */
855
+ usesDynRead: boolean;
856
+ /** (#2580 M0) Idempotence latch for `ensureDynReadHelpers` (once per module). */
857
+ dynReadHelpersEmitted: boolean;
858
+ /** Classes that must throw TypeError at evaluation time */
859
+ classThrowsOnEval: Set<string>;
860
+ /**
861
+ * (#1983) Names of top-level user `function` declarations in the source. Used
862
+ * by `classMemberFuncKey` to detect when a synthetic class-member key
863
+ * (`${className}_${member}`) would collide with a user function of the same
864
+ * name (e.g. `class A { m() {} }` + `function A_m() {}`), so the class
865
+ * member's **funcMap** entry can take a collision-free key. Populated in
866
+ * `collectDeclarations` (runs before any class body compiles).
867
+ */
868
+ topLevelFunctionNames: Set<string>;
869
+ /** Map from "ClassName_methodName" → method info for local classes */
870
+ classMethodSet: Set<string>;
871
+ /** Classes inside function bodies whose body compilation is deferred */
872
+ deferredClassBodies: Set<string>;
873
+ /** Set of "ClassName_propName" for getter/setter accessor properties */
874
+ classAccessorSet: Set<string>;
875
+ /**
876
+ * (#1888 S5c) Set of "structName_propName" whose getter/setter is compiled as
877
+ * a host-free CLOSURE (capturing env, call_ref-invoked) rather than the bare
878
+ * `${struct}_get_${prop}(this)` fn. Populated by the C2 define-site when
879
+ * `S5C_STRUCT_ACCESSOR_CLOSURE` is on; the C3 read / C4 write sites dispatch
880
+ * through the per-(struct,prop) `$__acc_get/set_<struct>_<prop>` globals +
881
+ * the S5b `__call_accessor_get/set` drivers ONLY when this set has the key, so
882
+ * class-accessor emission (#459/#1680/#1681/#1605) stays on the proven bare-fn
883
+ * path. Maps the key → the get/set global indices.
884
+ */
885
+ structAccessorClosure: Map<string, {
886
+ getGlobal?: number;
887
+ setGlobal?: number;
888
+ }>;
889
+ /** Set of "ClassName_propName" for static getter/setter accessor properties */
890
+ staticAccessorSet: Set<string>;
891
+ /** Set of "ClassName_methodName" for static methods (no self param) */
892
+ staticMethodSet: Set<string>;
893
+ /** Map from "ClassName_propName" → global index for static properties */
894
+ staticProps: Map<string, number>;
895
+ /**
896
+ * (#1719 CPR — compiled prototype record) Captured prototype-member overrides.
897
+ *
898
+ * `Array.prototype[Symbol.iterator] = fn` / `Array.prototype.values = fn` have
899
+ * no compiled landing spot today and are silently dropped — the override is
900
+ * never observed (#1719 root cause). CPR captures such writes here. The OUTER
901
+ * key is a **proto-owner identity token** (today a builtin name, e.g.
902
+ * `"Array"`); the INNER key is the well-known member key (`"@@iterator"`,
903
+ * `"values"`). The value is the lifted override closure's funcref index plus
904
+ * the funcTypeIdx needed to `call_ref` it. Read sites (array destructuring,
905
+ * for-of, spread) consult this when the whole-program brand
906
+ * (`arrayIteratorMaybeOverridden`) is set and drive the stored closure as the
907
+ * value's `@@iterator` (§7.4.2 GetIterator) instead of the backing-store walk.
908
+ *
909
+ * The proto-owner key is typed as an open string TOKEN (not a narrow union) so
910
+ * it can later carry user-class / struct-type identities — probe-1 showed
911
+ * `C.prototype.m=` is dropped for user classes too — without rebuilding the
912
+ * table; the cluster (#1130/#1320) grafts on by widening the token. This is the
913
+ * prototype-OVERRIDE substrate, kept conceptually distinct from instance-level
914
+ * own-property descriptors (`_wasmStructAccessors` / #1629), which live on
915
+ * values, not prototypes.
916
+ */
917
+ protoOverrides: Map<string, Map<string, {
918
+ funcIdx: number;
919
+ funcTypeIdx: number;
920
+ globalIdx: number;
921
+ }>>;
922
+ /**
923
+ * (#1719 CPR read-drive) True once the in-Wasm
924
+ * `__drive_proto_iterator(thisVal: externref, closure: externref) -> externref`
925
+ * driver placeholder has been reserved (pushed + registered in `funcMap` under
926
+ * `"__drive_proto_iterator"`). The read-drive sites (array dstr / for-of /
927
+ * spread) are emitted during body compilation, BEFORE the post-processing
928
+ * phase that can see the fully-populated `closureInfoByTypeIdx` needed to
929
+ * dispatch the override closure. So the FIRST read-drive site pushes a
930
+ * placeholder function (fixing its append-position funcIdx) and registers it in
931
+ * `funcMap`; the body is filled in post-processing (calls the registered
932
+ * `__call_fn_method_0`). The placeholder is never reserved when the brand is
933
+ * clear, so override-free modules stay byte-identical. Storing the funcIdx in
934
+ * `funcMap` (not a raw number here) is load-bearing: `shiftLateImportIndices`
935
+ * patches both the `funcMap` entry and the emitted `call` by the same delta, so
936
+ * a late-import index shift never desyncs the reservation.
937
+ */
938
+ protoIteratorDriverReserved?: boolean;
939
+ /**
940
+ * (#1888 S5b accessor live get/set) Set when `ensureObjectRuntime` reserves the
941
+ * `__call_accessor_get` / `__call_accessor_set` driver placeholders so the
942
+ * `__extern_get` / `__extern_set` accessor arms can `call` them. The bodies are
943
+ * filled in post-processing by `fillAccessorDrivers` AFTER
944
+ * `emitClosureMethodCallExportN(0/1)` registers `__call_fn_method_0/1` — same
945
+ * reserve/fill funcIdx-authority pattern as `protoIteratorDriverReserved`
946
+ * (proto-override.ts). Never reserved when the object runtime is not emitted
947
+ * (non-standalone), so host/GC modules stay byte-identical.
948
+ */
949
+ accessorGetDriverReserved?: boolean;
950
+ accessorSetDriverReserved?: boolean;
951
+ /**
952
+ * (#2166 PR-D1) True once the standalone `JSON.parse(text, reviver)` codec
953
+ * reserved its `__call_reviver(holder, key, value) -> externref` driver
954
+ * funcIdx — filled in finalize to wrap `__call_fn_method_2`. Same reserve/fill
955
+ * funcIdx-authority pattern as the accessor drivers above.
956
+ */
957
+ reviverDriverReserved?: boolean;
958
+ /**
959
+ * (#2166 PR-D2) True once the standalone `JSON.stringify` codec reserved its
960
+ * `__call_to_json(value, method, key) -> externref` driver funcIdx — filled in
961
+ * finalize to wrap `__call_fn_method_1` (value bound as the `toJSON`
962
+ * receiver).
963
+ */
964
+ toJsonDriverReserved?: boolean;
965
+ /**
966
+ * (#2166 PR-D3) True once the standalone `JSON.stringify` codec reserved its
967
+ * `__call_replacer(holder, replacer, key, value) -> externref` driver funcIdx
968
+ * — filled in finalize to wrap `__call_fn_method_2` (holder bound as the
969
+ * replacer `this`, key+value the two replacer args).
970
+ */
971
+ replacerDriverReserved?: boolean;
972
+ /**
973
+ * (#1888 Slice 1) True once the standalone open-any method-dispatch bridge
974
+ * `__apply_closure(fn, recv, args) -> externref` has reserved its funcIdx via
975
+ * a placeholder function pushed during `ensureObjectRuntime` (registered in
976
+ * `funcMap` under `"__apply_closure"`). The bridge calls the
977
+ * `__call_fn_method_0..4` exports, which are only emitted at FINALIZE (after
978
+ * the full `closureInfoByTypeIdx` is known), so the placeholder body is filled
979
+ * by `fillApplyClosure` in post-processing — mirroring the
980
+ * `protoIteratorDriverReserved` reserve-then-fill pattern (#1719). Only set
981
+ * under `--target standalone`, so the GC/host path stays byte-identical.
982
+ */
983
+ applyClosureReserved?: boolean;
984
+ /**
985
+ * (#1100) Set when the standalone Proxy trap-dispatch runtime reserved its
986
+ * `__proxy_call_{get,set,has}` driver placeholders (in `ensureProxyRuntime`).
987
+ * Those drivers invoke the user trap closures through the `__call_fn_method_N`
988
+ * exports, which are only emitted at FINALIZE, so their bodies are filled by
989
+ * `fillProxyDispatch` in post-processing — same reserve-then-fill pattern as
990
+ * `applyClosureReserved` / the accessor drivers (#1719). Only set under
991
+ * `--target standalone`, so the GC/host path stays byte-identical.
992
+ */
993
+ proxyDispatchReserved?: boolean;
994
+ /**
995
+ * (#2151) Method names for which a closed-struct `__call_m_<name>` dispatcher
996
+ * was reserved at an any-receiver call site (standalone/wasi). The placeholder
997
+ * body is filled by `fillClosedMethodDispatch` at FINALIZE (after all
998
+ * object-literal struct types + their `<Struct>_<name>` methods are known),
999
+ * mirroring the `fillApplyClosure` reserve-then-fill pattern (#1719). Each
1000
+ * dispatcher does a `ref.test/ref.cast/call <Struct>_<name>` type-switch over
1001
+ * every closed struct that has the method (threading the struct as `this`),
1002
+ * falling through to the open-`$Object` `__extern_method_call` otherwise. Only
1003
+ * populated under `--target standalone || --target wasi`.
1004
+ */
1005
+ closedMethodDispatchNames?: Set<string>;
1006
+ /**
1007
+ * (#2151 Slice 4) Method names that need a VARARG closed-struct dispatcher
1008
+ * `__call_m_<name>_vararg(recv, args)` for a DYNAMIC-spread call `o.m(...xs)`
1009
+ * whose arity is unknown at compile time. Filled at FINALIZE by
1010
+ * `fillClosedMethodDispatch` (the vararg pass), sourcing each declared param
1011
+ * from `__extern_get_idx(args, i)` instead of fixed dispatcher params.
1012
+ */
1013
+ closedMethodDispatchVarargNames?: Set<string>;
1014
+ /**
1015
+ * (#2664) Property names that need a deferred-fill member-WRITE dispatcher
1016
+ * `__set_member_<name>(recv: externref, val: externref)`. The symmetric
1017
+ * struct.set write dispatch (#2659) was emitted INLINE at each `any`-receiver
1018
+ * `obj.<name> = v` write, freezing its struct-candidate set at the write's
1019
+ * compile time. A field-writing closure compiled BEFORE a later struct type
1020
+ * (e.g. acorn's `$__fnctor_Parser`, registered after the closure) only got the
1021
+ * earlier candidate's `ref.test` arm; the real instance failed it and the
1022
+ * write leaked to the `__extern_set` sidecar while reads used the slot —
1023
+ * non-termination (#2664). Routing the write through a reserved dispatcher
1024
+ * filled at FINALIZE (when the full struct-type table is known) gives every
1025
+ * write site the COMPLETE candidate set regardless of compile order. Filled by
1026
+ * `fillMemberSetDispatch`; populated in BOTH gc/host and standalone (the
1027
+ * dual-struct-type compile-order hazard is mode-independent).
1028
+ */
1029
+ memberSetDispatchNames?: Set<string>;
1030
+ /**
1031
+ * (#2674) Property names that need a deferred-fill member-READ dispatcher
1032
+ * `__get_member_<name>(recv: externref) -> externref` — the SYMMETRIC read-side
1033
+ * counterpart of `memberSetDispatchNames`. The member-READ multi-struct
1034
+ * dispatch (`findAlternateStructsForField` + `ref.test`/`struct.get` chain) was
1035
+ * also enumerated INLINE per read site, so a reader compiled before a later
1036
+ * struct type only got the earlier candidate's arm → stale `__extern_get`
1037
+ * `undefined` read on the real (later-type) instance, while #2664's deferred
1038
+ * write hit the slot → read/write divergence → non-termination (acorn 9th wall).
1039
+ * Routing the alternates fallback through a reserved dispatcher filled at
1040
+ * FINALIZE gives every read site the COMPLETE candidate set. Filled by
1041
+ * `fillMemberGetDispatch`; populated in BOTH gc/host and standalone.
1042
+ */
1043
+ memberGetDispatchNames?: Set<string>;
1044
+ /**
1045
+ * (#1904) True once the standalone `__extern_is_array(externref) -> i32`
1046
+ * helper placeholder has been emitted by the object runtime. Its body is
1047
+ * filled in post-processing after all Wasm array carrier types (`__vec_*`
1048
+ * plus `$ObjVec`) are known.
1049
+ */
1050
+ externIsArrayReserved?: boolean;
1051
+ /**
1052
+ * (#2190) True once `__extern_get_idx` is registered with its static
1053
+ * `$Object`/`$ObjVec` arms (standalone only). The per-element-kind
1054
+ * `__vec_<k>` dispatch arms are appended at FINALIZE by
1055
+ * `fillExternGetIdxVecArms`, after every `__vec_*` carrier type is known —
1056
+ * the same reserve/fill pattern as `externIsArrayReserved`. Without the
1057
+ * deferred fill, an array literal of an element kind compiled after
1058
+ * `ensureObjectRuntime` would have no indexing arm and `(arr as any)[i]`
1059
+ * would read back null/0 (sibling of the #2189 `.length` gap).
1060
+ */
1061
+ externGetIdxReserved?: boolean;
1062
+ /**
1063
+ * (#2358 #10) True once `__to_primitive` reserved the
1064
+ * `__array_to_primitive_string` placeholder. Filled by `fillArrayToPrimitive`
1065
+ * (array-to-primitive.ts) in post-processing, AFTER `__extern_length` /
1066
+ * `__extern_get_idx` are registered — `__to_primitive` is emitted before those
1067
+ * helpers, so the array-ToPrimitive join arm can only call a RESERVED funcIdx
1068
+ * (mirror of `externGetIdxReserved` / the accessor-driver reserve/fill). Lets
1069
+ * `Number([1])` / `"1,2" == [1,2]` / `1 + [2]` reduce a runtime `$Vec` to its
1070
+ * Array.prototype.toString (`join(",")`) host-free, standalone only.
1071
+ */
1072
+ arrayToPrimitiveReserved?: boolean;
1073
+ /**
1074
+ * (#2638) True once `__to_primitive` has reserved the `__class_to_primitive`
1075
+ * driver — standalone routing of a nominal CLASS-instance struct (neither
1076
+ * `$Object` nor `$Vec`) through the per-struct `__call_valueOf`/`__call_toString`
1077
+ * dispatchers per §7.1.1.1. Those dispatchers are emitted at FINALIZE (after
1078
+ * `__to_primitive`), so the driver body is filled by `fillClassToPrimitive`
1079
+ * post-`emitToPrimitiveMethodExports`; same reserve/fill funcIdx discipline as
1080
+ * `arrayToPrimitiveReserved`. Lets `(new C() as any) - 8` / `Number(new C() as any)`
1081
+ * reduce via the class's valueOf/toString host-free, standalone only.
1082
+ */
1083
+ classToPrimitiveReserved?: boolean;
1084
+ /**
1085
+ * (#2038) True once the native iterator runtime (`ensureNativeIteratorRuntime`,
1086
+ * iterator-native.ts) has emitted `__iterator` / `__iterator_next` with a
1087
+ * vec-only body and is awaiting its USER-iterator arm. The USER arm dispatches
1088
+ * a custom `{[Symbol.iterator]()}` / `{next()}` object through the closed-struct
1089
+ * method dispatchers `__call_@@iterator` / `__call_next` and the field getters
1090
+ * `__sget_value` / `__sget_done`, all of which are emitted at FINALIZE (after
1091
+ * every user struct is known — `emitIteratorMethodExport` /
1092
+ * `emitStructFieldGetters`). So the carrier bodies are rebuilt with the USER arm
1093
+ * by `fillNativeIteratorUserArms` in post-processing — same reserve-then-fill
1094
+ * funcIdx-authority discipline as `protoIteratorDriverReserved` (#1719). The
1095
+ * eager body is a valid vec-only carrier (byte-identical to the pre-#2038
1096
+ * runtime), so if the fill is ever skipped (e.g. multi-module) custom iterables
1097
+ * keep trapping as before rather than shipping a broken module. Only set under
1098
+ * `--target standalone` / `wasi`.
1099
+ */
1100
+ nativeIteratorUserArmPending?: boolean;
1101
+ /**
1102
+ * Static property initializer expressions to compile into __module_init.
1103
+ * `className` (#1395) is the owning class name — used to set
1104
+ * `enclosingClassName` + `isStaticContext` on the initFctx so `this`
1105
+ * inside the initializer (and any closures it spawns) resolves to the
1106
+ * class-object singleton via `emitLazyClassObjectGet`.
1107
+ */
1108
+ staticInitExprs: {
1109
+ globalIdx?: number;
1110
+ initializer?: ts.Expression;
1111
+ staticBlock?: ts.ClassStaticBlockDeclaration;
1112
+ className?: string;
1113
+ }[];
1114
+ /** Counter for generated closure types/functions */
1115
+ closureCounter: number;
1116
+ /**
1117
+ * (#2640) When set, `compileArrowAsClosure` widens any callback parameter
1118
+ * whose resolved type is a typed WasmGC vec/array (`__vec_*`/`__arr_*`/
1119
+ * `$__vec_base`) to `externref`. Set transiently by
1120
+ * `compileArrayLikePrototypeCall` around the callback compile: that path
1121
+ * dispatches a generic `Array.prototype.X.call(arrayLike, cb)` over a
1122
+ * DYNAMIC (non-vec) array-like receiver, and passes that receiver to the
1123
+ * callback's array parameter as an `externref`. Without the widening,
1124
+ * TypeScript infers the callback's array param as `T[]` → a typed vec ref,
1125
+ * so the dispatch loop must pass `ref.null` (the receiver fails the vec
1126
+ * `ref.test`) and the callback's `obj.length`/`obj[i]` lowers to a
1127
+ * `struct.get` on null → "dereferencing a null pointer". Widening to
1128
+ * externref routes those reads through the tag-aware dynamic reader.
1129
+ * This path is ONLY entered for non-vec array-like receivers (real
1130
+ * `__vec_`/`__arr_` receivers bail out of `compileArrayLikePrototypeCall`
1131
+ * upstream), so the typed `arr.forEach(cb)` hot path is never touched.
1132
+ */
1133
+ forceExternrefCallbackParams?: boolean;
1134
+ /** Map from local variable name → closure metadata (for call_ref dispatch) */
1135
+ closureMap: Map<string, ClosureInfo>;
1136
+ /** Map from closure struct type index → closure metadata (for anonymous closures) */
1137
+ closureInfoByTypeIdx: Map<number, ClosureInfo>;
1138
+ /** Resolved concrete types for generic functions (from call-site analysis) */
1139
+ genericResolved: Map<string, {
1140
+ params: ValType[];
1141
+ results: ValType[];
1142
+ }>;
1143
+ /** Rest parameter info per function (functions with ...rest syntax) */
1144
+ funcRestParams: Map<string, RestParamInfo>;
1145
+ /**
1146
+ * Functions whose body reads `arguments`. Used by callers to decide
1147
+ * whether to populate the `__extras_argv` module global with extra
1148
+ * runtime args beyond the formal param count (#1053).
1149
+ */
1150
+ funcUsesArguments: Set<string>;
1151
+ /**
1152
+ * Module global index for the runtime extras argv vec (#1053).
1153
+ * Lazily registered on first use; -1 if not yet created.
1154
+ * Type: (mut (ref null $vec_externref))
1155
+ */
1156
+ extrasArgvGlobalIdx: number;
1157
+ /** Vec struct type index for the extras argv global (matches externref vec type). */
1158
+ extrasArgvVecTypeIdx: number;
1159
+ /**
1160
+ * Absolute Wasm global index for the `__argc` (mut i32) module global.
1161
+ * Set by the caller to communicate the actual call-site argument count
1162
+ * to functions that use `arguments`. -1 = not yet created.
1163
+ */
1164
+ argcGlobalIdx: number;
1165
+ /**
1166
+ * Absolute Wasm global index for the `__current_this` (mut externref) module
1167
+ * global (#1636-S1). Set by `__call_fn_method_N` to the host-supplied
1168
+ * receiver before invoking the closure body; restored after the call.
1169
+ * A `ThisKeyword` reference in a free-function closure (no local `this`
1170
+ * binding, not in static context) reads from this global instead of the
1171
+ * previous `undefined` fallback. -1 = not yet created.
1172
+ */
1173
+ currentThisGlobalIdx: number;
1174
+ /** Map from struct name → set of closure type indices used for valueOf fields */
1175
+ valueOfClosureTypes: Map<string, number[]>;
1176
+ /**
1177
+ * (#1989) Set of `${structName}_${valueOf|toString|@@toPrimitive}` method full
1178
+ * names whose SHARED func body has already been claimed by the first object
1179
+ * literal of a deduped anon-struct type. Same-shape literals share a struct
1180
+ * type, so the first literal compiled keeps the shared `${name}_valueOf` func
1181
+ * (referenced by the host `__call_*`/`__sget_*` exports and name-keyed coercion
1182
+ * fallbacks); every LATER same-shape literal forks its own per-literal method
1183
+ * func and stores its own funcref in the struct field, so per-instance
1184
+ * `call_ref` dispatch resolves to the correct method body per object.
1185
+ */
1186
+ toPrimitiveSharedClaimed: Set<string>;
1187
+ /**
1188
+ * (#1989) Set of anon-struct type names that have MORE THAN ONE object literal
1189
+ * sharing the deduped struct type and carrying a `valueOf`/`toString`/
1190
+ * `@@toPrimitive` method — i.e. the same-shape collision case where each
1191
+ * literal stores its own method funcref. Only these structs route the host
1192
+ * `__call_*` ToPrimitive dispatch through the per-instance struct-field closure
1193
+ * (instead of the name-keyed standalone func, which is the first literal's body
1194
+ * and is correct + simpler for the single-literal case). This keeps the
1195
+ * single-literal path — including the §7.1.1.1 step-6 TypeError walk — on the
1196
+ * well-tested standalone arm, and only opts the genuine collision case into
1197
+ * per-instance dispatch.
1198
+ */
1199
+ toPrimitiveForkedStructs: Set<string>;
1200
+ /** Tag index for the exception tag (-1 if not yet registered) */
1201
+ exnTagIdx: number;
1202
+ /** Whether union type helper imports have been registered */
1203
+ hasUnionImports: boolean;
1204
+ /**
1205
+ * #1121: Function names whose return type was promoted from implicit-`any`
1206
+ * to a concrete numeric type (f64) by inferNumericReturnTypes. Used by
1207
+ * collectDeclarations to override the TS-derived return type when the
1208
+ * recursive numeric kernel pattern is detected.
1209
+ */
1210
+ numericReturnTypes?: Map<string, ValType>;
1211
+ /** Set of function names that are async (for .d.ts generation) */
1212
+ asyncFunctions: Set<string>;
1213
+ /** Set of function names that are generators (function*) */
1214
+ generatorFunctions: Set<string>;
1215
+ /** Map from generator function name → yield element type */
1216
+ generatorYieldType: Map<string, ValType>;
1217
+ /** Shared native generator IteratorResult-like struct type index, or -1 before registration. */
1218
+ nativeGeneratorResultTypeIdx: number;
1219
+ /** Function declarations lowered to Wasm-native generator state machines (#680). */
1220
+ nativeGenerators: Map<string, NativeGeneratorInfo>;
1221
+ /**
1222
+ * Function declarations pre-registered during module-pass eager class body
1223
+ * compilation. The entry has a reserved `mod.functions` slot and signature,
1224
+ * but its body still belongs to the normal nested-function hoist pass.
1225
+ */
1226
+ preRegisteredBodyless?: Set<string>;
1227
+ /** Map from module-level variable name → global index in mod.globals */
1228
+ moduleGlobals: Map<string, number>;
1229
+ /** Deferred `export default <variable>` where variable is a module global (#1108).
1230
+ * Resolved after all collectDeclarations calls when global indices are final. */
1231
+ deferredDefaultGlobalExport?: string;
1232
+ /** Module-level variable initializers (compiled into __module_init) */
1233
+ moduleInitStatements: ts.Statement[];
1234
+ /** Nested function capture info. */
1235
+ nestedFuncCaptures: Map<string, {
1236
+ name: string;
1237
+ outerLocalIdx: number;
1238
+ mutable?: boolean;
1239
+ valType?: ValType;
1240
+ /**
1241
+ * #1205: Whether this capture's TDZ flag must be propagated to the lifted
1242
+ * function as an extra leading param. When true, the lifted fn signature
1243
+ * gains a trailing flag-ref-cell param after all value captures and the
1244
+ * call site (calls.ts) prepends the boxed flag ref. Mirrors the arrow-
1245
+ * function Stage 3 wiring in `compileArrowAsClosure`.
1246
+ */
1247
+ hasTdzFlag?: boolean;
1248
+ /**
1249
+ * #1205: At-construction-time outer-fctx flag local index. May point
1250
+ * to either the raw i32 flag local (must be wrapped at the call site)
1251
+ * or an already-boxed ref-cell local (passed through directly). Stored
1252
+ * as metadata so the call site can re-resolve via `fctx.tdzFlagLocals`
1253
+ * / `fctx.boxedTdzFlags` at call time.
1254
+ */
1255
+ outerTdzFlagIdx?: number;
1256
+ }[]>;
1257
+ /** Map from child className → parent className (for local class inheritance) */
1258
+ classParentMap: Map<string, string>;
1259
+ /**
1260
+ * (#1366a) Map from child className → built-in JS parent name when the parent
1261
+ * is a host-constructible builtin (Error / TypeError / RangeError / ...).
1262
+ * Subclass instances are externref-backed; `super(args)` lowers to
1263
+ * `__new_<Parent>(args)` instead of the field-walk path.
1264
+ */
1265
+ classBuiltinParentMap: Map<string, string>;
1266
+ /**
1267
+ * (#1366a) Set of class names whose runtime instance representation is
1268
+ * externref (NOT a WasmGC struct). Constructor return type, `new` result
1269
+ * type, and `instanceof` routing all consult this set. Currently populated
1270
+ * for subclasses of host-constructible builtins.
1271
+ */
1272
+ classExternrefBackedSet: Set<string>;
1273
+ /** Counter for assigning unique class tags (for instanceof support) */
1274
+ classTagCounter: number;
1275
+ /** Map from class name → unique tag value (for instanceof support) */
1276
+ classTagMap: Map<string, number>;
1277
+ /** Map from TS symbol name → synthetic class name for class expressions */
1278
+ classExprNameMap: Map<string, string>;
1279
+ /** Map from ClassExpression AST node → synthetic class name */
1280
+ anonClassExprNames: Map<ts.ClassExpression, string>;
1281
+ /** Map from function/class identifier → its ES-spec .name string value */
1282
+ functionNameMap: Map<string, string>;
1283
+ /** Whether to attach source positions for source map generation */
1284
+ sourceMap: boolean;
1285
+ /** Map from tuple type signature key → type index of the tuple struct */
1286
+ tupleTypeMap: Map<string, number>;
1287
+ /** Fast mode: default number to i32, promote to f64 only when needed */
1288
+ fast: boolean;
1289
+ /** Use WasmGC-native strings instead of wasm:js-string imports */
1290
+ nativeStrings: boolean;
1291
+ /** #1719 S1 — `ITER_OVERRIDDEN` whole-program brand for the array
1292
+ * object-value representation track. Set by the `sourceOverridesArrayIterator`
1293
+ * pre-scan (in index.ts) when the program may monkeypatch
1294
+ * `Array.prototype[Symbol.iterator]` / `Array.prototype.values`
1295
+ * (assignment or `Object.define{Property,Properties}(Array.prototype, …)`).
1296
+ * When `false` (the common case) every array-destructuring site emits
1297
+ * byte-identical output and takes the existing backing-store fast path.
1298
+ * The S2 slice consults this flag to route a branded array RHS through the
1299
+ * host-Array reflection + host `GetIterator` so an overridden `@@iterator`
1300
+ * is observed (§7.4.2 / §8.5.2). Default `false`. */
1301
+ arrayIteratorMaybeOverridden: boolean;
1302
+ /** #1588 PR-B: dual i8/i16 storage. When true (and `nativeStrings`),
1303
+ * string allocation sites proven `ascii`/`utf8-guaranteed` by the encoding
1304
+ * analysis use an i8-backed `Utf8String`; everything else stays i16.
1305
+ * Default false → byte-identical to today (the Utf8String types are not
1306
+ * even registered when off). */
1307
+ utf8Storage: boolean;
1308
+ /** Native string support type indices */
1309
+ nativeStrDataTypeIdx: number;
1310
+ anyStrTypeIdx: number;
1311
+ nativeStrTypeIdx: number;
1312
+ consStrTypeIdx: number;
1313
+ /**
1314
+ * (#40) Immutable `(array i32)` type index for the Unicode case-mapping tables
1315
+ * (emitNativeCaseConversion). Registered once on first use.
1316
+ */
1317
+ caseTableArrTypeIdx?: number;
1318
+ /** #1588 PR-B: i8 backing array + Utf8String subtype indices. -1 when
1319
+ * `utf8Storage` is off (types not registered). */
1320
+ utf8StrDataTypeIdx: number;
1321
+ utf8StrTypeIdx: number;
1322
+ /** #1588 PR-B: the live AllocSiteRegistry from the IR pipeline, threaded so
1323
+ * the string-lowering sites can read the `encoding` annotation. Undefined
1324
+ * for non-IR / legacy front-end paths (→ encoding reads back `wtf16`). */
1325
+ allocRegistry?: import('../../ir/alloc-registry.js').AllocSiteRegistry;
1326
+ /** Whether native string helper functions have been emitted */
1327
+ nativeStrHelpersEmitted: boolean;
1328
+ /** Whether native string host bridge helpers have been emitted */
1329
+ nativeStrExternBridgeEmitted: boolean;
1330
+ /** Whether the testRuntime string helpers (#1187) have been emitted */
1331
+ testRuntimeStringHelpersEmitted: boolean;
1332
+ /** Test-only: emit testRuntime string-coercion exports (#1187). */
1333
+ testRuntime: boolean;
1334
+ /** Map from native string helper name → function index */
1335
+ nativeStrHelpers: Map<string, number>;
1336
+ /** #1103a: Wasm-native Map runtime (standalone / WASI). All -1 / empty until
1337
+ * `ensureMapRuntimeTypes` / `ensureMapHelpers` run; only used when the
1338
+ * native-collections path is active (gated on nativeStrings/standalone). */
1339
+ mapTypeIdx: number;
1340
+ mapEntryTypeIdx: number;
1341
+ mapEntriesTypeIdx: number;
1342
+ mapBucketsTypeIdx: number;
1343
+ mapIterTypeIdx: number;
1344
+ /** Shared {value, done} iterator-result struct for native collections. */
1345
+ mapIterResultTypeIdx: number;
1346
+ /** Map from native Map helper name → function index. */
1347
+ mapHelpers: Map<string, number>;
1348
+ /** Whether the Map runtime helper functions have been emitted. */
1349
+ mapHelpersEmitted: boolean;
1350
+ /** #1539: map from native standalone-regex helper name → function index.
1351
+ * Mirrors `nativeStrHelpers`; populated by `src/codegen/native-regex.ts`. */
1352
+ nativeRegexHelpers: Map<string, number>;
1353
+ /** #1677: import-function count captured the instant the native-string
1354
+ * helpers were first emitted (mid-finalize). Used by
1355
+ * `reconcileNativeStrFinalizeShift` to shift the helper bodies + map by the
1356
+ * number of imports added afterwards during the rest of finalize. -1 until
1357
+ * helpers are emitted; reset to -1 once reconciled. */
1358
+ nativeStrHelperImportBase: number;
1359
+ /** Map from value type kind → ref cell struct type index */
1360
+ refCellTypeMap: Map<string, number>;
1361
+ /** Type index of the $AnyValue boxed-any struct */
1362
+ anyValueTypeIdx: number;
1363
+ /**
1364
+ * (#2106 S1) Global index of the standalone `$undefined` singleton — an
1365
+ * immutable tag-1 `$AnyValue`, reserved up-front at `ensureAnyValueType` time
1366
+ * so `undefined` is distinguishable from `null` (`ref.null extern`) in
1367
+ * standalone/native-strings mode. `undefined` otherwise has no host value and
1368
+ * conflates with null. Reserved as a GLOBAL (not a late func import) to avoid
1369
+ * the #329 native-string finalize-shift hazard. `undefined` until reserved.
1370
+ */
1371
+ undefinedGlobalIdx?: number;
1372
+ /** Map from any-value helper name → function index */
1373
+ anyHelpers: Map<string, number>;
1374
+ /** Whether any-value helper functions have been emitted */
1375
+ anyHelpersEmitted: boolean;
1376
+ /** (#1789) Whether the WASI module-init guard (idempotent __module_init +
1377
+ * prepended init call on exports) has been applied. */
1378
+ moduleInitGuardApplied: boolean;
1379
+ /**
1380
+ * #1984 — freeze-point discipline (child of #2043 Option 3). Set to `true`
1381
+ * by `generateModule`/`generateMultiModule` once the module's index spaces
1382
+ * are final (right before `stackBalance`, after the last legitimate
1383
+ * `addUnionImports`/`addStringImports`/`reconcileNativeStrFinalizeShift`
1384
+ * mutation in every mode). While set, `addImport`/`ensureLateImport` throw a
1385
+ * named producer-site error instead of silently mutating a finalized import
1386
+ * space — so the producer that added an import too late self-identifies with
1387
+ * its own stack, rather than #2043's emit-time validation only naming the
1388
+ * downstream symptom. Default `false`. */
1389
+ indexSpaceFrozen: boolean;
1390
+ /** Shape-inferred array-like variables */
1391
+ shapeMap: Map<string, {
1392
+ vecTypeIdx: number;
1393
+ arrTypeIdx: number;
1394
+ elemType: ValType;
1395
+ }>;
1396
+ /** Set of function names that failed during hoisting pre-pass */
1397
+ hoistFailedFuncs?: Set<string>;
1398
+ /** Counter for unique tagged template cache global variables */
1399
+ templateCacheCounter: number;
1400
+ /** Type index for template vec struct */
1401
+ templateVecTypeIdx: number;
1402
+ /**
1403
+ * (#2186) Type index for the shared `$__vec_base` supertype — a `(length i32)`
1404
+ * struct that every `__vec_<elemKind>` subtypes. Lets standalone runtime
1405
+ * helpers (`__extern_length`) `ref.test`/`ref.cast` a boxed array externref
1406
+ * to read its `.length` uniformly, regardless of element kind. -1 = not yet
1407
+ * registered (created lazily on first `getOrRegisterVecType`).
1408
+ */
1409
+ vecBaseTypeIdx: number;
1410
+ /**
1411
+ * (#2159 / #38) Type index for the standalone `$__dv_window` struct — a
1412
+ * `{buf: (ref null __vec_i32_byte), byteOffset: i32, byteLength: i32}` wrapper
1413
+ * produced by `new DataView(buffer, byteOffset, byteLength)` when the view is
1414
+ * windowed (offset > 0 or an explicit byteLength). Lets the native DataView
1415
+ * accessors add `byteOffset` to every byte index while sharing the parent's
1416
+ * backing array (so windowed writes are visible through the full view), and
1417
+ * lets `dv.byteOffset`/`dv.byteLength` reflect the ctor args. -1 = not yet
1418
+ * registered (created lazily). Offset-0 default-length views keep the bare
1419
+ * i32_byte vec representation (no wrapper, zero new cost).
1420
+ */
1421
+ dvWindowTypeIdx: number;
1422
+ /**
1423
+ * (#2159 / #2357 / #47) Type index for the standalone `$__subview` struct — a
1424
+ * `{base: (ref null __vec_<elem>), byteOffset: i32, length: i32}` view produced
1425
+ * by `TypedArray.prototype.subarray(begin, end)`. It SHARES the parent's backing
1426
+ * `data` array (true aliasing — a sub-write is visible in the parent) and carries
1427
+ * the element offset + windowed length. Element access discriminates view-vs-plain
1428
+ * at COMPILE time via the receiver's resolved ValType (a binding initialised by
1429
+ * `subarray` resolves to `$__subview`), so the plain-array `a[i]` hot path takes
1430
+ * ZERO extra instructions — no per-access runtime branch. Keyed per element kind
1431
+ * in `subviewTypeMap`; this scalar holds the most-recently-registered idx for
1432
+ * back-compat. -1 = not yet registered. (Spec: plan/issues/2357.)
1433
+ */
1434
+ subviewTypeIdx: number;
1435
+ /** (#2357) Per-element-kind `$__subview` struct type indices, keyed by elemKind. */
1436
+ subviewTypeMap: Map<string, number>;
1437
+ /** Type index for the WasmGC `$Error_struct` used in standalone/WASI mode (#1104). -1 = not yet registered. */
1438
+ errorStructTypeIdx: number;
1439
+ /** Extra properties for empty object variables */
1440
+ widenedTypeProperties: Map<string, {
1441
+ name: string;
1442
+ type: ValType;
1443
+ }[]>;
1444
+ /** Map from widened variable name to its registered struct name */
1445
+ widenedVarStructMap: Map<string, string>;
1446
+ /** Widened empty-object fields introduced by Object.defineProperty rather than assignment. */
1447
+ widenedDefinePropertyKeys: Set<string>;
1448
+ /**
1449
+ * (#2372) Standalone-only: receiver var names that are the target of at least
1450
+ * one `Object.defineProperty(var, key, desc)` where `desc` is a *dynamic*
1451
+ * (non-inline-literal) descriptor. Such defines are applied via the native
1452
+ * `__obj_define_from_desc` `$Object` runtime, which the struct-widening read
1453
+ * path (`struct.get`) cannot observe. Membership here suppresses
1454
+ * struct-widening for the receiver so it stays on the `$Object` representation
1455
+ * and both the dynamic write and the read-back route through the native
1456
+ * runtime consistently. Empty in host/gc/wasi mode (only populated under
1457
+ * `ctx.standalone`).
1458
+ */
1459
+ dynamicDescriptorWidenVars: Set<string>;
1460
+ /**
1461
+ * (#2584) Standalone-only: receiver var names that are the subject of at least
1462
+ * one `$Object`-hash-only operation — bracket read/write (`o[k]`), `key in o`,
1463
+ * `Object.keys/values/entries/getOwnPropertyDescriptor/getOwnPropertyNames(o)`,
1464
+ * `Object.assign(o, …)` / `Object.assign(…, o)`, or `for (… in o)`. These
1465
+ * consumers all read the native `$Object` open-hash runtime, which a widened
1466
+ * closed WasmGC struct is invisible to. A var written via dot-access AND read
1467
+ * via any of these would otherwise widen to a struct on the write side but miss
1468
+ * it on the read side (`o.a = 7; o["a"]` → 0). Membership here suppresses
1469
+ * struct-widening for the receiver so it stays a `__new_plain_object` /
1470
+ * `$Object`; dot-writes then route through `__extern_set` and every access form
1471
+ * reads the same hash consistently. Mirrors `dynamicDescriptorWidenVars`; the
1472
+ * two sets are additive. Empty in host/gc/wasi mode (only populated under
1473
+ * `ctx.standalone`).
1474
+ */
1475
+ objectHashConsumerVars: Set<string>;
1476
+ /**
1477
+ * (#1239) Variable names whose initializer is an object literal carrying
1478
+ * `get`/`set` accessors. Such variables are stored as plain JS host
1479
+ * objects (via `__new_plain_object` + `__defineProperty_accessor`) and
1480
+ * must NEVER be treated as a wasmGC struct ref — every read/write goes
1481
+ * through the externref host path so V8's accessor descriptor fires.
1482
+ *
1483
+ * Populated in `compileObjectLiteralWithAccessors` (literals.ts) and
1484
+ * consulted by `resolveStructNameForExpr` and `resolveEffectiveStructName`
1485
+ * to short-circuit the struct-resolution chain back to `undefined`.
1486
+ */
1487
+ externrefAccessorVars: Set<string>;
1488
+ /** Math methods that need inline Wasm implementations */
1489
+ pendingMathMethods: Set<string>;
1490
+ /**
1491
+ * (#1602) Object-method-as-closure trampolines whose body forwards the
1492
+ * method's params positionally. The method's `func.typeIdx` can be
1493
+ * re-resolved (param types / order finalized) AFTER the trampoline was
1494
+ * emitted, which would leave the eagerly-built forwarding body referencing a
1495
+ * stale signature and produce an invalid module. We rebuild each trampoline
1496
+ * body against the method's FINAL signature in a post-pass after all function
1497
+ * bodies are compiled.
1498
+ */
1499
+ pendingMethodTrampolines: {
1500
+ trampolineBody: Instr[];
1501
+ /** The trampoline's own func index. */
1502
+ trampolineFuncIdx: number;
1503
+ methodFuncIdx: number;
1504
+ objStructTypeIdx: number;
1505
+ /** User-param count the wrapper func type was built with (excludes self). */
1506
+ userParamCount: number;
1507
+ /**
1508
+ * (#1669) The wrapper func type's user-param types and result, captured at
1509
+ * emit time. These are the static types of the `local.get`s the forwarding
1510
+ * body reads, and the type the trampoline must return. The method's
1511
+ * signature can drift away from these during later body compilation; the
1512
+ * finalize pass coerces each forwarded arg from `wrapperUserParams[i]` to
1513
+ * the method's final param type, and the method's result back to
1514
+ * `wrapperResult`, so the rebuilt body validates against both signatures.
1515
+ * Captured directly (not re-derived from `trampolineFuncIdx`) because late
1516
+ * import shifting can move that index relative to the recorded value.
1517
+ */
1518
+ wrapperUserParams: ValType[];
1519
+ wrapperResult: ValType | undefined;
1520
+ /**
1521
+ * (#1340) True when the underlying callable is a plain function declaration
1522
+ * with no hidden `this` param (so the finalizer must NOT slice off the
1523
+ * first param of `sig.params` and must NOT emit a `ref.null` prologue for
1524
+ * `this`). Methods leave this false/undefined and keep the legacy
1525
+ * `this`-drop behaviour.
1526
+ */
1527
+ noThisParam?: boolean;
1528
+ /**
1529
+ * (#1809) True when `methodFuncIdx` already pointed at a host IMPORT at
1530
+ * registration time — e.g. a DOM/host global (`resizeTo`, `scrollBy`) or
1531
+ * any `declare`d function used as a first-class value, where the trampoline
1532
+ * legitimately forwards into an imported function. The late-import shift
1533
+ * walker keeps import indices stable (new imports append at the end, so it
1534
+ * only bumps indices `>= importsBefore` and leaves existing import targets
1535
+ * untouched), so an import target at finalize is EXPECTED here, not a missed
1536
+ * shift. The #1525b guard must only fire when a target that was a DEFINED
1537
+ * function at registration resolves to an import at finalize.
1538
+ */
1539
+ methodTargetsImport?: boolean;
1540
+ /**
1541
+ * (#2025) Whether the method body reads `this` (param 0), computed at
1542
+ * registration BEFORE the TypeError-helper late import shifts function
1543
+ * indices (which would make a finalize-time `methodFuncIdx` lookup point at
1544
+ * the wrong function). Finalize reuses this captured value to decide whether
1545
+ * the trampoline's null-`this` arm throws a catchable TypeError.
1546
+ */
1547
+ methodUsesThis?: boolean;
1548
+ }[];
1549
+ /** True if Math.clz32 or Math.imul is used — requires ToUint32 Wasm helper */
1550
+ needsToUint32: boolean;
1551
+ /** Map from class name → class AST declaration node */
1552
+ classDeclarationMap: Map<string, ts.ClassDeclaration | ts.ClassExpression>;
1553
+ /** Cache for function type deduplication: signature key → type index */
1554
+ funcTypeCache: Map<string, number>;
1555
+ /** Wrapper type indices */
1556
+ wrapperNumberTypeIdx: number;
1557
+ wrapperStringTypeIdx: number;
1558
+ wrapperBooleanTypeIdx: number;
1559
+ /** Native union-helper carrier type indices, present under WASI/standalone. */
1560
+ nativeBoxNumberTypeIdx: number;
1561
+ nativeBoxBooleanTypeIdx: number;
1562
+ nativeBigIntTypeIdx: number;
1563
+ /** Cache for function reference wrappers: signature key → ClosureInfo */
1564
+ funcRefWrapperCache: Map<string, ClosureInfo>;
1565
+ /** Pending module-init body (not yet in mod.functions) that needs global index fixup */
1566
+ pendingInitBody: Instr[] | null;
1567
+ /** Map from function name to inlinable function info */
1568
+ inlinableFunctions: Map<string, InlinableFunctionInfo>;
1569
+ /** Global index of the __symbol_counter */
1570
+ symbolCounterGlobalIdx: number;
1571
+ /** (#2163) Global index of the native symbol id→description table
1572
+ * (`ref_null` to an array of `$AnyString`), lazily allocated. -1 until first
1573
+ * use. Standalone-mode native `.description` storage. */
1574
+ symbolDescGlobalIdx: number;
1575
+ /** (#2163) Type index of the symbol description table's array type
1576
+ * (`array (mut (ref null $AnyString))`). -1 until created. */
1577
+ symbolDescArrTypeIdx: number;
1578
+ /** (#2163) Native `Symbol.for`/`Symbol.keyFor` registry (standalone mode).
1579
+ * Two parallel growable arrays — slot→key string (reuses
1580
+ * `symbolDescArrTypeIdx`) and slot→symbol id (`array (mut i32)`) — plus a
1581
+ * count global. All -1 until the first `Symbol.for`/`keyFor`. */
1582
+ symbolRegKeysGlobalIdx: number;
1583
+ symbolRegIdsGlobalIdx: number;
1584
+ symbolRegCountGlobalIdx: number;
1585
+ /** (#2163) Type index of the registry ids array (`array (mut i32)`). */
1586
+ symbolRegIdsArrTypeIdx: number;
1587
+ /** Stack of in-progress parent function bodies for index shifting during closure compilation */
1588
+ parentBodiesStack: Instr[][];
1589
+ /** All live (allocated but not yet attached to ctx.mod.functions) FunctionContext bodies.
1590
+ * Walked by addUnionImports / shiftLateImportIndices to ensure call-funcIdx values
1591
+ * in nested function bodies under construction (e.g. `cbFctx.body` in
1592
+ * compileArrowAsCallback during its captures-extraction / param-coercion setup
1593
+ * phase, BEFORE the savedFunc swap puts it on funcStack) are still shifted on
1594
+ * late import addition. (#1384) */
1595
+ liveBodies: Set<Instr[]>;
1596
+ /** Hash-based lookup for anonymous struct deduplication */
1597
+ anonStructHash: Map<string, string>;
1598
+ /**
1599
+ * (#2009) Result of the same-structural-shape collision-resolution post-pass:
1600
+ * anon struct name → its shape-id. Populated ONLY for structs that genuinely
1601
+ * collide (a different-named struct shares the same field TYPES, making them
1602
+ * runtime-indistinguishable under WasmGC iso-recursive canonicalization). Such
1603
+ * structs get a hidden trailing `$shape` i32 field retro-stamped per-instance;
1604
+ * the host `__struct_field_names`/`__sset_*` exports read it to recover the
1605
+ * instance's real field names by VALUE. Non-colliding structs are absent here
1606
+ * and keep their original layout (zero blast radius — the common case, incl.
1607
+ * all IR-path construction, is byte-identical to main).
1608
+ */
1609
+ shapeIdByStructName: Map<string, number>;
1610
+ /** (#2009) shape-id → ordered field-name CSV, for the host name export. */
1611
+ shapeNameCsvById: string[];
1612
+ /**
1613
+ * (#2009 R3b) anon object-literal struct name → its field names in JS
1614
+ * INSERTION order (the order keys were first introduced while evaluating the
1615
+ * literal source: named props left-to-right, spreads contributing each
1616
+ * source's own keys in order, FIRST occurrence wins). The struct's slot order
1617
+ * comes from `ts.Type.getProperties()`, which for spread-result types is
1618
+ * last-spread-first and does NOT match JS enumeration order. Host enumeration
1619
+ * (`Object.keys`/`JSON.stringify`/`for-in`) is driven by the field-name CSV in
1620
+ * `__struct_field_names`, read BY NAME (slot-independent), so reordering the
1621
+ * CSV by this list restores spec enumeration order without touching slots,
1622
+ * getters, dedup, or the `$shape` field. First literal of a deduped canonical
1623
+ * type wins (deterministic by compile order). Empty when a struct's checker
1624
+ * order already matches insertion order (plain literals), so the reorder is a
1625
+ * no-op for the common case.
1626
+ */
1627
+ structInsertionOrder: Map<string, string[]>;
1628
+ /** Pending late import shift state */
1629
+ pendingLateImportShift: {
1630
+ importsBefore: number;
1631
+ } | null;
1632
+ /** Map from class name → global index of the prototype externref singleton */
1633
+ protoGlobals: Map<string, number>;
1634
+ /** Map from class name → own method names (instance methods, for prototype allowlist; see #1047) */
1635
+ classMethodNames: Map<string, string[]>;
1636
+ /** Map from class name → global idx of the method-name CSV string constant (see #1047) */
1637
+ classMethodsCsvGlobal: Map<string, number>;
1638
+ /** Map from class name → global index of the class-object externref singleton (#1395). Used so `C` resolves to a real object whose static-method descriptors are queryable. */
1639
+ classObjectGlobals: Map<string, number>;
1640
+ /** Map from class name → own static method names (for the static method allowlist; #1395) */
1641
+ classStaticMethodNames: Map<string, string[]>;
1642
+ /** Map from class name → global idx of the static-method-name CSV string constant (#1395) */
1643
+ classStaticMethodsCsvGlobal: Map<string, number>;
1644
+ /** #1888 S6 — lazily materialized built-in namespace singleton globals
1645
+ * (Array/Object static method surface under standalone). */
1646
+ builtinObjectGlobals: Map<string, number>;
1647
+ /** (#1394) Map from `${className}_${methodName}` → global idx of the cached
1648
+ * externref singleton closure for the method. Lazily allocated on first
1649
+ * property-access of `C.prototype.<method>` or `instance.<method>` (as
1650
+ * value). Reused on every subsequent access so `c.m === C.prototype.m`
1651
+ * holds (verifyProperty identity assertions across ~478 class/elements
1652
+ * tests). The companion canonical trampoline is named
1653
+ * `__obj_meth_tramp_${className}_${methodName}_cached` and is also reused
1654
+ * across all access sites to avoid bloating mod.functions. */
1655
+ methodClosureGlobals: Map<string, number>;
1656
+ /**
1657
+ * (#2025) Once an extractable method-as-closure trampoline is emitted, the
1658
+ * `__new_TypeError` import + message string are registered eagerly so the
1659
+ * trampoline's null-`this` arm can throw a CATCHABLE TypeError (instead of
1660
+ * trapping on a null `struct.get`) with stable, shift-tracked indices.
1661
+ * Pure-lookup after that — the trampoline never registers mid-finalize.
1662
+ */
1663
+ nullThisTypeErrorReady: boolean;
1664
+ /** (#1340) Singleton closure-struct externref globals for top-level function
1665
+ * declarations used as first-class values. Keyed by function name. Ensures
1666
+ * `foo === foo` and so sidecar writes on `foo.prototype` are observed by
1667
+ * later reads. Mirrors `methodClosureGlobals` (#1394) for the function-decl
1668
+ * case where the same JS identifier is read as a value at multiple sites. */
1669
+ funcClosureGlobals: Map<string, number>;
1670
+ /** Whether targeting WASI */
1671
+ wasi: boolean;
1672
+ /** Whether targeting standalone (no JS host, no WASI runtime — #1470).
1673
+ * When true, the emitter MUST NOT add `wasm:js-string` namespace imports
1674
+ * or JS-host string helpers (`__concat_N`, `__extern_toString`,
1675
+ * `__unbox_string`, `__str_from_mem`, `__str_to_mem`,
1676
+ * `__str_extern_len`). Implies `nativeStrings === true`. */
1677
+ standalone: boolean;
1678
+ /** (#2179) True when the module body contains any `delete` of a property or
1679
+ * element access (e.g. `delete o.a` / `delete o[k]`). Pre-scanned once at
1680
+ * module setup. When true, `any`/`unknown`-typed property READS in JS-host
1681
+ * mode are routed through the tombstone-aware `__extern_get` host helper
1682
+ * instead of the inline `ref.test`+`struct.get` fast-path — the fast-path
1683
+ * reads the live WasmGC field and bypasses the runtime delete tombstone, so
1684
+ * a post-delete read returned the stale value (#2179). Delete-free modules
1685
+ * keep the byte-identical inline fast-path (zero overhead). */
1686
+ moduleUsesDelete?: boolean;
1687
+ /** (#1472 Phase A) Set of dynamic-shape object/property host-import names
1688
+ * already refused under `--target standalone`, used to deduplicate the
1689
+ * compile-error so a single source construct emits at most one error per
1690
+ * import name. Lazily initialized in late-imports.ts. */
1691
+ standaloneRefusedImports?: Set<string>;
1692
+ /** (#1472 Phase B) Type indices for the Wasm-native open-object runtime
1693
+ * ($Object / $PropMap / $PropEntry), allocated once by ensureObjectRuntime
1694
+ * in object-runtime.ts. Undefined until first open-object op under
1695
+ * --target standalone. */
1696
+ objectRuntimeTypes?: ObjectRuntimeTypes;
1697
+ /** (#2175 S0) Module-type index of the single shared `$NativeProto` struct —
1698
+ * the host-free builtin/class prototype-object representation. Registered
1699
+ * once by `registerNativeProtoType` (property-access.ts) the first time a
1700
+ * `.prototype`-as-value read demands a native proto object under
1701
+ * `--target standalone`. Undefined until then. */
1702
+ nativeProtoTypeIdx?: number;
1703
+ /** (#2175 S0) Builtin-brand id table — a reserved high-negative i32 band
1704
+ * disjoint from `classTagMap`'s range, so a `$NativeProto.$brand` (or the
1705
+ * `$ClassMeta.$parentTag` externref-backed-subclass slot from #2101) is a
1706
+ * single i32 namespace shared with class tags without collision. Seeded
1707
+ * lazily from the BUILTIN_BRAND_TABLE constant by `getBuiltinBrand`. */
1708
+ builtinBrandMap?: Map<string, number>;
1709
+ /** (#2175 S0) Per-funcIdx metadata for native-method-closure values, so the
1710
+ * existing `.length`/`.name`-on-function reads resolve a closure's arity and
1711
+ * member name (e.g. `RegExp.prototype.test.length === 1`,
1712
+ * `.name === "test"`). Populated by `ensureStandaloneNativeMethodClosure`. */
1713
+ nativeClosureMeta?: Map<number, {
1714
+ name: string;
1715
+ length: number;
1716
+ }>;
1717
+ /** (#2193 PR-B) Struct-type indices of `$NativeProto` member closures whose
1718
+ * FIRST user param is the receiver (`this`) — e.g. `Array.prototype.slice`'s
1719
+ * `(self, this, start, end)` closure. Unlike a plain user function (which
1720
+ * ignores `this`), a reflective `m.call(thisArg, …args)` on one of these MUST
1721
+ * thread `thisArg` into param 1 instead of dropping it. The generic `.call`
1722
+ * dispatch in expressions/calls.ts consults this set to decide. Populated by
1723
+ * `ensureStandaloneNativeMethodClosure`. */
1724
+ nativeProtoReceiverClosureStructTypes?: Set<number>;
1725
+ /** (#682) Native standalone RegExp engine hook. Standalone mode currently
1726
+ * enables the reduced literal-substring backend; null means RegExp lowering
1727
+ * must stay on the explicit #1474 refusal path. */
1728
+ standaloneRegExpEngine: StandaloneRegExpEngineConfig | null;
1729
+ /**
1730
+ * (#1373b) When true, async functions flow through the IR's CPS lowering
1731
+ * (Phase C). When false (default), the IR selector buckets async functions
1732
+ * into the `"async-function"` fallback reason and they take the legacy
1733
+ * direct-codegen path. The first scaffolding slice (#1373b Slice 1)
1734
+ * keeps this hardcoded `false`; subsequent slices (Slice 2: PENDING-path
1735
+ * CPS continuations, Slice 3: gate-flip) wire it on incrementally once
1736
+ * the lowering is parity-tested against the legacy path.
1737
+ *
1738
+ * Read by `src/ir/select.ts`'s `isAsyncIrReady(ctx)` helper; threaded
1739
+ * through `src/ir/integration.ts` into the selector via the
1740
+ * `IrPlanOptions.supportsAsyncIr` field.
1741
+ */
1742
+ supportsAsyncIr: boolean;
1743
+ /**
1744
+ * #2524 / #2633 — when true (WASI only), std-IO is lowered to imported
1745
+ * `node:fs` `readSync`/`writeSync` calls (over a shim-owned, imported linear
1746
+ * memory) instead of inline `fd_read`/`fd_write`. console.log/warn/error and
1747
+ * process.std*.write lower to `writeSync(1|2, …)`; the bespoke
1748
+ * `js2wasm:node-process` shim was retired (#2633). See `linkNodeShims` in
1749
+ * `CodegenOptions`.
1750
+ */
1751
+ linkNodeShims: boolean;
1752
+ /** #2631/#2633: func index of the imported `node:fs::readSync` (fd,ptr,len)->i32 (-1 = not registered). */
1753
+ nodeFsReadSyncIdx: number;
1754
+ /** #2631/#2633: func index of the imported `node:fs::writeSync` (fd,ptr,len)->i32 (-1 = not registered). */
1755
+ nodeFsWriteSyncIdx: number;
1756
+ /** WASI import indices */
1757
+ wasiFdWriteIdx: number;
1758
+ wasiFdReadIdx?: number;
1759
+ wasiProcExitIdx: number;
1760
+ wasiPathOpenIdx: number;
1761
+ wasiFdCloseIdx: number;
1762
+ wasiPollOneoffIdx?: number;
1763
+ /** (#2632 Phase 2) wasi_snapshot_preview1::fd_fdstat_set_flags import func idx — undefined if not registered. */
1764
+ wasiFdFdstatSetFlagsIdx?: number;
1765
+ wasiBumpPtrGlobalIdx: number;
1766
+ /** #1482: wasi_snapshot_preview1::environ_sizes_get import index (-1 = not registered) */
1767
+ wasiEnvironSizesGetIdx: number;
1768
+ /** #1482: wasi_snapshot_preview1::environ_get import index (-1 = not registered) */
1769
+ wasiEnvironGetIdx: number;
1770
+ /** #1482: env::__wasi_env_get_str late import index for JS-polyfill fast path (-1 = not registered) */
1771
+ wasiEnvGetStrIdx: number;
1772
+ /** (#1483) WASI clock_time_get import func idx — -1 if not yet registered. */
1773
+ wasiClockTimeGetIdx?: number;
1774
+ /** (#1483) Pending flag — emit `__wasi_write_string` after lib-globals scan. */
1775
+ wasiPendingFdWriteHelper?: boolean;
1776
+ /** (#1483 + #1493) Pending flag — emit `__wasi_write_string_stderr` after lib-globals scan. */
1777
+ wasiPendingConsoleStderrHelper?: boolean;
1778
+ /** (#1483) Pending flag — emit `__wasi_write_file_sync` after lib-globals scan. */
1779
+ wasiPendingPathOpenHelper?: boolean;
1780
+ /** (#1483) Pending flag — emit `__wasi_date_now` / `__wasi_performance_now` after lib-globals scan. */
1781
+ wasiClockHelpersPending?: boolean;
1782
+ /** (#1484) Pending flag — emit `__wasi_sleep_ms` after lib-globals scan. */
1783
+ wasiPendingSleepMsHelper?: boolean;
1784
+ /** (#2632) Pending flag — register timer heap + run-loop reactor after lib-globals scan. */
1785
+ wasiPendingTimerHeap?: boolean;
1786
+ /** (#2632 Phase 2) Pending flag — activate the fd0 stdin reactor (multi-sub poll + internal buffer) before timer-heap registration. */
1787
+ wasiPendingStdinReactor?: boolean;
1788
+ /** Set of node:fs functions used in this compilation unit (both WASI and JS-host fs paths). */
1789
+ wasiNodeFsFuncs: Set<string>;
1790
+ /** (#2657) Local names imported from `"wasi_snapshot_preview1"` — the raw-WASI
1791
+ * fd_read/fd_write passthrough bindings (loopdive/js2#389). Empty for any
1792
+ * program that does not import the raw WASI module. */
1793
+ wasiRawImports: Set<string>;
1794
+ /** (#2657) Local names imported from `"wasm:memory"` — js2wasm's inline
1795
+ * linear-memory access intrinsics (`store32`/`load32`/`store8`/`load8`). Empty
1796
+ * for any program that does not import the intrinsic module. */
1797
+ wasiMemAccessors: Set<string>;
1798
+ /**
1799
+ * #1886 — Linear-safe `Uint8Array` analysis result. Populated (WASI/standalone
1800
+ * only) by `analyzeLinearUint8` as a pre-pass; `undefined` otherwise. Symbols
1801
+ * in `linearUint8.safeBindings` are byte buffers proven to never escape the
1802
+ * GC heap, so codegen backs them by linear memory (a `(ptr,len)` pair) with
1803
+ * zero-copy `fd_read`/`fd_write`. Every consumer is additive — when this is
1804
+ * `undefined` or a binding is absent, the existing GC-vec path is used
1805
+ * unchanged. (Codegen consumers land in later slices; the analysis itself is
1806
+ * side-effect free and safe to run unconditionally behind the WASI gate.)
1807
+ */
1808
+ linearUint8?: import('../linear-uint8-analysis.js').LinearUint8Result;
1809
+ /**
1810
+ * #2660 S1 — whole-program escape / dynamic-use classification for `new F()`
1811
+ * function-constructor instances. Each site is classified `reconstruct`
1812
+ * (dynamically consumed AND no typed own-field consumer → S3 `$Object`
1813
+ * reconstruction candidate), `keep-typed` (has a typed own-field consumer →
1814
+ * never reconstruct, hot-path protection), or `keep-static` (no dynamic
1815
+ * consumer → no reconstruction needed). **INERT in S1** — produced by
1816
+ * `analyzeFnctorEscapeGate` and stored here, but NOT yet consumed by any
1817
+ * lowering decision (S3 wires `compileNewFunctionDeclaration` to read it). The
1818
+ * conservative default (`keep`) means an empty/imprecise result leaves emitted
1819
+ * Wasm byte-identical.
1820
+ */
1821
+ fnctorEscapeGate?: import('../fnctor-escape-gate.js').FnctorEscapeGateResult;
1822
+ /**
1823
+ * #1886 Slice B — Func index of the lazily-emitted
1824
+ * `__lin_u8_alloc(len:i32)->i32` bump allocator for linear-backed Uint8Array
1825
+ * buffers (`undefined` = not yet emitted). Allocates from a dedicated page-4
1826
+ * arena pointed at by `$__lin_u8_arena_ptr` (NOT the page-0 string-literal
1827
+ * `$__wasi_bump_ptr`, which would alias literal data). Reuses the #1856
1828
+ * align8 + on-demand `memory.grow` idiom (see `codegen-linear/runtime.ts
1829
+ * addRuntime`), emitted here because the WasmGC front-end owns its own
1830
+ * memory/globals and cannot call the linear backend's module bootstrap.
1831
+ */
1832
+ linearU8AllocFuncIdx?: number;
1833
+ /**
1834
+ * #1886 Slice B — func-type index for `__lin_u8_alloc`'s `(i32)->(i32)`
1835
+ * signature, reserved eagerly (before any GC struct/array or native-string
1836
+ * helper type) so the shared type-table prefix stays stable. The allocator
1837
+ * function is emitted later and reuses this slot. See reserveLinearU8AllocType.
1838
+ */
1839
+ linearU8AllocTypeIdx?: number;
1840
+ /**
1841
+ * (#2026 #53) Eagerly-reserved `$ObjVecArr` = `(array (mut externref))` type
1842
+ * index, registered in the up-front type-init phase (`reserveObjVecArrType`)
1843
+ * when the source declares a class. The dynamic-`new` runtime-argv path
1844
+ * (`emitDynamicNewFallback`) and `ensureObjectRuntime` both ADOPT this slot
1845
+ * instead of minting the type lazily mid-expression — minting it late baked an
1846
+ * unresolved `-1` heap-type ref (the #2043 / subview type-idx-stability hazard).
1847
+ */
1848
+ reservedObjVecArrTypeIdx?: number;
1849
+ /** #1886 Slice B — global index of the page-4 linear-U8 arena bump pointer. */
1850
+ linearU8ArenaGlobalIdx?: number;
1851
+ /** Whether `node:fs` JS-host imports are permitted (non-WASI target only, #1491). */
1852
+ allowFs: boolean;
1853
+ /**
1854
+ * #1524 — When true, `addImport` rejects any JS-host `env` import that is
1855
+ * not on the dual-mode allowlist (`src/codegen/host-import-allowlist.ts`).
1856
+ * Auto-enabled when `wasi: true` (unless the caller passes
1857
+ * `strictNoHostImports: false` explicitly). Drives the architectural gate
1858
+ * documented under "Architecture Principles → JS host optional" in CLAUDE.md.
1859
+ */
1860
+ strictNoHostImports: boolean;
1861
+ /** Map from let/const module global variable name → TDZ flag global index */
1862
+ tdzGlobals: Map<string, number>;
1863
+ /** Set of let/const module global variable names */
1864
+ tdzLetConstNames: Set<string>;
1865
+ /** Compile-time property descriptor flags */
1866
+ definedPropertyFlags: Map<string, number>;
1867
+ /** Properties whose descriptor/value lives in the runtime sidecar. */
1868
+ sidecarDefinedPropertyKeys: Set<string>;
1869
+ /**
1870
+ * (#2726) `varName:propName` keys for which `Object.defineProperty` was
1871
+ * statically observed on an identifier receiver — recorded uniformly across
1872
+ * EVERY defineProperty lowering path (inline data, inline accessor fast path,
1873
+ * runtime-descriptor, etc.). Used ONLY to route `hasOwnProperty` /
1874
+ * `propertyIsEnumerable` to the runtime helper instead of constant-folding
1875
+ * against the (defineProperty-widened) static struct shape: a configurable
1876
+ * `delete` records a `_wasmStructDeletedKeys` tombstone the compile-time
1877
+ * shape answer can't see. Kept SEPARATE from `definedPropertyFlags` /
1878
+ * `sidecarDefinedPropertyKeys` so it never perturbs descriptor-flag or
1879
+ * `getOwnPropertyDescriptor` routing — it is a presence-routing signal only.
1880
+ */
1881
+ definePropertyReceiverKeys: Set<string>;
1882
+ /**
1883
+ * (#2726) `varName:propName` keys defined as a NON-configurable ACCESSOR via
1884
+ * the inline-accessor `Object.defineProperty` fast path on a statically
1885
+ * struct-typed receiver. That path compiles the getter/setter into a
1886
+ * `${struct}_get/set_<prop>` function + `classAccessorSet` and — unlike the
1887
+ * data fast path — never mirrors the descriptor's `configurable` flag into the
1888
+ * runtime `_wasmPropDescs` sidecar, so the host `__delete_property` can't see
1889
+ * it and wrongly reports a successful delete. The struct-field `delete` site
1890
+ * consults this set to emit OrdinaryDelete's refusal (return `false`; strict
1891
+ * mode ⇒ TypeError) for `delete obj.accessor` of a non-configurable accessor
1892
+ * (#2726 group (d): `11.4.1-4-a-2-s`). Consumed ONLY by the delete site.
1893
+ */
1894
+ nonConfigurableAccessorKeys: Set<string>;
1895
+ /** Object mutability state sets */
1896
+ nonExtensibleVars: Set<string>;
1897
+ frozenVars: Set<string>;
1898
+ sealedVars: Set<string>;
1899
+ /** Per-shape default property flags table */
1900
+ shapePropFlags: Map<number, Uint8Array>;
1901
+ /** Cache for function-constructor struct types */
1902
+ funcConstructorMap: Map<string, {
1903
+ structTypeIdx: number;
1904
+ ctorFuncName: string;
1905
+ }>;
1906
+ /**
1907
+ * (#2660 S2) Per-fnctor prototype `$Object` — fnctor symbol name → module
1908
+ * global index (`mut externref`) holding a native `$Object` for `F.prototype`.
1909
+ * Synthesized on the first `F.prototype` read/write in standalone mode so
1910
+ * `Object.create(F.prototype)` resolves and #2660 S3 can seed `instance.$proto`
1911
+ * from it. Empty/unused in host/GC mode (the prototype stays on the closure).
1912
+ */
1913
+ fnctorPrototypeObject: Map<string, number>;
1914
+ /** Per-compilation recursion guard for ensureStructForType (prevents infinite loops on circular types) */
1915
+ ensureStructPending: Set<ts.Type>;
1916
+ /** Node builtin modules registered as externref globals (#1044) */
1917
+ nodeBuiltinGlobals: Map<string, number>;
1918
+ /**
1919
+ * JSX runtime import detected during preprocessing (#1540). The codegen
1920
+ * intercepts call expressions whose callee identifier matches one of the
1921
+ * recorded local names (`localJsx`/`localJsxs`/`localJsxDev`) and routes
1922
+ * them to the matching `__jsx_runtime_*` host import. The `Fragment`
1923
+ * binding is exposed as a no-arg externref-returning function under
1924
+ * `nodeBuiltinGlobals` so identifier resolution treats it like any
1925
+ * declared externref.
1926
+ */
1927
+ jsxRuntime?: import('../../import-resolver.js').JsxRuntimeImport;
1928
+ /**
1929
+ * #1261 — module-wide worst-case eval tier (1=no eval … 5=direct sloppy).
1930
+ * Computed read-only by `classifyEvalTier`; downstream optimization gating
1931
+ * (#1262–#1265) consumes it. Optional because not every context constructs
1932
+ * from a full source file.
1933
+ */
1934
+ evalTier?: import('../eval-tiering.js').EvalTier;
1935
+ }
1936
+ export type { SourcePos };