@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
package/dist/cli.js ADDED
@@ -0,0 +1,363 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
+ import { readFileSync, writeFileSync } from "node:fs";
4
+ import { resolve, basename, dirname } from "node:path";
5
+ function getCliVersion() {
6
+ const bundledVersion = typeof __JS2WASM_CLI_VERSION__ === "string" ? __JS2WASM_CLI_VERSION__ : void 0;
7
+ if (bundledVersion) return bundledVersion;
8
+ const require2 = createRequire(import.meta.url);
9
+ const pkg = require2("../package.json");
10
+ return pkg.version ?? "0.0.0";
11
+ }
12
+ const args = process.argv.slice(2);
13
+ if (args.includes("--ts7")) {
14
+ process.env.JS2WASM_TS7 = "1";
15
+ }
16
+ const { compile } = await import("./index.js");
17
+ const { buildDefaultDefines } = await import("./define-substitution-BcUeKC2A.js").then((n) => n.d);
18
+ if (args.includes("--version") || args.includes("-v")) {
19
+ console.log(getCliVersion());
20
+ process.exit(0);
21
+ }
22
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
23
+ console.log(`Usage: js2wasm <input.ts> [options]
24
+
25
+ Compile a TypeScript file to WebAssembly (GC proposal).
26
+
27
+ Options:
28
+ -o, --out <dir> Output directory (default: same as input)
29
+ --target <t> Host/output target — the single host axis (#2736):
30
+ web (default) WasmGC / JS-host browser surface (DOM
31
+ ambient globals in scope);
32
+ node a real Node host (Node ambient surface, no DOM);
33
+ deno a real Deno host (Deno ambient surface, no DOM);
34
+ wasi standalone WASI Preview 1 (fd-based host calls).
35
+ Also accepts the backend-lowering names gc / linear /
36
+ standalone (orthogonal backend choice; gc is the default
37
+ backend for web/node/deno).
38
+ --standalone Shorthand for --target standalone (pure WasmGC, no JS host,
39
+ no WASI). Forces nativeStrings: true and refuses to emit
40
+ wasm:js-string or env JS-host imports.
41
+ --allocator <a> Linear backend allocator (#1856): bump (default,
42
+ allocate-and-exit arena, smallest binary) or arena-reset
43
+ (same arena + __arena_reset/__arena_used exports for hosts
44
+ reusing one instance across short-lived tasks). Linear
45
+ target only.
46
+ --allow-fs Allow node:fs JS-host imports (readFileSync, writeFileSync)
47
+ for non-WASI targets (#1491). Off by default to prevent
48
+ accidental capability leakage.
49
+ --utf8-storage Dual i8/i16 string storage (#1588): store strings proven
50
+ UTF-8 (literals, JSON, decoder results, ...) as i8-backed
51
+ Utf8String for a cheaper Component Model boundary. Implies
52
+ nativeStrings on the WasmGC backend. Off by default
53
+ (byte-identical output when off).
54
+ --wat Emit only WAT (no binary)
55
+ --no-wat Skip WAT output
56
+ --no-dts Skip .d.ts output
57
+ --wit Generate WIT interface file for Component Model
58
+ --wit-package <p> Package name for --wit output (ns:name[@version]).
59
+ Implies --wit. Defaults to js2wasm:<input-basename>.
60
+ -v, --verbose List every dropped host-import warning individually instead
61
+ of collapsing them into a one-line summary (WASI/strict mode)
62
+ -O, --optimize Run Binaryen wasm-opt optimizer (on by default at -O3)
63
+ -O1..-O4 Set optimization level (1-4)
64
+ --no-optimize, -O0
65
+ Disable the optimizer; emit raw codegen output. Optimization
66
+ is ON by default; this restores the pre-#1950 behaviour.
67
+ (No-op when binaryen/wasm-opt is unavailable — that path
68
+ already degrades to a one-line note, never a failure.)
69
+ --link-node-shims (WASI, #2625/#2633) Emit the per-module linkable node:<mod>
70
+ shims instead of inlining the host APIs. Std-IO goes through
71
+ node:fs: the module imports readSync/writeSync + its memory
72
+ from node:fs (no wasi_snapshot_preview1 for stream IO) and
73
+ links node-fs.wasm. console.log / process.std*.write lower to
74
+ writeSync(1|2, …); stdin is readSync(0, …). Off by default —
75
+ the inline fd_read/fd_write path is self-contained.
76
+ --emulate <env> Emulate a host runtime's globals so they type-check without
77
+ @types/node. 'node' = ambient process/etc.; 'none' = off.
78
+ Auto-enabled (type-level only) when the source imports a
79
+ 'node:' builtin (use 'none' to disable that); otherwise off,
80
+ and using process warns to add this flag (#2603).
81
+ --platform <p> DEPRECATED (#2736): alias for --target {web,node,deno}.
82
+ 'web' = DOM globals (window/document/…) in scope (today's
83
+ default); 'node'/'deno' = DOM globals NOT in scope (so
84
+ window.stop is a type error) and Node-style API emulation on
85
+ (implies --emulate node). Prefer --target; this prints a
86
+ deprecation warning. Unset preserves today's behaviour.
87
+ --no-host-imports Strict dual-mode: reject JS-host 'env' imports not on
88
+ the allowlist (#1524). Implied by --target wasi.
89
+ --allow-host-imports
90
+ Escape hatch: disable strict dual-mode for a WASI build
91
+ (debug-only). Useful when temporarily mixing host + WASI
92
+ imports while migrating to standalone mode.
93
+ --define K=V Substitute identifier path K with literal V before parsing.
94
+ Repeatable. Example:
95
+ --define process.env.NODE_ENV='"production"'
96
+ String values must include their own quotes.
97
+ --mode <m> Shorthand for --define-style production/development build.
98
+ 'production' sets process.env.NODE_ENV="production" and
99
+ typeof process / typeof window to "undefined".
100
+ 'development' sets process.env.NODE_ENV="development".
101
+ --ts7 Use @typescript/native-preview (TypeScript 7 Go-port) as
102
+ the parser/checker frontend (preview; full migration
103
+ tracked in #1029). Equivalent to JS2WASM_TS7=1.
104
+ -q, --quiet Suppress the post-compile "how to run" hint
105
+ -v, --version Print version and exit
106
+ -h, --help Show this help
107
+
108
+ Output files:
109
+ <name>.wasm WebAssembly binary
110
+ <name>.wat WebAssembly text format
111
+ <name>.d.ts TypeScript declarations
112
+ <name>.imports.js createImports() helper`);
113
+ process.exit(0);
114
+ }
115
+ let inputPath;
116
+ let outDir;
117
+ let emitWat = true;
118
+ let emitDts = true;
119
+ let watOnly = false;
120
+ let verbose = false;
121
+ let optimize = 3;
122
+ let target;
123
+ let allocator;
124
+ let emitWit = false;
125
+ let witPackageName;
126
+ let allowFs = false;
127
+ let quiet = false;
128
+ let utf8Storage = false;
129
+ let strictNoHostImports;
130
+ let linkNodeShims = false;
131
+ let emulateNode = false;
132
+ let emulateExplicit = false;
133
+ let platform;
134
+ const defines = {};
135
+ for (let i = 0; i < args.length; i++) {
136
+ const arg = args[i];
137
+ if (arg === "-o" || arg === "--out") {
138
+ outDir = args[++i];
139
+ } else if (arg === "--target" || arg.startsWith("--target=")) {
140
+ const t = arg.startsWith("--target=") ? arg.slice("--target=".length) : args[++i];
141
+ if (t === "gc" || t === "linear" || t === "wasi" || t === "standalone") {
142
+ target = t;
143
+ } else if (t === "web" || t === "node" || t === "deno") {
144
+ platform = t;
145
+ } else {
146
+ console.error(`Unknown target: ${t} (expected web, node, deno, wasi, gc, linear, or standalone)`);
147
+ process.exit(1);
148
+ }
149
+ } else if (arg === "--standalone") {
150
+ target = "standalone";
151
+ } else if (arg === "--allocator") {
152
+ const a = args[++i];
153
+ if (a === "bump" || a === "arena-reset") {
154
+ allocator = a;
155
+ } else {
156
+ console.error(`Unknown allocator: ${a} (expected bump or arena-reset)`);
157
+ process.exit(1);
158
+ }
159
+ } else if (arg === "--wat") {
160
+ watOnly = true;
161
+ } else if (arg === "--no-wat") {
162
+ emitWat = false;
163
+ } else if (arg === "--no-dts") {
164
+ emitDts = false;
165
+ } else if (arg === "--wit") {
166
+ emitWit = true;
167
+ } else if (arg === "--wit-package") {
168
+ const pkg = args[++i];
169
+ if (!pkg) {
170
+ console.error("--wit-package requires a package name argument");
171
+ process.exit(1);
172
+ }
173
+ witPackageName = pkg;
174
+ emitWit = true;
175
+ } else if (arg.startsWith("--wit-package=")) {
176
+ const pkg = arg.slice("--wit-package=".length);
177
+ if (!pkg) {
178
+ console.error("--wit-package requires a package name argument");
179
+ process.exit(1);
180
+ }
181
+ witPackageName = pkg;
182
+ emitWit = true;
183
+ } else if (arg === "--allow-fs") {
184
+ allowFs = true;
185
+ } else if (arg === "--quiet" || arg === "-q") {
186
+ quiet = true;
187
+ } else if (arg === "--utf8-storage") {
188
+ utf8Storage = true;
189
+ } else if (arg === "--link-node-shims") {
190
+ linkNodeShims = true;
191
+ } else if (arg === "--emulate" || arg.startsWith("--emulate=")) {
192
+ const env = arg.startsWith("--emulate=") ? arg.slice("--emulate=".length) : args[++i];
193
+ if (env === "node") {
194
+ emulateNode = true;
195
+ emulateExplicit = true;
196
+ } else if (env === "none") {
197
+ emulateNode = false;
198
+ emulateExplicit = true;
199
+ } else {
200
+ console.error(`Unknown --emulate value: ${env ?? "(missing)"} (expected: node | none)`);
201
+ process.exit(1);
202
+ }
203
+ } else if (arg === "--platform" || arg.startsWith("--platform=")) {
204
+ const p = arg.startsWith("--platform=") ? arg.slice("--platform=".length) : args[++i];
205
+ if (p === "node" || p === "web" || p === "deno") {
206
+ platform = p;
207
+ console.error(`warning: --platform is deprecated; use --target ${p} instead.`);
208
+ } else {
209
+ console.error(`Unknown --platform value: ${p ?? "(missing)"} (expected: node | web | deno)`);
210
+ process.exit(1);
211
+ }
212
+ } else if (arg === "--no-host-imports") {
213
+ strictNoHostImports = true;
214
+ } else if (arg === "--allow-host-imports") {
215
+ strictNoHostImports = false;
216
+ } else if (arg === "--verbose" || arg === "-v") {
217
+ verbose = true;
218
+ } else if (arg === "-O" || arg === "--optimize") {
219
+ optimize = true;
220
+ } else if (arg === "--no-optimize" || arg === "-O0") {
221
+ optimize = false;
222
+ } else if (/^-O[1-4]$/.test(arg)) {
223
+ optimize = parseInt(arg.slice(2));
224
+ } else if (arg === "--define") {
225
+ const kv = args[++i];
226
+ if (!kv) {
227
+ console.error("--define requires a KEY=VALUE argument");
228
+ process.exit(1);
229
+ }
230
+ const eq = kv.indexOf("=");
231
+ if (eq < 0) {
232
+ console.error(`--define expected KEY=VALUE, got: ${kv}`);
233
+ process.exit(1);
234
+ }
235
+ defines[kv.slice(0, eq)] = kv.slice(eq + 1);
236
+ } else if (arg.startsWith("--define=")) {
237
+ const kv = arg.slice("--define=".length);
238
+ const eq = kv.indexOf("=");
239
+ if (eq < 0) {
240
+ console.error(`--define expected KEY=VALUE, got: ${kv}`);
241
+ process.exit(1);
242
+ }
243
+ defines[kv.slice(0, eq)] = kv.slice(eq + 1);
244
+ } else if (arg === "--mode") {
245
+ const m = args[++i];
246
+ if (m !== "production" && m !== "development") {
247
+ console.error(`Unknown --mode: ${m} (expected production or development)`);
248
+ process.exit(1);
249
+ }
250
+ Object.assign(defines, buildDefaultDefines(m));
251
+ } else if (arg === "--ts7") ;
252
+ else if (!arg.startsWith("-")) {
253
+ inputPath = arg;
254
+ } else {
255
+ console.error(`Unknown option: ${arg}`);
256
+ process.exit(1);
257
+ }
258
+ }
259
+ if (!inputPath) {
260
+ console.error("Error: no input file specified");
261
+ process.exit(1);
262
+ }
263
+ if (target === "standalone" && allowFs) {
264
+ console.error("error: --standalone and --allow-fs are mutually exclusive");
265
+ process.exit(1);
266
+ }
267
+ if (allocator !== void 0 && target !== "linear") {
268
+ console.error("error: --allocator requires --target linear");
269
+ process.exit(1);
270
+ }
271
+ const absInput = resolve(inputPath);
272
+ const source = readFileSync(absInput, "utf-8");
273
+ if (!emulateExplicit && !emulateNode && /['"]node:[A-Za-z0-9_./-]+['"]/.test(source)) {
274
+ emulateNode = true;
275
+ console.error("note: auto-enabled Node API emulation (found a `node:` import). Pass --emulate none to disable.");
276
+ }
277
+ const name = basename(absInput, ".ts");
278
+ const dir = outDir ? resolve(outDir) : dirname(absInput);
279
+ const result = await compile(source, {
280
+ ...optimize ? { optimize } : {},
281
+ ...target ? { target } : {},
282
+ ...allocator ? { allocator } : {},
283
+ ...emitWit ? { wit: witPackageName ? { packageName: witPackageName } : true } : {},
284
+ ...allowFs ? { allowFs: true } : {},
285
+ ...utf8Storage ? { utf8Storage: true } : {},
286
+ ...linkNodeShims ? { linkNodeShims: true } : {},
287
+ ...emulateNode ? { emulateNode: true } : {},
288
+ ...platform ? { platform } : {},
289
+ fileName: absInput,
290
+ ...strictNoHostImports !== void 0 ? { strictNoHostImports } : {},
291
+ ...Object.keys(defines).length > 0 ? { define: defines } : {}
292
+ });
293
+ if (!result.success) {
294
+ for (const e of result.errors) {
295
+ const severity = e.severity === "warning" ? "warning" : "error";
296
+ const where = e.file ?? absInput;
297
+ console.error(`${where}:${e.line}:${e.column} - ${severity}: ${e.message}`);
298
+ }
299
+ process.exit(1);
300
+ }
301
+ const isAllowlistWarning = (msg) => msg.includes("not on the dual-mode allowlist");
302
+ let suppressedAllowlist = 0;
303
+ const warnCounts = /* @__PURE__ */ new Map();
304
+ for (const e of result.errors) {
305
+ if (e.severity !== "warning") continue;
306
+ if (!verbose && isAllowlistWarning(e.message)) {
307
+ suppressedAllowlist++;
308
+ continue;
309
+ }
310
+ warnCounts.set(e.message, (warnCounts.get(e.message) ?? 0) + 1);
311
+ }
312
+ for (const [msg, count] of warnCounts) {
313
+ console.error(count > 1 ? `warning: ${msg} (${count}×)` : `warning: ${msg}`);
314
+ }
315
+ if (suppressedAllowlist > 0) {
316
+ console.error(
317
+ `warning: ${suppressedAllowlist} host import(s) not on the dual-mode allowlist were dropped (no-op under WASI/strict mode; not in the emitted .wasm). Re-run with --verbose to list them.`
318
+ );
319
+ }
320
+ if (watOnly) {
321
+ process.stdout.write(result.wat);
322
+ process.exit(0);
323
+ }
324
+ let emittedWasmPath;
325
+ {
326
+ const wasmPath = resolve(dir, `${name}.wasm`);
327
+ writeFileSync(wasmPath, result.binary);
328
+ console.log(`${wasmPath} (${result.binary.byteLength} bytes)`);
329
+ emittedWasmPath = wasmPath;
330
+ }
331
+ if (emitWat) {
332
+ const watPath = resolve(dir, `${name}.wat`);
333
+ writeFileSync(watPath, result.wat);
334
+ console.log(`${watPath} (${result.wat.length} chars)`);
335
+ }
336
+ if (emitDts) {
337
+ const dtsPath = resolve(dir, `${name}.d.ts`);
338
+ writeFileSync(dtsPath, result.dts);
339
+ console.log(`${dtsPath} (${result.dts.length} chars)`);
340
+ }
341
+ {
342
+ const helperPath = resolve(dir, `${name}.imports.js`);
343
+ writeFileSync(helperPath, result.importsHelper);
344
+ console.log(`${helperPath} (${result.importsHelper.length} chars)`);
345
+ }
346
+ if (emitWit && result.wit) {
347
+ const witPath = resolve(dir, `${name}.wit`);
348
+ writeFileSync(witPath, result.wit);
349
+ console.log(`${witPath} (${result.wit.length} chars)`);
350
+ }
351
+ if (!quiet && emittedWasmPath) {
352
+ if (target === "wasi" || target === "standalone" || target === "linear") {
353
+ console.log(`
354
+ To run: wasmtime -W gc=y,function-references=y,tail-call=y,exceptions=y ${emittedWasmPath}`);
355
+ } else {
356
+ console.log(
357
+ `
358
+ This is a JS-host build (default --target gc) — it needs the generated ${name}.imports.js helper. To run with Node.js:
359
+ node --experimental-wasm-imported-strings -e "import('./${name}.imports.js').then(async ({ createImports }) => { const { instance } = await WebAssembly.instantiate(require('fs').readFileSync('${emittedWasmPath}'), createImports()); /* call instance.exports.* */ })"
360
+ For a pure-Wasm build runnable under Wasmtime, recompile with --standalone.`
361
+ );
362
+ }
363
+ }
@@ -0,0 +1,97 @@
1
+ import { CodegenContext } from './context/types.js';
2
+ /** Reserved name for the accessor-get driver (arity-0 getter wrapper). */
3
+ export declare const CALL_ACCESSOR_GET = "__call_accessor_get";
4
+ /** Reserved name for the accessor-set driver (arity-1 setter wrapper). */
5
+ export declare const CALL_ACCESSOR_SET = "__call_accessor_set";
6
+ /**
7
+ * (#2166 PR-D1) Reserved name for the JSON reviver driver (arity-2 method
8
+ * wrapper: `reviver.call(holder, key, value)`).
9
+ */
10
+ export declare const CALL_REVIVER = "__call_reviver";
11
+ /**
12
+ * (#2166 PR-D2) Reserved name for the JSON `toJSON` driver (arity-1 method
13
+ * wrapper: `value.toJSON(key)`).
14
+ */
15
+ export declare const CALL_TO_JSON = "__call_to_json";
16
+ /**
17
+ * (#2166 PR-D3) Reserved name for the JSON `stringify` replacer driver (arity-2
18
+ * method wrapper: `replacer.call(holder, key, value)`).
19
+ */
20
+ export declare const CALL_REPLACER = "__call_replacer";
21
+ /**
22
+ * Reserve the `__call_accessor_get` driver placeholder and return its funcIdx.
23
+ *
24
+ * Signature: `(externref recv, externref getter) -> externref`.
25
+ * The body is left as a bare `unreachable` and filled by `fillAccessorDrivers`
26
+ * in post-processing. The reservation must run while `ensureObjectRuntime` is
27
+ * emitting `__extern_get`, so the append-position funcIdx is stable before any
28
+ * accessor arm emits its `call`.
29
+ *
30
+ * Idempotent: a second call returns the already-reserved funcIdx.
31
+ */
32
+ export declare function reserveAccessorGetDriver(ctx: CodegenContext): number;
33
+ /**
34
+ * Reserve the `__call_accessor_set` driver placeholder and return its funcIdx.
35
+ *
36
+ * Signature: `(externref recv, externref setter, externref value) -> ()`.
37
+ * Setters return no value (the assignment expression result is the RHS, handled
38
+ * at the call site), so the driver result type is empty. Body filled by
39
+ * `fillAccessorDrivers`. Idempotent.
40
+ */
41
+ export declare function reserveAccessorSetDriver(ctx: CodegenContext): number;
42
+ /**
43
+ * (#2166 PR-D1) Reserve the `__call_reviver` driver placeholder and return its
44
+ * funcIdx.
45
+ *
46
+ * Signature: `(externref holder, externref key, externref value) -> externref`.
47
+ * Filled by `fillAccessorDrivers` to wrap `__call_fn_method_2(holder, reviver,
48
+ * key, value)` — but note the reviver closure itself is NOT a driver param: the
49
+ * §25.5.1 walk threads it separately and the driver receives `holder` as the
50
+ * `this` and `key`/`value` as the two reviver args, with the reviver closure
51
+ * passed as the dispatcher's 2nd operand by the codec via a 4th hidden param.
52
+ * To keep the driver arity fixed we instead make the reviver the FIRST arg and
53
+ * holder the receiver: see `fillAccessorDrivers`. Idempotent.
54
+ */
55
+ export declare function reserveReviverDriver(ctx: CodegenContext): number;
56
+ /**
57
+ * (#2166 PR-D2) Reserve the `__call_to_json` driver placeholder and return its
58
+ * funcIdx.
59
+ *
60
+ * Signature: `(externref value, externref method, externref key) -> externref`.
61
+ * Filled by `fillAccessorDrivers` to wrap `__call_fn_method_1(value, method,
62
+ * key)` — `value` bound as the `toJSON` receiver (`this`), `key` the §25.5.2
63
+ * SerializeJSONProperty step-2.b argument. Idempotent.
64
+ */
65
+ export declare function reserveToJsonDriver(ctx: CodegenContext): number;
66
+ /**
67
+ * (#2166 PR-D3) Reserve the `__call_replacer` driver placeholder and return its
68
+ * funcIdx.
69
+ *
70
+ * Signature: `(externref holder, externref replacer, externref key,
71
+ * externref value) -> externref`. The replacer function is invoked as
72
+ * `replacer.call(holder, key, value)` (§25.5.2 SerializeJSONProperty step 3),
73
+ * so `holder` binds as `this` and `key`/`value` are the two arguments — exactly
74
+ * the reviver driver's shape. Filled by `fillAccessorDrivers` wrapping
75
+ * `__call_fn_method_2`. Idempotent.
76
+ */
77
+ export declare function reserveReplacerDriver(ctx: CodegenContext): number;
78
+ /**
79
+ * Fill the reserved accessor driver bodies in post-processing, AFTER
80
+ * `emitClosureMethodCallExportN(0)` / `(1)` have registered
81
+ * `__call_fn_method_0` / `__call_fn_method_1` in `funcMap`. Each driver is a
82
+ * thin wrapper that forwards to the matching closure-method dispatcher, reusing
83
+ * the proven re-entrancy-safe `__current_this` install/restore (#1636-S1)
84
+ * instead of duplicating funcref-type dispatch inside the object runtime:
85
+ *
86
+ * __call_accessor_get(recv, getter) = return __call_fn_method_0(recv, getter)
87
+ * __call_accessor_set(recv, setter, value) =
88
+ * __call_fn_method_1(recv, setter, value) ; drop result
89
+ *
90
+ * No-op when the corresponding driver was never reserved (no accessor arm
91
+ * needs it). When the driver WAS reserved but the matching dispatcher was never
92
+ * emitted (no closure of that arity exists — so no real getter/setter closure
93
+ * could have been installed either), the body is filled with a valid fallback
94
+ * (return-undefined for get; bare return for set) so the module still verifies —
95
+ * mirrors `fillProtoIteratorDriver`'s null fallback.
96
+ */
97
+ export declare function fillAccessorDrivers(ctx: CodegenContext): void;
@@ -0,0 +1,72 @@
1
+ import { ValType } from '../ir/types.js';
2
+ import { CodegenContext, FunctionContext } from './context/types.js';
3
+ /**
4
+ * Register the $AnyValue struct type for boxing `any` typed values.
5
+ * The struct has a tag field to distinguish the boxed type at runtime,
6
+ * plus payload fields for each possible value kind.
7
+ *
8
+ * Called lazily — only emitted when the module actually uses `any`-typed values.
9
+ */
10
+ export declare function ensureAnyValueType(ctx: CodegenContext): void;
11
+ /**
12
+ * (#2106 S1.0) Push the standalone `$undefined` singleton (a `ref $AnyValue`,
13
+ * tag 1) onto the stack. Returns `false` (emitting nothing) when not in
14
+ * standalone/native-strings mode or the singleton was not reserved — callers
15
+ * then fall back to their existing `ref.null.extern` / host-`__get_undefined`
16
+ * path. INERT until S1.1 routes `emitUndefined` here.
17
+ */
18
+ export declare function emitUndefinedSingleton(ctx: CodegenContext, fctx: FunctionContext): boolean;
19
+ /**
20
+ * (#2106 S1.0) Test whether the `ref $AnyValue` on top of the stack is the
21
+ * `$undefined` singleton (tag === 1). Consumes the ref, leaves an i32. Returns
22
+ * `false` (emitting nothing) when the singleton is unavailable. INERT until S1.1
23
+ * routes the `=== undefined` / `typeof === "undefined"` consumers here.
24
+ */
25
+ export declare function emitIsUndefinedSingleton(ctx: CodegenContext, fctx: FunctionContext): boolean;
26
+ /**
27
+ * Lazily register wrapper struct types for Number, String, Boolean.
28
+ * Each wrapper is a struct with a single `value` field holding the primitive.
29
+ * Also registers WrapperX_valueOf functions that extract the value.
30
+ * Must be called before resolveWasmType is used for wrapper types.
31
+ */
32
+ export declare function ensureWrapperTypes(ctx: CodegenContext): void;
33
+ /**
34
+ * Emit valueOf helper functions for wrapper types.
35
+ * Must be called after all imports are registered (so function indices are stable)
36
+ * but before user functions that call valueOf.
37
+ */
38
+ export declare function emitWrapperValueOfFunctions(ctx: CodegenContext): void;
39
+ /**
40
+ * Check if a ValType represents a boxed `any` value (ref $AnyValue).
41
+ */
42
+ export declare function isAnyValue(type: ValType, ctx: CodegenContext): boolean;
43
+ export declare function ensureAnyFromExternHelper(ctx: CodegenContext): number | undefined;
44
+ /**
45
+ * (#1461/#54) Native standalone `(externref, externref) -> i32` strict-equality
46
+ * (`===`, StrictEqualityComparison) over two boxed externref values. The pure-Wasm
47
+ * replacement for the `__host_eq` host import in the array-like search arm
48
+ * (`indexOf`/`lastIndexOf`). Composes the two existing engine-owned helpers:
49
+ * `__any_from_extern` (recovers a boxed externref primitive — number/boolean/
50
+ * string/null/object — into a uniform `(ref $AnyValue)`) then `__any_strict_eq`
51
+ * (===-compares two `$AnyValue`, numeric class unified via `f64.eq` ⇒ NaN≠NaN,
52
+ * strings by content, objects by identity). Standalone-only; returns undefined
53
+ * otherwise (caller keeps the host import).
54
+ */
55
+ export declare function ensureExternStrictEqHelper(ctx: CodegenContext): number | undefined;
56
+ /**
57
+ * (#1461/#54) Native standalone `(externref, externref) -> i32` SameValueZero
58
+ * (§7.2.11) over two boxed externref values — the pure-Wasm replacement for the
59
+ * `__same_value_zero` host import in the array-like `includes` search arm.
60
+ * SameValueZero differs from `===` ONLY in `NaN`: SameValueZero(NaN, NaN) is
61
+ * true (and +0/−0 are equal under both, which `f64.eq` already gives). So:
62
+ * `__extern_strict_eq(a, b) || (a and b are both NaN numbers)`. The NaN test
63
+ * recovers both via `__any_from_extern`, checks tag ∈ {2,3} (number) and the
64
+ * f64 self-inequality (`x !== x`).
65
+ */
66
+ export declare function ensureExternSameValueZeroHelper(ctx: CodegenContext): number | undefined;
67
+ export declare function ensureAnyToExternHelper(ctx: CodegenContext): number | undefined;
68
+ /**
69
+ * Emit inline wasm helper functions for boxing/unboxing `any` values.
70
+ * Called lazily when any-typed operations are first encountered.
71
+ */
72
+ export declare function ensureAnyHelpers(ctx: CodegenContext): void;
@@ -0,0 +1,46 @@
1
+ import { ts } from '../ts-api.js';
2
+ /**
3
+ * Return true if `expr` provably produces a 32-bit signed integer at runtime,
4
+ * given that `i32Locals` is the set of locals already known to hold i32.
5
+ *
6
+ * Recognised i32-safe forms (mirrors `isI32SafeExpr` in function-body.ts but
7
+ * is intentionally narrower — we err on the side of disqualification):
8
+ * - integer numeric literal in [-2^31, 2^31)
9
+ * - identifier referencing a known-i32 local
10
+ * - bitwise `|`, `&`, `^`, `<<`, `>>` (always produce int32 per ECMAScript)
11
+ * - comparison ops (return boolean = i32)
12
+ * - unary `+` / `-` / `~` of an i32-safe operand
13
+ * - `+` / `-` / `*` of two i32-safe operands (overflow wraps; receiver is i32)
14
+ * - parenthesised / `as`-cast / non-null-asserted i32-safe expr
15
+ *
16
+ * Note: `>>>` is intentionally excluded — it produces uint32 which can sit
17
+ * above 2^31 and would be reinterpreted as a negative i32 on store. The
18
+ * conservative choice is to disqualify (the array would then stay f64).
19
+ */
20
+ export declare function isI32SafeExprForArray(expr: ts.Expression | undefined, i32Locals: ReadonlySet<string>, depth?: number): boolean;
21
+ /**
22
+ * Compute the set of `let arr: number[] = []`-style locals in `decl` whose
23
+ * element storage can safely lower to `i32` instead of `f64`.
24
+ *
25
+ * Pre-conditions for promotion (all must hold):
26
+ * 1. The declaration has an explicit `number[]` (or `Array<number>`) type
27
+ * annotation. Without the annotation, downstream codegen still picks
28
+ * f64 from the contextual type and the override would not flow to the
29
+ * assignment-site `compileExpression(value, arrDef.element)` path.
30
+ * 2. The initializer is `[]`, `new Array(n?)`, or `Array(n?)`.
31
+ * 3. The local is not captured in any nested function (closures break
32
+ * cross-scope type assumptions, exactly as for #1120 scalar locals).
33
+ * 4. The local is never used outside whitelisted positions:
34
+ * - `arr[i]` (read) (parent: ElementAccessExpression as receiver)
35
+ * - `arr[i] = E` (parent of `arr` is the LHS access)
36
+ * - `arr.length` (PropertyAccessExpression as receiver)
37
+ * - `arr.push(E)` / `arr[i]++` / etc. — only `arr.push(E)` is allowed,
38
+ * and only when E is i32-safe. All other method calls disqualify.
39
+ * 5. Every `arr[i] = E` has E i32-safe per `isI32SafeExprForArray`.
40
+ * 6. The local is never the LHS of a plain assignment (`arr = ...` after
41
+ * the declaration) — the candidate-collection step already restricts
42
+ * to let/const, but a single-let `let arr: number[]` could still be
43
+ * reassigned. We catch this in the use scan because a bare identifier
44
+ * reference on the LHS of `=` is not in the whitelist.
45
+ */
46
+ export declare function collectI32SpecializedArrays(decl: ts.FunctionLikeDeclaration, i32CoercedLocals: ReadonlySet<string>): Set<string>;
@@ -0,0 +1,69 @@
1
+ import { ts } from '../ts-api.js';
2
+ import { CodegenContext, FunctionContext } from './context/types.js';
3
+ import { Instr } from '../ir/types.js';
4
+ /**
5
+ * Cheap AST pre-scan: set `ctx.usesArrayHoles` when the program contains any
6
+ * array-literal elision (`OmittedExpression`). Runs once before body
7
+ * compilation (mirrors `scanForNewTarget`). When clear — the common case — the
8
+ * hole read-guard is never emitted and every array read stays byte-identical.
9
+ *
10
+ * Setting the flag in a pre-pass (rather than lazily at the first hole-store)
11
+ * is what lets a `a[i]` element *read* in one function emit the `$Hole → undefined`
12
+ * guard even though the hole-bearing literal lives in a *different* function
13
+ * compiled later — function compilation order is not source order, so a per-site
14
+ * lazy flag would desync reads against stores.
15
+ */
16
+ export declare function scanForArrayHoles(ctx: CodegenContext, root: ts.Node): void;
17
+ /**
18
+ * Lazily register the `$Hole` struct type and the `$__hole` singleton global.
19
+ * Idempotent — returns the absolute global index, caches both the type index
20
+ * (`ctx.holeTypeIdx`) and the global index (`ctx.holeGlobalIdx`).
21
+ *
22
+ * Registered **late** (during body compilation, after class collection) and
23
+ * **once**, per `project_type_index_shift_and_deadelim`: pushing a struct type
24
+ * mid-class-collection would desync class struct typeidxs. Both call sites
25
+ * (literal store + element read) run inside `compileDeclarations`, so the type
26
+ * is always appended after the class struct types are fixed.
27
+ *
28
+ * The global is **immutable** with a constant `struct.new $Hole` initializer —
29
+ * a valid WasmGC constant init expression for a zero-field immutable struct, so
30
+ * `$Hole`'s ref identity is fixed at instantiation and every `global.get`
31
+ * yields the same ref (required for `ref.test`/`ref.eq` identity). A const init
32
+ * never contains a `call`, so it is immune to late-import index shifts.
33
+ */
34
+ export declare function ensureHoleType(ctx: CodegenContext): number;
35
+ /**
36
+ * Push the `$Hole` sentinel as an `externref`, ready to store into an
37
+ * externref-element vec slot (`array.new_fixed` / `array.set`).
38
+ * Stack: `[] → [externref]`.
39
+ */
40
+ export declare function emitHoleSentinel(ctx: CodegenContext, fctx: FunctionContext): void;
41
+ /**
42
+ * Read-boundary mapping: if the externref on the stack is the `$Hole` sentinel,
43
+ * replace it with `undefined`; otherwise leave it unchanged.
44
+ * Stack: `[externref] → [externref]`.
45
+ *
46
+ * The single most important correctness rule for sparse arrays — the sentinel
47
+ * must never leak past a value-producing read. Reusable across S1 (element read,
48
+ * join) and the later HOF / destructuring slices.
49
+ */
50
+ export declare function emitHoleToUndefined(ctx: CodegenContext, fctx: FunctionContext): void;
51
+ /**
52
+ * Detached-`Instr[]` form of {@link emitHoleToUndefined}, for call sites that
53
+ * assemble a callback-arg / loop-body instruction list off `fctx.body` (e.g.
54
+ * `buildClosureCallInstrs`). Allocates the scratch temp via `fctx` and resolves
55
+ * the `undefined` value up front (flushing any late-import shift into the
56
+ * current body BEFORE the funcIdx is baked into the returned instrs), so the
57
+ * sequence can be spliced anywhere. Stack: `[externref] → [externref]`.
58
+ */
59
+ export declare function holeToUndefinedInstrs(ctx: CodegenContext, fctx: FunctionContext): Instr[];
60
+ /**
61
+ * Instruction list form of the hole test for the array-join fold, where the
62
+ * element-to-string conversion is assembled as a detached `Instr[]` (not pushed
63
+ * onto `fctx.body`). Given the element `externref` already on the (virtual)
64
+ * stack, returns instrs that leave `i32` = 1 iff the element is `$Hole`.
65
+ * Caller wraps `whenHole` / `whenPresent` in the `if`. Registers `$Hole` on
66
+ * demand (caller gates on `usesArrayHoles`), so the `ref.test` typeidx is valid
67
+ * even if no hole-literal has been compiled yet in this module.
68
+ */
69
+ export declare function holeTestInstrs(ctx: CodegenContext): Instr[];