@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.
- package/CHANGELOG.md +1425 -0
- package/LICENSE +189 -0
- package/README.md +451 -0
- package/dist/checker/index.d.ts +117 -0
- package/dist/checker/language-service.d.ts +39 -0
- package/dist/checker/node-capability-map.d.ts +63 -0
- package/dist/checker/type-mapper.d.ts +84 -0
- package/dist/cjs-rewrite.d.ts +19 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +363 -0
- package/dist/codegen/accessor-driver.d.ts +97 -0
- package/dist/codegen/any-helpers.d.ts +72 -0
- package/dist/codegen/array-element-typing.d.ts +46 -0
- package/dist/codegen/array-holes.d.ts +69 -0
- package/dist/codegen/array-methods.d.ts +68 -0
- package/dist/codegen/array-object-proto.d.ts +64 -0
- package/dist/codegen/array-reduce-fusion.d.ts +31 -0
- package/dist/codegen/array-to-primitive.d.ts +28 -0
- package/dist/codegen/async-cps.d.ts +239 -0
- package/dist/codegen/async-scheduler.d.ts +349 -0
- package/dist/codegen/binary-ops.d.ts +78 -0
- package/dist/codegen/binding-info.d.ts +31 -0
- package/dist/codegen/builtin-scaffold.d.ts +98 -0
- package/dist/codegen/builtin-static-globals.d.ts +8 -0
- package/dist/codegen/builtin-tags.d.ts +189 -0
- package/dist/codegen/case-convert-native.d.ts +12 -0
- package/dist/codegen/case-tables.d.ts +4 -0
- package/dist/codegen/class-bodies.d.ts +41 -0
- package/dist/codegen/class-member-keys.d.ts +33 -0
- package/dist/codegen/class-to-primitive.d.ts +39 -0
- package/dist/codegen/closed-method-dispatch.d.ts +42 -0
- package/dist/codegen/closures.d.ts +285 -0
- package/dist/codegen/coercion-engine.d.ts +154 -0
- package/dist/codegen/coercion-plan.d.ts +29 -0
- package/dist/codegen/context/bodies.d.ts +4 -0
- package/dist/codegen/context/create-context.d.ts +4 -0
- package/dist/codegen/context/errors.d.ts +39 -0
- package/dist/codegen/context/locals.d.ts +69 -0
- package/dist/codegen/context/source-pos.d.ts +5 -0
- package/dist/codegen/context/speculative.d.ts +95 -0
- package/dist/codegen/context/types.d.ts +1936 -0
- package/dist/codegen/custom-iterable.d.ts +34 -0
- package/dist/codegen/dataview-native.d.ts +51 -0
- package/dist/codegen/date-parse-native.d.ts +13 -0
- package/dist/codegen/dead-elimination.d.ts +26 -0
- package/dist/codegen/declarations.d.ts +147 -0
- package/dist/codegen/deno-api.d.ts +11 -0
- package/dist/codegen/destructuring-params.d.ts +102 -0
- package/dist/codegen/dyn-read.d.ts +26 -0
- package/dist/codegen/eval-tiering.d.ts +19 -0
- package/dist/codegen/expressions/assignment.d.ts +61 -0
- package/dist/codegen/expressions/builtins.d.ts +26 -0
- package/dist/codegen/expressions/calls-closures.d.ts +54 -0
- package/dist/codegen/expressions/calls-guards.d.ts +49 -0
- package/dist/codegen/expressions/calls-optional.d.ts +4 -0
- package/dist/codegen/expressions/calls.d.ts +83 -0
- package/dist/codegen/expressions/eval-inline.d.ts +24 -0
- package/dist/codegen/expressions/extern.d.ts +67 -0
- package/dist/codegen/expressions/fnctor-prototype.d.ts +52 -0
- package/dist/codegen/expressions/helpers.d.ts +212 -0
- package/dist/codegen/expressions/identifiers.d.ts +57 -0
- package/dist/codegen/expressions/late-imports.d.ts +81 -0
- package/dist/codegen/expressions/logical-ops.d.ts +18 -0
- package/dist/codegen/expressions/misc.d.ts +27 -0
- package/dist/codegen/expressions/new-super.d.ts +25 -0
- package/dist/codegen/expressions/promise-subclass.d.ts +38 -0
- package/dist/codegen/expressions/proto-override.d.ts +63 -0
- package/dist/codegen/expressions/unary-updates.d.ts +21 -0
- package/dist/codegen/expressions/unary.d.ts +6 -0
- package/dist/codegen/expressions.d.ts +31 -0
- package/dist/codegen/fallback-telemetry.d.ts +53 -0
- package/dist/codegen/fixups.d.ts +80 -0
- package/dist/codegen/fmod.d.ts +10 -0
- package/dist/codegen/fnctor-escape-gate.d.ts +92 -0
- package/dist/codegen/function-body.d.ts +52 -0
- package/dist/codegen/generators-native.d.ts +92 -0
- package/dist/codegen/helpers/body-references-own-this.d.ts +22 -0
- package/dist/codegen/helpers/body-uses-arguments.d.ts +12 -0
- package/dist/codegen/helpers/is-strict-function.d.ts +52 -0
- package/dist/codegen/host-import-allowlist.d.ts +140 -0
- package/dist/codegen/index.d.ts +500 -0
- package/dist/codegen/ir-tail-call.d.ts +8 -0
- package/dist/codegen/iterator-native.d.ts +44 -0
- package/dist/codegen/json-codec-native.d.ts +78 -0
- package/dist/codegen/json-runtime.d.ts +35 -0
- package/dist/codegen/json-standalone.d.ts +25 -0
- package/dist/codegen/linear-uint8-analysis.d.ts +46 -0
- package/dist/codegen/linear-uint8-arena.d.ts +7 -0
- package/dist/codegen/linear-uint8-codegen.d.ts +103 -0
- package/dist/codegen/linear-uint8-signatures.d.ts +26 -0
- package/dist/codegen/literals.d.ts +115 -0
- package/dist/codegen/map-runtime.d.ts +142 -0
- package/dist/codegen/math-helpers.d.ts +7 -0
- package/dist/codegen/member-get-dispatch.d.ts +42 -0
- package/dist/codegen/member-set-dispatch.d.ts +28 -0
- package/dist/codegen/native-proto.d.ts +98 -0
- package/dist/codegen/native-regex.d.ts +158 -0
- package/dist/codegen/native-strings.d.ts +146 -0
- package/dist/codegen/new-target.d.ts +30 -0
- package/dist/codegen/node-fs-api.d.ts +47 -0
- package/dist/codegen/number-format-native.d.ts +9 -0
- package/dist/codegen/number-ryu.d.ts +27 -0
- package/dist/codegen/object-ops.d.ts +94 -0
- package/dist/codegen/object-runtime.d.ts +171 -0
- package/dist/codegen/parse-number-native.d.ts +10 -0
- package/dist/codegen/peephole.d.ts +6 -0
- package/dist/codegen/property-access.d.ts +294 -0
- package/dist/codegen/raw-wasi-api.d.ts +13 -0
- package/dist/codegen/regex/bytecode.d.ts +140 -0
- package/dist/codegen/regex/casefold.d.ts +41 -0
- package/dist/codegen/regex/compile.d.ts +51 -0
- package/dist/codegen/regex/parse.d.ts +76 -0
- package/dist/codegen/regex/unicode.d.ts +42 -0
- package/dist/codegen/regex/vm.d.ts +24 -0
- package/dist/codegen/regexp-standalone.d.ts +350 -0
- package/dist/codegen/registry/error-types.d.ts +38 -0
- package/dist/codegen/registry/imports.d.ts +46 -0
- package/dist/codegen/registry/types.d.ts +59 -0
- package/dist/codegen/set-algebra.d.ts +17 -0
- package/dist/codegen/set-runtime.d.ts +74 -0
- package/dist/codegen/shared.d.ts +111 -0
- package/dist/codegen/stack-balance.d.ts +43 -0
- package/dist/codegen/statements/control-flow.d.ts +25 -0
- package/dist/codegen/statements/destructuring.d.ts +177 -0
- package/dist/codegen/statements/exceptions.d.ts +11 -0
- package/dist/codegen/statements/functions.d.ts +1 -0
- package/dist/codegen/statements/index.d.ts +1 -0
- package/dist/codegen/statements/loops.d.ts +7 -0
- package/dist/codegen/statements/nested-declarations.d.ts +78 -0
- package/dist/codegen/statements/shared.d.ts +38 -0
- package/dist/codegen/statements/tdz.d.ts +43 -0
- package/dist/codegen/statements/variables.d.ts +3 -0
- package/dist/codegen/statements.d.ts +9 -0
- package/dist/codegen/string-builder.d.ts +131 -0
- package/dist/codegen/string-ops.d.ts +87 -0
- package/dist/codegen/struct-accessor-closure.d.ts +36 -0
- package/dist/codegen/symbol-native.d.ts +55 -0
- package/dist/codegen/temporal-native.d.ts +8 -0
- package/dist/codegen/timsort.d.ts +2 -0
- package/dist/codegen/type-coercion.d.ts +123 -0
- package/dist/codegen/typeof-delete.d.ts +38 -0
- package/dist/codegen/uri-encoding-native.d.ts +33 -0
- package/dist/codegen/value-tags.d.ts +74 -0
- package/dist/codegen/walk-instructions.d.ts +20 -0
- package/dist/codegen/weak-collections-runtime.d.ts +16 -0
- package/dist/codegen/with-scope.d.ts +106 -0
- package/dist/codegen-linear/c-abi.d.ts +74 -0
- package/dist/codegen-linear/context.d.ts +86 -0
- package/dist/codegen-linear/index.d.ts +28 -0
- package/dist/codegen-linear/layout.d.ts +39 -0
- package/dist/codegen-linear/runtime.d.ts +161 -0
- package/dist/codegen-linear/simd.d.ts +7 -0
- package/dist/compiler/define-substitution.d.ts +27 -0
- package/dist/compiler/early-errors/assignment.d.ts +26 -0
- package/dist/compiler/early-errors/context.d.ts +17 -0
- package/dist/compiler/early-errors/duplicates.d.ts +20 -0
- package/dist/compiler/early-errors/index.d.ts +11 -0
- package/dist/compiler/early-errors/labels.d.ts +13 -0
- package/dist/compiler/early-errors/module-rules.d.ts +36 -0
- package/dist/compiler/early-errors/node-checks.d.ts +7 -0
- package/dist/compiler/early-errors/predicates.d.ts +140 -0
- package/dist/compiler/early-errors/tdz.d.ts +17 -0
- package/dist/compiler/import-manifest.d.ts +18 -0
- package/dist/compiler/output.d.ts +46 -0
- package/dist/compiler/validation.d.ts +45 -0
- package/dist/compiler.d.ts +48 -0
- package/dist/define-substitution-BcUeKC2A.js +109 -0
- package/dist/emit/binary.d.ts +50 -0
- package/dist/emit/c-header.d.ts +23 -0
- package/dist/emit/canonical-recgroup.d.ts +86 -0
- package/dist/emit/encoder.d.ts +28 -0
- package/dist/emit/object.d.ts +14 -0
- package/dist/emit/opcodes.d.ts +464 -0
- package/dist/emit/sourcemap.d.ts +33 -0
- package/dist/emit/wat.d.ts +6 -0
- package/dist/env.d.ts +46 -0
- package/dist/import-resolver.d.ts +68 -0
- package/dist/index.d.ts +486 -0
- package/dist/index.js +755 -0
- package/dist/ir/alloc-registry.d.ts +75 -0
- package/dist/ir/analysis/encoding.d.ts +38 -0
- package/dist/ir/analysis/escape.d.ts +32 -0
- package/dist/ir/analysis/lattice.d.ts +72 -0
- package/dist/ir/analysis/ownership.d.ts +31 -0
- package/dist/ir/analysis/stack-alloc.d.ts +20 -0
- package/dist/ir/backend/bytecode-emitter.d.ts +237 -0
- package/dist/ir/backend/bytecode-vm.d.ts +74 -0
- package/dist/ir/backend/emitter.d.ts +121 -0
- package/dist/ir/backend/handles.d.ts +133 -0
- package/dist/ir/backend/legality.d.ts +9 -0
- package/dist/ir/backend/linear-emitter.d.ts +41 -0
- package/dist/ir/backend/wasmgc-emitter.d.ts +43 -0
- package/dist/ir/builder.d.ts +401 -0
- package/dist/ir/from-ast.d.ts +192 -0
- package/dist/ir/index.d.ts +16 -0
- package/dist/ir/integration.d.ts +27 -0
- package/dist/ir/lower.d.ts +203 -0
- package/dist/ir/nodes.d.ts +1452 -0
- package/dist/ir/passes/alloc-discipline.d.ts +19 -0
- package/dist/ir/passes/constant-fold.d.ts +7 -0
- package/dist/ir/passes/dead-code.d.ts +18 -0
- package/dist/ir/passes/inline-small.d.ts +7 -0
- package/dist/ir/passes/monomorphize.d.ts +21 -0
- package/dist/ir/passes/simplify-cfg.d.ts +19 -0
- package/dist/ir/passes/tagged-union-types.d.ts +45 -0
- package/dist/ir/passes/tagged-unions.d.ts +22 -0
- package/dist/ir/propagate.d.ts +135 -0
- package/dist/ir/select.d.ts +81 -0
- package/dist/ir/types.d.ts +832 -0
- package/dist/ir/verify-alloc.d.ts +18 -0
- package/dist/ir/verify.d.ts +7 -0
- package/dist/link/index.d.ts +11 -0
- package/dist/link/isolation.d.ts +24 -0
- package/dist/link/linker.d.ts +37 -0
- package/dist/link/reader.d.ts +158 -0
- package/dist/link/resolver.d.ts +19 -0
- package/dist/optimize.d.ts +54 -0
- package/dist/optimize.js +262 -0
- package/dist/position-map.d.ts +64 -0
- package/dist/process-stdin-prelude.d.ts +16 -0
- package/dist/resolve.d.ts +82 -0
- package/dist/runtime/builtins.d.ts +1 -0
- package/dist/runtime-C-4q_KwU.js +164438 -0
- package/dist/runtime-containment.d.ts +6 -0
- package/dist/runtime-eval.d.ts +132 -0
- package/dist/runtime-instantiate.d.ts +16 -0
- package/dist/runtime.d.ts +128 -0
- package/dist/runtime.js +12 -0
- package/dist/shape-inference.d.ts +20 -0
- package/dist/treeshake.d.ts +17 -0
- package/dist/ts-api.d.ts +30 -0
- package/dist/wit-generator.d.ts +18 -0
- 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 };
|