diff --git a/docs/content/docs/cli.mdx b/docs/content/docs/cli.mdx index 8be1a2642..786cf2c63 100644 --- a/docs/content/docs/cli.mdx +++ b/docs/content/docs/cli.mdx @@ -134,7 +134,7 @@ Verifies and loads the installed precompiled runtime objects and vendored librar
Coverage only. After the report, list the functions that already operate on values typed only at runtime and the bindings, fields, functions, classes and modules that unsupported constructs would move to the dynamic tier, each with the diagnostic behind it. With a name such as x, Point, or Point.x, show only the matching units. See Dynamic tier.
--wasm <file.wasm>
-
Coverage only. Report a WebAssembly module the program loads from a path its sources do not spell out. The report already lists modules whose paths the compiler resolves, modules inlined as base64 literals, and .wasm files shipped by packages that use WebAssembly; a scriptc.wasm array in package.json adds files the same way as this flag. Each module is listed with its size, whether it validates, and the WebAssembly proposals it uses. scriptc does not compile WebAssembly modules to native code yet. Repeatable.
+
Coverage only. Report a WebAssembly module the program loads from a path its sources do not spell out. The report already lists modules whose paths the compiler resolves, modules inlined as base64 literals, and .wasm files shipped by packages that use WebAssembly; a scriptc.wasm array in package.json adds files the same way as this flag. Each module is listed with its size, whether it validates, and the WebAssembly proposals it uses. Builds translate the modules they find to native code; a build reads the scriptc.wasm array but not this flag. Repeatable.
--sanitize
Build an executable with AddressSanitizer and a reference-count audit at exit, the same checks scriptc's own test suite uses. Requires a C compiler and is available only for host builds. Not supported with --emit=asm or --emit=obj.
diff --git a/docs/content/limitations/builtin-apis/performance-entries.mdx b/docs/content/limitations/builtin-apis/performance-entries.mdx index 92af98cb7..a42940b68 100644 --- a/docs/content/limitations/builtin-apis/performance-entries.mdx +++ b/docs/content/limitations/builtin-apis/performance-entries.mdx @@ -1,2 +1,4 @@ - **Performance entries:** `performance.mark()`, `measure()`, and the `getEntries` methods return entries with Node's fields, `toJSON()`, inspection, and identity. `Object.keys`, `for...in`, object spread, and `hasOwnProperty` on an entry are unsupported, and an entry stored in an `unknown` slot prints as a plain object. +- **Event-loop metrics:** `performance.eventLoopUtilization()` counts the main thread's CPU time since the event loop started as active time, so blocking system calls count as idle where Node counts them as active. + `monitorEventLoopDelay()` supports `enable()`, `disable()`, `reset()`, `percentile()`, and the `min`, `max`, `mean`, `stddev`, `count`, and `exceeds` readings; the BigInt readings, `percentiles`, and non-literal option objects are unsupported. diff --git a/docs/content/limitations/builtin-apis/streams-and-readline.mdx b/docs/content/limitations/builtin-apis/streams-and-readline.mdx index beda29c7d..73b48c88d 100644 --- a/docs/content/limitations/builtin-apis/streams-and-readline.mdx +++ b/docs/content/limitations/builtin-apis/streams-and-readline.mdx @@ -1,4 +1,7 @@ - **Streams and readline:** Stream chunks are Buffers or strings. + `NodeJS.ReadableStream` and `NodeJS.WritableStream`, and `stream.Readable` and `stream.Writable` under `@types/node`, accept every stream: when a program passes file, zlib, or `node:stream` streams through them, child-process pipes and `process.stdout` and `process.stderr` join those streams as `Readable` and `Writable` instances. + `readable.pipe(process.stdout)` and `readable.pipe(process.stderr)` compile and, as in Node, do not end the process stream. + A `pipeline` stage that arrives as an untyped value must be a native stream at run time; other values throw a not-supported error. `Readable.from` accepts arrays, Sets, Map and Set iterators, generators, async generators, and class iterables and async iterables whose values are strings or Buffers, and in JavaScript any iterable or async iterable of them; a stream that mixes strings and Buffers is unsupported. In JavaScript, a sync iterator value with a `then` method that is not a promise, and an object whose `[Symbol.asyncIterator]` or `[Symbol.iterator]` method is a generator method, are unsupported. Object-mode streams of other values (including `Readable.from` over a `Map`, whose values are entry arrays) are unsupported. @@ -11,6 +14,7 @@ `stream.compose` accepts two or more streams, or one `Duplex`; functions, iterables, and web streams as stages are unsupported, and the `ERR_INVALID_ARG_VALUE` message for a stream that is no longer readable or writable names the stream's class instead of printing the stream. `pipeline` from `node:stream/promises` accepts a trailing `{ signal, end }` object, and `finished` accepts `readable`, `writable`, `error`, `cleanup`, and `signal` options, with boolean literals for the flags. Stream constructors accept a `signal` option in an options object literal, and `stream.addAbortSignal` accepts any stream. + A `transform` or `flush` option callback whose completion callback types `data` as `any`, as @types/node's `TransformCallback` does, may pass a Buffer, a string, or nothing; any other value throws a TypeError where the callback is called, instead of Node's `ERR_INVALID_ARG_TYPE` stream error. `node:readline` and `node:readline/promises` (also reached as `readline.promises`) interfaces, from `createInterface(options)` or `createInterface(input, output, completer, terminal)`, read `process.stdin` or a readable stream: `question`, `prompt`, `write` (with a key object literal of `name`, `ctrl`, `meta`, and `shift`), `pause`, `resume`, `'line'`/`'close'`/`'pause'`/`'resume'`/`'error'`/`'history'`/`'SIGINT'`/`'SIGTSTP'`/`'SIGCONT'` listeners, and `for await` compile. The `history`, `historySize`, `removeHistoryDuplicates`, `completer`, `tabSize`, and `escapeCodeTimeout` options are validated as in Node. With `terminal: true`, or with no `terminal` option and `process.stdout` as the output when it is a TTY, the interface runs Node's terminal mode: the editing keys, the kill ring, undo and redo, history recording and recall, Tab completion through the completer, Ctrl+C, Ctrl+D, and Ctrl+Z, `TERM=dumb`, and the same escape sequences written to the output. diff --git a/docs/content/limitations/builtin-function-values.mdx b/docs/content/limitations/builtin-function-values.mdx index 80d0814b1..541c9fb2b 100644 --- a/docs/content/limitations/builtin-function-values.mdx +++ b/docs/content/limitations/builtin-function-values.mdx @@ -16,7 +16,11 @@ Other immutable aliases of table-backed Node builtins support direct calls, but Native calls accept standard process streams; custom native streams and mutations to `util.inspect.colors` remain unsupported. `util.inherits` links the prototypes of constructor functions, and `util.deprecate`, `util.callbackify`, and `util.debuglog` return native function values that forward receivers and arguments. -Class constructors passed to `util.inherits` or `util.deprecate` are refused. +In JavaScript, a constructor function can inherit from `EventEmitter`, the legacy `Stream` constructor, or a stream class through `util.inherits` or `Object.setPrototypeOf`. +`EventEmitter.call(this)` and `Stream.call(this)` initialize the object as Node does, and its listener methods keep their state in the object's own `_events`, `_eventsCount`, and `_maxListeners` properties. +The `captureRejections` option and `events.errorMonitor` listeners are not supported on such objects. +Calling `Readable`, `Writable`, `Duplex`, `Transform`, or `PassThrough` with a constructor function's receiver throws `SC2020` where the call runs. +Other class constructors passed to `util.inherits` or `util.deprecate` are refused. Deprecation warnings are emitted on the next tick and follow assignments to `process.noDeprecation` and `process.throwDeprecation`; compiled binaries take no Node command-line flags such as `--no-deprecation` or `--trace-deprecation`, and `process.traceDeprecation` is unsupported. A stored `util.deprecate` reports a `length` of 4, where Node reports 3. In TypeScript, a `util.callbackify` result must reach a callback whose error parameter accepts `null`; the @types/node overloads that type it as non-null are refused. diff --git a/docs/content/limitations/child-process-workers.mdx b/docs/content/limitations/child-process-workers.mdx index 5b41c5e53..9d6602509 100644 --- a/docs/content/limitations/child-process-workers.mdx +++ b/docs/content/limitations/child-process-workers.mdx @@ -12,3 +12,7 @@ Message listeners may return `void` or `Promise`. Messages use newline-delimited JSON, so their static types must be JSON-stringifiable or `unknown` backed by a checked JSON tree. `send()` returns the channel's backpressure state and invokes its callback later with `null` or an `Error`. `disconnect()` changes `connected` synchronously, before the later disconnect events. + +A `'data'` listener on a child's `stdout` or `stderr` whose chunk is `unknown` or `any` receives strings when a `setEncoding()` statement on the same stream precedes it in its block or an enclosing block, and Buffers when the function never calls `setEncoding()` on that stream. +Any other placement of `setEncoding()` is refused at compile time, and a `setEncoding()` call that runs elsewhere afterwards makes the listener throw a TypeError instead of receiving strings. +An inline `'exit'` or `'close'` listener may declare `(code: number, signal: string)`, which TypeScript accepts through the catch-all `on` overload; it receives the `null` values Node passes, and a typed use of a `null` value throws a TypeError. diff --git a/docs/content/limitations/console-and-process-streams.mdx b/docs/content/limitations/console-and-process-streams.mdx index 0d7cd8f30..c62b82f0c 100644 --- a/docs/content/limitations/console-and-process-streams.mdx +++ b/docs/content/limitations/console-and-process-streams.mdx @@ -9,4 +9,5 @@ JavaScript can store `process.stdin`, `stdout`, and `stderr`, replace output `wr Input supports data/end/error listeners, pause/resume, buffered reads, and TTY raw mode. Output writes are synchronous, with successful callbacks on the next-tick queue; queued backpressure is not modeled. Stored streams do not support piping, encoding changes, arbitrary properties, or other events. -TypeScript output parameters support `write(string)`. +A TypeScript `NodeJS.WritableStream` parameter that only receives `process.stdout` or `process.stderr` supports `write(string)`. +When other streams flow into the same parameter, the process streams join them as `Writable` instances with the full writable surface. diff --git a/docs/content/limitations/language-features/generics.mdx b/docs/content/limitations/language-features/generics.mdx index 6e203506f..a234c8f57 100644 --- a/docs/content/limitations/language-features/generics.mdx +++ b/docs/content/limitations/language-features/generics.mdx @@ -3,3 +3,9 @@ Independent concrete uses have no specialization-count limit; recursively expanding demands and type layouts produce diagnostics. Other generic calls compile when the target resolves statically. Generic function values require a concrete signature at use and a binding that is never reassigned. +- **Variadic wrappers:** A generic higher-order wrapper is specialized to each wrapped function's exact signature. + `Parameters`, `ReturnType`, and rest parameters typed as fixed tuples become that signature's parameter list. + A function expression with no parameters that reads `arguments` compiles only when its value is asserted to, or contextually typed as, one fixed-arity signature; `arguments` is then that signature's tuple. + Forwarding it with `fn.apply(this, arguments)` passes `this` through. + Reading `fn.name` on a wrapped function requires its name to be known where the wrapper is called, such as a function declaration or a `const`-bound function. + `Parameters` over a signature with optional or array-typed rest parameters is unsupported, because that tuple has no fixed length. diff --git a/docs/content/limitations/webassembly-modules.mdx b/docs/content/limitations/webassembly-modules.mdx index e3bf6e500..43fa55e48 100644 --- a/docs/content/limitations/webassembly-modules.mdx +++ b/docs/content/limitations/webassembly-modules.mdx @@ -1,7 +1,31 @@ -Compiled programs can't load WebAssembly modules yet. -Code that only mentions the `WebAssembly` types type-checks, including packages whose declarations name them, and `typeof WebAssembly` answers as it does in Node.js. -Every use of the API itself is rejected: `WebAssembly.compile`, `instantiate` and `validate`, `new WebAssembly.Module` and the other constructors, `instanceof` checks, and reads of `globalThis.WebAssembly`. -TypeScript sources fail to build with SC2020 at each use, and JavaScript sources throw that diagnostic when the statement runs. +scriptc translates WebAssembly modules to native code when it builds the program; there is no interpreter or JIT in the executable. +A build translates every module whose bytes it can see: files at paths the compiler resolves (`require.resolve`, `createRequire(...).resolve`, `import.meta.resolve`, `new URL("./x.wasm", import.meta.url)`, `path.join(__dirname, ...)`), including `.so` WebAssembly shared libraries such as quickjs-wasi's extensions, modules inlined as base64 or byte-array literals, `.wasm` files shipped by packages whose code uses WebAssembly, and files listed in a `scriptc.wasm` array in `package.json`. +At run time `WebAssembly.compile`, `instantiate`, `validate` and `new WebAssembly.Module` find the translated module by the SHA-256 of the bytes they are given. +Bytes the build did not see, including bytes produced at run time, reject with a `CompileError` that says the module was not translated, and `WebAssembly.validate` answers `false` for them. +`scriptc coverage` lists the modules a build finds, with their size, whether they validate, and the WebAssembly proposals they use. -`scriptc coverage` lists the modules a program would load, with their size, whether they validate, and the WebAssembly proposals they use. -It finds modules at paths the compiler resolves, modules inlined as base64 literals, `.wasm` files shipped by packages that use WebAssembly, and files named with [`--wasm`](/docs/cli) or a `scriptc.wasm` array in `package.json`. +Translated modules can use the WebAssembly 2.0 feature set: the MVP plus sign-extension operators, non-trapping float-to-int conversions, bulk memory, multi-value, mutable globals, reference types, and extended constant expressions. +Modules that use SIMD, threads, exception handling, tail calls, typed function references or GC, memory64, or multiple memories are not translated, so loading them rejects with the `CompileError` above; packages that fall back to a scalar build when that happens, such as undici and es-module-lexer, take their fallback. + +Supported: `WebAssembly.compile`, `instantiate` (with bytes or a `Module`), `validate`, `new WebAssembly.Module`, `new WebAssembly.Instance`, `new WebAssembly.Memory`, `new WebAssembly.Table`, `new WebAssembly.Global`, `WebAssembly.Module.imports`, `exports` and `customSections`, and `instanceof` for every class; the error classes `CompileError`, `LinkError` and `RuntimeError`, constructed with or without `new`; `globalThis.WebAssembly` and its `compile`, `instantiate` and `validate` functions as values. +Instances expose exported functions, memories (`buffer`, `grow`), tables (`get`, `set`, `grow`, `length`) and globals (`value`, `valueOf`). +Imports can be functions, numbers or BigInts for immutable globals, and memories, tables and globals that the program constructs or other instances export; their limits, types and mutability are checked with Node.js's `LinkError` messages. +Function references from a table or global reach JavaScript as callable functions, and exported functions can be stored in tables and globals, which is what dynamic linkers such as quickjs-wasi's extension loader do. +Traps throw `WebAssembly.RuntimeError` with Node.js's messages, unbounded recursion throws `RangeError`, and an exception thrown by an imported function propagates through the WebAssembly frames unchanged. +A `WebAssembly.Module` can be sent to a worker through `workerData` or `postMessage`. + +Not supported yet: the `Tag` and `Exception` constructors, shared memories (`new WebAssembly.Memory({ shared: true, ... })` throws a `TypeError`), `compileStreaming` and `instantiateStreaming`, and the classes used as values other than with `new`, `instanceof` and `WebAssembly.Module`'s static functions. +TypeScript sources fail to build with SC2020 at each such use, and JavaScript sources throw that diagnostic when the statement runs. +Programs built for `wasm32-wasi` can't use the WebAssembly API. + +Differences from Node.js: + +- Growing a memory, from JavaScript or inside the module, does not detach the previous `ArrayBuffer`. + The memory never moves, so views created before the growth stay valid but keep their old length; code that reads `memory.buffer` again after growing, as WebAssembly glue code does, behaves as in Node.js. +- `valueOf()` answers a `WebAssembly.Global`'s value only when the receiver's static type is `WebAssembly.Global`; through an untyped value it answers the object, and converting a `Global` to a primitive uses the object rather than its value. +- Instances are never freed, together with their memories, imports and exports. +- A load whose result the module never uses may be removed instead of trapping when its address is out of bounds. + Loads whose result is dropped explicitly still trap. +- NaN payloads may differ, for example when a signaling NaN passes through arithmetic or a JavaScript number. +- `WebAssembly.compile` and `instantiate` with bytes settle after the current microtasks, as in Node.js, but can settle after `setImmediate` callbacks that Node.js would run later. +- The executable reads `.wasm` files at run time from the paths they had when it was built. diff --git a/docs/src/generated/node-v24-compatibility.json b/docs/src/generated/node-v24-compatibility.json index 2f7fd6696..e5fd082f6 100644 --- a/docs/src/generated/node-v24-compatibility.json +++ b/docs/src/generated/node-v24-compatibility.json @@ -329,8 +329,8 @@ "apiEntries": 92, "static": { "supported": 1, - "partial": 15, - "refused": 1, + "partial": 16, + "refused": 0, "not-implemented": 75, "by-design": 0, "unreviewed": 0, @@ -539,9 +539,9 @@ "apiEntries": 131, "static": { "supported": 0, - "partial": 19, + "partial": 25, "refused": 0, - "not-implemented": 112, + "not-implemented": 106, "by-design": 0, "unreviewed": 0, "not-applicable": 0 @@ -36590,9 +36590,9 @@ "inherited": true }, "static": { - "status": "refused", - "detail": "Explicitly rejected by a named compiler diagnostic.", - "verification": "explicit-refusal" + "status": "partial", + "detail": "Implemented for the call shapes accepted by the compiler lowering.", + "verification": "test-backed" } }, { @@ -54688,9 +54688,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the documented scriptc module-loader subset.", + "verification": "test-backed" } }, { @@ -54803,9 +54803,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the documented scriptc module-loader subset.", + "verification": "test-backed" } }, { @@ -55286,9 +55286,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the documented scriptc module-loader subset.", + "verification": "test-backed" } }, { @@ -55309,9 +55309,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the documented scriptc module-loader subset.", + "verification": "test-backed" } }, { @@ -55677,9 +55677,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the call shapes accepted by the compiler lowering.", + "verification": "test-backed" } }, { @@ -55815,9 +55815,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "partial", + "detail": "Implemented for the documented scriptc module-loader subset.", + "verification": "test-backed" } }, { diff --git a/internal/compatibility/generated/node-v24-backlog.json b/internal/compatibility/generated/node-v24-backlog.json index 3b419ea20..51459d3b3 100644 --- a/internal/compatibility/generated/node-v24-backlog.json +++ b/internal/compatibility/generated/node-v24-backlog.json @@ -7,9 +7,9 @@ "tierItemCount": 3454, "tiers": { "static": { - "audit-partial": 1190, - "verify-gap": 2136, - "replace-refusal": 41, + "audit-partial": 1197, + "verify-gap": 2130, + "replace-refusal": 40, "classify": 2, "implement": 85 } @@ -34235,12 +34235,25 @@ "priority": "high", "tiers": { "static": { - "status": "refused", - "action": "replace-refusal", - "verification": "explicit-refusal", + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", "confidence": "high", - "source": "surface-manifest:unsupported:stdlib.webassembly", - "tests": [] + "source": "surface-manifest:stdlib.webassembly", + "tests": [ + "tests/corpus/webassembly-api.mjs", + "tests/corpus/webassembly-typed.ts", + "tests/corpus/webassembly-worker.ts", + "tests/corpus/webassembly-spec-int/main.mjs", + "tests/corpus/webassembly-spec-float/main.mjs", + "tests/corpus/webassembly-spec-control/main.mjs", + "tests/corpus/webassembly-spec-memory/main.mjs", + "tests/corpus/webassembly-spec-table/main.mjs", + "tests/corpus/webassembly-spec-imports/main.mjs", + "tests/corpus/webassembly-jsapi.mjs", + "tests/corpus/webassembly-wpt-jsapi.mjs", + "tests/corpus/webassembly-dylink/main.mjs" + ] } } }, @@ -54264,12 +54277,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "compiler-feature:perf_hooks.histogram.percentile", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, @@ -54389,12 +54405,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "compiler-feature:perf_hooks.histogram.reset", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, @@ -54914,12 +54933,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "compiler-feature:perf_hooks.histogram.disable", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, @@ -54939,12 +54961,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "compiler-feature:perf_hooks.histogram.enable", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, @@ -55339,12 +55364,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "surface-manifest:node-builtin.perf_hooks.monitorEventLoopDelay", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, @@ -55499,12 +55527,15 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:perf_hooks", - "tests": [] + "status": "partial", + "action": "audit-partial", + "verification": "test-backed", + "confidence": "high", + "source": "compiler-feature:perf_hooks.performance.eventLoopUtilization", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] } } }, diff --git a/internal/compatibility/generated/node-v24-internal.json b/internal/compatibility/generated/node-v24-internal.json index 2582c75b3..0e1e73a26 100644 --- a/internal/compatibility/generated/node-v24-internal.json +++ b/internal/compatibility/generated/node-v24-internal.json @@ -341,8 +341,8 @@ "apiEntries": 92, "static": { "supported": 1, - "partial": 15, - "refused": 1, + "partial": 16, + "refused": 0, "not-implemented": 75, "by-design": 0, "unreviewed": 0, @@ -566,9 +566,9 @@ "apiEntries": 131, "static": { "supported": 0, - "partial": 19, + "partial": 25, "refused": 0, - "not-implemented": 112, + "not-implemented": 106, "by-design": 0, "unreviewed": 0, "not-applicable": 0 @@ -52298,6 +52298,18 @@ "tests/corpus/6295-jose-hs256/main.mjs", "tests/corpus/6331-jose-root-entry/main.ts", "tests/corpus/text-codec-values/main.ts", + "tests/corpus/webassembly-api.mjs", + "tests/corpus/webassembly-dylink/main.mjs", + "tests/corpus/webassembly-jsapi.mjs", + "tests/corpus/webassembly-spec-control/main.mjs", + "tests/corpus/webassembly-spec-float/main.mjs", + "tests/corpus/webassembly-spec-imports/main.mjs", + "tests/corpus/webassembly-spec-int/main.mjs", + "tests/corpus/webassembly-spec-memory/main.mjs", + "tests/corpus/webassembly-spec-table/main.mjs", + "tests/corpus/webassembly-typed.ts", + "tests/corpus/webassembly-worker.ts", + "tests/corpus/webassembly-wpt-jsapi.mjs", "tests/fixtures/node-types/navigator.ts", "tests/harness/fetch-conformance.test.ts", "tests/harness/project-config.test.ts" @@ -53649,8 +53661,22 @@ "inherited": true }, "static": { - "status": "refused", - "evidence": "surface-manifest:unsupported:stdlib.webassembly" + "status": "partial", + "evidence": "surface-manifest:stdlib.webassembly", + "tests": [ + "tests/corpus/webassembly-api.mjs", + "tests/corpus/webassembly-typed.ts", + "tests/corpus/webassembly-worker.ts", + "tests/corpus/webassembly-spec-int/main.mjs", + "tests/corpus/webassembly-spec-float/main.mjs", + "tests/corpus/webassembly-spec-control/main.mjs", + "tests/corpus/webassembly-spec-memory/main.mjs", + "tests/corpus/webassembly-spec-table/main.mjs", + "tests/corpus/webassembly-spec-imports/main.mjs", + "tests/corpus/webassembly-jsapi.mjs", + "tests/corpus/webassembly-wpt-jsapi.mjs", + "tests/corpus/webassembly-dylink/main.mjs" + ] }, "anchorSource": "exact" }, @@ -75620,7 +75646,9 @@ "tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5213-perf-timing-errors.ts", "tests/corpus/5214-perf-entry-inspect.ts", - "tests/corpus/5215-perf-timing-validation.js" + "tests/corpus/5215-perf-timing-validation.js", + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" ] }, "anchorSource": "chapter" @@ -77661,8 +77689,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "compiler-feature:perf_hooks.histogram.percentile", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, @@ -77776,8 +77808,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "compiler-feature:perf_hooks.histogram.reset", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, @@ -78259,8 +78295,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "compiler-feature:perf_hooks.histogram.disable", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, @@ -78282,8 +78322,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "compiler-feature:perf_hooks.histogram.enable", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, @@ -78650,8 +78694,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "surface-manifest:node-builtin.perf_hooks.monitorEventLoopDelay", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, @@ -78800,8 +78848,12 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:perf_hooks" + "status": "partial", + "evidence": "compiler-feature:perf_hooks.performance.eventLoopUtilization", + "tests": [ + "tests/corpus/6397-event-loop-metrics.ts", + "tests/fixtures/node-types/event-loop-metrics.ts" + ] }, "anchorSource": "exact" }, diff --git a/internal/compatibility/static-support.json b/internal/compatibility/static-support.json index 32eea0977..734e038ef 100644 --- a/internal/compatibility/static-support.json +++ b/internal/compatibility/static-support.json @@ -28,6 +28,7 @@ "webstreams": "unreviewed" }, "evidenceByManifestPrefix": { + "stdlib.webassembly": ["tests/corpus/webassembly-api.mjs", "tests/corpus/webassembly-typed.ts", "tests/corpus/webassembly-worker.ts", "tests/corpus/webassembly-spec-int/main.mjs", "tests/corpus/webassembly-spec-float/main.mjs", "tests/corpus/webassembly-spec-control/main.mjs", "tests/corpus/webassembly-spec-memory/main.mjs", "tests/corpus/webassembly-spec-table/main.mjs", "tests/corpus/webassembly-spec-imports/main.mjs", "tests/corpus/webassembly-jsapi.mjs", "tests/corpus/webassembly-wpt-jsapi.mjs", "tests/corpus/webassembly-dylink/main.mjs"], "node-builtin.fs.readFileSync": ["tests/corpus/1403-buffer-fs.ts", "tests/corpus/2595-fs-arg-ladders.cjs", "tests/corpus/2919-fs-function-values.ts", "tests/corpus/2920-fs-promises-function-values.ts", "tests/corpus/fs-read-encodings.ts"], "syntax.using-declarations": ["tests/corpus/2841-using-sync.ts"], "syntax.await-using-declarations": ["tests/corpus/2842-await-using.ts"], @@ -138,6 +139,8 @@ "node-builtin.perf_hooks.performance.getEntries": ["tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5214-perf-entry-inspect.ts", "tests/corpus/5215-perf-timing-validation.js"], "node-builtin.perf_hooks.performance.clearMarks": ["tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5213-perf-timing-errors.ts", "tests/corpus/5215-perf-timing-validation.js"], "node-builtin.perf_hooks.performance.clearMeasures": ["tests/corpus/5212-perf-marks-measures.ts"], + "node-builtin.perf_hooks.performance.eventLoopUtilization": ["tests/corpus/6397-event-loop-metrics.ts", "tests/fixtures/node-types/event-loop-metrics.ts"], + "node-builtin.perf_hooks.monitorEventLoopDelay": ["tests/corpus/6397-event-loop-metrics.ts", "tests/fixtures/node-types/event-loop-metrics.ts"], "node-builtin.process": ["tests/corpus/990-process-basics.ts", "tests/corpus/2314-process-introspection.ts"], "node-builtin.process.hrtime": ["tests/corpus/process-hrtime.js"], "node-builtin.process.memoryUsage": ["tests/corpus/5210-process-memory-usage.ts"], @@ -246,6 +249,8 @@ { "chapter": "util", "symbols": ["util.parseEnv"], "status": "partial", "evidence": ["tests/corpus/node24-env-parse.ts", "tests/corpus/node24-env-parse-errors.ts", "tests/corpus/node24-env-imports.cjs", "tests/fixtures/node-types/env-files.ts", "tests/harness/project-config.test.ts"] }, { "chapter": "process", "symbols": ["process.memoryUsage.rss"], "status": "partial", "evidence": ["tests/corpus/5210-process-memory-usage.ts"] }, { "chapter": "perf_hooks", "symbols": ["performance.now"], "status": "partial", "evidence": ["tests/corpus/2427-perf-hooks-now.ts", "tests/corpus/2446-performance-global.ts"] }, + { "chapter": "perf_hooks", "symbols": ["performance.eventLoopUtilization"], "status": "partial", "evidence": ["tests/corpus/6397-event-loop-metrics.ts", "tests/fixtures/node-types/event-loop-metrics.ts"] }, + { "chapter": "perf_hooks", "symbols": ["histogram.enable", "histogram.disable", "histogram.percentile", "histogram.reset"], "status": "partial", "evidence": ["tests/corpus/6397-event-loop-metrics.ts", "tests/fixtures/node-types/event-loop-metrics.ts"] }, { "chapter": "perf_hooks", "symbols": ["performance.mark", "performance.measure", "performance.getEntries", "performance.getEntriesByName", "performance.getEntriesByType", "performance.clearMarks", "performance.clearMeasures"], "status": "partial", "evidence": ["tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5213-perf-timing-errors.ts", "tests/corpus/5214-perf-entry-inspect.ts", "tests/corpus/5215-perf-timing-validation.js"] }, { "chapter": "perf_hooks", "symbols": ["PerformanceEntry", "PerformanceMark", "PerformanceMeasure"], "status": "partial", "evidence": ["tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5214-perf-entry-inspect.ts"] }, { "chapter": "perf_hooks", "parent": "Class: `PerformanceEntry`", "symbols": ["duration", "entryType", "name", "startTime"], "status": "partial", "evidence": ["tests/corpus/5212-perf-marks-measures.ts", "tests/corpus/5214-perf-entry-inspect.ts"] }, diff --git a/packages/compiler/ambient/scriptc-node-fallback.d.ts b/packages/compiler/ambient/scriptc-node-fallback.d.ts index cb059fc1d..411291d94 100644 --- a/packages/compiler/ambient/scriptc-node-fallback.d.ts +++ b/packages/compiler/ambient/scriptc-node-fallback.d.ts @@ -80,21 +80,54 @@ declare namespace NodeJS { path?: string | undefined; syscall?: string | undefined; } - /* The piped child-output stream (child.stdout / child.stderr under - * stdio ["ignore", "pipe", "pipe"]): 'data' fires one Buffer chunk per - * read (≤64KB, consumer-driven — no listener, no read), 'end' fires - * once at EOF and always BEFORE the child's 'exit'. A flowing stream - * keeps the loop alive. */ + /* The readable-stream interface every Node stream implements. The + * piped child-output stream (child.stdout / child.stderr under stdio + * ["ignore", "pipe", "pipe"]) is declared with it: 'data' fires one + * Buffer chunk per read (≤64KB, consumer-driven — no listener, no + * read), 'end' fires once at EOF and always BEFORE the child's 'exit'. A + * flowing stream keeps the loop alive. A program that also passes + * other streams (fs, zlib, node:stream) where this interface is + * expected compiles it as the node:stream Readable, with child output + * bridged into one. */ interface ReadableStream { on(event: "data", listener: (chunk: Buffer) => void): void; on(event: "data", listener: (chunk: string) => void): void; on(event: "end", listener: () => void): void; + on(event: string, listener: (...args: any[]) => void): void; once(event: "data", listener: (chunk: Buffer) => void): void; once(event: "data", listener: (chunk: string) => void): void; once(event: "end", listener: () => void): void; + once(event: string, listener: (...args: any[]) => void): void; /* setEncoding('utf8') makes subsequent data chunks strings, including * multibyte sequences split across native pipe reads. */ setEncoding(encoding: string): this; + readonly readable: boolean; + pause(): this; + resume(): this; + isPaused(): boolean; + pipe(destination: T, options?: { end?: boolean }): T; + unpipe(destination?: WritableStream): this; + [Symbol.asyncIterator](): AsyncIterableIterator; + } + /* The writable-stream interface every Node stream implements: + * process.stdout/process.stderr, fs.WriteStream and the node:stream + * Writable family. Written only to the process streams, it compiles as + * their descriptor; with other streams flowing into it, as the + * node:stream Writable (the process streams convert into one). */ + interface WritableStream { + readonly writable: boolean; + write(data: string | Uint8Array, callback?: (error?: Error | null) => void): boolean; + write( + data: string | Uint8Array, + encoding: BufferEncoding, + callback?: (error?: Error | null) => void, + ): boolean; + end(callback?: () => void): void; + end(data: string | Uint8Array, callback?: () => void): void; + end(data: string | Uint8Array, encoding: BufferEncoding, callback?: () => void): void; + /* Node's EventEmitter signature: listeners take untyped arguments. */ + on(event: string, listener: (...args: any[]) => void): void; + once(event: string, listener: (...args: any[]) => void): void; } } @@ -1271,8 +1304,37 @@ declare module "node:perf_hooks" { getEntriesByType(type: EntryType): PerformanceEntry[]; clearMarks(name?: string): void; clearMeasures(name?: string): void; + eventLoopUtilization( + utilization1?: EventLoopUtilization, + utilization2?: EventLoopUtilization, + ): EventLoopUtilization; } export const performance: Performance; + /* Event-loop metrics: utilization (idle/active ms since the loop started) + * and monitorEventLoopDelay's sampling histogram (nanoseconds). */ + export interface EventLoopUtilization { + idle: number; + active: number; + utilization: number; + } + export interface EventLoopMonitorOptions { + resolution?: number | undefined; + } + export interface Histogram { + readonly count: number; + readonly exceeds: number; + readonly max: number; + readonly mean: number; + readonly min: number; + readonly stddev: number; + percentile(percentile: number): number; + reset(): void; + } + export interface IntervalHistogram extends Histogram { + enable(): boolean; + disable(): boolean; + } + export function monitorEventLoopDelay(options?: EventLoopMonitorOptions): IntervalHistogram; } declare module "perf_hooks" { export * from "node:perf_hooks"; @@ -3066,8 +3128,10 @@ declare module "child_process" { destroy(): void; on(event: "drain" | "finish", listener: () => void): void; on(event: "error", listener: (err: Error) => void): void; + on(event: string, listener: (...args: any[]) => void): void; once(event: "drain" | "finish", listener: () => void): void; once(event: "error", listener: (err: Error) => void): void; + once(event: string, listener: (...args: any[]) => void): void; } export interface ChildProcess extends Disposable { @@ -6414,7 +6478,7 @@ declare module "node:cluster" { /* node:tty — the fd probe (the same isatty(3) behind process.*.isTTY) * and the supported structural view of a process output stream. */ declare module "tty" { - export interface WriteStream { + export interface WriteStream extends NodeJS.WritableStream { write(data: string | Uint8Array, callback?: (error?: Error | null) => void): boolean; write( data: string | Uint8Array, @@ -6664,8 +6728,8 @@ declare module "stream" { resume(): this; isPaused(): boolean; setEncoding(encoding: string): this; - pipe(destination: T, options?: { end?: boolean }): T; - unpipe(destination?: Writable): this; + pipe(destination: T, options?: { end?: boolean }): T; + unpipe(destination?: NodeJS.WritableStream): this; destroy(error?: Error): this; readonly readable: boolean; readonly readableEnded: boolean; diff --git a/packages/compiler/shims/fs-extra/core/api.ts b/packages/compiler/shims/fs-extra/core/api.ts index a17a5f9a7..7a59f17e2 100644 --- a/packages/compiler/shims/fs-extra/core/api.ts +++ b/packages/compiler/shims/fs-extra/core/api.ts @@ -1081,8 +1081,15 @@ function copyEntrySync( throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`); if (!destExists) fs.mkdirSync(dest); for (const item of fs.readdirSync(src)) { + const srcItem = path.join(src, item); const destItem = path.join(dest, item); - copyEntrySync(state, path.join(src, item), destItem, fs.existsSync(destItem), false); + // fs-extra's copyDirItem checks every entry against its destination: + // a destination symlink back into the source tree must not let the + // overwrite below unlink the source's own file. + const destItemStat = statOrNullSync(destItem); + if (destItemStat !== null && sameNode(fs.statSync(srcItem), destItemStat)) + throw new Error("Source and destination must not be the same."); + copyEntrySync(state, srcItem, destItem, destItemStat !== null, false); } if (!destExists) fs.chmodSync(dest, srcStat.mode); return; diff --git a/packages/compiler/src/backend/executable-features.ts b/packages/compiler/src/backend/executable-features.ts index b36f47d88..38f44e58e 100644 --- a/packages/compiler/src/backend/executable-features.ts +++ b/packages/compiler/src/backend/executable-features.ts @@ -16,6 +16,7 @@ export function executableLinkFeatures(mod: IrModule): NativeLinkFeatures { fileHandle: features.fileHandle, fetch: features.fetch, ...(features.eventTarget ? { eventTarget: true } : {}), + ...(features.wasm ? { wasm: true } : {}), ...(features.warningReplace ? { warningReplace: true } : {}), ...(features.stdioExtended ? { stdioExtended: true } : {}), zlib: features.zlib, @@ -31,6 +32,7 @@ export function executableLinkFeatures(mod: IrModule): NativeLinkFeatures { bigint: features.bigint, searchParams: features.searchParams, qs: features.qs, + dynBuiltinClass: features.dynBuiltinClass, parseArgs: features.parseArgs, stream: features.stream, net: features.net, @@ -45,5 +47,6 @@ export function executableLinkFeatures(mod: IrModule): NativeLinkFeatures { tlsCa: features.tlsCa, cipher: features.cipher, webcrypto: features.webcrypto, + perfLoop: features.perfLoop, }; } diff --git a/packages/compiler/src/backend/library-pack.ts b/packages/compiler/src/backend/library-pack.ts index 4ca5856ea..42275c5af 100644 --- a/packages/compiler/src/backend/library-pack.ts +++ b/packages/compiler/src/backend/library-pack.ts @@ -42,6 +42,7 @@ export async function compilePackedLibrary( bigint: options.bigint ?? false, searchParams: options.searchParams ?? false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -55,6 +56,7 @@ export async function compilePackedLibrary( tls: false, cipher: false, webcrypto: false, + perfLoop: false, tlsCa: false, }; const selection = await loadRuntimePack({ diff --git a/packages/compiler/src/backend/llvm/emit-module.ts b/packages/compiler/src/backend/llvm/emit-module.ts index 86b275763..4e4f11828 100644 --- a/packages/compiler/src/backend/llvm/emit-module.ts +++ b/packages/compiler/src/backend/llvm/emit-module.ts @@ -1,4 +1,5 @@ /* LlEmitter's module-level output: module parts, helper definitions, library declarations and FFI callback definitions. */ +import { emitWasmModules } from "./wasm-modules.js"; import { type LlEmitter, ffiCallbackDummyLl, llStrBytes } from "./emitter.js"; import { mangleAsyncSpawn, @@ -312,6 +313,7 @@ export function emitModuleParts(emitter: LlEmitter): string[] { emitter.declare(`declare zeroext i1 @scr_loop_run(ptr)`); if (emitter.mod.commonJsEntry === true) emitter.declare(`declare void @scr_loop_commonjs_entry()`); + if (emitter.readsLoopMetrics()) emitter.declare(`declare void @scr_perf_loop_mark()`); emitter.declare(`declare zeroext i1 @scr_report_unhandled_rejections()`); emitter.declare(`declare void @scr_discard_unhandled_rejections()`); } @@ -730,6 +732,9 @@ export function emitModuleParts(emitter: LlEmitter): string[] { out.push(fnDefs[0] ?? ""); for (let i = 1; i < fnDefs.length; i++) out.push("", fnDefs[i]!); out.push(""); + // WebAssembly modules translated into this program, and the registry. + for (const line of emitWasmModules(emitter.mod, flushedDecls, emitter.wasmBoundsChecks)) + out.push(line); // main(): scr_init, the program-dependent error-vt interval stamps, // scr_lib_init(argc, argv), then the entry function. An uncaught @@ -873,6 +878,8 @@ export function emitModuleParts(emitter: LlEmitter): string[] { ...(runsLoop ? [ ...(emitter.mod.commonJsEntry === true ? [` call void @scr_loop_commonjs_entry()`] : []), + // performance.eventLoopUtilization measures from here on. + ...(emitter.readsLoopMetrics() ? [` call void @scr_perf_loop_mark()`] : []), ` %loop_rejection = call zeroext i1 @scr_loop_run(ptr ${asyncEntry ? "%top" : "null"})`, ` %lexc = call zeroext i1 @scr_exc_pending()`, ` br i1 %lexc, label %luncaught, label %lok`, diff --git a/packages/compiler/src/backend/llvm/emitter.ts b/packages/compiler/src/backend/llvm/emitter.ts index f7b9f2517..b72a6e226 100644 --- a/packages/compiler/src/backend/llvm/emitter.ts +++ b/packages/compiler/src/backend/llvm/emitter.ts @@ -1,3 +1,4 @@ +import { wasmBoundsChecks } from "./wasm-modules.js"; import { jsTruthy } from "./jsval.js"; import { type ArraySearchKind } from "./array-search.js"; import { emitStringInputs } from "./string-lifetimes.js"; @@ -181,6 +182,7 @@ import { genResultThunkFor, childExitThunkFor, childExitSignalThunkFor, + childDataDynThunkFor, childDataThunkFor, execFileThunkFor, ipcMessageThunkFor, @@ -413,6 +415,9 @@ export interface LlvmTargetOptions { * teardown after `process.exit` to a helper process (`--detached-exit`). * Executables only; the runtime's weak default keeps it off. */ detachedExit?: boolean; + /** Translated WebAssembly memories check bounds explicitly instead of + * relying on guard pages (wasm-modules.ts wasmBoundsChecks). */ + wasmBoundsChecks?: boolean; } export function emitLlvmModule(input: IrModule, options: LlvmTargetOptions = {}): string { @@ -682,6 +687,7 @@ export class LlEmitter { readonly emitLibraryIdentity: boolean; readonly runtimeAbiMarker: boolean; readonly detachedExit: boolean; + readonly wasmBoundsChecks: boolean; /** Interned string literals: UTF-8 text → { symbol, byte length } — * first-use order, the runtime ABI’s determinism discipline. */ readonly literals = new Map(); @@ -1175,6 +1181,13 @@ export class LlEmitter { this.emitLibraryIdentity = options.emitLibraryIdentity !== false; this.runtimeAbiMarker = options.runtimeAbiMarker === true; this.detachedExit = options.detachedExit === true; + this.wasmBoundsChecks = + options.wasmBoundsChecks === true || + wasmBoundsChecks({ + sanitize: false, + pointerBits: options.pointerBits ?? 64, + targetTriple: options.targetTriple ?? "", + }); this.rcHelpers = options.inlineRc !== undefined ? new Set() : null; this.rcMode = options.inlineRc; this.rcHelpersNoinline = options.rcHelpersNoinline === true; @@ -4201,6 +4214,20 @@ export class LlEmitter { /** Moves need plain slots that nothing else reads behind the binding's * back: no debugger view, no coroutine frame, no borrowed (+0) return. */ + /** Whether the program reads event-loop utilization (perf.loopStart / + * perf.idleTime): main then marks the loop's start before running it. */ + private loopMetricsRead: boolean | undefined; + readsLoopMetrics(): boolean { + if (this.loopMetricsRead !== undefined) return this.loopMetricsRead; + const visitor = { + expr: (e: IrExpr): boolean => + !(e.kind === "libCall" && (e.fn === "perf.loopStart" || e.fn === "perf.idleTime")), + stmt: (): boolean => true, + }; + this.loopMetricsRead = !this.mod.functions.every((fn) => everyStmtList(fn.body, visitor)); + return this.loopMetricsRead; + } + private lastUseMovesAllowed(): boolean { return ( this.debug === null && @@ -5564,6 +5591,10 @@ export class LlEmitter { return childDataThunkFor(this, param); } + childDataDynThunkFor(chunk: "bytes" | "str"): string { + return childDataDynThunkFor(this, chunk); + } + emitterFixedAdapter(cbT: IrType & { kind: "func" }): { fn: string; shim: string } { return emitterFixedAdapter(this, cbT); } diff --git a/packages/compiler/src/backend/llvm/expr-callbacks.ts b/packages/compiler/src/backend/llvm/expr-callbacks.ts index b7954c174..28bd15759 100644 --- a/packages/compiler/src/backend/llvm/expr-callbacks.ts +++ b/packages/compiler/src/backend/llvm/expr-callbacks.ts @@ -771,6 +771,31 @@ export function childDataThunkFor(host: LlvmEmitterContext, param: IrType): stri return sym; } +/** The child-stream 'data' thunk for an unknown/any chunk parameter: the + * runtime's Buffer (or, after setEncoding, string) chunk boxes into a + * checked-dynamic value the listener owns. */ +export function childDataDynThunkFor(host: LlvmEmitterContext, chunk: "bytes" | "str"): string { + const key = `cdd:${chunk}`; + let sym = host.resolveThunks.get(key); + if (sym) return sym; + sym = `sc_cdd_${host.resolveThunks.size}`; + host.resolveThunks.set(key, sym); + const box = chunk === "bytes" ? "scr_dyn_new_buffer" : "scr_dyn_new_str"; + host.declare(`declare ptr @${box}(ptr)`); + host.resolveThunkDefs.push( + `define internal void @${sym}(ptr %cb, ptr %chunk) ${FN_ATTRS} { ; child 'data' → dyn (${chunk})`, + `entry:`, + ` %d = call ptr @${box}(ptr %chunk)`, + ` %fnp = getelementptr inbounds %ScrClosure, ptr %cb, i64 0, i32 1`, + ` %fn = load ptr, ptr %fnp`, + ` call void %fn(ptr %cb, ptr %d)`, + ` ret void`, + `}`, + ``, + ); + return sym; +} + export function emitterFixedAdapter( host: LlvmEmitterContext, cbT: IrType & { kind: "func" }, diff --git a/packages/compiler/src/backend/llvm/expr-stream-callbacks.ts b/packages/compiler/src/backend/llvm/expr-stream-callbacks.ts index 3f7961163..9be757a20 100644 --- a/packages/compiler/src/backend/llvm/expr-stream-callbacks.ts +++ b/packages/compiler/src/backend/llvm/expr-stream-callbacks.ts @@ -17,7 +17,7 @@ export function streamDataAdapter( const p = cbT.params[0]; if ( cbT.params.length > 1 || - (p && p.kind !== "bytes" && p.kind !== "string" && p.kind !== "dyn") + (p && p.kind !== "bytes" && p.kind !== "string" && p.kind !== "dyn" && p.kind !== "union") ) { throw new InternalCompilerError( "llvm emitter bug: stream data listener param shape (frontend must fence)", @@ -73,6 +73,46 @@ export function streamDataAdapter( ); finish("%r0"); d.push(`}`, ``); + } else if (p.kind === "union") { + // A `Buffer | string` chunk: wrap whichever slot the stream filled at + // its arm of the (boxed) union. + const def = host.unionsById.get(p.unionId); + const bytesTag = def ? def.arms.findIndex((a) => a.kind === "bytes" && a.elem === "u8") : -1; + const strTag = def ? def.arms.findIndex((a) => a.kind === "string") : -1; + if ( + !def || + host.nullableUnions.has(p.unionId) || + bytesTag < 0 || + strTag < 0 || + def.arms.length !== 2 + ) + throw new InternalCompilerError( + "llvm emitter bug: stream data listener union is not Buffer | string (frontend must fence)", + ); + host.declare(`declare ptr @scr_union_new_ref(i32, ptr, ptr, ptr, ptr)`); + host.declare(`declare ptr @scr_bytes_retain_v(ptr)`); + host.declare(`declare void @scr_bytes_release_v(ptr)`); + host.declare(`declare ptr @scr_str_retain_v(ptr)`); + host.declare(`declare void @scr_str_release_v(ptr)`); + d.push( + ` %uslot = alloca ptr`, + ` %isb = icmp ne ptr %a0, null`, + ` br i1 %isb, label %buf, label %str`, + `buf:`, + ` %rb = call ptr @scr_bytes_retain_v(ptr %a0)`, + ` %ub = call ptr @scr_union_new_ref(i32 ${bytesTag}, ptr %rb, ptr @scr_bytes_retain_v, ptr @scr_bytes_release_v, ptr null)`, + ` store ptr %ub, ptr %uslot`, + ` br label %go`, + `str:`, + ` %rs = call ptr @scr_str_retain_v(ptr %a1)`, + ` %us = call ptr @scr_union_new_ref(i32 ${strTag}, ptr %rs, ptr @scr_str_retain_v, ptr @scr_str_release_v, ptr null)`, + ` store ptr %us, ptr %uslot`, + ` br label %go`, + `go:`, + ` %uv = load ptr, ptr %uslot`, + ); + finish("%uv"); + d.push(`}`, ``); } else { // dyn: box by runtime tag — the JS lane's adapter parameter. host.declare(`declare ptr @scr_dyn_new_buffer(ptr)`); diff --git a/packages/compiler/src/backend/llvm/lib-dispatch.ts b/packages/compiler/src/backend/llvm/lib-dispatch.ts index 16759a592..6cec9d403 100644 --- a/packages/compiler/src/backend/llvm/lib-dispatch.ts +++ b/packages/compiler/src/backend/llvm/lib-dispatch.ts @@ -857,6 +857,7 @@ export function emitLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlValue { case "event": case "events": case "blob": + case "wasm": case "record": case "disposable": case "punycode": diff --git a/packages/compiler/src/backend/llvm/lib-process.ts b/packages/compiler/src/backend/llvm/lib-process.ts index eaf7f31cd..4a7be1a35 100644 --- a/packages/compiler/src/backend/llvm/lib-process.ts +++ b/packages/compiler/src/backend/llvm/lib-process.ts @@ -305,6 +305,28 @@ export function emitChildProcessLibCall(host: LlvmEmitterContext, e: LibCallExpr B.line(`${raw} = call ptr @${get}(ptr ${recv.name}) ; +1 or NULL`); return host.wrapNullable(raw, raw, def!.arms[streamTag]!, streamTag, e.type, nullTag); } + if (e.fn === "child.stdioStream") { + // The general stream representation's stdio read: the child's bridged + // runtime stream (+1) or NULL for an unpiped slot. + if (e.type.kind !== "union") + throw new InternalCompilerError(`llvm emitter bug: ${e.fn} result is not a union`); + const def = host.unionsById.get(e.type.unionId); + const streamTag = def ? def.arms.findIndex((a) => a.kind === "object") : -1; + const nullTag = def ? def.arms.findIndex((a) => a.kind === "nullT") : -1; + const fd = e.args[1]; + if (streamTag < 0 || nullTag < 0 || fd?.kind !== "numLit") + throw new InternalCompilerError(`llvm emitter bug: ${e.fn} lacks its arms or slot`); + const recv = host.emitExpr(e.args[0]!); + const key = fd.value === 0 ? "stdin" : fd.value === 1 ? "stdout" : "stderr"; + host.declare(`declare ptr @scr_stream_child_stdio(ptr, ptr, ${host.sizeType})`); + const raw = B.tmp(); + B.line( + `${raw} = call ptr @scr_stream_child_stdio(ptr ${recv.name}, ptr ${host.cstr(key)}, ${host.sizeType} ${key.length}) ; +1 or NULL`, + ); + const out = host.wrapNullable(raw, raw, def!.arms[streamTag]!, streamTag, e.type, nullTag); + host.emitPendingCheck(); + return out; + } if (e.fn === "writer.writeString" || e.fn === "writer.writeBytes") { const writer = host.emitExpr(e.args[0]!); const data = host.emitExpr(e.args[1]!); diff --git a/packages/compiler/src/backend/llvm/lib-shared.ts b/packages/compiler/src/backend/llvm/lib-shared.ts index 503ed0e6d..91242b45c 100644 --- a/packages/compiler/src/backend/llvm/lib-shared.ts +++ b/packages/compiler/src/backend/llvm/lib-shared.ts @@ -127,6 +127,11 @@ export const LIB_FN_SYMS: Record = { "str.encodeUriComponent": "scr_str_encode_uri_component", "error.cause": "scr_error_cause", "error.setCause": "scr_error_set_cause", + "error.setCode": "scr_error_set_code_value", + "error.setCodeDyn": "scr_error_set_code_dyn", + "error.assign": "scr_error_assign_dyn", + "error.hasKey": "scr_error_has_key", + "error.hasCode": "scr_error_has_code", "error.defineCause": "scr_error_define_cause", "error.deleteCause": "scr_error_delete_cause", "error.hasCause": "scr_error_has_cause", @@ -278,6 +283,14 @@ export const LIB_FN_SYMS: Record = { "perf.entryDetail": "scr_perf_entry_detail", "perf.entryKeep": "scr_perf_entry_keep", "perf.entryRef": "scr_perf_entry_ref", + "perf.loopStart": "scr_perf_loop_start", + "perf.idleTime": "scr_perf_idle_time", + "perf.eldNew": "scr_eld_new", + "perf.eldEnable": "scr_eld_enable", + "perf.eldDisable": "scr_eld_disable", + "perf.eldReset": "scr_eld_reset", + "perf.eldPercentile": "scr_eld_percentile", + "perf.eldStat": "scr_eld_stat", "process.memoryUsageTake": "scr_process_memory_usage_take", "process.memoryUsageField": "scr_process_memory_usage_field", "process.rss": "scr_process_rss", @@ -727,6 +740,8 @@ export const LIB_FN_SYMS: Record = { "child.unref": "scr_child_unref", "child.ref": "scr_child_ref", "procStream.write": "scr_proc_stream_write", + "stream.stdioWritable": "scr_stream_stdio_writable", + "stream.unboxDyn": "scr_stream_unbox_dyn", "process.kill": "scr_process_kill_named", "process.killNum": "scr_process_kill", // fs.promises (scr_bytes_io.c / scr_lib.c): the promise forms settle @@ -859,6 +874,24 @@ export const LIB_FN_SYMS: Record = { "event.get": "scr_event_obj_get", "event.set": "scr_event_obj_set", "blob.new": "scr_blob_new", + "wasm.compile": "scr_wasm_compile", + "wasm.validate": "scr_wasm_validate", + "wasm.instantiate": "scr_wasm_instantiate", + "wasm.moduleNew": "scr_wasm_module_new", + "wasm.instanceNew": "scr_wasm_instance_new", + "wasm.is": "scr_wasm_is", + "wasm.errorNew": "scr_wasm_error_new", + "wasm.memoryNew": "scr_wasm_memory_construct", + "wasm.tableNew": "scr_wasm_table_construct", + "wasm.globalNew": "scr_wasm_global_construct", + "wasm.withoutNew": "scr_wasm_construct_without_new", + "wasm.moduleImports": "scr_wasm_module_imports", + "wasm.moduleExports": "scr_wasm_module_exports", + "wasm.moduleCustomSections": "scr_wasm_module_custom_sections", + "wasm.valueOf": "scr_wasm_value_of", + "wasm.function": "scr_wasm_function", + "wasm.namespace": "scr_wasm_namespace", + "wasm.globalView": "scr_wasm_global_view", "blob.fileNew": "scr_file_new", "blob.slice": "scr_blob_slice", "blob.text": "scr_blob_text", @@ -1110,6 +1143,7 @@ export const LIB_FN_SYMS: Record = { "readable.opFind": "scr_stream_op_find", "readable.opReduce": "scr_stream_op_reduce", "readable.pipe": "scr_stream_pipe", + "readable.pipeGeneral": "scr_stream_pipe_general", "writable.cork": "scr_stream_cork", "writable.uncork": "scr_stream_uncork", "stream.destroyErr": "scr_stream_destroy", @@ -1424,6 +1458,9 @@ export const LIB_FN_SYMS: Record = { "dyn.classPrototype": "scr_dyn_class_prototype", "dyn.classBasePrototype": "scr_dyn_class_base_prototype", "dyn.classInherit": "scr_dyn_class_inherit", + "dyn.builtinClass": "scr_dyn_builtin_class", + "dyn.builtinInstanceOf": "scr_dyn_builtin_instanceof", + "dyn.functionInstanceOf": "scr_dyn_function_instanceof", "dyn.classSuper": "scr_dyn_class_super", "dyn.assignPrototype": "scr_dyn_assign_prototype", "dyn.definePrototypeProps": "scr_dyn_define_prototype_props", @@ -1596,6 +1633,7 @@ export const USES_TIMERS_LIB_FNS = new Set([ "readable.opReduce", "readable.resume", "readable.pipe", + "readable.pipeGeneral", "readable.unpipe", "writable.write", "writable.writeStr", diff --git a/packages/compiler/src/backend/llvm/lib-stream.ts b/packages/compiler/src/backend/llvm/lib-stream.ts index b62b237df..0ded59a1a 100644 --- a/packages/compiler/src/backend/llvm/lib-stream.ts +++ b/packages/compiler/src/backend/llvm/lib-stream.ts @@ -56,6 +56,8 @@ export function emitStreamLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlV host.declare(`declare void @scr_child_stream_thunk0(ptr, ptr)`); } else if (param.kind === "union") { adapter = host.childDataThunkFor(param); + } else if (param.kind === "dyn") { + adapter = host.childDataDynThunkFor("bytes"); } else { adapter = "scr_child_stream_thunk_bytes"; host.declare(`declare void @scr_child_stream_thunk_bytes(ptr, ptr)`); @@ -78,7 +80,8 @@ export function emitStreamLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlV if (e.fn === "stream.onDataStr") { host.usesTimers = true; const cbT = e.args[1]!.type; - if (cbT.kind !== "func" || cbT.params[0]?.kind !== "string") { + const strParam = cbT.kind === "func" ? cbT.params[0]?.kind : undefined; + if (strParam !== "string" && strParam !== "dyn") { throw new InternalCompilerError( "llvm emitter bug: stream.onDataStr callback not a string func", ); @@ -87,10 +90,12 @@ export function emitStreamLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlV const cb = host.emitExpr(e.args[1]!); const once = host.emitExpr(e.args[2]!); host.toHeap(cb); - host.declare(`declare void @scr_child_stream_thunk_str(ptr, ptr)`); + let adapter = "scr_child_stream_thunk_str"; + if (strParam === "dyn") adapter = host.childDataDynThunkFor("str"); + else host.declare(`declare void @scr_child_stream_thunk_str(ptr, ptr)`); host.declare(`declare void @scr_child_stream_on_data_str(ptr, ptr, ptr, i1 zeroext)`); B.line( - `call void @scr_child_stream_on_data_str(ptr ${s0.name}, ptr ${cb.name}, ptr @scr_child_stream_thunk_str, i1 ${once.name})`, + `call void @scr_child_stream_on_data_str(ptr ${s0.name}, ptr ${cb.name}, ptr @${adapter}, i1 ${once.name})`, ); return { name: "", type: e.type }; } diff --git a/packages/compiler/src/backend/llvm/wasm-modules.ts b/packages/compiler/src/backend/llvm/wasm-modules.ts new file mode 100644 index 000000000..8a7045687 --- /dev/null +++ b/packages/compiler/src/backend/llvm/wasm-modules.ts @@ -0,0 +1,77 @@ +/* The WebAssembly modules translated into a program (IrModule.wasmModules): + * each module's translation (wasm/translate.ts) and the registry the + * runtime looks modules up in (scr_wasm_registry, scr_wasm_abi.h). The + * translations join the program module, so the native helper optimizes, + * partitions and caches them with it. Programs that do not use the + * WebAssembly API carry no wasmModules and emit nothing here. */ +import type { IrModule } from "../../ir/ir.js"; +import { decodeBase64 } from "../../wasm/base64.js"; +import { translateWasmModule, WasmTranslateError } from "../../wasm/translate.js"; + +function hexBytes(hex: string): Uint8Array { + const out = new Uint8Array(hex.length / 2); + for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); + return out; +} + +/** Whether translated memories check bounds explicitly instead of relying + * on guard pages and the runtime's fault handler: sanitizer builds (whose + * runtime owns SIGSEGV), 32-bit targets, and Windows, which has no + * fault handler yet. */ +export function wasmBoundsChecks(options: { + sanitize: boolean; + pointerBits: 32 | 64; + targetTriple: string; +}): boolean { + if (options.sanitize || options.pointerBits === 32) return true; + const target = options.targetTriple || process.platform; + return /windows|mingw|cygwin|win32|msvc/.test(target); +} + +/** The top-level lines of every translated module plus the registry. + * `declared` holds the declarations the module already carries; runtime + * entry points it lacks are declared here. A module the translator + * cannot translate is left out of the registry, so loading it at run + * time rejects with the CompileError for untranslated bytes. */ +export function emitWasmModules( + mod: IrModule, + declared: ReadonlySet, + boundsChecks: boolean, +): string[] { + const modules = mod.wasmModules; + if (modules === undefined) return []; + const out: string[] = []; + const decls = new Set(declared); + const descriptors: string[] = []; + for (const module of modules) { + const bytes = decodeBase64(module.bytes); + if (bytes === null) continue; + let translation; + try { + translation = translateWasmModule(bytes, hexBytes(module.sha256), { + boundsChecks, + customSections: mod.wasmCustomSections === true, + }); + } catch (error) { + if (error instanceof WasmTranslateError) continue; + throw error; + } + for (const decl of translation.decls) { + if (decls.has(decl)) continue; + decls.add(decl); + out.push(decl); + } + for (const part of translation.text) out.push(part); + descriptors.push(translation.descriptor); + } + if (descriptors.length === 0) { + out.push(`@scr_wasm_registry = constant { i64, ptr } { i64 0, ptr null }`); + } else { + out.push( + `@sc_wasm_registry_modules = private constant [${descriptors.length} x ptr] [${descriptors.map((d) => `ptr ${d}`).join(", ")}]`, + `@scr_wasm_registry = constant { i64, ptr } { i64 ${descriptors.length}, ptr @sc_wasm_registry_modules }`, + ); + } + out.push(""); + return out; +} diff --git a/packages/compiler/src/backend/native-link-info-core.ts b/packages/compiler/src/backend/native-link-info-core.ts index 8f2df0452..031f99ddd 100644 --- a/packages/compiler/src/backend/native-link-info-core.ts +++ b/packages/compiler/src/backend/native-link-info-core.ts @@ -25,6 +25,9 @@ export interface NativeLinkFeatures { fileHandle: boolean; fetch: boolean; eventTarget?: boolean; + /** The WebAssembly API (scr_wasm.c). Absent when unused, so programs + * without it keep their link identity. */ + wasm?: boolean; /** The program assigns process.emitWarning: links the * SCR_WARNING_REPLACE variant of the dyn-async unit. */ warningReplace?: boolean; @@ -46,6 +49,7 @@ export interface NativeLinkFeatures { bigint: boolean; searchParams: boolean; qs: boolean; + dynBuiltinClass: boolean; parseArgs: boolean; stream: boolean; net: boolean; @@ -61,6 +65,8 @@ export interface NativeLinkFeatures { /** crypto.createCipheriv/createDecipheriv: scr_cipher.c plus the mbedTLS * archive. */ cipher: boolean; + /** perf_hooks event-loop metrics: scr_perf_loop.c. */ + perfLoop: boolean; tlsCa: boolean; /** crypto.subtle importKey/sign/verify/digest and CryptoKey values: * scr_webcrypto.c. */ diff --git a/packages/compiler/src/backend/native/contracts.ts b/packages/compiler/src/backend/native/contracts.ts index e64614595..8abdc6c38 100644 --- a/packages/compiler/src/backend/native/contracts.ts +++ b/packages/compiler/src/backend/native/contracts.ts @@ -118,6 +118,8 @@ export interface CcOptions { * native fetch AbortSignal built on the same engine: compiles * scr_event_target.c. */ eventTarget?: boolean; + /** The WebAssembly API: compiles scr_wasm.c. */ + wasm?: boolean; /** SCR_WARNING_REPLACE: process.emitWarning replacement support. */ warningReplace?: boolean; /** SCR_STDIO_EXTENDED: stdin encoding, string data listeners, resize. */ @@ -150,6 +152,11 @@ export interface CcOptions { * line (escape-only programs ride the always-linked component encoder * and never flip this). */ qs?: boolean; + /** The program uses EventEmitter or a stream class as an untyped + * constructor value (a constructor function's base): compiles + * scr_dyn_builtin_class.c, which also references the inspection, + * dyn-invoke and symbol units. */ + dynBuiltinClass?: boolean; /** The program uses native util parsing, comparison, or styling. Optional * utility units also require their symbol, inspection, and warning features. */ parseArgs?: boolean; @@ -214,6 +221,8 @@ export interface CcOptions { cipher?: boolean; /** crypto.subtle importKey/sign/verify/digest: compiles scr_webcrypto.c. */ webcrypto?: boolean; + /** perf_hooks event-loop metrics: compiles scr_perf_loop.c. */ + perfLoop?: boolean; /** Internal compiler hook: called only after a strict native artifact hit * or a successful stable build has installed `outPath`. The executable * frontend cache uses it to publish its stamp after native dependencies diff --git a/packages/compiler/src/backend/native/executable.ts b/packages/compiler/src/backend/native/executable.ts index 9c083fe9b..33c126de8 100644 --- a/packages/compiler/src/backend/native/executable.ts +++ b/packages/compiler/src/backend/native/executable.ts @@ -182,6 +182,7 @@ const RUNTIME_UNITS: readonly RuntimeUnit[] = [ unit((u) => u.opts.dc, "scr_dc.c"), unit((u) => u.opts.dynTier, "scr_js_value.c"), unit((u) => u.opts.eventTarget || u.nativeFetch, "scr_event_target.c"), + unit((u) => u.opts.wasm, "scr_wasm.c"), unit( (u) => u.opts.dynAsync || @@ -195,6 +196,8 @@ const RUNTIME_UNITS: readonly RuntimeUnit[] = [ // The performance timeline (every perf_hooks user-timing call selects // dynAsync, whose unit carries the timeline's buffer warning). unit((u) => u.opts.dynAsync, "scr_perf.c"), + // perf_hooks event-loop metrics, only for programs that read them. + unit((u) => u.opts.perfLoop, "scr_perf_loop.c"), // Blob and File (every blob.* call selects dynAsync, whose unit boxes // their reads as dyn promises). unit((u) => u.opts.dynAsync, "scr_blob.c"), @@ -235,6 +238,15 @@ const RUNTIME_UNITS: readonly RuntimeUnit[] = [ (u) => u.opts.parseArgs && u.opts.inspect && u.opts.dynAsync && u.opts.dynInvoke && u.regex, "scr_util_callable.c", ), + unit( + (u) => + u.opts.dynBuiltinClass && + u.opts.inspect && + u.opts.dynInvoke && + u.opts.symbol && + (u.opts.emitter || u.opts.workers), + "scr_dyn_builtin_class.c", + ), unit((u) => u.opts.stream, "scr_stream.c", "scr_fs_stream.c"), // The zlib stream classes reference both the zlib engine and the // stream unit. diff --git a/packages/compiler/src/backend/runtime-pack-core.ts b/packages/compiler/src/backend/runtime-pack-core.ts index 6a660e00c..be94b33b9 100644 --- a/packages/compiler/src/backend/runtime-pack-core.ts +++ b/packages/compiler/src/backend/runtime-pack-core.ts @@ -82,6 +82,7 @@ export interface RuntimeFeatureSet extends NativeLinkFeatures { workers: boolean; youngNursery: boolean; eventTarget: boolean; + wasm: boolean; dynTier: boolean; warningReplace: boolean; stdioExtended: boolean; @@ -272,6 +273,7 @@ export function effectiveRuntimeFeatures( workers: features.workers === true, youngNursery: features.youngNursery === true, eventTarget: features.eventTarget === true, + wasm: features.wasm === true, dynTier: features.dynTier === true, warningReplace: features.warningReplace === true, stdioExtended: features.stdioExtended === true, diff --git a/packages/compiler/src/backend/runtime-pack-targets.test.ts b/packages/compiler/src/backend/runtime-pack-targets.test.ts index 49ca691cb..a39ce78e2 100644 --- a/packages/compiler/src/backend/runtime-pack-targets.test.ts +++ b/packages/compiler/src/backend/runtime-pack-targets.test.ts @@ -107,6 +107,7 @@ const features = { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -121,6 +122,7 @@ const features = { tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, }; test.each([ diff --git a/packages/compiler/src/backend/runtime-pack.test.ts b/packages/compiler/src/backend/runtime-pack.test.ts index 91a74eb7e..1681626b7 100644 --- a/packages/compiler/src/backend/runtime-pack.test.ts +++ b/packages/compiler/src/backend/runtime-pack.test.ts @@ -44,6 +44,7 @@ const BASE: NativeLinkFeatures = { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -58,6 +59,7 @@ const BASE: NativeLinkFeatures = { tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, }; async function fixture(target: NativeTargetSpec = MACOS_ARM64_TARGET) { diff --git a/packages/compiler/src/backend/target-diagnostics.ts b/packages/compiler/src/backend/target-diagnostics.ts index 365d5e913..d130ce95e 100644 --- a/packages/compiler/src/backend/target-diagnostics.ts +++ b/packages/compiler/src/backend/target-diagnostics.ts @@ -192,6 +192,14 @@ export function moduleWasiUnavailableSurface( found = { surface: "OS signals (WASI Preview 1 has no signal API)", loc }; return false; } + if (node.fn.startsWith("wasm.")) { + found = { + surface: + "the WebAssembly API (a wasm32-wasi program cannot load translated modules into its own linear memory yet)", + loc, + }; + return false; + } if (node.fn === "crypto.cipherNew") { found = { surface: diff --git a/packages/compiler/src/backend/warm-cache.ts b/packages/compiler/src/backend/warm-cache.ts index eb7822d10..9a505d517 100644 --- a/packages/compiler/src/backend/warm-cache.ts +++ b/packages/compiler/src/backend/warm-cache.ts @@ -50,6 +50,7 @@ export async function warmNativeCaches( bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -63,6 +64,7 @@ export async function warmNativeCaches( tls: false, cipher: false, webcrypto: false, + perfLoop: false, tlsCa: false, }, }); diff --git a/packages/compiler/src/coverage/report.ts b/packages/compiler/src/coverage/report.ts index 6570f23d1..89733e255 100644 --- a/packages/compiler/src/coverage/report.ts +++ b/packages/compiler/src/coverage/report.ts @@ -221,13 +221,13 @@ export function renderCoverage(input: CoverageInput, opts: CoverageRenderOptions out.push(""); } - // The WebAssembly modules the build can see: what translating them would - // take (wasm/discover.ts). No module compiles to native code yet; the - // sites that load one are blockers or deferred fences above. + // The WebAssembly modules the build can see (wasm/discover.ts). A build + // translates the valid ones to native code (wasm/translate.ts) when the + // program uses the WebAssembly API; the others fail to load at run time. const wasm = input.wasmModules ?? []; if (wasm.length > 0) { out.push( - ` ${c(DIM, "WebAssembly modules:")} ${c(DIM, "(found at build time; none compile to native code yet)")}`, + ` ${c(DIM, "WebAssembly modules:")} ${c(DIM, "(found at build time; valid ones compile to native code)")}`, ); for (const m of wasm) { const name = m.path !== undefined ? displayPath(m.path, opts.root) : "inline module"; diff --git a/packages/compiler/src/coverage/surface-manifest.ts b/packages/compiler/src/coverage/surface-manifest.ts index d82367611..9867a5617 100644 --- a/packages/compiler/src/coverage/surface-manifest.ts +++ b/packages/compiler/src/coverage/surface-manifest.ts @@ -444,16 +444,17 @@ export function generateSurfaceManifest(compilerVersion: string): SurfaceManifes } } - // ── the WebAssembly global: every reached use refuses (webAssemblyDiag) ─ + // ── the WebAssembly global (builtins/webassembly.ts, wasm/translate.ts): + // the core API lowers over modules translated at build time; the rest + // refuses at each use (webAssemblyDiag) ─ { const refusal = webAssemblyDiag("WebAssembly", { file: "", start: 0, end: 0 }); add({ id: "stdlib.webassembly", kind: "stdlib", name: "globalThis.WebAssembly", - status: "unsupported", - code: refusal.code, - ...(refusal.hint !== undefined ? { note: refusal.hint } : {}), + status: "static", + note: `compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, instanceof, the error classes, exports, imports and Module transfer to workers, over the modules translated at build time; the rest refuses with ${refusal.code} (${refusal.hint ?? ""})`, }); } diff --git a/packages/compiler/src/diagnostics/diagnostic.ts b/packages/compiler/src/diagnostics/diagnostic.ts index 049202624..e4d4006ca 100644 --- a/packages/compiler/src/diagnostics/diagnostic.ts +++ b/packages/compiler/src/diagnostics/diagnostic.ts @@ -740,17 +740,20 @@ export function noLoweringDiag( }; } -/** A REACHED use of the WebAssembly API (SC2020): scriptc.d.ts declares - * its types so packages that mention them typecheck, but no module - * compiles to native code yet. `surface` names what was used - * ('WebAssembly.compile', 'new WebAssembly.Module', 'globalThis.WebAssembly'). */ +/** A REACHED use of a part of the WebAssembly API scriptc does not + * implement yet (SC2020): the streaming functions, Tag and Exception, the + * classes as values. compile, instantiate, validate, the Module, Instance, + * Memory, Table and Global constructors, Module.imports/exports/ + * customSections and the error classes lower (builtins/webassembly.ts). + * `surface` names what was used ('WebAssembly.compileStreaming', + * 'WebAssembly.Memory'). */ export function webAssemblyDiag(surface: string, loc: SrcLoc): ScrDiagnostic { return { code: "SC2020", - message: `'${surface}' is not supported yet: scriptc does not compile WebAssembly modules to native code yet`, + message: `'${surface}' is not supported yet: scriptc implements WebAssembly.compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, and the error classes over modules translated at build time, but not this part of the API`, loc, milestone: "later", - hint: "WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations)", + hint: "the streaming functions, Tag and Exception, and the classes used as values other than with new and instanceof are planned; 'scriptc coverage' lists the modules this program loads (https://scriptc.dev/limitations)", }; } diff --git a/packages/compiler/src/executable/executable-cache.test.ts b/packages/compiler/src/executable/executable-cache.test.ts index d12a5d1f0..5b0982dc1 100644 --- a/packages/compiler/src/executable/executable-cache.test.ts +++ b/packages/compiler/src/executable/executable-cache.test.ts @@ -45,6 +45,7 @@ const native: EarlyExecutableNativeFeatures = { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -59,6 +60,7 @@ const native: EarlyExecutableNativeFeatures = { tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, }; async function fixture(): Promise<{ diff --git a/packages/compiler/src/executable/executable-cache.ts b/packages/compiler/src/executable/executable-cache.ts index 4f3fed552..fd4a34ec2 100644 --- a/packages/compiler/src/executable/executable-cache.ts +++ b/packages/compiler/src/executable/executable-cache.ts @@ -56,6 +56,7 @@ export interface EarlyExecutableNativeFeatures { fileHandle: boolean; fetch: boolean; eventTarget?: boolean; + wasm?: boolean; warningReplace?: boolean; stdioExtended?: boolean; zlib: boolean; @@ -71,6 +72,7 @@ export interface EarlyExecutableNativeFeatures { bigint: boolean; searchParams: boolean; qs: boolean; + dynBuiltinClass: boolean; parseArgs: boolean; stream: boolean; net: boolean; @@ -83,6 +85,7 @@ export interface EarlyExecutableNativeFeatures { nodeTest: boolean; tls: boolean; cipher: boolean; + perfLoop: boolean; tlsCa: boolean; webcrypto: boolean; } @@ -189,6 +192,7 @@ const BOOLEAN_NATIVE_KEYS = [ "bigint", "searchParams", "qs", + "dynBuiltinClass", "parseArgs", "stream", "net", @@ -203,6 +207,7 @@ const BOOLEAN_NATIVE_KEYS = [ "tlsCa", "cipher", "webcrypto", + "perfLoop", ] as const satisfies readonly (keyof EarlyExecutableNativeFeatures)[]; function validNativeFeatures(value: unknown): value is EarlyExecutableNativeFeatures { diff --git a/packages/compiler/src/frontend/lowering/array-values.ts b/packages/compiler/src/frontend/lowering/array-values.ts index 8f2b28a3f..0ca8503df 100644 --- a/packages/compiler/src/frontend/lowering/array-values.ts +++ b/packages/compiler/src/frontend/lowering/array-values.ts @@ -8,6 +8,7 @@ import { type IrType, isIntegerBytesElem, type SrcLoc, + STRING, UNDEFINED_T, typeEquals, typeKey, @@ -84,29 +85,54 @@ export function arrayValueRead( }; } -/** Read a stabilized union of native arrays without copying either the - * receiver or its elements. Every arm contributes its missing-value case. */ +/** Read one position of a stabilized union of native arrays and tuples + * (`const [a, b] = re.exec(s) || ["", ""]`) without copying the receiver + * or its elements. Every array arm contributes its missing-value case; a + * tuple arm answers its field, or undefined past its end. Tuple arms need + * a constant position. With `stringChars` (the string iterator's code + * points as a fresh string[]), a string arm (`re.exec(s) || ""`) answers + * its code point at the position, or undefined past its end. */ export function unionArrayValueRead( lowerer: Lowerer, value: IrExpr, index: IrExpr, loc: SrcLoc, + stringChars?: (text: IrExpr) => IrExpr, ): IrExpr | null { if (value.type.kind !== "union") return null; const unionId = value.type.unionId; const arms = lowerer.unions.get(unionId)?.arms; if (!arms?.length) return null; + const position = index.kind === "numLit" ? String(index.value) : null; + // A tuple arm's answer at the position: its field, or undefined past + // its end. Null when the arm is neither an array nor a tuple. + const tupleField = (arm: IrType): { name: string; type: IrType } | "past" | null => { + if (arm.kind !== "record" || position === null) return null; + const shape = lowerer.shapes.get(arm.shapeId); + if (!shape?.tuple) return null; + return shape.fields.find((f) => f.name === position) ?? "past"; + }; // Keep the collection's IrType union layout and narrow each element at // its use; an inferred array predicate changes the collection's ABI. - for (const arm of arms) if (arm.kind !== "array") return null; + const stringArm = (arm: IrType): boolean => arm.kind === "string" && stringChars !== undefined; + for (const arm of arms) + if (arm.kind !== "array" && !stringArm(arm) && tupleField(arm) === null) return null; const answers = new Map(); for (const arm of arms) { - if (arm.kind !== "array") return null; - const answer = arrayValueType(lowerer, arm.elem); + const field = arm.kind === "array" || stringArm(arm) ? null : tupleField(arm); + const answer = + arm.kind === "array" + ? arrayValueType(lowerer, arm.elem) + : stringArm(arm) + ? arrayValueType(lowerer, STRING) + : field === "past" + ? UNDEFINED_T + : field!.type; const parts = answer.kind === "union" ? lowerer.unions.get(answer.unionId)!.arms : [answer]; for (const part of parts) answers.set(typeKey(part), part); } const joined = [...answers.values()].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1)); + if (joined.length === 1 && joined[0]!.kind === "undefinedT") return null; if ( joined.length > 1 && (!unionContainerArmsOk(joined) || @@ -118,12 +144,39 @@ export function unionArrayValueRead( let result: IrExpr | null = null; for (let tag = arms.length - 1; tag >= 0; tag--) { const arm = arms[tag]!; - if (arm.kind !== "array") return null; const receiver: IrExpr = { kind: "unionNarrow", unionId, tag, value, type: arm, loc }; - const read = lowerer.coerceToExpected( - arrayValueRead(lowerer, receiver, index, arm.elem, loc), - type, - ); + let read: IrExpr; + if (arm.kind === "array") { + read = lowerer.coerceToExpected( + arrayValueRead(lowerer, receiver, index, arm.elem, loc), + type, + ); + } else if (stringArm(arm)) { + read = lowerer.coerceToExpected( + arrayValueRead(lowerer, stringChars!(receiver), index, STRING, loc), + type, + ); + } else { + const field = tupleField(arm); + if (field === null) return null; + if (field === "past") { + const missing = lowerer.wrappedUndefined(type, loc); + if (!missing) return null; + read = missing; + } else { + read = lowerer.coerceToExpected( + { + kind: "recordGet", + obj: receiver, + shapeId: (arm as IrType & { kind: "record" }).shapeId, + field: field.name, + type: field.type, + loc, + }, + type, + ); + } + } result = result === null ? read diff --git a/packages/compiler/src/frontend/lowering/builtin-calls.ts b/packages/compiler/src/frontend/lowering/builtin-calls.ts index de287be4f..d2e4b53d5 100644 --- a/packages/compiler/src/frontend/lowering/builtin-calls.ts +++ b/packages/compiler/src/frontend/lowering/builtin-calls.ts @@ -1,4 +1,5 @@ import { lowerReadlineCursorCall } from "./builtins/readline.js"; +import { lowerMonitorEventLoopDelayCall } from "./builtins/performance.js"; import { lowerEnvironmentData, lowerReceiveMessageOnPort, @@ -104,6 +105,9 @@ export function lowerBuiltinCall( return lowerAddAbortListener(lowerer, expr, loc); } if (bi.module === "events" && bi.member === "once") return lowerEventsOnce(lowerer, expr, loc); + if (bi.module === "perf_hooks" && bi.member === "monitorEventLoopDelay") { + return lowerMonitorEventLoopDelayCall(lowerer, expr); + } if (bi.module === "events") { const helper = lowerEventsEmitterHelper(lowerer, expr, bi.member, loc); if (helper) return helper; diff --git a/packages/compiler/src/frontend/lowering/builtins/builtin-class-dyn.ts b/packages/compiler/src/frontend/lowering/builtins/builtin-class-dyn.ts new file mode 100644 index 000000000..ac73924ad --- /dev/null +++ b/packages/compiler/src/frontend/lowering/builtins/builtin-class-dyn.ts @@ -0,0 +1,149 @@ +import { numLit } from "../../../ir/build.js"; +import { BOOL, DYN, RUNTIME_EMITTER_CLASS, type IrExpr, type SrcLoc } from "../../../ir/ir.js"; +import * as ts from "../../ts7/adapter.js"; +import { locOf } from "../../program.js"; +import type { Lowerer } from "../lowerer.js"; + +/* EventEmitter and the stream classes as untyped constructor values, the + * bases of JavaScript constructor functions: + * + * function Bus() { EventEmitter.call(this); } + * util.inherits(Bus, EventEmitter); + * + * A compiled `class Bus extends EventEmitter` gets a native emitter prefix, + * but `new Bus()` on a constructor function builds an untyped object, so + * the base is the runtime's dyn constructor (scr_dyn_builtin_class.c): a + * function whose prototype carries Node's EventEmitter methods over the + * object's own `_events` table. The stream classes have prototype chains + * for util.inherits and instanceof; constructing over them refuses where + * it runs. These values appear only where a constructor function uses its + * base: util.inherits, `Base.call(this, …)` and `Base.apply(this, …)`, + * `Base.prototype` and `instanceof Base` on an untyped value. */ + +/** scr_dyn_builtin_class's kind for a runtime class, or null. */ +export function builtinClassKind(className: string): number | null { + switch (className) { + case RUNTIME_EMITTER_CLASS: + return 0; + case "%Readable": + return 2; + case "%Writable": + return 3; + case "%Duplex": + return 4; + case "%Transform": + return 5; + case "%PassThrough": + return 6; + default: + return null; + } +} + +/** The classes by builtin module member. JavaScript sources bind + * `require("events").EventEmitter` as a module member rather than a class + * value, and `require("stream")` is the legacy Stream constructor. */ +const MODULE_CLASS_KINDS: Readonly>>> = { + events: { EventEmitter: 0, default: 0 }, + stream: { Stream: 1, Readable: 2, Writable: 3, Duplex: 4, Transform: 5, PassThrough: 6 }, +}; + +/** The kind of a builtin module member that is one of those classes. */ +export function builtinMemberClassKind(module: string, member: string): number | null { + return MODULE_CLASS_KINDS[module]?.[member] ?? null; +} + +function unparenthesized(node: ts.Expression): ts.Expression { + let current = node; + while (ts.isParenthesizedExpression(current)) current = current.expression; + return current; +} + +/** The kind of a node that names one of those classes: a class value, a + * builtin module member, or the events and stream modules themselves. */ +export function builtinClassKindOf(lowerer: Lowerer, node: ts.Expression): number | null { + const expr = unparenthesized(node); + const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr)); + if (mapped?.kind === "classval") return builtinClassKind(mapped.className); + const member = ts.isIdentifier(expr) + ? lowerer.builtinImportOf(expr) + : ts.isPropertyAccessExpression(expr) + ? lowerer.builtinMemberOf(expr) + : null; + if (member) return MODULE_CLASS_KINDS[member.module]?.[member.member] ?? null; + const module = lowerer.builtinNamespaceModuleOf(expr); + return module === "events" ? 0 : module === "stream" ? 1 : null; +} + +/** Whether evaluating the node can be skipped: a binding or a member of + * one, or of a builtin require. */ +function referenceOnly(node: ts.Expression): boolean { + const expr = unparenthesized(node); + if (ts.isIdentifier(expr)) return true; + if (ts.isPropertyAccessExpression(expr) && !expr.questionDotToken) { + const base = unparenthesized(expr.expression); + return ( + ts.isIdentifier(base) || + (ts.isCallExpression(base) && + ts.isIdentifier(base.expression) && + base.expression.text === "require" && + base.arguments.nodes.length === 1 && + ts.isStringLiteral(base.arguments.nodes[0]!)) + ); + } + return false; +} + +/** The untyped constructor named by a node, or null when it names none of + * those classes. */ +export function builtinClassDynValueOf(lowerer: Lowerer, node: ts.Expression): IrExpr | null { + const kind = builtinClassKindOf(lowerer, node); + if (kind === null) return null; + const loc = locOf(node); + const value = builtinClassValue(kind, loc); + if (referenceOnly(node)) return value; + return { + kind: "seqExpr", + stmts: [{ kind: "exprStmt", expr: lowerer.lowerExpr(node), loc }], + result: value, + type: DYN, + loc, + }; +} + +export function builtinClassValue(kind: number, loc: SrcLoc): IrExpr { + return { kind: "libCall", fn: "dyn.builtinClass", args: [numLit(kind, loc)], type: DYN, loc }; +} + +/** `Base.call(this, …)` / `Base.apply(this, args)` on one of those class + * values: Function.prototype.call/apply over the untyped constructor. */ +export function lowerBuiltinClassCall(lowerer: Lowerer, call: ts.CallExpression): IrExpr | null { + const callee = call.expression; + if (!ts.isPropertyAccessExpression(callee) || callee.questionDotToken) return null; + const method = callee.name.text; + if (method !== "call" && method !== "apply") return null; + if (call.arguments.nodes.some(ts.isSpreadElement)) return null; + const receiver = builtinClassDynValueOf(lowerer, callee.expression); + if (receiver === null) return null; + const loc = locOf(call); + return { + kind: "dynInvoke", + recv: receiver, + method, + calleeName: callee.getText(), + args: call.arguments.nodes.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), + type: DYN, + loc, + }; +} + +/** `value instanceof Base` for an untyped value. */ +export function builtinClassInstanceOf(value: IrExpr, kind: number, loc: SrcLoc): IrExpr { + return { + kind: "libCall", + fn: "dyn.builtinInstanceOf", + args: [value, numLit(kind, loc)], + type: BOOL, + loc, + }; +} diff --git a/packages/compiler/src/frontend/lowering/builtins/child-process-methods.ts b/packages/compiler/src/frontend/lowering/builtins/child-process-methods.ts index a435bf740..e1a25d169 100644 --- a/packages/compiler/src/frontend/lowering/builtins/child-process-methods.ts +++ b/packages/compiler/src/frontend/lowering/builtins/child-process-methods.ts @@ -1,5 +1,6 @@ import { boolLit, strLit } from "../../../ir/build.js"; import * as ts from "../../ts7/adapter.js"; +import { requestGeneralStreamSurface } from "../general-streams.js"; import { type Lowerer } from "../lowerer.js"; import { isJsSourceFile, locOf } from "../../program.js"; import { isChildSurfaceMember } from "../surfaces.js"; @@ -131,8 +132,16 @@ export function lowerChildMethodCall( ) { for (const param of listenerNode.parameters.nodes) lowerer.checkedCallbackParams.add(param); } - const cb = lowerer.lowerExpr(call.arguments.nodes[1]!); + const narrowed = + event === "exit" || event === "close" + ? narrowedExitListenerParams(lowerer, listenerNode) + : []; + const cb = + narrowed.length > 0 + ? lowerWithCheckedParams(lowerer, listenerNode, narrowed) + : lowerer.lowerExpr(call.arguments.nodes[1]!); if ( + narrowed.length > 0 || (isJsSourceFile(listenerNode.getSourceFile()) && cb.type.kind === "dyn") || (cb.type.kind === "func" && (cb.type.rest || @@ -301,10 +310,12 @@ export function lowerChildMethodCall( /** Method calls on piped child-output stream receivers (child.stdout / * child.stderr — the childStream kind): on/once("data" | "end"). - * 'data' listeners take zero parameters, `(chunk: Buffer)`, or a - * `Buffer | string`-union chunk (the ngrok appendOutput shape — the - * runtime only ever fires Buffers; the compiler-emitted adapter wraps - * the chunk at the union's Buffer arm); 'end' listeners take none. + * 'data' listeners take zero parameters, `(chunk: Buffer)`, `(chunk: + * string)`, an unknown/any chunk (boxed as a checked-dynamic value; see + * childStreamEncodedAt), or a `Buffer | string`-union chunk (the ngrok + * appendOutput shape — the runtime only ever fires Buffers; the + * compiler-emitted adapter wraps the chunk at the union's Buffer arm); + * 'end' listeners take none. * Statement position only (Node returns the stream for chaining; here * the result is void). Chained receivers (`child.stdout?.on(...)`) * ride the optional-chain re-dispatch (chainBlocked). Everything else @@ -335,6 +346,7 @@ export function lowerChildStreamMethodCall( const evT = lowerer.typeOf(call.arguments.nodes[0]!); const event = evT.isStringLiteralType() ? evT.value : null; if (event !== "data" && event !== "end") { + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `stream.${name}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, call.arguments.nodes[0]!, @@ -342,6 +354,7 @@ export function lowerChildStreamMethodCall( ); } if (!ts.isExpressionStatement(call.parent)) { + requestGeneralStreamSurface(lowerer, access.expression); lowerer.unsupported( "SC1090", call, @@ -376,23 +389,32 @@ export function lowerChildStreamMethodCall( if ( param !== undefined && param.kind !== "string" && + param.kind !== "dyn" && !(param.kind === "bytes" && param.elem === "u8") && !unionOk(param) ) { lowerer.unsupported( "SC1090", call.arguments.nodes[1]!, - `data listeners whose parameter is not 'Buffer', 'string', or a Buffer-armed union (got '${lowerer.fmt(param)}')`, + `data listeners whose parameter is not 'Buffer', 'string', 'unknown', or a Buffer-armed union (got '${lowerer.fmt(param)}')`, ); } + // An unknown/any chunk is a Buffer, or a string once setEncoding ran. + // The registration takes whichever the enclosing code establishes; a + // later setEncoding that contradicts it throws the runtime's + // listener-type TypeError instead of delivering the other kind. + const strings = + param?.kind === "string" || + (param?.kind === "dyn" && childStreamEncodedAt(lowerer, access.expression, call)); return { kind: "libCall", - fn: param?.kind === "string" ? "stream.onDataStr" : "stream.onData", + fn: strings ? "stream.onDataStr" : "stream.onData", args: [receiver, cb, once], type: VOID, loc, }; } + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `ReadableStream.${name}`, call, @@ -418,6 +440,7 @@ export function lowerChildWriterMethodCall( if (name === "write") { if (call.arguments.nodes.length !== 1 || call.arguments.nodes.some(ts.isSpreadElement)) { + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `child stdin write with ${call.arguments.nodes.length} arguments`, call, @@ -461,6 +484,7 @@ export function lowerChildWriterMethodCall( const eventType = lowerer.typeOf(call.arguments.nodes[0]!); const event = eventType.isStringLiteralType() ? eventType.value : null; if (event !== "drain" && event !== "finish" && event !== "error") { + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `child stdin ${name}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, call.arguments.nodes[0]!, @@ -507,6 +531,7 @@ export function lowerChildWriterMethodCall( return { kind: "libCall", fn, args: [receiver, cb, once], type: VOID, loc }; } + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `Writable.${name}`, call, @@ -514,3 +539,255 @@ export function lowerChildWriterMethodCall( lowerer.checker.getSymbolAtLocation(access.name), ); } + +/** A receiver spelled as a plain access path (`child.stdout`, `out`): its + * root symbol and member names, or null for other forms. A `const` alias + * of an access path (`const out = child.stdout`) resolves to that path, + * and so does a method call declared to return `this` + * (`child.stdout.setEncoding("utf8")`), so every spelling of one stream + * gets the same key. */ +function accessPathOf( + lowerer: Lowerer, + expr: ts.Expression, + depth = 0, +): { root: ts.Symbol; path: string } | null { + if (depth > 16) return null; + if (ts.isParenthesizedExpression(expr) || ts.isNonNullExpression(expr)) { + return accessPathOf(lowerer, expr.expression, depth + 1); + } + if (ts.isIdentifier(expr)) { + const root = lowerer.checker.getSymbolAtLocation(expr); + if (!root) return null; + const init = constInitializerOf(root); + const aliased = init === null ? null : accessPathOf(lowerer, init, depth + 1); + return aliased ?? { root, path: "" }; + } + if (ts.isPropertyAccessExpression(expr) && !expr.questionDotToken) { + const base = accessPathOf(lowerer, expr.expression, depth + 1); + return base === null ? null : { root: base.root, path: `${base.path}.${expr.name.text}` }; + } + if (returnsReceiver(lowerer, expr)) { + return accessPathOf( + lowerer, + (expr.expression as ts.PropertyAccessExpression).expression, + depth + 1, + ); + } + return null; +} + +/** A method call (`recv.m(...)`, not optional) whose declaration returns + * `this`, so its value is the receiver itself. */ +function returnsReceiver(lowerer: Lowerer, expr: ts.Expression): expr is ts.CallExpression { + if ( + !ts.isCallExpression(expr) || + expr.questionDotToken || + !ts.isPropertyAccessExpression(expr.expression) || + expr.expression.questionDotToken + ) + return false; + const declaration = lowerer.checker.getResolvedSignature(expr)?.declaration; + return declaration?.type?.kind === ts.SyntaxKind.ThisType; +} + +/** A call of a child_process factory (spawn, fork, exec, execFile), each + * of which returns a new ChildProcess. */ +function createsChildProcess(lowerer: Lowerer, call: ts.CallExpression): boolean { + const declaration = lowerer.checker.getResolvedSignature(call)?.declaration; + if ( + declaration === undefined || + !ts.isFunctionDeclaration(declaration) || + declaration.name === undefined || + !["spawn", "fork", "exec", "execFile"].includes(declaration.name.text) + ) + return false; + for (let node: ts.Node | undefined = declaration.parent; node; node = node.parent) { + if (ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name)) { + return node.name.text === "child_process" || node.name.text === "node:child_process"; + } + } + return false; +} + +/** The statement that always evaluates `call` when it runs: the call is + * the statement's expression, a variable's initializer, or the receiver of + * a method chain that is one of those. Null for calls under a condition, + * an operator, an argument list or any other construct. */ +function unconditionalStatementOf(call: ts.CallExpression): ts.Statement | null { + let node: ts.Node = call; + for (;;) { + const parent: ts.Node | undefined = node.parent; + if (parent === undefined) return null; + if ( + ts.isParenthesizedExpression(parent) || + ts.isNonNullExpression(parent) || + (ts.isPropertyAccessExpression(parent) && + parent.expression === node && + !parent.questionDotToken) || + (ts.isCallExpression(parent) && parent.expression === node && !parent.questionDotToken) + ) { + node = parent; + continue; + } + if (ts.isExpressionStatement(parent)) return parent; + if (ts.isVariableDeclaration(parent) && parent.initializer === node) { + const list = parent.parent; + const statement = list?.parent; + return list !== undefined && + ts.isVariableDeclarationList(list) && + statement !== undefined && + ts.isVariableStatement(statement) + ? statement + : null; + } + return null; + } +} + +/** The initializer of a symbol declared once as a `const` variable, else null. */ +function constInitializerOf(symbol: ts.Symbol): ts.Expression | null { + const decls = symbol.declarations; + if (decls.length !== 1) return null; + const decl = decls[0]!; + if ( + !ts.isVariableDeclaration(decl) || + !ts.isIdentifier(decl.name) || + decl.initializer === undefined || + (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0 + ) + return null; + return decl.initializer; +} + +/** Whether two resolved access paths name different objects: the same root + * with different members, or two `const` roots each initialized by `new` + * or a child_process factory (such as two `spawn()` results). Any other + * call may return an object another binding already holds. */ +function distinctPaths( + lowerer: Lowerer, + a: { root: ts.Symbol; path: string }, + b: { root: ts.Symbol; path: string }, +): boolean { + if (a.root === b.root) return a.path !== b.path; + const fresh = (root: ts.Symbol): boolean => { + let init = constInitializerOf(root); + while (init !== null && ts.isParenthesizedExpression(init)) init = init.expression; + if (init === null) return false; + return ( + ts.isNewExpression(init) || (ts.isCallExpression(init) && createsChildProcess(lowerer, init)) + ); + }; + return fresh(a.root) && fresh(b.root); +} + +/** Whether an unknown-typed 'data' listener registered by `call` receives + * strings: a `setEncoding` statement on the same receiver path precedes + * the registration in its own block or an enclosing block of the same + * function. With no setEncoding on that path in the function, chunks are + * Buffers. Any other placement leaves the encoding state unclear, which + * is reported. */ +function childStreamEncodedAt( + lowerer: Lowerer, + receiver: ts.Expression, + call: ts.CallExpression, +): boolean { + const key = accessPathOf(lowerer, receiver); + const statement: ts.Node = call.parent!; + let scope: ts.Node | undefined = statement; + while (scope && !ts.isFunctionLike(scope) && !ts.isSourceFile(scope)) scope = scope.parent; + const unclear = (): never => + lowerer.unsupported( + "SC1090", + call.arguments.nodes[1]!, + "untyped child-stream 'data' listeners whose setEncoding state is unclear at their registration sites (declare the chunk as 'Buffer' or 'string')", + ); + if (key === null || scope === undefined) return unclear(); + const preceding = new Set(); + for (let node: ts.Node = statement; node !== scope;) { + const parent: ts.Node | undefined = node.parent; + if (parent === undefined) break; + if (ts.isBlock(parent) || ts.isSourceFile(parent)) { + for (const sibling of parent.statements.nodes) { + if (sibling === node) break; + preceding.add(sibling); + } + } + node = parent; + } + const receiverType = lowerer.checker.getNonNullableType(lowerer.typeOf(receiver)); + let before = false; + let elsewhere = false; + const visit = (node: ts.Node): void => { + if (node !== scope && ts.isFunctionLike(node)) return; + if ( + ts.isCallExpression(node) && + ts.isPropertyAccessExpression(node.expression) && + node.expression.name.text === "setEncoding" + ) { + const target = node.expression.expression; + const path = accessPathOf(lowerer, target); + if (path !== null && path.root === key.root && path.path === key.path) { + const statement = unconditionalStatementOf(node); + if (statement !== null && preceding.has(statement)) before = true; + else elsewhere = true; + } else if ( + (path === null || !distinctPaths(lowerer, path, key)) && + lowerer.checker.isTypeAssignableTo(receiverType, lowerer.typeOf(target)) + ) { + // Another spelling that can hold this stream (a parameter, a `let` + // copy, a call result): its setEncoding may be this stream's. + elsewhere = true; + } + } + ts.forEachChild(node, visit); + }; + visit(scope); + if (elsewhere) return unclear(); + return before; +} + +/** An inline 'exit'/'close' listener may declare `(code: number, signal: + * string)`: TypeScript accepts it through ChildProcess's catch-all `on` + * overload, while Node passes `number | null` and `Signals | null`. Those + * parameters bind as checked-dynamic values (the socket 'data' listener + * precedent), so the body observes the null Node passes; a typed use of a + * null value throws the checked conversion's TypeError. Returns the + * narrowed parameter symbols, empty when the declared types already + * admit null. */ +function narrowedExitListenerParams(lowerer: Lowerer, listener: ts.Expression): ts.Symbol[] { + if (!ts.isArrowFunction(listener) && !ts.isFunctionExpression(listener)) return []; + if (isJsSourceFile(listener.getSourceFile())) return []; + const symbols: ts.Symbol[] = []; + const wanted: readonly string[] = ["f64", "string"]; + listener.parameters.nodes.slice(0, 2).forEach((param, i) => { + if (!ts.isIdentifier(param.name) || param.dotDotDotToken || param.initializer) return; + if (param.questionToken) return; + const symbol = lowerer.checker.getSymbolAtLocation(param.name); + if (!symbol || lowerer.runtimeOptionalBindingTypes.has(symbol)) return; + if (lowerer.paramShape(param).type.kind !== wanted[i]) return; + symbols.push(symbol); + }); + return symbols; +} + +/** Lowers an inline listener with the given parameters bound as + * checked-dynamic values typed `unknown` for the body. */ +function lowerWithCheckedParams( + lowerer: Lowerer, + listener: ts.Expression, + symbols: readonly ts.Symbol[], +): IrExpr { + const previousImplicit = lowerer.implicitParamTypes; + const implicit = new Map(previousImplicit ?? []); + for (const symbol of symbols) { + implicit.set(symbol, lowerer.checker.getUnknownType()); + lowerer.runtimeOptionalBindingTypes.set(symbol, DYN); + } + lowerer.implicitParamTypes = implicit; + try { + return lowerer.lowerExpr(listener); + } finally { + for (const symbol of symbols) lowerer.runtimeOptionalBindingTypes.delete(symbol); + lowerer.implicitParamTypes = previousImplicit; + } +} diff --git a/packages/compiler/src/frontend/lowering/builtins/errors.ts b/packages/compiler/src/frontend/lowering/builtins/errors.ts index a8b4dbcd6..439c9fca3 100644 --- a/packages/compiler/src/frontend/lowering/builtins/errors.ts +++ b/packages/compiler/src/frontend/lowering/builtins/errors.ts @@ -52,6 +52,20 @@ export function refuseExecExceptionCode(lowerer: Lowerer, node: ts.Node): never * declaration is not stdlib). Reads only: writes keep their fence (no * compiled program constructs an errno error). Null for non-error * receivers and non-stdlib members, so the chain keeps trying. */ +/** Error members with slots of their own: never read through the dynamic + * node, even when an intersection restates them. */ +const ERROR_SLOT_MEMBERS = new Set([ + "code", + "cause", + "stack", + "message", + "name", + "errno", + "syscall", + "path", + "dest", +]); + export function lowerErrorCodeProperty( lowerer: Lowerer, expr: ts.PropertyAccessExpression, @@ -135,6 +149,33 @@ export function lowerErrorCodeProperty( declared, ); } + // A member an `Error & { ... }` intersection adds beyond Error's own and + // the system-error metadata (`Object.assign(new Error(m), { status })`): + // an own property of the error's checked-dynamic node, read at the + // declared type (the intersection mapping admits only checkable types). + if ( + recvT.className === "%Error" && + !ERROR_SLOT_MEMBERS.has(expr.name.text) && + !expr.questionDotToken && + !lowerer.isStdlibMember(expr) && + lowerer.typeOf(expr.expression).isIntersectionType() + ) { + const declared = lowerer.mapTypeOf(lowerer.typeOf(expr)); + if (declared && declared.kind !== "void") { + const receiver = lowerer.lowerExpr(expr.expression); + const loc = locOf(expr); + return lowerer.coerceToExpected( + { + kind: "dynKeyGet", + value: lowerer.coerceToExpected(receiver, DYN), + key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, + type: DYN, + loc, + }, + declared, + ); + } + } // A program class under the receiver's class can carry its own `code` // (a declared field or a property added through an untyped reference), // which Node reads instead of the errno code: read through the error's diff --git a/packages/compiler/src/frontend/lowering/builtins/performance.ts b/packages/compiler/src/frontend/lowering/builtins/performance.ts index 2a9962b0f..7aac3b80c 100644 --- a/packages/compiler/src/frontend/lowering/builtins/performance.ts +++ b/packages/compiler/src/frontend/lowering/builtins/performance.ts @@ -18,6 +18,7 @@ import { } from "../../../ir/ir.js"; import { PERF_ENTRY_FIELDS, PERF_ENTRY_MARKER, perfEntryJsonShape } from "../../type-mapper.js"; import { builtinImportOf } from "./module-bindings.js"; +import { lowerOptionalArgument } from "../optional-arguments.js"; import { checkedIterableSpread } from "../checked-iterable-spread.js"; /** True for any spelling of node:perf_hooks' `performance` object — the @@ -134,6 +135,12 @@ export function lowerPerfHooksCall( loc, }; } + if ( + access.name.text === "eventLoopUtilization" && + isPerfHooksPerformanceExpr(lowerer, access.expression) + ) { + return lowerEventLoopUtilization(lowerer, expr); + } const timeline = PERF_TIMELINE_CALLS.get(access.name.text); if (timeline && isPerfHooksPerformanceExpr(lowerer, access.expression)) { return lowerPerfTimelineCall(lowerer, expr, access.name.text, timeline, loc); @@ -142,7 +149,7 @@ export function lowerPerfHooksCall( lowerer.noLowering( `perf_hooks performance.${access.name.text}`, expr, - "performance.now() (and its .bind(performance) function value), mark, measure, the getEntries family, clearMarks and clearMeasures are the lowered surface", + "performance.now() (and its .bind(performance) function value), mark, measure, the getEntries family, clearMarks, clearMeasures and eventLoopUtilization are the lowered surface", ); } return null; @@ -513,3 +520,305 @@ export function fencePerfEntryKeyWalk( `${what} over performance entries (Node keeps their fields as prototype getters, so own-key walks see none; read the fields or call toJSON())`, ); } + +/* ── event-loop metrics: eventLoopUtilization and monitorEventLoopDelay ── */ + +/** The stdlib IntervalHistogram (monitorEventLoopDelay's result), by the + * receiver's checker type. Its value is the runtime histogram handle. */ +function isIntervalHistogram(lowerer: Lowerer, node: ts.Expression): boolean { + const symbol = lowerer.typeOf(node).getSymbol(); + return symbol?.name === "IntervalHistogram" && lowerer.isStdlibSymbol(symbol); +} + +/** IntervalHistogram's numeric members, as perf.eldStat selectors. */ +const HISTOGRAM_STATS: ReadonlyMap = new Map([ + ["min", 0], + ["max", 1], + ["mean", 2], + ["stddev", 3], + ["count", 4], + ["exceeds", 5], +]); + +/** `h.min`, `h.max`, … on an IntervalHistogram: the runtime's current + * statistic (Node's hdr_histogram values; nanoseconds). Null for every + * other read. */ +export function lowerHistogramProperty( + lowerer: Lowerer, + expr: ts.PropertyAccessExpression, +): IrExpr | null { + const which = HISTOGRAM_STATS.get(expr.name.text); + if ( + which === undefined || + expr.questionDotToken || + !isIntervalHistogram(lowerer, expr.expression) + ) + return null; + const loc = locOf(expr); + return { + kind: "libCall", + fn: "perf.eldStat", + args: [lowerer.lowerExprExpecting(expr.expression, F64), numLit(which, loc)], + type: F64, + loc, + }; +} + +/** enable(), disable(), reset() and percentile(p) on an IntervalHistogram. + * Other members (the BigInt twins, the percentiles Map) fence by name. */ +export function lowerHistogramMethodCall( + lowerer: Lowerer, + expr: ts.CallExpression, + access: ts.PropertyAccessExpression, +): IrExpr | null { + if (access.questionDotToken || !isIntervalHistogram(lowerer, access.expression)) return null; + const loc = locOf(expr); + const name = access.name.text; + const handle = (): IrExpr => lowerer.lowerExprExpecting(access.expression, F64); + const args = expr.arguments.nodes; + if ((name === "enable" || name === "disable" || name === "reset") && args.length === 0) { + const fn = + name === "enable" + ? "perf.eldEnable" + : name === "disable" + ? "perf.eldDisable" + : "perf.eldReset"; + return { kind: "libCall", fn, args: [handle()], type: name === "reset" ? VOID : BOOL, loc }; + } + if (name === "percentile" && args.length === 1 && !ts.isSpreadElement(args[0]!)) { + // Node validates first: NaN, p <= 0 and p > 100 throw ERR_OUT_OF_RANGE. + const h = lowerer.declareHiddenLocal("%histogram", F64); + const p = lowerer.declareHiddenLocal("%percentile", F64); + const pRef = (): IrExpr => varRef(p.id, F64, loc); + const cmp = (op: "!==" | "<=" | ">", left: IrExpr, right: IrExpr): IrExpr => ({ + kind: "bin", + op, + left, + right, + type: BOOL, + loc, + }); + const or = (left: IrExpr, right: IrExpr): IrExpr => ({ + kind: "logical", + op: "||", + left, + right, + type: BOOL, + loc, + }); + const outOfRange = or( + or(cmp("!==", pRef(), pRef()), cmp("<=", pRef(), numLit(0, loc))), + cmp(">", pRef(), numLit(100, loc)), + ); + const message: IrExpr = { + kind: "strConcat", + left: { + kind: "strLit", + value: 'The value of "percentile" is out of range. It must be > 0 && <= 100. Received ', + type: STRING, + loc, + }, + right: { kind: "toString", operand: pRef(), type: STRING, loc }, + type: STRING, + loc, + }; + const thrown: IrExpr = { + kind: "libCall", + fn: "error.nodeThrow", + args: [ + numLit(2, loc), + { kind: "strLit", value: "ERR_OUT_OF_RANGE", type: STRING, loc }, + message, + ], + type: F64, + loc, + }; + return { + kind: "seqExpr", + stmts: [ + { kind: "varDecl", localId: h.id, init: handle(), loc }, + { kind: "varDecl", localId: p.id, init: lowerer.lowerExprExpecting(args[0]!, F64), loc }, + ], + result: { + kind: "ternary", + cond: outOfRange, + then: thrown, + else_: { + kind: "libCall", + fn: "perf.eldPercentile", + args: [varRef(h.id, F64, loc), pRef()], + type: F64, + loc, + }, + type: F64, + loc, + }, + type: F64, + loc, + }; + } + lowerer.noLowering( + `IntervalHistogram.${name}`, + expr, + "enable(), disable(), reset(), percentile(p) and the min, max, mean, stddev, count and exceeds readings are the lowered surface", + ); +} + +/** `monitorEventLoopDelay(options?)` from node:perf_hooks, in any import + * spelling (`lowerBuiltinCall`): a new sampling histogram handle. The + * options are an inline object literal; the runtime validates the + * resolution as Node does (an integer of at least 1). */ +export function lowerMonitorEventLoopDelayCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { + const loc = locOf(expr); + const args = expr.arguments.nodes; + let resolution: IrExpr = numLit(10, loc); + if (args.length > 1 || args.some(ts.isSpreadElement)) { + lowerer.noLowering( + "this monitorEventLoopDelay call form", + expr, + "pass at most one options object", + ); + } + if (args.length === 1) { + const options = args[0]!; + if (!ts.isObjectLiteralExpression(options)) { + lowerer.noLowering( + "monitorEventLoopDelay with a non-literal options object", + options, + "spell the options inline: monitorEventLoopDelay({ resolution: 20 })", + ); + } + for (const property of options.properties.nodes) { + const shorthand = ts.isShorthandPropertyAssignment(property); + if ( + (!shorthand && !ts.isPropertyAssignment(property)) || + !ts.isIdentifier(property.name) || + property.name.text !== "resolution" + ) { + lowerer.noLowering( + "monitorEventLoopDelay options other than resolution", + property, + "resolution is the one option", + ); + } + // An undefined resolution takes the default, as Node's destructuring. + resolution = lowerOptionalArgument( + lowerer, + shorthand ? property.name : property.initializer, + F64, + numLit(10, loc), + ); + } + } + return { kind: "libCall", fn: "perf.eldNew", args: [resolution], type: F64, loc }; +} + +/** performance.eventLoopUtilization(u1?, u2?) — Node's + * lib/internal/perf/event_loop_utilization.js over the runtime's loop + * start and idle time, one lifted helper per arity. */ +function lowerEventLoopUtilization(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { + const loc = locOf(expr); + const args = expr.arguments.nodes; + const resultT = lowerer.mapTypeOf(lowerer.typeOf(expr)); + if (resultT?.kind !== "record" || args.length > 2 || args.some(ts.isSpreadElement)) { + lowerer.noLowering("this performance.eventLoopUtilization call form", expr); + } + const helper = eluHelperOf(lowerer, args.length, resultT); + return { + kind: "call", + callee: helper, + args: args.map((arg) => lowerer.lowerExprExpecting(arg, resultT)), + type: resultT, + loc, + }; +} + +function eluHelperOf(lowerer: Lowerer, arity: number, recT: IrType & { kind: "record" }): string { + const name = `%perf.elu.${arity}`; + if (lowerer.liftedFns.some((f) => f.name === name)) return name; + const loc: SrcLoc = { file: "", start: 0, end: 0 }; + const f64Local = (id: string) => ({ id, name: id, type: F64, mutable: false }); + const params = Array.from({ length: arity }, (_, i) => ({ + localId: `u${i + 1}.0`, + name: `u${i + 1}`, + type: recT as IrType, + })); + const locals = [ + ...params.map((p) => ({ id: p.localId, name: p.name, type: recT as IrType, mutable: false })), + f64Local("ls.0"), + f64Local("idle.0"), + f64Local("active.0"), + ]; + const ref = (id: string): IrExpr => varRef(id, F64, loc); + const field = (param: string, f: string): IrExpr => ({ + kind: "recordGet", + obj: varRef(param, recT, loc), + shapeId: recT.shapeId, + field: f, + type: F64, + loc, + }); + const bin = (op: "+" | "-" | "/" | "<=", left: IrExpr, right: IrExpr): IrExpr => ({ + kind: "bin", + op, + left, + right, + type: op === "<=" ? BOOL : F64, + loc, + }); + const record = (idle: IrExpr, active: IrExpr, utilization: IrExpr): IrExpr => ({ + kind: "recordLit", + fields: [ + { name: "idle", value: idle }, + { name: "active", value: active }, + { name: "utilization", value: utilization }, + ], + type: recT, + loc, + }); + const result = (idle: IrExpr, active: IrExpr): IrStmt => ({ + kind: "return", + value: record(idle, active, bin("/", active, bin("+", idle, active))), + loc, + }); + const decl = (id: string, init: IrExpr): IrStmt => ({ kind: "varDecl", localId: id, init, loc }); + const body: IrStmt[] = [ + decl("ls.0", { kind: "libCall", fn: "perf.loopStart", args: [], type: F64, loc }), + { + kind: "if", + cond: bin("<=", ref("ls.0"), numLit(0, loc)), + then: [ + { kind: "return", value: record(numLit(0, loc), numLit(0, loc), numLit(0, loc)), loc }, + ], + else_: null, + loc, + }, + ]; + if (arity === 2) { + body.push( + decl("idle.0", bin("-", field("u1.0", "idle"), field("u2.0", "idle"))), + decl("active.0", bin("-", field("u1.0", "active"), field("u2.0", "active"))), + result(ref("idle.0"), ref("active.0")), + ); + } else { + body.push( + decl("idle.0", { kind: "libCall", fn: "perf.idleTime", args: [], type: F64, loc }), + decl( + "active.0", + bin( + "-", + bin("-", { kind: "libCall", fn: "perf.now", args: [], type: F64, loc }, ref("ls.0")), + ref("idle.0"), + ), + ), + arity === 0 + ? result(ref("idle.0"), ref("active.0")) + : result( + bin("-", ref("idle.0"), field("u1.0", "idle")), + bin("-", ref("active.0"), field("u1.0", "active")), + ), + ); + } + lowerer.liftedFns.push({ name, params, returnType: recT, locals, body, loc }); + return name; +} diff --git a/packages/compiler/src/frontend/lowering/builtins/process.ts b/packages/compiler/src/frontend/lowering/builtins/process.ts index eb3703a53..9ac1fc059 100644 --- a/packages/compiler/src/frontend/lowering/builtins/process.ts +++ b/packages/compiler/src/frontend/lowering/builtins/process.ts @@ -3,6 +3,7 @@ import { envSnapshotHelper, lowerProcessLoadEnvFile } from "./environment.js"; import { dynUndefinedExpr, boolLit, numLit, strLit, varRef } from "../../../ir/build.js"; import { timerStyleCallback } from "../lower-timers.js"; import * as ts from "../../ts7/adapter.js"; +import { requestGeneralStreamSurface } from "../general-streams.js"; import { type Lowerer, own } from "../lowerer.js"; import { isJsSourceFile, locOf } from "../../program.js"; import { isSafeToDiscard } from "../expressions/evaluation-safety.js"; @@ -225,6 +226,7 @@ export function lowerProcStreamMethodCall( const receiver = lowerer.lowerExpr(access.expression); const data = lowerer.lowerExpr(call.arguments.nodes[0]!); if (data.type.kind !== "string") { + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `write of '${lowerer.fmt(data.type)}' data on a stream value`, call.arguments.nodes[0]!, @@ -233,6 +235,7 @@ export function lowerProcStreamMethodCall( } return { kind: "libCall", fn: "procStream.write", args: [receiver, data], type: BOOL, loc }; } + requestGeneralStreamSurface(lowerer, access.expression); lowerer.noLowering( `WritableStream.${name}`, call, diff --git a/packages/compiler/src/frontend/lowering/builtins/properties.ts b/packages/compiler/src/frontend/lowering/builtins/properties.ts index b0caa0456..e60a14c0c 100644 --- a/packages/compiler/src/frontend/lowering/builtins/properties.ts +++ b/packages/compiler/src/frontend/lowering/builtins/properties.ts @@ -1,5 +1,5 @@ import { isBuiltinClassInstance } from "./receiver-types.js"; -import { strLit } from "../../../ir/build.js"; +import { numLit, strLit } from "../../../ir/build.js"; import * as ts from "../../ts7/adapter.js"; import { type Lowerer } from "../lowerer.js"; import { locOf } from "../../program.js"; @@ -192,6 +192,25 @@ export function lowerBuiltinExtraProperty( // +1-or-NULL runtime pair. if (kind === "child" && (name === "stdin" || name === "stdout" || name === "stderr")) { const receiver = lowerer.lowerExpr(expr.expression); + // Under the general stream representation (general-streams.ts) the + // declared stream type maps to a runtime stream class: the read + // answers the child's bridged stream (one per stdio slot, so repeated + // reads keep identity), fed by the same pipe. + const general = lowerer.generalNodeStreams ? generalChildStdioType(lowerer, expr, name) : null; + if (general) { + const type: IrType = { + kind: "union", + unionId: lowerer.unions.intern([general, { kind: "nullT" }]), + }; + const read: IrExpr = { + kind: "libCall", + fn: "child.stdioStream", + args: [receiver, numLit(name === "stdin" ? 0 : name === "stdout" ? 1 : 2, loc)], + type, + loc, + }; + return lowerer.maybeNarrow(read, expr); + } const streamType = name === "stdin" ? CHILDWRITER_T : CHILDSTREAM_T; const type: IrType = { kind: "union", @@ -259,3 +278,21 @@ export function lowerBuiltinExtraProperty( } return null; } + +/** The runtime stream class a child stdio read produces under the general + * stream representation, or null when the declared type keeps the stdio + * handle (the fallback declarations' ChildStdin). */ +function generalChildStdioType( + lowerer: Lowerer, + expr: ts.PropertyAccessExpression, + name: "stdin" | "stdout" | "stderr", +): IrType | null { + const className = name === "stdin" ? "%Writable" : "%Readable"; + const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr)); + if (!mapped) return null; + const arms = + mapped.kind === "union" ? (lowerer.unions.get(mapped.unionId)?.arms ?? []) : [mapped]; + return arms.some((arm) => arm.kind === "object" && arm.className === className) + ? { kind: "object", className } + : null; +} diff --git a/packages/compiler/src/frontend/lowering/builtins/webassembly.ts b/packages/compiler/src/frontend/lowering/builtins/webassembly.ts index dc61853f8..56347e437 100644 --- a/packages/compiler/src/frontend/lowering/builtins/webassembly.ts +++ b/packages/compiler/src/frontend/lowering/builtins/webassembly.ts @@ -2,17 +2,44 @@ import * as ts from "../../ts7/adapter.js"; import { type Lowerer, PoisonError } from "../lowerer.js"; import { locOf } from "../../program.js"; import { webAssemblyDiag } from "../../../diagnostics/diagnostic.js"; -import { STRING, type IrExpr } from "../../../ir/ir.js"; +import { BOOL, DYN, F64, STRING, type IrExpr } from "../../../ir/ir.js"; +import { dynUndefinedExpr } from "../../../ir/build.js"; +import { lowerDynObjectLiteral } from "../expressions/object-literals.js"; import { stdlibGlobalNameOf } from "../surfaces.js"; +import { isWebAssemblyType } from "../../type-mapper.js"; /* The WebAssembly API. scriptc.d.ts declares its types (lib.dom's - * namespace) so that packages whose declarations mention them typecheck, - * and the type mapper gives those types the checked-dynamic representation. - * No module compiles to native code yet, so every reached use of the API - * value fences at its expression with webAssemblyDiag: a build error in - * TypeScript sources, a located runtime fence in JavaScript ones. typeof - * needs no value and folds to Node's answer. */ + * namespace) and the type mapper gives them the checked-dynamic + * representation. Modules whose bytes the build sees are translated to + * native code (wasm/translate.ts) and found at run time by the SHA-256 of + * their bytes (scr_wasm.c): + * - WebAssembly.compile, instantiate and validate calls, new + * WebAssembly.Module, Instance, Memory, Table and Global, and + * WebAssembly.Module.imports, exports and customSections lower to + * wasm.* libCalls; members of the values they produce (exports, memory + * buffers, globals, tables) dispatch through the native handles; + * - the classes called without `new` throw Node's TypeError + * (wasm.withoutNew); + * - `v instanceof WebAssembly.` lowers to wasm.is; + * - the error classes construct with or without `new` (wasm.errorNew). + * Every other reached use of the API value (the classes as values, the + * streaming functions, Tag and Exception) still fences at its expression + * with webAssemblyDiag: a build error in TypeScript sources, a located + * runtime fence in JavaScript ones. typeof needs no value and folds to Node's + * answer. A lowering marks the lowerer, so the build translates the + * modules it discovers (lowerToIr). */ +/** The classes `wasm.is` answers, by kind. */ +const WASM_CLASSES = [ + "Module", + "Instance", + "Memory", + "Table", + "Global", + "CompileError", + "LinkError", + "RuntimeError", +] as const; /** Strips the spellings that leave a value unchanged: parentheses, type * assertions, `satisfies` and non-null assertions. */ function bare(expr: ts.Expression): ts.Expression { @@ -130,3 +157,248 @@ export function lowerWebAssemblyTypeof(lowerer: Lowerer, operand: ts.Expression) } return null; } + +/** The member `WebAssembly.` names (any spelling of the namespace), + * or null. */ +function webAssemblyMember(lowerer: Lowerer, expr: ts.Expression): string | null { + const surface = webAssemblySurface(lowerer, expr); + if (surface === null || !surface.startsWith("WebAssembly.")) return null; + const member = surface.slice("WebAssembly.".length); + return member.includes(".") ? null : member; +} + +function lowerArg(lowerer: Lowerer, arg: ts.Expression): IrExpr { + return ts.isObjectLiteralExpression(arg) + ? lowerDynObjectLiteral(lowerer, arg) + : lowerer.lowerExprExpecting(arg, DYN); +} + +/** An argument whose evaluation has no effect: a literal, a plain + * identifier, or an empty object or array literal. */ +function isInert(arg: ts.Expression): boolean { + const node = bare(arg); + if (ts.isObjectLiteralExpression(node)) return node.properties.nodes.length === 0; + if (ts.isArrayLiteralExpression(node)) return node.elements.nodes.length === 0; + return ( + ts.isIdentifier(node) || + ts.isNumericLiteral(node) || + node.kind === ts.SyntaxKind.BigIntLiteral || + ts.isStringLiteral(node) || + ts.isNoSubstitutionTemplateLiteral(node) || + node.kind === ts.SyntaxKind.NullKeyword || + node.kind === ts.SyntaxKind.TrueKeyword || + node.kind === ts.SyntaxKind.FalseKeyword + ); +} + +/** The arguments, padded with undefined to `count`. Extra arguments are + * ignored, as the API ignores them, when evaluating them has no effect; + * null for spreads or other extra arguments (they stay refused). */ +function lowerArgs( + lowerer: Lowerer, + args: readonly ts.Expression[], + count: number, + loc: IrExpr["loc"], +): IrExpr[] | null { + if (args.some(ts.isSpreadElement)) return null; + if (args.length > count) { + if (!args.slice(count).every(isInert)) return null; + args = args.slice(0, count); + } + const out = args.map((arg) => lowerArg(lowerer, arg)); + while (out.length < count) out.push(dynUndefinedExpr(loc)); + return out; +} + +function errorNew(member: string, args: IrExpr[], loc: IrExpr["loc"]): IrExpr { + const kind = (WASM_CLASSES as readonly string[]).indexOf(member); + return { + kind: "libCall", + fn: "wasm.errorNew", + args: [{ kind: "numLit", value: kind, type: F64, loc }, args[0]!, args[1]!], + type: DYN, + loc, + }; +} + +/** The classes that require `new`, in wasm.withoutNew's numbering. */ +const NEW_ONLY = ["Module", "Instance", "Memory", "Table", "Global"]; + +/** `WebAssembly.Module.imports(module)`, `exports(module)` and + * `customSections(module, name)`. Their results are arrays of descriptors + * or ArrayBuffers built as checked-dynamic values, then taken into the + * call's own type. Null for anything else. */ +function lowerModuleStatic(lowerer: Lowerer, call: ts.CallExpression): IrExpr | null { + const surface = webAssemblySurface(lowerer, call.expression); + const name = surface?.startsWith("WebAssembly.Module.") + ? surface.slice("WebAssembly.Module.".length) + : null; + if (name !== "imports" && name !== "exports" && name !== "customSections") return null; + const loc = locOf(call); + const args = lowerArgs(lowerer, call.arguments.nodes, name === "customSections" ? 2 : 1, loc); + if (args === null) return null; + lowerer.usesWebAssembly = true; + if (name === "customSections") lowerer.usesWasmCustomSections = true; + const fn = + name === "imports" + ? "wasm.moduleImports" + : name === "exports" + ? "wasm.moduleExports" + : "wasm.moduleCustomSections"; + const result: IrExpr = { kind: "libCall", fn, args, type: DYN, loc }; + return lowerer.coerceInto(call, result, lowerer.irTypeOf(call)); +} + +/** `WebAssembly.compile(bytes)`, `WebAssembly.instantiate(source, + * imports?)`, `WebAssembly.validate(bytes)`, the error classes called + * without `new`, the other classes called without `new` (a TypeError), and + * Module's static functions. Null for anything else. */ +export function lowerWebAssemblyCall(lowerer: Lowerer, call: ts.CallExpression): IrExpr | null { + if (call.questionDotToken) return null; + const member = webAssemblyMember(lowerer, call.expression); + if (member === null) return lowerModuleStatic(lowerer, call); + const loc = locOf(call); + const newOnly = NEW_ONLY.indexOf(member); + if (newOnly >= 0) { + // The arguments evaluate, then the call throws. + const args = lowerArgs(lowerer, call.arguments.nodes, 2, loc); + if (args === null) return null; + lowerer.usesWebAssembly = true; + return { + kind: "libCall", + fn: "wasm.withoutNew", + args: [{ kind: "numLit", value: newOnly, type: F64, loc }, args[0]!, args[1]!], + type: DYN, + loc, + }; + } + const isError = member === "CompileError" || member === "LinkError" || member === "RuntimeError"; + if (member !== "compile" && member !== "instantiate" && member !== "validate" && !isError) + return null; + const used = member === "instantiate" || isError ? 2 : 1; + const args = lowerArgs(lowerer, call.arguments.nodes, used, loc); + if (args === null) return null; + lowerer.usesWebAssembly = true; + let result: IrExpr; + if (isError) result = errorNew(member, args, loc); + else if (member === "validate") + result = { kind: "libCall", fn: "wasm.validate", args: [args[0]!], type: BOOL, loc }; + else if (member === "compile") + result = { + kind: "libCall", + fn: "wasm.compile", + args: [args[0]!], + type: { kind: "promise", inner: DYN }, + loc, + }; + else + result = { + kind: "libCall", + fn: "wasm.instantiate", + args: [args[0]!, args[1]!], + type: { kind: "promise", inner: DYN }, + loc, + }; + return result; +} + +/** `new WebAssembly.Module(bytes)`, `new WebAssembly.Instance(module, + * imports?)`, `new WebAssembly.Memory(descriptor)`, `new + * WebAssembly.Table(descriptor, value?)`, `new + * WebAssembly.Global(descriptor, value?)` and the error classes. Null for + * anything else. */ +export function lowerWebAssemblyNew(lowerer: Lowerer, expr: ts.NewExpression): IrExpr | null { + const member = webAssemblyMember(lowerer, expr.expression); + if (member === null) return null; + const isError = member === "CompileError" || member === "LinkError" || member === "RuntimeError"; + if (!NEW_ONLY.includes(member) && !isError) return null; + const loc = locOf(expr); + const used = member === "Module" || member === "Memory" ? 1 : 2; + const args = lowerArgs(lowerer, expr.arguments?.nodes ?? [], used, loc); + if (args === null) return null; + lowerer.usesWebAssembly = true; + let result: IrExpr; + if (isError) result = errorNew(member, args, loc); + else if (member === "Module") + result = { kind: "libCall", fn: "wasm.moduleNew", args: [args[0]!], type: DYN, loc }; + else if (member === "Memory") + result = { kind: "libCall", fn: "wasm.memoryNew", args: [args[0]!], type: DYN, loc }; + else if (member === "Table") + result = { kind: "libCall", fn: "wasm.tableNew", args: [args[0]!, args[1]!], type: DYN, loc }; + else if (member === "Global") + result = { kind: "libCall", fn: "wasm.globalNew", args: [args[0]!, args[1]!], type: DYN, loc }; + else + result = { + kind: "libCall", + fn: "wasm.instanceNew", + args: [args[0]!, args[1]!], + type: DYN, + loc, + }; + return result; +} + +/** `v instanceof WebAssembly.`. Null for anything else. */ +export function lowerWebAssemblyInstanceof( + lowerer: Lowerer, + expr: ts.BinaryExpression, +): IrExpr | null { + const member = webAssemblyMember(lowerer, expr.right); + if (member === null) return null; + const kind = (WASM_CLASSES as readonly string[]).indexOf(member); + if (kind < 0) return null; + const loc = locOf(expr); + lowerer.usesWebAssembly = true; + const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN); + return { + kind: "libCall", + fn: "wasm.is", + args: [value, { kind: "numLit", value: kind, type: F64, loc }], + type: BOOL, + loc, + }; +} + +/** WebAssembly API values: `WebAssembly.compile`, `instantiate` and + * `validate` read as functions, the namespace itself (`WebAssembly`, + * `globalThis.WebAssembly`), and the global object cast to a type with a + * `WebAssembly` member (pi codemode's spelling). Null for anything else, + * which refuseWebAssemblyUse then fences. */ +export function lowerWebAssemblyValue(lowerer: Lowerer, expr: ts.Expression): IrExpr | null { + const surface = webAssemblySurface(lowerer, expr); + if (surface === null) return null; + const loc = locOf(expr); + const node = bare(expr); + const fn = (name: string, args: IrExpr[]): IrExpr => { + lowerer.usesWebAssembly = true; + return { kind: "libCall", fn: name as "wasm.namespace", args, type: DYN, loc }; + }; + if (surface === "globalThis.WebAssembly") { + // The cast spelling names the global object, not its member. + const cast = + (ts.isAsExpression(expr) || ts.isTypeAssertion(expr)) && + isGlobalThis(lowerer, expr.expression); + return cast ? fn("wasm.globalView", []) : fn("wasm.namespace", []); + } + if (surface === "WebAssembly") return fn("wasm.namespace", []); + const index = ["WebAssembly.compile", "WebAssembly.instantiate", "WebAssembly.validate"].indexOf( + surface, + ); + if (index < 0 || !ts.isPropertyAccessExpression(node)) return null; + return fn("wasm.function", [{ kind: "numLit", value: index, type: F64, loc }]); +} + +/** `global.valueOf()` on a receiver typed as a WebAssembly value: a + * Global answers its value (the generic dyn.valueOf answers the object + * itself for native handles other than Date). Null for other receivers. */ +export function lowerWebAssemblyValueOf( + lowerer: Lowerer, + receiver: ts.Expression, + recv: IrExpr, + loc: IrExpr["loc"], +): IrExpr | null { + const ctx = { checker: lowerer.checker, isStdlibFile: lowerer.isStdlibFile }; + if (!isWebAssemblyType(lowerer.typeOf(receiver), ctx)) return null; + lowerer.usesWebAssembly = true; + return { kind: "libCall", fn: "wasm.valueOf", args: [recv], type: DYN, loc }; +} diff --git a/packages/compiler/src/frontend/lowering/call-arguments.ts b/packages/compiler/src/frontend/lowering/call-arguments.ts index f5600b033..db7691a1c 100644 --- a/packages/compiler/src/frontend/lowering/call-arguments.ts +++ b/packages/compiler/src/frontend/lowering/call-arguments.ts @@ -1,3 +1,4 @@ +import { forwardedTupleType, pureForwardedValues, stripTypeWrappers } from "./typed-arguments.js"; import { dynUndefinedExpr } from "../../ir/build.js"; import { InternalCompilerError } from "../../errors.js"; import * as ts from "../ts7/adapter.js"; @@ -26,13 +27,13 @@ import { checkedIterableSpread } from "./checked-iterable-spread.js"; import { type ParamShape } from "./call-signatures.js"; import { arrayValueRead, arrayValueType } from "./array-values.js"; import { buildArrayConversion } from "./coercions/builders.js"; -import { typeKey } from "../type-mapper.js"; +import { restTupleElementTypes, typeKey } from "../type-mapper.js"; function fixedTupleSpreadInfo( lowerer: Lowerer, node: ts.Expression, ): { type: IrType & { kind: "record" }; fields: { name: string; type: IrType }[] } | null { - const type = lowerer.mapTypeOf(lowerer.typeOf(node)); + const type = forwardedTupleType(lowerer, node) ?? lowerer.mapTypeOf(lowerer.typeOf(node)); if (type?.kind !== "record") return null; const shape = lowerer.shapes.get(type.shapeId); if (!shape?.tuple || shape.fields.length === 0) return null; @@ -42,6 +43,18 @@ function fixedTupleSpreadInfo( }; } +/** `...t` over a provably EMPTY tuple bound to a plain name (`[]`, a rest + * tuple whose type parameter or `Parameters` resolved to no positions): + * it contributes no arguments, and reading the name has no effect. */ +function emptyTupleSpread(lowerer: Lowerer, node: ts.Expression): boolean { + let operand = node; + while (ts.isParenthesizedExpression(operand)) operand = operand.expression; + if (!ts.isIdentifier(operand)) return false; + const forwarded = forwardedTupleType(lowerer, operand); + if (forwarded) return forwarded.kind === "array"; + return restTupleElementTypes(lowerer.typeOf(operand), lowerer.typeCtx)?.length === 0; +} + export function completeArgs( lowerer: Lowerer, argNodes: readonly ts.Expression[], @@ -59,7 +72,9 @@ export function completeArgs( // graph. Ordinary calls and fixed tuples never need that analysis. const runtimeSpreads = argNodes.filter( (arg): arg is ts.SpreadElement => - ts.isSpreadElement(arg) && !fixedTupleSpreadInfo(lowerer, arg.expression), + ts.isSpreadElement(arg) && + !fixedTupleSpreadInfo(lowerer, arg.expression) && + !emptyTupleSpread(lowerer, arg.expression), ); // Spread operands lowered while choosing the completion, each exactly once. const loweredSpreads = new Map(); @@ -190,6 +205,12 @@ export function completeArgs( sources.push(arg); continue; } + if (emptyTupleSpread(lowerer, arg.expression)) continue; + const pure = pureForwardedValues(lowerer, arg.expression); + if (pure) { + for (const value of pure) sources.push({ ir: value }); + continue; + } const tuple = fixedTupleSpreadInfo(lowerer, arg.expression); if (!tuple) { sources.push(arg); @@ -204,7 +225,13 @@ export function completeArgs( // values as separately written arguments while the saved tuple stays // alive through the call. const spreadLoc = locOf(arg); - const value = lowerer.coerceInto(arg.expression, lowerer.lowerExpr(arg.expression), tuple.type); + // A forwarded tuple seen through type assertions (`...(arguments as + // unknown as Parameters)`) spreads the tuple itself. + const operand = + forwardedTupleType(lowerer, arg.expression) !== null + ? stripTypeWrappers(arg.expression) + : arg.expression; + const value = lowerer.coerceInto(arg.expression, lowerer.lowerExpr(operand), tuple.type); const saved = lowerer.declareHiddenLocal("%callSpread", tuple.type); const savedRef = (): IrExpr => ({ kind: "varRef", @@ -506,9 +533,38 @@ export function completeFuncValueArgs( shapes.push({ type: rest, mode: "rest" }); return completeArgs(lowerer, call.arguments.nodes, shapes, loc, call); } + // A fixed-tuple spread (`fn(...args)` over a tuple-typed rest binding) + // has a compile-time arity: completion flattens it into the positional + // slots exactly like a direct call's. + if ( + funcType.rest !== true && + call.arguments.nodes.some(ts.isSpreadElement) && + call.arguments.nodes.every( + (arg) => + !ts.isSpreadElement(arg) || + fixedTupleSpreadInfo(lowerer, arg.expression) !== null || + emptyTupleSpread(lowerer, arg.expression), + ) + ) { + const shapes: ParamShape[] = funcType.params.map((type) => ({ + type, + mode: omittedArgFor(lowerer, type, loc) ? "omittable" : "required", + })); + return completeArgs(lowerer, call.arguments.nodes, shapes, loc, call); + } const args = call.arguments.nodes.map((arg, index) => lowerer.lowerExprExpecting(arg, funcType.params[index]), ); + // Effect-free surplus arguments of a fixed-arity value (`(r: void) => + // void` drops its void slot) evaluate to nothing observable: drop them, + // as the callee ignores them. + while ( + funcType.rest !== true && + args.length > funcType.params.length && + isSafeToDiscard(args[args.length - 1]!) + ) { + args.pop(); + } for (let i = args.length; i < funcType.params.length; i++) { const absent = omittedArgFor(lowerer, funcType.params[i]!, loc); if (!absent) { diff --git a/packages/compiler/src/frontend/lowering/call-signatures.ts b/packages/compiler/src/frontend/lowering/call-signatures.ts index 7570fff88..954122a16 100644 --- a/packages/compiler/src/frontend/lowering/call-signatures.ts +++ b/packages/compiler/src/frontend/lowering/call-signatures.ts @@ -1,3 +1,8 @@ +import { + typedArgumentsCandidate, + typedArgumentsShapes, + typedArgumentsTarget, +} from "./typed-arguments.js"; import { InternalCompilerError } from "../../errors.js"; import * as ts from "../ts7/adapter.js"; import { bodyReadsArguments } from "../arguments-usage.js"; @@ -15,6 +20,7 @@ import { import { isJsSourceFile, isNodeEsmFile } from "../program.js"; import { genResultRecord, + restTupleParamTypes, isAnyArrayType, isUnitOnlyTsType, jsOpenObjectType, @@ -56,6 +62,10 @@ export interface ParamShape { bodyType?: IrType; callDefault?: IrExpr; entryNarrow?: IrType; + /** One flattened position of a fixed-tuple rest parameter + * (restTupleShapes): the declaration's last parameter owns every shape + * from its index on, and the body binds the tuple (declareParams). */ + restTuple?: true; } export interface FnSig { @@ -373,6 +383,28 @@ export function isThisParameter(param: ts.ParameterDeclaration): boolean { return ts.isIdentifier(param.name) && param.name.text === "this"; } +/** A TypeScript rest parameter bound to a name whose type is a fixed tuple + * (`...args: [A, B]`, `...args: A` with A bound to a tuple, `...args: + * Parameters` with F bound): one required shape per position. Call + * sites and function values see the equivalent fixed signature; the body + * rebuilds the tuple (declareParams) unless it only forwards it. Null for + * every other parameter. */ +export function restTupleShapes( + lowerer: Lowerer, + param: ts.ParameterDeclaration, + tsType?: ts.Type, +): ParamShape[] | null { + if ( + param.dotDotDotToken === undefined || + !ts.isIdentifier(param.name) || + isJsSourceFile(param.getSourceFile()) + ) { + return null; + } + const elems = restTupleParamTypes(tsType ?? lowerer.typeOf(param.name), lowerer.typeCtx); + return elems ? elems.map((type) => ({ type, mode: "required", restTuple: true })) : null; +} + /** ParamShapes for a whole parameter list. */ export function paramShapes( lowerer: Lowerer, @@ -380,21 +412,47 @@ export function paramShapes( signature?: ts.Signature, blameOf?: (param: ts.ParameterDeclaration, index: number) => ts.Node, ): ParamShape[] { - if (!signature) - return params.filter((p) => !isThisParameter(p)).map((param) => lowerer.paramShape(param)); + const out: ParamShape[] = []; + if (!signature) { + for (const param of params) { + if (isThisParameter(param)) continue; + const flattened = restTupleShapes(lowerer, param); + if (flattened) out.push(...flattened); + else out.push(lowerer.paramShape(param)); + } + return out; + } const symbols = signature.getParameters(); - return params.map((declParam, i) => { + const shapeAt = (declParam: ts.ParameterDeclaration, i: number): ParamShape => { const stage = lowerer.stageSourceType(declParam.name); if (stage) return { type: stage, mode: "required" as const }; const symbol = symbols[i]; const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name); + // A call-site instantiation whose concrete argument type does not map + // is that argument's blocker: name it there, with its concrete type, + // rather than as the declaration's unbound type parameter. + if ( + blameOf !== undefined && + !isJsSourceFile(declParam.getSourceFile()) && + (tsType.flags & ts.TypeFlags.Any) === 0 && + declParam.type !== undefined && + mentionsTypeParameter(lowerer, lowerer.checker.getTypeFromTypeNode(declParam.type)) && + lowerer.mapTypeOf(tsType) === null + ) { + lowerer.badType(blameOf(declParam, i), tsType); + } let mapped = jsOpenObjectType( declParam, lowerer.runtimeOptionalBindingType( declParam.name, - lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name), + lowerer.mapTypeOf(tsType) ?? + // A TypeScript instantiation at `any` (a type argument inferred + // from an untyped value) takes the checked-dynamic slot. + ((tsType.flags & ts.TypeFlags.Any) !== 0 && !isJsSourceFile(declParam.getSourceFile()) + ? DYN + : lowerer.irTypeOf(declParam.name)), ), lowerer.shapes, lowerer.unions, @@ -428,7 +486,32 @@ export function paramShapes( ); } return { type: mapped, mode: declParam.questionToken ? "omittable" : "required" }; + }; + params.forEach((declParam, i) => { + const symbol = symbols[i]; + const flattened = restTupleShapes( + lowerer, + declParam, + symbol ? lowerer.checker.getTypeOfSymbol(symbol) : undefined, + ); + if (flattened) out.push(...flattened); + else out.push(shapeAt(declParam, i)); }); + return out; +} + +/** A declared type that is (or is a union over) a bare type parameter + * or an instantiation of a generic alias/interface over type arguments. */ +function mentionsTypeParameter(lowerer: Lowerer, t: ts.Type): boolean { + if (t.flags & ts.TypeFlags.TypeParameter) return true; + const mentions = (part: ts.Type): boolean => mentionsTypeParameter(lowerer, part); + if (t.isUnionType()) return ts.constituentTypes(t).some(mentions); + if (t.getAliasTypeArguments().some(mentions)) return true; + return ( + (t.flags & ts.TypeFlags.Object) !== 0 && + ((t as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference) !== 0 && + lowerer.checker.getTypeArguments(t as ts.TypeReference).some(mentions) + ); } /** A default expression may itself yield undefined. Keep that arm in the @@ -828,6 +911,16 @@ export function lambdaSignature( | ts.SetAccessorDeclaration, ): { shapes: ParamShape[]; funcType: IrType & { kind: "func" } } { if (!node.body) lowerer.unsupported("SC1090", node, "function overload signatures"); + // A parameterless function expression forwarding its `arguments`, + // asserted to a fixed signature: that signature is its ABI. + if (typedArgumentsCandidate(node) && !node.typeParameters?.nodes.length) { + const target = typedArgumentsTarget(lowerer, node); + if (target) { + const shapes = typedArgumentsShapes(target); + lowerer.typedArgumentsLambdas.add(node); + return { shapes, funcType: funcTypeFromParamShapes(shapes, target.ret) }; + } + } // A JS replacement of a native stream's write method receives the // actual call tuple, including overloads and omitted arguments. Node's // contextual overload signature cannot define this closure's ABI. diff --git a/packages/compiler/src/frontend/lowering/class-protocol-dispatch.ts b/packages/compiler/src/frontend/lowering/class-protocol-dispatch.ts index 0c9a24f24..298ff45dc 100644 --- a/packages/compiler/src/frontend/lowering/class-protocol-dispatch.ts +++ b/packages/compiler/src/frontend/lowering/class-protocol-dispatch.ts @@ -188,7 +188,8 @@ function protocolSignature( call: ts.CallExpression, access: ts.PropertyAccessExpression, ): ProtocolSignature | null { - const recvTs = lowerer.typeOf(access.expression); + // A guarded optional step's receiver still carries its nullish arms. + const recvTs = lowerer.checker.getNonNullableType(lowerer.typeOf(access.expression)); const property = lowerer.checker.getPropertyOfType(recvTs, access.name.text); if (!property) return null; const declarations = property.declarations; @@ -240,10 +241,11 @@ export function lowerProtocolMethodCall( access: ts.PropertyAccessExpression, recv: IrExpr, ): IrExpr | null { + // An optional chain that already guarded this step (`s?.m(x)`, the chain + // re-dispatching with the narrowed receiver) calls like a plain one. if ( recv.type.kind !== "dyn" || - call.questionDotToken || - access.questionDotToken || + lowerer.chainBlocked(call, access) || call.arguments.nodes.some(ts.isSpreadElement) ) return null; diff --git a/packages/compiler/src/frontend/lowering/class-prototypes.ts b/packages/compiler/src/frontend/lowering/class-prototypes.ts index d337dc802..6c6c7811d 100644 --- a/packages/compiler/src/frontend/lowering/class-prototypes.ts +++ b/packages/compiler/src/frontend/lowering/class-prototypes.ts @@ -1,4 +1,5 @@ import { dynUndefinedExpr, varRef } from "../../ir/build.js"; +import { builtinClassKind, builtinClassValue } from "./builtins/builtin-class-dyn.js"; import * as ts from "../ts7/adapter.js"; import { BOOL, @@ -450,6 +451,19 @@ export function lowerClassPrototypeData( exactClassOfReceiver(lowerer, expr.expression) ?? (stored?.kind === "classval" ? lowerer.classes.get(stored.className) : undefined); if (!info) return null; + // EventEmitter.prototype and the stream prototypes: the untyped + // constructor's prototype object (builtin-class-dyn.ts). + const builtinKind = builtinClassKind(info.def.name); + if (builtinKind !== null) { + const loc = locOf(expr); + return { + kind: "dynKeyGet", + value: builtinClassValue(builtinKind, loc), + key: { kind: "strLit", value: "prototype", type: STRING, loc }, + type: DYN, + loc, + }; + } const parent = expr.parent; const descriptorKey = ts.isCallExpression(parent) && diff --git a/packages/compiler/src/frontend/lowering/coercions/function-adapters.ts b/packages/compiler/src/frontend/lowering/coercions/function-adapters.ts index 445014b88..3d8817ab1 100644 --- a/packages/compiler/src/frontend/lowering/coercions/function-adapters.ts +++ b/packages/compiler/src/frontend/lowering/coercions/function-adapters.ts @@ -4,6 +4,7 @@ import { InternalCompilerError } from "../../../errors.js"; import type { IrExpr, IrParam, IrStmt, IrType, SrcLoc } from "../../../ir/ir.js"; import { canAdaptDynFuncTo, + canDynCheckTo, DYN, F64, isUnitType, @@ -341,6 +342,19 @@ export function funcCoerceAdapter( voidRet = toT.ret.kind === "dyn" ? "dyn" : "strand"; } } + // An untyped result (a generic wrapper's `any` handed back `as F`) takes + // the checked-dynamic extraction to the slot's result: a record checks + // its shape, a Promise keeps its identity and checks its payload when it + // settles. + const checkedRet = + strandRet && + fromT.ret.kind === "dyn" && + canDynCheckTo( + toT.ret, + (id) => lowerer.shapes.get(id), + (id) => lowerer.unions.get(id), + ); + if (checkedRet) strandRet = false; const key = `fnadapt:${typeKey(fromT)}:${typeKey(toT)}`; const existing = lowerer.coercions.retags.get(key); if (existing) return existing; @@ -440,6 +454,10 @@ export function funcCoerceAdapter( `a '${lowerer.fmt(fromT)}' function invoked through a '${lowerer.fmt(toT)}' slot (the result cannot convert to '${lowerer.fmt(toT.ret)}' — the checker's loose function compatibility admitted the assignment, but the call has no exact lowering)`, ), ]; + } else if (checkedRet) { + body = [ + { kind: "return", value: { kind: "dynCheck", value: call, type: toT.ret, loc }, loc }, + ]; } else { const result = lowerer.coerceToExpected(call, toT.ret); if (!typeEquals(result.type, toT.ret)) diff --git a/packages/compiler/src/frontend/lowering/expressions/binary.ts b/packages/compiler/src/frontend/lowering/expressions/binary.ts index cecbde717..8ef631f60 100644 --- a/packages/compiler/src/frontend/lowering/expressions/binary.ts +++ b/packages/compiler/src/frontend/lowering/expressions/binary.ts @@ -1,5 +1,6 @@ /* Binary operators: arithmetic, comparisons and equality, logical and nullish pairs, and string conversion for concatenation. */ import * as ts from "../../ts7/adapter.js"; +import { cleanFuncAdaptable } from "../coercions/function-adapters.js"; import { type Lowerer, jsFuncNameOf } from "../lowerer.js"; import { BIGINT_T, @@ -481,6 +482,22 @@ export function lowerNullishPair( ); } } + // An optional callback defaulted to a function of another signature + // (`o.tags ?? (() => ({}))`, fewer parameters or a narrower result): the + // result is the callback's own function type, and the default adapts into + // it (JavaScript ignores surplus arguments). The checker's merged union + // signature would lose the callback's result shape. + if (present?.kind === "func" && present.rest !== true) { + const raw = lowerer.lowerExpr(expr.right); + if ( + raw.type.kind === "func" && + (typeEquals(raw.type, present) || cleanFuncAdaptable(lowerer, raw.type, present)) + ) { + const right = lowerer.coerceInto(expr.right, raw, present); + lowerer.nullishFuncResults.add(expr); + return { kind: "nullish", left, right, type: present, loc }; + } + } lowerer.unsupported( "SC1090", expr, diff --git a/packages/compiler/src/frontend/lowering/expressions/element-access.ts b/packages/compiler/src/frontend/lowering/expressions/element-access.ts index 144742257..f39b7c428 100644 --- a/packages/compiler/src/frontend/lowering/expressions/element-access.ts +++ b/packages/compiler/src/frontend/lowering/expressions/element-access.ts @@ -63,6 +63,8 @@ import { npmStaticPackageOfPath } from "../../npm-static.js"; import { isSafeToRepeat } from "./evaluation-safety.js"; import { lowerClassPrototypeComputedAssignment } from "../class-prototypes.js"; import { isClassCallback } from "../class-callbacks.js"; +import { isKeyedFieldAccess } from "./keyed-field-targets.js"; +import { lowerFieldCompoundValue } from "./updates.js"; /** `a[i]` reads. Only f64 indices into array receivers are modeled; JS * string-key element access (`a["length"]`) and string indexing (`s[0]` @@ -1417,6 +1419,11 @@ export function lowerElementCompoundParts( const target = expr.left as ts.ElementAccessExpression; fenceNodeModuleMutation(lowerer, target, "assignment"); const loc = locOf(expr); + // A record through a computed key (`totals[side] += n` with a literal + // union key, `counts[name] += 1` on an index-signature record): the + // member compound's receiver, key, old value, rhs, write sequence. + if (isKeyedFieldAccess(lowerer, target)) + return { expr: lowerFieldCompoundValue(lowerer, target, op, expr.right, loc), stmts: null }; const checked = lowerer.lowerExpr(target.expression); if (checked?.type.kind === "dyn" && isJsSourceFile(expr.getSourceFile())) { const stmts: IrStmt[] = []; diff --git a/packages/compiler/src/frontend/lowering/expressions/identifiers.ts b/packages/compiler/src/frontend/lowering/expressions/identifiers.ts index 70ed1b2ba..c2e5ddcbb 100644 --- a/packages/compiler/src/frontend/lowering/expressions/identifiers.ts +++ b/packages/compiler/src/frontend/lowering/expressions/identifiers.ts @@ -1,6 +1,8 @@ /* Identifier references in expression position: lowerExprInner's identifier branch and its helpers. */ import { cjsMemberAliasValueOf } from "../cjs-exports-object.js"; +import { builtinClassValue, builtinMemberClassKind } from "../builtins/builtin-class-dyn.js"; import * as ts from "../../ts7/adapter.js"; +import { InternalCompilerError } from "../../../errors.js"; import * as posix from "node:path/posix"; import { type Lowerer, PoisonError } from "../lowerer.js"; import { @@ -21,6 +23,7 @@ import { import { lowerNodeModuleIdentifier } from "../lower-node-module.js"; import { lowerCjsExportsObjectValue } from "../cjs-exports-object.js"; import { captureContextArguments } from "../function-context.js"; +import { argumentsOwner, typedArgumentsCandidate } from "../typed-arguments.js"; import { isCjsExportTableLiteral, isCjsJsFile, @@ -96,7 +99,18 @@ export function lowerIdentifierExpr(lowerer: Lowerer, expr: ts.Identifier, loc: // type and lowerLambda declared the local. if (expr.text === "arguments") { const binding = captureContextArguments(lowerer.fnStack); - if (binding) return { kind: "varRef", localId: binding.id, type: DYN, loc }; + if (binding && lowerer.ctx.pureTuples.has(binding.id)) { + throw new InternalCompilerError("lowerer bug: forwarded-only 'arguments' read as a value"); + } + if (binding) return { kind: "varRef", localId: binding.id, type: binding.type, loc }; + const owner = argumentsOwner(expr); + if (owner && typedArgumentsCandidate(owner)) { + lowerer.unsupported( + "SC1090", + expr, + "'arguments' in a function expression whose value is not asserted to one fixed-arity signature (assert it, as in `function () { … } as F`, and the function lowers against that signature)", + ); + } } // A compiler-projected adapter as a VALUE: the adapter has no // runtime function object (its calls rewrite directly) — call it @@ -539,6 +553,10 @@ export function lowerIdentifierExpr(lowerer: Lowerer, expr: ts.Identifier, loc: // the same identity-token story as stdlib globals above (the // harness adds worker_threads.Worker to its identity Set). if (isJsSourceFile(expr.getSourceFile())) { + // EventEmitter and the stream classes are the runtime's untyped + // constructors, so constructor functions can inherit from them. + const classKind = builtinMemberClassKind(bi.module, bi.member); + if (classKind !== null) return builtinClassValue(classKind, loc); // A function member is a function value that fences when called. if (builtinModuleFnOf(lowerer, bi.module, bi.member)) return builtinFunctionFenceValue(lowerer, bi, expr, loc); diff --git a/packages/compiler/src/frontend/lowering/expressions/keyed-field-targets.ts b/packages/compiler/src/frontend/lowering/expressions/keyed-field-targets.ts new file mode 100644 index 000000000..7a4f9c557 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/expressions/keyed-field-targets.ts @@ -0,0 +1,271 @@ +/* Read-modify-write targets for computed record keys: `r[k] op= v`, `r[k]++` and `r[k] ??= v`. */ +import * as ts from "../../ts7/adapter.js"; +import { + BOOL, + F64, + STRING, + typeEquals, + type IrExpr, + type IrStmt, + type SrcLoc, +} from "../../../ir/ir.js"; +import { isJsSourceFile } from "../../program.js"; +import { constituentTypes } from "../../ts7/checker.js"; +import type { FieldTarget } from "../lower-exprs.js"; +import type { Lowerer } from "../lowerer.js"; + +export type KeyedFieldTarget = FieldTarget & { container: "recordKeyed" }; + +/** The property names a computed key's type allows: one or more string + * literals (a literal union such as `"sent" | "received"`, enum string + * members, or a type parameter bound to one inside a generic instance). + * Null for any other key type. */ +export function literalFieldKeys(lowerer: Lowerer, keyNode: ts.Expression): string[] | null { + let t: ts.Type = lowerer.typeOf(keyNode); + if (t.flags & ts.TypeFlags.TypeParameter) { + const bound = lowerer.typeParamTsResolver(t); + if (!bound) return null; + t = bound; + } + const parts = t.flags & ts.TypeFlags.Union ? constituentTypes(t) : [t]; + const keys: string[] = []; + for (const part of parts) { + if (!part.isStringLiteralType()) return null; + if (!keys.includes(part.value)) keys.push(part.value); + } + return keys.length > 0 ? keys : null; +} + +/** Does `r[k]` read and write through declared record storage by key? A + * checker-only test (nothing lowers), so a caller can route before it + * evaluates the receiver: TypeScript sources only, a record whose declared + * fields include every name the key's literal type allows, or a pure + * index-signature record with a string key. */ +export function isKeyedFieldAccess(lowerer: Lowerer, access: ts.ElementAccessExpression): boolean { + if ( + access.questionDotToken || + isJsSourceFile(access.getSourceFile()) || + lowerer.isProcessEnv(access.expression) + ) + return false; + const keys = literalFieldKeys(lowerer, access.argumentExpression); + if (!keys && !(lowerer.typeOf(access.argumentExpression).flags & ts.TypeFlags.StringLike)) + return false; + const receiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression)); + if (receiver?.kind !== "record") return false; + const shape = lowerer.shapes.get(receiver.shapeId); + if (!shape || shape.tuple) return false; + if (shape.fields.length === 0) return shape.indexValue !== undefined; + return keys !== null && keys.every((k) => shape.fields.some((f) => f.name === k)); +} + +/** The target of a read-modify-write through `r[k]`, or null when + * isKeyedFieldAccess declines. A literal-union key dispatches over the + * declared fields it names, which must share one type; a string key on a + * pure index-signature record reads and writes its entries. The receiver + * and key may arrive already lowered (and saved) by the caller; otherwise + * both lower here, unsaved. A caller that evaluates the target more than + * once saves `obj` and then `key`, the JavaScript evaluation order. With + * `numeric`, a missing index-signature entry reads as NaN (every numeric + * update applies ToNumber to it) instead of a value armed with undefined. */ +export function keyedFieldTarget( + lowerer: Lowerer, + access: ts.ElementAccessExpression, + numeric: boolean, + lowered?: { obj: IrExpr; key: IrExpr }, +): KeyedFieldTarget | null { + if (!isKeyedFieldAccess(lowerer, access)) return null; + const keyNode = access.argumentExpression; + const keys = literalFieldKeys(lowerer, keyNode); + const obj = lowered?.obj ?? lowerer.lowerExpr(access.expression); + if (obj.type.kind !== "record") { + lowerer.unsupported( + "SC1090", + access.expression, + `updating a computed key of a '${lowerer.fmt(obj.type)}' value (narrow the receiver to its record type first)`, + ); + } + const shapeId = obj.type.shapeId; + const shape = lowerer.shapes.get(shapeId)!; + // A single literal spelled at the site (or an identifier whose type is + // that one literal) names the field statically: identifier evaluation + // is pure, so skipping it matches JavaScript. + const indexed = shape.fields.length === 0; + const staticKey = + !indexed && keys?.length === 1 && (ts.isStringLiteralLike(keyNode) || ts.isIdentifier(keyNode)); + const key = staticKey ? null : (lowered?.key ?? lowerer.lowerExpr(keyNode)); + if (key && key.type.kind !== "string") { + lowerer.unsupported( + "SC1090", + keyNode, + `updating a record through a '${lowerer.fmt(key.type)}' key (convert the key to a string first)`, + ); + } + if (keys && !indexed) { + const fields = keys.map((k) => shape.fields.find((f) => f.name === k)); + const first = fields[0]; + if (!first || fields.some((f) => !f || !typeEquals(f.type, first.type))) { + lowerer.unsupported( + "SC1090", + access, + `updating '${lowerer.fmt(obj.type)}' through a key whose fields are not all stored with one type (${keys.map((k) => `'${k}'`).join(", ")}; switch over the key and update each field)`, + ); + } + return { + container: "recordKeyed", + obj, + shapeId, + field: keys[0]!, + keys, + key, + fieldType: first.type, + }; + } + if (!indexed || !shape.indexValue) { + lowerer.unsupported( + "SC1090", + access, + `updating '${lowerer.fmt(obj.type)}' through a runtime key (the stored record declares fields)`, + ); + } + return { + container: "recordKeyed", + obj, + shapeId, + field: "", + keys: null, + key, + fieldType: shape.indexValue, + ...(numeric && shape.indexValue.kind === "f64" ? { missNaN: true as const } : {}), + }; +} + +/** Does `key` name `field`? */ +function keyIs(key: IrExpr, field: string, loc: SrcLoc): IrExpr { + return { + kind: "strEq", + negated: false, + left: key, + right: { kind: "strLit", value: field, type: STRING, loc }, + type: BOOL, + loc, + }; +} + +/** A key outside its literal type (smuggled through a cast) names no + * declared field: a fixed-shape record cannot add the property, so the + * update throws the TypeError of a keyed write miss. */ +function keyMiss(key: IrExpr, target: KeyedFieldTarget, loc: SrcLoc): IrExpr { + const message: IrExpr = { + kind: "strConcat", + left: { + kind: "strConcat", + left: { kind: "strLit", value: "Cannot add property '", type: STRING, loc }, + right: key, + type: STRING, + loc, + }, + right: { kind: "strLit", value: "' to a fixed-shape object", type: STRING, loc }, + type: STRING, + loc, + }; + return { + kind: "libCall", + fn: "error.nodeThrow", + args: [ + { kind: "numLit", value: 1, type: F64, loc }, + { kind: "strLit", value: "", type: STRING, loc }, + message, + ], + type: target.fieldType, + loc, + }; +} + +/** The current value of a keyed target. */ +export function keyedFieldRead(lowerer: Lowerer, target: KeyedFieldTarget, loc: SrcLoc): IrExpr { + const { obj, shapeId, key, fieldType } = target; + if (!target.keys) { + const type = target.missNaN + ? fieldType + : fieldType.kind === "dyn" + ? fieldType + : lowerer.withUndefinedArmOf(fieldType); + if (!type || !key) throw new Error("keyed index-signature target without a key or read type"); + return { + kind: "recordKeyGet", + obj, + shapeId, + key, + ...(target.missNaN ? { missNaN: true as const } : {}), + type, + loc, + }; + } + const get = (field: string): IrExpr => ({ + kind: "recordGet", + obj, + shapeId, + field, + type: fieldType, + loc, + }); + if (!key) return get(target.keys[0]!); + return target.keys.reduceRight( + (otherwise, field) => ({ + kind: "ternary", + cond: keyIs(key, field, loc), + then: get(field), + else_: otherwise, + type: fieldType, + loc, + }), + keyMiss(key, target, loc), + ); +} + +/** Store `value` (already of the target's field type) through a keyed + * target. A multi-key dispatch references the value once per field, so a + * value that is not a plain local is saved first. */ +export function keyedFieldWrite( + lowerer: Lowerer, + target: KeyedFieldTarget, + value: IrExpr, + loc: SrcLoc, +): IrStmt { + const { obj, shapeId, key } = target; + if (!target.keys) { + if (!key) throw new Error("keyed index-signature target without a key"); + return { kind: "recordKeySet", obj, shapeId, key, value, loc }; + } + if (!key) return { kind: "recordSet", obj, shapeId, field: target.keys[0]!, value, loc }; + const prefix: IrStmt[] = []; + let stored = value; + if (value.kind !== "varRef") { + const local = lowerer.declareHiddenLocal("%keyedValue", value.type); + prefix.push({ kind: "varDecl", localId: local.id, init: value, loc }); + stored = { kind: "varRef", localId: local.id, type: value.type, loc }; + } + const chain = target.keys.reduceRight( + (otherwise, field) => [ + { + kind: "if", + cond: keyIs(key, field, loc), + then: [{ kind: "recordSet", obj, shapeId, field, value: stored, loc }], + else_: otherwise, + loc, + }, + ], + [{ kind: "exprStmt", expr: keyMiss(key, target, loc), loc }], + ); + return { kind: "block", body: [...prefix, ...chain], loc }; +} + +/** Save a keyed target's key after its receiver, so a multi-key dispatch + * reads and writes the field the key named when it was evaluated. */ +export function saveKeyedFieldKey( + target: FieldTarget, + save: (value: IrExpr, name: string) => IrExpr, +): void { + if (target.container === "recordKeyed" && target.key) target.key = save(target.key, "%keyedKey"); +} diff --git a/packages/compiler/src/frontend/lowering/expressions/narrowing.ts b/packages/compiler/src/frontend/lowering/expressions/narrowing.ts index b54da8180..9f98ac2db 100644 --- a/packages/compiler/src/frontend/lowering/expressions/narrowing.ts +++ b/packages/compiler/src/frontend/lowering/expressions/narrowing.ts @@ -26,6 +26,7 @@ import { jsBindingHasOpenWrites } from "../lower-stmts.js"; import { narrowClassUnion, narrowStoredClassValue, structuralNarrowing } from "../class-unions.js"; import { checkedClassAssertion, checkedClassUnionAssertion } from "../class-assertions.js"; import { isOptionalProcessStreamProperty } from "../builtins/process.js"; +import { requestGeneralStreamSurface } from "../general-streams.js"; import { literalValues } from "../../literal-values.js"; import { literalUnionArm } from "../../union-discriminants.js"; import { checkedArmExtraction } from "../coercions/unions.js"; @@ -1186,6 +1187,56 @@ function classInstanceOrAbsent(lowerer: Lowerer, type: IrType): boolean { ); } +/** `Object.fromEntries(...) as T` with T a declared record (the generic + * `transform>(t: T): T` idiom): the + * entries build a pure index-signature record, which has no layout in + * common with T's struct. Node keeps the object itself, with exactly the + * keys and the order the entries gave it. The result of fromEntries is a + * fresh object nothing else references, so the checked-dynamic bridge, + * which keeps keys and their order the same way `JSON.parse(text) as T` + * does, cannot be told apart from the original object; a value outside + * T throws the catchable TypeError of every checked cast. The entries' + * values must be scalars or checked-dynamic values, which the bridge + * passes by value or by identity; native arrays and records would be + * copied. Other sources may be aliased, where a rebuilt object would sever + * mutation, so they keep the exact-shape fence. */ +function freshEntriesRecordAssertion( + lowerer: Lowerer, + expr: ts.AsExpression | ts.TypeAssertion, + inner: IrExpr, + target: IrType | null, +): IrExpr | null { + if (inner.type.kind !== "record" || target?.kind !== "record") return null; + const source = lowerer.shapes.get(inner.type.shapeId); + const dest = lowerer.shapes.get(target.shapeId); + if (!source?.indexValue || source.tuple || source.fields.length > 0) return null; + if (!dest || dest.tuple || dest.indexValue || shapeHasAccessorSlots(dest)) return null; + // Native arrays and records in the entries would be copied on the way + // through the checked-dynamic bridge, severing their identity: only + // slots of scalars or checked-dynamic values pass. + if (extractionCopiesReference(lowerer, source.indexValue)) return null; + let operand: ts.Expression = expr.expression; + while (ts.isParenthesizedExpression(operand)) operand = operand.expression; + if ( + !ts.isCallExpression(operand) || + !ts.isPropertyAccessExpression(operand.expression) || + operand.expression.name.text !== "fromEntries" || + !lowerer.isStdlibGlobal(operand.expression.expression, "Object") + ) + return null; + if (!lowerer.dynConvertible(inner.type)) return null; + if ( + !canDynCheckTo( + target, + (id) => lowerer.shapes.get(id), + (id) => lowerer.unions.get(id), + ) + ) + return null; + const loc = locOf(expr); + return { kind: "dynCheck", value: lowerer.coerceToExpected(inner, DYN), type: target, loc }; +} + /** `e as T` and the old-style assertion `e` — one node shape (both * carry `.type` and `.expression`), one lowering. */ export function lowerAsExpression( @@ -1237,12 +1288,14 @@ export function lowerAsExpression( // the requested shape; an assertion does not bypass runtime checks. const narrowed = lowerer.mapTypeOf(lowerer.typeOf(expr.expression)); const bridged = - narrowed && - (narrowed.kind === "f64" || - narrowed.kind === "bool" || - narrowed.kind === "string" || - narrowed.kind === "object" || - narrowed.kind === "dyn"); + (narrowed && + (narrowed.kind === "f64" || + narrowed.kind === "bool" || + narrowed.kind === "string" || + narrowed.kind === "object" || + narrowed.kind === "dyn")) || + // `catch (e: any)`: the binding reads as its checked-dynamic value. + (narrowed === null && (lowerer.typeOf(expr.expression).flags & ts.TypeFlags.Any) !== 0); if (!bridged) lowerer.unsupported("SC1063", expr); } const inner = lowerer.lowerExpr(expr.expression); @@ -1323,6 +1376,8 @@ export function lowerAsExpression( ) { return lowerer.coerceInto(expr, inner, target); } + const rebuilt = freshEntriesRecordAssertion(lowerer, expr, inner, target); + if (rebuilt) return rebuilt; // `job as Job & { startedAt: number }` on a record: the asserted // record refines the stored one, so the assertion keeps the object // (a width copy would sever writes through the asserted view). @@ -1376,6 +1431,12 @@ export function lowerAsExpression( return inner; // erasure, unchanged } + // `value as never` is the escape hatch that makes an unknown value fit + // any slot (`tagSuccess(value as never)`). No value has type never, so + // checking against its placeholder layout would reject every value. + // Erase it instead: the consuming slot applies the same validated + // extraction an unknown value gets wherever the checker admits it. + if (expr.type.kind === ts.SyntaxKind.NeverKeyword) return inner; const targetTs = lowerer.checker.getTypeFromTypeNode(expr.type); const target = lowerer.mapTypeOf(targetTs) ?? dynFallbackType(lowerer, expr.type, targetTs); if (!target) lowerer.badType(expr.type, targetTs); @@ -1450,6 +1511,9 @@ export function lowerAsExpression( if (DYN_HANDLE_KINDS.has(target.kind)) { return { kind: "dynCheck", value: inner, type: target, loc: locOf(expr) }; } + // `value as NodeJS.ReadableStream`: the general stream classes take + // the checked cast (general-streams.ts). + requestGeneralStreamSurface(lowerer, expr); lowerer.unsupported( "SC1090", expr, diff --git a/packages/compiler/src/frontend/lowering/expressions/nullish-assignment.ts b/packages/compiler/src/frontend/lowering/expressions/nullish-assignment.ts index 4366b8d6b..81b3b9d69 100644 --- a/packages/compiler/src/frontend/lowering/expressions/nullish-assignment.ts +++ b/packages/compiler/src/frontend/lowering/expressions/nullish-assignment.ts @@ -18,6 +18,11 @@ import { arrayNumberRead, arrayValueRead, arrayValueStore } from "../array-value import { fenceNodeModuleMutation } from "../lower-node-module.js"; import { globalSymbolKey } from "./global-symbols.js"; import { tryLowerExpression } from "./try-lower-expression.js"; +import { + type KeyedFieldTarget, + keyedFieldTarget, + saveKeyedFieldKey, +} from "./keyed-field-targets.js"; import { eventAccessorRead, eventAccessorWrite, @@ -147,6 +152,7 @@ export function lowerShortCircuitAssignment(lowerer: Lowerer, expr: ts.BinaryExp } else { const receiver = save(lowerer.lowerExpr(target.expression), "%shortCircuitReceiver"); let key = lowerer.lowerExpr(target.argumentExpression); + let keyed: KeyedFieldTarget | null = null; if (receiver.type.kind === "dyn") { key = save( { @@ -245,6 +251,17 @@ export function lowerShortCircuitAssignment(lowerer: Lowerer, expr: ts.BinaryExp value: lowerer.coerceToExpected(value, indexValue), loc, }); + } else if ( + receiver.type.kind === "record" && + (keyed = keyedFieldTarget(lowerer, target, false, { obj: receiver, key })) + ) { + // `totals[side] ??= v` through a literal-union key: the read and + // the write dispatch over the declared fields the key can name. + const field = keyed; + saveKeyedFieldKey(field, save); + storage = field.fieldType; + read = lowerer.fieldGetExpr(field, locOf(target), target); + write = (value) => lowerer.fieldSetStmt(field, value, loc, target); } else { lowerer.unsupported( "SC1090", diff --git a/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts b/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts index 930e1a7cb..995514a4d 100644 --- a/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts +++ b/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts @@ -1,3 +1,5 @@ +import { isSafeToDiscard } from "./evaluation-safety.js"; +import { completeFuncValueArgs } from "../call-arguments.js"; import { dynUndefinedExpr } from "../../../ir/build.js"; import * as ts from "../../ts7/adapter.js"; import { DYN, STRING, UNDEFINED_T, VOID, isUnitType, typeEquals } from "../../../ir/ir.js"; @@ -429,7 +431,22 @@ export function lowerOptionalChain( if (dotNode === expr && ts.isCallExpression(expr)) { if (narrowed.kind !== "func") lowerer.badType(recvNode, lowerer.typeOf(recvNode)); const params = narrowed.params; + // Forwarded fixed tuples (`f?.(...args)`) complete into the slots. + if (expr.arguments.nodes.some(ts.isSpreadElement)) { + const completed = completeFuncValueArgs(lowerer, expr, narrowed, loc); + const call: IrExpr = { + kind: "callValue", + callee: recvRef, + args: completed, + type: narrowed.ret, + loc, + }; + return lowerer.finishOptionalChain(expr, id, receiver, call, loc); + } const args = expr.arguments.nodes.map((a, i) => lowerer.lowerExprExpecting(a, params[i])); + // Effect-free surplus arguments (a dropped `void` slot) are ignored. + while (narrowed.rest !== true && args.length > params.length && isSafeToDiscard(args.at(-1)!)) + args.pop(); const body: IrExpr = { kind: "callValue", callee: recvRef, args, type: narrowed.ret, loc }; return lowerer.finishOptionalChain(expr, id, receiver, body, loc); } diff --git a/packages/compiler/src/frontend/lowering/expressions/property-access.ts b/packages/compiler/src/frontend/lowering/expressions/property-access.ts index e0bfee25d..65c8fbcbc 100644 --- a/packages/compiler/src/frontend/lowering/expressions/property-access.ts +++ b/packages/compiler/src/frontend/lowering/expressions/property-access.ts @@ -1,6 +1,10 @@ /* Property reads (`a.b`): lowerExprInner's property-access branch, intrinsic and union properties, field reads and targets, and match-group reads. */ import { staticallySelected } from "../static-typeof.js"; import * as ts from "../../ts7/adapter.js"; +import { lowerHistogramProperty } from "../builtins/performance.js"; +import { staticFunctionNameRead } from "../static-function-names.js"; +import { typedArgumentsArity } from "../typed-arguments.js"; +import { isThisParameter } from "../call-signatures.js"; import { localPrivateBrandClass } from "../private-brands.js"; import { type Lowerer, PoisonError, jsFuncNameOf, neverTaintedJsType, own } from "../lowerer.js"; import { @@ -156,6 +160,7 @@ import { errorPropertyRead } from "../error-methods.js"; import { isSafeToRepeat } from "./evaluation-safety.js"; import { isZlibStreamMember, lowerZlibStreamBytesWritten } from "../builtins/compression.js"; import { isFsStreamMember, lowerFsStreamProperty } from "../builtins/fs-streams.js"; +import { keyedFieldRead } from "./keyed-field-targets.js"; /** True when a property access names an ABSTRACT property declaration * (`abstract p: number` — a PropertyDeclaration, not an accessor). @@ -256,6 +261,23 @@ export function lowerPropertyAccessExpr( const navigator = lowerNavigatorMember(lowerer, expr, NODE_COMPAT_VERSION); if (navigator) return navigator; } + // `fn.name` on a function parameter of a generic instance keyed by + // its argument's static name (call-site specialization). + { + const staticName = staticFunctionNameRead(lowerer, expr); + if (staticName !== null) return { kind: "strLit", value: staticName, type: STRING, loc }; + } + // An IntervalHistogram's readings (min, max, mean, stddev, count, exceeds). + { + const reading = lowerHistogramProperty(lowerer, expr); + if (reading) return reading; + } + // `.length` of a forwarded fixed tuple (a typed `arguments`, a tuple + // rest parameter, an alias of either): the signature's arity. + if (expr.name.text === "length" && !expr.questionDotToken) { + const arity = typedArgumentsArity(lowerer, expr.expression); + if (arity !== null) return { kind: "numLit", value: arity, type: F64, loc }; + } // `require("./x").member` over a program module's export table: the // module's %init at this position, then the member read exactly like // a `const m = require("./x")` binding's (cjs-inline-require.ts). @@ -574,9 +596,12 @@ export function lowerPropertyAccessExpr( p.dotDotDotToken === undefined, ); if (fixedArity) { + // A `this` parameter is type-only: callers never pass it. return { kind: "numLit", - value: (fn as ts.FunctionLikeDeclaration).parameters.nodes.length, + value: (fn as ts.FunctionLikeDeclaration).parameters.nodes.filter( + (p) => !isThisParameter(p), + ).length, type: F64, loc, }; @@ -1121,6 +1146,23 @@ export function lowerPropertyAccessExpr( ); } } + // A stdlib-declared member (`message` of an interface extending Error) + // on a catch binding narrowed to a structural type: the binding reads + // as its checked-dynamic value, so the member does too. + if (!expr.questionDotToken && lowerer.caughtLocalOf(expr.expression)) { + const recv = lowerer.lowerExpr(expr.expression); + if (recv.kind === "caughtToDyn") { + const read: IrExpr = { + kind: "dynKeyGet", + key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) }, + value: recv, + type: DYN, + loc, + }; + const declared = lowerer.mapTypeOf(lowerer.typeOf(expr)); + return declared && declared.kind !== "void" ? lowerer.coerceToExpected(read, declared) : read; + } + } // The lib fence's PROPERTY chokepoint: a stdlib-declared member that // no lowering above claimed ([1,2].entries, Math.SQRT2, Promise.all, // re.exec as a value, ...) reports SC2020 here. @@ -3512,6 +3554,7 @@ export function fieldGetExpr( ); if (checked) target = { ...target, obj: checked }; } + if (target.container === "recordKeyed") return keyedFieldRead(lowerer, target, loc); if (target.container === "dynamic") return lowerer.coerceInto( blame, diff --git a/packages/compiler/src/frontend/lowering/expressions/relational.ts b/packages/compiler/src/frontend/lowering/expressions/relational.ts index 4aa62534e..91d1468c2 100644 --- a/packages/compiler/src/frontend/lowering/expressions/relational.ts +++ b/packages/compiler/src/frontend/lowering/expressions/relational.ts @@ -1,5 +1,6 @@ /* instanceof and in, including private-name and runtime-key in. */ import * as ts from "../../ts7/adapter.js"; +import { builtinClassInstanceOf, builtinClassKind } from "../builtins/builtin-class-dyn.js"; import { checkedPrivateIn, localPrivateBrandClass, @@ -25,7 +26,7 @@ import { typeEquals, typeKey, } from "../../../ir/ir.js"; -import { refuseWebAssemblyUse } from "../builtins/webassembly.js"; +import { lowerWebAssemblyInstanceof, refuseWebAssemblyUse } from "../builtins/webassembly.js"; import { lowerSocketInstanceOf } from "../lower-server.js"; import { builtinClassRefOf } from "../builtins/class-values.js"; import { lowerZlibInstanceOf } from "../builtins/compression.js"; @@ -62,6 +63,8 @@ import { nullProtoRecordShape, recordNullProtoTest } from "../null-prototype.js" * Folding is limited to side-effect-free operands — dropping a computed * operand would skip its effects, so those are rejected instead. */ export function lowerInstanceOf(lowerer: Lowerer, expr: ts.BinaryExpression, loc: SrcLoc): IrExpr { + const webAssembly = lowerWebAssemblyInstanceof(lowerer, expr); + if (webAssembly !== null) return webAssembly; refuseWebAssemblyUse(lowerer, expr.right); // `x instanceof net.Socket` over a union with a netSocket arm — the // h2 compat 'connect' narrowing (lower-server.ts): a union tag test. @@ -471,6 +474,22 @@ export function lowerInstanceOf(lowerer: Lowerer, expr: ts.BinaryExpression, loc const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN); return checkedClassInstanceOf(lowerer, value, constructor, loc); } + // `this instanceof Glob` in a JavaScript constructor function: the + // function's prototype against the value's prototype chain. + if ( + constructor?.type.kind === "func" && + isJsSourceFile(expr.getSourceFile()) && + lowerer.dynConvertible(constructor.type) + ) { + const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN); + return { + kind: "libCall", + fn: "dyn.functionInstanceOf", + args: [value, { kind: "dynFrom", value: constructor, type: DYN, loc }], + type: BOOL, + loc, + }; + } lowerer.unsupported( "SC1090", expr.right, @@ -579,6 +598,14 @@ export function lowerInstanceOf(lowerer: Lowerer, expr: ts.BinaryExpression, loc loc, }; } + // `u instanceof EventEmitter` (or a stream class): an untyped object + // built by a constructor function inherits the untyped constructor's + // prototype (builtin-class-dyn.ts). Compiled emitters and streams have + // no untyped form, so the prototype chain answers for every value. + const builtinKind = builtinClassKind(target.def.name); + if (left.type.kind === "dyn" && builtinKind !== null) { + return builtinClassInstanceOf(left, builtinKind, loc); + } if (left.type.kind === "dyn") { lowerer.unsupported( "SC1090", @@ -1144,6 +1171,24 @@ function lowerPrivateIn( } /** The string keys every record inherits from Object.prototype. */ +/** Keys built-in errors carry outside their class fields: Node's system + * error properties, and AggregateError's, SuppressedError's and + * AssertionError's own members. */ +const BUILTIN_ERROR_SLOT_KEYS: ReadonlySet = new Set([ + "errno", + "syscall", + "path", + "dest", + "info", + "errors", + "error", + "suppressed", + "actual", + "expected", + "operator", + "generatedMessage", +]); + const OBJECT_PROTOTYPE_KEYS: ReadonlySet = new Set([ "constructor", "__defineGetter__", @@ -1360,9 +1405,10 @@ export function lowerInExpression( // predicate's `err instanceof Error && "code" in err` shape): `code` // answers from the runtime error's code slot (stamped by fs/system/ // event/spawn errors, absent on plain constructions — exactly Node's - // own-property answer), and the always-declared members fold true. - // Everything else fences: the runtime object carries no other dynamic - // properties to ask (`stack` would be a lie — Node has one, we don't). + // own-property answer), and the always-present members (message, name, + // stack, Object.prototype's keys, members the static class declares) + // fold true. Other keys test the declaring subclasses and the error's + // own runtime properties; keys of built-in errors' extra slots fence. if (recv.type.kind === "object") { // %DOMException first: `'cause' in e` answers the options form's // own-property record (the runtime slot), and code/name/message are @@ -1384,34 +1430,77 @@ export function lowerInExpression( if (key === "cause") { return { kind: "libCall", fn: "error.hasCause", args: [recv], type: BOOL, loc }; } + // The code slot, or an own `code` with another value + // (`err.code = undefined` is present). if (key === "code") { - const codeType = lowerer.envValueType(); - if (codeType.kind !== "union") - throw new InternalCompilerError("lowerer bug: error code type is not a union"); - const undefTag = lowerer.armTag(codeType.unionId, UNDEFINED_T); - const read: IrExpr = { + return { kind: "libCall", fn: "error.hasCode", args: [recv], type: BOOL, loc }; + } + // The receiver evaluates for its effects when the answer is static. + const always = (): IrExpr => + recv.kind === "varRef" || recv.kind === "caughtNarrow" + ? { kind: "boolLit", value: true, type: BOOL, loc } + : { + kind: "seqExpr", + stmts: [{ kind: "exprStmt", expr: recv, loc }], + result: { kind: "boolLit", value: true, type: BOOL, loc }, + type: BOOL, + loc, + }; + if (key === "message" || key === "name") return always(); + // Every Error has its own `stack`, and Error.prototype's `toString` + // and `constructor` are among Object.prototype's keys. + if (key === "stack" || OBJECT_PROTOTYPE_KEYS.has(key)) return always(); + // A member the static class declares is always present. + const declares = (c: ClassInfo): boolean => + c.fields.has(key) || + lowerer.findMethodOn(c, key) !== null || + lowerer.findMethodOn(c, `get:${key}`) !== null || + lowerer.findMethodOn(c, `set:${key}`) !== null; + const staticInfo = lowerer.classes.get(recv.type.className); + if (staticInfo && declares(staticInfo)) return always(); + // Any other key: a descendant class that declares it (instanceof), or + // an own property set at runtime (a throw site's extra fields, + // Object.assign, writes through a dynamic view). Keys built-in errors + // keep outside their class fields depend on the runtime error and + // stay fenced. + if (!BUILTIN_ERROR_SLOT_KEYS.has(key)) { + const stable = recv.kind === "varRef" || recv.kind === "caughtNarrow"; + const slot = stable ? null : lowerer.declareHiddenLocal("%inRecv", recv.type); + const ref = (): IrExpr => (slot ? varRef(slot.id, recv.type, loc) : recv); + const tests: IrExpr[] = []; + const staticName = recv.type.className; + for (const c of lowerer.classes.values()) { + const name = c.def.name; + if (name === staticName || !lowerer.isSubclassOf(name, staticName) || !declares(c)) + continue; + // A declaring ancestor below the static class already covers it. + if (c.base && c.base.def.name !== staticName && declares(c.base)) continue; + tests.push({ kind: "instanceOf", value: ref(), className: name, type: BOOL, loc }); + } + tests.push({ kind: "libCall", - fn: "error.code", - args: [recv], - type: codeType, + fn: "error.hasKey", + args: [ref(), { kind: "strLit", value: key, type: STRING, loc }], + type: BOOL, loc, - }; + }); + const answer = tests.reduce((acc, test) => ({ + kind: "logical", + op: "||", + left: acc, + right: test, + type: BOOL, + loc, + })); + if (!slot) return answer; return { - kind: "unionIsTag", - unionId: codeType.unionId, - tag: undefTag, - negated: true, - value: read, + kind: "seqExpr", + stmts: [{ kind: "varDecl", localId: slot.id, init: recv, loc }], + result: answer, type: BOOL, loc, }; } - if ( - (key === "message" || key === "name") && - (recv.kind === "varRef" || recv.kind === "caughtNarrow") - ) { - return { kind: "boolLit", value: true, type: BOOL, loc }; - } lowerer.unsupported( "SC1090", expr, diff --git a/packages/compiler/src/frontend/lowering/expressions/updates.ts b/packages/compiler/src/frontend/lowering/expressions/updates.ts index 2270f6043..41d8f6332 100644 --- a/packages/compiler/src/frontend/lowering/expressions/updates.ts +++ b/packages/compiler/src/frontend/lowering/expressions/updates.ts @@ -42,6 +42,7 @@ import type { CompoundOp } from "../surfaces.js"; import { tryLowerExpression } from "./try-lower-expression.js"; import { hasRuntimeStatics } from "../class-runtime-statics.js"; import { declareContextLocal } from "../function-context.js"; +import { keyedFieldTarget, keyedFieldWrite, saveKeyedFieldKey } from "./keyed-field-targets.js"; /** Read-modify-write updates read the member first: an unassigned * deferred-init receiver throws Node's member-read TypeError. */ @@ -337,10 +338,11 @@ export function lowerIncDec( } const target = ts.isPropertyAccessExpression(access) ? lowerer.fieldTarget(access) - : symbolFieldTarget(lowerer, access); + : (symbolFieldTarget(lowerer, access) ?? keyedFieldTarget(lowerer, access, true)); if (target && lowerer.dynConvertible(target.fieldType)) { checkDeferredMemberReceiver(lowerer, target, access); target.obj = save(target.obj, "%incrementReceiver"); + saveKeyedFieldKey(target, save); return finish(lowerer.fieldGetExpr(target, loc, access), (value) => lowerer.fieldSetStmt( target, @@ -617,6 +619,7 @@ export function fieldSetStmt( }; } } + if (target.container === "recordKeyed") return keyedFieldWrite(lowerer, target, value, loc); if (target.container === "dynamic") return { kind: "exprStmt", @@ -872,12 +875,13 @@ export function lowerFieldCompoundValue( const targetOf = (): FieldTarget | null => ts.isPropertyAccessExpression(access) ? lowerer.fieldTarget(access) - : symbolFieldTarget(lowerer, access); + : (symbolFieldTarget(lowerer, access) ?? keyedFieldTarget(lowerer, access, true)); const target = targetOf(); if (!target) lowerer.unsupported("SC1090", access, "compound assignment to unsupported field targets"); checkDeferredMemberReceiver(lowerer, target, access); target.obj = save(target.obj, "%compoundReceiver"); + saveKeyedFieldKey(target, save); // Accessors observe getter, RHS side effects, then setter, all through // the saved receiver. const fieldRead = lowerer.fieldGetExpr(target, locOf(access), access); diff --git a/packages/compiler/src/frontend/lowering/function-context.ts b/packages/compiler/src/frontend/lowering/function-context.ts index e31e194c5..92042b7d7 100644 --- a/packages/compiler/src/frontend/lowering/function-context.ts +++ b/packages/compiler/src/frontend/lowering/function-context.ts @@ -48,6 +48,16 @@ export interface FnCtx { argumentsLocal?: IrLocal | null; /** Arrows inherit the nearest ordinary function's arguments binding. */ inheritsArguments?: boolean; + /** A function lowered on demand on top of an unrelated caller's frames + * (a generic instance): lexical `this` resolution stops here, so the + * body sees what it sees when lowered alone. */ + thisBoundary?: true; + /** Tuple bindings of this function that are only forwarded + * (typed-arguments.ts onlyForwarded): binding local id → the native + * slots forwarding reads. Such a binding is never materialized. Local ids + * are unique within one function only, and nested functions never read + * these bindings (a read there needs the tuple). */ + pureTuples: Map; /** Declared return type — lets `return` detect record-shape mismatches * (SC2002) before the validator would ICE on them. */ returnType: IrType; @@ -81,6 +91,7 @@ export function newFnCtx( captures: lifted ? [] : null, captureSources: [], captureBySymbol: new Map(), + pureTuples: new Map(), selfSymbol, selfType, returnType, @@ -154,7 +165,16 @@ export function captureContextBinding( throw new InternalCompilerError("lowerer bug: no active function context"); const direct = bindingInContext(current, symbol); if (direct !== null) return { local: direct, origin: direct, error: null }; - for (let depth = stack.length - 2; depth >= 0; depth--) { + let floor = 0; + if (symbol === undefined) { + for (let depth = stack.length - 1; depth >= 0; depth--) { + if (stack[depth]!.thisBoundary) { + floor = depth; + break; + } + } + } + for (let depth = stack.length - 2; depth >= floor; depth--) { const origin = bindingInContext(stack[depth]!, symbol); if (origin === null) continue; diff --git a/packages/compiler/src/frontend/lowering/general-streams.ts b/packages/compiler/src/frontend/lowering/general-streams.ts new file mode 100644 index 000000000..0113a9958 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/general-streams.ts @@ -0,0 +1,114 @@ +/* The general stream representation (TypeMapperCtx.generalNodeStreams). + * + * NodeJS.ReadableStream and NodeJS.WritableStream (and @types/node's + * stream.Readable / stream.Writable, which also type child stdio) name the + * interface every Node stream implements. By default they map to the + * child/process stdio handles: the specialized representation of the + * values that commonly fill them (child.stdout, process.stdout). A program + * that moves another stream — fs.createReadStream(), a zlib Transform, a + * Readable subclass — into one of those slots needs the general + * representation instead: the runtime stream classes, with the stdio + * handles converted into them where they are read or flow. + * + * The decision is per program. Reachable emit lowers without it; a flow + * that needs it marks the lowerer (needsGeneralNodeStreams) and lowerToIr + * lowers the whole program again with it. Programs without such a flow + * never take the second pass, so their IR is unchanged. */ +import type { IrExpr, IrType } from "../../ir/ir.js"; +import { everyTypeChild } from "../../ir/traverse.js"; +import * as ts from "../ts7/adapter.js"; +import { isGeneralNodeStreamInterface } from "../type-mapper.js"; +import type { Lowerer } from "./lowerer.js"; +import { streamSidesOf } from "./lower-stream.js"; + +const STDIO_STREAM_KINDS: ReadonlySet = new Set([ + "childStream", + "childWriter", + "procStream", +]); + +/** Whether `type` (through union arms, record fields and the structural + * type children) contains a part satisfying `test`. */ +function containsPart(lowerer: Lowerer, type: IrType, test: (part: IrType) => boolean): boolean { + const seen = new Set(); + const walk = (part: IrType): boolean => { + if (test(part)) return true; + if (part.kind === "union") { + if (seen.has(`u:${part.unionId}`)) return false; + seen.add(`u:${part.unionId}`); + return (lowerer.unions.get(part.unionId)?.arms ?? []).some(walk); + } + if (part.kind === "record") { + if (seen.has(`r:${part.shapeId}`)) return false; + seen.add(`r:${part.shapeId}`); + return (lowerer.shapes.get(part.shapeId)?.fields ?? []).some((f) => walk(f.type)); + } + let found = false; + everyTypeChild(part, (child) => { + found = walk(child); + return !found; + }); + return found; + }; + return walk(type); +} + +function isGeneralStream(lowerer: Lowerer, part: IrType): boolean { + return ( + part.kind === "object" && streamSidesOf(lowerer, lowerer.classes.get(part.className)) !== null + ); +} + +/** A mismatched flow (requireExactShape's input) that the general stream + * representation resolves: a general stream into a stdio-represented + * slot, a child pipe handle into an 'unknown' slot, or an 'unknown' value + * into a child-pipe slot (the general classes take a checked cast). */ +export function needsGeneralNodeStreams( + lowerer: Lowerer, + actual: IrType, + expected: IrType, +): boolean { + const stdio = (part: IrType): boolean => STDIO_STREAM_KINDS.has(part.kind); + const pipeHandle = (part: IrType): boolean => + part.kind === "childStream" || part.kind === "childWriter"; + if (actual.kind === "dyn") return containsPart(lowerer, expected, pipeHandle); + if (containsPart(lowerer, expected, stdio)) + return containsPart(lowerer, actual, (p) => isGeneralStream(lowerer, p)); + return expected.kind === "dyn" && containsPart(lowerer, actual, pipeHandle); +} + +/** Under the general representation, process.stdout / process.stderr (the + * procStream fd scalar) flowing into a runtime Writable slot: an + * fd-backed Writable whose writes take the same synchronous path as + * process.stdout.write. Null when the flow is not that one. */ +export function stdioIntoGeneralStream( + lowerer: Lowerer, + expr: IrExpr, + expected: IrType, +): IrExpr | null { + if (!lowerer.generalNodeStreams || expr.type.kind !== "procStream") return null; + const writable: IrType = { kind: "object", className: "%Writable" }; + const accepts = + (expected.kind === "object" && expected.className === "%Writable") || + (expected.kind === "union" && lowerer.armTag(expected.unionId, writable) >= 0); + if (!accepts) return null; + return { + kind: "libCall", + fn: "stream.stdioWritable", + args: [expr], + type: writable, + loc: expr.loc, + }; +} + +/** A stdio-handle receiver whose member has no lowering on the handle + * (`out.on("error", ...)`, `child.stdout.pipe(...)`, `output.end()`): when + * its declared type is one the general representation maps to a runtime + * stream class, the program lowers again with it, where the full stream + * surface applies. The caller still reports its fence for this pass. */ +export function requestGeneralStreamSurface(lowerer: Lowerer, receiver: ts.Expression): void { + if (lowerer.generalNodeStreams) return; + const type = lowerer.checker.getNonNullableType(lowerer.typeOf(receiver)); + if (isGeneralNodeStreamInterface(type, lowerer.typeCtx)) + lowerer.requiresGeneralNodeStreams = true; +} diff --git a/packages/compiler/src/frontend/lowering/generic-functions.ts b/packages/compiler/src/frontend/lowering/generic-functions.ts index f588faf6d..b586884c5 100644 --- a/packages/compiler/src/frontend/lowering/generic-functions.ts +++ b/packages/compiler/src/frontend/lowering/generic-functions.ts @@ -1,3 +1,4 @@ +import { staticNameBindings } from "./static-function-names.js"; import * as ts from "../ts7/adapter.js"; import { bodyReadsArguments } from "../arguments-usage.js"; import type { Lowerer } from "./lowerer.js"; @@ -100,6 +101,9 @@ export interface GenericFnInfo { * names where the slot binds the call site's object type. Computed on * first use. */ implicitPatterns?: (ImplicitPattern | null)[]; + /** Parameter index → symbol for the function parameters whose `.name` + * the body reads (static-function-names.ts); computed on first use. */ + nameReadParams?: Map; } export interface GenericInstance { @@ -140,6 +144,9 @@ export interface GenericInstance { implicitInferReturn?: true; /** An erased instance (every type parameter bound to `unknown`). */ erased?: true; + /** Name-keyed instances: function parameter → its call site's static + * name (null when only known at run time), folded at `.name` reads. */ + staticFnNames?: Map; } /** Defaults bind during inference; collection only resolves symbols in @@ -295,7 +302,13 @@ export function genericCallInstance( const retTs = lowerer.checker.getReturnTypeOfSignature(rsig); const local = localClassResultInstance(lowerer, expr, info, rsig, params, retTs); if (local) return local; - const mappedReturn = lowerer.mapTypeOf(retTs); + // A result instantiated at `any` (a type argument inferred from an + // untyped value, such as an untyped forwarding call) is checked-dynamic. + const mappedReturn = + lowerer.mapTypeOf(retTs) ?? + ((retTs.flags & ts.TypeFlags.Any) !== 0 && !isJsSourceFile(info.decl.getSourceFile()) + ? DYN + : null); if (!mappedReturn) { fenceGenericSignatureResult(lowerer, expr, retTs); lowerer.badType(expr, retTs); @@ -317,6 +330,7 @@ export function genericCallInstance( // different fields). Non-literal bindings (a key union, plain string) // share one runtime-keyed instance per IR signature, exactly the // widened discipline. + const named = staticNameBindings(lowerer, expr, info); const keyofTps = keyofConstrainedTypeParams(info); if (keyofTps.size > 0) { const tsBindings = new Map(); @@ -333,12 +347,19 @@ export function genericCallInstance( }) .join(","); return internGenericInstance(lowerer, expr, info, params, returnType, () => bindings, { - extraKey: `@${litKey}`, + extraKey: `@${litKey}${named?.key ?? ""}`, tsBindings, + ...(named ? { staticFnNames: named.names } : {}), }); } - return internGenericInstance(lowerer, expr, info, params, returnType, (tsBindings) => - lowerer.inferTypeParamBindings(expr, info, rsig, tsBindings), + return internGenericInstance( + lowerer, + expr, + info, + params, + returnType, + (tsBindings) => lowerer.inferTypeParamBindings(expr, info, rsig, tsBindings), + named ? { extraKey: named.key, staticFnNames: named.names } : undefined, ); } @@ -498,7 +519,11 @@ function internGenericInstance( params: ParamShape[], returnType: IrType, makeBindings: (tsBindings: Map) => Map, - opts?: { extraKey?: string; tsBindings?: Map }, + opts?: { + extraKey?: string; + tsBindings?: Map; + staticFnNames?: Map; + }, ): GenericInstance { // keyof-constrained instantiations append their literal keys // (extraKey): the IR signature alone under-discriminates there — two @@ -541,6 +566,7 @@ function internGenericInstance( bindings, tsBindings, typeArgsText, + ...(opts?.staticFnNames ? { staticFnNames: opts.staticFnNames } : {}), }; info.instances.set(key, inst); lowerer.instantiationQueue.push({ info, inst }); @@ -671,7 +697,11 @@ function unifySignatureBindings( tsBindings.set(sym, lowerer.typeParamTsResolver(inst) ?? inst); } if (!bindings.has(sym)) { - const mapped = lowerer.mapTypeOf(inst); + const mapped = + lowerer.mapTypeOf(inst) ?? + ((inst.flags & ts.TypeFlags.Any) !== 0 && !isJsSourceFile(info.decl.getSourceFile()) + ? DYN + : null); // A visitor's inferred T can be void. It still binds the // return convention of `(node) => T`; discarding it leaves // the callback's return type spuriously uninstantiated. @@ -824,6 +854,8 @@ export function lowerGenericInstance( const prevSuppress = lowerer.suppressStats; const prevClass = lowerer.currentClass; const prevImplicit = lowerer.implicitParamTypes; + const prevStaticFnNames = lowerer.staticFnNames; + lowerer.staticFnNames = inst.staticFnNames ?? null; // A generic METHOD of a generic-class INSTANTIATION lowers under BOTH // binding sets: the receiver instantiation's class type parameters // underneath, the method instantiation's own on top (disjoint symbol @@ -873,6 +905,8 @@ export function lowerGenericInstance( : lowerer.bodyReturnType(isAsync, inst.returnType); const fnCtx = newFnCtx(false, null, null, bodyReturn); fnCtx.isAsync = isAsync; + // Instances lower on demand, on top of whichever caller reached them. + fnCtx.thisBoundary = true; // Implicit-any instances whose declared return did not map lower in // return-INFERENCE mode: `return` statements record here bare, and the // post-pass (resolveInferredReturn) settles the type and wraps them. @@ -984,6 +1018,7 @@ export function lowerGenericInstance( lowerer.typeParamBindings = prevBindings; lowerer.typeParamTsBindings = prevTsBindings; lowerer.implicitParamTypes = prevImplicit; + lowerer.staticFnNames = prevStaticFnNames; lowerer.instantiationContext = prevContext; lowerer.localClassInstantiations.pop(); lowerer.suppressStats = prevSuppress; diff --git a/packages/compiler/src/frontend/lowering/lower-calls.ts b/packages/compiler/src/frontend/lowering/lower-calls.ts index 5d326709c..b0b7884f2 100644 --- a/packages/compiler/src/frontend/lowering/lower-calls.ts +++ b/packages/compiler/src/frontend/lowering/lower-calls.ts @@ -1,7 +1,10 @@ +import { isForwardedTupleSpread, lowerForwardingApply } from "./typed-arguments.js"; import { guardNullProto, nullProtoRecordShape } from "./null-prototype.js"; +import { lowerBuiltinClassCall } from "./builtins/builtin-class-dyn.js"; import { refuseModuleMemberThis } from "./module-member-this.js"; import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js"; import { lowerHashStreamCall } from "./builtins/hash-stream.js"; +import { lowerWebAssemblyValueOf } from "./builtins/webassembly.js"; import { lowerResponseStaticJson } from "./lower-stdlib.js"; import { lowerArrayCallbackCall } from "./containers/array-callback-call.js"; /** Dispatch source calls, builtin members and receiver-specific operations. @@ -149,6 +152,7 @@ import { import { fencePerfEntryKeyWalk, isPerfEntryType, + lowerHistogramMethodCall, lowerPerfHooksCall, perfEntryTag, } from "./builtins/performance.js"; @@ -254,7 +258,6 @@ const ZLIB_STREAM_METHODS: ReadonlySet = new Set(["flush", "params", "cl export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { const loc = locOf(expr); - // Object's checker return type is `any`. Claim known object inputs // before generic checked-dynamic dispatch tries to load the constructor. if ( @@ -266,6 +269,11 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { if (object) return object; } + // `EventEmitter.call(this)` in a constructor function: the untyped + // EventEmitter constructor initializes the receiver. + const builtinClassCall = lowerBuiltinClassCall(lowerer, expr); + if (builtinClassCall) return builtinClassCall; + // require() of a JSON document: the shared parsed object. const json = lowerJsonRequireCall(lowerer, expr); if (json) return json; @@ -1406,6 +1414,9 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { if (ts.isPropertyAccessExpression(expr.expression)) { const intrinsic = fenceNodeModuleMutationCall(lowerer, expr, expr.expression) ?? + // `f.apply(thisArg, args)` forwarding a fixed argument tuple (typed + // `arguments`, a tuple rest parameter): a direct call. + lowerForwardingApply(lowerer, expr, expr.expression) ?? // Builtin namespace imports first (`fs.readFileSync(...)` where fs // is `import * as fs from "node:fs"`): the same tables and fences // as named builtin imports — before anything below tries to lower @@ -1417,6 +1428,7 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { // .bind(performance) function value over the runtime's // process-start-anchored monotonic clock. lowerPerfHooksCall(lowerer, expr, expr.expression) ?? + lowerHistogramMethodCall(lowerer, expr, expr.expression) ?? // The composed crypto pattern (randomBytes(n).toString(enc)) // — its receiver is a Buffer-typed CALL no other lowering claims. lowerer.lowerCryptoComposedCall(expr, expr.expression) ?? @@ -1901,6 +1913,19 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { // or marshals the callee and applies through a runtime-built argument // list (lowerSpreadArgsCall). Shapes outside its lanes fall through // to the historical fences. + // Forwarded fixed tuples (`fn(...args)` over a tuple rest parameter or a + // typed `arguments`) have a compile-time arity: complete them into the + // callee's positional slots directly, without the runtime-arity lane. + if ( + callee.type.rest !== true && + expr.arguments.nodes.some(ts.isSpreadElement) && + expr.arguments.nodes.every( + (a) => !ts.isSpreadElement(a) || isForwardedTupleSpread(lowerer, a.expression), + ) + ) { + const args = completeFuncValueArgs(lowerer, expr, callee.type, loc); + return { kind: "callValue", callee, args, type: callee.type.ret, loc }; + } if (expr.arguments.nodes.some((a) => ts.isSpreadElement(a))) { const spreadServed = lowerSpreadArgsCall(lowerer, expr, callee, loc); if (spreadServed) return spreadServed; @@ -3319,7 +3344,13 @@ function lowerDynReceiverMethodCall( // array — scalar narrowings bridge through maybeNarrow's dynCheck and // take the ordinary typed paths, but there is no static home for an // any-elemented array). Typed receivers keep their own lowerings. - const recvTs = lowerer.typeOf(access.expression); + // An optional step the chain already guarded (`s?.m(x)`) has a receiver + // proven non-nullish. + const rawRecvTs = lowerer.typeOf(access.expression); + const recvTs = + access.questionDotToken !== undefined && lowerer.chainHandled.has(access) + ? lowerer.checker.getNonNullableType(rawRecvTs) + : rawRecvTs; if (lowerer.classImplementedProtocol(recvTs)) { const property = lowerer.checker.getPropertyOfType(recvTs, access.name.text); if ( @@ -3644,6 +3675,8 @@ function lowerDynReceiverMethodCall( // answers each kind's own: primitives and plain objects themselves, a // Date its time value, an own or inherited valueOf member its result. if (access.name.text === "valueOf" && call.arguments.nodes.length === 0) { + const webAssembly = lowerWebAssemblyValueOf(lowerer, access.expression, recv, locOf(call)); + if (webAssembly !== null) return webAssembly; return { kind: "libCall", fn: "dyn.valueOf", @@ -4351,6 +4384,14 @@ function lowerCaughtPredicateCall( const paramSymbol = lowerer.checker.getSymbolAtLocation(param.name); if (!paramSymbol) return null; const ret = decl.body.statements.nodes.length === 1 ? decl.body.statements.nodes[0] : undefined; + // A longer guard whose parameter is `unknown` (or `any`) takes the caught + // value as an ordinary checked-dynamic argument: the call path converts + // the binding, and the narrowed binding reads through the same value. + if ( + (!ret || !ts.isReturnStatement(ret) || !ret.expression) && + lowerer.mapTypeOf(lowerer.checker.getTypeOfSymbol(paramSymbol))?.kind === "dyn" + ) + return null; if (!ret || !ts.isReturnStatement(ret) || !ret.expression) { lowerer.unsupported( "SC1090", @@ -6892,6 +6933,7 @@ function recordAssignHelper( const helper = `%obj.assign.${lowerer.arrHofHelpers.size}`; lowerer.arrHofHelpers.set(key, helper); const sShape = lowerer.shapes.get(srcShapeId)!; + const tShape = lowerer.shapes.get(targetShapeId)!; const tT: IrType = { kind: "record", shapeId: targetShapeId }; const sT: IrType = { kind: "record", shapeId: srcShapeId }; const tRef: IrExpr = { kind: "varRef", localId: "t.0", type: tT, loc }; @@ -6906,12 +6948,13 @@ function recordAssignHelper( type: f.type, loc, }; + const targetType = tShape.fields.find((x) => x.name === f.name)!.type; const set: IrStmt = { kind: "recordSet", obj: tRef, shapeId: targetShapeId, field: f.name, - value: get, + value: typeEquals(targetType, f.type) ? get : lowerer.coerceToExpected(get, targetType), loc, }; const present = lowerer.recordFieldPresent(sRef, srcShapeId, f.name, loc); @@ -7459,6 +7502,8 @@ function lowerObjectStaticCall( }; } } + const onError = lowerObjectAssignOntoError(lowerer, call); + if (onError) return onError; const hybrid = lowerObjectAssignHybrid(lowerer, call); if (hybrid) return hybrid; // `Object.assign({}, lit)` — an EMPTY fresh-literal target and one @@ -7551,7 +7596,12 @@ function lowerObjectStaticCall( !shapeHasAccessorSlots(sShape) && sShape.fields.every((sf) => { const tf = tShape.fields.find((x) => x.name === sf.name); - return tf !== undefined && typeEquals(tf.type, sf.type); + // A source value converts into a wider target field (`{ bail: + // true }` into `bail?: boolean`). + return ( + tf !== undefined && + (typeEquals(tf.type, sf.type) || lowerer.coercibleValue(sf.type, tf.type)) + ); }); if (ok) { const loc = locOf(call); @@ -7569,6 +7619,37 @@ function lowerObjectStaticCall( } } } + // `throw Object.assign(record, { extra })`: an error-shaped record given + // a member its type lacks, thrown at once. A fixed record cannot grow + // the member, so the throw carries a checked-dynamic copy of the target + // with the source's members added. The copy is unobservable: control + // leaves with the throw, so nothing on that path reads the target again. + { + let parent: ts.Node | undefined = call.parent; + while (parent && ts.isParenthesizedExpression(parent)) parent = parent.parent; + const argNodes = call.arguments.nodes; + if ( + parent && + ts.isThrowStatement(parent) && + argNodes.length === 2 && + !argNodes.some((a) => ts.isSpreadElement(a)) + ) { + const tProbe = tryLowerExpression(lowerer, argNodes[0]!); + const sProbe = tryLowerExpression(lowerer, argNodes[1]!); + if ( + tProbe?.type.kind === "record" && + lowerer.dynConvertible(tProbe.type) && + sProbe && + (sProbe.type.kind === "dyn" || lowerer.dynConvertible(sProbe.type)) + ) { + const loc = locOf(call); + const target = lowerer.coerceToExpected(lowerer.lowerExpr(argNodes[0]!), DYN); + const source = lowerer.coerceToExpected(lowerer.lowerExpr(argNodes[1]!), DYN); + if (target.type.kind === "dyn" && source.type.kind === "dyn") + return { kind: "libCall", fn: "dyn.assign", args: [target, source], type: DYN, loc }; + } + } + } // `Object.assign(target, ...sources)` over a CHECKED-DYNAMIC target // — the n-ary/spread form (`Object.assign({}, ...plugins.map(p => // p.options), coreOptions)`, support.js's option-table merge). The @@ -8799,6 +8880,9 @@ export function lowerRecordFieldCall( }; return init ? { kind: "seqExpr", stmts: [init], result, type: result.type, loc } : result; } + // An optional callback field the checker narrowed at this call + // (`o.cb ? o.cb(x) : …`, `if (o.cb) o.cb(x)`): extract the func arm. + if (callee.type.kind === "union") callee = lowerer.maybeNarrow(callee, access); if (callee.type.kind !== "func") lowerer.badType(access, lowerer.typeOf(access)); // JavaScript passes the record as `this`. A record with no dynamic form // cannot be that receiver; the library's own function fields (the @@ -9645,6 +9729,30 @@ export function lowerObjectMethodCall( `calls of the abstract method '${method}' with no concrete implementation below the receiver's static class`, ); } + // The static receiver's nearest declaration is an override adapted to + // the inherited ABI, and nothing below overrides it: call its body + // directly under its declared signature (exact parameters and result). + // The slot function stays reachable; it lifts the body. + const adapted = found.declarer.returnAdapters?.get(method); + // A TypeScript override's own entry answers its declared result. A + // JavaScript body's result is inferred, so its callers keep the slot. + const declarerDecl = found.declarer.decl; + if ( + adapted && + !(declarerDecl && isJsSourceFile(declarerDecl.getSourceFile())) && + !lowerer.overrideBelow(info, method) + ) { + lowerer.noteEdge(`%${found.declarer.def.name}.${method}`); + const receiver = lowerReceiver(); + const args = lowerer.completeArgs(call.arguments.nodes, adapted.params, locOf(call), call); + return { + kind: "call", + callee: `%${found.declarer.def.name}.${method}$own`, + args: [lowerer.upcastTo(receiver, found.declarer.def.name), ...args], + type: adapted.ret, + loc: locOf(call), + }; + } if (lowerer.overrideBelow(info, method)) lowerer.noteVirtualEdge(info, method); else lowerer.noteEdge(`%${found.declarer.def.name}.${method}`); const receiver = lowerReceiver(); @@ -10255,3 +10363,60 @@ function maybePromiseHandlerResult( } return stmt; } + +/** `Object.assign(err, ...sources)` in TypeScript onto an error-hierarchy + * target (`Object.assign(new Error(message), details)`): the sources' + * own members land on the error — the runtime copy over its + * checked-dynamic node, whose name, message, stack, cause and code feed + * back into the typed slots — and the call answers the error itself. + * Null for every other target. */ +function lowerObjectAssignOntoError(lowerer: Lowerer, call: ts.CallExpression): IrExpr | null { + const argNodes = call.arguments.nodes; + if ( + isJsSourceFile(call.getSourceFile()) || + argNodes.length < 2 || + argNodes.some((a) => ts.isSpreadElement(a)) + ) + return null; + const probe = tryLowerExpression(lowerer, argNodes[0]!); + if (probe?.type.kind !== "object" || !lowerer.isErrorRootedClass(probe.type.className)) + return null; + const loc = locOf(call); + const target = lowerer.lowerExpr(argNodes[0]!); + const slot = lowerer.declareHiddenLocal("%assignErr", target.type); + const sources: IrExpr[] = []; + for (const node of argNodes.slice(1)) { + const raw = lowerer.lowerExpr(node); + fenceSymbolFieldCopy(lowerer, node, raw.type); + const source = lowerer.coerceToExpected(raw, DYN); + if (source.type.kind !== "dyn") { + lowerer.unsupported( + "SC1090", + node, + `Object.assign onto an Error from a '${lowerer.fmt(raw.type)}' source (sources enter the error's dynamic properties)`, + ); + } + sources.push(source); + } + const ref = (): IrExpr => ({ kind: "varRef", localId: slot.id, type: target.type, loc }); + return { + kind: "seqExpr", + stmts: [ + { kind: "varDecl", localId: slot.id, init: target, loc }, + { + kind: "exprStmt", + expr: { + kind: "libCall", + fn: "error.assign", + args: [ref(), { kind: "dynArrLit", elems: sources, type: DYN, loc }], + type: VOID, + loc, + }, + loc, + }, + ], + result: ref(), + type: target.type, + loc, + }; +} diff --git a/packages/compiler/src/frontend/lowering/lower-classes.ts b/packages/compiler/src/frontend/lowering/lower-classes.ts index bce4ac6f0..680812905 100644 --- a/packages/compiler/src/frontend/lowering/lower-classes.ts +++ b/packages/compiler/src/frontend/lowering/lower-classes.ts @@ -31,6 +31,7 @@ import type { FnCtx, Lowerer } from "./lowerer.js"; import { inlineNamespaceRequireOf, lowerWithInlineRequireInit } from "./cjs-inline-require.js"; import { BOOL, + canDynCheckTo, DATE_T, DYN, F64, @@ -500,6 +501,12 @@ export interface ClassInfo { /** Own JS overrides whose signature cannot use the inherited ABI. The slot * retains that ABI, but its implementation throws before executing. */ methodEntryFences?: Map; + /** Own TypeScript overrides whose declared result differs from the + * inherited ABI's but converts into it (`Promise` over `any`, a + * union narrowed to its inherited arm): the slot function `%C.m` keeps the + * inherited ABI and converts the result of the body, which lowers as + * `%C.m$own` with the declared result (async when declared so). */ + returnAdapters?: Map; /** OWN GENERIC instance methods (own type parameters — `m(x: T)`), * monomorphized per call site like top-level generic functions: instance * `n` is the module function `%C.m%n` taking `this` as param 0. They @@ -2256,6 +2263,7 @@ export function collectClassShapeInner( } >(); const methodEntryFences = new Map(); + const returnAdapters = new Map(); // Own accessor declarations ("get:x"/"set:x" → node), for the // partial-override analysis below (diagnostics need the node). const accessorNodes = new Map(); @@ -3441,7 +3449,67 @@ export function collectClassShapeInner( overridden.declarer.decl !== null && isJsSourceFile(overridden.declarer.decl.getSourceFile()) && overridden.sig.gen === undefined; - if (fencedJsOverride) { + // A TypeScript override that only changes the result, into a + // type that converts into the inherited one (`Promise` over + // an `any` base, `string | undefined` over `string`): the slot + // keeps the inherited ABI and converts the body's result at the + // boundary (lowerClassMethodMemberInner). + const ownAsync = + member.modifiers?.nodes.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true; + if ( + !fencedJsOverride && + !functionLocalClass(decl) && + overridden.sig.gen === undefined && + // An async base's slot answers its promise: a Promise type, or + // the checked-dynamic value of an untyped async method. + (overridden.sig.async !== true || + overridden.sig.ret.kind === "promise" || + overridden.sig.ret.kind === "dyn") && + !overridden.sig.abstract && + overridden.sig.params.length === shapes.length && + overridden.sig.params.every( + (p, i) => + p.mode === shapes[i]!.mode && + (p.mode === "required" || p.mode === "omittable") && + // Each inherited argument converts into the override's + // parameter: equal, a checked extraction from an `any` + // slot, or a widening (a contravariant parameter). + (typeEquals(p.type, shapes[i]!.type) || + (p.type.kind === "dyn" && + canDynCheckTo( + shapes[i]!.type, + (id) => lowerer.shapes.get(id), + (id) => lowerer.unions.get(id), + )) || + lowerer.coercibleValue(p.type, shapes[i]!.type)), + ) && + (ownAsync ? ft.ret.kind === "promise" : true) && + (typeEquals(ft.ret, overridden.sig.ret) || + (overridden.sig.ret.kind === "dyn" + ? ft.ret.kind !== "void" && lowerer.dynConvertible(ft.ret) + : lowerer.coercibleValue(ft.ret, overridden.sig.ret) || + // A promise whose payload widens into the inherited one + // (`Promise` over an untyped async `Promise`). + (ft.ret.kind === "promise" && + overridden.sig.ret.kind === "promise" && + lowerer.promisePayloadWidens(ft.ret, overridden.sig.ret)) || + // A JavaScript override's inferred `any` result checks + // into the inherited type (`toString() { return + // this.message }` over Error's). + (ft.ret.kind === "dyn" && + isJsSourceFile(member.getSourceFile()) && + overridden.sig.ret.kind !== "void" && + canDynCheckTo( + overridden.sig.ret, + (id) => lowerer.shapes.get(id), + (id) => lowerer.unions.get(id), + )))) + ) { + returnAdapters.set(mName, { params: [...shapes], ret: ft.ret, async: ownAsync }); + shapes.splice(0, shapes.length, ...overridden.sig.params); + ft.ret = overridden.sig.ret; + if (overridden.sig.async === true) thunkAsyncSlot(overridden, mName); + } else if (fencedJsOverride) { // A dormant JS method must not poison the whole class. Keep // the inherited call/dispatch ABI and refuse at method entry; // lowering this body with the base signature would change JS. @@ -3496,7 +3564,34 @@ export function collectClassShapeInner( // fiber spawn wrapper; vtable slots hold raw implementations) — // an override chain touching an async method on either end would // put a spawn wrapper behind a virtual slot, so it fences. - if (overridden && (asyncMember || overridden.sig.async === true)) { + // An override chain touching async methods dispatches through + // plain slot functions that return the body's promise: the async + // bodies lower as `%C.m$own` behind them (thunkAsyncSlot). + if ( + overridden && + !returnAdapters.has(mName) && + (asyncMember || overridden.sig.async === true) && + !isJsSourceFile(member.getSourceFile()) && + !functionLocalClass(decl) && + member.asteriskToken === undefined && + overridden.sig.gen === undefined && + !overridden.sig.abstract && + ft.ret.kind === "promise" && + typeEquals(ft.ret, overridden.sig.ret) && + overridden.sig.params.length === shapes.length && + overridden.sig.params.every( + (p, i) => typeEquals(p.type, shapes[i]!.type) && p.mode === shapes[i]!.mode, + ) + ) { + if (overridden.sig.async === true) thunkAsyncSlot(overridden, mName); + if (asyncMember) + returnAdapters.set(mName, { params: [...shapes], ret: ft.ret, async: true }); + } + if ( + overridden && + !returnAdapters.has(mName) && + (asyncMember || overridden.sig.async === true) + ) { const message = `overriding ${overridden.sig.async === true ? "the async method" : "a method with an async method"} '${mName}' (async methods dispatch statically — the vtable slot machinery has no fiber-spawn story)`; if (isJsSourceFile(member.getSourceFile())) methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), message)); @@ -3527,7 +3622,7 @@ export function collectClassShapeInner( } else { methods.set( mName, - asyncMember + asyncMember && !returnAdapters.has(mName) ? { params: shapes, ret: ft.ret, async: true as const } : { params: shapes, ret: ft.ret }, ); @@ -4245,6 +4340,7 @@ export function collectClassShapeInner( fieldOrder, methods, ...(methodEntryFences.size > 0 ? { methodEntryFences } : {}), + ...(returnAdapters.size > 0 ? { returnAdapters } : {}), decl, ...(emitOverride !== undefined ? { emitOverride } : {}), ctor, @@ -6623,6 +6719,28 @@ function abstractMemberSignature( /** A nominal return subtype uses the same owned pointer as the inherited * return slot. The current class is still being collected, so consult its * already collected base chain before the complete class graph is available. */ +/** An inherited ASYNC method that an override now dispatches against: its + * slot becomes a plain function returning the body's promise, and the + * async body lowers behind it as `%C.m$own` (the adapter path with an + * identity conversion), so a virtual call never enters an async body + * without its spawn wrapper. */ +function thunkAsyncSlot( + overridden: { declarer: ClassInfo; sig: ClassMethodSignature }, + mName: string, +): void { + if (overridden.sig.async !== true) return; + const declarer = overridden.declarer; + declarer.returnAdapters ??= new Map(); + if (!declarer.returnAdapters.has(mName)) { + declarer.returnAdapters.set(mName, { + params: [...overridden.sig.params], + ret: overridden.sig.ret, + async: true, + }); + } + delete overridden.sig.async; +} + function overrideReturnAbi( lowerer: Lowerer, declared: IrType, @@ -7845,6 +7963,82 @@ function lowerClassMethodMemberInner( allowDiagSink: true, }); } + // An override converting its declared result into the inherited ABI: + // the body lowers as `%C.m$own` under its declared result, and the slot + // function forwards to it and converts what it returns. + const adapter = info.returnAdapters?.get(mName); + if (adapter) { + const ownSig: ClassMethodSignature = { ...sig, params: adapter.params, ret: adapter.ret }; + if (adapter.async) ownSig.async = true; + const own = lowerClassMethodBody(lowerer, info, fnLike, `%${className}.${mName}$own`, ownSig); + if (!own) return null; + lowerer.liftedFns.push(own); + const loc = locOf(fnLike); + const params: IrParam[] = [ + { localId: "this.0", name: "this", type: thisType }, + ...sig.params.map((p, i) => ({ localId: `p.${i}`, name: `p${i}`, type: p.type })), + ]; + const fnCtx = newFnCtx(false, null, null, sig.ret); + lowerer.fnStack.push(fnCtx); + try { + const call: IrExpr = { + kind: "call", + callee: own.name, + args: params.map((p, i): IrExpr => { + const ref: IrExpr = { kind: "varRef", localId: p.localId, type: p.type, loc }; + // `this` passes through; each inherited argument converts into + // the override's declared parameter (checked where it narrows). + return i === 0 ? ref : lowerer.coerceInto(fnLike.name, ref, adapter.params[i - 1]!.type); + }), + type: adapter.ret, + loc, + }; + // A void slot discards the override's result after running it. A + // toString slot hands on what every ToString consumer of the result + // makes of it (`String(err)`, templates): undefined reads + // "undefined", as in Node. Other slots check the result into the + // inherited type. + const result = (): IrExpr => + mName === "toString" && sig.ret.kind === "string" + ? call.type.kind === "dyn" + ? { kind: "libCall", fn: "dyn.stringConstructor", args: [call], type: STRING, loc } + : lowerer.ensureString(call, fnLike.name) + : lowerer.coerceInto(fnLike.name, call, sig.ret); + const body: IrStmt[] = + sig.ret.kind === "void" + ? [ + { kind: "exprStmt", expr: call, loc }, + { kind: "return", value: null, loc }, + ] + : [{ kind: "return", value: result(), loc }]; + return { + name: `%${className}.${mName}`, + params, + returnType: sig.ret, + locals: [ + ...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })), + ...lowerer.ctx.locals, + ], + body, + loc, + }; + } finally { + lowerer.fnStack.pop(); + } + } + return lowerClassMethodBody(lowerer, info, fnLike, `%${className}.${mName}`, sig); +} + +function lowerClassMethodBody( + lowerer: Lowerer, + info: ClassInfo, + fnLike: ts.MethodDeclaration | ts.AccessorDeclaration, + fnName: string, + sig: ClassMethodSignature, +): IrFunction | null { + const className = info.def.name; + const thisType: IrType = { kind: "object", className }; + if (!fnLike.body) return null; const prevClass = lowerer.currentClass; lowerer.currentClass = info; // ASYNC methods: the module function is an async IrFunction — its @@ -7886,7 +8080,7 @@ function lowerClassMethodMemberInner( const body = [...declared.prologue, ...lowerer.lowerStmts(fnLike.body.statements.nodes)]; appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(fnLike)); const fn: IrFunction = { - name: `%${className}.${mName}`, + name: fnName, params, returnType: bodyReturn, locals: lowerer.ctx.locals, diff --git a/packages/compiler/src/frontend/lowering/lower-comptime.ts b/packages/compiler/src/frontend/lowering/lower-comptime.ts index 41c6704c5..f239eea82 100644 --- a/packages/compiler/src/frontend/lowering/lower-comptime.ts +++ b/packages/compiler/src/frontend/lowering/lower-comptime.ts @@ -4,7 +4,7 @@ import { InternalCompilerError } from "../../errors.js"; * literals — records/arrays/unions included, subject to comptimeBakeable. */ import * as ts from "../ts7/adapter.js"; import type { Lowerer } from "./lowerer.js"; -import { type IrExpr, type IrType } from "../../ir/ir.js"; +import { isUnitType, type IrExpr, type IrType } from "../../ir/ir.js"; import { comptimeFailedDiag } from "../../diagnostics/diagnostic.js"; import { locOf } from "../program.js"; import { PoisonError } from "./lowerer.js"; @@ -76,7 +76,7 @@ export function lowerComptime(lowerer: Lowerer, expr: ts.CallExpression): IrExpr "SC1090", expr, `baking comptime results of type '${lowerer.fmt(target)}' into the binary ` + - `(only number, string, boolean, arrays, and records lower to literals)`, + `(number, string, boolean, and arrays, records and unions of those lower to literals; a record or union type reachable from itself does not)`, ); } // 5. The host executes the extracted callback under a finite budget. @@ -110,20 +110,104 @@ function comptimeFailureDetail(error: unknown): string { /** True when a comptime result of this type can be written as a literal * expression: number/string/boolean, arrays and record shapes of those, - * nested. Closures, class instances, unions, promises, dyn, and void - * cannot be baked. */ + * and unions of those with null or undefined (the mixed rows of a JSON + * table: `(string | number)[][]`), nested. Closures, class instances, + * promises, dyn, void, and recursive types (a record or union reachable + * from itself, directly or through arrays) cannot be baked. */ export function comptimeBakeable(lowerer: Lowerer, t: IrType): boolean { + return bakeableWithin(lowerer, t, new Set()); +} + +/** comptimeBakeable below the records and unions in `open` (keyed + * `record:` and `union:`), whose members are being + * checked: reaching one of them again means the type is recursive. */ +function bakeableWithin(lowerer: Lowerer, t: IrType, open: Set): boolean { switch (t.kind) { case "f64": case "string": case "bool": return true; case "array": - return lowerer.comptimeBakeable(t.elem); + return bakeableWithin(lowerer, t.elem, open); case "record": { const shape = lowerer.shapes.get(t.shapeId); - return !!shape && shape.fields.every((f) => lowerer.comptimeBakeable(f.type)); + const key = `record:${t.shapeId}`; + if (!shape || open.has(key)) return false; + open.add(key); + const bakeable = shape.fields.every((f) => bakeableWithin(lowerer, f.type, open)); + open.delete(key); + return bakeable; } + case "union": { + const arms = lowerer.unions.get(t.unionId)?.arms; + const key = `union:${t.unionId}`; + if (arms === undefined || open.has(key)) return false; + open.add(key); + const bakeable = arms.every( + (arm) => isUnitType(arm) || (arm.kind !== "union" && bakeableWithin(lowerer, arm, open)), + ); + open.delete(key); + return bakeable; + } + default: + return false; + } +} + +/** The tag of the arm of union `unionId` that `value` bakes into, or -1. + * A record value whose discriminant field holds one of the union's + * discriminant values takes that case's arm, since arms with overlapping + * shapes can both fit it. Any other value takes the first arm it fits, in + * the union's arm order: a JSON value fits exactly one scalar arm, and + * array or record arms are told apart by their contents. */ +function comptimeUnionArm(lowerer: Lowerer, unionId: string, value: unknown): number { + const def = lowerer.unions.get(unionId); + if (!def) return -1; + const discriminant = def.discriminant; + if ( + discriminant !== undefined && + typeof value === "object" && + value !== null && + !Array.isArray(value) + ) { + const key = (value as Record)[discriminant.field]; + const named = discriminant.cases.find((c) => c.values.some((v) => v === key)); + if (named !== undefined) + return comptimeFits(lowerer, value, def.arms[named.tag]!) ? named.tag : -1; + } + return def.arms.findIndex((arm) => comptimeFits(lowerer, value, arm)); +} + +/** Whether `value` bakes into the bakeable type `t` without a mismatch: + * the arm choice of a union literal. Records are exact, as in + * comptimeValueToIr; an absent field reads as undefined. */ +function comptimeFits(lowerer: Lowerer, value: unknown, t: IrType): boolean { + switch (t.kind) { + case "f64": + return typeof value === "number" && Number.isFinite(value); + case "string": + return typeof value === "string"; + case "bool": + return typeof value === "boolean"; + case "nullT": + return value === null; + case "undefinedT": + return value === undefined; + case "array": + return Array.isArray(value) && value.every((el) => comptimeFits(lowerer, el, t.elem)); + case "record": { + if (typeof value !== "object" || value === null || Array.isArray(value)) return false; + const shape = lowerer.shapes.get(t.shapeId); + if (!shape) return false; + const obj = value as Record; + const declared = new Set(shape.fields.map((f) => f.name)); + return ( + Object.keys(obj).every((key) => declared.has(key)) && + shape.fields.every((f) => comptimeFits(lowerer, obj[f.name], f.type)) + ); + } + case "union": + return comptimeUnionArm(lowerer, t.unionId, value) >= 0; default: return false; } @@ -265,6 +349,23 @@ export function comptimeValueToIr( })); return { kind: "recordLit", fields, type: expected, loc }; } + case "union": { + const arms = lowerer.unions.get(expected.unionId)!.arms; // bakeable-checked + const tag = comptimeUnionArm(lowerer, expected.unionId, value); + if (tag < 0) fail(describeComptimeValue(value)); + const arm = arms[tag]!; + const payload: IrExpr = isUnitType(arm) + ? { kind: "unitLit", unit: arm.kind === "nullT" ? "null" : "undefined", type: arm, loc } + : lowerer.comptimeValueToIr(value, arm, path, blame); + return { + kind: "unionWrap", + unionId: expected.unionId, + tag, + value: payload, + type: expected, + loc, + }; + } default: // comptimeBakeable already fenced these off. throw new InternalCompilerError(`lowerer bug: unbakeable comptime target '${expected.kind}'`); diff --git a/packages/compiler/src/frontend/lowering/lower-event-emitter.ts b/packages/compiler/src/frontend/lowering/lower-event-emitter.ts index 06e9c4ab1..4b8b9ea14 100644 --- a/packages/compiler/src/frontend/lowering/lower-event-emitter.ts +++ b/packages/compiler/src/frontend/lowering/lower-event-emitter.ts @@ -1245,7 +1245,19 @@ export function lowerEmitterMethodCall( ); } const p = cbT.params[0]; - if (p !== undefined && !(p.kind === "bytes" && p.elem === "u8") && p.kind !== "string") { + // A `Buffer | string` chunk (NodeJS.ReadableStream's listener + // shape) takes whichever side the stream delivers. + const chunkUnion = + p?.kind === "union" && + (lowerer.unions.get(p.unionId)?.arms ?? []).every( + (arm) => (arm.kind === "bytes" && arm.elem === "u8") || arm.kind === "string", + ); + if ( + p !== undefined && + !(p.kind === "bytes" && p.elem === "u8") && + p.kind !== "string" && + !chunkUnion + ) { lowerer.noLowering( `a 'data' listener whose chunk parameter is '${lowerer.fmt(p)}'`, args[1]!, diff --git a/packages/compiler/src/frontend/lowering/lower-exprs.ts b/packages/compiler/src/frontend/lowering/lower-exprs.ts index 749b3f535..9047cf2c5 100644 --- a/packages/compiler/src/frontend/lowering/lower-exprs.ts +++ b/packages/compiler/src/frontend/lowering/lower-exprs.ts @@ -1,4 +1,4 @@ -import { refuseWebAssemblyUse } from "./builtins/webassembly.js"; +import { lowerWebAssemblyValue, refuseWebAssemblyUse } from "./builtins/webassembly.js"; import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../ir/build.js"; import { InternalCompilerError } from "../../errors.js"; /* Expression lowering: the expression dispatch (lowerExpr), literals @@ -152,6 +152,21 @@ export type FieldTarget = // (the write-slot type; reads arm it with undefined under // noUncheckedIndexedAccess in fieldGetExpr). | { container: "recordOvf"; obj: IrExpr; shapeId: string; field: string; fieldType: IrType } + // A computed key of a record in a read-modify-write (`r[k] += v`, + // `r[k]++`, `r[k] ??= v`; keyed-field-targets.ts): `keys` lists the + // declared fields a literal-union key can name, which share fieldType; + // null keys mean a string key into a pure index-signature record, whose + // entries fieldType types. `key` is null when the one literal is static. + | { + container: "recordKeyed"; + obj: IrExpr; + shapeId: string; + field: string; + keys: readonly string[] | null; + key: IrExpr | null; + fieldType: IrType; + missNaN?: true; + } | { container: "accessor"; obj: IrExpr; className: string; field: string; fieldType: IrType } // A RECORD accessor property (an object-literal `get x()`/`set x(v)` — // the shape carries %get:/%set: closure slots): reads call the getter @@ -264,7 +279,10 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { if (externalTypeSpecifier !== null) { lowerer.externalHostFence(externalTypeSpecifier, expr); } - // Every reached use of the WebAssembly API fences at its expression. + // WebAssembly API values lower; every other reached use of the API + // fences at its expression. + const webAssemblyValue = lowerWebAssemblyValue(lowerer, expr); + if (webAssemblyValue !== null) return webAssemblyValue; refuseWebAssemblyUse(lowerer, expr); if (ts.isNumericLiteral(expr)) { @@ -467,7 +485,7 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { // Only arrows can see an enclosing method's `this` (JS lexical-this); // `this` in plain nested functions is already a tsc error under // noImplicitThis, so the generic scope walk here is preflight-safe. - const local = lowerer.resolveThis(); + const local = lowerer.resolveThis(expr); if (local) { const value: IrExpr = { kind: "varRef", localId: local.id, type: local.type, loc }; // `this.#x` in a function-local class's prototype method, whose `this` @@ -1040,6 +1058,15 @@ export function nullishBranches( export function lowerCondition(lowerer: Lowerer, expr: ts.Expression): IrExpr { let e: ts.Expression = expr; while (ts.isParenthesizedExpression(e)) e = e.expression; + // `if (Object.setPrototypeOf)`: the feature test of transpiled Error + // subclasses' prototype reset. Node always has it. + if ( + ts.isPropertyAccessExpression(e) && + !e.questionDotToken && + e.name.text === "setPrototypeOf" && + lowerer.isStdlibGlobal(e.expression, "Object") + ) + return { kind: "boolLit", value: true, type: BOOL, loc: locOf(e) }; if (ts.isPropertyAccessExpression(e)) { const presence = lowerPromiseThenPresence(lowerer, e, { kind: "boolLit", @@ -2245,7 +2272,25 @@ export function caughtRead( // Unnarrowed reads cross into unknown. The caught-value dispatch pass // retains known native class payloads through live identity capsules; // other payload kinds use the runtime's ordinary conversion. - if (narrowed?.kind === "dyn") { + // `catch (e: any)` (or useUnknownInCatchVariables off) reads the same way. + if ( + narrowed?.kind === "dyn" || + (narrowed === null && (lowerer.typeOf(node).flags & ts.TypeFlags.Any) !== 0) + ) { + return { kind: "caughtToDyn", value: ref, type: DYN, loc }; + } + + // A binding a user type predicate (or an assertion) narrowed to a + // structural type (`isErrorLike(e)` → `{ message: string; … }`, an + // intersection like `TypeError & { code: unknown }`): the thrown value is + // still whatever was thrown, so it crosses as a checked-dynamic value and + // each member read validates its own result, as JavaScript reads it. + const checked = lowerer.typeOf(node); + if ( + narrowed?.kind === "record" || + narrowed?.kind === "union" || + (narrowed === null && (checked.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection)) !== 0) + ) { return { kind: "caughtToDyn", value: ref, type: DYN, loc }; } lowerer.unsupported("SC1063", node); diff --git a/packages/compiler/src/frontend/lowering/lower-functions.ts b/packages/compiler/src/frontend/lowering/lower-functions.ts index 0ef601672..f0f2c45ea 100644 --- a/packages/compiler/src/frontend/lowering/lower-functions.ts +++ b/packages/compiler/src/frontend/lowering/lower-functions.ts @@ -1,3 +1,4 @@ +import { declareTypedArguments } from "./typed-arguments.js"; import { varRef } from "../../ir/build.js"; import { InternalCompilerError } from "../../errors.js"; import * as ts from "../ts7/adapter.js"; @@ -309,6 +310,8 @@ export function lowerLambda( : null; const { params, prologue } = lowerer.declareParams(node.parameters.nodes, shapes); if (receiver) prologue.unshift(receiver); + if (ts.isFunctionExpression(node) && lowerer.typedArgumentsLambdas.has(node)) + declareTypedArguments(lowerer, node, shapes, params, prologue); declareFunctionArguments( lowerer, node, diff --git a/packages/compiler/src/frontend/lowering/lower-inspect.ts b/packages/compiler/src/frontend/lowering/lower-inspect.ts index 89b56a1ee..1310469fb 100644 --- a/packages/compiler/src/frontend/lowering/lower-inspect.ts +++ b/packages/compiler/src/frontend/lowering/lower-inspect.ts @@ -1,4 +1,5 @@ import { dynUndefinedExpr, boolLit, helperLoc, numLit, strLit, varRef } from "../../ir/build.js"; +import { builtinClassDynValueOf, builtinClassKindOf } from "./builtins/builtin-class-dyn.js"; import { InternalCompilerError } from "../../errors.js"; import * as ts from "../ts7/adapter.js"; @@ -35,7 +36,6 @@ import type { ClassInfo } from "./lower-classes.js"; import { isSafeToDiscard, isSafeToRepeat } from "./expressions/evaluation-safety.js"; import { symbolFieldDisplayName } from "./symbol-fields.js"; import { eventTargetRootOf } from "./lower-event-target.js"; -import { builtinClassRefOf } from "./builtins/class-values.js"; import { lowerSystemErrorMap } from "./lower-system-errors.js"; import { isPerfEntryType, perfEntryJson } from "./builtins/performance.js"; import { recordMayKeepSource, recordSourceTest } from "./record-sources.js"; @@ -2610,21 +2610,15 @@ function lowerUtilCallableCall( const arity = member === "deprecate" ? 4 : member === "callbackify" ? 1 : 2; // Program classes keep static prototypes: there is no function object // whose prototype chain the runtime could relink or wrap. + // EventEmitter and the stream classes are the exception as superCtor: + // the runtime has untyped constructors for them (builtin-class-dyn.ts). const classArgs = member === "inherits" ? 2 : member === "deprecate" ? 1 : 0; - // A runtime-provided parent (`util.inherits(Ctor, stream.Readable)`, the - // from2 and multistream shape) has no prototype object the runtime could - // link a constructor function's prototype to. - const parent = member === "inherits" ? expr.arguments.nodes[1] : undefined; - if (parent !== undefined && !ts.isSpreadElement(parent)) { - const ref = builtinClassRefOf(lowerer, parent); - if (ref !== null) - lowerer.noLowering( - `util.inherits onto the runtime-provided class '${ref.name}'`, - parent, - "declare the subclass with extends", - ); - } - for (const arg of expr.arguments.nodes.slice(0, classArgs)) { + const builtinBase = + member === "inherits" && expr.arguments.nodes[1] !== undefined + ? builtinClassKindOf(lowerer, expr.arguments.nodes[1]) + : null; + for (const [index, arg] of expr.arguments.nodes.slice(0, classArgs).entries()) { + if (index === 1 && builtinBase !== null) continue; if (lowerer.mapTypeOf(lowerer.typeOf(arg))?.kind === "classval") lowerer.noLowering( `util.${member} over a class constructor`, @@ -2643,9 +2637,12 @@ function lowerUtilCallableCall( const stmts: IrStmt[] = []; const args: IrExpr[] = []; for (let i = 0; i < arity; i++) { - const input: IrExpr = expr.arguments.nodes[i] - ? lowerer.lowerExprExpecting(expr.arguments.nodes[i]!, DYN) - : dynUndefinedExpr(loc); + const node = expr.arguments.nodes[i]; + const input: IrExpr = !node + ? dynUndefinedExpr(loc) + : i === 1 && builtinBase !== null + ? (builtinClassDynValueOf(lowerer, node) ?? lowerer.lowerExprExpecting(node, DYN)) + : lowerer.lowerExprExpecting(node, DYN); const saved = lowerer.declareHiddenLocal("%utilInput", DYN); stmts.push({ kind: "varDecl", localId: saved.id, init: input, loc }); args.push(varRef(saved.id, DYN, loc)); diff --git a/packages/compiler/src/frontend/lowering/lower-modules.ts b/packages/compiler/src/frontend/lowering/lower-modules.ts index 16dc0a2ca..bea6c7f7d 100644 --- a/packages/compiler/src/frontend/lowering/lower-modules.ts +++ b/packages/compiler/src/frontend/lowering/lower-modules.ts @@ -925,6 +925,14 @@ export function moduleArtifacts( valueInstanceOfRoots.add(root.def.name); } break; + case "libCall": + // The general stream representation's child stdio read bridges + // through the runtime install that boxes both stream classes. + if (node.fn === "child.stdioStream") { + visitClass("%Readable"); + visitClass("%Writable"); + } + break; case "dynFrom": if (boxedChild(node.value.type)) { // A generic child can expose native stdio without importing stream. diff --git a/packages/compiler/src/frontend/lowering/lower-stdlib.ts b/packages/compiler/src/frontend/lowering/lower-stdlib.ts index 3ad934ccc..78d690c6b 100644 --- a/packages/compiler/src/frontend/lowering/lower-stdlib.ts +++ b/packages/compiler/src/frontend/lowering/lower-stdlib.ts @@ -4,6 +4,7 @@ import { InternalCompilerError } from "../../errors.js"; import * as ts from "../ts7/adapter.js"; import { lowerToNumberArgument } from "./lower-exprs.js"; import type { Lowerer } from "./lowerer.js"; +import { isDeclaredInAmbientNamespace } from "../type-mapper.js"; import { arrayOf, BOOL, @@ -1023,7 +1024,15 @@ export function fenceStaticAbortControllerMemberRead( function isStdlibFetchInterface(lowerer: Lowerer, node: ts.Node, owner: string): ts.Symbol | null { const type = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(node)); for (const symbol of [type.getSymbol(), type.getAliasSymbol()]) { - if (symbol?.name === owner && lowerer.isStdlibSymbol(symbol)) return symbol; + // NodeJS.ReadableStream shares the WHATWG interface's name. + if ( + symbol?.name === owner && + lowerer.isStdlibSymbol(symbol) && + !symbol.declarations.some( + (d) => ts.isInterfaceDeclaration(d) && isDeclaredInAmbientNamespace(d, "NodeJS"), + ) + ) + return symbol; } return null; } diff --git a/packages/compiler/src/frontend/lowering/lower-stmts.ts b/packages/compiler/src/frontend/lowering/lower-stmts.ts index f004ac15f..ed5d97480 100644 --- a/packages/compiler/src/frontend/lowering/lower-stmts.ts +++ b/packages/compiler/src/frontend/lowering/lower-stmts.ts @@ -1,5 +1,7 @@ +import { lowerTupleAliasDecl, stripTypeWrappers } from "./typed-arguments.js"; import { declaredMemberOf } from "./expressions/property-access.js"; import { hostsAll } from "./expressions/hosted-narrowing.js"; +import { requestGeneralStreamSurface } from "./general-streams.js"; import { matchAllRowsReadByElements, storedMatchAllRowsReadByElements, @@ -1495,6 +1497,8 @@ const THROWN_AS_DYN: ReadonlySet = new Set([ ]); export function lowerStmt(lowerer: Lowerer, stmt: ts.Statement): IrStmt | IrStmt[] | null { + if (ownPrototypeResetStatement(lowerer, stmt)) + return { kind: "block", body: [], loc: locOf(stmt) }; if (ts.isClassDeclaration(stmt)) { if (!stmt.name) lowerer.unsupported("SC1090", stmt, "anonymous local class declarations"); const info = lowerer.lowerClassExpressionInfo(stmt); @@ -2417,20 +2421,30 @@ export function lowerBindingPattern( lowerer.fenceStaticHeadersIteration(pattern); if ( srcType.kind === "union" && - lowerer.unions.get(srcType.unionId)?.arms.every((arm) => arm.kind === "array") + lowerer.unions + .get(srcType.unionId) + ?.arms.every( + (arm) => + arm.kind === "array" || + arm.kind === "string" || + (arm.kind === "record" && lowerer.shapes.get(arm.shapeId)?.tuple === true), + ) && + lowerer.unions.get(srcType.unionId)!.arms.some((arm) => arm.kind !== "string") ) { for (let i = 0; i < pattern.elements.nodes.length; i++) { const el = pattern.elements.nodes[i]!; if (ts.isOmittedExpression(el) || el.name === undefined) continue; if (el.dotDotDotToken) - lowerer.unsupported("SC1031", el, "rest elements over a union of array layouts"); + lowerer.unsupported("SC1031", el, "rest elements over a union of array or tuple layouts"); const loc = locOf(el); - let value = unionArrayValueRead(lowerer, srcRef(), numLit(i, loc), loc); + let value = unionArrayValueRead(lowerer, srcRef(), numLit(i, loc), loc, (text) => + strCharsCall(lowerer, text, loc), + ); if (!value) lowerer.unsupported( "SC1031", el, - "array union elements without a common native representation", + "array or tuple union elements without a common native representation", ); if (el.initializer) value = applyBindingDefault(lowerer, el, value); lowerer.bindPatternTarget(el.name, value, isLet, out); @@ -4751,6 +4765,10 @@ export function lowerVarDecl( } } if (!ts.isIdentifier(decl.name)) lowerer.unsupported("SC1031", decl.name); + { + const alias = lowerTupleAliasDecl(lowerer, decl); + if (alias) return alias; + } // A NULLISH generic binding (`const i: I = null as any` — the // declared type has no mapping, the value is provably null/undefined @@ -5171,6 +5189,16 @@ export function lowerVarDecl( init.type.kind === "func" ) type = init.type; + // A typed-arguments function expression (typed-arguments.ts): the + // checker types the binding variadic, but its value has the fixed + // signature every use asserts. + if ( + !decl.type && + init.type.kind === "func" && + (lowerer.typedArgumentsLambdas.has(stripTypeWrappers(decl.initializer)) || + lowerer.nullishFuncResults.has(stripTypeWrappers(decl.initializer))) + ) + type = init.type; // A TypeScript lambda whose closure returns the runtime result (a missing // read, a `??` default of another type) instead of the checker's bare // return type: the binding keeps the checker's parameters and takes the @@ -7463,6 +7491,34 @@ export function lowerExprStatement(lowerer: Lowerer, expr: ts.Expression): IrStm loc, }; } + // `err.code = v` on an Error value (`err as Error & { code?: + // string }`): typed reads come from the runtime error's code + // slot, so the write lands there. A value that is not statically + // a string checks at runtime: strings take the slot, anything + // else clears it and stays a dynamic own property. The + // system-error members (errno, syscall, path, dest) read + // through the checked-dynamic node and keep the dynamic write, as + // do JavaScript files, whose reads use that node too. + if ( + !isJsSourceFile(expr.getSourceFile()) && + recv?.type.kind === "object" && + lowerer.isErrorRootedClass(recv.type.className) && + expr.left.name.text === "code" + ) { + const loc = locOf(expr); + const stringValue = isStringTyped(lowerer.typeOf(expr.right)); + return { + kind: "exprStmt", + expr: { + kind: "libCall", + fn: stringValue ? "error.setCode" : "error.setCodeDyn", + args: [recv, lowerer.lowerExprExpecting(expr.right, stringValue ? STRING : DYN)], + type: VOID, + loc, + }, + loc, + }; + } if (recv?.type.kind === "object" && recv.type.className === "%Error") { const loc = locOf(expr); return { @@ -8982,6 +9038,8 @@ export function lowerForOf(lowerer: Lowerer, stmt: ts.ForOfStatement): IrStmt { } const builtin = lowerForAwaitBuiltin(lowerer, stmt); if (builtin) return builtin; + // A NodeJS.ReadableStream iterates as the general Readable. + requestGeneralStreamSurface(lowerer, stmt.expression); lowerer.unsupported( "SC1070", stmt, @@ -11286,6 +11344,141 @@ export function stdlibBufferVarAlias(lowerer: Lowerer, decl: ts.VariableDeclarat ); } +/** A checker type that is a string or string literal (or a union of them). */ +function isStringTyped(t: ts.Type): boolean { + if (t.isUnionType()) return ts.constituentTypes(t).every(isStringTyped); + return (t.flags & (ts.TypeFlags.String | ts.TypeFlags.StringLiteral)) !== 0; +} + +/** The Error-subclass prototype reset of transpiled code, inside a class + * constructor: + * + * const proto = new.target.prototype; + * if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto); + * else this.__proto__ = proto; + * + * (also `Object.setPrototypeOf(this, new.target.prototype)` and + * `Object.setPrototypeOf(this, C.prototype)` in C's own constructor when no + * class extends C). A compiled instance already has exactly that prototype, + * so each statement is a no-op. True for those statements. */ +function ownPrototypeResetStatement(lowerer: Lowerer, stmt: ts.Statement): boolean { + if (ts.isVariableStatement(stmt)) { + const decls = stmt.declarationList.declarations.nodes; + if (decls.length !== 1 || (stmt.declarationList.flags & ts.NodeFlags.Const) === 0) return false; + const decl = decls[0]!; + if (!ts.isIdentifier(decl.name) || !decl.initializer) return false; + const ctor = enclosingConstructor(decl); + if (!ctor || !ownPrototypeRef(lowerer, decl.initializer, ctor)) return false; + const symbol = lowerer.checker.getSymbolAtLocation(decl.name); + if (!symbol) return false; + // Every other use of the binding must be one of the reset statements. + let onlyResets = true; + ts.walkPreorder(ctor, (n) => { + if (!onlyResets) return "stop"; + if (!ts.isIdentifier(n) || n === decl.name) return undefined; + if (lowerer.checker.getSymbolAtLocation(n) !== symbol) return undefined; + const statement = n.parent?.parent; + if ( + !statement || + !ts.isExpressionStatement(statement) || + resetTarget(lowerer, statement.expression) !== n + ) + onlyResets = false; + return undefined; + }); + return onlyResets; + } + if (!ts.isExpressionStatement(stmt)) return false; + const ctor = enclosingConstructor(stmt); + if (!ctor) return false; + const target = resetTarget(lowerer, stmt.expression); + return target !== null && ownPrototypeRef(lowerer, target, ctor); +} + +/** The prototype operand of `Object.setPrototypeOf(this, P)` or + * `this.__proto__ = P`, or null. */ +function resetTarget(lowerer: Lowerer, expr: ts.Expression): ts.Expression | null { + if ( + ts.isCallExpression(expr) && + expr.arguments.nodes.length === 2 && + expr.arguments.nodes[0]!.kind === ts.SyntaxKind.ThisKeyword && + ts.isPropertyAccessExpression(expr.expression) && + expr.expression.name.text === "setPrototypeOf" && + lowerer.isStdlibGlobal(expr.expression.expression, "Object") + ) + return expr.arguments.nodes[1]!; + if ( + ts.isBinaryExpression(expr) && + expr.operatorToken.kind === ts.SyntaxKind.EqualsToken && + ts.isPropertyAccessExpression(expr.left) && + expr.left.expression.kind === ts.SyntaxKind.ThisKeyword && + expr.left.name.text === "__proto__" + ) + return expr.right; + return null; +} + +/** The class constructor whose body holds `node`, crossing only statements + * and blocks (any nested function rebinds `this`). */ +function enclosingConstructor(node: ts.Node): ts.ConstructorDeclaration | null { + for (let cur = node.parent; cur !== undefined; cur = cur.parent) { + if (ts.isConstructorDeclaration(cur)) return cur; + if ( + ts.isFunctionLike(cur) || + ts.isClassDeclaration(cur) || + ts.isClassExpression(cur) || + ts.isSourceFile(cur) + ) + return null; + } + return null; +} + +/** Whether `node` denotes the prototype of the object `ctor` constructs: + * `new.target.prototype`, a const holding it, or the class's own + * `C.prototype` when no class extends C. */ +function ownPrototypeRef( + lowerer: Lowerer, + node: ts.Expression, + ctor: ts.ConstructorDeclaration, +): boolean { + while (ts.isParenthesizedExpression(node)) node = node.expression; + if (ts.isPropertyAccessExpression(node) && node.name.text === "prototype") { + const base = node.expression; + if ( + ts.isMetaProperty(base) && + base.keywordToken === ts.SyntaxKind.NewKeyword && + base.name.text === "target" + ) + return true; + const cls = ctor.parent; + if (!ts.isIdentifier(base) || !(ts.isClassDeclaration(cls) || ts.isClassExpression(cls))) + return false; + const symbol = lowerer.resolveValueSymbol(base); + const info = symbol ? lowerer.classBySymbol.get(symbol) : undefined; + if (!info || symbol!.valueDeclaration !== cls) return false; + for (const other of lowerer.classes.values()) { + if (other !== info && lowerer.isSubclassOf(other.def.name, info.def.name)) return false; + } + return true; + } + if (ts.isIdentifier(node)) { + const symbol = lowerer.resolveValueSymbol(node); + const decl = symbol?.valueDeclaration; + return ( + decl !== undefined && + ts.isVariableDeclaration(decl) && + decl.initializer !== undefined && + ts.isVariableDeclarationList(decl.parent) && + (decl.parent.flags & ts.NodeFlags.Const) !== 0 && + enclosingConstructor(decl) === ctor && + !ts.isIdentifier(decl.initializer) && + ownPrototypeRef(lowerer, decl.initializer, ctor) + ); + } + return false; +} + function isAssertionInitializer(node: ts.Expression): boolean { let e = node; while (ts.isParenthesizedExpression(e)) e = e.expression; diff --git a/packages/compiler/src/frontend/lowering/lower-stream.ts b/packages/compiler/src/frontend/lowering/lower-stream.ts index e9424aec0..eb919909b 100644 --- a/packages/compiler/src/frontend/lowering/lower-stream.ts +++ b/packages/compiler/src/frontend/lowering/lower-stream.ts @@ -49,6 +49,7 @@ import { sideEffectFreeOptionValue } from "./surfaces.js"; import { lowerDynObjectLiteral } from "./expressions/object-literals.js"; import { dynUndefinedExpr, varRef } from "../../ir/build.js"; import { genResultRecord } from "../type-mapper.js"; +import { requestGeneralStreamSurface } from "./general-streams.js"; import { extractIteratorValue, genStep, genValue, stepDrivable } from "./lower-generators.js"; import { BOOL, @@ -586,6 +587,33 @@ function dynOptionsValue(lowerer: Lowerer, arg: ts.Expression): IrExpr | null { return v.type.kind === "dyn" ? v : null; } +/** @types/node declares the transform/flush completion callback as + * `(error?: Error | null, data?: any) => void`. Outside objectMode Node + * accepts only a Buffer, a string or nothing as `data`, so the callback + * parameter is typed with that union while the option callback lowers: a + * checked-dynamic value passed as `data` converts at the call. Returns the + * pinned parameter symbol (the caller unpins it), or null when the + * declared type needs no pin. */ +function pinAnyDataCompletion( + lowerer: Lowerer, + which: string, + fnNode: ts.MethodDeclaration | ts.FunctionExpression | ts.ArrowFunction, +): ts.Symbol | null { + const index = which === "transform" ? 2 : which === "flush" ? 0 : -1; + const param = index < 0 ? undefined : fnNode.parameters.nodes[index]; + if (param === undefined || !ts.isIdentifier(param.name) || param.dotDotDotToken) return null; + const symbol = lowerer.checker.getSymbolAtLocation(param.name); + if (!symbol || lowerer.stageSourceTypes.has(symbol)) return null; + const declared = lowerer.paramShape(param).type; + if (declared.kind !== "func" || declared.rest || declared.params[1]?.kind !== "dyn") return null; + const data = unionOf(lowerer, [BYTES, STRING, { kind: "undefinedT" }]); + lowerer.stageSourceTypes.set( + symbol, + funcOf([declared.params[0]!, data, ...declared.params.slice(2)], declared.ret), + ); + return symbol; +} + /** Parses the options object literal of a stream constructor. `which` * names the callbacks this class accepts, in canonical flag order. */ function parseStreamOptions( @@ -671,22 +699,27 @@ function parseStreamOptions( continue; } const full = tuples[name]!.map((t) => (t === "fn" ? null : t)); - // The completion-callback tail: typed by the checker contextually; - // accept the user's declared func type as the tuple's entry so the - // prefix check compares like with like. - const { funcType } = lowerer.lambdaSignature(fnNode); - const tuple: IrType[] = full.map((t, i) => { - if (t !== null) return t; - const declared = funcType.params[i]; - if (declared !== undefined && declared.kind !== "func" && declared.kind !== "dyn") { - lowerer.noLowering( - `a '${name}' callback whose parameter ${i} is '${lowerer.fmt(declared)}' where Node passes the completion callback`, - fnNode!, - ); - } - return declared ?? funcOf([], VOID); - }); - present.set(name, lowerStreamCallback(lowerer, name, fnNode, thisType, tuple)); + const pinned = pinAnyDataCompletion(lowerer, name, fnNode); + try { + // The completion-callback tail: typed by the checker contextually; + // accept the user's declared func type as the tuple's entry so the + // prefix check compares like with like. + const { funcType } = lowerer.lambdaSignature(fnNode); + const tuple: IrType[] = full.map((t, i) => { + if (t !== null) return t; + const declared = funcType.params[i]; + if (declared !== undefined && declared.kind !== "func" && declared.kind !== "dyn") { + lowerer.noLowering( + `a '${name}' callback whose parameter ${i} is '${lowerer.fmt(declared)}' where Node passes the completion callback`, + fnNode!, + ); + } + return declared ?? funcOf([], VOID); + }); + present.set(name, lowerStreamCallback(lowerer, name, fnNode, thisType, tuple)); + } finally { + if (pinned) lowerer.stageSourceTypes.delete(pinned); + } continue; } // `{ signal }` shorthand: the binding is the value. @@ -2044,6 +2077,24 @@ function lowerStreamArg( const v = isHashValueType(lowered.type) ? hashStreamOf(lowered, what === "pipeline" || what === "compose") : lowered; + // A checked-dynamic pipeline stage (an untyped source or destination): + // a boxed native stream unwraps at run time; other values (iterables, + // functions) throw the not-supported Error there. + if (v.type.kind === "dyn" && what === "pipeline") { + return { + kind: "libCall", + fn: "stream.unboxDyn", + args: [ + v, + strLit( + "pipeline stages other than native streams (iterables, generators, plain functions, and { readable, writable } pairs) are not supported yet", + locOf(node), + ), + ], + type: { kind: "object", className: "%Duplex" }, + loc: locOf(node), + }; + } const info = v.type.kind === "object" ? lowerer.classes.get(v.type.className) : undefined; if (!streamSidesOf(lowerer, info)) { // A provably-non-stream value in a JS source (the invalid-input @@ -3296,6 +3347,124 @@ function pipeEndOption(lowerer: Lowerer, options: ts.Expression | undefined, loc return end; } +/** `readable.pipe(process.stdout)`: the process stream joins the pipe as + * an fd-backed Writable (stream.stdioWritable), and — like Node, which + * never ends process.stdout or process.stderr from a pipe — the source's + * end does not end it. pipe() answers the process stream itself. */ +function pipeIntoStdio( + lowerer: Lowerer, + call: ts.CallExpression, + access: ts.PropertyAccessExpression, + target: IrExpr, +): IrExpr { + const loc = locOf(call); + // JS order: the receiver, then the destination, then the options. + const receiverValue = lowerer.lowerExpr(access.expression); + const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type); + const stdio = lowerer.declareHiddenLocal("%pipeStdio", target.type); + const options = call.arguments.nodes[1]; + const stmts: IrStmt[] = [ + { kind: "varDecl", localId: source.id, init: receiverValue, loc }, + { kind: "varDecl", localId: stdio.id, init: target, loc }, + ]; + // The options literal still evaluates; its end flag has no effect here. + if (options !== undefined) { + stmts.push({ kind: "exprStmt", expr: pipeEndOption(lowerer, options, loc), loc }); + } + const receiver: IrExpr = { kind: "varRef", localId: source.id, type: receiverValue.type, loc }; + const writable: IrType = { kind: "object", className: "%Writable" }; + stmts.push({ + kind: "exprStmt", + expr: { + kind: "libCall", + fn: "readable.pipe", + args: [ + receiver, + { + kind: "libCall", + fn: "stream.stdioWritable", + args: [{ kind: "varRef", localId: stdio.id, type: target.type, loc }], + type: writable, + loc, + }, + boolLit(false, loc), + ], + type: writable, + loc, + }, + loc, + }); + return { + kind: "seqExpr", + stmts, + result: { kind: "varRef", localId: stdio.id, type: target.type, loc }, + type: target.type, + loc, + }; +} + +/** The pipe() libCall for a destination of type `dst`. Under the general + * stream representation a Writable slot can hold the converted + * process.stdout / process.stderr, which a pipe never ends (as in Node), so + * the pipe takes readable.pipeGeneral, which checks for them. */ +function generalPipe(lowerer: Lowerer, dst: IrType): "readable.pipe" | "readable.pipeGeneral" { + return lowerer.generalNodeStreams && dst.kind === "object" && dst.className === "%Writable" + ? "readable.pipeGeneral" + : "readable.pipe"; +} + +/** `readable.pipe(untyped)`: a checked-dynamic destination unwraps a boxed + * native stream at run time (stream.unboxDyn; other values throw the + * not-supported Error), and pipe() answers the destination value itself. */ +function pipeIntoDyn( + lowerer: Lowerer, + call: ts.CallExpression, + access: ts.PropertyAccessExpression, + target: IrExpr, +): IrExpr { + const loc = locOf(call); + const receiverValue = lowerer.lowerExpr(access.expression); + const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type); + const destination = lowerer.declareHiddenLocal("%pipeDestination", target.type); + const stmts: IrStmt[] = [ + { kind: "varDecl", localId: source.id, init: receiverValue, loc }, + { kind: "varDecl", localId: destination.id, init: target, loc }, + ]; + const end = pipeEndOption(lowerer, call.arguments.nodes[1], loc); + const duplex: IrType = { kind: "object", className: "%Duplex" }; + stmts.push({ + kind: "exprStmt", + expr: { + kind: "libCall", + fn: lowerer.generalNodeStreams ? "readable.pipeGeneral" : "readable.pipe", + args: [ + { kind: "varRef", localId: source.id, type: receiverValue.type, loc }, + { + kind: "libCall", + fn: "stream.unboxDyn", + args: [ + { kind: "varRef", localId: destination.id, type: target.type, loc }, + strLit("pipe destinations other than native streams are not supported yet", loc), + ], + type: duplex, + loc, + }, + end, + ], + type: duplex, + loc, + }, + loc, + }); + return { + kind: "seqExpr", + stmts, + result: { kind: "varRef", localId: destination.id, type: target.type, loc }, + type: target.type, + loc, + }; +} + export function lowerStreamMethodCall( lowerer: Lowerer, call: ts.CallExpression, @@ -3545,22 +3714,26 @@ export function lowerStreamMethodCall( loc, }; } - const dst = lowerer.lowerExpr(args[0]!); + const target = lowerer.lowerExpr(args[0]!); + if (target.type.kind === "procStream") return pipeIntoStdio(lowerer, call, access, target); + if (target.type.kind === "dyn") return pipeIntoDyn(lowerer, call, access, target); + const dst = target; const dstInfo = dst.type.kind === "object" ? lowerer.classes.get(dst.type.className) : undefined; const dstSides = streamSidesOf(lowerer, dstInfo); if (dstSides !== "w" && dstSides !== "rw") { + requestGeneralStreamSurface(lowerer, args[0]!); lowerer.noLowering( `pipe into a '${lowerer.fmt(dst.type)}'`, args[0]!, - "the destination must be a stream Writable/Duplex (process streams and sockets are not pipe destinations yet)", + "the destination must be a stream Writable/Duplex, process.stdout or process.stderr (sockets are not pipe destinations yet)", ); } const end = pipeEndOption(lowerer, args[1], loc); const receiver = lowerer.lowerExpr(access.expression); return { kind: "libCall", - fn: "readable.pipe", + fn: generalPipe(lowerer, dst.type), args: [receiver, dst, end], type: dst.type, loc, diff --git a/packages/compiler/src/frontend/lowering/lowerer.ts b/packages/compiler/src/frontend/lowering/lowerer.ts index 1c2dea445..ecd511495 100644 --- a/packages/compiler/src/frontend/lowering/lowerer.ts +++ b/packages/compiler/src/frontend/lowering/lowerer.ts @@ -1,5 +1,8 @@ +import { onlyForwarded } from "./typed-arguments.js"; +import { needsGeneralNodeStreams, stdioIntoGeneralStream } from "./general-streams.js"; import { extendAssertedRecordMembers } from "./assertion-members.js"; import { jsDynamicDeclarations } from "./js-dynamic-objects.js"; +import { builtinClassValue, builtinMemberClassKind } from "./builtins/builtin-class-dyn.js"; import { lifetimeRegionType, lowerLifetimeRegionCall, @@ -30,8 +33,13 @@ import { isSettledIteratorValueRead } from "./lower-generators.js"; import { concreteCollectionNarrow } from "./collection-narrowing.js"; import { lowerWorkerMetadata } from "./builtins/workers.js"; import { fenceStaticBlobMember, lowerBlobNew, lowerStaticBlobCall } from "./builtins/blob.js"; -import { refuseWebAssemblyUse } from "./builtins/webassembly.js"; +import { + lowerWebAssemblyCall, + lowerWebAssemblyNew, + refuseWebAssemblyUse, +} from "./builtins/webassembly.js"; import { discoverWasmModules, type WasmModuleReport } from "../../wasm/discover.js"; +import { encodeBase64 } from "../../wasm/base64.js"; import { resolveRequireRuntime } from "../runtime-resolve.js"; import { lowerKeyObjectCall } from "./builtins/key-object.js"; import { fenceWebCryptoMember, lowerWebCryptoCall } from "./builtins/webcrypto.js"; @@ -186,6 +194,7 @@ import type { IrGlobal, IrLocal, IrModule, + IrWasmModule, IrParam, IrRecordShape, IrStmt, @@ -881,6 +890,10 @@ export interface LowererMode { /** Statically resolved child_process.fork program roots, in stable target-id order. */ forkTargets?: readonly ts.SourceFile[]; frontendServices?: FrontendServices | undefined; + /** The program's general stream representation (TypeMapperCtx. + * generalNodeStreams). lowerToIr turns it on only after a pass without + * it saw a stream flow that needs it (requiresGeneralNodeStreams). */ + generalNodeStreams?: boolean; /** LoadResult.inlineRequireCycleCalls. */ inlineRequireCycleCalls?: ReadonlySet | undefined; /** LowerOptions.libraryCallbacks (see there). */ @@ -1041,10 +1054,40 @@ export function lowerToIr( for (const d of extraModuleCycleDiags) reachableEmit.pushDiag(d); for (const d of ffiValidation.diagnostics) reachableEmit.pushDiag(d); const emitted = reachableEmit.emitReachable(options.libRoots); - const { reachable } = emitted; + let { reachable } = emitted; let result = emitted.result; let resultLowerer = reachableEmit; timing("reachable-emit", { reachable: reachable.size }); + // The general stream representation (TypeMapperCtx.generalNodeStreams) + // is a per-program decision: only a program whose reachable code moved + // a general stream into a stdio-represented stream slot lowers again + // with it. Every other program keeps the single pass above unchanged. + const generalNodeStreams = reachableEmit.requiresGeneralNodeStreams; + if (generalNodeStreams) { + const general = new Lowerer(program, entry, moduleOrder, { + frontendServices: options.frontendServices, + projectCheckJs: options.projectCheckJs ?? false, + targetPlatform, + startupCrash, + inlineRequireCycleCalls, + ffiImports, + libraryCallbacks, + forkTargets, + workerTargets, + externalTypes, + externalTypeSpecifiersByFile, + tierMode, + ffiBindingSymbols: ffiValidation.symbolsByName, + generalNodeStreams: true, + }); + for (const d of extraModuleCycleDiags) general.pushDiag(d); + for (const d of ffiValidation.diagnostics) general.pushDiag(d); + const generalEmitted = general.emitReachable(options.libRoots); + reachable = generalEmitted.reachable; + result = generalEmitted.result; + resultLowerer = general; + timing("general-streams-relower", { reachable: reachable.size }); + } // A generic class-rest support decision can depend on record metadata // whose historical owner is discovered only while retained bodies lower. // If the settled answer is a fence, rerun the ordinary reachable emit so @@ -1052,10 +1095,11 @@ export function lowerToIr( // declarators stay unvisited, bindings block, cascades and stats match the // historical compiler. This is a rare compatibility fallback; programs // without such a settled fence retain checker-backed IR exactly once. - if (reachableEmit.requiresHistoricalOrderRelower) { + if (resultLowerer.requiresHistoricalOrderRelower) { const emit = new Lowerer(program, entry, moduleOrder, { frontendServices: options.frontendServices, projectCheckJs: options.projectCheckJs ?? false, + ...(generalNodeStreams ? { generalNodeStreams: true } : {}), reachable, targetPlatform, startupCrash, @@ -1111,25 +1155,70 @@ export function lowerToIr( diagnostics: [...result.diagnostics, ...contracts.diagnostics], }; else if (contracts.count > 0) result = { ...result, contracts }; + const discoverModules = ( + onModule?: (sha256: string, bytes: Uint8Array) => void, + ): WasmModuleReport[] => + discoverWasmModules({ + files: moduleOrder.includes(entry) ? moduleOrder : [...moduleOrder, entry], + entry: entry.fileName, + configured: options.wasmFiles ?? [], + resolveRequest: (fromFile, specifier) => { + const resolved = resolveRequireRuntime( + fromFile, + specifier, + targetPlatform, + undefined, + options.frontendServices, + ); + return resolved.ok ? resolved.value : null; + }, + ...(onModule === undefined ? {} : { onModule }), + }); + // A program that uses the WebAssembly API carries every module the build + // can see and translate (wasm/translate.ts); the rest fail at run time + // with the CompileError for untranslated bytes. + if (result.module !== null && resultLowerer.usesWebAssembly) { + const bytesByHash = new Map(); + const reports = discoverModules((sha256, bytes) => bytesByHash.set(sha256, bytes)); + const wasmModules: IrWasmModule[] = []; + for (const report of reports) { + const bytes = bytesByHash.get(report.sha256); + if (report.status !== "valid" || bytes === undefined) continue; + wasmModules.push({ sha256: report.sha256, bytes: encodeBase64(bytes) }); + } + result.module.wasmModules = wasmModules; + if (resultLowerer.usesWasmCustomSections) result.module.wasmCustomSections = true; + timing("wasm-discovery", { modules: wasmModules.length }); + } if (options.coverage !== true) return result; - const remainder = new Lowerer(program, entry, moduleOrder, { - frontendServices: options.frontendServices, - projectCheckJs: options.projectCheckJs ?? false, - reachable, - remainder: true, - alreadyFlushed: resultLowerer.flushedSymbols, - inlineRequireCycleCalls, - targetPlatform, - ffiImports, - libraryCallbacks, - forkTargets, - workerTargets, - ffiBindingSymbols: ffiValidation.symbolsByName, - externalTypes, - externalTypeSpecifiersByFile, - tierMode, - }); - const rem = remainder.run(); + const remainderPass = (general: boolean): Lowerer => + new Lowerer(program, entry, moduleOrder, { + frontendServices: options.frontendServices, + projectCheckJs: options.projectCheckJs ?? false, + ...(general ? { generalNodeStreams: true } : {}), + reachable, + remainder: true, + alreadyFlushed: resultLowerer.flushedSymbols, + inlineRequireCycleCalls, + targetPlatform, + ffiImports, + libraryCallbacks, + forkTargets, + workerTargets, + ffiBindingSymbols: ffiValidation.symbolsByName, + externalTypes, + externalTypeSpecifiersByFile, + tierMode, + }); + let remainder = remainderPass(generalNodeStreams); + let rem = remainder.run(); + // Unreached code reports what it would compile to once reached: a + // stream flow there that needs the general representation lowers the + // remainder again with it, as reachable emit would. + if (!generalNodeStreams && remainder.requiresGeneralNodeStreams) { + remainder = remainderPass(true); + rem = remainder.run(); + } timing("coverage-remainder"); // Tiers (tier-analysis.ts): reached statements in dynamic-tier functions, // and with tierReport the report-only demotion analysis. @@ -1164,21 +1253,7 @@ export function lowerToIr( }, }; if (tiers !== undefined) covered.tiers = tiers; - const wasmModules = discoverWasmModules({ - files: moduleOrder.includes(entry) ? moduleOrder : [...moduleOrder, entry], - entry: entry.fileName, - configured: options.wasmFiles ?? [], - resolveRequest: (fromFile, specifier) => { - const resolved = resolveRequireRuntime( - fromFile, - specifier, - targetPlatform, - undefined, - options.frontendServices, - ); - return resolved.ok ? resolved.value : null; - }, - }); + const wasmModules = discoverModules(); timing("wasm-discovery", { modules: wasmModules.length }); if (wasmModules.length > 0) covered.wasmModules = wasmModules; return covered; @@ -1929,6 +2004,18 @@ export class Lowerer { * type parameters are bound to `unknown`, so lambdaSignature admits * them. */ readonly erasingLambdas = new Set(); + /** Function expressions lowered against a fixed target signature with a + * tuple-typed `arguments` (typed-arguments.ts). */ + readonly typedArgumentsLambdas = new Set(); + /** Const bindings holding a forwarded fixed tuple (`const args = + * arguments as any` in a typed-arguments function) → the tuple type. */ + readonly tupleAliasSymbols = new Map(); + /** `??` expressions whose result is the optional callback's own function + * type (an adapted function default); their bindings take that type. */ + readonly nullishFuncResults = new Set(); + /** The static names of the current generic instance's name-keyed + * function parameters (static-function-names.ts). */ + staticFnNames: Map | null = null; /** Nesting depth of erased generic bodies being lowered (erased lambdas * and erased instances). */ erasingDepth = 0; @@ -2030,7 +2117,9 @@ export class Lowerer { /** A pipeline() function stage's `source` parameter: the IR type of what * the pipeline passes it (the previous stage as an async iterable), set * while the stage lowers. Parameter typing and `for await` heads read - * it before the checker's `AsyncIterable`. */ + * it before the checker's `AsyncIterable`. A stream option callback's + * completion parameter declared with an any-typed `data` is pinned here + * too while the callback lowers (pinAnyDataCompletion). */ readonly stageSourceTypes = new Map(); /** Set when a match result lowers to execGroups/matchGroups, the inputs * of regex span folding. */ @@ -2508,6 +2597,12 @@ export class Lowerer { /** Settled generic class-rest metadata requires the historical emit * fallback so its fence can poison the original statement atomically. */ requiresHistoricalOrderRelower = false; + /** A general stream value (a runtime stream class instance) reached a + * slot the child/process stdio handles represent — NodeJS.ReadableStream, + * NodeJS.WritableStream, or @types/node's stream.Readable/Writable — or + * a stdio handle reached an 'unknown' slot. lowerToIr then lowers the + * program again under the general stream representation. */ + requiresGeneralNodeStreams = false; /** Helpers that snapshot shape declaration order into their bodies. * Reachability lowers inits before the declarations they discover, so * these rebuild after the worklist restores historical shape metadata. */ @@ -2762,6 +2857,12 @@ export class Lowerer { readonly workerTargets: readonly ts.SourceFile[]; readonly workerTargetIdByPath = new Map(); usesWorkers = false; + /** The program uses the WebAssembly API (builtins/webassembly.ts): the + * build translates the modules it discovers. */ + usesWebAssembly = false; + /** The program calls WebAssembly.Module.customSections: translated + * modules keep their custom sections. */ + usesWasmCustomSections = false; /** The program constructs a LifetimeRegion (lifetime-regions.ts). */ usesLifetimeRegions = false; /** Per-directory answers of experimental-import.ts's declaration-file test. */ @@ -2963,6 +3064,7 @@ export class Lowerer { * refuse and fence exactly as before. Stage S6 demotes the units of * committed refusals in "auto" and keeps them refusals in "static-only". */ readonly tierMode: TierMode; + readonly generalNodeStreams: boolean; /** Functions finishModule placed in the dynamic tier (ir/tiers.ts). */ dynamicFunctions: DynamicFunction[] = []; /** Their IR, for coverage's dynamic statement count. */ @@ -3091,6 +3193,7 @@ export class Lowerer { this.startupCrash = mode.startupCrash ?? null; this.targetPlatform = mode.targetPlatform ?? process.platform; this.tierMode = mode.tierMode ?? "auto"; + this.generalNodeStreams = mode.generalNodeStreams ?? false; this.workerTargets = mode.workerTargets ?? []; this.workerTargets.forEach((sf, id) => { this.workerTargetIdByPath.set(tsgoPath(resolve(sf.fileName)), id); @@ -3187,6 +3290,7 @@ export class Lowerer { isExternalTypeFile: (sf) => this.externalTypeSpecifiersByFile.has(tsgoPath(resolve(sf.fileName))), typeMemo: this.typeMemo, + ...(this.generalNodeStreams ? { generalNodeStreams: true } : {}), canMemoizeType: () => this.typeParamBindings === null && this.typeParamTsBindings === null && @@ -8471,6 +8575,8 @@ export class Lowerer { * validator ICEs on them as the usual backstop. */ requireExactShape(node: ts.Node, actual: IrType, expected: IrType): void { if (typeEquals(actual, expected)) return; + if (!this.generalNodeStreams && needsGeneralNodeStreams(this, actual, expected)) + this.requiresGeneralNodeStreams = true; // dyn mismatches first. A dyn ('unknown') value flowing into a typed // slot needs a CHECKED cast — the hint points at `as `; tsc // usually rejects this before we do, so the fence is mostly defensive. @@ -8688,6 +8794,9 @@ export class Lowerer { } if (expr.type.kind === "void" && expected.kind !== "void" && this.neverValued.has(expr)) return this.divergentValue(expr, expected); + // process.stdout/stderr into a general Writable slot (general-streams.ts). + const stdioStream = stdioIntoGeneralStream(this, expr, expected); + if (stdioStream) return this.coerceToExpected(stdioStream, expected); // Iterator-typed slots: native iterators and differently typed // generators step through an adapter generator. if (expected.kind === "generator" && !typeEquals(expr.type, expected)) { @@ -9723,6 +9832,8 @@ export class Lowerer { node = node.expression; if (expected) { if (ts.isConditionalExpression(node)) return lowerTernary(this, node, expected); + const escaped = this.neverAssertionInto(node, expected); + if (escaped) return escaped; const fresh = this.emptyCollectionFor(node, expected); if (fresh) return this.coerceInto(node, fresh, expected); } @@ -10636,6 +10747,14 @@ export class Lowerer { return findMethodOn(this, info, name); } + /** A class whose root is the runtime's %Error (builtin errors and their + * program subclasses). */ + isErrorRootedClass(className: string): boolean { + let info = this.classes.get(className) ?? null; + while (info && info.base) info = info.base; + return info?.def.name === "%Error"; + } + isSubclassOf(sub: string, sup: string): boolean { return isSubclassOf(this, sub, sup); } @@ -10922,6 +11041,108 @@ export class Lowerer { return declareContextLocal(this.ctx, name, type, false, undefined, undefined); } + /** The body binding of a fixed-tuple rest parameter: one native slot per + * position (the flattened ABI), rebuilt into the tuple the source names. + * The empty tuple rides the empty-array representation. */ + declareRestTupleParam( + decl: ts.ParameterDeclaration, + nameNode: ts.Identifier, + elemShapes: readonly ParamShape[], + params: IrParam[], + prologue: IrStmt[], + ): void { + const loc = locOf(decl); + const name = nameNode.text; + const fn = decl.parent; + const symbol = this.checker.getSymbolAtLocation(nameNode); + const isRead = (id: ts.Identifier): boolean => + id !== nameNode && this.checker.getSymbolAtLocation(id) === symbol; + const pure = fn !== undefined && symbol !== undefined && onlyForwarded(this, fn, isRead); + // A forwarded-only tuple is never built: a tuple with optional + // positions (`Parameters<(n?: T) => R>`, whose length varies per call) + // forwards its slots, an omitted position as undefined — which a + // callee's default treats exactly as an omitted argument. Its length + // is the one read that would observe the difference. + const tupleType = + pure && + elemShapes.length > 0 && + this.mapTypeOf(this.typeOf(nameNode)) === null && + !readsLength(fn!, isRead) + ? this.forwardedSlotsTuple(elemShapes) + : this.irTypeOf(nameNode); + const slots = elemShapes.map((shape, i) => { + const slot = this.declareHiddenLocal(`%${name}.${i}`, shape.type); + params.push({ localId: slot.id, name: `%${name}.${i}`, type: shape.type }); + return slot; + }); + const body = this.declareLocal(nameNode, name, tupleType, true); + if (pure) { + this.ctx.pureTuples.set(body.id, slots); + return; + } + const init = this.tupleOfSlots(slots, tupleType, nameNode, loc); + prologue.push({ kind: "varDecl", localId: body.id, init, loc }); + } + + /** `value as never` flowing into a typed slot: `never` is assignable to + * every type, so the assertion promises the slot's type. A dynamic value + * takes the checked extraction to it, as `value as T` would. Null for + * every other form, and for numeric, dynamic and union slots, which + * keep the existing lowering. */ + private neverAssertionInto(node: ts.Expression, expected: IrType): IrExpr | null { + if (!(ts.isAsExpression(node) || ts.isTypeAssertion(node))) return null; + if (expected.kind === "f64" || expected.kind === "dyn" || expected.kind === "union") + return null; + if (!(this.checker.getTypeFromTypeNode(node.type).flags & ts.TypeFlags.Never)) return null; + const innerTs = this.typeOf(node.expression); + if (!(innerTs.flags & ts.TypeFlags.Any) && this.mapTypeOf(innerTs)?.kind !== "dyn") return null; + if ( + !canDynCheckTo( + expected, + (id) => this.shapes.get(id), + (id) => this.unions.get(id), + ) + ) + return null; + const inner = this.lowerExpr(node.expression); + if (inner.type.kind !== "dyn") return null; + return { kind: "dynCheck", value: inner, type: expected, loc: locOf(node) }; + } + + /** The tuple record of a forwarded-only rest tuple's native slots. */ + private forwardedSlotsTuple(elemShapes: readonly ParamShape[]): IrType { + const fields = elemShapes.map((shape, i) => ({ name: String(i), type: shape.type })); + fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + return { kind: "record", shapeId: this.shapes.intern(fields, true) }; + } + + /** A fresh tuple holding the given positional slots, typed `tupleType` + * (a tuple record, or the empty-array form of `[]`). */ + tupleOfSlots(slots: readonly IrLocal[], tupleType: IrType, blame: ts.Node, loc: SrcLoc): IrExpr { + if (slots.length === 0) { + if (tupleType.kind !== "array") this.badType(blame, this.typeOf(blame)); + return { kind: "arrayLit", elems: [], type: tupleType, loc }; + } + const shape = tupleType.kind === "record" ? this.shapes.get(tupleType.shapeId) : undefined; + if (!shape?.tuple || shape.fields.length !== slots.length) + this.badType(blame, this.typeOf(blame)); + return { + kind: "recordLit", + fields: slots.map((slot, i) => { + const field = shape.fields.find((f) => f.name === String(i))!; + return { + name: field.name, + value: this.coerceToExpected( + { kind: "varRef", localId: slot.id, type: slot.type, loc }, + field.type, + ), + }; + }), + type: tupleType, + loc, + }; + } + /** Declares a callee's parameter locals from its ParamShapes and builds * the DEFAULT-PARAM PROLOGUE. Required/optional/rest params bind their * symbol directly (one local of the ABI type). A defaulted param `x: T = e` @@ -10958,6 +11179,17 @@ export class Lowerer { return defaultAfterUndefined(undefinedValue, this.coerceInto(node, absent, expected)); }; decls.forEach((decl, i) => { + // A fixed-tuple rest parameter owns every remaining (flattened) + // shape, possibly none for `[]` (restTupleShapes). + if ( + decl.dotDotDotToken !== undefined && + ts.isIdentifier(decl.name) && + i === decls.length - 1 && + (shapes[i] === undefined ? shapes.length === i : shapes[i]!.restTuple === true) + ) { + this.declareRestTupleParam(decl, decl.name, shapes.slice(i), params, prologue); + return; + } const shape = shapes[i]!; if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) { // Pattern parameter: one hidden ABI slot carries the source value; @@ -11289,6 +11521,13 @@ export class Lowerer { } if (!symbol) return null; const direct = this.resolveKey(symbol, ident); + if (direct && this.ctx.pureTuples.has(direct.id)) { + // onlyForwarded proved every read forwards; a plain read here means + // the analysis and the lowering disagree. + throw new InternalCompilerError( + `lowerer bug: forwarded-only tuple '${ident.text}' read as a value`, + ); + } if (direct) return direct; // A PARAMETER PROPERTY declares two symbols: references resolve to the // PARAMETER symbol, while the declaration's name binds the PROPERTY @@ -11318,8 +11557,8 @@ export class Lowerer { /** Lexical `this` — the enclosing method's this-param, possibly captured * through arrows (function expressions/declarations reset `this` in JS; * their bodies never see an enclosing method's binding). */ - resolveThis(): IrLocal | null { - return this.resolveKey(undefined); + resolveThis(blame?: ts.Node): IrLocal | null { + return this.resolveKey(undefined, blame); } peekLocal(ident: ts.Identifier): IrLocal | null { @@ -11961,6 +12200,8 @@ export class Lowerer { // dispatch. The general identifier-call paths have no lowering for a // promise-returning ambient global, and `import` is a keyword callee no // identifier path matches. + const webAssembly = lowerWebAssemblyCall(this, expr); + if (webAssembly !== null) return webAssembly; refuseWebAssemblyUse(this, expr.expression); return ( lowerLifetimeRegionCall(this, expr) ?? @@ -12189,6 +12430,8 @@ export class Lowerer { } lowerNew(expr: ts.NewExpression): IrExpr { + const webAssembly = lowerWebAssemblyNew(this, expr); + if (webAssembly !== null) return webAssembly; refuseWebAssemblyUse(this, expr.expression, "new "); const builtin = lowerLifetimeRegionNew(this, expr) ?? @@ -12601,6 +12844,12 @@ export class Lowerer { } // A bare `fs.constants` read (not one of the baked bits above). if (bi.member === "constants" && bi.module === "fs") return fsConstantsObject(loc); + // `stream.Readable` as a JavaScript value: the runtime's untyped + // constructor, the base a constructor function inherits. + if (isJsSourceFile(expr.getSourceFile())) { + const classKind = builtinMemberClassKind(bi.module, bi.member); + if (classKind !== null) return builtinClassValue(classKind, loc); + } if (builtinModuleFnOf(this, bi.module, bi.member)) { this.unsupported( "SC1090", @@ -13150,6 +13399,31 @@ export class Lowerer { } } +/** Whether some read of a binding (identified by `isRead`) in `fn` takes + * its `.length`. */ +function readsLength(fn: ts.Node, isRead: (id: ts.Identifier) => boolean): boolean { + let found = false; + ts.walkPreorder(fn, (n) => { + if (found) return "stop"; + if (!ts.isIdentifier(n) || !isRead(n)) return undefined; + let top: ts.Node = n; + while ( + top.parent && + (ts.isParenthesizedExpression(top.parent) || + ts.isAsExpression(top.parent) || + ts.isTypeAssertion(top.parent) || + ts.isSatisfiesExpression(top.parent) || + ts.isNonNullExpression(top.parent)) + ) + top = top.parent; + const p = top.parent; + if (p && ts.isPropertyAccessExpression(p) && p.expression === top && p.name.text === "length") + found = true; + return undefined; + }); + return found; +} + /** A union of record layouts flowing into one record slot: a function * returning differently-shaped object literals (`{ ok: false }` and * `{ ok: true, size }`, whose union the checker normalizes to arms with diff --git a/packages/compiler/src/frontend/lowering/static-function-names.ts b/packages/compiler/src/frontend/lowering/static-function-names.ts new file mode 100644 index 000000000..d86e55a80 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/static-function-names.ts @@ -0,0 +1,219 @@ +import * as ts from "../ts7/adapter.js"; +import { isJsSourceFile } from "../program.js"; +import type { Lowerer } from "./lowerer.js"; +import type { GenericFnInfo } from "./generic-functions.js"; +import { stripTypeWrappers } from "./typed-arguments.js"; + +/** `fn.name` inside generic higher-order functions. + * + * Native closures carry no name, but a generic wrapper is instantiated per + * call site anyway: when its body reads `.name` of a function parameter, + * the instantiation key also carries the static name of that call's + * argument (the function declaration's name, a const binding's inferred + * name, the name of the function a wrapper call returns), and the read + * folds to that string. A call whose argument's name is only known at run + * time keeps a precise refusal at the read. */ + +/** Parameter index → symbol for the parameters whose `.name` the generic + * body reads (and never reassigns). Computed once per generic. */ +export function nameReadParams(lowerer: Lowerer, info: GenericFnInfo): Map { + if (info.nameReadParams) return info.nameReadParams; + const out = new Map(); + // JavaScript generics read function names through the checked-value + // box, which carries the runtime name already. + if (isJsSourceFile(info.decl.getSourceFile())) { + info.nameReadParams = out; + return out; + } + const bySymbol = new Map(); + info.decl.parameters.nodes.forEach((param, i) => { + if (!ts.isIdentifier(param.name) || param.dotDotDotToken) return; + if (!functionTypedParameter(lowerer, param)) return; + const symbol = lowerer.checker.getSymbolAtLocation(param.name); + if (symbol) bySymbol.set(symbol, i); + }); + if (bySymbol.size > 0) { + const written = new Set(); + const read = new Set(); + ts.walkPreorder(info.decl, (node) => { + if (ts.isTypeNode(node)) return "skip"; + if ( + ts.isPropertyAccessExpression(node) && + node.name.text === "name" && + ts.isIdentifier(node.expression) + ) { + const symbol = lowerer.checker.getSymbolAtLocation(node.expression); + if (symbol && bySymbol.has(symbol)) read.add(symbol); + } + if ( + ts.isBinaryExpression(node) && + node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && + node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && + ts.isIdentifier(node.left) + ) { + const symbol = lowerer.checker.getSymbolAtLocation(node.left); + if (symbol) written.add(symbol); + } + return undefined; + }); + for (const symbol of read) { + if (!written.has(symbol)) out.set(bySymbol.get(symbol)!, symbol); + } + } + info.nameReadParams = out; + return out; +} + +/** A parameter declared with a function type, or with a type parameter + * constrained to one (`fn: F` where `F extends (...args: any) => any`). */ +function functionTypedParameter(lowerer: Lowerer, param: ts.ParameterDeclaration): boolean { + const t = lowerer.typeOf(param.name); + if (lowerer.checker.getCallSignatures(t).length > 0) return true; + if (!(t.flags & ts.TypeFlags.TypeParameter)) return false; + const symbol = t.getSymbol(); + const decl = symbol ? symbol.declarations.find(ts.isTypeParameterDeclaration) : undefined; + if (!decl?.constraint) return false; + const constraint = lowerer.checker.getTypeFromTypeNode(decl.constraint); + return lowerer.checker.getCallSignatures(constraint).length > 0; +} + +/** The instantiation key suffix and name bindings of one call of `info`, + * or null when the body reads no parameter's name. */ +export function staticNameBindings( + lowerer: Lowerer, + call: ts.CallExpression, + info: GenericFnInfo, +): { key: string; names: Map } | null { + const params = nameReadParams(lowerer, info); + if (params.size === 0) return null; + const names = new Map(); + const parts: string[] = []; + for (const [index, symbol] of params) { + const arg = call.arguments.nodes[index]; + const name = arg && !ts.isSpreadElement(arg) ? staticFunctionName(lowerer, arg) : null; + names.set(symbol, name); + parts.push(name === null ? "?" : JSON.stringify(name)); + } + return { key: `@name(${parts.join(",")})`, names }; +} + +/** The `name` JavaScript gives the function `expr` evaluates to, when it is + * statically known; null otherwise. */ +export function staticFunctionName(lowerer: Lowerer, expr: ts.Expression): string | null { + return staticNameOf(lowerer, expr, new Set()); +} + +function staticNameOf(lowerer: Lowerer, expr: ts.Expression, seen: Set): string | null { + const e = stripTypeWrappers(expr); + if (seen.has(e)) return null; + seen.add(e); + // An anonymous function as a call argument gets no inferred name. + if (ts.isFunctionExpression(e) || ts.isArrowFunction(e)) { + return !ts.isArrowFunction(e) && e.name ? e.name.text : ""; + } + if (ts.isIdentifier(e)) { + const symbol = lowerer.resolveValueSymbol(e); + if (!symbol) return null; + const bound = lowerer.staticFnNames?.get(symbol); + if (bound !== undefined) return bound; + const decl = symbol.valueDeclaration; + if (decl === undefined) return null; + if (ts.isFunctionDeclaration(decl)) return decl.name ? decl.name.text : "default"; + if ( + ts.isVariableDeclaration(decl) && + ts.isIdentifier(decl.name) && + decl.initializer !== undefined && + (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 + ) { + const init = stripTypeWrappers(decl.initializer); + // `const f = () => …` / `const f = function () {}`: the binding names + // an anonymous function definition. + if (ts.isArrowFunction(init)) return decl.name.text; + if (ts.isFunctionExpression(init)) return init.name ? init.name.text : decl.name.text; + return staticNameOf(lowerer, init, seen); + } + return null; + } + if (ts.isCallExpression(e) && ts.isIdentifier(e.expression)) { + // A call of a generic higher-order function returns the function its + // body returns: every `return` names the same anonymous definition or + // the same local const binding. + const symbol = lowerer.resolveValueSymbol(e.expression); + const info = symbol ? lowerer.genericFnsBySymbol.get(symbol) : undefined; + if (!info) return null; + return returnedFunctionName(lowerer, info.decl, seen); + } + if (ts.isPropertyAccessExpression(e)) { + const symbol = lowerer.checker.getSymbolAtLocation(e.name); + const decl = symbol ? symbol.valueDeclaration : undefined; + if (decl && ts.isMethodDeclaration(decl) && ts.isIdentifier(decl.name)) return decl.name.text; + return null; + } + return null; +} + +function returnedFunctionName( + lowerer: Lowerer, + decl: GenericFnInfo["decl"], + seen: Set, +): string | null { + const body = decl.body; + if (body === undefined) return null; + if (!ts.isBlock(body)) return functionValueName(lowerer, body, seen); + let name: string | null | undefined; + let ok = true; + ts.walkPreorder(body, (node) => { + if (!ok) return "stop"; + if (ts.isFunctionLike(node)) return "skip"; + if (!ts.isReturnStatement(node)) return undefined; + const here = node.expression ? functionValueName(lowerer, node.expression, seen) : null; + if (here === null || (name !== undefined && name !== here)) ok = false; + else name = here; + return undefined; + }); + return ok && name !== undefined ? name : null; +} + +/** The name of a returned function value: an anonymous definition returned + * directly is nameless; a local const binding names its definition. */ +function functionValueName( + lowerer: Lowerer, + expr: ts.Expression, + seen: Set, +): string | null { + const e = stripTypeWrappers(expr); + if (ts.isFunctionExpression(e) || ts.isArrowFunction(e)) { + return !ts.isArrowFunction(e) && e.name ? e.name.text : ""; + } + if (ts.isIdentifier(e)) return staticNameOf(lowerer, e, seen); + return null; +} + +/** `fn.name` where `fn` is a name-keyed parameter of the generic instance + * being lowered: the folded name, or a precise refusal when this call + * site's argument has no static name. Null for every other read. */ +export function staticFunctionNameRead( + lowerer: Lowerer, + expr: ts.PropertyAccessExpression, +): string | null { + const names = lowerer.staticFnNames; + if ( + names === null || + expr.name.text !== "name" || + expr.questionDotToken !== undefined || + !ts.isIdentifier(expr.expression) + ) { + return null; + } + const symbol = lowerer.checker.getSymbolAtLocation(expr.expression); + if (!symbol || !names.has(symbol)) return null; + const name = names.get(symbol); + if (name === null || name === undefined) { + lowerer.unsupported( + "SC1090", + expr, + `reading '${expr.expression.text}.name' when the call passes a function whose name is only known at run time (generic wrappers fold the name of a function declaration, a const-bound function, or a wrapper call's result)`, + ); + } + return name; +} diff --git a/packages/compiler/src/frontend/lowering/surfaces.ts b/packages/compiler/src/frontend/lowering/surfaces.ts index c98634695..37a1c625d 100644 --- a/packages/compiler/src/frontend/lowering/surfaces.ts +++ b/packages/compiler/src/frontend/lowering/surfaces.ts @@ -2458,6 +2458,27 @@ export const AMBIENT_SURFACE_FNS: readonly AmbientSurfaceRow[] = [ name: "perf_hooks.performance.clearMeasures", fns: ["perf.clearMeasures"], }, + { + id: "node-builtin.perf_hooks.performance.eventLoopUtilization", + kind: "node-builtin", + name: "perf_hooks.performance.eventLoopUtilization", + fns: ["perf.loopStart", "perf.idleTime"], + note: "active time is the main thread's CPU time since the loop started; the one- and two-argument difference forms are supported", + }, + { + id: "node-builtin.perf_hooks.monitorEventLoopDelay", + kind: "node-builtin", + name: "perf_hooks.monitorEventLoopDelay", + fns: [ + "perf.eldNew", + "perf.eldEnable", + "perf.eldDisable", + "perf.eldReset", + "perf.eldPercentile", + "perf.eldStat", + ], + note: "an unref'd sampling interval records the delay histogram; enable, disable, reset, percentile and the min, max, mean, stddev, count and exceeds readings are supported", + }, // ── the process global's ambient reads and authority calls // (lowerProcessProperty/lowerProcessMethodCall — process is a // provenance-checked global here, not an importable module). diff --git a/packages/compiler/src/frontend/lowering/typed-arguments.ts b/packages/compiler/src/frontend/lowering/typed-arguments.ts new file mode 100644 index 000000000..b52a3e059 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/typed-arguments.ts @@ -0,0 +1,516 @@ +import * as ts from "../ts7/adapter.js"; +import { bodyReadsArguments } from "../arguments-usage.js"; +import { isJsSourceFile, locOf } from "../program.js"; +import { restTupleElementTypes, unitOnlyUnion } from "../type-mapper.js"; +import { DYN, type IrExpr, type IrLocal, type IrStmt, type IrType, arrayOf } from "../../ir/ir.js"; +import type { Lowerer } from "./lowerer.js"; +import { captureContextArguments } from "./function-context.js"; +import { isThisParameter, type ParamShape } from "./call-signatures.js"; +import { tryLowerExpression } from "./expressions/try-lower-expression.js"; +import { omittedArgFor } from "./call-arguments.js"; + +/** Variadic forwarding through a FIXED signature. + * + * A TypeScript function expression that declares no parameters and reads + * `arguments` (`function (this: unknown) { return fn.apply(this, arguments) } + * as F`) is lowered against the fixed function type its value is asserted + * to: one native slot per position of that type, and `arguments` is the + * tuple of those slots. Inside a generic instantiation F is the call + * site's concrete signature, so a higher-order wrapper specializes to the + * wrapped function's exact ABI. Forwarding (`f.apply(thisArg, args)`, + * `f(...args)`) then calls with the tuple's positions directly. */ + +/** `e`, with the type-only wrappers that never change its value removed. */ +export function stripTypeWrappers(e: ts.Expression): ts.Expression { + let cur = e; + for (;;) { + if (ts.isParenthesizedExpression(cur)) cur = cur.expression; + else if (ts.isAsExpression(cur) || ts.isTypeAssertion(cur) || ts.isSatisfiesExpression(cur)) + cur = cur.expression; + else if (ts.isNonNullExpression(cur)) cur = cur.expression; + else return cur; + } +} + +/** The outermost type assertion around `node` (`node as unknown as F` → F), + * looking through parentheses; null when the value is not asserted. */ +function assertedTypeNode(node: ts.Node): ts.TypeNode | null { + let cur: ts.Node = node; + let found: ts.TypeNode | null = null; + for (let parent = cur.parent; parent !== undefined; parent = cur.parent) { + if (ts.isParenthesizedExpression(parent)) { + cur = parent; + continue; + } + if ((ts.isAsExpression(parent) || ts.isTypeAssertion(parent)) && parent.expression === cur) { + found = parent.type; + cur = parent; + continue; + } + break; + } + return found; +} + +/** The fixed function type a value is asserted to, or null. */ +function assertedFuncType(lowerer: Lowerer, node: ts.Node): (IrType & { kind: "func" }) | null { + const typeNode = assertedTypeNode(node); + if (!typeNode) return null; + const mapped = lowerer.mapTypeOf(lowerer.checker.getTypeFromTypeNode(typeNode)); + return mapped?.kind === "func" ? mapped : null; +} + +function sameFuncType(a: IrType & { kind: "func" }, b: IrType & { kind: "func" }): boolean { + return JSON.stringify(a) === JSON.stringify(b); +} + +/** A function expression whose `arguments` can be typed: TypeScript source, + * no runtime parameters (a `this` parameter is type-only), an ordinary + * (non-generator) function that reads its own `arguments`. */ +export function typedArgumentsCandidate(node: ts.Node): node is ts.FunctionExpression { + return ( + ts.isFunctionExpression(node) && + node.asteriskToken === undefined && + !isJsSourceFile(node.getSourceFile()) && + node.parameters.nodes.every(isThisParameter) && + bodyReadsArguments(node) + ); +} + +/** The fixed signature a typed-arguments function expression is lowered + * against: the type its value is asserted to (`function () {…} as F`), the + * one type every use of its const binding asserts it to (`const w = + * function () {…}; return w as unknown as F`), or its contextual function + * type. Null when none names one fixed-arity signature. */ +export function typedArgumentsTarget( + lowerer: Lowerer, + node: ts.FunctionExpression, +): (IrType & { kind: "func" }) | null { + const fixed = (t: (IrType & { kind: "func" }) | null) => (t && t.rest !== true ? t : null); + const direct = assertedFuncType(lowerer, node); + if (direct) return fixed(direct); + let top: ts.Node = node; + while (top.parent && ts.isParenthesizedExpression(top.parent)) top = top.parent; + const decl = top.parent; + if ( + decl && + ts.isVariableDeclaration(decl) && + decl.initializer === top && + decl.type === undefined && + ts.isIdentifier(decl.name) && + (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 + ) { + const symbol = lowerer.checker.getSymbolAtLocation(decl.name); + const scope = enclosingScope(decl); + if (symbol && scope) { + let target: (IrType & { kind: "func" }) | null = null; + let ok = true; + let uses = 0; + ts.walkPreorder(scope, (n) => { + if (!ok) return "stop"; + if (n === decl.name || !ts.isIdentifier(n) || n.text !== decl.name.text) return undefined; + if (lowerer.checker.getSymbolAtLocation(n) !== symbol) return undefined; + uses++; + const asserted = assertedFuncType(lowerer, n); + if (!asserted || (target && !sameFuncType(target, asserted))) ok = false; + else target = asserted; + return undefined; + }); + if (ok && uses > 0) return fixed(target); + } + } + const ctxType = lowerer.checker.getContextualType(node); + if (!ctxType) return null; + const sigs = lowerer.checker.getCallSignatures(lowerer.checker.getNonNullableType(ctxType)); + if (sigs.length !== 1) return null; + const mapped = lowerer.mapTypeOf(lowerer.checker.getNonNullableType(ctxType)); + return mapped?.kind === "func" ? fixed(mapped) : null; +} + +function enclosingScope(node: ts.Node): ts.Node | null { + for (let cur = node.parent; cur !== undefined; cur = cur.parent) { + if (ts.isSourceFile(cur) || (ts.isFunctionLike(cur) && cur.body !== undefined)) return cur; + } + return null; +} + +/** The tuple type of a fixed parameter list, interned exactly as the + * spelled tuple (and `Parameters`) map: positional fields, or the + * empty-array form for no parameters. */ +export function tupleTypeOfParams(lowerer: Lowerer, params: readonly IrType[]): IrType { + if (params.length === 0) return arrayOf(unitOnlyUnion(lowerer.unions)); + const fields = params.map((type, i) => ({ name: String(i), type })); + fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + return { kind: "record", shapeId: lowerer.shapes.intern(fields, true) }; +} + +/** The ABI shapes of a typed-arguments function: one required slot per + * position of its target signature. */ +export function typedArgumentsShapes(target: IrType & { kind: "func" }): ParamShape[] { + return target.params.map((type) => ({ type, mode: "required" })); +} + +/** Declares the hidden positional slots of a typed-arguments function and + * binds its `arguments` to their tuple. */ +export function declareTypedArguments( + lowerer: Lowerer, + node: ts.FunctionExpression, + shapes: readonly ParamShape[], + params: { localId: string; name: string; type: IrType }[], + prologue: IrStmt[], +): void { + const loc = locOf(node); + const slots = shapes.map((shape, i) => { + const slot = lowerer.declareHiddenLocal(`%arguments.${i}`, shape.type); + params.push({ localId: slot.id, name: `%arguments.${i}`, type: shape.type }); + return slot; + }); + const tupleType = tupleTypeOfParams( + lowerer, + shapes.map((s) => s.type), + ); + const local = lowerer.declareHiddenLocal("%arguments", tupleType); + lowerer.ctx.argumentsLocal = local; + // Pure forwarding (every read is forwarded, counted, or aliased by a + // binding that is itself only forwarded): no tuple exists at all. + if ( + onlyForwarded(lowerer, node, (id) => id.text === "arguments" && argumentsOwner(id) === node) + ) { + lowerer.ctx.pureTuples.set(local.id, slots); + return; + } + prologue.push({ + kind: "varDecl", + localId: local.id, + init: lowerer.tupleOfSlots(slots, tupleType, node, loc), + loc, + }); +} + +/** Whether every read of a tuple binding in `fn` (identified by `isRoot`) + * only forwards it: `f.apply(t, x)`, `g(...x)` into a program function, + * `x.length`, or a const alias whose own reads only forward. Reads inside + * nested functions (arrows included) capture the binding and need the + * tuple. Type assertions around a read never matter. */ +export function onlyForwarded( + lowerer: Lowerer, + fn: ts.Node, + isRoot: (id: ts.Identifier) => boolean, +): boolean { + const body = (fn as ts.Node & { body?: ts.Node }).body; + if (body === undefined) return false; + const roots: ((id: ts.Identifier) => boolean)[] = [isRoot]; + let ok = true; + const visit = (scope: ts.Node, test: (id: ts.Identifier) => boolean): void => { + ts.walkPreorder(scope, (n) => { + if (!ok) return "stop"; + if (ts.isTypeNode(n)) return "skip"; + if (!ts.isIdentifier(n) || !test(n)) return undefined; + for (let cur = n.parent; cur !== undefined && cur !== fn; cur = cur.parent) { + if (ts.isFunctionLike(cur)) { + ok = false; + return "stop"; + } + } + let top: ts.Node = n; + while ( + top.parent && + (ts.isParenthesizedExpression(top.parent) || + ts.isAsExpression(top.parent) || + ts.isTypeAssertion(top.parent) || + ts.isSatisfiesExpression(top.parent) || + ts.isNonNullExpression(top.parent)) + ) + top = top.parent; + const p = top.parent; + if (!p) { + ok = false; + return "stop"; + } + if (ts.isPropertyAccessExpression(p) && p.expression === top && p.name.text === "length") + return undefined; + if ( + ts.isCallExpression(p) && + p.arguments.nodes.length === 2 && + p.arguments.nodes[1] === top && + ts.isPropertyAccessExpression(p.expression) && + p.expression.name.text === "apply" && + p.expression.questionDotToken === undefined + ) + return undefined; + if (ts.isSpreadElement(p) && p.parent && ts.isCallExpression(p.parent)) { + const sigs = lowerer.checker.getCallSignatures( + lowerer.checker.getNonNullableType(lowerer.typeOf(p.parent.expression)), + ); + const decl = sigs.length === 1 ? sigs[0]!.declaration : undefined; + if (decl && !decl.getSourceFile().isDeclarationFile) return undefined; + } + if ( + ts.isVariableDeclaration(p) && + p.initializer === top && + ts.isIdentifier(p.name) && + (ts.getCombinedNodeFlags(p) & ts.NodeFlags.Const) !== 0 + ) { + const alias = lowerer.checker.getSymbolAtLocation(p.name); + const aliasName = p.name; + if (alias) { + roots.push((id) => id !== aliasName && lowerer.checker.getSymbolAtLocation(id) === alias); + return undefined; + } + } + ok = false; + return "stop"; + }); + }; + for (let i = 0; i < roots.length && ok; i++) visit(body, roots[i]!); + return ok; +} + +/** The native slots of a pure-forwarded tuple binding read at `node` in + * the current function, or null when the tuple is materialized. */ +function pureSlotsOf(lowerer: Lowerer, node: ts.Expression): IrLocal[] | null { + const operand = stripTypeWrappers(node); + if (!ts.isIdentifier(operand)) return null; + const local = + operand.text === "arguments" ? lowerer.ctx.argumentsLocal : lowerer.peekLocal(operand); + return local ? (lowerer.ctx.pureTuples.get(local.id) ?? null) : null; +} + +/** The positional values `node` forwards when it is a pure-forwarded tuple + * (slot reads, in order), or null. */ +export function pureForwardedValues(lowerer: Lowerer, node: ts.Expression): IrExpr[] | null { + const slots = pureSlotsOf(lowerer, node); + if (!slots) return null; + const loc = locOf(node); + return slots.map((slot) => ({ kind: "varRef", localId: slot.id, type: slot.type, loc })); +} + +/** Whether `node` reads a tuple-typed `arguments` binding: the nearest + * ordinary function (arrows inherit it) is a typed-arguments function. + * Looks the binding up without allocating captures. */ +function isTypedArgumentsRead(lowerer: Lowerer, node: ts.Expression): boolean { + if (!ts.isIdentifier(node) || node.text !== "arguments") return false; + const stack = lowerer.fnStack; + let owner = stack.length - 1; + while (owner > 0 && stack[owner]!.inheritsArguments) owner--; + const own = owner >= 0 ? stack[owner]!.argumentsLocal : undefined; + return own !== undefined && own !== null && own.type.kind !== "dyn"; +} + +/** The fixed tuple `node` forwards, or null: the typed `arguments`, a + * fixed-tuple rest parameter, or a const alias of either — seen through + * type assertions, which never change the value. */ +export function forwardedTupleType(lowerer: Lowerer, node: ts.Expression): IrType | null { + const operand = stripTypeWrappers(node); + if (!ts.isIdentifier(operand)) return null; + if (operand.text === "arguments") { + if (!isTypedArgumentsRead(lowerer, operand)) return null; + return captureContextArguments(lowerer.fnStack)!.type; + } + const symbol = lowerer.resolveValueSymbol(operand); + if (!symbol) return null; + const alias = lowerer.tupleAliasSymbols.get(symbol); + if (alias) return alias; + const decl = symbol.valueDeclaration; + if ( + decl !== undefined && + ts.isParameter(decl) && + decl.dotDotDotToken !== undefined && + ts.isIdentifier(decl.name) && + !isJsSourceFile(decl.getSourceFile()) && + // Checker-only probe first: an ordinary array rest never maps here. + restTupleElementTypes(lowerer.typeOf(operand), lowerer.typeCtx) !== null + ) { + // A tuple with optional positions has no value type of its own; its + // forwarded-only binding carries the slots' tuple (declareRestTupleParam). + const t = lowerer.mapTypeOf(lowerer.typeOf(operand)) ?? lowerer.peekLocal(operand)?.type; + if (t && isTupleValueType(lowerer, t)) return t; + } + return null; +} + +function isTupleValueType(lowerer: Lowerer, t: IrType): boolean { + if (t.kind === "record") return lowerer.shapes.get(t.shapeId)?.tuple === true; + // The empty tuple's representation (mapType's `[]` rule): an array over + // the unit-only union. Looked up, never interned, so probing a value + // leaves the registries untouched. + if (t.kind !== "array" || t.elem.kind !== "union") return false; + const arms = lowerer.unions.get(t.elem.unionId)?.arms; + return ( + arms !== undefined && + arms.length === 2 && + arms.some((a) => a.kind === "nullT") && + arms.some((a) => a.kind === "undefinedT") + ); +} + +/** The positional reads of a forwarded tuple value (already saved in a + * local), in order. */ +function tupleReads( + lowerer: Lowerer, + ref: () => IrExpr, + tupleType: IrType, + loc: IrExpr["loc"], +): IrExpr[] { + if (tupleType.kind !== "record") return []; + const shape = lowerer.shapes.get(tupleType.shapeId)!; + return [...shape.fields] + .sort((a, b) => Number(a.name) - Number(b.name)) + .map((field) => ({ + kind: "recordGet" as const, + obj: ref(), + shapeId: tupleType.shapeId, + field: field.name, + type: field.type, + loc, + })); +} + +/** `f.apply(thisArg, args)` where `args` forwards a fixed tuple and `f` is a + * fixed-arity function value: a direct call of `f` with the tuple's + * positions and `thisArg` as the call-time receiver. Null for every other + * form (the existing Function.prototype paths keep them). */ +export function lowerForwardingApply( + lowerer: Lowerer, + call: ts.CallExpression, + access: ts.PropertyAccessExpression, +): IrExpr | null { + if (access.name.text !== "apply" || access.questionDotToken !== undefined) return null; + const argNodes = call.arguments.nodes; + if (argNodes.length !== 2 || argNodes.some(ts.isSpreadElement)) return null; + const tupleType = forwardedTupleType(lowerer, argNodes[1]!); + if (!tupleType) return null; + const callee = tryLowerExpression(lowerer, access.expression); + if (callee?.type.kind !== "func") return null; + const fnType = callee.type; + const loc = locOf(call); + if (fnType.rest === true) { + lowerer.unsupported( + "SC1090", + call, + "forwarding a fixed argument tuple through 'apply' to a variadic function value", + ); + } + const savedFn = lowerer.declareHiddenLocal("%applyFn", fnType); + const savedThis = lowerer.declareHiddenLocal("%applyThis", DYN); + const stmts: IrStmt[] = [ + { kind: "varDecl", localId: savedFn.id, init: callee, loc }, + { + kind: "varDecl", + localId: savedThis.id, + init: lowerer.lowerExprExpecting(argNodes[0]!, DYN), + loc, + }, + ]; + let reads = pureForwardedValues(lowerer, argNodes[1]!); + if (!reads) { + const savedArgs = lowerer.declareHiddenLocal("%applyArgs", tupleType); + stmts.push({ + kind: "varDecl", + localId: savedArgs.id, + init: lowerer.lowerExpr(stripTypeWrappers(argNodes[1]!)), + loc, + }); + reads = tupleReads( + lowerer, + () => ({ kind: "varRef", localId: savedArgs.id, type: tupleType, loc }), + tupleType, + loc, + ); + } + // JS drops surplus positions and fills missing ones with undefined. + const args = fnType.params.map((param, i): IrExpr => { + const read = reads[i]; + if (read) return lowerer.coerceInto(call, read, param); + const absent = omittedArgFor(lowerer, param, loc); + if (!absent) { + lowerer.unsupported( + "SC1090", + call, + "forwarding fewer arguments through 'apply' than the callee's required parameters", + ); + } + return absent; + }); + const invoked: IrExpr = { + kind: "callValue", + callee: { kind: "varRef", localId: savedFn.id, type: fnType, loc }, + receiver: { kind: "varRef", localId: savedThis.id, type: DYN, loc }, + args, + type: fnType.ret, + loc, + }; + return { kind: "seqExpr", stmts, result: invoked, type: fnType.ret, loc }; +} + +/** `const args = arguments as …` (or an alias of a rest tuple) inside a + * typed-arguments function: the binding holds the tuple itself — the + * assertion only re-describes the value — and stays a forwarding source. */ +export function lowerTupleAliasDecl(lowerer: Lowerer, decl: ts.VariableDeclaration): IrStmt | null { + if ( + !decl.initializer || + !ts.isIdentifier(decl.name) || + (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0 || + lowerer.fnStack.length === 0 + ) { + return null; + } + const tupleType = forwardedTupleType(lowerer, decl.initializer); + if (!tupleType) return null; + const symbol = lowerer.checker.getSymbolAtLocation(decl.name); + if (!symbol) return null; + const declared = lowerer.mapTypeOf(lowerer.typeOf(decl.name)); + if (declared && declared.kind !== "dyn" && JSON.stringify(declared) !== JSON.stringify(tupleType)) + return null; + lowerer.tupleAliasSymbols.set(symbol, tupleType); + const slots = pureSlotsOf(lowerer, decl.initializer); + if (slots) { + // An alias of a pure-forwarded tuple is itself only forwarded + // (onlyForwarded followed it): it names the same slots. + const local = lowerer.declareLocal(decl.name, decl.name.text, tupleType, false); + lowerer.ctx.pureTuples.set(local.id, slots); + return { kind: "block", body: [], loc: locOf(decl) }; + } + const init = lowerer.lowerExpr(stripTypeWrappers(decl.initializer)); + const local = lowerer.declareLocal(decl.name, decl.name.text, tupleType, false); + return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) }; +} + +/** A spread operand forwarding a fixed tuple (forwardedTupleType), + * including one that resolved to no positions at all. */ +export function isForwardedTupleSpread(lowerer: Lowerer, node: ts.Expression): boolean { + return forwardedTupleType(lowerer, node) !== null; +} + +/** `arguments` read inside a typed-arguments function: its fixed arity. */ +export function typedArgumentsArity(lowerer: Lowerer, node: ts.Expression): number | null { + if (!ts.isIdentifier(node)) return null; + const t = forwardedTupleType(lowerer, node); + if (!t) return null; + if (t.kind !== "record") return 0; + const fields = lowerer.shapes.get(t.shapeId)?.fields ?? []; + // A position that may be undefined may also be absent at the call: the + // native signature always passes it, so the count is not static. + if ( + fields.some( + (f) => f.type.kind === "union" && lowerer.armTag(f.type.unionId, { kind: "undefinedT" }) >= 0, + ) + ) { + lowerer.unsupported( + "SC1090", + node.parent ?? node, + "'length' of an argument tuple whose positions may be omitted (the native signature always passes every position, so the count is not static)", + ); + } + return fields.length; +} + +/** The function whose `arguments` an identifier reads: the nearest + * enclosing non-arrow function. */ +export function argumentsOwner(node: ts.Node): ts.Node | null { + for (let cur = node.parent; cur !== undefined; cur = cur.parent) { + if (ts.isFunctionLike(cur) && !ts.isArrowFunction(cur)) return cur; + if (ts.isSourceFile(cur)) return null; + } + return null; +} diff --git a/packages/compiler/src/frontend/type-mapper.ts b/packages/compiler/src/frontend/type-mapper.ts index 3c79a1281..87711a659 100644 --- a/packages/compiler/src/frontend/type-mapper.ts +++ b/packages/compiler/src/frontend/type-mapper.ts @@ -980,7 +980,7 @@ function isDeclaredInAmbientModule(d: ts.Declaration, name: string): boolean { /** True when the declaration's nearest enclosing namespace is `name` * (`declare global { namespace NodeJS { ... } }` — the NodeJS-global * interfaces @types/node declares outside any ambient module). */ -function isDeclaredInAmbientNamespace(d: ts.Declaration, name: string): boolean { +export function isDeclaredInAmbientNamespace(d: ts.Declaration, name: string): boolean { let node: ts.Node | undefined = d.parent; while (node) { if (ts.isModuleDeclaration(node) && ts.isIdentifier(node.name)) { @@ -991,6 +991,31 @@ function isDeclaredInAmbientNamespace(d: ts.Declaration, name: string): boolean return false; } +/** Whether `type` is one of the stream spellings the general stream + * representation (TypeMapperCtx.generalNodeStreams) maps differently: + * NodeJS.ReadableStream / NodeJS.WritableStream, @types/node's + * stream.Readable / stream.Writable, or the fallback declarations' + * ChildStdin. */ +export function isGeneralNodeStreamInterface( + type: ts.Type, + ctx: Pick, +): boolean { + const psym = type.getSymbol() ?? type.getAliasSymbol(); + if (psym === undefined) return false; + return psym.declarations.some((d) => { + if (!(ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d))) return false; + if (!ctx.isStdlibFile(d.getSourceFile())) return false; + if (psym.name === "ReadableStream" || psym.name === "WritableStream") + return ts.isInterfaceDeclaration(d) && isDeclaredInAmbientNamespace(d, "NodeJS"); + if (psym.name === "ChildStdin") return isDeclaredInAmbientModule(d, "child_process"); + return ( + (psym.name === "Readable" || psym.name === "Writable") && + isNodeTypesPath(d.getSourceFile().fileName) && + isDeclaredInAmbientModule(d, "stream") + ); + }); +} + /** A type declared in the shipped WebAssembly namespace (scriptc.d.ts): * its modules, instances, memories, tables, globals, error classes and the * Exports/Imports records. */ @@ -1146,6 +1171,13 @@ export interface TypeMapperCtx { * type descriptions for project-owned values, but their imported runtime * bindings are fenced separately by the Lowerer. */ isExternalTypeFile: (sf: ts.SourceFile) => boolean; + /** The program's general stream representation (lowerToIr decides it + * per program): NodeJS.ReadableStream / NodeJS.WritableStream and + * @types/node's stream.Readable / stream.Writable map to the runtime + * stream classes instead of the child/process stdio handles, so values + * from every stream producer share their slots. Off (the default), the + * stdio handles keep those spellings. */ + generalNodeStreams?: boolean; /** Successful context-free mappings, keyed by the * TypeScript server's stable type id. A generated facade can reference the * same large record/function type thousands of times; remapping its full @@ -1744,6 +1776,18 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { // option) holds that dynamic value too, so the whole union is dynamic. if (type.isUnionType() && ts.constituentTypes(type).some((t) => isWebAssemblyType(t, ctx))) return DYN; + // JavaScript inference merges WebAssembly.instantiate's overloads into + // `Promise & Promise`: a promise + // of a WebAssembly value either way. + if ( + type.isIntersectionType() && + ts.constituentTypes(type).every((t) => { + if (t.getSymbol()?.name !== "Promise") return false; + const arg = ctx.checker.getTypeArguments(t as ts.TypeReference)[0]; + return arg !== undefined && isWebAssemblyType(arg, ctx); + }) + ) + return { kind: "promise", inner: DYN }; // Immutable (@scriptc/types) is a deep-readonly view: the value is // still the T it maps. const immutableSource = immutableSourceType(type, ctx); @@ -1805,6 +1849,16 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { contextResolutions++; return viaIndexed; } + // `Parameters` / `ReturnType` over a bound function-typed + // parameter (variadic higher-order wrappers): the checker keeps both + // conditionals symbolic inside the body, and their `infer` positions + // match a call signature, which matchInferReference cannot decide. + const viaSignature = + mapBoundSignatureAlias(type, ctx) ?? mapBoundKeyofNeverConditional(type, ctx); + if (viaSignature !== null) { + contextResolutions++; + return viaSignature; + } // A conditional type over a bound parameter (`Infer`, a // mapped type's member): evaluate it against the bindings. if (type.isConditionalType()) { @@ -3176,6 +3230,20 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { // global-namespace interface real code writes in its own signatures — // prefixStream's `output` param). The representation is the raw fd // scalar; the lowered surface is write(string). + // Under the program's general stream representation (generalNodeStreams) + // NodeJS.WritableStream is the runtime Writable instead: the process + // streams convert into it where they flow (process.stdioWritable). + const nodeWritableInterface = + psym?.name === "WritableStream" && + psym.declarations.some( + (d) => + ts.isInterfaceDeclaration(d) && + ctx.isStdlibFile(d.getSourceFile()) && + isDeclaredInAmbientNamespace(d, "NodeJS"), + ); + if (nodeWritableInterface && ctx.generalNodeStreams === true) { + return { kind: "object", className: "%Writable" }; + } if ( (psym?.name === "WriteStream" && psym.declarations.some( @@ -3185,13 +3253,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { (isDeclaredInAmbientModule(d, "tty") || (isDeclaredInAmbientModule(d, "process") && isDeclaredInAmbientNamespace(d, "NodeJS"))), )) || - (psym?.name === "WritableStream" && - psym.declarations.some( - (d) => - ts.isInterfaceDeclaration(d) && - ctx.isStdlibFile(d.getSourceFile()) && - isDeclaredInAmbientNamespace(d, "NodeJS"), - )) + nodeWritableInterface ) { return PROCSTREAM_T; } @@ -3201,6 +3263,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { // of the broad @types class fence where they are constructed. if ( (psym?.name === "ChildStdin" && + ctx.generalNodeStreams !== true && psym.declarations.some( (d) => ts.isInterfaceDeclaration(d) && @@ -3208,6 +3271,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { isDeclaredInAmbientModule(d, "child_process"), )) || (psym?.name === "Writable" && + ctx.generalNodeStreams !== true && psym.declarations.some( (d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) && @@ -3218,6 +3282,20 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { ) { return { kind: "childWriter" }; } + // Under the general stream representation the fallback declarations' + // ChildStdin is the runtime Writable too (child.stdioStream bridges it). + if ( + ctx.generalNodeStreams === true && + psym?.name === "ChildStdin" && + psym.declarations.some( + (d) => + ts.isInterfaceDeclaration(d) && + ctx.isStdlibFile(d.getSourceFile()) && + isDeclaredInAmbientModule(d, "child_process"), + ) + ) { + return { kind: "object", className: "%Writable" }; + } // The static node:stream classes (the shipped fallback declarations — // NOT @types/node, whose stream.Readable also types child stdio; under // @types/node the childStream mapping below keeps priority and the @@ -3225,6 +3303,9 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { // branch: the fallback's Readable must map to the runtime class, and // under the fallback child.stdout is NodeJS.ReadableStream (its own // branch below), so the two never collide. + // @types/node's Duplex/Transform/PassThrough classes have no child-stdio + // reading, so they map to the runtime classes too; its Readable and + // Writable join them under the general representation. for (const [irName, rec] of RUNTIME_STREAM_CLASSES) { if ( psym?.name === rec.lib && @@ -3232,38 +3313,39 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { (d) => ts.isClassDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()) && - !isNodeTypesPath(d.getSourceFile().fileName) && + (!isNodeTypesPath(d.getSourceFile().fileName) || + ctx.generalNodeStreams === true || + (rec.lib !== "Readable" && rec.lib !== "Writable")) && isDeclaredInAmbientModule(d, "stream"), ) ) { return { kind: "object", className: irName }; } } - // node:zlib's stream classes (the shipped fallback declarations): their - // instances are runtime Transform streams. + // node:zlib's stream classes (the shipped fallback declarations and + // @types/node's): their instances are runtime Transform streams. if ( psym !== undefined && ZLIB_STREAM_MODES.has(psym.name) && psym.declarations.some( (d) => - ts.isClassDeclaration(d) && + (ts.isClassDeclaration(d) || + (ts.isInterfaceDeclaration(d) && isNodeTypesPath(d.getSourceFile().fileName))) && ctx.isStdlibFile(d.getSourceFile()) && - !isNodeTypesPath(d.getSourceFile().fileName) && isDeclaredInAmbientModule(d, "zlib"), ) ) { return { kind: "object", className: "%Transform" }; } - // fs.ReadStream / fs.WriteStream (the shipped fallback declarations): - // their instances are runtime Readable / Writable streams - // (scr_fs_stream.c). + // fs.ReadStream / fs.WriteStream (the shipped fallback declarations and + // @types/node's): their instances are runtime Readable / Writable + // streams (scr_fs_stream.c). if ( (psym?.name === "ReadStream" || psym?.name === "WriteStream") && psym.declarations.some( (d) => ts.isClassDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()) && - !isNodeTypesPath(d.getSourceFile().fileName) && isDeclaredInAmbientModule(d, "fs"), ) ) { @@ -3285,6 +3367,9 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { isDeclaredInAmbientNamespace(d, "NodeJS"), )) ) { + // The general representation: the runtime Readable, which child + // stdio reads produce through the child stream bridge. + if (ctx.generalNodeStreams === true) return { kind: "object", className: "%Readable" }; return { kind: "childStream" }; } // dgram.Socket: the same ambiguous "Socket" name disambiguated by its @@ -3995,6 +4080,27 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { return { kind: "record", shapeId: perfEntryShape(ctx.shapes, ctx.unions) }; } // readline's getCursorPos() record, in Node's key order ({ cols, rows }). + // perf_hooks' EventLoopUtilization (performance.eventLoopUtilization's + // result): a plain data record in Node's key order. + if (isStdlibInterface("EventLoopUtilization")) { + return { + kind: "record", + shapeId: ctx.shapes.intern( + [ + { name: "active", type: F64 }, + { name: "idle", type: F64 }, + { name: "utilization", type: F64 }, + ], + false, + undefined, + ["idle", "active", "utilization"], + ), + }; + } + // monitorEventLoopDelay's IntervalHistogram: a numeric handle into the + // runtime's histogram table, like a timer handle. Its members lower over + // the handle (builtins/performance.ts). + if (isStdlibInterface("IntervalHistogram")) return F64; if (isStdlibInterface("CursorPos")) { return { kind: "record", @@ -4331,10 +4437,18 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { const mapped = mapType(checker.getTypeOfSymbol(p), ctx); if (!mapped) return false; const arms = mapped.kind === "union" ? ctx.unions.get(mapped.unionId)?.arms : [mapped]; + // Under the general stream representation the stdio members are the + // runtime stream classes. + const isExpected = (arm: IrType): boolean => + arm.kind === expected || + (ctx.generalNodeStreams === true && + arm.kind === "object" && + ((expected === "childStream" && arm.className === "%Readable") || + (expected === "childWriter" && arm.className === "%Writable"))); return ( arms !== undefined && - arms.some((arm) => arm.kind === expected) && - arms.every((arm) => arm.kind === expected || arm.kind === unit) + arms.some(isExpected) && + arms.every((arm) => isExpected(arm) || arm.kind === unit) ); }; const childShaped = @@ -4547,11 +4661,44 @@ function mapCallSignature(sig: ts.Signature, ctx: TypeMapperCtx): IrType | null // declaration as a typed packed-array closure would bypass its boxed // spread/error semantics and change coverage classification. if (rest && decl !== undefined && isJsSourceFile(decl.getSourceFile())) return null; + // A fixed-tuple rest (`...args: [A, B]`, `...args: Parameters` over + // a bound F) flattens to its positional parameters. Pattern rests keep + // their packed-record ABI and stay unmapped as values. + if (rest && decl !== undefined && ts.isParameter(decl) && ts.isIdentifier(decl.name)) { + const elems = restTupleParamTypes(checker.getTypeOfSymbol(p), ctx); + if (elems) { + params.push(...elems); + continue; + } + } const optional = decl !== undefined && ts.isParameter(decl) && (decl.questionToken !== undefined || decl.initializer !== undefined); let pt = mapType(checker.getTypeOfSymbol(p), ctx); + // A parameter a TypeScript program types `any` takes whatever the + // caller passes: the checked-dynamic slot, as an `any`-typed binding + // already is (dynFallbackType). Declaration files keep their paths. + // Only function declarations, spelled function types and lambda + // parameters whose default is the only source of their type (`(n = + // lookup() ?? 5) => ...` with an `any` lookup): other lambdas and + // methods in object literals keep their existing checked-dynamic story. + if ( + !pt && + !rest && + decl !== undefined && + ts.isParameter(decl) && + decl.parent !== undefined && + (ts.isFunctionDeclaration(decl.parent) || + ts.isFunctionTypeNode(decl.parent) || + ((ts.isArrowFunction(decl.parent) || ts.isFunctionExpression(decl.parent)) && + decl.initializer !== undefined && + decl.type === undefined && + !isJsSourceFile(decl.getSourceFile()))) && + !decl.getSourceFile().isDeclarationFile && + (checker.getTypeOfSymbol(p).flags & ts.TypeFlags.Any) !== 0 + ) + pt = DYN; if ( decl && ts.isParameter(decl) && @@ -4699,6 +4846,9 @@ function unionDiscriminant( ): IrUnionDiscriminant | undefined { if (arms.filter((arm) => arm.kind === "record").length < 2 || parts.length < 2) return undefined; const { checker } = ctx; + // Tuple shapes keep positions only: their checker `length` literal has + // no slot to compare (discriminantField refuses tuple shapes too). + if (parts.some((part) => ctx.shapes.get(part.mapped.shapeId)?.tuple)) return undefined; for (const candidate of checker.getPropertiesOfType(parts[0]!.source)) { if (candidate.name.startsWith("__@")) continue; const byTag = new Map(); @@ -5036,6 +5186,167 @@ function mapBoundIndexedAccess(type: ts.Type, ctx: TypeMapperCtx): IrType | null return mapType(checker.getTypeOfSymbol(prop), ctx); } +/** The standard library's `Parameters` / `ReturnType` over a type + * parameter the current instantiation binds to a callable checker type: + * that type's one call signature. Concrete arguments never reach here (the + * checker evaluates those conditionals itself); generic bodies keep them + * symbolic because their `infer` sits in a call signature. */ +function boundSignatureAlias( + type: ts.Type, + ctx: TypeMapperCtx, +): { name: "Parameters" | "ReturnType"; sig: ts.Signature } | null { + const { checker, resolveTypeParamTs } = ctx; + if (!resolveTypeParamTs) return null; + const alias = type.getAliasSymbol(); + if (!alias || (alias.name !== "Parameters" && alias.name !== "ReturnType")) return null; + const aliasArgs = type.getAliasTypeArguments(); + const arg = aliasArgs[0]; + if (aliasArgs.length !== 1 || !arg || !(arg.flags & ts.TypeFlags.TypeParameter)) return null; + const isLibAlias = alias.declarations.some( + (d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()), + ); + if (!isLibAlias) return null; + const bound = resolveTypeParamTs(arg); + if (!bound || bound.flags & ts.TypeFlags.TypeParameter) return null; + const sigs = checker.getCallSignatures(bound); + const sig = sigs[0]; + if (sigs.length !== 1 || !sig || sig.getTypeParameters().length > 0) return null; + return { name: alias.name, sig }; +} + +/** One position of a fixed-arity parameter tuple. An optional position + * still has a native slot (the function type's `T | undefined` slot). */ +interface TupleElement { + type: ts.Type; + optional: boolean; +} + +/** The positional parameters of a signature as a fixed tuple: a trailing + * rest flattened when its own type is a fixed tuple. Null for a variadic + * position, which has no fixed native arity. */ +function signatureParameters(sig: ts.Signature, ctx: TypeMapperCtx): TupleElement[] | null { + const { checker } = ctx; + const out: TupleElement[] = []; + for (const p of sig.getParameters()) { + const decl = p.valueDeclaration; + const type = checker.getTypeOfSymbol(p); + if (decl !== undefined && ts.isParameter(decl)) { + if (decl.dotDotDotToken !== undefined) { + const inner = restTupleElements(type, ctx); + if (!inner) return null; + out.push(...inner); + continue; + } + out.push({ + type, + optional: decl.questionToken !== undefined || decl.initializer !== undefined, + }); + continue; + } + out.push({ type, optional: (p.flags & ts.SymbolFlags.Optional) !== 0 }); + } + return out; +} + +/** The required-only positional parameter types of a signature (the + * value-level `Parameters` tuple), null when a position is optional + * or variadic: such a tuple's length varies per call. */ +function signatureParameterTypes(sig: ts.Signature, ctx: TypeMapperCtx): ts.Type[] | null { + const elems = signatureParameters(sig, ctx); + if (!elems || elems.some((e) => e.optional)) return null; + return elems.map((e) => e.type); +} + +/** The element types of a REST parameter's type when it is a fixed tuple: + * a tuple of required elements (`[number, string]`, the empty `[]`), a type + * parameter bound to one, or `Parameters` over a bound function type. + * Such a rest parameter has a compile-time arity, so its native ABI is the + * flattened positional list (exactly the equivalent fixed signature — + * TypeScript treats `(...a: [A, B]) => R` and `(a: A, b: B) => R` alike). */ +export function restTupleElementTypes(type: ts.Type, ctx: TypeMapperCtx): ts.Type[] | null { + return restTupleElements(type, ctx)?.map((e) => e.type) ?? null; +} + +/** restTupleElementTypes with each position's optionality: a rest tuple + * may end in optional positions (`[A, B?]`, `Parameters<(a: A, b?: B) => + * R>`), which flatten to `T | undefined` slots exactly as the function + * type's optional parameters do. */ +function restTupleElements(type: ts.Type, ctx: TypeMapperCtx): TupleElement[] | null { + const { checker } = ctx; + if (type.flags & ts.TypeFlags.TypeParameter) { + const bound = ctx.resolveTypeParamTs?.(type); + return bound && bound !== type ? restTupleElements(bound, ctx) : null; + } + const viaAlias = boundSignatureAlias(type, ctx); + if (viaAlias) { + return viaAlias.name === "Parameters" ? signatureParameters(viaAlias.sig, ctx) : null; + } + if (!checker.isTupleType(type)) return null; + const ref = type as ts.TupleTypeReference; + const tupleShape = + (ref.elementFlags as ts.ElementFlags[] | undefined) !== undefined + ? ref + : (ref.getTarget() as ts.TupleType | undefined); + const args = checker.getTypeArguments(ref); + if (args.length === 0) return []; + const flags = tupleShape?.elementFlags; + if (flags === undefined) return null; + if (flags.some((f) => !(f & (ts.ElementFlags.Required | ts.ElementFlags.Optional)))) return null; + return args.map((t, i) => ({ + type: t, + optional: (flags[i]! & ts.ElementFlags.Optional) !== 0, + })); +} + +/** One tuple element's IR type under the tuple mapping's rules. */ +function mapTupleElement(t: ts.Type, ctx: TypeMapperCtx): IrType | null { + let et = (t.flags & ts.TypeFlags.Any) !== 0 ? DYN : mapType(t, ctx); + if (et?.kind === "void" && isUnitOnlyTsType(t, ctx.resolveTypeParam)) + et = unitOnlyUnion(ctx.unions); + return !et || et.kind === "void" ? null : et; +} + +/** The mapped element types of a fixed-tuple rest parameter type + * (restTupleElementTypes), null when it is not one or an element does not + * map. */ +export function restTupleParamTypes(type: ts.Type, ctx: TypeMapperCtx): IrType[] | null { + const elems = restTupleElements(type, ctx); + if (!elems) return null; + const out: IrType[] = []; + for (const e of elems) { + let et = mapTupleElement(e.type, ctx); + // An optional position's slot holds undefined when the caller omits + // it, as an optional parameter's does (mapCallSignature). + if (et && e.optional && et.kind !== "dyn") et = withUndefinedArm(et, ctx.unions); + if (!et) return null; + out.push(et); + } + return out; +} + +/** `Parameters` (the fixed tuple of F's parameters, interned exactly as + * the spelled tuple maps) and `ReturnType` (F's mapped result) over a + * bound function-typed type parameter. */ +function mapBoundSignatureAlias(type: ts.Type, ctx: TypeMapperCtx): IrType | null { + const target = boundSignatureAlias(type, ctx); + if (!target) return null; + if (target.name === "ReturnType") { + const ret = ctx.checker.getReturnTypeOfSignature(target.sig); + return ret.flags & ts.TypeFlags.Any ? DYN : mapType(ret, ctx); + } + const elems = signatureParameterTypes(target.sig, ctx); + if (!elems) return null; + if (elems.length === 0) return arrayOf(unitOnlyUnion(ctx.unions)); + const fields: { name: string; type: IrType }[] = []; + for (let i = 0; i < elems.length; i++) { + const et = mapTupleElement(elems[i]!, ctx); + if (!et) return null; + fields.push({ name: String(i), type: et }); + } + fields.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + return { kind: "record", shapeId: ctx.shapes.intern(fields, true) }; +} + /** `Partial` / `Readonly` where T is a STILL-GENERIC type parameter — * the one mapped-type spelling a monomorphized body can contain that the * checker cannot resolve for us (`keyof T` is unknown inside the body, so @@ -5107,13 +5418,17 @@ function mapGenericAwaitedAlias(type: ts.Type, ctx: TypeMapperCtx): IrType | nul const aliasArgs = type.getAliasTypeArguments(); const arg = aliasArgs[0]; if (aliasArgs.length !== 1 || !arg) return null; - if (!(arg.flags & ts.TypeFlags.TypeParameter)) return null; + // `Awaited>` (an async wrapper's settled result) resolves + // through F's bound signature like a bare type parameter. + const viaSignature = + arg.flags & ts.TypeFlags.TypeParameter ? null : boundSignatureAlias(arg, ctx); + if (!(arg.flags & ts.TypeFlags.TypeParameter) && viaSignature?.name !== "ReturnType") return null; // Provenance: the STANDARD LIBRARY's alias, not a user's shadowing one. const isLibAlias = alias.declarations.some( (d) => ts.isTypeAliasDeclaration(d) && ctx.isStdlibFile(d.getSourceFile()), ); if (!isLibAlias) return null; - const bound = resolveTypeParam(arg); + const bound = viaSignature ? mapBoundSignatureAlias(arg, ctx) : resolveTypeParam(arg); if (!bound) return null; let r = bound; while (r.kind === "promise") r = r.inner; @@ -5139,11 +5454,15 @@ function mapGenericIndexedAccess(type: ts.Type, ctx: TypeMapperCtx): IrType | nu const obj = type.getObjectType(); if (obj === undefined || !(obj.flags & ts.TypeFlags.TypeParameter)) return null; const bound = resolveTypeParam(obj); + const idx = type.getIndexType(); + if (idx === undefined) return null; + // `T[keyof T]` over a T bound to an unknown-valued record view + // (`Record` maps to the checked-dynamic value, see + // mapRecordType): every member reads as unknown. + if (bound?.kind === "dyn" && idx.isIndexType() && idx.getTarget() === obj) return DYN; if (!bound || bound.kind !== "record") return null; const shape = shapes.get(bound.shapeId); if (!shape || shape.tuple) return null; - const idx = type.getIndexType(); - if (idx === undefined) return null; let covered: IrType[] | null = null; if (idx.isStringLiteralType()) { const f = shape.fields.find((x) => x.name === idx.value); @@ -5160,7 +5479,62 @@ function mapGenericIndexedAccess(type: ts.Type, ctx: TypeMapperCtx): IrType | nu } if (!covered || covered.length === 0) return null; const first = covered[0]!; - return covered.every((t) => typeEquals(t, first)) ? first : null; + if (covered.every((t) => typeEquals(t, first))) return first; + // Only the `keyof T` index itself covers every field at once; a key + // parameter bound to string keeps its literal-key resolution below. + if (!(idx.isIndexType() && idx.getTarget() === obj)) return null; + // Fields of different scalar types (`Object.entries` over a bound record + // reads `T[keyof T]`): any one of them, the union of their types. + const arms: IrType[] = []; + for (const t of covered) { + const parts = t.kind === "union" ? (ctx.unions.get(t.unionId)?.arms ?? null) : [t]; + if (!parts) return null; + for (const part of parts) { + if ( + part.kind !== "f64" && + part.kind !== "string" && + part.kind !== "bool" && + part.kind !== "undefinedT" && + part.kind !== "nullT" + ) + return null; + if (!arms.some((a) => typeEquals(a, part))) arms.push(part); + } + } + if (arms.length === 1) return arms[0]!; + arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1)); + return { kind: "union", unionId: ctx.unions.intern(arms) }; +} + +/** `keyof T extends never ? A : B` over a bound record T (the lib's + * Object.entries element spelling): decided by whether the binding has any + * key. */ +function mapBoundKeyofNeverConditional(type: ts.Type, ctx: TypeMapperCtx): IrType | null { + const { resolveTypeParam, shapes } = ctx; + if (!resolveTypeParam || !type.isConditionalType()) return null; + const check = type.getCheckType(); + const ext = type.getExtendsType(); + if (!check || !ext || !(ext.flags & ts.TypeFlags.Never) || !check.isIndexType()) return null; + const target = check.getTarget(); + if (!target || !(target.flags & ts.TypeFlags.TypeParameter)) return null; + const bound = resolveTypeParam(target); + // A T bound to the checked-dynamic value (`Record`, an + // unknown-valued record view) has no static key set to decide the + // branch, but both branches of the lib's `keyof T extends never ? + // unknown : T[keyof T]` read as unknown there: one answer either way. + if (bound?.kind === "dyn") { + const whenEmpty = type.getTrueType(); + const otherwise = type.getFalseType(); + const a = whenEmpty ? mapType(whenEmpty, ctx) : null; + const b = otherwise ? mapType(otherwise, ctx) : null; + return a && b && typeEquals(a, b) ? a : null; + } + if (bound?.kind !== "record") return null; + const shape = shapes.get(bound.shapeId); + if (!shape || shape.tuple) return null; + const hasKeys = shape.fields.length > 0 || shape.indexValue !== undefined; + const branch = hasKeys ? type.getFalseType() : type.getTrueType(); + return branch ? mapType(branch, ctx) : null; } /** A mapped type over a type parameter of the instance being lowered (`{ @@ -5303,10 +5677,13 @@ function matchInferReference( const target = (t: ts.Type): ts.Type | undefined => t.isTypeReference?.() ? (t as ts.TypeReference).getTarget?.() : undefined; const wantTarget = target(extendsType) ?? extendsType.getAliasSymbol(); - if (!wantTarget) return undefined; + if (!wantTarget) return matchInferSignature(checked, extendsType, ctx); const gotTarget = target(checked) ?? checked.getAliasSymbol(); - if (!gotTarget) return checked.flags & ts.TypeFlags.Object ? undefined : false; - if (gotTarget !== wantTarget) return undefined; + if (!gotTarget) + return checked.flags & ts.TypeFlags.Object + ? matchInferThenable(checked, extendsType, ctx) + : false; + if (gotTarget !== wantTarget) return matchInferThenable(checked, extendsType, ctx); const wantArgs = target(extendsType) ? checker.getTypeArguments(extendsType as ts.TypeReference) : extendsType.getAliasTypeArguments(); @@ -5327,6 +5704,154 @@ function matchInferReference( return inferred; } +/** The type parameter an `infer X` declares, when `t` is one. */ +function inferSymbolOf(t: ts.Type, _ctx: TypeMapperCtx): ts.Symbol | undefined { + if (!(t.flags & ts.TypeFlags.TypeParameter)) return undefined; + const symbol = t.getSymbol(); + return symbol && + symbol.declarations.some((d) => d.parent !== undefined && ts.isInferTypeNode(d.parent)) + ? symbol + : undefined; +} + +/** `checked extends (...args: any) => infer R` — the shape of the standard + * library's ReturnType, over a concrete function type: R binds to its + * result. Pattern parameters must be `any` or `any[]`, and a pattern rest + * `any` or `any[]`; anything else stays undecided. The match follows + * TypeScript's assignability: a primitive never matches a function type, + * a function that needs more arguments than a pattern without a rest + * passes never matches, and a positional `any[]` parameter needs the + * function's parameter there to accept an array. */ +function matchInferSignature( + checked: ts.Type, + extendsType: ts.Type, + ctx: TypeMapperCtx, +): Map | false | undefined { + const { checker } = ctx; + const wantSigs = checker.getCallSignatures(extendsType); + const want = wantSigs[0]; + if (wantSigs.length !== 1 || !want || want.getTypeParameters().length > 0) return undefined; + const wantShape = signatureShape(want, ctx); + if (wantShape === undefined) return undefined; + const isAny = (t: ts.Type): boolean => (t.flags & ts.TypeFlags.Any) !== 0; + const isAnyArray = (t: ts.Type): boolean => + checker.isArrayType(t) && isAny(checker.getTypeArguments(t as ts.TypeReference)[0]!); + if (!wantShape.params.every((p) => isAny(p.type) || isAnyArray(p.type))) return undefined; + if (wantShape.rest !== null && !isAny(wantShape.rest)) return undefined; + if (!(checked.flags & ts.TypeFlags.Object)) return false; + const gotSigs = checker.getCallSignatures(checked); + const got = gotSigs[0]; + if (gotSigs.length !== 1 || !got || got.getTypeParameters().length > 0) return undefined; + const gotShape = signatureShape(got, ctx); + if (gotShape !== undefined) { + // `(a: any) => infer R` rejects `(a: string, b: string) => R` and + // `(...args: [string, number]) => R`: they need more arguments. + if (wantShape.rest === null && requiredArguments(gotShape) > wantShape.params.length) + return false; + for (let i = 0; i < wantShape.params.length; i++) { + if (!isAnyArray(wantShape.params[i]!.type)) continue; + const param = gotShape.params[i]?.type ?? gotShape.rest; + if (param === undefined || param === null) continue; + const accepts = acceptsArray(param, ctx); + if (accepts !== true) return accepts; + } + } else if (wantShape.params.some((p) => isAnyArray(p.type))) { + return undefined; + } + const wantRet = checker.getReturnTypeOfSignature(want); + const infer = inferSymbolOf(wantRet, ctx); + if (infer) return new Map([[infer, checker.getReturnTypeOfSignature(got)]]); + return wantRet.flags & ts.TypeFlags.Any ? new Map() : undefined; +} + +/** A signature's parameters as a call sees them: the positional ones, with + * a fixed-tuple rest (`...args: [A, B?]`) flattened into positions, and the + * element type of an array rest (`any` for `...args: any`). Undefined when + * a parameter has no declaration, or the rest is a variadic tuple or + * another type. */ +function signatureShape( + sig: ts.Signature, + ctx: TypeMapperCtx, +): { params: { type: ts.Type; optional: boolean }[]; rest: ts.Type | null } | undefined { + const { checker } = ctx; + const params: { type: ts.Type; optional: boolean }[] = []; + for (const p of sig.getParameters()) { + const decl = p.valueDeclaration; + if (decl === undefined || !ts.isParameter(decl)) return undefined; + const type = checker.getTypeOfSymbol(p); + if (decl.dotDotDotToken === undefined) { + params.push({ + type, + optional: decl.questionToken !== undefined || decl.initializer !== undefined, + }); + continue; + } + if (type.flags & ts.TypeFlags.Any) return { params, rest: type }; + if (checker.isArrayType(type)) + return { params, rest: checker.getTypeArguments(type as ts.TypeReference)[0]! }; + const elems = restTupleElements(type, ctx); + if (!elems) return undefined; + for (const e of elems) params.push({ type: e.type, optional: e.optional }); + return { params, rest: null }; + } + return { params, rest: null }; +} + +/** The fewest arguments a call must pass: up to the last required position. */ +function requiredArguments(shape: { params: { optional: boolean }[] }): number { + let required = 0; + shape.params.forEach((p, i) => { + if (!p.optional) required = i + 1; + }); + return required; +} + +/** Whether a parameter of this type accepts an `any[]` argument: true for + * `any`, `unknown` and array types, false for primitives, undefined + * otherwise. */ +function acceptsArray(t: ts.Type, ctx: TypeMapperCtx): boolean | undefined { + if (t.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) return true; + if (ctx.checker.isArrayType(t)) return true; + const primitive = + ts.TypeFlags.StringLike | + ts.TypeFlags.NumberLike | + ts.TypeFlags.BooleanLike | + ts.TypeFlags.BigIntLike | + ts.TypeFlags.ESSymbolLike | + ts.TypeFlags.Undefined | + ts.TypeFlags.Null | + ts.TypeFlags.Void; + return t.flags & primitive ? false : undefined; +} + +/** `checked extends PromiseLike` (or `Promise`) over the + * standard library's Promise: U binds to the settled type. An object with + * no `then` member is no thenable. Everything else stays undecided. */ +function matchInferThenable( + checked: ts.Type, + extendsType: ts.Type, + ctx: TypeMapperCtx, +): Map | false | undefined { + const { checker } = ctx; + const stdlibNamed = (t: ts.Type, names: readonly string[]): boolean => { + const symbol = t.getSymbol(); + return ( + symbol !== undefined && + names.includes(symbol.name) && + symbol.declarations.some((d) => ctx.isStdlibFile(d.getSourceFile())) + ); + }; + if (!stdlibNamed(extendsType, ["PromiseLike", "Promise"])) return undefined; + const wantArgs = checker.getTypeArguments(extendsType as ts.TypeReference); + const infer = wantArgs.length === 1 ? inferSymbolOf(wantArgs[0]!, ctx) : undefined; + if (!infer) return undefined; + if (stdlibNamed(checked, ["Promise", "PromiseLike"])) { + const gotArgs = checker.getTypeArguments(checked as ts.TypeReference); + return gotArgs.length === 1 ? new Map([[infer, gotArgs[0]!]]) : undefined; + } + return checker.getPropertyOfType(checked, "then") === undefined ? false : undefined; +} + /** The type mentions a mapped key or bound alias parameter (a template * shape evalMappedTemplate does not reduce). */ function mentionsMappedParams( @@ -5490,10 +6015,22 @@ export function isUnitOnlyTsType(t: ts.Type, resolveTypeParam?: TypeParamResolve return parts.every( (p) => (p.flags & UNIT) !== 0 || - ((p.flags & ts.TypeFlags.TypeParameter) !== 0 && resolveTypeParam?.(p)?.kind === "void"), + ((p.flags & ts.TypeFlags.TypeParameter) !== 0 && resolveTypeParam?.(p)?.kind === "void") || + boundVoidReturnType(p, resolveTypeParam), ); } +/** `ReturnType` over a type parameter bound to a void-returning + * function (a variadic wrapper's result slot): a unit-only value. */ +function boundVoidReturnType(p: ts.Type, resolveTypeParam?: TypeParamResolver): boolean { + if (!resolveTypeParam || p.getAliasSymbol()?.name !== "ReturnType") return false; + const args = p.getAliasTypeArguments(); + const arg = args[0]; + if (args.length !== 1 || !arg || !(arg.flags & ts.TypeFlags.TypeParameter)) return false; + const bound = resolveTypeParam(arg); + return bound?.kind === "func" && bound.ret.kind === "void"; +} + /** IR-level `t | undefined`, canonicalized and fenced exactly like the * ts-union branch of mapType (typeKey-sorted arms, deduplicated; * Date/dyn/void arms unrepresentable; a func arm IS representable — the @@ -5626,6 +6163,7 @@ function mapErrorMetadataIntersection(type: ts.Type, ctx: TypeMapperCtx): IrType }); if (!hasError) return null; let error: IrType | null = null; + const extra: ts.Symbol[] = []; for (const part of parts) { const mapped = mapType(part, ctx); if (mapped?.kind === "object" && RUNTIME_ERROR_CLASSES.has(mapped.className)) { @@ -5646,14 +6184,45 @@ function mapErrorMetadataIntersection(type: ts.Type, ctx: TypeMapperCtx): IrType : ["code", "syscall", "path", "dest"].includes(property.name) ? "string" : null; - if (!expected || !(property.flags & ts.SymbolFlags.Optional)) return null; + if (!expected) { + extra.push(property); + continue; + } const field = mapType(ctx.checker.getTypeOfSymbol(property), ctx); const arms = field?.kind === "union" ? ctx.unions.get(field.unionId)?.arms : field ? [field] : []; if (!arms?.length || !arms.every((arm) => arm.kind === expected || arm.kind === "undefinedT")) return null; + // A required member must still admit the absent value the slot reads. + if ( + !(property.flags & ts.SymbolFlags.Optional) && + !arms.some((arm) => arm.kind === "undefinedT") + ) + return null; } } + if (!error) return null; + // Members beyond Error's own and the system-error metadata (`Error & { + // status: number }`, Object.assign's result) are own properties of the + // error's checked-dynamic node: each must map to a type a checked read + // can produce. Error's own string members keep their slots. + for (const property of extra) { + const field = mapType(ctx.checker.getTypeOfSymbol(property), ctx); + if (!field || field.kind === "void") return null; + if (property.name === "message" || property.name === "name") { + if (field.kind !== "string") return null; + continue; + } + if (property.name === "stack" || property.name === "cause") return null; + if ( + !canDynCheckTo( + field, + (id) => ctx.shapes.get(id), + (id) => ctx.unions.get(id), + ) + ) + return null; + } return error; } @@ -6161,6 +6730,8 @@ function mapRecordType(widened: ts.Type, ctx: TypeMapperCtx): IrType | null { (inner.indexValue === undefined || inner.indexValue.kind === "dyn") ) return DYN; + const covered = coveredOptionalFieldsShape(widened, inner, ctx); + if (covered !== null) return { kind: "record", shapeId: covered }; const merged = dictSpreadLiteralShape(widened, inner, ctx); if (merged === "dyn") return DYN; if (merged !== null) return { kind: "record", shapeId: merged }; @@ -6174,6 +6745,51 @@ function mapRecordType(widened: ts.Type, ctx: TypeMapperCtx): IrType | null { } } +/** An index signature already describes every OPTIONAL declared member + * whose type is its slot type: @types/node's `ProcessEnv extends + * Dict { TZ?: string }` and every spread of it, or a declared + * environment `{ CI?: string } & Dictionary`. At runtime such a + * member is just another key, so the shape interns as the pure + * index-signature record. Its slot admits undefined, as the optional + * members do (`env.CI = undefined` keeps the key). A hybrid layout would + * give each member a struct slot, which enumerates before the overflow + * keys (Node keeps one insertion order) and makes `delete` and spread + * answer differently for declared and undeclared keys. Required members, + * and members typed otherwise than the slot (whose reads the slot type + * could not give back), keep the hybrid shape. */ +function coveredOptionalFieldsShape( + widened: ts.Type, + parts: RecordShapeParts, + ctx: TypeMapperCtx, +): string | null { + const slot = parts.indexValue; + if (!slot || parts.fields.length === 0) return null; + const { checker, shapes, unions } = ctx; + // The members' common type must be the slot plus undefined. Read it off + // the members (already interned) rather than building it: a hybrid that + // does not qualify must not intern anything new. + const optionalSlot = parts.fields[0]!.type; + if (!parts.fields.every((field) => typeEquals(field.type, optionalSlot))) return null; + if (optionalSlot.kind !== "union" || unions.armTag(optionalSlot.unionId, UNDEFINED_T) < 0) + return null; + const memberArms = unions.get(optionalSlot.unionId)?.arms ?? []; + const slotArms = + slot.kind === "union" ? (unions.get(slot.unionId)?.arms ?? []) : isUnitType(slot) ? [] : [slot]; + const definedArms = memberArms.filter((arm): boolean => arm.kind !== "undefinedT"); + const slotDefined = slotArms.filter((arm): boolean => arm.kind !== "undefinedT"); + if ( + definedArms.length === 0 || + definedArms.length !== slotDefined.length || + !slotDefined.every((arm) => definedArms.some((other) => typeEquals(arm, other))) + ) + return null; + if (!isSupportedIndexValue(optionalSlot)) return null; + const props = checker.getPropertiesOfType(widened); + if (props.length !== parts.fields.length) return null; + if (!props.every((p) => (p.flags & ts.SymbolFlags.Optional) !== 0)) return null; + return shapes.intern([], false, optionalSlot, []); +} + /** The type of an object literal that spreads an index-signature record * (`{ ...tags, bucket: b, status }`, the metric-tags idiom). The checker * drops the signature and types the literal by its explicit members only, diff --git a/packages/compiler/src/index.ts b/packages/compiler/src/index.ts index b6ed2d443..7b1ef7109 100644 --- a/packages/compiler/src/index.ts +++ b/packages/compiler/src/index.ts @@ -535,6 +535,7 @@ async function compileExecutableNative( fileHandle: features.fileHandle, fetch: features.fetch, ...(features.eventTarget ? { eventTarget: true } : {}), + ...(features.wasm ? { wasm: true } : {}), ...(features.warningReplace ? { warningReplace: true } : {}), ...(features.stdioExtended ? { stdioExtended: true } : {}), zlib: features.zlib, @@ -550,6 +551,7 @@ async function compileExecutableNative( bigint: features.bigint, searchParams: features.searchParams, qs: features.qs, + dynBuiltinClass: features.dynBuiltinClass, parseArgs: features.parseArgs, stream: features.stream, net: features.net, @@ -566,6 +568,7 @@ async function compileExecutableNative( tlsCa: features.tlsCa, cipher: features.cipher, webcrypto: features.webcrypto, + perfLoop: features.perfLoop, ...(onArtifactReady === undefined ? {} : { onArtifactReady }), ...(ffi === null ? {} @@ -730,6 +733,7 @@ async function prepareExecutableInput( wasi: buildPlatform === "wasi", runtimeAbiMarker: outputKind === "obj", objectAudit: opts.sanitize === true, + ...(opts.sanitize === true ? { wasmBoundsChecks: true } : {}), ...inlineRcOption(opts.optimization, opts.sanitize === true), }); } catch (err) { @@ -795,6 +799,7 @@ async function prepareExecutableInput( wasi: buildPlatform === "wasi", runtimeAbiMarker: useRuntimePack, objectAudit: opts.sanitize === true, + ...(opts.sanitize === true ? { wasmBoundsChecks: true } : {}), ...inlineRcOption(opts.optimization, opts.sanitize === true), ...(opts.detachedExit === true ? { detachedExit: true } : {}), }); diff --git a/packages/compiler/src/ir/builtin-effects.ts b/packages/compiler/src/ir/builtin-effects.ts index 0cbafcb3f..142b1e25c 100644 --- a/packages/compiler/src/ir/builtin-effects.ts +++ b/packages/compiler/src/ir/builtin-effects.ts @@ -75,6 +75,8 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "process.stdoutWriteBytes", "process.stderrWriteBytes", "procStream.write", + "child.stdioStream", + "stream.unboxDyn", "weakMap.new", "weakSet.new", "dyn.fromEntries", @@ -133,6 +135,20 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "blob.new", "blob.fileNew", "blob.slice", + "wasm.compile", + "wasm.validate", + "wasm.instantiate", + "wasm.moduleNew", + "wasm.instanceNew", + "wasm.errorNew", + "wasm.memoryNew", + "wasm.tableNew", + "wasm.globalNew", + "wasm.withoutNew", + "wasm.moduleImports", + "wasm.moduleExports", + "wasm.moduleCustomSections", + "wasm.valueOf", "events.addAbortListener", "fetch.streamNew", "fetch.streamFrom", @@ -332,6 +348,7 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "stream.onDyn", "readable.resume", "readable.pipe", + "readable.pipeGeneral", "readable.unpipe", "writable.write", "writable.writeStr", @@ -375,6 +392,8 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "perf.entries", "perf.clearMarks", "perf.clearMeasures", + // monitorEventLoopDelay's resolution: Node's ERR_OUT_OF_RANGE. + "perf.eldNew", // Non-TTY stdin: Node's stdin has no setRawMode member, so the call is // the exact catchable TypeError. "process.stdinSetRawMode", @@ -411,6 +430,7 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "error.stack", "error.cause", "error.setCause", + "error.assign", "error.deleteCause", "dyn.objectTag", // Numeric coercion runs user valueOf/toString — throws propagate. @@ -567,6 +587,9 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "dyn.objCreateWithProperties", "dyn.getPrototype", "dyn.setPrototype", + // a proxy in the prototype chain can throw + "dyn.builtinInstanceOf", + "dyn.functionInstanceOf", "dyn.getOwnPropertyNames", "dyn.ownKeys", "dyn.getOwnPropertySymbols", diff --git a/packages/compiler/src/ir/builtin-signatures.ts b/packages/compiler/src/ir/builtin-signatures.ts index 8468785b9..99ca04ae4 100644 --- a/packages/compiler/src/ir/builtin-signatures.ts +++ b/packages/compiler/src/ir/builtin-signatures.ts @@ -108,6 +108,45 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "blob.bytes": { argTypes: [DYN], result: { kind: "promise", inner: BYTES_U8 } }, "blob.arrayBuffer": { argTypes: [DYN], result: { kind: "promise", inner: DYN } }, "blob.is": { argTypes: [DYN, F64], result: BOOL }, + /** WebAssembly (scr_wasm.c): modules translated at build time + * (wasm/translate.ts), found at run time by the SHA-256 of their bytes. + * compile and instantiate over bytes settle on a later loop turn; + * instantiate over a Module settles now, as in Node. `wasm.is` answers + * instanceof for Module, Instance, Memory, Table and Global (kinds 0-4) + * and CompileError, LinkError and RuntimeError (5-7); `wasm.errorNew` + * constructs one of the error classes (kind 5-7, message, options). */ + "wasm.compile": { argTypes: [DYN], result: { kind: "promise", inner: DYN } }, + "wasm.validate": { argTypes: [DYN], result: BOOL }, + "wasm.instantiate": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } }, + "wasm.moduleNew": { argTypes: [DYN], result: DYN }, + "wasm.instanceNew": { argTypes: [DYN, DYN], result: DYN }, + "wasm.is": { argTypes: [DYN, F64], result: BOOL }, + "wasm.errorNew": { argTypes: [F64, DYN, DYN], result: DYN }, + /** new WebAssembly.Memory(descriptor), Table(descriptor, value) and + * Global(descriptor, value) (an undefined value is the type's default); + * `wasm.withoutNew` throws the TypeError for Module, Instance, Memory, + * Table or Global (kinds 0-4) called without new, after its arguments + * evaluate. */ + "wasm.memoryNew": { argTypes: [DYN], result: DYN }, + "wasm.tableNew": { argTypes: [DYN, DYN], result: DYN }, + "wasm.globalNew": { argTypes: [DYN, DYN], result: DYN }, + "wasm.withoutNew": { argTypes: [F64, DYN, DYN], result: DYN }, + /** WebAssembly.Module.imports(module), exports(module) and + * customSections(module, name): checked-dynamic arrays of descriptor + * objects and ArrayBuffers. */ + "wasm.moduleImports": { argTypes: [DYN], result: DYN }, + "wasm.moduleExports": { argTypes: [DYN], result: DYN }, + "wasm.moduleCustomSections": { argTypes: [DYN, DYN], result: DYN }, + /** `v.valueOf()` on a WebAssembly-typed receiver: a Global's value, + * dyn.valueOf's answer for anything else. */ + "wasm.valueOf": { argTypes: [DYN], result: DYN }, + /** WebAssembly.compile (0), instantiate (1) and validate (2) as function + * values, and the namespace object holding them. */ + "wasm.function": { argTypes: [F64], result: DYN }, + "wasm.namespace": { argTypes: [], result: DYN }, + /** The global object viewed through a cast to a type with a WebAssembly + * member: an object holding the namespace. */ + "wasm.globalView": { argTypes: [], result: DYN }, "abort.timeout": { argTypes: [DYN], result: DYN }, "abort.now": { argTypes: [DYN], result: DYN }, "abort.any": { argTypes: [DYN], result: DYN }, @@ -401,6 +440,20 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "perf.entryDetail": { argTypes: [F64], result: DYN }, "perf.entryKeep": { argTypes: [DYN], result: VOID }, "perf.entryRef": { argTypes: [F64], result: DYN }, + /** perf_hooks event-loop metrics (scr_perf_loop.c): loopStart is the + * loop's start in performance.now() ms (0 before it), idleTime the idle + * ms since. eldNew(resolution ms) creates a monitorEventLoopDelay + * histogram handle (MAY THROW Node's resolution RangeError); enable/disable answer whether the state changed; + * eldPercentile expects Node's validated range; eldStat(which) reads + * 0 min, 1 max, 2 mean, 3 stddev, 4 count, 5 exceeds. */ + "perf.loopStart": { argTypes: [], result: F64 }, + "perf.idleTime": { argTypes: [], result: F64 }, + "perf.eldNew": { argTypes: [F64], result: F64 }, + "perf.eldEnable": { argTypes: [F64], result: BOOL }, + "perf.eldDisable": { argTypes: [F64], result: BOOL }, + "perf.eldReset": { argTypes: [F64], result: VOID }, + "perf.eldPercentile": { argTypes: [F64, F64], result: F64 }, + "perf.eldStat": { argTypes: [F64, F64], result: F64 }, /** process.memoryUsage(): memoryUsageTake samples the resident set and * the runtime heap once (MAY THROW Node's uv_resident_set_memory error) * and memoryUsageField(k) reads that sample (0 rss, 1 heapTotal, 2 @@ -2594,8 +2647,13 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ * queue, end/destroy settle it, writable is a pure state read, and * listener callbacks move into the writer registry. */ "child.stdin": { argTypes: [CHILD_T], result: VOID }, + /** Under the general stream representation (general-streams.ts), a + * stdio read (slot 0, 1 or 2) answers the child's bridged runtime stream + * — `Writable | null` for stdin, `Readable | null` otherwise; the bridge + * throws when the program lacks the stream unit's boxing helpers. */ + "child.stdioStream": { argTypes: [CHILD_T, F64], result: VOID }, // Listener registrations: callback func shapes are program-dependent - // (zero-param / Buffer / Buffer-armed union) — the slots pin arity, + // (zero-param / Buffer / string / unknown / Buffer-armed union) — the slots pin arity, // the stream receiver, and the once-flag. "stream.onData": { argTypes: [CHILDSTREAM_T, null, BOOL], result: VOID }, "stream.onDataStr": { argTypes: [CHILDSTREAM_T, null, BOOL], result: VOID }, @@ -2615,6 +2673,21 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ * stderrWrite paths so buffering and ordering stay identical. Data * borrowed; the bool is Node's always-true backpressure signal. */ "procStream.write": { argTypes: [PROCSTREAM_T, STRING], result: BOOL }, + /** process.stdout/stderr flowing into a runtime Writable slot under the + * general stream representation: an fd-backed Writable (+1) whose + * writes take process.stdout.write's synchronous path. */ + /** A pipeline() stage that is a checked-dynamic value: a boxed native + * stream unwraps by identity (+1); anything else throws the given + * not-supported message. Typed as a Duplex so every stage position + * accepts it; the runtime pipeline checks the stream's real sides. */ + "stream.unboxDyn": { + argTypes: [DYN, STRING], + result: { kind: "object", className: "%Duplex" }, + }, + "stream.stdioWritable": { + argTypes: [PROCSTREAM_T], + result: { kind: "object", className: "%Writable" }, + }, "child.killed": { argTypes: [CHILD_T], result: BOOL }, "child.kill": { argTypes: [CHILD_T, STRING], result: BOOL }, "child.killNum": { argTypes: [CHILD_T, F64], result: BOOL }, @@ -3203,6 +3276,23 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "error.hasCause": { argTypes: [null], result: BOOL }, /** Assignment borrows both operands and retains the new cause. */ "error.setCause": { argTypes: [null, DYN], result: VOID }, + /** `err.code = s` on an error-hierarchy receiver: the code slot that + * error.code reads and coded throws stamp. Borrows both; never throws. */ + "error.setCode": { argTypes: [null, STRING], result: VOID }, + /** `err.code = v` with a value that is not statically a string: strings + * take the code slot, anything else clears it and sets the dynamic own + * property. Borrows both; never throws. */ + "error.setCodeDyn": { argTypes: [null, DYN], result: VOID }, + /** `Object.assign(err, ...sources)` onto an error-hierarchy receiver + * (args: the error, a dyn array of the sources): the own-member copy + * onto its checked-dynamic node, then the typed slots (name, message, + * stack, cause, code) re-read from it. Throws what the copy throws. */ + "error.assign": { argTypes: [null, DYN], result: VOID }, + /** `key in err` for a key no compiled class of the receiver declares + * (args: the error, the key): a runtime-set own property (Object.assign, + * throw-site fields, dynamic writes) or an Object.prototype member. */ + "error.hasKey": { argTypes: [null, STRING], result: BOOL }, + "error.hasCode": { argTypes: [null], result: BOOL }, "error.defineCause": { argTypes: [null, DYN], result: VOID }, "error.deleteCause": { argTypes: [null], result: VOID }, /** The compiler-resolved Node-parity throw for always-throwing lowered @@ -3495,6 +3585,16 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "dyn.classPrototype": { argTypes: [DYN, DYN], result: DYN }, "dyn.classBasePrototype": { argTypes: [DYN], result: DYN }, "dyn.classInherit": { argTypes: [DYN, DYN], result: DYN }, + /** EventEmitter (0), Stream (1), Readable (2), Writable (3), Duplex (4), + * Transform (5) and PassThrough (6) as untyped constructor values, one + * per thread (scr_dyn_builtin_class.c). */ + "dyn.builtinClass": { argTypes: [F64], result: DYN }, + /** `value instanceof C` for those constructors, over the value's + * prototype chain. */ + "dyn.builtinInstanceOf": { argTypes: [DYN, F64], result: BOOL }, + /** `value instanceof f` for an untyped constructor function: the + * prototype chain against f.prototype. */ + "dyn.functionInstanceOf": { argTypes: [DYN, DYN], result: BOOL }, "dyn.classSuper": { argTypes: [DYN, DYN, DYN], result: VOID }, "dyn.assignPrototype": { argTypes: [DYN, DYN, DYN], result: DYN }, "dyn.definePrototypeProps": { argTypes: [DYN, DYN, DYN], result: DYN }, @@ -3652,7 +3752,9 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ * returns the below-hwm answer. readable.read: (recv, size — -1 for * absent) → Buffer|null union. pause/resume return recv +1 (`this`); * isPaused answers the flag. readable.pipe: (recv, dst, end) → dst +1, - * fires 'pipe' on dst; readable.unpipe (recv[, dst]) → recv +1. + * fires 'pipe' on dst; readable.pipeGeneral: the same, with `end` off + * when dst is the converted process.stdout / process.stderr; + * readable.unpipe (recv[, dst]) → recv +1. * writable.write/writeStr: (recv, chunk[, cb]) → below-hwm bool (cb * MOVES when present, called after the user write completes). * writable.end: (recv, flags[, chunk][, cb]) → recv +1. cork/uncork are @@ -3850,6 +3952,7 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "readable.resume": { argTypes: [null], result: VOID }, "readable.isPaused": { argTypes: [null], result: BOOL }, "readable.pipe": { argTypes: [null, null, BOOL], result: VOID }, + "readable.pipeGeneral": { argTypes: [null, null, BOOL], result: VOID }, "readable.unpipe": { argTypes: [null], result: VOID }, "readable.flowing": { argTypes: [null], result: VOID }, "writable.write": { argTypes: [null, BYTES_U8], result: BOOL }, diff --git a/packages/compiler/src/ir/function-references.test.ts b/packages/compiler/src/ir/function-references.test.ts index 23bcb86ef..4ecc60a6f 100644 --- a/packages/compiler/src/ir/function-references.test.ts +++ b/packages/compiler/src/ir/function-references.test.ts @@ -212,6 +212,8 @@ const MODULE_FIELDS: Record>, Role> = { "contracts.acyclic[]": "other", "contracts.immortalGlobals[]": "other", "contracts.programLifetime[]": "other", + "wasmModules[].sha256": "other", + "wasmModules[].bytes": "other", "threadSlotKeys[]": "other", }; diff --git a/packages/compiler/src/ir/ir.ts b/packages/compiler/src/ir/ir.ts index 6d63007fb..4c5bbd183 100644 --- a/packages/compiler/src/ir/ir.ts +++ b/packages/compiler/src/ir/ir.ts @@ -1044,6 +1044,24 @@ export interface IrModule { * write in the program (ir/contract-check.ts). Backends may rely on them * unconditionally. Absent when the program writes no contract. */ contracts?: IrContracts; + /** The WebAssembly modules translated into this program (wasm/ + * translate.ts), present exactly when the program uses the WebAssembly + * API (possibly empty). The backend appends each module's translation + * and emits the registry the runtime looks modules up in. */ + wasmModules?: IrWasmModule[]; + /** The program calls WebAssembly.Module.customSections, so translated + * modules keep their custom sections (otherwise they carry none, and + * debug sections cost nothing). */ + wasmCustomSections?: boolean; +} + +/** A WebAssembly module whose bytes the build saw, validated within the + * translatable feature level. */ +export interface IrWasmModule { + /** Hex SHA-256 of the bytes. */ + sha256: string; + /** The bytes, base64. */ + bytes: string; } /** Verified contract facts, keyed by IR names. */ diff --git a/packages/compiler/src/ir/runtime-features.ts b/packages/compiler/src/ir/runtime-features.ts index caa39e66c..b52afafcb 100644 --- a/packages/compiler/src/ir/runtime-features.ts +++ b/packages/compiler/src/ir/runtime-features.ts @@ -149,6 +149,7 @@ const ABORT_SIGNAL_LIB_FNS: ReadonlySet = new Set([ /** Entry points that link the stream unit (with STREAM_LIB_PREFIXES). */ const STREAM_LIB_FNS: ReadonlySet = new Set([ + "child.stdioStream", "console.bind", "crypto.hashStream", "crypto.hashStreamPiped", @@ -167,6 +168,8 @@ const STREAM_LIB_FNS: ReadonlySet = new Set([ "stream.destroyErr", "stream.errored", "stream.prop", + "stream.stdioWritable", + "stream.unboxDyn", "stream.workerStdio", ]); @@ -238,8 +241,21 @@ const CHILD_PROCESS_LIB_FNS: ReadonlySet = new Set([ /** libCall name prefixes that link the child-process unit. */ const CHILD_PROCESS_LIB_PREFIXES: readonly string[] = ["child.", "cp.", "spawnRes.", "writer."]; +/** The entry points scr_dyn_builtin_class.c defines. The unit calls + * listeners through the dyn-invoke unit, renders unhandled 'error' + * payloads through the inspect unit, creates EventEmitter's private + * symbols through the symbol unit and shares defaultMaxListeners with the + * emitter unit, so each of them links all five. */ +const BUILTIN_CLASS_LIB_FNS: readonly IrLibFn[] = [ + "dyn.builtinClass", + "dyn.builtinInstanceOf", + "dyn.functionInstanceOf", +]; + /** Entry points that link the symbol unit, besides the sym. and disposable. families. */ const SYMBOL_LIB_FNS: ReadonlySet = new Set([ + // EventEmitter's kShapeMode and kCapture properties + ...BUILTIN_CLASS_LIB_FNS, "dyn.usingDispose", "dyn.usingMethod", "util.isDeepStrictEqual", @@ -467,7 +483,12 @@ const RUNTIME_FEATURE_RULES = { * queueMicrotask scheduling goes through the runtime's *_als entry * points, which carry the active stores into each callback. */ asyncContext: rule({ fns: [...ASYNC_CONTEXT_LIB_FNS] }), - bigint: rule({ fns: ["process.hrtimeValue"], prefixes: ["bigint."], types: ["bigint"] }), + /** scr_wasm.c converts i64 values through BigInt. */ + bigint: rule({ + fns: ["process.hrtimeValue"], + prefixes: ["bigint.", "wasm."], + types: ["bigint"], + }), childProcess: rule({ fns: [...CHILD_PROCESS_LIB_FNS], prefixes: CHILD_PROCESS_LIB_PREFIXES, @@ -494,14 +515,15 @@ const RUNTIME_FEATURE_RULES = { (fn) => fn.async === true && fn.generator === undefined && fn.returnType.kind === "dyn", ), // The legacy url functions and crypto.createCipheriv emit their - // deprecation warnings through the dyn-async unit. + // deprecation warnings through the dyn-async unit; scr_wasm.c boxes its + // handles and promises through it. fns: [ ...DYN_ASYNC_LIB_FNS, ...READABLE_DYN_ASYNC_LIB_FNS, ...LEGACY_URL_LIB_FNS, "crypto.cipherNew", ], - prefixes: READABLE_DYN_ASYNC_PREFIXES, + prefixes: [...READABLE_DYN_ASYNC_PREFIXES, "wasm."], expr: (node, tables) => (node.kind === "awaitExpr" && node.type.kind === "dyn") || // Rejection reasons cross as dyn values (allSettled's records, any's @@ -510,9 +532,16 @@ const RUNTIME_FEATURE_RULES = { (node.name === "promise.allSettled" || node.name === "promise.any")) || (node.kind === "dynFrom" && boxesPromise(node.value.type, tables(), new Set())), }), + /** EventEmitter and the stream classes as untyped constructor values + * (scr_dyn_builtin_class.c), which call listeners through the dyn-invoke + * unit, render unhandled 'error' payloads through the inspect unit and + * create EventEmitter's private symbols through the symbol unit. */ + dynBuiltinClass: rule({ + fns: [...BUILTIN_CLASS_LIB_FNS], + }), dynInvoke: rule({ initial: (mod) => mod.workers === true, - fns: [...DYN_INVOKE_LIB_FNS, ...UTIL_CALLABLE_LIB_FNS], + fns: [...DYN_INVOKE_LIB_FNS, ...UTIL_CALLABLE_LIB_FNS, ...BUILTIN_CLASS_LIB_FNS], // Constant-key reads of Object.prototype member names answer the // inherited member through scr_dyn_invoke.c. expr: (node, _tables) => @@ -529,7 +558,7 @@ const RUNTIME_FEATURE_RULES = { emitter: rule({ initial: (mod) => mod.workers === true || (mod.classes ?? []).some((c) => c.name === RUNTIME_EMITTER_CLASS), - fns: [...STREAM_LIB_FNS], + fns: [...STREAM_LIB_FNS, ...BUILTIN_CLASS_LIB_FNS], prefixes: ["emitter.", ...STREAM_LIB_PREFIXES], }), /** Subclasses of the runtime EventTarget/Event bases tear down and box @@ -563,7 +592,13 @@ const RUNTIME_FEATURE_RULES = { * terminal unit prints completion errors through it when there is a * completer. */ inspect: rule({ - fns: ["global.native", "util.styleText", "crypto.cipherNew", ...UTIL_CALLABLE_LIB_FNS], + fns: [ + "global.native", + "util.styleText", + "crypto.cipherNew", + ...BUILTIN_CLASS_LIB_FNS, + ...UTIL_CALLABLE_LIB_FNS, + ], prefixes: ["insp.", "console.", "test."], libCall: (node) => node.fn === "rl.terminal" && !isDynUndefined(node.args[3]!), }), @@ -588,6 +623,9 @@ const RUNTIME_FEATURE_RULES = { /** scr_util_callable.c reads options through the parseArgs unit's * descriptors. */ parseArgs: rule({ fns: [...PARSE_ARGS_LIB_FNS, ...UTIL_CALLABLE_LIB_FNS] }), + /** perf_hooks event-loop metrics (eventLoopUtilization, + * monitorEventLoopDelay): scr_perf_loop.c. */ + perfLoop: rule({ fns: ["perf.idleTime"], prefixes: ["perf.loop", "perf.eld"] }), processEvents: rule({ fns: [...PROCESS_EVENT_LIB_FNS, "util.styleText"], types: ["procStream"] }), /** scr_url_legacy.c parses and stringifies queries. */ qs: rule({ fns: [...QS_LIB_FNS, ...LEGACY_URL_LIB_FNS] }), @@ -640,6 +678,8 @@ const RUNTIME_FEATURE_RULES = { tlsCa: rule({ prefixes: ["tlsca."] }), /** process.emitWarning is assigned (process.setEmitWarning). */ warningReplace: rule({ fns: ["process.setEmitWarning"] }), + /** The WebAssembly API (scr_wasm.c). */ + wasm: rule({ prefixes: ["wasm."] }), /** crypto.subtle importKey/sign/verify/digest and CryptoKey: * scr_webcrypto.c. */ webcrypto: rule({ prefixes: ["webcrypto."] }), @@ -667,6 +707,7 @@ function noRuntimeFeatures(): RuntimeFeatures { dgram: false, dnsPromises: false, dynAsync: false, + dynBuiltinClass: false, dynInvoke: false, dynTier: false, emitter: false, @@ -683,6 +724,7 @@ function noRuntimeFeatures(): RuntimeFeatures { net: false, nodeTest: false, parseArgs: false, + perfLoop: false, processEvents: false, qs: false, regex: false, @@ -693,6 +735,7 @@ function noRuntimeFeatures(): RuntimeFeatures { tls: false, tlsCa: false, warningReplace: false, + wasm: false, webcrypto: false, zlib: false, }; diff --git a/packages/compiler/src/ir/validate.ts b/packages/compiler/src/ir/validate.ts index 84827e787..835dfa8ba 100644 --- a/packages/compiler/src/ir/validate.ts +++ b/packages/compiler/src/ir/validate.ts @@ -4113,6 +4113,11 @@ function validateFunction( e.fn === "error.cause" || e.fn === "error.hasCause" || e.fn === "error.setCause" || + e.fn === "error.setCode" || + e.fn === "error.setCodeDyn" || + e.fn === "error.assign" || + e.fn === "error.hasKey" || + e.fn === "error.hasCode" || e.fn === "error.defineCause" || e.fn === "error.deleteCause" ) { @@ -5228,6 +5233,20 @@ function validateFunction( } return true; } + if (e.fn === "child.stdioStream") { + const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined; + const slot = e.args[1]; + const className = + slot?.kind === "numLit" ? (slot.value === 0 ? "%Writable" : "%Readable") : null; + const ok = + def && + className !== null && + def.arms.length === 2 && + def.arms.some((a) => a.kind === "object" && a.className === className) && + def.arms.some((a) => a.kind === "nullT"); + if (!ok) err(`libCall ${e.fn} must return the stream class of its stdio slot or null`, e.loc); + return true; + } if (e.fn === "child.stdin" || e.fn === "child.stdout" || e.fn === "child.stderr") { const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined; const handleKind = e.fn === "child.stdin" ? "childWriter" : "childStream"; @@ -5719,9 +5738,9 @@ function validateFunction( } return true; } - if (e.fn === "readable.pipe") { + if (e.fn === "readable.pipe" || e.fn === "readable.pipeGeneral") { if (!isStreamObject(e.args[1]?.type) || !typeEquals(e.type, e.args[1]!.type)) { - err(`libCall readable.pipe must return its destination's type`, e.loc); + err(`libCall ${e.fn} must return its destination's type`, e.loc); } return true; } diff --git a/packages/compiler/src/library/ir-policy.ts b/packages/compiler/src/library/ir-policy.ts index 2d1bc85d4..0c343fa98 100644 --- a/packages/compiler/src/library/ir-policy.ts +++ b/packages/compiler/src/library/ir-policy.ts @@ -54,6 +54,11 @@ const LIB_MODE_REFUSED_PREFIXES: readonly [string, string][] = [ ["webcrypto.", "WebCrypto (crypto.subtle)"], ["fs.watch", "fs.watch"], ["watcher.", "fs.watch"], + // The event-loop metrics sample the loop and its timers (scr_perf_loop.c), + // which library links exclude. + ["perf.loopStart", "performance.eventLoopUtilization"], + ["perf.idleTime", "performance.eventLoopUtilization"], + ["perf.eld", "perf_hooks.monitorEventLoopDelay"], ["test.", "the node:test surface"], ["readable.", "the node:stream surface"], ["writable.", "the node:stream surface"], @@ -158,6 +163,7 @@ export function moduleLibAsyncSurface(mod: IrModule): { surface: string; loc: Sr [features.nodeTest, "the node:test surface"], [features.dynAsync, "the checked-dynamic async surface"], [features.dc, "the diagnostics_channel surface"], + [features.perfLoop, "the perf_hooks event-loop metrics"], ]; for (const [on, surface] of coarse) { if (on) return { surface, loc: entryLoc }; diff --git a/packages/compiler/src/native/cli.ts b/packages/compiler/src/native/cli.ts index 1585b6c9e..3fa934da1 100644 --- a/packages/compiler/src/native/cli.ts +++ b/packages/compiler/src/native/cli.ts @@ -89,6 +89,7 @@ async function main(): Promise { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -102,6 +103,7 @@ async function main(): Promise { tls: false, cipher: false, webcrypto: false, + perfLoop: false, tlsCa: false, }, options.optimization ?? "release", diff --git a/packages/compiler/src/native/prepare.ts b/packages/compiler/src/native/prepare.ts index e4216f511..a2a15179f 100644 --- a/packages/compiler/src/native/prepare.ts +++ b/packages/compiler/src/native/prepare.ts @@ -143,6 +143,7 @@ function validFeatures(value: unknown): value is NativeLinkFeatures { "bigint", "searchParams", "qs", + "dynBuiltinClass", "parseArgs", "stream", "net", @@ -157,6 +158,7 @@ function validFeatures(value: unknown): value is NativeLinkFeatures { "tlsCa", "cipher", "webcrypto", + "perfLoop", ].every((name) => typeof features[name] === "boolean"); } diff --git a/packages/compiler/src/native/sanitizer.test.ts b/packages/compiler/src/native/sanitizer.test.ts index 33be5b30e..ea9690ce7 100644 --- a/packages/compiler/src/native/sanitizer.test.ts +++ b/packages/compiler/src/native/sanitizer.test.ts @@ -75,6 +75,7 @@ test.skipIf(process.platform !== "linux" && process.platform !== "darwin")( workers: false, youngNursery: false, eventTarget: false, + wasm: false, dynTier: false, warningReplace: false, stdioExtended: false, @@ -95,6 +96,7 @@ test.skipIf(process.platform !== "linux" && process.platform !== "darwin")( bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -109,6 +111,7 @@ test.skipIf(process.platform !== "linux" && process.platform !== "darwin")( tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, nativeFetch: false, netEffective: false, httpEffective: false, diff --git a/packages/compiler/src/wasm/base64.ts b/packages/compiler/src/wasm/base64.ts new file mode 100644 index 000000000..122bcd4ef --- /dev/null +++ b/packages/compiler/src/wasm/base64.ts @@ -0,0 +1,61 @@ +/* Base64 for WebAssembly module bytes: decoding inline modules found in + * source text (discover.ts) and carrying translated modules on the IR + * (IrModule.wasmModules). Plain TypeScript, so the native compiler + * compiles it too. */ + +const BASE64_VALUES = (() => { + const table = new Int16Array(128).fill(-1); + const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (let i = 0; i < alphabet.length; i++) table[alphabet.charCodeAt(i)] = i; + // base64url spellings + table["-".charCodeAt(0)] = 62; + table["_".charCodeAt(0)] = 63; + return table; +})(); + +/** Decodes standard or URL-safe base64 (padding optional); null when the + * text is not base64. */ +export function decodeBase64(text: string): Uint8Array | null { + let end = text.length; + while (end > 0 && text.charCodeAt(end - 1) === 61) end--; + if (text.length - end > 2 || end % 4 === 1) return null; + const out = new Uint8Array(Math.floor((end * 3) / 4)); + let acc = 0; + let bits = 0; + let j = 0; + for (let i = 0; i < end; i++) { + const c = text.charCodeAt(i); + const v = c < 128 ? BASE64_VALUES[c]! : -1; + if (v < 0) return null; + acc = ((acc << 6) | v) & 0xffffff; + bits += 6; + if (bits >= 8) { + bits -= 8; + out[j++] = (acc >> bits) & 0xff; + } + } + return j === out.length ? out : out.subarray(0, j); +} + +const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** Standard base64 with padding. */ +export function encodeBase64(bytes: Uint8Array): string { + const parts: string[] = []; + let chunk = ""; + for (let i = 0; i < bytes.length; i += 3) { + const a = bytes[i]!; + const b = i + 1 < bytes.length ? bytes[i + 1]! : 0; + const c = i + 2 < bytes.length ? bytes[i + 2]! : 0; + const n = (a << 16) | (b << 8) | c; + chunk += BASE64_ALPHABET[(n >> 18) & 63]! + BASE64_ALPHABET[(n >> 12) & 63]!; + chunk += i + 1 < bytes.length ? BASE64_ALPHABET[(n >> 6) & 63]! : "="; + chunk += i + 2 < bytes.length ? BASE64_ALPHABET[n & 63]! : "="; + if (chunk.length >= 65536) { + parts.push(chunk); + chunk = ""; + } + } + parts.push(chunk); + return parts.join(""); +} diff --git a/packages/compiler/src/wasm/binary.ts b/packages/compiler/src/wasm/binary.ts index 5ddc28cc9..eaedf25af 100644 --- a/packages/compiler/src/wasm/binary.ts +++ b/packages/compiler/src/wasm/binary.ts @@ -20,6 +20,7 @@ * The decoder never evaluates anything and keeps no module contents beyond * the counts and the feature set it reports. It is plain TypeScript that * the native compiler also compiles. */ +import { readMemargFlags } from "./module.js"; /** Proposals the summary can name, in report order. The first group is the * translatable set; the rest are reported as unsupported. */ @@ -1244,19 +1245,9 @@ class FunctionValidator { /** A memarg. A memory other than 0 stops typing (multi-memory). */ memarg(naturalAlign: number): void { const r = this.r; - let align = r.u32(); - let multi = false; - if (align >= 64 && align < 128) { - align -= 64; - multi = true; - } else if (align >= 64) { - r.malformed("malformed memop flags"); - } - let memory = 0; - if (multi) { - memory = r.u32(); - if (memory !== 0) this.otherMemory(memory); - } + const { align, memory } = readMemargFlags(() => r.u32()); + if (align < 0) r.malformed("malformed memop flags"); + if (memory !== 0) this.otherMemory(memory); if (this.m.memory64) r.u64(); else r.u32(); if (!this.typed) return; @@ -1840,9 +1831,9 @@ class FunctionValidator { scanMemarg(): void { const r = this.r; - const align = r.u32(); - if (align >= 128) r.malformed("malformed memop flags"); - if (align >= 64 && r.u32() !== 0) this.m.feature("multi-memory"); + const { align, memory } = readMemargFlags(() => r.u32()); + if (align < 0) r.malformed("malformed memop flags"); + if (memory !== 0) this.m.feature("multi-memory"); if (this.m.memory64) r.u64(); else r.u32(); } diff --git a/packages/compiler/src/wasm/discover.ts b/packages/compiler/src/wasm/discover.ts index 95fc28647..931bc1dac 100644 --- a/packages/compiler/src/wasm/discover.ts +++ b/packages/compiler/src/wasm/discover.ts @@ -6,7 +6,9 @@ * 1. path: a `.wasm` path the compiler resolves from the source text * (`require.resolve`, `createRequire(...).resolve`, `import.meta.resolve`, * `new URL("./x.wasm", import.meta.url)`, and `path.join(__dirname, ...)` - * or `__dirname + "/x.wasm"`); + * or `__dirname + "/x.wasm"`), or a `.so` path spelled the same ways + * whose file is a module (WebAssembly shared libraries, such as + * quickjs-wasi's extensions); * 2. inline: a string literal that decodes as base64 to a module, or an * array literal of its bytes; * 3. package: every `.wasm` file shipped by a reached npm package whose @@ -28,6 +30,9 @@ import { trackedReadFile, } from "../frontend/input-tracker.js"; import { analyzeWasm, isWasmHeader, type WasmModuleSummary } from "./binary.js"; +import { decodeBase64 } from "./base64.js"; + +export { decodeBase64 }; export type WasmSourceKind = "path" | "inline" | "package" | "config"; @@ -56,6 +61,9 @@ export interface WasmDiscoveryInput { configured: readonly string[]; /** require.resolve from `fromFile`, or null when it does not resolve. */ resolveRequest: (fromFile: string, specifier: string) => string | null; + /** Receives each distinct module's bytes once, when it is first found + * (builds translate them). */ + onModule?: (sha256: string, bytes: Uint8Array) => void; } const SCAN_KINDS: ReadonlySet = new Set([ @@ -72,6 +80,9 @@ const BASE64_MAGIC = "AGFzbQ"; const BYTES_MAGIC = /\[\s*(?:0|0x0+)\s*,\s*(?:97|0x61)\s*,\s*(?:115|0x73)\s*,\s*(?:109|0x6d)\s*,/i; /** Package directories deeper than this are not searched for modules. */ const PACKAGE_SCAN_DEPTH = 6; +/** A `.so` path in a string literal: the cheap test before a file with no + * `.wasm` mention is walked for shared-library paths. */ +const SHARED_LIBRARY_PATH = /\.so["'`]/; /** Larger files are reported by size but not read. */ const MAX_MODULE_BYTES = 256 * 1024 * 1024; @@ -110,6 +121,7 @@ class Discovery { }; this.byHash.set(sha256, report); this.order.push(sha256); + this.input.onModule?.(sha256, bytes); } if (report.path === undefined && path !== undefined) report.path = path; addSource(report, source); @@ -132,6 +144,8 @@ class Discovery { return; } if (bytes.length > MAX_MODULE_BYTES) return; + // A shared-library path names a module only when the file is one. + if (source.kind === "path" && !path.endsWith(".wasm") && !isWasmHeader(bytes)) return; this.byPath.set(path, this.addBytes(bytes, path, source)); } @@ -139,7 +153,7 @@ class Discovery { scanFile(sf: ts.SourceFile): void { const text = sf.text; - const paths = text.includes(".wasm"); + const paths = text.includes(".wasm") || SHARED_LIBRARY_PATH.test(text); const base64 = text.includes(BASE64_MAGIC); const bytes = BYTES_MAGIC.test(text); if (!paths && !base64 && !bytes) return; @@ -177,7 +191,8 @@ class Discovery { ); } - /** The module path a resolution expression names, when it ends in .wasm. */ + /** The module path a resolution expression names, when it ends in .wasm + * (or .so). */ resolvedPath(sf: ts.SourceFile, node: ts.Node): string | null { const dir = dirname(sf.fileName); if (ts.isCallExpression(node)) { @@ -238,7 +253,7 @@ class Discovery { if (!ts.isStringLiteral(arg) && !ts.isNoSubstitutionTemplateLiteral(arg)) return null; parts.push(arg.text); } - if (!parts[parts.length - 1]!.endsWith(".wasm")) return null; + if (!isModulePath(parts[parts.length - 1]!)) return null; let path = parts[0]!; for (let i = 1; i < parts.length; i++) path = resolve(path, parts[i]!); return path; @@ -307,9 +322,15 @@ function addSource(report: WasmModuleReport, source: WasmSource): void { report.sources.push(source); } +/** A path that may name a module: `.wasm`, or `.so` for WebAssembly shared + * libraries (addFile keeps those only when the file is a module). */ +function isModulePath(text: string): boolean { + return text.endsWith(".wasm") || text.endsWith(".so"); +} + function wasmLiteral(node: ts.Expression): string | null { if (!ts.isStringLiteral(node) && !ts.isNoSubstitutionTemplateLiteral(node)) return null; - return node.text.endsWith(".wasm") ? node.text : null; + return isModulePath(node.text) ? node.text : null; } function isDirname(node: ts.Expression): boolean { @@ -351,40 +372,6 @@ function byteArrayLiteral(node: ts.ArrayLiteralExpression): Uint8Array | null { return out; } -const BASE64_VALUES = (() => { - const table = new Int16Array(128).fill(-1); - const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - for (let i = 0; i < alphabet.length; i++) table[alphabet.charCodeAt(i)] = i; - // base64url spellings - table["-".charCodeAt(0)] = 62; - table["_".charCodeAt(0)] = 63; - return table; -})(); - -/** Decodes standard or URL-safe base64 (padding optional); null when the - * text is not base64. */ -export function decodeBase64(text: string): Uint8Array | null { - let end = text.length; - while (end > 0 && text.charCodeAt(end - 1) === 61) end--; - if (text.length - end > 2 || end % 4 === 1) return null; - const out = new Uint8Array(Math.floor((end * 3) / 4)); - let acc = 0; - let bits = 0; - let j = 0; - for (let i = 0; i < end; i++) { - const c = text.charCodeAt(i); - const v = c < 128 ? BASE64_VALUES[c]! : -1; - if (v < 0) return null; - acc = ((acc << 6) | v) & 0xffffff; - bits += 6; - if (bits >= 8) { - bits -= 8; - out[j++] = (acc >> bits) & 0xff; - } - } - return j === out.length ? out : out.subarray(0, j); -} - /** The root directory of the npm package that contains `file` (the * directory below its innermost node_modules), or null outside one. */ export function packageRootOf(file: string): string | null { diff --git a/packages/compiler/src/wasm/module.ts b/packages/compiler/src/wasm/module.ts new file mode 100644 index 000000000..587a20d81 --- /dev/null +++ b/packages/compiler/src/wasm/module.ts @@ -0,0 +1,676 @@ +/* The structure of a WebAssembly module, for the translator. + * + * binary.ts validates a module and keeps nothing but counts. This parser + * reads the parts translation needs (types, imports, functions, tables, + * memories, globals, exports, the start function, element and data + * segments, function bodies and custom sections) from bytes that binary.ts + * already accepted, so it checks nothing beyond what it must to stay in + * bounds. Constant expressions and function bodies are kept as byte ranges + * that the translator reads itself. + * + * i64 values never become JavaScript numbers: the translator reads their + * LEB128 encodings into two 32-bit halves. Plain TypeScript, so the native + * compiler compiles it too. */ + +export const VAL_I32 = 0x7f; +export const VAL_I64 = 0x7e; +export const VAL_F32 = 0x7d; +export const VAL_F64 = 0x7c; +export const VAL_FUNCREF = 0x70; +export const VAL_EXTERNREF = 0x6f; + +export const KIND_FUNC = 0; +export const KIND_TABLE = 1; +export const KIND_MEMORY = 2; +export const KIND_GLOBAL = 3; + +export interface WasmFuncType { + params: number[]; + results: number[]; +} + +/** A byte range of the module: a constant expression (through its `end` + * opcode) or a payload. */ +export interface WasmRange { + start: number; + end: number; +} + +export interface WasmImport { + module: string; + name: string; + kind: number; + /** Functions: the type index. Tables and globals: the value type. */ + type: number; + min: number; + max: number | null; + mutable: boolean; +} + +export interface WasmTable { + elemType: number; + min: number; + max: number | null; + imported: boolean; + /** A defined table's initializer (reference-types table with an init + * expression), or null for the null reference. */ + init: WasmRange | null; +} + +export interface WasmMemory { + min: number; + max: number | null; + imported: boolean; +} + +export interface WasmGlobal { + type: number; + mutable: boolean; + imported: boolean; + init: WasmRange | null; +} + +export interface WasmExport { + name: string; + kind: number; + index: number; +} + +export interface WasmElem { + mode: "active" | "passive" | "declarative"; + table: number; + offset: WasmRange | null; + elemType: number; + /** One initializer per element: a function index (>= 0), or -1 when the + * element is a constant expression in `exprs`. */ + funcs: number[]; + exprs: (WasmRange | null)[]; +} + +export interface WasmData { + mode: "active" | "passive"; + memory: number; + offset: WasmRange | null; + payload: WasmRange; +} + +export interface WasmCode { + /** Declared locals, expanded (not including parameters). */ + locals: number[]; + body: WasmRange; +} + +export interface WasmCustom { + name: string; + payload: WasmRange; +} + +export interface WasmModule { + bytes: Uint8Array; + types: WasmFuncType[]; + imports: WasmImport[]; + /** The type index of every function, imported functions first. */ + funcTypes: number[]; + importedFuncs: number; + tables: WasmTable[]; + memories: WasmMemory[]; + globals: WasmGlobal[]; + exports: WasmExport[]; + start: number | null; + elems: WasmElem[]; + datas: WasmData[]; + codes: WasmCode[]; + customs: WasmCustom[]; + /** Functions referenced outside a body (exports, element segments, + * ref.func in constant expressions): only these need a function + * reference record. Bodies add their own ref.func targets, which a valid + * module also declares in one of these places. */ + declaredRefs: Set; +} + +/** A byte cursor over a module that binary.ts validated. */ +export class WasmCursor { + bytes: Uint8Array; + pos: number; + constructor(bytes: Uint8Array, pos: number) { + this.bytes = bytes; + this.pos = pos; + } + + u8(): number { + const b = this.bytes[this.pos]; + if (b === undefined) throw new Error("wasm: unexpected end of module"); + this.pos++; + return b; + } + + u32(): number { + let result = 0; + let scale = 1; + for (;;) { + const b = this.u8(); + result += (b & 0x7f) * scale; + if ((b & 0x80) === 0) return result; + scale *= 128; + } + } + + /** A signed LEB128 of at most 33 bits. */ + s33(): number { + let result = 0; + let scale = 1; + for (;;) { + const b = this.u8(); + result += (b & 0x7f) * scale; + scale *= 128; + if ((b & 0x80) === 0) { + if (b & 0x40) result -= scale; + return result; + } + } + } + + /** A signed 32-bit LEB128 as a signed 32-bit number. */ + s32(): number { + return this.s33() | 0; + } + + /** A signed 64-bit LEB128 as its two's-complement halves [lo, hi], each + * an unsigned 32-bit number. */ + s64(): [number, number] { + let lo = 0; + let hi = 0; + let shift = 0; + let b = 0; + do { + b = this.u8(); + const bits = b & 0x7f; + if (shift < 32) { + lo = (lo | (bits << shift)) >>> 0; + if (shift > 25) hi = (hi | (bits >>> (32 - shift))) >>> 0; + } else if (shift < 64) { + hi = (hi | (bits << (shift - 32))) >>> 0; + } + shift += 7; + } while (b & 0x80); + if (shift < 64 && b & 0x40) { + // Sign-extend from bit `shift`. + if (shift < 32) { + lo = (lo | (~0 << shift)) >>> 0; + hi = 0xffffffff; + } else { + hi = (hi | (~0 << (shift - 32))) >>> 0; + } + } + return [lo, hi]; + } + + u32le(): number { + const b = this.bytes; + const p = this.pos; + this.pos += 4; + return (b[p]! | (b[p + 1]! << 8) | (b[p + 2]! << 16) | (b[p + 3]! << 24)) >>> 0; + } + + name(): string { + const length = this.u32(); + const start = this.pos; + this.pos += length; + return decodeUtf8(this.bytes, start, this.pos); + } + + /** Skips a constant expression through its `end` and answers its range. */ + constExpr(): WasmRange { + const start = this.pos; + for (;;) { + const op = this.u8(); + if (op === 0x0b) break; + skipImmediates(this, op); + } + return { start, end: this.pos }; + } + + valType(): number { + return this.u8(); + } + + /** A block type: -1 for the empty type, a value type, or a type index. */ + blockType(): + | { kind: "empty" } + | { kind: "value"; type: number } + | { kind: "index"; index: number } { + const b = this.bytes[this.pos]!; + if (b === 0x40) { + this.pos++; + return { kind: "empty" }; + } + if ( + b === VAL_I32 || + b === VAL_I64 || + b === VAL_F32 || + b === VAL_F64 || + b === VAL_FUNCREF || + b === VAL_EXTERNREF + ) { + this.pos++; + return { kind: "value", type: b }; + } + return { kind: "index", index: this.s33() }; + } +} + +function decodeUtf8(bytes: Uint8Array, start: number, end: number): string { + let out = ""; + let i = start; + while (i < end) { + const b = bytes[i]!; + let cp = b; + let need = 0; + if (b >= 0xf0) { + cp = b & 0x07; + need = 3; + } else if (b >= 0xe0) { + cp = b & 0x0f; + need = 2; + } else if (b >= 0xc0) { + cp = b & 0x1f; + need = 1; + } + for (let k = 1; k <= need; k++) cp = cp * 64 + (bytes[i + k]! & 0x3f); + out += String.fromCodePoint(cp); + i += need + 1; + } + return out; +} + +/** The flags of a memarg (the immediates of loads, stores and atomics): + * the alignment exponent and the memory index. Flags with bit 6 set + * (multi-memory) are followed by an explicit memory index, which may be + * 0; flags of 128 or more are malformed and answer align -1 without + * reading further. The offset follows. Validation (binary.ts), translation + * and skipImmediates all read memargs through this function, so they agree + * on where each instruction ends; `u32` reads the next u32 immediate of + * their own reader. */ +export function readMemargFlags(u32: () => number): { align: number; memory: number } { + const flags = u32(); + if (flags >= 128) return { align: -1, memory: 0 }; + if (flags >= 64) return { align: flags - 64, memory: u32() }; + return { align: flags, memory: 0 }; +} + +/** Reads the immediates of opcode `op` (already consumed). Covers the + * translatable feature level; anything else was refused before + * translation. */ +export function skipImmediates(c: WasmCursor, op: number): void { + switch (op) { + case 0x02: + case 0x03: + case 0x04: + c.blockType(); + return; + case 0x0c: + case 0x0d: + case 0x10: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0xd2: + c.u32(); + return; + case 0x0e: { + const n = c.u32(); + for (let i = 0; i <= n; i++) c.u32(); + return; + } + case 0x11: + c.u32(); + c.u32(); + return; + case 0x1c: { + const n = c.u32(); + for (let i = 0; i < n; i++) c.valType(); + return; + } + case 0x3f: + case 0x40: + // The memory index (a LEB128 zero; V8 accepts long encodings). + c.u32(); + return; + case 0x41: + c.s32(); + return; + case 0x42: + c.s64(); + return; + case 0x43: + c.pos += 4; + return; + case 0x44: + c.pos += 8; + return; + case 0xd0: + c.valType(); + return; + case 0xfc: { + const sub = c.u32(); + switch (sub) { + case 8: + c.u32(); + c.u32(); + return; + case 9: + case 13: + case 15: + case 16: + case 17: + c.u32(); + return; + case 10: + c.u32(); + c.u32(); + return; + case 11: + c.u32(); + return; + case 12: + case 14: + c.u32(); + c.u32(); + return; + default: + return; + } + } + default: + if (op >= 0x28 && op <= 0x3e) { + const flags = readMemargFlags(() => c.u32()); + if (flags.align < 0 || flags.memory !== 0) + throw new Error(`wasm: memarg of memory ${flags.memory} is not supported`); + c.u32(); + } + return; + } +} + +function limits(c: WasmCursor): { min: number; max: number | null } { + const flags = c.u8(); + const min = c.u32(); + const max = flags & 0x01 ? c.u32() : null; + return { min, max }; +} + +/** Parses a module binary.ts reported as valid within the translatable + * feature level. */ +export function parseWasmModule(bytes: Uint8Array): WasmModule { + const m: WasmModule = { + bytes, + types: [], + imports: [], + funcTypes: [], + importedFuncs: 0, + tables: [], + memories: [], + globals: [], + exports: [], + start: null, + elems: [], + datas: [], + codes: [], + customs: [], + declaredRefs: new Set(), + }; + const c = new WasmCursor(bytes, 8); + while (c.pos < bytes.length) { + const id = c.u8(); + const size = c.u32(); + const end = c.pos + size; + switch (id) { + case 0: { + const name = c.name(); + m.customs.push({ name, payload: { start: c.pos, end } }); + break; + } + case 1: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + c.u8(); // 0x60 + const params: number[] = []; + const np = c.u32(); + for (let k = 0; k < np; k++) params.push(c.valType()); + const results: number[] = []; + const nr = c.u32(); + for (let k = 0; k < nr; k++) results.push(c.valType()); + m.types.push({ params, results }); + } + break; + } + case 2: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const module = c.name(); + const name = c.name(); + const kind = c.u8(); + const imp: WasmImport = { + module, + name, + kind, + type: 0, + min: 0, + max: null, + mutable: false, + }; + if (kind === KIND_FUNC) { + imp.type = c.u32(); + m.funcTypes.push(imp.type); + m.importedFuncs++; + } else if (kind === KIND_TABLE) { + imp.type = c.valType(); + const l = limits(c); + imp.min = l.min; + imp.max = l.max; + m.tables.push({ + elemType: imp.type, + min: l.min, + max: l.max, + imported: true, + init: null, + }); + } else if (kind === KIND_MEMORY) { + const l = limits(c); + imp.min = l.min; + imp.max = l.max; + m.memories.push({ min: l.min, max: l.max, imported: true }); + } else { + imp.type = c.valType(); + imp.mutable = c.u8() === 1; + m.globals.push({ type: imp.type, mutable: imp.mutable, imported: true, init: null }); + } + m.imports.push(imp); + } + break; + } + case 3: { + const n = c.u32(); + for (let i = 0; i < n; i++) m.funcTypes.push(c.u32()); + break; + } + case 4: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + let init: WasmRange | null = null; + if (c.bytes[c.pos] === 0x40) { + // table with an initializer: 0x40 0x00 tabletype expr + c.pos += 2; + const elemType = c.valType(); + const l = limits(c); + init = c.constExpr(); + m.tables.push({ elemType, min: l.min, max: l.max, imported: false, init }); + continue; + } + const elemType = c.valType(); + const l = limits(c); + m.tables.push({ elemType, min: l.min, max: l.max, imported: false, init }); + } + break; + } + case 5: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const l = limits(c); + m.memories.push({ min: l.min, max: l.max, imported: false }); + } + break; + } + case 6: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const type = c.valType(); + const mutable = c.u8() === 1; + const init = c.constExpr(); + noteConstRefs(m, init); + m.globals.push({ type, mutable, imported: false, init }); + } + break; + } + case 7: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const name = c.name(); + const kind = c.u8(); + const index = c.u32(); + m.exports.push({ name, kind, index }); + if (kind === KIND_FUNC) m.declaredRefs.add(index); + } + break; + } + case 8: + m.start = c.u32(); + break; + case 9: { + const n = c.u32(); + for (let i = 0; i < n; i++) m.elems.push(elemSegment(m, c)); + break; + } + case 10: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const size = c.u32(); + const bodyEnd = c.pos + size; + const locals: number[] = []; + const groups = c.u32(); + for (let g = 0; g < groups; g++) { + const count = c.u32(); + const type = c.valType(); + for (let k = 0; k < count; k++) locals.push(type); + } + m.codes.push({ locals, body: { start: c.pos, end: bodyEnd } }); + c.pos = bodyEnd; + } + break; + } + case 11: { + const n = c.u32(); + for (let i = 0; i < n; i++) { + const flags = c.u32(); + if (flags === 1) { + const size = c.u32(); + m.datas.push({ + mode: "passive", + memory: 0, + offset: null, + payload: { start: c.pos, end: c.pos + size }, + }); + c.pos += size; + continue; + } + const memory = flags === 2 ? c.u32() : 0; + const offset = c.constExpr(); + const size = c.u32(); + m.datas.push({ + mode: "active", + memory, + offset, + payload: { start: c.pos, end: c.pos + size }, + }); + c.pos += size; + } + break; + } + default: + // 12 (data count) and anything binary.ts accepted without content + // translation needs. + break; + } + c.pos = end; + } + return m; +} + +function elemSegment(m: WasmModule, c: WasmCursor): WasmElem { + const flags = c.u32(); + const passiveOrDeclarative = (flags & 1) !== 0; + const explicitTable = (flags & 2) !== 0; + const usesExprs = (flags & 4) !== 0; + let mode: WasmElem["mode"] = "active"; + if (passiveOrDeclarative) mode = explicitTable ? "declarative" : "passive"; + let table = 0; + let offset: WasmRange | null = null; + if (!passiveOrDeclarative) { + if (explicitTable) table = c.u32(); + offset = c.constExpr(); + } + let elemType = VAL_FUNCREF; + if (passiveOrDeclarative || explicitTable) { + // elemkind (0x00 = funcref) or a reference type + const b = c.u8(); + elemType = usesExprs ? b : VAL_FUNCREF; + } + const n = c.u32(); + const funcs: number[] = []; + const exprs: (WasmRange | null)[] = []; + for (let i = 0; i < n; i++) { + if (usesExprs) { + const expr = c.constExpr(); + const direct = refFuncOf(m.bytes, expr); + if (direct !== null) { + funcs.push(direct); + exprs.push(null); + m.declaredRefs.add(direct); + } else { + noteConstRefs(m, expr); + funcs.push(-1); + exprs.push(expr); + } + } else { + const f = c.u32(); + funcs.push(f); + exprs.push(null); + m.declaredRefs.add(f); + } + } + return { mode, table, offset, elemType, funcs, exprs }; +} + +/** The function of a `ref.func f; end` expression, or null. */ +function refFuncOf(bytes: Uint8Array, expr: WasmRange): number | null { + if (bytes[expr.start] !== 0xd2) return null; + const c = new WasmCursor(bytes, expr.start + 1); + const f = c.u32(); + return c.pos === expr.end - 1 && bytes[c.pos] === 0x0b ? f : null; +} + +function noteConstRefs(m: WasmModule, expr: WasmRange): void { + const c = new WasmCursor(m.bytes, expr.start); + while (c.pos < expr.end) { + const op = c.u8(); + if (op === 0xd2) { + m.declaredRefs.add(c.u32()); + continue; + } + skipImmediates(c, op); + } +} diff --git a/packages/compiler/src/wasm/translate.test.ts b/packages/compiler/src/wasm/translate.test.ts new file mode 100644 index 000000000..86ba042ef --- /dev/null +++ b/packages/compiler/src/wasm/translate.test.ts @@ -0,0 +1,247 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, test } from "vitest"; +import { analyzeWasm } from "./binary.js"; +import { decodeBase64, encodeBase64 } from "./base64.js"; +import { WasmCursor, parseWasmModule } from "./module.js"; +import { + signatureHash, + stackCheckedFunctions, + translateWasmModule, + wasmSymbolPrefix, +} from "./translate.js"; + +const SHA = new Uint8Array(32).fill(0xab); + +/** (module (func (export "add") (param i32 i32) (result i32) local.get 0 local.get 1 i32.add) + * (memory (export "mem") 1) (data (i32.const 8) "hi")) */ +const ADD = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 13, + 2, 3, 97, 100, 100, 0, 0, 3, 109, 101, 109, 2, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11, 11, 8, 1, + 0, 65, 8, 11, 2, 104, 105, +]); + +/** Every top-level line must be one the native helper's text partitioner + * accepts (native/llvm-codegen/src/partition.cpp), so translated modules + * keep the program on its concurrent parsing path. */ +function topLevelLines(text: string[]): string[] { + const lines: string[] = []; + for (const part of text) { + let inFunction = false; + for (const line of part.split("\n")) { + if (inFunction) { + if (line === "}") inFunction = false; + continue; + } + if (line.startsWith("define ")) inFunction = true; + lines.push(line); + } + } + return lines; +} + +describe("translateWasmModule", () => { + test("emits functions, thunks, data and the descriptor in the helper's grammar", () => { + const out = translateWasmModule(ADD, SHA, { boundsChecks: false }); + const prefix = wasmSymbolPrefix(SHA); + expect(prefix).toBe("scr_wasm_abababababababab"); + expect(out.descriptor).toBe(`@${prefix}_desc`); + const text = out.text.join("\n"); + expect(text).toContain(`define internal i32 @${prefix}_f0(ptr %inst, i32 %p0, i32 %p1)`); + expect(text).toContain(`define internal void @${prefix}_x0(ptr %inst, ptr %a, ptr %r)`); + expect(text).toContain(`c"hi"`); + expect(text).toContain(`"disable-tail-calls"="true"`); + for (const line of topLevelLines(out.text)) { + expect( + line === "" || /^(define internal |@[\w.$-]+ = (private|internal) )/.test(line), + line, + ).toBe(true); + } + for (const decl of out.decls) expect(decl).toMatch(/^declare /); + }); + + test("keeps custom sections only when asked, and gives unexported table functions call thunks", () => { + // (module (type $t (func (param i32) (result i32))) (table 2 funcref) + // (elem (i32.const 0) $hidden $shown) (func $hidden (type $t) local.get 0) + // (func $shown (export "shown") (type $t) local.get 0)), plus a custom + // section "meta" with "hi". + const refs = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127, 3, 3, 2, 0, 0, 4, 4, 1, 112, 0, 2, + 7, 9, 1, 5, 115, 104, 111, 119, 110, 0, 1, 9, 8, 1, 0, 65, 0, 11, 2, 0, 1, 10, 11, 2, 4, 0, + 32, 0, 11, 4, 0, 32, 0, 11, 0, 7, 4, 109, 101, 116, 97, 104, 105, + ]); + const prefix = wasmSymbolPrefix(SHA); + const plain = translateWasmModule(refs, SHA, { boundsChecks: false }).text.join("\n"); + expect(plain).toContain( + `@${prefix}_customs = private constant [0 x { ptr, i64, ptr, i64 }] []`, + ); + expect(plain).not.toContain(`c"hi"`); + const kept = translateWasmModule(refs, SHA, { boundsChecks: false, customSections: true }); + const text = kept.text.join("\n"); + expect(text).toContain(`@${prefix}_c0 = private unnamed_addr constant [2 x i8] c"hi", align 1`); + expect(text).toContain(`@${prefix}_customs = private constant [1 x { ptr, i64, ptr, i64 }]`); + // One call thunk for the signature, used by the unexported function + // only (the exported one has its export thunk). + expect(text).toContain( + `define internal void @${prefix}_k0(ptr %code, ptr %inst, ptr %a, ptr %r)`, + ); + expect(text).toContain(`%res = call i32 %code(ptr %inst, i32 `); + expect(text).toContain( + `@${prefix}_calls = private constant [2 x ptr] [ptr @${prefix}_k0, ptr null]`, + ); + for (const line of topLevelLines(kept.text)) { + expect( + line === "" || /^(define internal |@[\w.$-]+ = (private|internal) )/.test(line), + line, + ).toBe(true); + } + }); + + test("checks memory accesses explicitly only when asked", () => { + const guarded = translateWasmModule(ADD, SHA, { boundsChecks: false }).text.join("\n"); + const checked = translateWasmModule(ADD, SHA, { boundsChecks: true }).text.join("\n"); + expect(guarded).not.toContain("%msize"); + expect(checked).toContain("%msize"); + }); + + test("reads a memarg with an explicit memory index as one immediate", () => { + // (func (result i32) (i32.load 0 offset=8 (i32.const 0))) with memory 1: + // memarg flags 0x42 (alignment 2, memory index present), memory 0, + // offset 8, then `end`. + const bytes = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 127, 3, 2, 1, 0, 5, 3, 1, 0, 1, 10, 10, 1, 8, + 0, 65, 0, 40, 66, 0, 8, 11, + ]); + expect(analyzeWasm(bytes).status).toBe("valid"); + const text = translateWasmModule(bytes, SHA, { boundsChecks: false }).text.join("\n"); + expect(text).toContain("add i64 %v1, 8"); + expect(text).toContain("load i32, ptr %v3"); + }); + + test("translates every valid module of the WebAssembly spec test suite", () => { + const cases = readFileSync(join(import.meta.dirname, "../../test/wasm-spec-cases.txt"), "utf8") + .split("\n") + .filter((line) => line !== "" && !line.startsWith("#")); + let translated = 0; + for (const line of cases) { + const [, , where, b64] = line.split(" "); + const bytes = decodeBase64(b64!)!; + if (analyzeWasm(bytes).status !== "valid") continue; + try { + translateWasmModule(bytes, SHA, { boundsChecks: false }); + } catch (error) { + throw new Error(`${where}: ${error instanceof Error ? error.message : String(error)}`); + } + translated++; + } + expect(translated).toBeGreaterThan(800); + }); +}); + +/** A module from its sections: `[id, ...payload]`, each payload under 128 + * bytes. */ +function wasmModule(...sections: number[][]): Uint8Array { + const out = [0, 97, 115, 109, 1, 0, 0, 0]; + for (const [id, ...payload] of sections) out.push(id!, payload.length, ...payload); + return new Uint8Array(out); +} + +/** (module (memory 1) (func (export "f") (param i32) (result i32) + * local.get 0 i32.load )) with the memarg's bytes as given. */ +function loadModule(memarg: number[]): Uint8Array { + const body = [0, 0x20, 0, 0x28, ...memarg, 0x0b]; + return wasmModule( + [1, 1, 0x60, 1, 0x7f, 1, 0x7f], + [3, 1, 0], + [5, 1, 0, 1], + [7, 1, 1, 0x66, 0, 0], + [10, 1, body.length, ...body], + ); +} + +describe("memargs and operand types", () => { + test("a memarg naming memory 0 explicitly translates as the plain form", () => { + // Flags 0x42: alignment 2 with bit 6 set, then memory index 0 and + // offset 4. Validation and translation read the same three immediates. + // Only the descriptor (which records the module's byte length) differs. + const code = (memarg: number[]): string[] => + translateWasmModule(loadModule(memarg), SHA, { boundsChecks: true }) + .text.join("\n") + .split("\n") + .filter((line) => !line.startsWith(`@${wasmSymbolPrefix(SHA)}_desc =`)); + expect(code([0x42, 0, 4])).toEqual(code([0x02, 4])); + }); + + test("a memarg naming another memory is refused", () => { + expect(() => + translateWasmModule(loadModule([0x42, 1, 4]), SHA, { boundsChecks: true }), + ).toThrow(/memory 1/); + }); + + test("local.tee of an i32 into an externref local is refused", () => { + // (func (local externref) i32.const 1 local.tee 0 drop): the operand + // never reaches a reference slot. + const body = [1, 1, 0x6f, 0x41, 1, 0x22, 0, 0x1a, 0x0b]; + const bytes = wasmModule([1, 1, 0x60, 0, 0], [3, 1, 0], [10, 1, body.length, ...body]); + expect(() => translateWasmModule(bytes, SHA, { boundsChecks: false })).toThrow( + /local\.tee operand type does not match/, + ); + }); +}); + +describe("module parsing", () => { + test("reads the parts translation needs", () => { + const m = parseWasmModule(ADD); + expect(m.types).toEqual([{ params: [0x7f, 0x7f], results: [0x7f] }]); + expect(m.exports.map((e) => e.name)).toEqual(["add", "mem"]); + expect(m.memories).toEqual([{ min: 1, max: null, imported: false }]); + expect(m.datas[0]!.mode).toBe("active"); + expect([...m.declaredRefs]).toEqual([0]); + }); + + test("decodes signed 64-bit LEB128 into two's-complement halves", () => { + const halves = (bytes: number[]): [number, number] => + new WasmCursor(new Uint8Array(bytes), 0).s64(); + expect(halves([0x7f])).toEqual([0xffffffff, 0xffffffff]); + expect(halves([0x80, 0x80, 0x80, 0x80, 0x10])).toEqual([0, 1]); + expect(halves([0xff, 0xff, 0xff, 0xff, 0x0f])).toEqual([0xffffffff, 0]); + expect(halves([0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f])).toEqual([ + 0, 0x80000000, + ]); + expect(halves([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00])).toEqual([ + 0xffffffff, 0x7fffffff, + ]); + }); +}); + +describe("stack checks", () => { + test("only functions through which the stack can grow without bound check it", () => { + // f0 <-> f1 recurse mutually, f2 recurses on itself, f3 calls f0 once. + const calls = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 5, 4, 0, 0, 0, 0, 10, 21, 4, 4, 0, 16, 1, + 11, 4, 0, 16, 0, 11, 4, 0, 16, 2, 11, 4, 0, 16, 0, 11, + ]); + expect([...stackCheckedFunctions(parseWasmModule(calls))].sort()).toEqual([0, 1, 2]); + expect(stackCheckedFunctions(parseWasmModule(ADD)).size).toBe(0); + // Only code without the fault handler checks explicitly. + const checked = translateWasmModule(calls, SHA, { boundsChecks: true }).text.join("\n"); + expect(checked.split("@scr_wasm_stack_limit").length - 1).toBe(3); + const guarded = translateWasmModule(calls, SHA, { boundsChecks: false }).text.join("\n"); + expect(guarded).not.toContain("@scr_wasm_stack_limit"); + }); +}); + +describe("helpers", () => { + test("equal signatures share their identity across modules", () => { + expect(signatureHash("ii:i")).toBe(signatureHash("ii:i")); + expect(signatureHash("ii:i")).not.toBe(signatureHash("i:i")); + expect(signatureHash(":")).toMatch(/^u0x[0-9a-f]{16}$/); + }); + + test("base64 round-trips module bytes", () => { + expect(encodeBase64(ADD)).toBe(Buffer.from(ADD).toString("base64")); + expect(decodeBase64(encodeBase64(ADD))).toEqual(ADD); + expect(encodeBase64(new Uint8Array([1]))).toBe("AQ=="); + expect(encodeBase64(new Uint8Array([1, 2]))).toBe("AQI="); + }); +}); diff --git a/packages/compiler/src/wasm/translate.ts b/packages/compiler/src/wasm/translate.ts new file mode 100644 index 000000000..4c02499ca --- /dev/null +++ b/packages/compiler/src/wasm/translate.ts @@ -0,0 +1,2296 @@ +/* WebAssembly to LLVM IR. + * + * Translates one validated module (binary.ts accepted it within the + * translatable feature level) to LLVM assembly that the program's emitter + * appends to its own module, so the native helper optimizes, partitions and + * caches it with the program. The runtime (scr_wasm.c) implements the + * JavaScript API over the descriptor this emits; scr_wasm_abi.h is the + * contract both sides follow. + * + * Shape of the output: + * - one internal function per wasm function, taking the instance as its + * first parameter (`ptr %inst`) and the wasm values directly (i32, i64, + * float, double; references are pointers). Several results return as a + * literal struct. An imported function is a stub that packs its + * arguments and calls scr_wasm_import_call. + * - one thunk per exported function, `void (ptr inst, ptr args, ptr + * results)` over 64-bit slots, which the runtime calls under its trap + * guard; + * - an init function (globals, table initializers, active element and + * data segments); the descriptor names the start function; + * - constant data (segments, names, signatures) and the descriptor. + * + * The instance layout (scr_wasm_abi.h): host at 0, memory base at 8, + * memory object at 16, function reference records at 24, then one pointer + * per table and one cell pointer per global. + * + * Memory accesses compute `base + zext(address) + offset` in 64 bits. With + * guard pages (64-bit hosts) the runtime reserves enough address space that + * every such address past the memory faults, so accesses are unchecked and + * the base is loaded once per function (the memory never moves). With + * explicit bounds checks (sanitizer builds and hosts without the fault + * handler) the base and byte length live in function-local slots that are + * reloaded after every call and memory.grow. + * + * Locals, block results and loop parameters are allocas; LLVM promotes them + * to SSA values. Traps call scr_wasm_trap, which never returns. Plain + * TypeScript without bigint, so the native compiler compiles it too. */ +import { + KIND_FUNC, + KIND_GLOBAL, + KIND_MEMORY, + KIND_TABLE, + VAL_EXTERNREF, + VAL_F32, + VAL_F64, + VAL_FUNCREF, + VAL_I32, + VAL_I64, + WasmCursor, + parseWasmModule, + readMemargFlags, + skipImmediates, + type WasmFuncType, + type WasmModule, + type WasmRange, +} from "./module.js"; + +/** Trap codes (scr_wasm_abi.h SCR_WASM_TRAP_*). */ +export const TRAP_UNREACHABLE = 1; +export const TRAP_MEMORY_OOB = 2; +export const TRAP_DIV_BY_ZERO = 3; +export const TRAP_DIV_UNREPRESENTABLE = 4; +export const TRAP_REM_BY_ZERO = 5; +export const TRAP_FLOAT_UNREPRESENTABLE = 6; +export const TRAP_TABLE_OOB = 7; +export const TRAP_SIGNATURE = 8; +export const TRAP_NULL = 9; +/** scr_wasm_abi.h SCR_WASM_TRAP_EXHAUSTION. */ +export const TRAP_EXHAUSTION = 100; + +/** The descriptor ABI version both sides agree on. */ +export const WASM_ABI_VERSION = 2; + +/** Instance slot offsets (bytes). */ +const OFF_MEMBASE = 8; +const OFF_MEMORY = 16; +const OFF_FUNCREFS = 24; +const OFF_TABLES = 32; +/** sizeof(ScrWasmFuncRef). */ +const FUNCREF_SIZE = 24; + +export interface WasmTranslateOptions { + /** Explicit bounds checks instead of guard pages. */ + boundsChecks: boolean; + /** Keep the custom sections, for WebAssembly.Module.customSections. */ + customSections?: boolean; +} + +export interface WasmTranslation { + /** External declarations, one line each. */ + decls: string[]; + /** Definitions in the emitter's top-level grammar. */ + text: string[]; + /** The descriptor's symbol (internal). */ + descriptor: string; +} + +/** A construct the translator does not support in an otherwise valid module. */ +export class WasmTranslateError extends Error {} + +/** Attributes of translated functions. Recursion must exhaust the stack + * as it does in V8, so LLVM may not turn self-recursion into loops (tail + * recursion elimination, including its accumulator form, which would make + * `f(x) + 1` recursion loop forever) or calls into jumps. */ +const FUNC_ATTRS = `nounwind "disable-tail-calls"="true"`; + +const RUNTIME_DECLS = [ + "declare void @scr_wasm_trap(i32) noreturn nounwind cold", + "declare void @scr_wasm_import_call(ptr, i32, ptr, ptr)", + "declare i32 @scr_wasm_memory_grow(ptr, i32)", + "declare void @scr_wasm_memory_fill(ptr, i32, i32, i32)", + "declare void @scr_wasm_memory_copy(ptr, i32, i32, i32)", + "declare void @scr_wasm_memory_init(ptr, i32, i32, i32, i32)", + "declare void @scr_wasm_data_drop(ptr, i32)", + "declare ptr @scr_wasm_table_get(ptr, i32, i32)", + "declare void @scr_wasm_table_set(ptr, i32, i32, ptr)", + "declare i32 @scr_wasm_table_grow(ptr, i32, ptr, i32)", + "declare void @scr_wasm_table_fill(ptr, i32, i32, ptr, i32)", + "declare void @scr_wasm_table_copy(ptr, i32, i32, i32, i32, i32)", + "declare void @scr_wasm_table_init(ptr, i32, i32, i32, i32, i32)", + "declare void @scr_wasm_elem_drop(ptr, i32)", + "declare void @scr_wasm_global_set_ref(ptr, ptr)", +]; + +function llType(t: number): string { + switch (t) { + case VAL_I32: + return "i32"; + case VAL_I64: + return "i64"; + case VAL_F32: + return "float"; + case VAL_F64: + return "double"; + case VAL_FUNCREF: + case VAL_EXTERNREF: + return "ptr"; + default: + throw new WasmTranslateError(`value type 0x${t.toString(16)} is not supported`); + } +} + +function zeroOf(t: number): string { + switch (t) { + case VAL_I32: + case VAL_I64: + return "0"; + case VAL_F32: + case VAL_F64: + return "0.0"; + default: + return "null"; + } +} + +/** The runtime's signature letter of a value type. */ +function sigChar(t: number): string { + switch (t) { + case VAL_I32: + return "i"; + case VAL_I64: + return "I"; + case VAL_F32: + return "f"; + case VAL_F64: + return "F"; + case VAL_FUNCREF: + return "r"; + case VAL_EXTERNREF: + return "x"; + default: + throw new WasmTranslateError(`value type 0x${t.toString(16)} is not supported`); + } +} + +function sigString(ft: WasmFuncType): string { + let s = ""; + for (const p of ft.params) s += sigChar(p); + s += ":"; + for (const r of ft.results) s += sigChar(r); + return s; +} + +function retType(results: readonly number[]): string { + if (results.length === 0) return "void"; + if (results.length === 1) return llType(results[0]!); + return `{ ${results.map(llType).join(", ")} }`; +} + +function hex8(n: number): string { + return (n >>> 0).toString(16).padStart(8, "0"); +} + +/** An i64 constant from its halves, in LLVM's unsigned hexadecimal form. */ +function i64Lit(lo: number, hi: number): string { + return `u0x${hex8(hi)}${hex8(lo)}`; +} + +/** The canonical signature identity call_indirect compares: two + * independent 32-bit FNV-1a hashes of the signature text. Equal signatures + * in different modules get the same identity. */ +export function signatureHash(sig: string): string { + let a = 0x811c9dc5; + let b = 0x01000193 ^ 0x5bd1e995; + for (let i = 0; i < sig.length; i++) { + const c = sig.charCodeAt(i); + a = Math.imul(a ^ c, 0x01000193); + b = Math.imul(b ^ c, 0x01000193) ^ (b >>> 13); + } + return i64Lit(a >>> 0, b >>> 0); +} + +/** UTF-8 bytes of a string. */ +function utf8Bytes(text: string): number[] { + const out: number[] = []; + for (let i = 0; i < text.length; i++) { + const cp = text.codePointAt(i)!; + if (cp > 0xffff) i++; + if (cp < 0x80) out.push(cp); + else if (cp < 0x800) out.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f)); + else if (cp < 0x10000) + out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f)); + else { + out.push( + 0xf0 | (cp >> 18), + 0x80 | ((cp >> 12) & 0x3f), + 0x80 | ((cp >> 6) & 0x3f), + 0x80 | (cp & 0x3f), + ); + } + } + return out; +} + +/** An LLVM c"..." string body for bytes. */ +function cBytes(bytes: Uint8Array, start: number, end: number): string { + let s = ""; + for (let i = start; i < end; i++) { + const b = bytes[i]!; + if (b >= 0x20 && b < 0x7f && b !== 0x22 && b !== 0x5c) s += String.fromCharCode(b); + else s += "\\" + (b < 16 ? "0" : "") + b.toString(16).toUpperCase(); + } + return s; +} + +interface StackValue { + v: string; + t: number; + /** The line of the load that produced the value (this.lines). */ + load?: number; +} + +interface Frame { + kind: "block" | "loop" | "if" | "func"; + params: number[]; + results: number[]; + /** Branch target: the loop header, or the end label. */ + target: string; + end: string; + /** Allocas the values of a branch to this frame are stored in: the loop + * parameters for a loop, the results otherwise. */ + branchSlots: string[]; + /** Allocas of the results at the frame's end (loops: their own). */ + resultSlots: string[]; + height: number; + /** An if whose else branch has not started. */ + elseLabel: string | null; + /** The parameter values of an if, for its implicit else. */ + ifParams: StackValue[]; + /** The start of the frame was reachable. */ + live: boolean; +} + +class Lines { + lines: string[] = []; + add(line: string): void { + this.lines.push(line); + } +} + +/** One module's translation. */ +class ModuleTranslator { + m: WasmModule; + p: string; + opts: WasmTranslateOptions; + text: string[] = []; + /** Functions that need a reference record. */ + refs: Set; + /** Functions whose entry checks the stack (stackCheckedFunctions). */ + stackChecked: Set; + typeHashes: string[]; + memoryCount: number; + + constructor(m: WasmModule, prefix: string, opts: WasmTranslateOptions) { + this.m = m; + this.p = prefix; + this.opts = opts; + this.refs = new Set(m.declaredRefs); + this.typeHashes = m.types.map((t) => signatureHash(sigString(t))); + this.memoryCount = m.memories.length; + if (m.memories.length > 1) throw new WasmTranslateError("multiple memories are not supported"); + this.stackChecked = stackCheckedFunctions(m); + } + + fn(index: number): string { + return `@${this.p}_f${index}`; + } + + funcType(index: number): WasmFuncType { + return this.m.types[this.m.funcTypes[index]!]!; + } + + globalSlot(index: number): number { + return OFF_TABLES + 8 * (this.m.tables.length + index); + } + + tableSlot(index: number): number { + return OFF_TABLES + 8 * index; + } + + signature(ft: WasmFuncType, name: string): string { + const params = ["ptr %inst"]; + for (let i = 0; i < ft.params.length; i++) params.push(`${llType(ft.params[i]!)} %p${i}`); + return `${retType(ft.results)} ${name}(${params.join(", ")})`; + } + + translate(): void { + const m = this.m; + for (let i = 0; i < m.importedFuncs; i++) this.importStub(i); + for (let i = 0; i < m.codes.length; i++) { + const index = m.importedFuncs + i; + const f = new FunctionTranslator(this, index); + this.text.push(...f.translate()); + } + } + + importStub(index: number): void { + const ft = this.funcType(index); + const out: string[] = []; + out.push(`define internal ${this.signature(ft, this.fn(index))} nounwind {`); + out.push(`entry:`); + const np = Math.max(1, ft.params.length); + const nr = Math.max(1, ft.results.length); + out.push(` %args = alloca [${np} x i64], align 8`); + out.push(` %res = alloca [${nr} x i64], align 8`); + for (let i = 0; i < ft.params.length; i++) { + const slot = toSlot(out, ft.params[i]!, `%p${i}`, `a${i}`); + out.push(` %ap${i} = getelementptr i64, ptr %args, i64 ${i}`); + out.push(` store i64 ${slot}, ptr %ap${i}`); + } + out.push(` %host = load ptr, ptr %inst`); + out.push(` call void @scr_wasm_import_call(ptr %host, i32 ${index}, ptr %args, ptr %res)`); + emitSlotReturn(out, ft.results, "%res"); + out.push(`}`); + this.text.push(out.join("\n")); + } + + /** The thunk the runtime calls for exported function `index`. */ + exportThunk(index: number): string { + const name = `@${this.p}_x${index}`; + const ft = this.funcType(index); + const out: string[] = []; + out.push(`define internal void ${name}(ptr %inst, ptr %a, ptr %r) nounwind {`); + out.push(`entry:`); + const args: string[] = ["ptr %inst"]; + for (let i = 0; i < ft.params.length; i++) { + out.push(` %ap${i} = getelementptr i64, ptr %a, i64 ${i}`); + out.push(` %as${i} = load i64, ptr %ap${i}`); + args.push(`${llType(ft.params[i]!)} ${fromSlot(out, ft.params[i]!, `%as${i}`, `a${i}`)}`); + } + const ret = retType(ft.results); + if (ft.results.length === 0) { + out.push(` call void ${this.fn(index)}(${args.join(", ")})`); + } else { + out.push(` %res = call ${ret} ${this.fn(index)}(${args.join(", ")})`); + for (let i = 0; i < ft.results.length; i++) { + let v = "%res"; + if (ft.results.length > 1) { + out.push(` %rv${i} = extractvalue ${ret} %res, ${i}`); + v = `%rv${i}`; + } + const slot = toSlot(out, ft.results[i]!, v, `r${i}`); + out.push(` %rp${i} = getelementptr i64, ptr %r, i64 ${i}`); + out.push(` store i64 ${slot}, ptr %rp${i}`); + } + } + out.push(` ret void`); + out.push(`}`); + this.text.push(out.join("\n")); + return name; + } + + /** A call thunk for signature `type`: `(code, inst, args, results)` + * calls `code` (a function of that signature) with the arguments in + * 64-bit slots. The runtime calls a function reference that reaches + * JavaScript through it when the module does not export the function. */ + callThunk(type: number): string { + const name = `@${this.p}_k${type}`; + const ft = this.m.types[type]!; + const out: string[] = []; + out.push(`define internal void ${name}(ptr %code, ptr %inst, ptr %a, ptr %r) nounwind {`); + out.push(`entry:`); + const args: string[] = ["ptr %inst"]; + for (let i = 0; i < ft.params.length; i++) { + out.push(` %ap${i} = getelementptr i64, ptr %a, i64 ${i}`); + out.push(` %as${i} = load i64, ptr %ap${i}`); + args.push(`${llType(ft.params[i]!)} ${fromSlot(out, ft.params[i]!, `%as${i}`, `a${i}`)}`); + } + const ret = retType(ft.results); + if (ft.results.length === 0) { + out.push(` call void %code(${args.join(", ")})`); + } else { + out.push(` %res = call ${ret} %code(${args.join(", ")})`); + for (let i = 0; i < ft.results.length; i++) { + let v = "%res"; + if (ft.results.length > 1) { + out.push(` %rv${i} = extractvalue ${ret} %res, ${i}`); + v = `%rv${i}`; + } + const slot = toSlot(out, ft.results[i]!, v, `r${i}`); + out.push(` %rp${i} = getelementptr i64, ptr %r, i64 ${i}`); + out.push(` store i64 ${slot}, ptr %rp${i}`); + } + } + out.push(` ret void`); + out.push(`}`); + this.text.push(out.join("\n")); + return name; + } + + /** Emits the init function: globals, table initializers and segments, + * in the specification's order. The runtime calls the start function + * (which takes and returns nothing) separately. */ + initFunction(): string { + const m = this.m; + const name = `@${this.p}_init`; + const f = new FunctionTranslator(this, -1); + const body = f.lines; + // Globals. + for (let g = 0; g < m.globals.length; g++) { + const global = m.globals[g]!; + if (global.imported || global.init === null) continue; + const v = f.constExpr(global.init); + const cell = f.loadPtrSlot(this.globalSlot(g)); + if (global.type === VAL_EXTERNREF) { + // A defined externref global starts as null or another global's + // value; the runtime's setter retains it. + body.add(` call void @scr_wasm_global_set_ref(ptr ${cell}, ptr ${v})`); + } else { + body.add(` store ${llType(global.type)} ${v}, ptr ${cell}`); + } + } + // Defined tables with an initializer. + for (let t = 0; t < m.tables.length; t++) { + const table = m.tables[t]!; + if (table.imported || table.init === null) continue; + const v = f.constExpr(table.init); + body.add( + ` call void @scr_wasm_table_fill(ptr %inst, i32 ${t}, i32 0, ptr ${v}, i32 ${table.min})`, + ); + } + // Element segments: active ones initialize their table and drop; + // declarative ones only drop. + for (let s = 0; s < m.elems.length; s++) { + const seg = m.elems[s]!; + if (seg.mode === "active") { + const offset = f.constExpr(seg.offset!); + body.add( + ` call void @scr_wasm_table_init(ptr %inst, i32 ${seg.table}, i32 ${s}, i32 ${offset}, i32 0, i32 ${seg.funcs.length})`, + ); + } + if (seg.mode !== "passive") body.add(` call void @scr_wasm_elem_drop(ptr %inst, i32 ${s})`); + } + for (let s = 0; s < m.datas.length; s++) { + const seg = m.datas[s]!; + if (seg.mode !== "active") continue; + const offset = f.constExpr(seg.offset!); + const length = seg.payload.end - seg.payload.start; + body.add( + ` call void @scr_wasm_memory_init(ptr %inst, i32 ${s}, i32 ${offset}, i32 0, i32 ${length})`, + ); + body.add(` call void @scr_wasm_data_drop(ptr %inst, i32 ${s})`); + } + body.add(` ret void`); + const out = [`define internal void ${name}(ptr %inst) nounwind {`, `entry:`]; + out.push(...f.entry.lines); + out.push(...body.lines); + out.push(`}`); + this.text.push(out.join("\n")); + return name; + } + + /** Constant data and the descriptor. */ + descriptor(sha256: Uint8Array): string { + const m = this.m; + const p = this.p; + const lines: string[] = []; + // First, so that every function its constant expressions reference has + // a record in the tables below. + const init = this.initFunction(); + let strings = 0; + const cstr = (text: readonly number[]): string => { + const sym = `@${p}_s${strings++}`; + const bytes = new Uint8Array(text); + lines.push( + `${sym} = private unnamed_addr constant [${bytes.length + 1} x i8] c"${cBytes(bytes, 0, bytes.length)}\\00"`, + ); + return sym; + }; + const textStr = (text: string): { sym: string; len: number } => { + const bytes = utf8Bytes(text); + return { sym: cstr(bytes), len: bytes.length }; + }; + // Imports. + const importRows: string[] = []; + let funcImport = 0; + let tableImport = 0; + let memoryImport = 0; + let globalImport = 0; + for (const imp of m.imports) { + const mod = textStr(imp.module); + const name = textStr(imp.name); + let index = 0; + let type = ""; + if (imp.kind === KIND_FUNC) { + index = funcImport++; + type = sigString(m.types[imp.type]!); + } else if (imp.kind === KIND_TABLE) { + index = tableImport++; + type = sigChar(imp.type); + } else if (imp.kind === KIND_MEMORY) { + index = memoryImport++; + } else { + index = globalImport++; + type = sigChar(imp.type); + } + const typeSym = cstr(utf8Bytes(type)); + importRows.push( + `{ ptr, i64, ptr, i64, i64, i64, ptr } { ptr ${mod.sym}, i64 ${mod.len}, ptr ${name.sym}, i64 ${name.len}, i64 ${imp.kind}, i64 ${index}, ptr ${typeSym} }`, + ); + } + const importType = "{ ptr, i64, ptr, i64, i64, i64, ptr }"; + const importsSym = `@${p}_imports`; + lines.push( + `${importsSym} = private constant [${importRows.length} x ${importType}] [${importRows.join(", ")}]`, + ); + // Exports. + const thunks = new Map(); + const exportRows: string[] = []; + for (const ex of m.exports) { + const name = textStr(ex.name); + let type = ""; + let call = "null"; + if (ex.kind === KIND_FUNC) { + type = sigString(this.funcType(ex.index)); + let thunk = thunks.get(ex.index); + if (thunk === undefined) { + thunk = this.exportThunk(ex.index); + thunks.set(ex.index, thunk); + } + call = thunk; + } else if (ex.kind === KIND_TABLE) { + type = sigChar(m.tables[ex.index]!.elemType); + } else if (ex.kind === KIND_GLOBAL) { + type = sigChar(m.globals[ex.index]!.type); + } + const typeSym = cstr(utf8Bytes(type)); + exportRows.push( + `{ ptr, i64, i64, i64, ptr, ptr } { ptr ${name.sym}, i64 ${name.len}, i64 ${ex.kind}, i64 ${ex.index}, ptr ${typeSym}, ptr ${call} }`, + ); + } + const exportType = "{ ptr, i64, i64, i64, ptr, ptr }"; + const exportsSym = `@${p}_exports`; + lines.push( + `${exportsSym} = private constant [${exportRows.length} x ${exportType}] [${exportRows.join(", ")}]`, + ); + // Function references: code, signature identity and signature text for + // every function a reference can name. + const nf = m.funcTypes.length; + const codes: string[] = []; + const callThunks: string[] = []; + const callThunkSyms = new Map(); + const types: string[] = []; + const sigs: string[] = []; + const sigSyms = new Map(); + for (let f = 0; f < nf; f++) { + const referenced = this.refs.has(f); + codes.push(referenced ? `ptr ${this.fn(f)}` : "ptr null"); + // Referenced functions the module does not export reach JavaScript + // through their signature's call thunk. + if (referenced && !thunks.has(f)) { + const type = m.funcTypes[f]!; + let thunk = callThunkSyms.get(type); + if (thunk === undefined) { + thunk = this.callThunk(type); + callThunkSyms.set(type, thunk); + } + callThunks.push(`ptr ${thunk}`); + } else { + callThunks.push("ptr null"); + } + types.push(`i64 ${this.typeHashes[m.funcTypes[f]!]!}`); + const sig = sigString(this.funcType(f)); + let sym = sigSyms.get(sig); + if (sym === undefined) { + sym = cstr(utf8Bytes(sig)); + sigSyms.set(sig, sym); + } + sigs.push(`ptr ${sym}`); + } + const codesSym = `@${p}_codes`; + const typesSym = `@${p}_types`; + const sigsSym = `@${p}_sigs`; + const callThunksSym = `@${p}_calls`; + lines.push(`${codesSym} = private constant [${nf} x ptr] [${codes.join(", ")}]`); + lines.push(`${callThunksSym} = private constant [${nf} x ptr] [${callThunks.join(", ")}]`); + lines.push(`${typesSym} = private constant [${nf} x i64] [${types.join(", ")}]`); + lines.push(`${sigsSym} = private constant [${nf} x ptr] [${sigs.join(", ")}]`); + // Tables. + const tableRows = m.tables.map( + (t) => + `{ i64, i64, i64, i64 } { i64 ${sigChar(t.elemType).charCodeAt(0)}, i64 ${t.min}, i64 ${t.max === null ? -1 : t.max}, i64 ${t.imported ? 1 : 0} }`, + ); + const tablesSym = `@${p}_tables`; + lines.push( + `${tablesSym} = private constant [${tableRows.length} x { i64, i64, i64, i64 }] [${tableRows.join(", ")}]`, + ); + // Globals. + const globalRows = m.globals.map( + (g) => + `{ i64, i64, i64 } { i64 ${sigChar(g.type).charCodeAt(0)}, i64 ${g.mutable ? 1 : 0}, i64 ${g.imported ? 1 : 0} }`, + ); + const globalsSym = `@${p}_globals`; + lines.push( + `${globalsSym} = private constant [${globalRows.length} x { i64, i64, i64 }] [${globalRows.join(", ")}]`, + ); + // Data segments. + const dataRows: string[] = []; + for (let s = 0; s < m.datas.length; s++) { + const seg = m.datas[s]!; + const len = seg.payload.end - seg.payload.start; + if (len === 0) { + dataRows.push(`{ ptr, i64 } { ptr null, i64 0 }`); + continue; + } + const sym = `@${p}_d${s}`; + lines.push( + `${sym} = private unnamed_addr constant [${len} x i8] c"${cBytes(m.bytes, seg.payload.start, seg.payload.end)}", align 1`, + ); + dataRows.push(`{ ptr, i64 } { ptr ${sym}, i64 ${len} }`); + } + const datasSym = `@${p}_datas`; + lines.push( + `${datasSym} = private constant [${dataRows.length} x { ptr, i64 }] [${dataRows.join(", ")}]`, + ); + // Element segments: a function index, -1 for null, or -(2 + g) for the + // value of global g. + const elemRows: string[] = []; + for (let s = 0; s < m.elems.length; s++) { + const seg = m.elems[s]!; + const items: string[] = []; + for (let k = 0; k < seg.funcs.length; k++) { + const f = seg.funcs[k]!; + if (f >= 0) { + items.push(`i64 ${f}`); + continue; + } + items.push(`i64 ${this.elemExprCode(seg.exprs[k]!)}`); + } + let itemsRef = "ptr null"; + if (items.length > 0) { + const sym = `@${p}_e${s}`; + lines.push(`${sym} = private constant [${items.length} x i64] [${items.join(", ")}]`); + itemsRef = `ptr ${sym}`; + } + elemRows.push( + `{ i64, i64, ptr } { i64 ${sigChar(seg.elemType).charCodeAt(0)}, i64 ${items.length}, ${itemsRef} }`, + ); + } + const elemsSym = `@${p}_elems`; + lines.push( + `${elemsSym} = private constant [${elemRows.length} x { i64, i64, ptr }] [${elemRows.join(", ")}]`, + ); + // Custom sections, when the program reads them. + const customRows: string[] = []; + if (this.opts.customSections === true) { + for (let s = 0; s < m.customs.length; s++) { + const custom = m.customs[s]!; + const name = textStr(custom.name); + const len = custom.payload.end - custom.payload.start; + let data = "ptr null"; + if (len > 0) { + const sym = `@${p}_c${s}`; + lines.push( + `${sym} = private unnamed_addr constant [${len} x i8] c"${cBytes(m.bytes, custom.payload.start, custom.payload.end)}", align 1`, + ); + data = `ptr ${sym}`; + } + customRows.push( + `{ ptr, i64, ptr, i64 } { ptr ${name.sym}, i64 ${name.len}, ${data}, i64 ${len} }`, + ); + } + } + const customsSym = `@${p}_customs`; + lines.push( + `${customsSym} = private constant [${customRows.length} x { ptr, i64, ptr, i64 }] [${customRows.join(", ")}]`, + ); + const memory = m.memories[0]; + const sha: string[] = []; + for (let i = 0; i < 32; i++) sha.push(`i8 ${sha256[i]!}`); + const desc = `@${p}_desc`; + const fields = [ + `[32 x i8] [${sha.join(", ")}]`, + `i64 ${m.bytes.length}`, + `i64 ${WASM_ABI_VERSION}`, + `i64 ${this.opts.boundsChecks ? 1 : 0}`, + `i64 ${m.imports.length}`, + `ptr ${importsSym}`, + `i64 ${m.exports.length}`, + `ptr ${exportsSym}`, + `i64 ${nf}`, + `i64 ${m.importedFuncs}`, + `ptr ${codesSym}`, + `ptr ${typesSym}`, + `ptr ${sigsSym}`, + `i64 ${m.tables.length}`, + `ptr ${tablesSym}`, + `i64 ${this.memoryCount}`, + `i64 ${memory === undefined ? 0 : memory.min}`, + `i64 ${memory === undefined || memory.max === null ? -1 : memory.max}`, + `i64 ${m.globals.length}`, + `ptr ${globalsSym}`, + `i64 ${m.datas.length}`, + `ptr ${datasSym}`, + `i64 ${m.elems.length}`, + `ptr ${elemsSym}`, + `ptr ${init}`, + `ptr ${m.start === null ? "null" : this.fn(m.start)}`, + `i64 ${customRows.length}`, + `ptr ${customsSym}`, + `ptr ${callThunksSym}`, + ]; + const descType = + "{ [32 x i8], i64, i64, i64, i64, ptr, i64, ptr, i64, i64, ptr, ptr, ptr, i64, ptr, i64, i64, i64, i64, ptr, i64, ptr, i64, ptr, ptr, ptr, i64, ptr, ptr }"; + lines.push(`${desc} = internal constant ${descType} { ${fields.join(", ")} }`); + this.text.push(lines.join("\n")); + return desc; + } + + /** The element-segment code of a non-ref.func constant expression. */ + elemExprCode(expr: WasmRange): number { + const c = new WasmCursor(this.m.bytes, expr.start); + const op = c.u8(); + if (op === 0xd0) { + c.valType(); + if (c.u8() === 0x0b) return -1; + } else if (op === 0x23) { + const g = c.u32(); + if (c.u8() === 0x0b) return -(2 + g); + } + throw new WasmTranslateError( + "element segment initializers other than ref.null, ref.func and global.get are not supported", + ); + } +} + +/** Store a value as a 64-bit slot; answers the slot operand. */ +function toSlot(out: string[], t: number, v: string, tag: string): string { + switch (t) { + case VAL_I32: + out.push(` %${tag}z = zext i32 ${v} to i64`); + return `%${tag}z`; + case VAL_I64: + return v; + case VAL_F32: + out.push(` %${tag}b = bitcast float ${v} to i32`); + out.push(` %${tag}z = zext i32 %${tag}b to i64`); + return `%${tag}z`; + case VAL_F64: + out.push(` %${tag}z = bitcast double ${v} to i64`); + return `%${tag}z`; + default: + out.push(` %${tag}z = ptrtoint ptr ${v} to i64`); + return `%${tag}z`; + } +} + +function fromSlot(out: string[], t: number, slot: string, tag: string): string { + switch (t) { + case VAL_I32: + out.push(` %${tag}v = trunc i64 ${slot} to i32`); + return `%${tag}v`; + case VAL_I64: + return slot; + case VAL_F32: + out.push(` %${tag}t = trunc i64 ${slot} to i32`); + out.push(` %${tag}v = bitcast i32 %${tag}t to float`); + return `%${tag}v`; + case VAL_F64: + out.push(` %${tag}v = bitcast i64 ${slot} to double`); + return `%${tag}v`; + default: + out.push(` %${tag}v = inttoptr i64 ${slot} to ptr`); + return `%${tag}v`; + } +} + +function emitSlotReturn(out: string[], results: readonly number[], buffer: string): void { + if (results.length === 0) { + out.push(` ret void`); + return; + } + const vals: string[] = []; + for (let i = 0; i < results.length; i++) { + out.push(` %rp${i} = getelementptr i64, ptr ${buffer}, i64 ${i}`); + out.push(` %rs${i} = load i64, ptr %rp${i}`); + vals.push(fromSlot(out, results[i]!, `%rs${i}`, `r${i}`)); + } + if (results.length === 1) { + out.push(` ret ${llType(results[0]!)} ${vals[0]}`); + return; + } + const ret = retType(results); + let agg = "undef"; + for (let i = 0; i < results.length; i++) { + out.push(` %agg${i} = insertvalue ${ret} ${agg}, ${llType(results[i]!)} ${vals[i]}, ${i}`); + agg = `%agg${i}`; + } + out.push(` ret ${ret} ${agg}`); +} + +const LOAD_INFO: Record = { + // opcode: [result type, memory type, bytes, extension] + 0x28: [VAL_I32, "i32", 4, ""], + 0x29: [VAL_I64, "i64", 8, ""], + 0x2a: [VAL_F32, "float", 4, ""], + 0x2b: [VAL_F64, "double", 8, ""], + 0x2c: [VAL_I32, "i8", 1, "sext"], + 0x2d: [VAL_I32, "i8", 1, "zext"], + 0x2e: [VAL_I32, "i16", 2, "sext"], + 0x2f: [VAL_I32, "i16", 2, "zext"], + 0x30: [VAL_I64, "i8", 1, "sext"], + 0x31: [VAL_I64, "i8", 1, "zext"], + 0x32: [VAL_I64, "i16", 2, "sext"], + 0x33: [VAL_I64, "i16", 2, "zext"], + 0x34: [VAL_I64, "i32", 4, "sext"], + 0x35: [VAL_I64, "i32", 4, "zext"], +}; + +const STORE_INFO: Record = { + 0x36: [VAL_I32, "i32", 4], + 0x37: [VAL_I64, "i64", 8], + 0x38: [VAL_F32, "float", 4], + 0x39: [VAL_F64, "double", 8], + 0x3a: [VAL_I32, "i8", 1], + 0x3b: [VAL_I32, "i16", 2], + 0x3c: [VAL_I64, "i8", 1], + 0x3d: [VAL_I64, "i16", 2], + 0x3e: [VAL_I64, "i32", 4], +}; + +/** Translates one function body (index >= 0) or hosts the init function's + * constant expressions (index -1). */ +class FunctionTranslator { + mt: ModuleTranslator; + m: WasmModule; + index: number; + ft: WasmFuncType; + entry = new Lines(); + lines = new Lines(); + stack: StackValue[] = []; + frames: Frame[] = []; + localTypes: number[] = []; + next = 0; + labels = 0; + live = true; + trapLabels = new Map(); + /** Guard mode: the memory base, loaded once in the entry block. */ + baseValue: string | null = null; + checked: boolean; + + constructor(mt: ModuleTranslator, index: number) { + this.mt = mt; + this.m = mt.m; + this.index = index; + this.ft = index >= 0 ? mt.funcType(index) : { params: [], results: [] }; + this.checked = mt.opts.boundsChecks; + } + + tmp(): string { + return `%v${this.next++}`; + } + + label(hint: string): string { + return `${hint}${this.labels++}`; + } + + add(line: string): void { + this.lines.add(line); + } + + emit(expr: string): string { + const v = this.tmp(); + this.add(` ${v} = ${expr}`); + return v; + } + + push(v: string, t: number): void { + this.stack.push({ v, t }); + } + + pop(): StackValue { + const v = this.stack.pop(); + if (v === undefined) throw new Error("wasm translator: operand stack underflow"); + return v; + } + + /** Pops a value that must have type `t`: the type a local, global, + * table or memory store writes. Validation guarantees it; a mismatch + * means the translator and the validator disagree about the code, so + * the module is not translated. */ + popType(t: number, what: string): StackValue { + const v = this.pop(); + if (v.t !== t) throw new WasmTranslateError(`${what} operand type does not match`); + return v; + } + + /** The declared type of local `i` (parameters first). */ + localType(i: number): number { + const t = this.localTypes[i]; + if (t === undefined) throw new WasmTranslateError(`unknown local ${i}`); + return t; + } + + /** The offset of a memarg over memory 0 (the only memory a translatable + * module has). */ + memargOffset(c: WasmCursor): number { + const flags = readMemargFlags(() => c.u32()); + if (flags.align < 0 || flags.memory !== 0) + throw new WasmTranslateError(`memarg of memory ${flags.memory} is not supported`); + return c.u32(); + } + + /** A memory index immediate (memory.size, memory.grow and the bulk + * memory instructions), which must be 0. */ + memoryIndex(c: WasmCursor): void { + const index = c.u32(); + if (index !== 0) throw new WasmTranslateError(`memory ${index} is not supported`); + } + + popN(n: number): StackValue[] { + const out = this.stack.splice(this.stack.length - n, n); + if (out.length !== n) throw new Error("wasm translator: operand stack underflow"); + return out; + } + + /** Starts a new basic block. */ + startBlock(label: string): void { + this.add(`${label}:`); + } + + alloca(type: string): string { + const v = `%s${this.next++}`; + this.entry.add(` ${v} = alloca ${type}`); + return v; + } + + slotPtr(offset: number): string { + if (offset === 0) return "%inst"; + return this.emit(`getelementptr inbounds i8, ptr %inst, i64 ${offset}`); + } + + loadPtrSlot(offset: number): string { + return this.emit(`load ptr, ptr ${this.slotPtr(offset)}, align 8`); + } + + trap(code: number): string { + let label = this.trapLabels.get(code); + if (label === undefined) { + label = `trap${code}`; + this.trapLabels.set(code, label); + } + return label; + } + + // ── memory ────────────────────────────────────────────────────────── + + /** Checked mode: the slots holding the base and byte length. */ + memSlots: { base: string; size: string } | null = null; + + refreshMemory(): void { + if (!this.checked || this.memSlots === null) return; + // From the memory object, not the instance: a memory another instance + // (or JavaScript) grew may have moved. + const mem = this.loadPtrSlot(OFF_MEMORY); + const base = this.emit(`load ptr, ptr ${mem}, align 8`); + this.add(` store ptr ${base}, ptr ${this.memSlots.base}`); + const sizePtr = this.emit(`getelementptr inbounds i8, ptr ${mem}, i64 8`); + const size = this.emit(`load i64, ptr ${sizePtr}, align 8`); + this.add(` store i64 ${size}, ptr ${this.memSlots.size}`); + } + + base(): string { + if (this.checked) { + return this.emit(`load ptr, ptr ${this.memSlots!.base}`); + } + if (this.baseValue === null) { + this.baseValue = "%membase"; + } + return this.baseValue; + } + + /** The address of an access of `bytes` bytes at `addr + offset`. */ + address(addr: string, offset: number, bytes: number): string { + const wide = this.emit(`zext i32 ${addr} to i64`); + const ea = offset === 0 ? wide : this.emit(`add i64 ${wide}, ${offset}`); + if (this.checked) { + const size = this.emit(`load i64, ptr ${this.memSlots!.size}`); + const endAddr = this.emit(`add i64 ${ea}, ${bytes}`); + const oob = this.emit(`icmp ugt i64 ${endAddr}, ${size}`); + const ok = this.label("ok"); + this.add(` br i1 ${oob}, label %${this.trap(TRAP_MEMORY_OOB)}, label %${ok}`); + this.startBlock(ok); + } + return this.emit(`getelementptr i8, ptr ${this.base()}, i64 ${ea}`); + } + + // ── constant expressions ──────────────────────────────────────────── + + constExpr(range: WasmRange): string { + const c = new WasmCursor(this.m.bytes, range.start); + const stack: string[] = []; + for (;;) { + const op = c.u8(); + if (op === 0x0b) break; + switch (op) { + case 0x41: + stack.push(String(c.s32())); + break; + case 0x42: { + const [lo, hi] = c.s64(); + stack.push(i64Lit(lo, hi)); + break; + } + case 0x43: + stack.push(this.emit(`bitcast i32 ${c.u32le() | 0} to float`)); + break; + case 0x44: { + const lo = c.u32le(); + const hi = c.u32le(); + stack.push(this.emit(`bitcast i64 ${i64Lit(lo, hi)} to double`)); + break; + } + case 0x23: { + const g = c.u32(); + const cell = this.loadPtrSlot(this.mt.globalSlot(g)); + stack.push(this.emit(`load ${llType(this.m.globals[g]!.type)}, ptr ${cell}`)); + break; + } + case 0xd0: + c.valType(); + stack.push("null"); + break; + case 0xd2: + stack.push(this.funcRef(c.u32())); + break; + case 0x6a: + case 0x6b: + case 0x6c: + case 0x7c: + case 0x7d: + case 0x7e: { + const b = stack.pop()!; + const a = stack.pop()!; + const t = op < 0x70 ? "i32" : "i64"; + const name = + op === 0x6a || op === 0x7c ? "add" : op === 0x6b || op === 0x7d ? "sub" : "mul"; + stack.push(this.emit(`${name} ${t} ${a}, ${b}`)); + break; + } + default: + throw new WasmTranslateError( + `constant expression opcode 0x${op.toString(16)} is not supported`, + ); + } + } + return stack[stack.length - 1]!; + } + + funcRef(f: number): string { + this.mt.refs.add(f); + const records = this.loadPtrSlot(OFF_FUNCREFS); + return this.emit(`getelementptr inbounds i8, ptr ${records}, i64 ${f * FUNCREF_SIZE}`); + } + + // ── control ───────────────────────────────────────────────────────── + + blockSig(c: WasmCursor): { params: number[]; results: number[] } { + const bt = c.blockType(); + if (bt.kind === "empty") return { params: [], results: [] }; + if (bt.kind === "value") return { params: [], results: [bt.type] }; + const t = this.m.types[bt.index]!; + return { params: t.params.slice(), results: t.results.slice() }; + } + + slotsFor(types: readonly number[]): string[] { + return types.map((t) => this.alloca(llType(t))); + } + + storeTo(slots: readonly string[], values: readonly StackValue[]): void { + for (let i = 0; i < slots.length; i++) { + const v = values[i]!; + this.add(` store ${llType(v.t)} ${v.v}, ptr ${slots[i]}`); + } + } + + loadFrom(slots: readonly string[], types: readonly number[]): void { + for (let i = 0; i < slots.length; i++) { + const t = types[i]!; + this.push(this.emit(`load ${llType(t)}, ptr ${slots[i]}`), t); + } + } + + /** Branch to the frame `depth` levels out (the stack keeps its values). */ + branch(depth: number): void { + const f = this.frames[this.frames.length - 1 - depth]!; + const n = f.branchSlots.length; + if (n > 0) this.storeTo(f.branchSlots, this.stack.slice(this.stack.length - n)); + this.add(` br label %${f.target}`); + } + + /** The label of a block that branches to `depth`, for conditional + * branches and tables: the target itself when no values travel. */ + branchEdge(depth: number, pending: string[]): string { + const f = this.frames[this.frames.length - 1 - depth]!; + if (f.branchSlots.length === 0) return f.target; + const edge = this.label("edge"); + const saved = this.lines; + const edgeLines = new Lines(); + this.lines = edgeLines; + this.startBlock(edge); + this.branch(depth); + this.lines = saved; + pending.push(...edgeLines.lines); + return edge; + } + + goDead(): void { + this.live = false; + } + + pushFrame(kind: Frame["kind"], sig: { params: number[]; results: number[] }): Frame { + const end = this.label("end"); + const frame: Frame = { + kind, + params: sig.params, + results: sig.results, + target: end, + end, + branchSlots: [], + resultSlots: this.slotsFor(sig.results), + height: this.stack.length - sig.params.length, + elseLabel: null, + ifParams: [], + live: true, + }; + frame.branchSlots = frame.resultSlots; + this.frames.push(frame); + return frame; + } + + /** Skips dead code from just after a terminator to the `else` or `end` + * of the current frame; answers the opcode it stopped at (consumed). */ + skipDead(c: WasmCursor): number { + let depth = 0; + for (;;) { + const op = c.u8(); + if (op === 0x02 || op === 0x03 || op === 0x04) { + c.blockType(); + depth++; + continue; + } + if (op === 0x0b) { + if (depth === 0) return op; + depth--; + continue; + } + if (op === 0x05 && depth === 0) return op; + skipImmediates(c, op); + } + } + + translate(): string[] { + const ft = this.ft; + const code = this.m.codes[this.index - this.m.importedFuncs]!; + // Locals. + const localSlots: string[] = []; + this.localTypes = ft.params.concat(code.locals); + for (let i = 0; i < this.localTypes.length; i++) { + const t = this.localTypes[i]!; + const slot = `%l${i}`; + localSlots.push(slot); + this.entry.add(` ${slot} = alloca ${llType(t)}`); + } + for (let i = 0; i < ft.params.length; i++) { + this.entry.add(` store ${llType(ft.params[i]!)} %p${i}, ptr %l${i}`); + } + for (let i = ft.params.length; i < this.localTypes.length; i++) { + const t = this.localTypes[i]!; + this.entry.add(` store ${llType(t)} ${zeroOf(t)}, ptr %l${i}`); + } + if (this.checked && this.mt.memoryCount > 0) { + this.memSlots = { base: "%mbase", size: "%msize" }; + this.entry.add(` %mbase = alloca ptr`); + this.entry.add(` %msize = alloca i64`); + } + // The function frame: branches to it return. + const ret = this.label("ret"); + const fnFrame: Frame = { + kind: "func", + params: [], + results: ft.results, + target: ret, + end: ret, + branchSlots: [], + resultSlots: this.slotsFor(ft.results), + height: 0, + elseLabel: null, + ifParams: [], + live: true, + }; + fnFrame.branchSlots = fnFrame.resultSlots; + this.frames.push(fnFrame); + if (this.memSlots !== null) this.refreshMemory(); + const c = new WasmCursor(this.m.bytes, code.body.start); + this.body(c, code.body.end); + // Epilogue. + const out: string[] = []; + out.push(`define internal ${this.mt.signature(ft, this.mt.fn(this.index))} ${FUNC_ATTRS} {`); + out.push(`entry:`); + out.push(...this.entry.lines); + if (!this.checked && this.baseValue !== null) { + out.push(` %membase.p = getelementptr inbounds i8, ptr %inst, i64 ${OFF_MEMBASE}`); + out.push(` %membase = load ptr, ptr %membase.p, align 8`); + } + if (this.checked && this.mt.stackChecked.has(this.index)) { + // Without the fault handler, stack exhaustion is an explicit check of + // the stack pointer against the runtime's guard for the running stack + // (thread or async fiber), in the functions through which the stack + // can grow without bound (stackCheckedFunctions). + // The address of a frame slot stands for the stack pointer; unlike + // llvm.stacksave it constrains no other code. + out.push(` %sp = alloca i8, align 1`); + out.push(` %sp.i = ptrtoint ptr %sp to i64`); + out.push(` %limit.p = call ptr @llvm.threadlocal.address.p0(ptr @scr_wasm_stack_limit)`); + out.push(` %limit = load i64, ptr %limit.p, align 8`); + out.push(` %exhausted = icmp ult i64 %sp.i, %limit`); + out.push(` br i1 %exhausted, label %exhausted.trap, label %body`); + out.push(`exhausted.trap:`); + out.push(` call void @scr_wasm_trap(i32 ${TRAP_EXHAUSTION})`); + out.push(` unreachable`); + } else { + out.push(` br label %body`); + } + out.push(`body:`); + out.push(...this.lines.lines); + for (const [code2, label] of this.trapLabels) { + out.push(`${label}:`); + out.push(` call void @scr_wasm_trap(i32 ${code2})`); + out.push(` unreachable`); + } + out.push(`}`); + return [out.join("\n")]; + } + + /** The function body; returns at the function's final `end`. */ + body(c: WasmCursor, end: number): void { + while (c.pos < end) { + if (!this.live) { + const op = this.skipDead(c); + if (op === 0x05) this.opElse(); + else if (this.opEnd()) return; + continue; + } + const op = c.u8(); + if (op === 0x0b) { + if (this.opEnd()) return; + continue; + } + this.instruction(c, op); + } + } + + /** `end`: closes the innermost frame; true when that was the function. */ + opEnd(): boolean { + const f = this.frames[this.frames.length - 1]!; + if (this.live) { + const n = f.results.length; + this.storeTo(f.resultSlots, this.stack.slice(this.stack.length - n)); + this.add(` br label %${f.end}`); + } + if (f.elseLabel !== null) { + // An if without else: the implicit else passes its parameters on. + this.startBlock(f.elseLabel); + if (f.live) { + this.storeTo(f.resultSlots, f.ifParams); + } + this.add(` br label %${f.end}`); + f.elseLabel = null; + } + this.frames.pop(); + this.stack.length = f.height; + this.startBlock(f.end); + if (f.kind === "func") { + if (f.results.length === 0) this.add(` ret void`); + else { + this.loadFrom(f.resultSlots, f.results); + const vals = this.popN(f.results.length); + if (vals.length === 1) this.add(` ret ${llType(vals[0]!.t)} ${vals[0]!.v}`); + else { + const rt = retType(f.results); + let agg = "undef"; + for (let i = 0; i < vals.length; i++) { + agg = this.emit(`insertvalue ${rt} ${agg}, ${llType(vals[i]!.t)} ${vals[i]!.v}, ${i}`); + } + this.add(` ret ${rt} ${agg}`); + } + } + return true; + } + this.loadFrom(f.resultSlots, f.results); + this.live = true; + return false; + } + + opElse(): void { + const f = this.frames[this.frames.length - 1]!; + if (this.live) { + const n = f.results.length; + this.storeTo(f.resultSlots, this.stack.slice(this.stack.length - n)); + this.add(` br label %${f.end}`); + } + this.stack.length = f.height; + this.startBlock(f.elseLabel!); + f.elseLabel = null; + for (const v of f.ifParams) this.stack.push(v); + this.live = f.live; + if (!f.live) { + // The if itself was dead: its else branch is too. + this.add(` unreachable`); + } + } + + call(index: number): void { + const ft = this.mt.funcType(index); + const args = this.popN(ft.params.length); + const argText = ["ptr %inst", ...args.map((a) => `${llType(a.t)} ${a.v}`)].join(", "); + this.callWith(this.mt.fn(index), ft, argText); + } + + callWith(callee: string, ft: WasmFuncType, argText: string): void { + const rt = retType(ft.results); + if (ft.results.length === 0) { + this.add(` call void ${callee}(${argText})`); + } else { + const r = this.emit(`call ${rt} ${callee}(${argText})`); + if (ft.results.length === 1) this.push(r, ft.results[0]!); + else + for (let i = 0; i < ft.results.length; i++) + this.push(this.emit(`extractvalue ${rt} ${r}, ${i}`), ft.results[i]!); + } + this.refreshMemory(); + } + + callIndirect(typeIndex: number, table: number): void { + const ft = this.m.types[typeIndex]!; + const idx = this.pop(); + const args = this.popN(ft.params.length); + const t = this.loadPtrSlot(this.mt.tableSlot(table)); + const sizePtr = this.emit(`getelementptr inbounds i8, ptr ${t}, i64 8`); + const size = this.emit(`load i32, ptr ${sizePtr}, align 8`); + const inRange = this.emit(`icmp ult i32 ${idx.v}, ${size}`); + const ok = this.label("ci"); + this.add(` br i1 ${inRange}, label %${ok}, label %${this.trap(TRAP_TABLE_OOB)}`); + this.startBlock(ok); + const elems = this.emit(`load ptr, ptr ${t}, align 8`); + const wide = this.emit(`zext i32 ${idx.v} to i64`); + const slot = this.emit(`getelementptr inbounds ptr, ptr ${elems}, i64 ${wide}`); + const rec = this.emit(`load ptr, ptr ${slot}, align 8`); + const isNull = this.emit(`icmp eq ptr ${rec}, null`); + const nn = this.label("cn"); + this.add(` br i1 ${isNull}, label %${this.trap(TRAP_SIGNATURE)}, label %${nn}`); + this.startBlock(nn); + const typePtr = this.emit(`getelementptr inbounds i8, ptr ${rec}, i64 8`); + const type = this.emit(`load i64, ptr ${typePtr}, align 8`); + const same = this.emit(`icmp eq i64 ${type}, ${this.mt.typeHashes[typeIndex]}`); + const go = this.label("cg"); + this.add(` br i1 ${same}, label %${go}, label %${this.trap(TRAP_SIGNATURE)}`); + this.startBlock(go); + const codePtr = this.emit(`load ptr, ptr ${rec}, align 8`); + const instPtr = this.emit(`getelementptr inbounds i8, ptr ${rec}, i64 16`); + const inst = this.emit(`load ptr, ptr ${instPtr}, align 8`); + const argText = [`ptr ${inst}`, ...args.map((a) => `${llType(a.t)} ${a.v}`)].join(", "); + this.callWith(codePtr, ft, argText); + } + + /** Integer division and remainder with wasm's traps. */ + divRem(op: number, t: string): void { + const b = this.pop(); + const a = this.pop(); + const ty = b.t; + const zero = this.emit(`icmp eq ${t} ${b.v}, 0`); + const signed = op === 0x6d || op === 0x6f || op === 0x7f || op === 0x81; + const rem = op === 0x6f || op === 0x70 || op === 0x81 || op === 0x82; + const nz = this.label("nz"); + this.add( + ` br i1 ${zero}, label %${this.trap(rem ? TRAP_REM_BY_ZERO : TRAP_DIV_BY_ZERO)}, label %${nz}`, + ); + this.startBlock(nz); + const min = t === "i32" ? "-2147483648" : "-9223372036854775808"; + if (signed && !rem) { + const isMin = this.emit(`icmp eq ${t} ${a.v}, ${min}`); + const isNeg1 = this.emit(`icmp eq ${t} ${b.v}, -1`); + const ovf = this.emit(`and i1 ${isMin}, ${isNeg1}`); + const okl = this.label("dv"); + this.add(` br i1 ${ovf}, label %${this.trap(TRAP_DIV_UNREPRESENTABLE)}, label %${okl}`); + this.startBlock(okl); + this.push(this.emit(`sdiv ${t} ${a.v}, ${b.v}`), ty); + return; + } + if (signed && rem) { + // INT_MIN % -1 is 0 in wasm (LLVM's srem would be undefined). + const isNeg1 = this.emit(`icmp eq ${t} ${b.v}, -1`); + const divisor = this.emit(`select i1 ${isNeg1}, ${t} 1, ${t} ${b.v}`); + this.push(this.emit(`srem ${t} ${a.v}, ${divisor}`), ty); + return; + } + this.push(this.emit(`${rem ? "urem" : "udiv"} ${t} ${a.v}, ${b.v}`), ty); + } + + /** Trapping float-to-int conversion. */ + truncTrap(op: number): void { + const x = this.pop(); + const from = x.t === VAL_F32 ? "float" : "double"; + // [lower bound exclusive?, lower, upper (exclusive)] as exact doubles. + let lo = ""; + let loInclusive = false; + let hi = ""; + let to = "i32"; + let signed = true; + switch (op) { + case 0xa8: // i32.trunc_f32_s + case 0xaa: // i32.trunc_f64_s + lo = op === 0xa8 ? "-2147483648.0" : "-2147483649.0"; + loInclusive = op === 0xa8; + hi = "2147483648.0"; + break; + case 0xa9: + case 0xab: + lo = "-1.0"; + hi = "4294967296.0"; + signed = false; + break; + case 0xae: + case 0xb0: + lo = "-9223372036854775808.0"; + loInclusive = true; + hi = "9223372036854775808.0"; + to = "i64"; + break; + default: + lo = "-1.0"; + hi = "18446744073709551616.0"; + to = "i64"; + signed = false; + break; + } + const d = from === "double" ? x.v : this.emit(`fpext float ${x.v} to double`); + const above = this.emit(`fcmp ${loInclusive ? "oge" : "ogt"} double ${d}, ${hexDouble(lo)}`); + const below = this.emit(`fcmp olt double ${d}, ${hexDouble(hi)}`); + const ok = this.emit(`and i1 ${above}, ${below}`); + const okl = this.label("cv"); + this.add(` br i1 ${ok}, label %${okl}, label %${this.trap(TRAP_FLOAT_UNREPRESENTABLE)}`); + this.startBlock(okl); + this.push( + this.emit(`${signed ? "fptosi" : "fptoui"} ${from} ${x.v} to ${to}`), + to === "i32" ? VAL_I32 : VAL_I64, + ); + } + + unaryIntrinsic(name: string, t: string, vt: number, extra = ""): void { + const a = this.pop(); + this.push(this.emit(`call ${t} @llvm.${name}(${t} ${a.v}${extra})`), vt); + } + + binaryIntrinsic(name: string, t: string, vt: number): void { + const b = this.pop(); + const a = this.pop(); + this.push(this.emit(`call ${t} @llvm.${name}(${t} ${a.v}, ${t} ${b.v})`), vt); + } + + binary(instr: string, t: string, vt: number): void { + const b = this.pop(); + const a = this.pop(); + this.push(this.emit(`${instr} ${t} ${a.v}, ${b.v}`), vt); + } + + compare(pred: string, t: string, float: boolean): void { + const b = this.pop(); + const a = this.pop(); + const r = this.emit(`${float ? "fcmp" : "icmp"} ${pred} ${t} ${a.v}, ${b.v}`); + this.push(this.emit(`zext i1 ${r} to i32`), VAL_I32); + } + + eqz(t: string): void { + const a = this.pop(); + const r = this.emit(`icmp eq ${t} ${a.v}, 0`); + this.push(this.emit(`zext i1 ${r} to i32`), VAL_I32); + } + + shift(instr: string, t: string, vt: number): void { + const b = this.pop(); + const a = this.pop(); + const masked = this.emit(`and ${t} ${b.v}, ${t === "i32" ? 31 : 63}`); + this.push(this.emit(`${instr} ${t} ${a.v}, ${masked}`), vt); + } + + rotate(name: string, t: string, vt: number): void { + const b = this.pop(); + const a = this.pop(); + this.push(this.emit(`call ${t} @llvm.${name}.${t}(${t} ${a.v}, ${t} ${a.v}, ${t} ${b.v})`), vt); + } + + convert(instr: string, from: string, to: string, vt: number): void { + const a = this.pop(); + this.push(this.emit(`${instr} ${from} ${a.v} to ${to}`), vt); + } + + instruction(c: WasmCursor, op: number): void { + switch (op) { + case 0x00: // unreachable + this.add(` br label %${this.trap(TRAP_UNREACHABLE)}`); + this.goDead(); + return; + case 0x01: + return; + case 0x02: { + // block + const sig = this.blockSig(c); + this.pushFrame("block", sig); + return; + } + case 0x03: { + // loop + const sig = this.blockSig(c); + const f = this.pushFrame("loop", sig); + f.target = this.label("loop"); + f.branchSlots = this.slotsFor(sig.params); + const params = this.popN(sig.params.length); + this.storeTo(f.branchSlots, params); + this.add(` br label %${f.target}`); + this.startBlock(f.target); + this.loadFrom(f.branchSlots, sig.params); + return; + } + case 0x04: { + // if + const sig = this.blockSig(c); + const cond = this.pop(); + const f = this.pushFrame("if", sig); + f.ifParams = this.stack.slice(this.stack.length - sig.params.length); + const then = this.label("then"); + f.elseLabel = this.label("else"); + const test = this.emit(`icmp ne i32 ${cond.v}, 0`); + this.add(` br i1 ${test}, label %${then}, label %${f.elseLabel}`); + this.startBlock(then); + return; + } + case 0x05: + this.opElse(); + return; + case 0x0c: { + const depth = c.u32(); + this.branch(depth); + this.goDead(); + return; + } + case 0x0d: { + const depth = c.u32(); + const cond = this.pop(); + const test = this.emit(`icmp ne i32 ${cond.v}, 0`); + const pending: string[] = []; + const target = this.branchEdge(depth, pending); + const cont = this.label("br"); + this.add(` br i1 ${test}, label %${target}, label %${cont}`); + for (const line of pending) this.add(line); + this.startBlock(cont); + return; + } + case 0x0e: { + const n = c.u32(); + const depths: number[] = []; + for (let i = 0; i < n; i++) depths.push(c.u32()); + const def = c.u32(); + const idx = this.pop(); + const pending: string[] = []; + const edges = new Map(); + const edgeOf = (d: number): string => { + let e = edges.get(d); + if (e === undefined) { + e = this.branchEdge(d, pending); + edges.set(d, e); + } + return e; + }; + const cases = depths.map((d, i) => `i32 ${i}, label %${edgeOf(d)}`); + this.add(` switch i32 ${idx.v}, label %${edgeOf(def)} [${cases.join(" ")}]`); + for (const line of pending) this.add(line); + this.goDead(); + return; + } + case 0x0f: // return + this.branch(this.frames.length - 1); + this.goDead(); + return; + case 0x10: + this.call(c.u32()); + return; + case 0x11: { + const type = c.u32(); + const table = c.u32(); + this.callIndirect(type, table); + return; + } + case 0x1a: { + // A dropped load must still fault when it is out of bounds: LLVM + // would delete an unused ordinary load. + const v = this.pop(); + if (v.load !== undefined) { + const line = this.lines.lines[v.load]!; + this.lines.lines[v.load] = line.replace(" = load ", " = load volatile "); + } + return; + } + case 0x1b: + case 0x1c: { + if (op === 0x1c) { + const n = c.u32(); + for (let i = 0; i < n; i++) c.valType(); + } + const cond = this.pop(); + const b = this.pop(); + const a = this.pop(); + const test = this.emit(`icmp ne i32 ${cond.v}, 0`); + const t = llType(a.t); + this.push(this.emit(`select i1 ${test}, ${t} ${a.v}, ${t} ${b.v}`), a.t); + return; + } + case 0x20: { + const i = c.u32(); + const t = this.localType(i); + this.push(this.emit(`load ${llType(t)}, ptr %l${i}`), t); + return; + } + case 0x21: { + const i = c.u32(); + const t = this.localType(i); + const v = this.popType(t, "local.set"); + this.add(` store ${llType(t)} ${v.v}, ptr %l${i}`); + return; + } + case 0x22: { + const i = c.u32(); + const t = this.localType(i); + const v = this.popType(t, "local.tee"); + this.stack.push(v); + this.add(` store ${llType(t)} ${v.v}, ptr %l${i}`); + return; + } + case 0x23: { + const g = c.u32(); + const t = this.m.globals[g]!.type; + const cell = this.loadPtrSlot(this.mt.globalSlot(g)); + this.push(this.emit(`load ${llType(t)}, ptr ${cell}, align 8`), t); + return; + } + case 0x24: { + const g = c.u32(); + const global = this.m.globals[g]; + if (global === undefined) throw new WasmTranslateError(`unknown global ${g}`); + const v = this.popType(global.type, "global.set"); + const cell = this.loadPtrSlot(this.mt.globalSlot(g)); + if (v.t === VAL_EXTERNREF) + this.add(` call void @scr_wasm_global_set_ref(ptr ${cell}, ptr ${v.v})`); + else this.add(` store ${llType(v.t)} ${v.v}, ptr ${cell}, align 8`); + return; + } + case 0x25: { + const t = c.u32(); + const i = this.pop(); + this.push( + this.emit(`call ptr @scr_wasm_table_get(ptr %inst, i32 ${t}, i32 ${i.v})`), + this.m.tables[t]!.elemType, + ); + return; + } + case 0x26: { + const t = c.u32(); + const table = this.m.tables[t]; + if (table === undefined) throw new WasmTranslateError(`unknown table ${t}`); + const v = this.popType(table.elemType, "table.set"); + const i = this.popType(VAL_I32, "table.set"); + this.add(` call void @scr_wasm_table_set(ptr %inst, i32 ${t}, i32 ${i.v}, ptr ${v.v})`); + return; + } + case 0x3f: { + this.memoryIndex(c); + const mem = this.loadPtrSlot(OFF_MEMORY); + const sizePtr = this.emit(`getelementptr inbounds i8, ptr ${mem}, i64 8`); + const size = this.emit(`load i64, ptr ${sizePtr}, align 8`); + const pages = this.emit(`lshr i64 ${size}, 16`); + this.push(this.emit(`trunc i64 ${pages} to i32`), VAL_I32); + return; + } + case 0x40: { + this.memoryIndex(c); + const delta = this.pop(); + this.push(this.emit(`call i32 @scr_wasm_memory_grow(ptr %inst, i32 ${delta.v})`), VAL_I32); + this.refreshMemory(); + return; + } + case 0x41: + this.push(String(c.s32()), VAL_I32); + return; + case 0x42: { + const [lo, hi] = c.s64(); + this.push(i64Lit(lo, hi), VAL_I64); + return; + } + case 0x43: + this.push(this.emit(`bitcast i32 ${c.u32le() | 0} to float`), VAL_F32); + return; + case 0x44: { + const lo = c.u32le(); + const hi = c.u32le(); + this.push(this.emit(`bitcast i64 ${i64Lit(lo, hi)} to double`), VAL_F64); + return; + } + case 0xd0: + c.valType(); + this.push("null", c.bytes[c.pos - 1]!); + return; + case 0xd1: { + const a = this.pop(); + const r = this.emit(`icmp eq ptr ${a.v}, null`); + this.push(this.emit(`zext i1 ${r} to i32`), VAL_I32); + return; + } + case 0xd2: + this.push(this.funcRef(c.u32()), VAL_FUNCREF); + return; + case 0xfc: + this.prefixed(c); + return; + default: + break; + } + if (op >= 0x28 && op <= 0x35) { + const offset = this.memargOffset(c); + const [vt, mt, bytes, ext] = LOAD_INFO[op]!; + const addr = this.popType(VAL_I32, "load address"); + const p = this.address(addr.v, offset, bytes); + const line = this.lines.lines.length; + const loaded = this.emit(`load ${mt}, ptr ${p}, align 1`); + if (ext === "") this.stack.push({ v: loaded, t: vt, load: line }); + else { + const extended = this.emit(`${ext} ${mt} ${loaded} to ${llType(vt)}`); + this.stack.push({ v: extended, t: vt, load: line }); + } + return; + } + if (op >= 0x36 && op <= 0x3e) { + const offset = this.memargOffset(c); + const [vt, mt, bytes] = STORE_INFO[op]!; + const v = this.popType(vt, "store"); + const addr = this.popType(VAL_I32, "store address"); + const p = this.address(addr.v, offset, bytes); + let value = v.v; + if (mt === "i8" || mt === "i16" || (mt === "i32" && v.t === VAL_I64)) { + value = this.emit(`trunc ${llType(v.t)} ${v.v} to ${mt}`); + } + this.add(` store ${mt} ${value}, ptr ${p}, align 1`); + return; + } + this.numeric(op); + } + + numeric(op: number): void { + const I32 = VAL_I32; + const I64 = VAL_I64; + const F32 = VAL_F32; + const F64 = VAL_F64; + switch (op) { + case 0x45: + return this.eqz("i32"); + case 0x46: + return this.compare("eq", "i32", false); + case 0x47: + return this.compare("ne", "i32", false); + case 0x48: + return this.compare("slt", "i32", false); + case 0x49: + return this.compare("ult", "i32", false); + case 0x4a: + return this.compare("sgt", "i32", false); + case 0x4b: + return this.compare("ugt", "i32", false); + case 0x4c: + return this.compare("sle", "i32", false); + case 0x4d: + return this.compare("ule", "i32", false); + case 0x4e: + return this.compare("sge", "i32", false); + case 0x4f: + return this.compare("uge", "i32", false); + case 0x50: + return this.eqz("i64"); + case 0x51: + return this.compare("eq", "i64", false); + case 0x52: + return this.compare("ne", "i64", false); + case 0x53: + return this.compare("slt", "i64", false); + case 0x54: + return this.compare("ult", "i64", false); + case 0x55: + return this.compare("sgt", "i64", false); + case 0x56: + return this.compare("ugt", "i64", false); + case 0x57: + return this.compare("sle", "i64", false); + case 0x58: + return this.compare("ule", "i64", false); + case 0x59: + return this.compare("sge", "i64", false); + case 0x5a: + return this.compare("uge", "i64", false); + case 0x5b: + return this.compare("oeq", "float", true); + case 0x5c: + return this.compare("une", "float", true); + case 0x5d: + return this.compare("olt", "float", true); + case 0x5e: + return this.compare("ogt", "float", true); + case 0x5f: + return this.compare("ole", "float", true); + case 0x60: + return this.compare("oge", "float", true); + case 0x61: + return this.compare("oeq", "double", true); + case 0x62: + return this.compare("une", "double", true); + case 0x63: + return this.compare("olt", "double", true); + case 0x64: + return this.compare("ogt", "double", true); + case 0x65: + return this.compare("ole", "double", true); + case 0x66: + return this.compare("oge", "double", true); + case 0x67: + return this.unaryIntrinsic("ctlz.i32", "i32", I32, ", i1 false"); + case 0x68: + return this.unaryIntrinsic("cttz.i32", "i32", I32, ", i1 false"); + case 0x69: + return this.unaryIntrinsic("ctpop.i32", "i32", I32); + case 0x6a: + return this.binary("add", "i32", I32); + case 0x6b: + return this.binary("sub", "i32", I32); + case 0x6c: + return this.binary("mul", "i32", I32); + case 0x6d: + case 0x6e: + case 0x6f: + case 0x70: + return this.divRem(op, "i32"); + case 0x71: + return this.binary("and", "i32", I32); + case 0x72: + return this.binary("or", "i32", I32); + case 0x73: + return this.binary("xor", "i32", I32); + case 0x74: + return this.shift("shl", "i32", I32); + case 0x75: + return this.shift("ashr", "i32", I32); + case 0x76: + return this.shift("lshr", "i32", I32); + case 0x77: + return this.rotate("fshl", "i32", I32); + case 0x78: + return this.rotate("fshr", "i32", I32); + case 0x79: + return this.unaryIntrinsic("ctlz.i64", "i64", I64, ", i1 false"); + case 0x7a: + return this.unaryIntrinsic("cttz.i64", "i64", I64, ", i1 false"); + case 0x7b: + return this.unaryIntrinsic("ctpop.i64", "i64", I64); + case 0x7c: + return this.binary("add", "i64", I64); + case 0x7d: + return this.binary("sub", "i64", I64); + case 0x7e: + return this.binary("mul", "i64", I64); + case 0x7f: + case 0x80: + case 0x81: + case 0x82: + return this.divRem(op, "i64"); + case 0x83: + return this.binary("and", "i64", I64); + case 0x84: + return this.binary("or", "i64", I64); + case 0x85: + return this.binary("xor", "i64", I64); + case 0x86: + return this.shift("shl", "i64", I64); + case 0x87: + return this.shift("ashr", "i64", I64); + case 0x88: + return this.shift("lshr", "i64", I64); + case 0x89: + return this.rotate("fshl", "i64", I64); + case 0x8a: + return this.rotate("fshr", "i64", I64); + case 0x8b: + return this.unaryIntrinsic("fabs.f32", "float", F32); + case 0x8c: { + const a = this.pop(); + this.push(this.emit(`fneg float ${a.v}`), F32); + return; + } + case 0x8d: + return this.unaryIntrinsic("ceil.f32", "float", F32); + case 0x8e: + return this.unaryIntrinsic("floor.f32", "float", F32); + case 0x8f: + return this.unaryIntrinsic("trunc.f32", "float", F32); + case 0x90: + return this.unaryIntrinsic("roundeven.f32", "float", F32); + case 0x91: + return this.unaryIntrinsic("sqrt.f32", "float", F32); + case 0x92: + return this.binary("fadd", "float", F32); + case 0x93: + return this.binary("fsub", "float", F32); + case 0x94: + return this.binary("fmul", "float", F32); + case 0x95: + return this.binary("fdiv", "float", F32); + case 0x96: + return this.binaryIntrinsic("minimum.f32", "float", F32); + case 0x97: + return this.binaryIntrinsic("maximum.f32", "float", F32); + case 0x98: + return this.binaryIntrinsic("copysign.f32", "float", F32); + case 0x99: + return this.unaryIntrinsic("fabs.f64", "double", F64); + case 0x9a: { + const a = this.pop(); + this.push(this.emit(`fneg double ${a.v}`), F64); + return; + } + case 0x9b: + return this.unaryIntrinsic("ceil.f64", "double", F64); + case 0x9c: + return this.unaryIntrinsic("floor.f64", "double", F64); + case 0x9d: + return this.unaryIntrinsic("trunc.f64", "double", F64); + case 0x9e: + return this.unaryIntrinsic("roundeven.f64", "double", F64); + case 0x9f: + return this.unaryIntrinsic("sqrt.f64", "double", F64); + case 0xa0: + return this.binary("fadd", "double", F64); + case 0xa1: + return this.binary("fsub", "double", F64); + case 0xa2: + return this.binary("fmul", "double", F64); + case 0xa3: + return this.binary("fdiv", "double", F64); + case 0xa4: + return this.binaryIntrinsic("minimum.f64", "double", F64); + case 0xa5: + return this.binaryIntrinsic("maximum.f64", "double", F64); + case 0xa6: + return this.binaryIntrinsic("copysign.f64", "double", F64); + case 0xa7: + return this.convert("trunc", "i64", "i32", I32); + case 0xa8: + case 0xa9: + case 0xaa: + case 0xab: + case 0xae: + case 0xaf: + case 0xb0: + case 0xb1: + return this.truncTrap(op); + case 0xac: + return this.convert("sext", "i32", "i64", I64); + case 0xad: + return this.convert("zext", "i32", "i64", I64); + case 0xb2: + return this.convert("sitofp", "i32", "float", F32); + case 0xb3: + return this.convert("uitofp", "i32", "float", F32); + case 0xb4: + return this.convert("sitofp", "i64", "float", F32); + case 0xb5: + return this.convert("uitofp", "i64", "float", F32); + case 0xb6: + return this.convert("fptrunc", "double", "float", F32); + case 0xb7: + return this.convert("sitofp", "i32", "double", F64); + case 0xb8: + return this.convert("uitofp", "i32", "double", F64); + case 0xb9: + return this.convert("sitofp", "i64", "double", F64); + case 0xba: + return this.convert("uitofp", "i64", "double", F64); + case 0xbb: + return this.convert("fpext", "float", "double", F64); + case 0xbc: + return this.convert("bitcast", "float", "i32", I32); + case 0xbd: + return this.convert("bitcast", "double", "i64", I64); + case 0xbe: + return this.convert("bitcast", "i32", "float", F32); + case 0xbf: + return this.convert("bitcast", "i64", "double", F64); + case 0xc0: + case 0xc1: { + const a = this.pop(); + const n = op === 0xc0 ? "i8" : "i16"; + const narrow = this.emit(`trunc i32 ${a.v} to ${n}`); + this.push(this.emit(`sext ${n} ${narrow} to i32`), I32); + return; + } + case 0xc2: + case 0xc3: + case 0xc4: { + const a = this.pop(); + const n = op === 0xc2 ? "i8" : op === 0xc3 ? "i16" : "i32"; + const narrow = this.emit(`trunc i64 ${a.v} to ${n}`); + this.push(this.emit(`sext ${n} ${narrow} to i64`), I64); + return; + } + default: + throw new WasmTranslateError(`opcode 0x${op.toString(16)} is not supported`); + } + } + + prefixed(c: WasmCursor): void { + const sub = c.u32(); + if (sub <= 7) { + // Saturating float-to-int conversions. + const a = this.pop(); + const from = a.t === VAL_F32 ? "f32" : "f64"; + const fromTy = a.t === VAL_F32 ? "float" : "double"; + const to = sub < 4 ? "i32" : "i64"; + const signed = (sub & 1) === 0; + this.push( + this.emit( + `call ${to} @llvm.${signed ? "fptosi" : "fptoui"}.sat.${to}.${from}(${fromTy} ${a.v})`, + ), + to === "i32" ? VAL_I32 : VAL_I64, + ); + return; + } + switch (sub) { + case 8: { + // memory.init + const seg = c.u32(); + this.memoryIndex(c); + const n = this.pop(); + const s = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_memory_init(ptr %inst, i32 ${seg}, i32 ${d.v}, i32 ${s.v}, i32 ${n.v})`, + ); + return; + } + case 9: + this.add(` call void @scr_wasm_data_drop(ptr %inst, i32 ${c.u32()})`); + return; + case 10: { + this.memoryIndex(c); + this.memoryIndex(c); + const n = this.pop(); + const s = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_memory_copy(ptr %inst, i32 ${d.v}, i32 ${s.v}, i32 ${n.v})`, + ); + return; + } + case 11: { + this.memoryIndex(c); + const n = this.pop(); + const v = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_memory_fill(ptr %inst, i32 ${d.v}, i32 ${v.v}, i32 ${n.v})`, + ); + return; + } + case 12: { + const seg = c.u32(); + const t = c.u32(); + const n = this.pop(); + const s = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_table_init(ptr %inst, i32 ${t}, i32 ${seg}, i32 ${d.v}, i32 ${s.v}, i32 ${n.v})`, + ); + return; + } + case 13: + this.add(` call void @scr_wasm_elem_drop(ptr %inst, i32 ${c.u32()})`); + return; + case 14: { + const dt = c.u32(); + const st = c.u32(); + const n = this.pop(); + const s = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_table_copy(ptr %inst, i32 ${dt}, i32 ${st}, i32 ${d.v}, i32 ${s.v}, i32 ${n.v})`, + ); + return; + } + case 15: { + const t = c.u32(); + const n = this.pop(); + const v = this.pop(); + this.push( + this.emit(`call i32 @scr_wasm_table_grow(ptr %inst, i32 ${t}, ptr ${v.v}, i32 ${n.v})`), + VAL_I32, + ); + return; + } + case 16: { + const t = c.u32(); + const tab = this.loadPtrSlot(this.mt.tableSlot(t)); + const sizePtr = this.emit(`getelementptr inbounds i8, ptr ${tab}, i64 8`); + this.push(this.emit(`load i32, ptr ${sizePtr}, align 8`), VAL_I32); + return; + } + case 17: { + const t = c.u32(); + const n = this.pop(); + const v = this.pop(); + const d = this.pop(); + this.add( + ` call void @scr_wasm_table_fill(ptr %inst, i32 ${t}, i32 ${d.v}, ptr ${v.v}, i32 ${n.v})`, + ); + return; + } + default: + throw new WasmTranslateError(`opcode 0xfc ${sub} is not supported`); + } + } +} + +/** The functions through which the stack can grow without bound, which + * check the stack pointer on entry: members of a cycle of direct calls + * (including self-recursion), and functions that call through a table or + * call an import (an indirect call can reach any function, and an import + * can call back into an export). Every other call chain is finite, so its + * depth is bounded by the module and the guard's reserve absorbs it. */ +export function stackCheckedFunctions(m: WasmModule): Set { + const n = m.funcTypes.length; + const callees: number[][] = []; + const checked = new Set(); + for (let f = 0; f < n; f++) callees.push([]); + for (let i = 0; i < m.codes.length; i++) { + const f = m.importedFuncs + i; + const body = m.codes[i]!.body; + const c = new WasmCursor(m.bytes, body.start); + while (c.pos < body.end) { + const op = c.u8(); + if (op === 0x10) { + const callee = c.u32(); + if (callee < m.importedFuncs) checked.add(f); + else callees[f]!.push(callee); + } else if (op === 0x11) { + c.u32(); + c.u32(); + checked.add(f); + } else { + skipImmediates(c, op); + } + } + } + // Tarjan's strongly connected components, iteratively. + const index = new Int32Array(n).fill(-1); + const low = new Int32Array(n); + const onStack = new Uint8Array(n); + const stack: number[] = []; + let next = 0; + for (let root = m.importedFuncs; root < n; root++) { + if (index[root] !== -1) continue; + const workNode: number[] = [root]; + const workEdge: number[] = [0]; + index[root] = low[root] = next++; + stack.push(root); + onStack[root] = 1; + while (workNode.length > 0) { + const top = workNode.length - 1; + const v = workNode[top]!; + const edges = callees[v]!; + const e = workEdge[top]!; + if (e < edges.length) { + workEdge[top] = e + 1; + const w = edges[e]!; + if (index[w] === -1) { + index[w] = low[w] = next++; + stack.push(w); + onStack[w] = 1; + workNode.push(w); + workEdge.push(0); + } else if (onStack[w]) { + low[v] = Math.min(low[v]!, index[w]!); + } + continue; + } + workNode.pop(); + workEdge.pop(); + if (workNode.length > 0) { + const parent = workNode[workNode.length - 1]!; + low[parent] = Math.min(low[parent]!, low[v]!); + } + if (low[v] === index[v]) { + const component: number[] = []; + for (;;) { + const w = stack.pop()!; + onStack[w] = 0; + component.push(w); + if (w === v) break; + } + if (component.length > 1 || edges.includes(v)) for (const w of component) checked.add(w); + } + } + } + return checked; +} + +/** A decimal double literal as LLVM's exact hexadecimal form. */ +function hexDouble(text: string): string { + const view = new DataView(new ArrayBuffer(8)); + view.setFloat64(0, Number(text)); + return `0x${hex8(view.getUint32(0))}${hex8(view.getUint32(4))}`.toUpperCase().replace("0X", "0x"); +} + +function hexOf(bytes: Uint8Array): string { + let s = ""; + for (let i = 0; i < bytes.length; i++) s += bytes[i]!.toString(16).padStart(2, "0"); + return s; +} + +/** The symbol prefix of a module's translation. */ +export function wasmSymbolPrefix(sha256: Uint8Array): string { + return `scr_wasm_${hexOf(sha256).slice(0, 16)}`; +} + +/** Translates a module that binary.ts validated within the translatable + * feature level. Throws WasmTranslateError for constructs outside it. */ +export function translateWasmModule( + bytes: Uint8Array, + sha256: Uint8Array, + opts: WasmTranslateOptions, +): WasmTranslation { + const m = parseWasmModule(bytes); + for (const t of m.tables) llType(t.elemType); + const mt = new ModuleTranslator(m, wasmSymbolPrefix(sha256), opts); + mt.translate(); + const descriptor = mt.descriptor(sha256); + const decls = RUNTIME_DECLS.slice(); + // Initial-exec: executables and their static runtime define it, so the + // check is one thread-pointer-relative load, not a TLS lookup call. + if (opts.boundsChecks) + decls.push("@scr_wasm_stack_limit = external thread_local(initialexec) global i64"); + return { decls, text: mt.text, descriptor }; +} diff --git a/packages/compiler/surface-manifest.json b/packages/compiler/surface-manifest.json index b2eeaecc0..b7cb3ab94 100644 --- a/packages/compiler/surface-manifest.json +++ b/packages/compiler/surface-manifest.json @@ -1867,6 +1867,13 @@ "status": "static", "note": "recognized module (bare and node:-prefixed specifiers)" }, + { + "id": "node-builtin.perf_hooks.monitorEventLoopDelay", + "kind": "node-builtin", + "name": "perf_hooks.monitorEventLoopDelay", + "status": "static", + "note": "an unref'd sampling interval records the delay histogram; enable, disable, reset, percentile and the min, max, mean, stddev, count and exceeds readings are supported" + }, { "id": "node-builtin.perf_hooks.performance.clearMarks", "kind": "node-builtin", @@ -1879,6 +1886,13 @@ "name": "perf_hooks.performance.clearMeasures", "status": "static" }, + { + "id": "node-builtin.perf_hooks.performance.eventLoopUtilization", + "kind": "node-builtin", + "name": "perf_hooks.performance.eventLoopUtilization", + "status": "static", + "note": "active time is the main thread's CPU time since the loop started; the one- and two-argument difference forms are supported" + }, { "id": "node-builtin.perf_hooks.performance.getEntries", "kind": "node-builtin", @@ -5699,9 +5713,8 @@ "id": "stdlib.webassembly", "kind": "stdlib", "name": "globalThis.WebAssembly", - "status": "unsupported", - "code": "SC2020", - "note": "WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations)" + "status": "static", + "note": "compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, instanceof, the error classes, exports, imports and Module transfer to workers, over the modules translated at build time; the rest refuses with SC2020 (the streaming functions, Tag and Exception, and the classes used as values other than with new and instanceof are planned; 'scriptc coverage' lists the modules this program loads (https://scriptc.dev/limitations))" }, { "id": "stdlib.webcrypto.CryptoKey", diff --git a/packages/compiler/test/native-callable-values.test.ts b/packages/compiler/test/native-callable-values.test.ts index e64a9319e..6e65b0c99 100644 --- a/packages/compiler/test/native-callable-values.test.ts +++ b/packages/compiler/test/native-callable-values.test.ts @@ -102,19 +102,19 @@ test.each(["llvm"] as const)( writeFileSync( join(pkg, "index.js"), ` -const inspect = (value) => eval(value); +const inspect = (value) => process.on("__proto__", value); function stopped(value) { - eval(value); + process.on("__proto__", value); return { done() { return "wrong"; } }; } -try { console.log(stopped("0").done()); } -catch (error) { console.log(String(error).includes("SC2009")); } +try { console.log(stopped(() => {}).done()); } +catch (error) { console.log(String(error).includes("SC2020")); } const first = { inspect }; const second = { inspect }; console.log(typeof first.inspect, first.inspect === second.inspect); for (const callback of [first.inspect, second.inspect]) { - try { callback({}); } - catch (error) { console.log(String(error).includes("SC2009")); } + try { callback(() => {}); } + catch (error) { console.log(String(error).includes("SC2020")); } } `, ); diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5817-constructor-function-instanceof.cjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5817-constructor-function-instanceof.cjs.json new file mode 100644 index 000000000..d9ad97beb --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5817-constructor-function-instanceof.cjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5817-constructor-function-instanceof.cjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5818-constructor-function-emitter-defaults.cjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5818-constructor-function-emitter-defaults.cjs.json new file mode 100644 index 000000000..f22e1aaeb --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5818-constructor-function-emitter-defaults.cjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5818-constructor-function-emitter-defaults.cjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6126-punycode-dependency/main.cjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6126-punycode-dependency/main.cjs.json index 5de83361a..36f02246c 100644 --- a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6126-punycode-dependency/main.cjs.json +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6126-punycode-dependency/main.cjs.json @@ -12,7 +12,7 @@ "end": 376 }, "milestone": "M4", - "hint": "relative imports (./file, ../dir/file), package.json-mediated project imports (#alias via the imports field, self-name references via exports), statically compiled npm packages, and the built-in fs, fs/promises, path, os, url, crypto, zlib, child_process, net, http, tls, https, http2, dgram, dns, util, util/types, string_decoder, querystring, readline, events, stream, stream/promises, stream/consumers, buffer, assert, assert/strict, worker_threads, cluster, tty, async_hooks, timers, timers/promises, diagnostics_channel, perf_hooks, module, and console modules (bare or node:-prefixed) and node:test (node:-prefixed only, like in Node) are supported" + "hint": "relative imports (./file, ../dir/file), package.json-mediated project imports (#alias via the imports field, self-name references via exports), statically compiled npm packages, and the built-in fs, fs/promises, path, os, url, crypto, zlib, child_process, net, http, tls, https, http2, dgram, dns, dns/promises, util, util/types, string_decoder, querystring, readline, events, stream, stream/promises, stream/consumers, stream/web, buffer, assert, assert/strict, worker_threads, cluster, tty, async_hooks, timers, timers/promises, diagnostics_channel, perf_hooks, module, v8, and console modules (bare or node:-prefixed) and node:test (node:-prefixed only, like in Node) are supported" } ] } diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6380-variadic-wrapper-arguments-apply.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6380-variadic-wrapper-arguments-apply.ts.json new file mode 100644 index 000000000..df0124219 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6380-variadic-wrapper-arguments-apply.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6380-variadic-wrapper-arguments-apply.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6381-variadic-wrapper-async.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6381-variadic-wrapper-async.ts.json new file mode 100644 index 000000000..2138df43d --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6381-variadic-wrapper-async.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6381-variadic-wrapper-async.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6382-variadic-wrapper-methods-this.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6382-variadic-wrapper-methods-this.ts.json new file mode 100644 index 000000000..2135f8b6f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6382-variadic-wrapper-methods-this.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6382-variadic-wrapper-methods-this.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6383-variadic-wrapper-rest-tuple.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6383-variadic-wrapper-rest-tuple.ts.json new file mode 100644 index 000000000..a2f7f32c4 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6383-variadic-wrapper-rest-tuple.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6383-variadic-wrapper-rest-tuple.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6384-variadic-wrapper-nested.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6384-variadic-wrapper-nested.ts.json new file mode 100644 index 000000000..d69618e3a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6384-variadic-wrapper-nested.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6384-variadic-wrapper-nested.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6385-variadic-wrapper-shared-local-names.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6385-variadic-wrapper-shared-local-names.ts.json new file mode 100644 index 000000000..5791565f2 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6385-variadic-wrapper-shared-local-names.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6385-variadic-wrapper-shared-local-names.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6390-catch-binding-predicate.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6390-catch-binding-predicate.ts.json new file mode 100644 index 000000000..fcfb2852f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6390-catch-binding-predicate.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6390-catch-binding-predicate.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6391-nullish-function-default.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6391-nullish-function-default.ts.json new file mode 100644 index 000000000..8200d301e --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6391-nullish-function-default.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6391-nullish-function-default.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6392-optional-chain-protocol-calls.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6392-optional-chain-protocol-calls.ts.json new file mode 100644 index 000000000..f2343714c --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6392-optional-chain-protocol-calls.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6392-optional-chain-protocol-calls.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6393-function-types-any-params.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6393-function-types-any-params.ts.json new file mode 100644 index 000000000..af0a9abe7 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6393-function-types-any-params.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6393-function-types-any-params.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6394-in-key-error-subclasses.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6394-in-key-error-subclasses.ts.json new file mode 100644 index 000000000..9df1e1014 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6394-in-key-error-subclasses.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6394-in-key-error-subclasses.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6395-generic-object-entries.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6395-generic-object-entries.ts.json new file mode 100644 index 000000000..879a09388 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6395-generic-object-entries.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6395-generic-object-entries.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6396-generic-any-instantiation.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6396-generic-any-instantiation.ts.json new file mode 100644 index 000000000..da41452ad --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6396-generic-any-instantiation.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6396-generic-any-instantiation.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6397-event-loop-metrics.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6397-event-loop-metrics.ts.json new file mode 100644 index 000000000..0a74534b0 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6397-event-loop-metrics.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6397-event-loop-metrics.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6398-conditional-fixed-arity.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6398-conditional-fixed-arity.ts.json new file mode 100644 index 000000000..878f45b09 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6398-conditional-fixed-arity.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6398-conditional-fixed-arity.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6400-override-any-base.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6400-override-any-base.ts.json new file mode 100644 index 000000000..a885a5175 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6400-override-any-base.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6400-override-any-base.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6401-override-param-variance.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6401-override-param-variance.ts.json new file mode 100644 index 000000000..ee14b5af3 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6401-override-param-variance.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6401-override-param-variance.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6402-override-js-base/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6402-override-js-base/main.ts.json new file mode 100644 index 000000000..3ac1bf1fe --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6402-override-js-base/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6402-override-js-base/pool.js", + "/tests/corpus/6402-override-js-base/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6403-error-code-write.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6403-error-code-write.ts.json new file mode 100644 index 000000000..b673f7920 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6403-error-code-write.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6403-error-code-write.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6404-error-in-and-assign.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6404-error-in-and-assign.ts.json new file mode 100644 index 000000000..c880bc57b --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6404-error-in-and-assign.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6404-error-in-and-assign.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6405-wrapped-default-parameters.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6405-wrapped-default-parameters.ts.json new file mode 100644 index 000000000..8be83f858 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6405-wrapped-default-parameters.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6405-wrapped-default-parameters.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6406-npm-instance-receiver/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6406-npm-instance-receiver/main.ts.json new file mode 100644 index 000000000..e651808f7 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6406-npm-instance-receiver/main.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6406-npm-instance-receiver/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6409-catch-binding-shapes.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6409-catch-binding-shapes.ts.json new file mode 100644 index 000000000..57e3aeaf1 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6409-catch-binding-shapes.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6409-catch-binding-shapes.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-json-mixed-scalar-tables/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-json-mixed-scalar-tables/main.ts.json new file mode 100644 index 000000000..c7ec1ab56 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-json-mixed-scalar-tables/main.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6410-json-mixed-scalar-tables/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-wrapper-untyped-results.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-wrapper-untyped-results.ts.json new file mode 100644 index 000000000..20c1be33a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6410-wrapper-untyped-results.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6410-wrapper-untyped-results.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-prototype-reset-constructors/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-prototype-reset-constructors/main.ts.json new file mode 100644 index 000000000..adfb3989d --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-prototype-reset-constructors/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6411-prototype-reset-constructors/issues.js", + "/tests/corpus/6411-prototype-reset-constructors/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-union-array-tuple-destructuring.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-union-array-tuple-destructuring.ts.json new file mode 100644 index 000000000..94d8b78e7 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6411-union-array-tuple-destructuring.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6411-union-array-tuple-destructuring.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6412-js-error-tostring-override/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6412-js-error-tostring-override/main.ts.json new file mode 100644 index 000000000..145c02428 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6412-js-error-tostring-override/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6412-js-error-tostring-override/errors.js", + "/tests/corpus/6412-js-error-tostring-override/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6413-override-js-async-base/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6413-override-js-async-base/main.ts.json new file mode 100644 index 000000000..de5fe5afb --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6413-override-js-async-base/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6413-override-js-async-base/lock.js", + "/tests/corpus/6413-override-js-async-base/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6414-catch-values-roundtrip.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6414-catch-values-roundtrip.ts.json new file mode 100644 index 000000000..797bd8ca2 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6414-catch-values-roundtrip.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6414-catch-values-roundtrip.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6415-error-code-dynamic-writes.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6415-error-code-dynamic-writes.ts.json new file mode 100644 index 000000000..6500a5b3b --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6415-error-code-dynamic-writes.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6415-error-code-dynamic-writes.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6453-constructor-function-emitter.cjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6453-constructor-function-emitter.cjs.json new file mode 100644 index 000000000..ae5c0050e --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6453-constructor-function-emitter.cjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6453-constructor-function-emitter.cjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6454-constructor-function-stream-bases.cjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6454-constructor-function-stream-bases.cjs.json new file mode 100644 index 000000000..bc48a7f35 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6454-constructor-function-stream-bases.cjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6454-constructor-function-stream-bases.cjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6463-node-readable-stream-producers.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6463-node-readable-stream-producers.ts.json new file mode 100644 index 000000000..e413951ae --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6463-node-readable-stream-producers.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6463-node-readable-stream-producers.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6464-node-writable-stream-producers.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6464-node-writable-stream-producers.ts.json new file mode 100644 index 000000000..fd805a2af --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6464-node-writable-stream-producers.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6464-node-writable-stream-producers.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-node-stream-js-boundary/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-node-stream-js-boundary/main.ts.json new file mode 100644 index 000000000..95278eab8 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-node-stream-js-boundary/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6465-node-stream-js-boundary/consume.js", + "/tests/corpus/6465-node-stream-js-boundary/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-optional-members-over-index-signature.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-optional-members-over-index-signature.ts.json new file mode 100644 index 000000000..91a157207 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6465-optional-members-over-index-signature.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6465-optional-members-over-index-signature.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-never-assertion-argument.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-never-assertion-argument.ts.json new file mode 100644 index 000000000..17f25aa22 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-never-assertion-argument.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6466-never-assertion-argument.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-node-stdio-stream-surface.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-node-stdio-stream-surface.ts.json new file mode 100644 index 000000000..8ebcddd22 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6466-node-stdio-stream-surface.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6466-node-stdio-stream-surface.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-fromentries-record-assertion.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-fromentries-record-assertion.ts.json new file mode 100644 index 000000000..21ca66953 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-fromentries-record-assertion.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6467-fromentries-record-assertion.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-node-stream-untyped-sources/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-node-stream-untyped-sources/main.ts.json new file mode 100644 index 000000000..dc843c047 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6467-node-stream-untyped-sources/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6467-node-stream-untyped-sources/sources.js", + "/tests/corpus/6467-node-stream-untyped-sources/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-generic-unknown-record-entries.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-generic-unknown-record-entries.ts.json new file mode 100644 index 000000000..0b4118c70 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-generic-unknown-record-entries.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6468-generic-unknown-record-entries.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-node-stdio-writable-slot.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-node-stdio-writable-slot.ts.json new file mode 100644 index 000000000..baf428dee --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6468-node-stdio-writable-slot.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6468-node-stdio-writable-slot.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts.json new file mode 100644 index 000000000..60b1360b0 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6469-node-stdio-writable-js-pipe/pipe.js", + "/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6470-stream-transform-any-data-callback.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6470-stream-transform-any-data-callback.ts.json new file mode 100644 index 000000000..3d4a39486 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6470-stream-transform-any-data-callback.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6470-stream-transform-any-data-callback.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6471-stream-data-buffer-or-string.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6471-stream-data-buffer-or-string.ts.json new file mode 100644 index 000000000..e8ff1e084 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6471-stream-data-buffer-or-string.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6471-stream-data-buffer-or-string.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6472-child-data-unknown-chunk.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6472-child-data-unknown-chunk.ts.json new file mode 100644 index 000000000..3c7183bb6 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6472-child-data-unknown-chunk.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6472-child-data-unknown-chunk.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6490-literal-key-field-updates.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6490-literal-key-field-updates.ts.json new file mode 100644 index 000000000..1e4e1e939 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6490-literal-key-field-updates.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6490-literal-key-field-updates.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6491-index-record-updates.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6491-index-record-updates.ts.json new file mode 100644 index 000000000..babda8c3c --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6491-index-record-updates.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6491-index-record-updates.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-api.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-api.mjs.json new file mode 100644 index 000000000..f3e1a711b --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-api.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-api.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-dylink/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-dylink/main.mjs.json new file mode 100644 index 000000000..14b064864 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-dylink/main.mjs.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/webassembly-dylink/extensions.js", + "/tests/corpus/webassembly-dylink/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-externref-lifetimes.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-externref-lifetimes.mjs.json new file mode 100644 index 000000000..7d264b2eb --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-externref-lifetimes.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-externref-lifetimes.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-jsapi.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-jsapi.mjs.json new file mode 100644 index 000000000..4f8ee17cf --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-jsapi.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-jsapi.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-lifetimes.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-lifetimes.mjs.json new file mode 100644 index 000000000..c9ab8d500 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-lifetimes.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-lifetimes.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-control/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-control/main.mjs.json new file mode 100644 index 000000000..58a263265 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-control/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-control/data.mjs", + "/tests/corpus/webassembly-spec-control/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-float/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-float/main.mjs.json new file mode 100644 index 000000000..e871d3b1d --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-float/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-float/data.mjs", + "/tests/corpus/webassembly-spec-float/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-imports/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-imports/main.mjs.json new file mode 100644 index 000000000..a23646c06 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-imports/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-imports/data.mjs", + "/tests/corpus/webassembly-spec-imports/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-int/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-int/main.mjs.json new file mode 100644 index 000000000..d19226a63 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-int/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-int/data.mjs", + "/tests/corpus/webassembly-spec-int/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-memory/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-memory/main.mjs.json new file mode 100644 index 000000000..4510ade3a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-memory/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-memory/data.mjs", + "/tests/corpus/webassembly-spec-memory/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-table/main.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-table/main.mjs.json new file mode 100644 index 000000000..50409b1d0 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-spec-table/main.mjs.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/wasm-spec/runner.mjs", + "/tests/corpus/webassembly-spec-table/data.mjs", + "/tests/corpus/webassembly-spec-table/main.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-typed.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-typed.ts.json new file mode 100644 index 000000000..7a3adb475 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-typed.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-typed.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-worker.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-worker.ts.json new file mode 100644 index 000000000..2b4ffd4ba --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-worker.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-worker.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-wpt-jsapi.mjs.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-wpt-jsapi.mjs.json new file mode 100644 index 000000000..dd80857d8 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-wpt-jsapi.mjs.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-wpt-jsapi.mjs" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/fromentries-aliased-entries.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/fromentries-aliased-entries.ts.json new file mode 100644 index 000000000..7388f2b71 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/fromentries-aliased-entries.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/diagnostics/fromentries-aliased-entries.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/util-inherits-runtime-class.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/util-inherits-runtime-class.ts.json deleted file mode 100644 index 5dfbdc324..000000000 --- a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/util-inherits-runtime-class.ts.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "order": [ - "/tests/diagnostics/util-inherits-runtime-class.ts" - ], - "diags": [] -} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/variadic-wrapper-fences.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/variadic-wrapper-fences.ts.json new file mode 100644 index 000000000..c3e44b2e5 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/variadic-wrapper-fences.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/diagnostics/variadic-wrapper-fences.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-fences.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-fences.ts.json deleted file mode 100644 index cfa602a2e..000000000 --- a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-fences.ts.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "order": [ - "/tests/fixtures/node-types/child-stdin-fences.ts" - ], - "diags": [] -} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-streams.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-streams.ts.json new file mode 100644 index 000000000..2bb443d2a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/child-stdin-streams.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/fixtures/node-types/child-stdin-streams.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/event-loop-metrics.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/event-loop-metrics.ts.json new file mode 100644 index 000000000..66246403d --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/event-loop-metrics.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/fixtures/node-types/event-loop-metrics.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/node-stream-interfaces.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/node-stream-interfaces.ts.json new file mode 100644 index 000000000..cfb5c1a10 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/node-stream-interfaces.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/fixtures/node-types/node-stream-interfaces.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/stream-construction.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/stream-construction.ts.json new file mode 100644 index 000000000..35dc0be0d --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/stream-construction.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/fixtures/node-types/stream-construction.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/timeout-type.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/timeout-type.ts.json new file mode 100644 index 000000000..46f0b6e38 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/fixtures/node-types/timeout-type.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/fixtures/node-types/timeout-type.ts" + ], + "diags": [] +} diff --git a/packages/runtime-pack-common/runtime-pack-matrix.mjs b/packages/runtime-pack-common/runtime-pack-matrix.mjs index 36ffaaf0f..28ccf0f59 100644 --- a/packages/runtime-pack-common/runtime-pack-matrix.mjs +++ b/packages/runtime-pack-common/runtime-pack-matrix.mjs @@ -69,6 +69,8 @@ export const OPTIONAL_RUNTIME_SOURCES = [ ["scr_async_dyn.c", any("dynAsync", "dynInvoke", "dc", "fileHandle", "nativeFetch")], // The performance timeline emits its buffer warning through scr_async_dyn.c. ["scr_perf.c", "dynAsync"], + // perf_hooks event-loop metrics, only for programs that read them. + ["scr_perf_loop.c", "perfLoop"], // Blob and File box their reads as dyn promises through scr_async_dyn.c. ["scr_blob.c", "dynAsync"], ["scr_zlib.c", "zlib"], @@ -88,6 +90,10 @@ export const OPTIONAL_RUNTIME_SOURCES = [ ["scr_util_compare.c", all("parseArgs", "symbol")], ["scr_util_style.c", all("parseArgs", "inspect", "dynAsync")], ["scr_util_callable.c", all("parseArgs", "inspect", "dynAsync", "dynInvoke", "regex")], + // Untyped EventEmitter and stream constructor values call listeners + // through the dyn-invoke unit, inspect unhandled 'error' payloads and + // create EventEmitter's private symbols. + ["scr_dyn_builtin_class.c", all("dynBuiltinClass", "inspect", "dynInvoke", "symbol", "emitter")], ["scr_stream.c", "stream"], // The zlib stream classes reference both the zlib engine and the stream unit. ["scr_zlib_stream.c", all("zlib", "stream")], @@ -112,6 +118,7 @@ export const OPTIONAL_RUNTIME_SOURCES = [ ["scr_tls_ca.c", "tlsCaEffective"], ["scr_tls.c", "tlsEffective"], ["scr_cipher.c", "cipher"], + ["scr_wasm.c", "wasm"], ["scr_webcrypto.c", "webcrypto"], ["scr_fetch.c", "nativeFetch"], ]; diff --git a/packages/runtime-wasm32-wasi/scripts/build.mjs b/packages/runtime-wasm32-wasi/scripts/build.mjs index a5a30dae0..64d28f15f 100644 --- a/packages/runtime-wasm32-wasi/scripts/build.mjs +++ b/packages/runtime-wasm32-wasi/scripts/build.mjs @@ -21,6 +21,7 @@ process.env.SCRIPTC_RUNTIME_PACK_CONFIG = JSON.stringify({ "scr_tls_ca.c", "scr_tls.c", "scr_cipher.c", + "scr_wasm.c", "scr_fetch.c", ], omitArchives: ["mbedtls"], diff --git a/packages/runtime/src/scr_async.c b/packages/runtime/src/scr_async.c index 8185422af..ef91de6fb 100644 --- a/packages/runtime/src/scr_async.c +++ b/packages/runtime/src/scr_async.c @@ -70,14 +70,6 @@ void __lsan_unregister_root_region(const void *p, size_t size) __attribute__((we #endif #endif -#ifdef SCR_ASAN_FIBERS -#define SCR_FIBER_STACK (8 * 1024 * 1024) -#else -/* Deep enough for ordinary recursion inside async bodies and generators - * once the overflow guard's reserve is taken off; idle and shallow fibers - * only touch the pages they use. */ -#define SCR_FIBER_STACK (512 * 1024) -#endif #if !defined(_WIN32) && !defined(__wasi__) /* Keep stacks out of malloc's size classes. Reuse a bounded number during diff --git a/packages/runtime/src/scr_async.h b/packages/runtime/src/scr_async.h index 6f56758ce..041d2ea03 100644 --- a/packages/runtime/src/scr_async.h +++ b/packages/runtime/src/scr_async.h @@ -29,6 +29,20 @@ void *scr_promise_retain_v(void *p); void scr_promise_release_v(void *p); typedef struct ScrFiber ScrFiber; +/* Bytes of each async fiber's native stack (scr_async.c), mapped without a + * guard page: compiled code checks scr_stack_guard instead, which sits + * scr_stack_guard_for's reserve above the mapping's start. Deep enough for + * ordinary recursion inside async bodies and generators once that reserve + * is taken off; idle and shallow fibers only touch the pages they use. + * AddressSanitizer's larger frames get more. */ +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define SCR_FIBER_STACK (8 * 1024 * 1024) +#endif +#endif +#ifndef SCR_FIBER_STACK +#define SCR_FIBER_STACK (512 * 1024) +#endif /* Spawn + run eagerly to the first suspension; returns the promise, +1. */ ScrPromise *scr_async_spawn(void (*entry)(ScrFiber *, void *), void *argpack); /* `await f(...)` of a fiber-backed async f: spawn and await in one call, diff --git a/packages/runtime/src/scr_dyn.h b/packages/runtime/src/scr_dyn.h index fb1bc1548..28d642501 100644 --- a/packages/runtime/src/scr_dyn.h +++ b/packages/runtime/src/scr_dyn.h @@ -191,6 +191,11 @@ typedef enum { X(SHARED_ARRAY_BUFFER, 37) \ X(STDIO, 27) /* stable process stdin/stdout/stderr values */ \ X(URL, 28) /* native WHATWG URL */ \ + X(WASM_GLOBAL, 61) /* WebAssembly.Global */ \ + X(WASM_INSTANCE, 58) /* WebAssembly.Instance */ \ + X(WASM_MEMORY, 59) /* WebAssembly.Memory */ \ + X(WASM_MODULE, 57) /* WebAssembly.Module (scr_wasm.c) */ \ + X(WASM_TABLE, 60) /* WebAssembly.Table */ \ X(WEAK_MAP, 23) /* native weak-key metadata */ \ X(WEAK_SET, 24) /* native weak membership */ \ X(WEB_CONTROLLER, 11) /* native ReadableStreamDefaultController */ \ @@ -1148,6 +1153,12 @@ ScrDyn *scr_dyn_define_prototype_props(ScrDyn *target, ScrDyn *descs, ScrDyn *pr * must be static literals (the box never frees them; name may be NULL). */ ScrDyn *scr_dyn_new_func(ScrClosure *clo, ScrDynThunk thunk, uint32_t arity, const char *sig, const char *name); ScrDyn *scr_dyn_new_class(ScrClassObj *cls, const char *type_key); +/* EventEmitter and the stream constructors as untyped constructor values, + * and instanceof over untyped constructor functions + * (scr_dyn_builtin_class.c, linked with the dynBuiltinClass feature). */ +ScrDyn *scr_dyn_builtin_class(double kind); +bool scr_dyn_builtin_instanceof(ScrDyn *value, double kind); +bool scr_dyn_function_instanceof(ScrDyn *value, ScrDyn *callee); bool scr_dyn_class_is_key(const ScrDyn *value, const ScrStr *type_key); bool scr_dyn_class_is(const ScrDyn *value, const char *type_key); /* Calls a dyn value: a non-function kind throws the catchable TypeError @@ -1281,7 +1292,8 @@ typedef struct ScrDynHandleOps { * inspector returns `this`) instead of the bare class name. */ bool inspect_bracketed_past_depth; /* The @@toStringTag when it differs from cls: String() answers - * "[object ]" and util.inspect prints ` [] `. */ + * "[object ]" and util.inspect prints ` [] `, or + * ` ` when the tag ends with "." and cls, as Node does. */ const char *to_string_tag; /* The view has no properties, so util.inspect prints it in full at any * depth, as Node prints `{}`. */ diff --git a/packages/runtime/src/scr_dyn_builtin_class.c b/packages/runtime/src/scr_dyn_builtin_class.c new file mode 100644 index 000000000..6d894615b --- /dev/null +++ b/packages/runtime/src/scr_dyn_builtin_class.c @@ -0,0 +1,1510 @@ +/* EventEmitter and the node:stream constructors as checked-dynamic + * constructor values. JavaScript constructor functions inherit from them + * the pre-class way: + * + * function Bus() { EventEmitter.call(this); } + * util.inherits(Bus, EventEmitter); + * + * A compiled EventEmitter instance keeps its listeners in native state, but + * the receiver here is an ordinary dyn object built by `new Bus()`. So the + * EventEmitter value is a native function whose prototype carries Node's + * lib/events.js methods over that object's own `_events`, `_eventsCount` + * and `_maxListeners` properties, the state Node's own implementation + * keeps there. Calling it with a receiver runs EventEmitter.init. + * + * Stream is Node's legacy constructor: EventEmitter.call(this, opts) and a + * prototype that inherits EventEmitter's. Readable, Writable, Duplex, + * Transform and PassThrough have prototypes chained as in Node, so + * util.inherits onto them and instanceof work, but their native state has + * no dyn object form: calling one with a receiver throws the "not + * supported yet" Error where the construction runs. + * + * One constructor per kind and thread, so every boxing of the same class + * value is the same function. All arguments are borrowed. */ +#include "scr_runtime.h" + +#include +#include +#include + +#ifdef _WIN32 +#include +#define BC_PID() ((long)_getpid()) +#else +#include +#define BC_PID() ((long)getpid()) +#endif + +enum { + BC_EMITTER, + BC_STREAM, + BC_READABLE, + BC_WRITABLE, + BC_DUPLEX, + BC_TRANSFORM, + BC_PASSTHROUGH, + BC_COUNT +}; + +static const char *const bc_names[BC_COUNT] = { + "EventEmitter", "Stream", "Readable", "Writable", "Duplex", "Transform", "PassThrough", +}; + +static SCR_TL ScrDyn *bc_ctors[BC_COUNT]; +static SCR_TL bool bc_teardown_registered; +/* Node's private kShapeMode and kCapture symbols, which util.inspect shows + * on every emitter as Symbol(shapeMode) and Symbol(kCapture). */ +enum { BC_SHAPE_MODE, BC_CAPTURE, BC_SYMBOLS }; +static SCR_TL ScrDyn *bc_symbols[BC_SYMBOLS]; + +static ScrDyn *bc_class(int kind); + +/* ── property helpers ───────────────────────────────────────────────── */ + +static ScrDyn *bc_key(const char *name) { + ScrStr *text = scr_str_new(name, strlen(name)); + ScrDyn *key = scr_dyn_new_str(text); + scr_str_release(text); + return key; +} + +/* object[key] with object as the receiver: +1, or NULL with an exception + * pending. */ +static ScrDyn *bc_get_key(ScrDyn *object, ScrDyn *key) { + ScrDyn *value = scr_dyn_reflect_get(object, key, object); + if (!value && !scr_exc_pending()) value = scr_dyn_retain(scr_dyn_undefined()); + return value; +} + +static ScrDyn *bc_get(ScrDyn *object, const char *name) { + ScrDyn *key = bc_key(name); + ScrDyn *value = bc_get_key(object, key); + scr_dyn_release(key); + return value; +} + +/* object[key] = value; the value moves in. False with an exception + * pending. */ +static bool bc_set_key(ScrDyn *object, ScrDyn *key, ScrDyn *value) { + scr_dyn_key_set_computed(object, key, value); + scr_dyn_release(value); + return !scr_exc_pending(); +} + +static bool bc_set(ScrDyn *object, const char *name, ScrDyn *value) { + ScrDyn *key = bc_key(name); + bool ok = bc_set_key(object, key, value); + scr_dyn_release(key); + return ok; +} + +static bool bc_undefined(const ScrDyn *value) { + return value->kind == SCR_DYN_UNDEF; +} + +static double bc_number(const ScrDyn *value) { + return value->kind == SCR_DYN_NUM ? value->v.num : 0; +} + +/* receiver.method(...args), dispatched through the receiver's own lookup + * like Node's `this.emit(...)`. +1 or NULL. */ +static ScrDyn *bc_invoke(ScrDyn *receiver, const char *method, ScrDyn *const *args, size_t argc) { + ScrDyn *fn = bc_get(receiver, method); + if (!fn) return NULL; + scr_dyn_this_push_dyn(receiver); + ScrDyn *result = scr_dyn_call(fn, args, argc, method); + scr_dyn_this_pop(); + scr_dyn_release(fn); + return result; +} + +static ScrDyn *bc_apply(ScrDyn *fn, ScrDyn *receiver, ScrDyn *const *args, size_t argc) { + scr_dyn_this_push_dyn(receiver); + ScrDyn *result = scr_dyn_call(fn, args, argc, "listener"); + scr_dyn_this_pop(); + return result; +} + +/* Listener lists are replaced rather than mutated: a fresh array with item + * first, or without the item at index. Node mutates its array in place, + * which nothing outside the emitter observes (emit iterates a copy and + * listeners() answers one). A leak warning already given stays given. */ +static ScrDyn *bc_list_copy(ScrDyn *list, ScrDyn *first, double skip) { + ScrDyn *copy = scr_dyn_new_arr(); + if (first) scr_dyn_arr_push(copy, scr_dyn_retain(first)); + double length = scr_dyn_arr_len(list); + for (double i = 0; i < length; i++) { + if (i == skip) continue; + ScrDyn *item = scr_dyn_index_get(list, i); + if (!item) { + scr_dyn_release(copy); + return NULL; + } + scr_dyn_arr_push(copy, item); + } + ScrDyn *warned = bc_get(list, "warned"); + if (!warned || (scr_dyn_truthy(warned) && !bc_set(copy, "warned", scr_dyn_new_bool(true)))) { + if (warned) scr_dyn_release(warned); + scr_dyn_release(copy); + return NULL; + } + scr_dyn_release(warned); + return copy; +} + +static ScrDyn *bc_unused_args[1]; + +static ScrDyn *bc_arg(ScrDyn *const *args, size_t argc, size_t index) { + return index < argc ? args[index] : scr_dyn_undefined(); +} + +/* The receiver of a prototype method call, +1. Methods called without one + * (an extracted `emitter.on`) read `this` as undefined, as in strict code. */ +static ScrDyn *bc_this(void) { + return scr_dyn_this_get(); +} + +static bool bc_require_object(ScrDyn *self, const char *reading) { + if (self->kind != SCR_DYN_UNDEF && self->kind != SCR_DYN_NULL) return true; + char message[96]; + snprintf(message, sizeof message, "Cannot read properties of %s (reading '%s')", + self->kind == SCR_DYN_NULL ? "null" : "undefined", reading); + scr_throw_error_msg(SCR_ERR_TYPE, message, strlen(message)); + return false; +} + +static bool bc_check_listener(const ScrDyn *listener) { + if (scr_dyn_is_callable(listener)) return true; + scr_dyn_arg_type_fail("listener", "of type function", listener); + return false; +} + +static void bc_teardown(void); + +static ScrDyn *bc_symbol(int which) { + if (!bc_symbols[which]) { + if (!bc_teardown_registered) { + bc_teardown_registered = true; + scr_atexit(bc_teardown); + } + const char *name = which == BC_SHAPE_MODE ? "shapeMode" : "kCapture"; + ScrStr *description = scr_str_new(name, strlen(name)); + ScrSym *symbol = scr_sym_new(description); + scr_str_release(description); + bc_symbols[which] = scr_dyn_new_symbol(symbol); + scr_sym_release(symbol); + } + return bc_symbols[which]; +} + +/* ── EventEmitter.init ──────────────────────────────────────────────── */ + +/* `_events` is fresh unless the receiver already has its own (Node's + * shapeMode, a subclass that pre-populates it); `_maxListeners` keeps a + * value set before the call. */ +static bool bc_emitter_init(ScrDyn *self, ScrDyn *opts) { + if (!bc_require_object(self, "_events")) return false; + ScrDyn *events = bc_get(self, "_events"); + if (!events) return false; + bool fresh = bc_undefined(events); + if (!fresh) { + ScrDyn *proto = scr_dyn_get_prototype(self); + if (!proto) { + scr_dyn_release(events); + return false; + } + if (proto->kind != SCR_DYN_NULL) { + ScrDyn *inherited = bc_get(proto, "_events"); + if (!inherited) { + scr_dyn_release(proto); + scr_dyn_release(events); + return false; + } + fresh = scr_dyn_strict_eq(events, inherited); + scr_dyn_release(inherited); + } + scr_dyn_release(proto); + } + scr_dyn_release(events); + if (fresh) { + if (!bc_set(self, "_events", scr_dyn_new_obj_null_proto())) return false; + if (!bc_set(self, "_eventsCount", scr_dyn_new_num(0))) return false; + } + if (!bc_set_key(self, bc_symbol(BC_SHAPE_MODE), scr_dyn_new_bool(!fresh))) return false; + ScrDyn *max = bc_get(self, "_maxListeners"); + if (!max) return false; + bool keep = scr_dyn_truthy(max); + if (!bc_set(self, "_maxListeners", keep ? max : (scr_dyn_release(max), scr_dyn_retain(scr_dyn_undefined())))) + return false; + if (opts->kind != SCR_DYN_UNDEF && opts->kind != SCR_DYN_NULL) { + ScrDyn *capture = bc_get(opts, "captureRejections"); + if (!capture) return false; + bool requested = !bc_undefined(capture); + if (requested && capture->kind != SCR_DYN_BOOL) { + scr_dyn_arg_type_fail("options.captureRejections", "of type boolean", capture); + scr_dyn_release(capture); + return false; + } + bool enabled = requested && capture->v.b; + scr_dyn_release(capture); + if (enabled) { + static const char message[] = "EventEmitter captureRejections on a constructor function is not supported yet"; + scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020"); + return false; + } + } + return bc_set_key(self, bc_symbol(BC_CAPTURE), scr_dyn_new_bool(false)); +} + +/* ── listener bookkeeping (lib/events.js) ───────────────────────────── */ + +static double bc_max_listeners(ScrDyn *self) { + ScrDyn *max = bc_get(self, "_maxListeners"); + if (!max) return -1; + double value; + if (bc_undefined(max)) { + value = scr_emitter_get_default_max(); + } else { + value = bc_number(max); + } + scr_dyn_release(max); + return value; +} + +static void bc_warn_tick(ScrClosure *self) { + ScrStr *message = (ScrStr *)scr_box_get_ref(self->caps[0]); + if (scr_warning_emit_hook) { + scr_warning_emit_hook("MaxListenersExceededWarning", NULL, message); + } else { + fflush(stdout); + fprintf(stderr, "(node:%ld) MaxListenersExceededWarning: %.*s\n", BC_PID(), + (int)message->len, message->data); + if (!scr_warning_trace_hint_shown) { + scr_warning_trace_hint_shown = true; + fputs("(Use `node --trace-warnings ...` to show where the warning was created)\n", stderr); + } + } + scr_str_release(message); +} + +/* The constructor name util.inspect prints at depth -1: `[Bus]`. */ +static ScrStr *bc_constructor_name(ScrDyn *self) { + ScrDyn *ctor = bc_get(self, "constructor"); + ScrStr *name = NULL; + if (ctor && scr_dyn_is_callable(ctor)) { + ScrDyn *text = bc_get(ctor, "name"); + if (text && text->kind == SCR_DYN_STR && text->v.str->len) name = scr_str_retain(text->v.str); + if (text) scr_dyn_release(text); + } + if (ctor) scr_dyn_release(ctor); + if (scr_exc_pending()) scr_exc_clear(); + return name ? name : scr_str_new("Object", 6); +} + +static void bc_warn_leak(ScrDyn *self, ScrDyn *type, double count, double max) { + char counted[32], limit[32]; + snprintf(counted, sizeof counted, "%g", count); + snprintf(limit, sizeof limit, "%g", max); + ScrStr *event = scr_dyn_string_coerce_js(type); + if (!event) { + scr_exc_clear(); + event = scr_str_new("", 0); + } + ScrStr *cls = bc_constructor_name(self); + ScrJsonBuf text; + scr_jb_init(&text); + scr_jb_puts(&text, "Possible EventEmitter memory leak detected. "); + scr_jb_puts(&text, counted); + scr_jb_putc(&text, ' '); + scr_jb_put_str(&text, event); + scr_jb_puts(&text, " listeners added to ["); + scr_jb_put_str(&text, cls); + scr_jb_puts(&text, "]. MaxListeners is "); + scr_jb_puts(&text, limit); + scr_jb_puts(&text, ". Use emitter.setMaxListeners() to increase limit"); + scr_str_release(event); + scr_str_release(cls); + ScrClosure *tick = scr_closure_new((void *)&bc_warn_tick, 1); + ScrBox *box = scr_box_new(SCR_BOX_STR); + scr_box_set_ref(box, scr_jb_finish(&text)); + tick->caps[0] = box; + scr_next_tick(tick); +} + +/* _addListener(target, type, listener, prepend): +1 target or NULL. */ +static ScrDyn *bc_add_listener(ScrDyn *self, ScrDyn *type, ScrDyn *listener, bool prepend) { + if (!bc_check_listener(listener)) return NULL; + ScrDyn *events = bc_get(self, "_events"); + if (!events) return NULL; + ScrDyn *existing = NULL; + if (bc_undefined(events)) { + scr_dyn_release(events); + events = scr_dyn_new_obj_null_proto(); + if (!bc_set(self, "_events", scr_dyn_retain(events)) || !bc_set(self, "_eventsCount", scr_dyn_new_num(0))) + goto fail; + } else { + ScrDyn *watcher = bc_get(events, "newListener"); + if (!watcher) goto fail; + bool watched = !bc_undefined(watcher); + scr_dyn_release(watcher); + if (watched) { + ScrDyn *inner = bc_get(listener, "listener"); + if (!inner) goto fail; + ScrDyn *name = bc_key("newListener"); + ScrDyn *args[3] = { name, type, bc_undefined(inner) || inner->kind == SCR_DYN_NULL ? listener : inner }; + ScrDyn *emitted = bc_invoke(self, "emit", args, 3); + scr_dyn_release(name); + scr_dyn_release(inner); + if (!emitted) goto fail; + scr_dyn_release(emitted); + /* the listener may have replaced _events */ + scr_dyn_release(events); + events = bc_get(self, "_events"); + if (!events) return NULL; + } + existing = bc_get_key(events, type); + if (!existing) goto fail; + } + if (!existing || bc_undefined(existing)) { + if (!bc_set_key(events, type, scr_dyn_retain(listener))) goto fail; + ScrDyn *count = bc_get(self, "_eventsCount"); + if (!count) goto fail; + double next = bc_number(count) + 1; + scr_dyn_release(count); + if (!bc_set(self, "_eventsCount", scr_dyn_new_num(next))) goto fail; + } else { + if (scr_dyn_is_callable(existing)) { + ScrDyn *list = scr_dyn_new_arr(); + scr_dyn_arr_push(list, scr_dyn_retain(prepend ? listener : existing)); + scr_dyn_arr_push(list, scr_dyn_retain(prepend ? existing : listener)); + if (!bc_set_key(events, type, scr_dyn_retain(list))) { + scr_dyn_release(list); + goto fail; + } + scr_dyn_release(existing); + existing = list; + } else if (prepend) { + ScrDyn *list = bc_list_copy(existing, listener, -1); + if (!list) goto fail; + if (!bc_set_key(events, type, scr_dyn_retain(list))) { + scr_dyn_release(list); + goto fail; + } + scr_dyn_release(existing); + existing = list; + } else if (existing->kind == SCR_DYN_ARR) { + scr_dyn_arr_push(existing, scr_dyn_retain(listener)); + } + double max = bc_max_listeners(self); + if (scr_exc_pending()) goto fail; + double length = existing->kind == SCR_DYN_ARR ? scr_dyn_arr_len(existing) : 0; + if (max > 0 && length > max) { + ScrDyn *warned = bc_get(existing, "warned"); + if (!warned) goto fail; + bool already = scr_dyn_truthy(warned); + scr_dyn_release(warned); + if (!already) { + if (!bc_set(existing, "warned", scr_dyn_new_bool(true))) goto fail; + bc_warn_leak(self, type, length, max); + } + } + } + if (existing) scr_dyn_release(existing); + scr_dyn_release(events); + return scr_dyn_retain(self); +fail: + if (existing) scr_dyn_release(existing); + scr_dyn_release(events); + return NULL; +} + +/* removeListener(type, listener): +1 self or NULL. */ +static ScrDyn *bc_remove_listener(ScrDyn *self, ScrDyn *type, ScrDyn *listener) { + if (!bc_check_listener(listener)) return NULL; + ScrDyn *events = bc_get(self, "_events"); + if (!events) return NULL; + if (bc_undefined(events)) { + scr_dyn_release(events); + return scr_dyn_retain(self); + } + ScrDyn *list = bc_get_key(events, type); + if (!list) goto fail_events; + if (bc_undefined(list)) { + scr_dyn_release(list); + scr_dyn_release(events); + return scr_dyn_retain(self); + } + ScrDyn *wrapped = scr_dyn_is_callable(list) ? bc_get(list, "listener") : NULL; + if (scr_exc_pending()) goto fail_list; + bool match = scr_dyn_is_callable(list) && + (scr_dyn_strict_eq(list, listener) || (wrapped && scr_dyn_strict_eq(wrapped, listener))); + if (match) { + ScrDyn *count = bc_get(self, "_eventsCount"); + if (!count) goto fail_wrapped; + double left = bc_number(count) - 1; + scr_dyn_release(count); + if (!bc_set(self, "_eventsCount", scr_dyn_new_num(left))) goto fail_wrapped; + ScrDyn *shaped = bc_get_key(self, bc_symbol(BC_SHAPE_MODE)); + if (!shaped) goto fail_wrapped; + bool shape_mode = scr_dyn_truthy(shaped); + scr_dyn_release(shaped); + if (shape_mode) { + if (!bc_set_key(events, type, scr_dyn_retain(scr_dyn_undefined()))) goto fail_wrapped; + } else if (left == 0) { + if (!bc_set(self, "_events", scr_dyn_new_obj_null_proto())) goto fail_wrapped; + } else { + scr_dyn_key_delete_computed(events, type, false); + if (scr_exc_pending()) goto fail_wrapped; + ScrDyn *watcher = bc_get(events, "removeListener"); + if (!watcher) goto fail_wrapped; + bool watched = scr_dyn_truthy(watcher); + scr_dyn_release(watcher); + if (watched) { + ScrDyn *name = bc_key("removeListener"); + ScrDyn *args[3] = { name, type, wrapped && scr_dyn_truthy(wrapped) ? wrapped : listener }; + ScrDyn *emitted = bc_invoke(self, "emit", args, 3); + scr_dyn_release(name); + if (!emitted) goto fail_wrapped; + scr_dyn_release(emitted); + } + } + } else if (list->kind == SCR_DYN_ARR) { + double length = scr_dyn_arr_len(list); + double position = -1; + for (double i = length - 1; i >= 0; i--) { + ScrDyn *item = scr_dyn_index_get(list, i); + if (!item) goto fail_wrapped; + bool same = scr_dyn_strict_eq(item, listener); + if (!same && scr_dyn_is_callable(item)) { + ScrDyn *inner = bc_get(item, "listener"); + if (!inner) { + scr_dyn_release(item); + goto fail_wrapped; + } + same = scr_dyn_strict_eq(inner, listener); + scr_dyn_release(inner); + } + scr_dyn_release(item); + if (same) { + position = i; + break; + } + } + if (position >= 0) { + ScrDyn *rest = bc_list_copy(list, NULL, position); + if (!rest) goto fail_wrapped; + ScrDyn *stored = scr_dyn_arr_len(rest) == 1 ? scr_dyn_index_get(rest, 0) : scr_dyn_retain(rest); + scr_dyn_release(rest); + if (!stored || !bc_set_key(events, type, stored)) goto fail_wrapped; + ScrDyn *watcher = bc_get(events, "removeListener"); + if (!watcher) goto fail_wrapped; + bool watched = !bc_undefined(watcher); + scr_dyn_release(watcher); + if (watched) { + ScrDyn *name = bc_key("removeListener"); + ScrDyn *args[3] = { name, type, listener }; + ScrDyn *emitted = bc_invoke(self, "emit", args, 3); + scr_dyn_release(name); + if (!emitted) goto fail_wrapped; + scr_dyn_release(emitted); + } + } + } + if (wrapped) scr_dyn_release(wrapped); + scr_dyn_release(list); + scr_dyn_release(events); + return scr_dyn_retain(self); +fail_wrapped: + if (wrapped) scr_dyn_release(wrapped); +fail_list: + scr_dyn_release(list); +fail_events: + scr_dyn_release(events); + return NULL; +} + +/* ── once wrappers ──────────────────────────────────────────────────── */ + +enum { BC_ONCE_FIRED, BC_ONCE_TARGET, BC_ONCE_TYPE, BC_ONCE_LISTENER, BC_ONCE_SELF, BC_ONCE_CAPS }; + +static ScrBox *bc_box(ScrDyn *value /* moves in */) { + ScrBox *box = scr_box_new_obj(scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v); + scr_box_set_ref(box, value); + return box; +} + +static ScrDyn *bc_cap(ScrClosure *closure, size_t index) { + return scr_box_get_ref(closure->caps[index]); /* +1 */ +} + +/* onceWrapper: the first call removes the wrapper, then calls the listener + * with the target as its receiver. The wrapper's reference to itself is + * dropped when it fires, so a fired wrapper holds no cycle. */ +static ScrDyn *bc_once_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + if (scr_box_get_f64(closure->caps[BC_ONCE_FIRED]) != 0) return scr_dyn_retain(scr_dyn_undefined()); + ScrDyn *target = bc_cap(closure, BC_ONCE_TARGET); + ScrDyn *type = bc_cap(closure, BC_ONCE_TYPE); + ScrDyn *listener = bc_cap(closure, BC_ONCE_LISTENER); + ScrDyn *self = bc_cap(closure, BC_ONCE_SELF); + ScrDyn *result = NULL; + ScrDyn *removal[2] = { type, self }; + ScrDyn *removed = bc_invoke(target, "removeListener", removal, 2); + if (removed) { + scr_dyn_release(removed); + scr_box_set_f64(closure->caps[BC_ONCE_FIRED], 1); + scr_box_set_ref(closure->caps[BC_ONCE_SELF], scr_dyn_retain(scr_dyn_undefined())); + result = bc_apply(listener, target, args, argc); + } + scr_dyn_release(self); + scr_dyn_release(listener); + scr_dyn_release(type); + scr_dyn_release(target); + return result; +} + +static ScrDyn *bc_once_wrap(ScrDyn *target, ScrDyn *type, ScrDyn *listener) { + ScrClosure *closure = scr_closure_new(NULL, BC_ONCE_CAPS); + closure->caps[BC_ONCE_FIRED] = scr_box_new(SCR_BOX_F64); + closure->caps[BC_ONCE_TARGET] = bc_box(scr_dyn_retain(target)); + closure->caps[BC_ONCE_TYPE] = bc_box(scr_dyn_retain(type)); + closure->caps[BC_ONCE_LISTENER] = bc_box(scr_dyn_retain(listener)); + closure->caps[BC_ONCE_SELF] = bc_box(scr_dyn_retain(scr_dyn_undefined())); + scr_closure_retain(closure); + ScrDyn *wrapper = scr_dyn_new_func(closure, bc_once_call, 0, "native:events", "bound onceWrapper"); + scr_box_set_ref(closure->caps[BC_ONCE_SELF], scr_dyn_retain(wrapper)); + scr_closure_release(closure); + if (!bc_set(wrapper, "listener", scr_dyn_retain(listener))) { + scr_dyn_release(wrapper); + return NULL; + } + return wrapper; +} + +/* ── EventEmitter.prototype ─────────────────────────────────────────── */ + +static ScrDyn *bc_on(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + ScrDyn *result = bc_require_object(self, "_events") + ? bc_add_listener(self, bc_arg(args, argc, 0), bc_arg(args, argc, 1), false) : NULL; + scr_dyn_release(self); + return result; +} + +static ScrDyn *bc_prepend(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + ScrDyn *result = bc_require_object(self, "_events") + ? bc_add_listener(self, bc_arg(args, argc, 0), bc_arg(args, argc, 1), true) : NULL; + scr_dyn_release(self); + return result; +} + +static ScrDyn *bc_once_common(ScrDyn *const *args, size_t argc, bool prepend) { + ScrDyn *self = bc_this(); + ScrDyn *type = bc_arg(args, argc, 0); + ScrDyn *listener = bc_arg(args, argc, 1); + ScrDyn *result = NULL; + if (bc_check_listener(listener) && bc_require_object(self, "_events")) { + ScrDyn *wrapper = bc_once_wrap(self, type, listener); + if (wrapper) { + result = bc_add_listener(self, type, wrapper, prepend); + scr_dyn_release(wrapper); + } + } + scr_dyn_release(self); + return result; +} + +static ScrDyn *bc_once(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + return bc_once_common(args, argc, false); +} + +static ScrDyn *bc_prepend_once(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + return bc_once_common(args, argc, true); +} + +static ScrDyn *bc_off(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + ScrDyn *result = bc_require_object(self, "_events") + ? bc_remove_listener(self, bc_arg(args, argc, 0), bc_arg(args, argc, 1)) : NULL; + scr_dyn_release(self); + return result; +} + +/* removeAllListeners(type?): with no 'removeListener' watcher the table is + * reset; otherwise every listener is removed through removeListener, last + * first, so the watcher sees each one (and itself last). */ +static ScrDyn *bc_remove_all(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + if (!bc_require_object(self, "_events")) { + scr_dyn_release(self); + return NULL; + } + ScrDyn *type = bc_arg(args, argc, 0); + bool all = argc == 0; + ScrDyn *events = bc_get(self, "_events"); + ScrDyn *watcher = NULL; + if (!events) goto fail; + if (bc_undefined(events)) goto done; + watcher = bc_get(events, "removeListener"); + if (!watcher) goto fail; + if (bc_undefined(watcher)) { + if (all) { + if (!bc_set(self, "_events", scr_dyn_new_obj_null_proto()) || !bc_set(self, "_eventsCount", scr_dyn_new_num(0))) + goto fail; + } else { + ScrDyn *present = bc_get_key(events, type); + if (!present) goto fail; + bool has = !bc_undefined(present); + scr_dyn_release(present); + if (has) { + ScrDyn *count = bc_get(self, "_eventsCount"); + if (!count) goto fail; + double left = bc_number(count) - 1; + scr_dyn_release(count); + if (left == 0) { + if (!bc_set(self, "_events", scr_dyn_new_obj_null_proto()) || !bc_set(self, "_eventsCount", scr_dyn_new_num(0))) + goto fail; + } else { + if (!bc_set(self, "_eventsCount", scr_dyn_new_num(left))) goto fail; + scr_dyn_key_delete_computed(events, type, false); + if (scr_exc_pending()) goto fail; + } + } + } + goto done; + } + if (all) { + ScrDyn *keys = scr_dyn_own_keys(events); + if (!keys) goto fail; + double length = scr_dyn_arr_len(keys); + for (double i = 0; i < length; i++) { + ScrDyn *key = scr_dyn_index_get(keys, i); + if (!key) { + scr_dyn_release(keys); + goto fail; + } + bool skip = key->kind == SCR_DYN_STR && key->v.str->len == 14 && memcmp(key->v.str->data, "removeListener", 14) == 0; + ScrDyn *done_key = NULL; + if (!skip) { + ScrDyn *one[1] = { key }; + done_key = bc_invoke(self, "removeAllListeners", one, 1); + } + scr_dyn_release(key); + if (!skip && !done_key) { + scr_dyn_release(keys); + goto fail; + } + if (done_key) scr_dyn_release(done_key); + } + scr_dyn_release(keys); + ScrDyn *name = bc_key("removeListener"); + ScrDyn *one[1] = { name }; + ScrDyn *cleared = bc_invoke(self, "removeAllListeners", one, 1); + scr_dyn_release(name); + if (!cleared) goto fail; + scr_dyn_release(cleared); + if (!bc_set(self, "_events", scr_dyn_new_obj_null_proto()) || !bc_set(self, "_eventsCount", scr_dyn_new_num(0))) + goto fail; + goto done; + } + { + ScrDyn *listeners = bc_get_key(events, type); + if (!listeners) goto fail; + if (scr_dyn_is_callable(listeners)) { + ScrDyn *pair[2] = { type, listeners }; + ScrDyn *removed = bc_invoke(self, "removeListener", pair, 2); + scr_dyn_release(listeners); + if (!removed) goto fail; + scr_dyn_release(removed); + } else if (listeners->kind == SCR_DYN_ARR) { + for (double i = scr_dyn_arr_len(listeners) - 1; i >= 0; i--) { + ScrDyn *item = scr_dyn_index_get(listeners, i); + if (!item) { + scr_dyn_release(listeners); + goto fail; + } + ScrDyn *pair[2] = { type, item }; + ScrDyn *removed = bc_invoke(self, "removeListener", pair, 2); + scr_dyn_release(item); + if (!removed) { + scr_dyn_release(listeners); + goto fail; + } + scr_dyn_release(removed); + } + scr_dyn_release(listeners); + } else { + scr_dyn_release(listeners); + } + } +done: + if (watcher) scr_dyn_release(watcher); + if (events) scr_dyn_release(events); + return self; +fail: + if (watcher) scr_dyn_release(watcher); + if (events) scr_dyn_release(events); + scr_dyn_release(self); + return NULL; +} + +/* emit(type, ...args): Node's unhandled 'error' rule, then each listener + * with the emitter as its receiver over a copy of the list. */ +static ScrDyn *bc_emit(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + if (!bc_require_object(self, "_events")) { + scr_dyn_release(self); + return NULL; + } + ScrDyn *type = bc_arg(args, argc, 0); + ScrDyn *const *rest = argc > 1 ? args + 1 : bc_unused_args; + size_t restc = argc > 1 ? argc - 1 : 0; + bool error = type->kind == SCR_DYN_STR && type->v.str->len == 5 && memcmp(type->v.str->data, "error", 5) == 0; + ScrDyn *events = bc_get(self, "_events"); + if (!events) goto fail_self; + if (!bc_undefined(events)) { + if (error) { + ScrDyn *handler = bc_get(events, "error"); + if (!handler) goto fail_events; + error = bc_undefined(handler); + scr_dyn_release(handler); + } + } else if (!error) { + scr_dyn_release(events); + scr_dyn_release(self); + return scr_dyn_new_bool(false); + } + if (error) { + ScrDyn *payload = restc ? rest[0] : scr_dyn_undefined(); + if (scr_dyn_err_instanceof(payload, SCR_ERR_ERROR)) { + scr_dyn_throw(scr_dyn_retain(payload)); + } else { + ScrStr *shown = scr_insp_dyn(payload, 0, 2); + ScrJsonBuf text; + scr_jb_init(&text); + scr_jb_puts(&text, "Unhandled error. ("); + scr_jb_put_str(&text, shown); + scr_jb_putc(&text, ')'); + scr_str_release(shown); + ScrStr *message = scr_jb_finish(&text); + scr_throw_error_msg_code(SCR_ERR_ERROR, message->data, message->len, "ERR_UNHANDLED_ERROR"); + scr_str_release(message); + } + goto fail_events; + } + ScrDyn *handler = bc_get_key(events, type); + if (!handler) goto fail_events; + bool fired = !bc_undefined(handler); + if (scr_dyn_is_callable(handler)) { + ScrDyn *result = bc_apply(handler, self, rest, restc); + scr_dyn_release(handler); + if (!result) goto fail_events; + scr_dyn_release(result); + } else if (handler->kind == SCR_DYN_ARR) { + /* arrayClone: listeners added or removed during the emit run next time */ + size_t length = (size_t)scr_dyn_arr_len(handler); + ScrDyn **listeners = malloc((length ? length : 1) * sizeof *listeners); + if (!listeners) scr_trap("out of memory"); + for (size_t i = 0; i < length; i++) listeners[i] = scr_dyn_index_get(handler, (double)i); + scr_dyn_release(handler); + bool ok = true; + for (size_t i = 0; i < length && ok; i++) { + if (!listeners[i]) { + ok = false; + break; + } + ScrDyn *result = bc_apply(listeners[i], self, rest, restc); + if (!result) ok = false; + else scr_dyn_release(result); + } + for (size_t i = 0; i < length; i++) + if (listeners[i]) scr_dyn_release(listeners[i]); + free(listeners); + if (!ok) goto fail_events; + } else { + scr_dyn_release(handler); + } + scr_dyn_release(events); + scr_dyn_release(self); + return scr_dyn_new_bool(fired); +fail_events: + scr_dyn_release(events); +fail_self: + scr_dyn_release(self); + return NULL; +} + +/* _listeners(target, type, unwrap): a fresh array. */ +static ScrDyn *bc_listeners_of(bool unwrap, ScrDyn *const *args, size_t argc) { + ScrDyn *self = bc_this(); + if (!bc_require_object(self, "_events")) { + scr_dyn_release(self); + return NULL; + } + ScrDyn *result = scr_dyn_new_arr(); + ScrDyn *events = bc_get(self, "_events"); + ScrDyn *list = NULL; + if (!events) goto fail; + if (bc_undefined(events)) goto done; + list = bc_get_key(events, bc_arg(args, argc, 0)); + if (!list) goto fail; + size_t length = scr_dyn_is_callable(list) ? 1 : list->kind == SCR_DYN_ARR ? (size_t)scr_dyn_arr_len(list) : 0; + for (size_t i = 0; i < length; i++) { + ScrDyn *item = scr_dyn_is_callable(list) ? scr_dyn_retain(list) : scr_dyn_index_get(list, (double)i); + if (!item) goto fail; + if (unwrap && scr_dyn_is_callable(item)) { + ScrDyn *inner = bc_get(item, "listener"); + if (!inner) { + scr_dyn_release(item); + goto fail; + } + if (!bc_undefined(inner)) { + scr_dyn_release(item); + item = inner; + } else { + scr_dyn_release(inner); + } + } + scr_dyn_arr_push(result, item); + } +done: + if (list) scr_dyn_release(list); + if (events) scr_dyn_release(events); + scr_dyn_release(self); + return result; +fail: + if (list) scr_dyn_release(list); + if (events) scr_dyn_release(events); + scr_dyn_release(result); + scr_dyn_release(self); + return NULL; +} + +static ScrDyn *bc_listeners(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + return bc_listeners_of(true, args, argc); +} + +static ScrDyn *bc_raw_listeners(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + return bc_listeners_of(false, args, argc); +} + +/* listenerCount(type, listener?) over an emitter's _events. */ +static ScrDyn *bc_count_listeners(ScrDyn *self, ScrDyn *type, ScrDyn *only) { + ScrDyn *events = bc_get(self, "_events"); + if (!events) return NULL; + double count = 0; + if (!bc_undefined(events)) { + ScrDyn *list = bc_get_key(events, type); + if (!list) { + scr_dyn_release(events); + return NULL; + } + size_t length = scr_dyn_is_callable(list) ? 1 : list->kind == SCR_DYN_ARR ? (size_t)scr_dyn_arr_len(list) : 0; + for (size_t i = 0; i < length; i++) { + if (!only) { + count++; + continue; + } + ScrDyn *item = scr_dyn_is_callable(list) ? scr_dyn_retain(list) : scr_dyn_index_get(list, (double)i); + if (!item) break; + bool same = scr_dyn_strict_eq(item, only); + if (!same && scr_dyn_is_callable(item)) { + ScrDyn *inner = bc_get(item, "listener"); + if (inner) { + same = scr_dyn_strict_eq(inner, only); + scr_dyn_release(inner); + } + } + scr_dyn_release(item); + if (same) count++; + } + scr_dyn_release(list); + } + scr_dyn_release(events); + if (scr_exc_pending()) return NULL; + return scr_dyn_new_num(count); +} + +static ScrDyn *bc_listener_count(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + ScrDyn *result = bc_require_object(self, "_events") + ? bc_count_listeners(self, bc_arg(args, argc, 0), + argc > 1 && !bc_undefined(args[1]) && args[1]->kind != SCR_DYN_NULL ? args[1] : NULL) + : NULL; + scr_dyn_release(self); + return result; +} + +/* EventEmitter.listenerCount(emitter, type): the deprecated static. */ +static ScrDyn *bc_static_listener_count(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *emitter = bc_arg(args, argc, 0); + ScrDyn *type = bc_arg(args, argc, 1); + ScrDyn *method = bc_require_object(emitter, "listenerCount") ? bc_get(emitter, "listenerCount") : NULL; + if (!method) return NULL; + ScrDyn *result; + if (scr_dyn_is_callable(method)) result = bc_apply(method, emitter, &type, 1); + else result = bc_count_listeners(emitter, type, NULL); + scr_dyn_release(method); + return result; +} + +static ScrDyn *bc_event_names(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + (void)args; + (void)argc; + ScrDyn *self = bc_this(); + if (!bc_require_object(self, "_eventsCount")) { + scr_dyn_release(self); + return NULL; + } + ScrDyn *count = bc_get(self, "_eventsCount"); + ScrDyn *result = NULL; + if (count) { + if (bc_number(count) > 0) { + ScrDyn *events = bc_get(self, "_events"); + if (events) { + result = scr_dyn_own_keys(events); + scr_dyn_release(events); + } + } else { + result = scr_dyn_new_arr(); + } + scr_dyn_release(count); + } + scr_dyn_release(self); + return result; +} + +static ScrDyn *bc_set_max(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *self = bc_this(); + ScrDyn *n = bc_arg(args, argc, 0); + if (n->kind != SCR_DYN_NUM) { + scr_dyn_arg_type_fail("n", "of type number", n); + scr_dyn_release(self); + return NULL; + } + if (n->v.num < 0 || n->v.num != n->v.num) { + ScrStr *shown = scr_dyn_string_coerce_js(n); + ScrJsonBuf text; + scr_jb_init(&text); + scr_jb_puts(&text, "The value of \"n\" is out of range. It must be a non-negative number. Received "); + if (shown) scr_jb_put_str(&text, shown); + if (shown) scr_str_release(shown); + ScrStr *message = scr_jb_finish(&text); + scr_throw_error_msg_code(SCR_ERR_RANGE, message->data, message->len, "ERR_OUT_OF_RANGE"); + scr_str_release(message); + scr_dyn_release(self); + return NULL; + } + if (!bc_require_object(self, "_maxListeners") || !bc_set(self, "_maxListeners", scr_dyn_retain(n))) { + scr_dyn_release(self); + return NULL; + } + return self; +} + +/* EventEmitter.defaultMaxListeners, Node's accessor over the one default + * the typed EventEmitter reads too (scr_events_emitter.c). The setter + * validates as Node's validateNumber(arg, 'defaultMaxListeners', 0). */ +static ScrDyn *bc_default_max_get(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + (void)args; + (void)argc; + return scr_dyn_new_num(scr_emitter_get_default_max()); +} + +static ScrDyn *bc_default_max_set(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + static const char name[] = "defaultMaxListeners"; + ScrStr *key = scr_str_new(name, sizeof name - 1); + scr_emitter_set_default_max_chk(argc ? args[0] : scr_dyn_undefined(), key); + scr_str_release(key); + if (scr_exc_pending()) return NULL; + return scr_dyn_retain(scr_dyn_undefined()); +} + +static void bc_define_default_max(ScrDyn *ctor) { + ScrDyn *descriptor = scr_dyn_new_obj(); + scr_dyn_obj_set(descriptor, "get", 3, + scr_dyn_new_func(scr_closure_new(NULL, 0), bc_default_max_get, 0, "native:events", "get")); + scr_dyn_obj_set(descriptor, "set", 3, + scr_dyn_new_func(scr_closure_new(NULL, 0), bc_default_max_set, 1, "native:events", "set")); + scr_dyn_obj_set(descriptor, "enumerable", 10, scr_dyn_new_bool(true)); + ScrStr *name = scr_str_new("defaultMaxListeners", 19); + ScrDyn *key = scr_dyn_new_str(name); + scr_str_release(name); + ScrDyn *defined = scr_dyn_define_property(ctor, key, descriptor); + if (defined) scr_dyn_release(defined); + scr_dyn_release(key); + scr_dyn_release(descriptor); +} + +static ScrDyn *bc_get_max(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + (void)args; + (void)argc; + ScrDyn *self = bc_this(); + double max = bc_require_object(self, "_maxListeners") ? bc_max_listeners(self) : -1; + scr_dyn_release(self); + if (scr_exc_pending()) return NULL; + return scr_dyn_new_num(max); +} + +/* ── Stream.prototype.pipe (lib/internal/streams/legacy.js) ─────────── */ + +enum { BC_PIPE_SOURCE, BC_PIPE_DEST, BC_PIPE_ENDED, BC_PIPE_HANDLERS, BC_PIPE_CAPS }; +enum { BC_ONDATA, BC_ONDRAIN, BC_ONEND, BC_ONCLOSE, BC_ONERROR, BC_CLEANUP, BC_HANDLER_COUNT }; + +static ScrDyn *bc_pipe_handler(ScrClosure *state, int which); + +static ScrDyn *bc_pipe_get_handler(ScrClosure *state, int which) { + ScrDyn *handlers = bc_cap(state, BC_PIPE_HANDLERS); + ScrDyn *handler = scr_dyn_index_get(handlers, which); + scr_dyn_release(handlers); + return handler; +} + +/* Calls source/dest.removeListener for one pipe handler. */ +static bool bc_pipe_remove(ScrDyn *emitter, const char *event, ScrClosure *state, int which) { + ScrDyn *handler = bc_pipe_get_handler(state, which); + if (!handler) return false; + ScrDyn *name = bc_key(event); + ScrDyn *pair[2] = { name, handler }; + ScrDyn *removed = bc_invoke(emitter, "removeListener", pair, 2); + scr_dyn_release(name); + scr_dyn_release(handler); + if (!removed) return false; + scr_dyn_release(removed); + return true; +} + +static bool bc_pipe_on(ScrDyn *emitter, const char *event, ScrClosure *state, int which) { + ScrDyn *handler = bc_pipe_get_handler(state, which); + if (!handler) return false; + ScrDyn *name = bc_key(event); + ScrDyn *pair[2] = { name, handler }; + ScrDyn *added = bc_invoke(emitter, "on", pair, 2); + scr_dyn_release(name); + scr_dyn_release(handler); + if (!added) return false; + scr_dyn_release(added); + return true; +} + +static bool bc_pipe_cleanup(ScrClosure *state) { + /* A second run (dest emitting 'close' from end(), with cleanup still + * queued on the source's 'end') finds the listeners removed, as Node's + * repeated removeListener calls do. */ + ScrDyn *handlers = bc_cap(state, BC_PIPE_HANDLERS); + bool cleaned = handlers->kind == SCR_DYN_ARR && scr_dyn_arr_len(handlers) == 0; + scr_dyn_release(handlers); + if (cleaned) return true; + ScrDyn *source = bc_cap(state, BC_PIPE_SOURCE); + ScrDyn *dest = bc_cap(state, BC_PIPE_DEST); + bool ok = bc_pipe_remove(source, "data", state, BC_ONDATA) && + bc_pipe_remove(dest, "drain", state, BC_ONDRAIN) && + bc_pipe_remove(source, "end", state, BC_ONEND) && + bc_pipe_remove(source, "close", state, BC_ONCLOSE) && + bc_pipe_remove(source, "error", state, BC_ONERROR) && + bc_pipe_remove(dest, "error", state, BC_ONERROR) && + bc_pipe_remove(source, "end", state, BC_CLEANUP) && + bc_pipe_remove(source, "close", state, BC_CLEANUP) && + bc_pipe_remove(dest, "close", state, BC_CLEANUP); + scr_dyn_release(dest); + scr_dyn_release(source); + /* the handlers array held the closures that hold this state */ + if (ok) scr_box_set_ref(state->caps[BC_PIPE_HANDLERS], scr_dyn_new_arr()); + return ok; +} + +static ScrDyn *bc_pipe_event(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + ScrClosure *state = (ScrClosure *)scr_box_get_ref(closure->caps[0]); + int which = (int)scr_box_get_f64(closure->caps[1]); + ScrDyn *source = bc_cap(state, BC_PIPE_SOURCE); + ScrDyn *dest = bc_cap(state, BC_PIPE_DEST); + bool ok = true; + switch (which) { + case BC_ONDATA: { + ScrDyn *writable = bc_get(dest, "writable"); + if (!writable) { + ok = false; + break; + } + bool open = scr_dyn_truthy(writable); + scr_dyn_release(writable); + if (!open) break; + ScrDyn *chunk = bc_arg(args, argc, 0); + ScrDyn *written = bc_invoke(dest, "write", &chunk, 1); + if (!written) { + ok = false; + break; + } + bool full = written->kind == SCR_DYN_BOOL && !written->v.b; + scr_dyn_release(written); + if (full) { + ScrDyn *pause = bc_get(source, "pause"); + if (!pause) { + ok = false; + break; + } + if (scr_dyn_is_callable(pause)) { + ScrDyn *paused = bc_apply(pause, source, bc_unused_args, 0); + if (paused) scr_dyn_release(paused); + else ok = false; + } + scr_dyn_release(pause); + } + break; + } + case BC_ONDRAIN: { + ScrDyn *readable = bc_get(source, "readable"); + ScrDyn *resume = readable ? bc_get(source, "resume") : NULL; + if (!readable || !resume) { + ok = false; + } else if (scr_dyn_truthy(readable) && scr_dyn_is_callable(resume)) { + ScrDyn *resumed = bc_apply(resume, source, bc_unused_args, 0); + if (resumed) scr_dyn_release(resumed); + else ok = false; + } + if (readable) scr_dyn_release(readable); + if (resume) scr_dyn_release(resume); + break; + } + case BC_ONEND: + case BC_ONCLOSE: { + if (scr_box_get_f64(state->caps[BC_PIPE_ENDED]) != 0) break; + scr_box_set_f64(state->caps[BC_PIPE_ENDED], 1); + ScrDyn *done = which == BC_ONEND ? bc_invoke(dest, "end", bc_unused_args, 0) : NULL; + if (which == BC_ONCLOSE) { + ScrDyn *destroy = bc_get(dest, "destroy"); + if (!destroy) { + ok = false; + break; + } + if (scr_dyn_is_callable(destroy)) done = bc_apply(destroy, dest, bc_unused_args, 0); + else done = scr_dyn_retain(scr_dyn_undefined()); + scr_dyn_release(destroy); + } + if (done) scr_dyn_release(done); + else ok = false; + break; + } + case BC_ONERROR: { + ok = bc_pipe_cleanup(state); + if (!ok) break; + ScrDyn *rethrow = scr_dyn_this_get(); + ScrDyn *name = bc_key("error"); + ScrDyn *count = rethrow->kind == SCR_DYN_UNDEF ? NULL : bc_invoke(rethrow, "listenerCount", &name, 1); + scr_dyn_release(name); + if (count && bc_number(count) == 0) { + scr_dyn_throw(scr_dyn_retain(bc_arg(args, argc, 0))); + ok = false; + } else if (!count && scr_exc_pending()) { + ok = false; + } + if (count) scr_dyn_release(count); + scr_dyn_release(rethrow); + break; + } + case BC_CLEANUP: + ok = bc_pipe_cleanup(state); + break; + default: + break; + } + scr_dyn_release(dest); + scr_dyn_release(source); + scr_closure_release(state); + return ok ? scr_dyn_retain(scr_dyn_undefined()) : NULL; +} + +static ScrDyn *bc_pipe_handler(ScrClosure *state, int which) { + ScrClosure *closure = scr_closure_new(NULL, 2); + ScrBox *owner = scr_box_new_obj(scr_closure_retain_v, scr_closure_release_v, scr_closure_trace_v); + scr_box_set_ref(owner, scr_closure_retain(state)); + closure->caps[0] = owner; + closure->caps[1] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(closure->caps[1], which); + return scr_dyn_new_func(closure, bc_pipe_event, 0, "native:stream", which == BC_ONDATA ? "ondata" + : which == BC_ONDRAIN ? "ondrain" : which == BC_ONEND ? "onend" : which == BC_ONCLOSE ? "onclose" + : which == BC_ONERROR ? "onerror" : "cleanup"); +} + +/* Stream.prototype.pipe(dest, options): Node's legacy pipe for streams + * that are only EventEmitters. 'end' and 'close' end or destroy the + * destination unless options.end is false or the destination is stdio. */ +static ScrDyn *bc_pipe(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + (void)closure; + ScrDyn *source = bc_this(); + ScrDyn *dest = bc_arg(args, argc, 0); + ScrDyn *options = bc_arg(args, argc, 1); + if (!bc_require_object(source, "on") || !bc_require_object(dest, "on")) { + scr_dyn_release(source); + return NULL; + } + ScrClosure *state = scr_closure_new(NULL, BC_PIPE_CAPS); + state->caps[BC_PIPE_SOURCE] = bc_box(scr_dyn_retain(source)); + state->caps[BC_PIPE_DEST] = bc_box(scr_dyn_retain(dest)); + state->caps[BC_PIPE_ENDED] = scr_box_new(SCR_BOX_F64); + ScrDyn *handlers = scr_dyn_new_arr(); + for (int i = 0; i < BC_HANDLER_COUNT; i++) scr_dyn_arr_push(handlers, bc_pipe_handler(state, i)); + state->caps[BC_PIPE_HANDLERS] = bc_box(handlers); + bool ok = bc_pipe_on(source, "data", state, BC_ONDATA) && bc_pipe_on(dest, "drain", state, BC_ONDRAIN); + bool end_dest = true; + if (ok && options->kind != SCR_DYN_UNDEF && options->kind != SCR_DYN_NULL) { + ScrDyn *end = bc_get(options, "end"); + if (!end) ok = false; + else { + end_dest = !(end->kind == SCR_DYN_BOOL && !end->v.b); + scr_dyn_release(end); + } + } + if (ok && end_dest) { + ScrDyn *stdio = bc_get(dest, "_isStdio"); + if (!stdio) ok = false; + else { + end_dest = !scr_dyn_truthy(stdio); + scr_dyn_release(stdio); + } + } + if (ok && end_dest) + ok = bc_pipe_on(source, "end", state, BC_ONEND) && bc_pipe_on(source, "close", state, BC_ONCLOSE); + if (ok) { + /* prependListener(source, 'error', onerror) and the same on dest */ + ScrDyn *onerror = bc_pipe_get_handler(state, BC_ONERROR); + ScrDyn *name = bc_key("error"); + ScrDyn *pair[2] = { name, onerror }; + ScrDyn *a = onerror ? bc_invoke(source, "prependListener", pair, 2) : NULL; + ScrDyn *b = a ? bc_invoke(dest, "prependListener", pair, 2) : NULL; + ok = a && b; + if (a) scr_dyn_release(a); + if (b) scr_dyn_release(b); + scr_dyn_release(name); + if (onerror) scr_dyn_release(onerror); + } + if (ok) + ok = bc_pipe_on(source, "end", state, BC_CLEANUP) && bc_pipe_on(source, "close", state, BC_CLEANUP) && + bc_pipe_on(dest, "close", state, BC_CLEANUP); + ScrDyn *result = NULL; + if (ok) { + ScrDyn *name = bc_key("pipe"); + ScrDyn *pair[2] = { name, source }; + ScrDyn *emitted = bc_invoke(dest, "emit", pair, 2); + scr_dyn_release(name); + if (emitted) { + scr_dyn_release(emitted); + result = scr_dyn_retain(dest); + } + } + scr_closure_release(state); + scr_dyn_release(source); + return result; +} + +/* ── the constructors ───────────────────────────────────────────────── */ + +static ScrDyn *bc_construct(ScrClosure *closure, ScrDyn *const *args, size_t argc) { + int kind = (int)scr_box_get_f64(closure->caps[0]); + ScrDyn *self = bc_this(); + ScrDyn *result = NULL; + if (kind == BC_EMITTER || kind == BC_STREAM) { + if (bc_emitter_init(self, bc_arg(args, argc, 0))) result = scr_dyn_retain(scr_dyn_undefined()); + } else { + char message[160]; + snprintf(message, sizeof message, + "'%s' as the base of a constructor function (util.inherits or %s.call(this)) is not supported yet", + bc_names[kind], bc_names[kind]); + scr_throw_error_msg_code(SCR_ERR_ERROR, message, strlen(message), "SC2020"); + } + scr_dyn_release(self); + return result; +} + +static void bc_method(ScrDyn *prototype, const char *name, ScrDynThunk thunk, uint32_t arity) { + ScrDyn *fn = scr_dyn_new_func(scr_closure_new(NULL, 0), thunk, arity, "native:events", name); + bc_set(prototype, name, fn); +} + +static void bc_alias(ScrDyn *prototype, const char *alias, const char *name) { + ScrDyn *fn = bc_get(prototype, name); + if (fn) bc_set(prototype, alias, fn); +} + +static void bc_teardown(void) { + for (int i = 0; i < BC_COUNT; i++) { + if (!bc_ctors[i]) continue; + ScrDyn *ctor = bc_ctors[i]; + /* prototype.constructor, EventEmitter.EventEmitter and Stream.Stream + * point back at the constructor, and Stream.Readable … at constructors + * whose own prototype is Stream: break those cycles first. */ + ScrDyn *prototype = bc_get(ctor, "prototype"); + if (prototype && prototype->kind == SCR_DYN_OBJ) bc_set(prototype, "constructor", scr_dyn_retain(scr_dyn_undefined())); + if (prototype) scr_dyn_release(prototype); + bc_set(ctor, bc_names[i], scr_dyn_retain(scr_dyn_undefined())); + if (i == BC_STREAM) + for (int other = BC_READABLE; other < BC_COUNT; other++) + bc_set(ctor, bc_names[other], scr_dyn_retain(scr_dyn_undefined())); + if (scr_exc_pending()) scr_exc_clear(); + } + for (int i = 0; i < BC_COUNT; i++) { + if (!bc_ctors[i]) continue; + ScrDyn *ctor = bc_ctors[i]; + bc_ctors[i] = NULL; + scr_dyn_release(ctor); + } + for (int i = 0; i < BC_SYMBOLS; i++) { + if (bc_symbols[i]) scr_dyn_release(bc_symbols[i]); + bc_symbols[i] = NULL; + } + if (scr_exc_pending()) scr_exc_clear(); +} + +static ScrDyn *bc_new_class(int kind, ScrDyn *parent) { + ScrClosure *closure = scr_closure_new(NULL, 1); + closure->function_kind = 4; /* an ordinary function with its own prototype */ + closure->caps[0] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(closure->caps[0], kind); + ScrDyn *ctor = scr_dyn_new_func(closure, bc_construct, 1, "native:events", bc_names[kind]); + ScrDyn *prototype = parent ? NULL : scr_dyn_new_obj(); + if (parent) { + ScrDyn *base = bc_get(parent, "prototype"); + prototype = scr_dyn_obj_create(base); + scr_dyn_release(base); + ScrDyn *linked = scr_dyn_set_prototype(ctor, parent); + if (linked) scr_dyn_release(linked); + } + bc_set(prototype, "constructor", scr_dyn_retain(ctor)); + bc_set(ctor, "prototype", scr_dyn_retain(prototype)); + if (kind == BC_EMITTER) { + bc_set(prototype, "_events", scr_dyn_retain(scr_dyn_undefined())); + bc_set(prototype, "_eventsCount", scr_dyn_new_num(0)); + bc_set(prototype, "_maxListeners", scr_dyn_retain(scr_dyn_undefined())); + bc_set_key(prototype, bc_symbol(BC_CAPTURE), scr_dyn_new_bool(false)); + bc_method(prototype, "setMaxListeners", bc_set_max, 1); + bc_method(prototype, "getMaxListeners", bc_get_max, 0); + bc_method(prototype, "emit", bc_emit, 1); + bc_method(prototype, "addListener", bc_on, 2); + bc_alias(prototype, "on", "addListener"); + bc_method(prototype, "prependListener", bc_prepend, 2); + bc_method(prototype, "once", bc_once, 2); + bc_method(prototype, "prependOnceListener", bc_prepend_once, 2); + bc_method(prototype, "removeListener", bc_off, 2); + bc_alias(prototype, "off", "removeListener"); + bc_method(prototype, "removeAllListeners", bc_remove_all, 1); + bc_method(prototype, "listeners", bc_listeners, 1); + bc_method(prototype, "rawListeners", bc_raw_listeners, 1); + bc_method(prototype, "listenerCount", bc_listener_count, 2); + bc_method(prototype, "eventNames", bc_event_names, 0); + bc_set(ctor, "EventEmitter", scr_dyn_retain(ctor)); + bc_define_default_max(ctor); + ScrDyn *count = scr_dyn_new_func(scr_closure_new(NULL, 0), bc_static_listener_count, 2, "native:events", "listenerCount"); + bc_set(ctor, "listenerCount", count); + } else if (kind == BC_STREAM) { + ScrDyn *pipe = scr_dyn_new_func(scr_closure_new(NULL, 0), bc_pipe, 2, "native:stream", "pipe"); + bc_set(prototype, "pipe", pipe); + } + scr_dyn_release(prototype); + if (scr_exc_pending()) scr_exc_clear(); + return ctor; +} + +/* All seven constructors are created together, each after its parent, so + * Stream's static members name the same constructors every other read + * answers. */ +static ScrDyn *bc_class(int kind) { + if (!bc_ctors[kind]) { + static const int parents[BC_COUNT] = { + -1, BC_EMITTER, BC_STREAM, BC_STREAM, BC_READABLE, BC_DUPLEX, BC_TRANSFORM, + }; + for (int each = 0; each < BC_COUNT; each++) { + if (bc_ctors[each]) continue; + bc_ctors[each] = bc_new_class(each, parents[each] >= 0 ? bc_ctors[parents[each]] : NULL); + } + /* Registered after the constructors exist, so the teardown runs before + * the runtime state their properties were stored in (scr_atexit is + * last in, first out). */ + if (!bc_teardown_registered) { + bc_teardown_registered = true; + scr_atexit(bc_teardown); + } + /* require("stream") is Stream itself, carrying its classes */ + ScrDyn *stream = bc_ctors[BC_STREAM]; + bc_set(stream, "Stream", scr_dyn_retain(stream)); + for (int other = BC_READABLE; other < BC_COUNT; other++) + bc_set(stream, bc_names[other], scr_dyn_retain(bc_ctors[other])); + if (scr_exc_pending()) scr_exc_clear(); + } + return bc_ctors[kind]; +} + +/* The constructor value for kind (the BC_* order), +1. */ +ScrDyn *scr_dyn_builtin_class(double kind) { + int index = (int)kind; + if (index < 0 || index >= BC_COUNT) scr_trap("scriptc: unknown builtin class value\n"); + return scr_dyn_retain(bc_class(index)); +} + +/* OrdinaryHasInstance over the value's prototype chain. */ +static bool bc_chain_has(ScrDyn *value, ScrDyn *prototype) { + if (value->kind != SCR_DYN_OBJ && value->kind != SCR_DYN_ARR && value->kind != SCR_DYN_FUNC && + value->kind != SCR_DYN_PROXY) + return false; + ScrDyn *current = scr_dyn_get_prototype(value); + while (current && current->kind != SCR_DYN_NULL) { + if (scr_dyn_strict_eq(current, prototype)) { + scr_dyn_release(current); + return true; + } + ScrDyn *next = scr_dyn_get_prototype(current); + scr_dyn_release(current); + current = next; + } + if (current) scr_dyn_release(current); + return false; +} + +/* `value instanceof `. Node's Writable also answers true for an + * object whose _writableState is a WritableState, which no untyped object + * has, so the prototype chain answers for every kind. */ +bool scr_dyn_builtin_instanceof(ScrDyn *value, double kind) { + int index = (int)kind; + if (index < 0 || index >= BC_COUNT) scr_trap("scriptc: unknown builtin class value\n"); + ScrDyn *prototype = bc_get(bc_class(index), "prototype"); + if (!prototype) return false; + bool found = bc_chain_has(value, prototype); + scr_dyn_release(prototype); + return found; +} + +/* `value instanceof callee` for an untyped constructor function. */ +bool scr_dyn_function_instanceof(ScrDyn *value, ScrDyn *callee) { + if (!scr_dyn_is_callable(callee)) { + static const char message[] = "Right-hand side of 'instanceof' is not callable"; + scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1); + return false; + } + ScrDyn *prototype = bc_get(callee, "prototype"); + if (!prototype) return false; + bool found = false; + if (prototype->kind == SCR_DYN_OBJ || prototype->kind == SCR_DYN_ARR || prototype->kind == SCR_DYN_FUNC || + prototype->kind == SCR_DYN_PROXY) { + found = bc_chain_has(value, prototype); + } else if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_ARR || value->kind == SCR_DYN_FUNC) { + static const char message[] = "Function has non-object prototype 'undefined' in instanceof check"; + scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1); + } + scr_dyn_release(prototype); + return found; +} diff --git a/packages/runtime/src/scr_error.h b/packages/runtime/src/scr_error.h index 453ebf3e1..a7c921f23 100644 --- a/packages/runtime/src/scr_error.h +++ b/packages/runtime/src/scr_error.h @@ -282,6 +282,21 @@ SCR_COLD void scr_undef_global_read(ScrStr *name); * +1 or NULL when absent (the compiler's undefined arm). The _msg_code * thrower is scr_throw_error_msg with the code stamped on the payload. */ void scr_error_set_code(ScrError *e, const char *code); +/* The program's `err.code = s` write into the same slot (and the error's + * checked-dynamic node, when it has one). Borrows both (scr_json.c). */ +void scr_error_set_code_value(ScrError *e, ScrStr *code); +/* `err.code = v` with a value that is not statically a string: a string + * takes the slot as above; anything else clears the slot and lands on the + * error's checked-dynamic node, as a dynamic property write would. + * Borrows both (scr_json.c). */ +void scr_error_set_code_dyn(ScrError *e, struct ScrDyn *value); +/* Object.assign(err, ...sources): the copy onto the error's checked-dynamic + * node, then the typed slots re-read from it. Borrows both (scr_json.c). */ +void scr_error_assign_dyn(ScrError *e, const struct ScrDyn *sources); +/* `key in err` for a key no compiled class declares: a runtime-set own + * property or an Object.prototype member. Borrows both (scr_json.c). */ +bool scr_error_has_key(ScrError *e, const ScrStr *key); +bool scr_error_has_code(ScrError *e); const char *scr_error_message_code(const ScrStr *msg); ScrStr *scr_error_code(ScrError *e); SCR_COLD void scr_throw_error_msg_code(int kind, const char *message, size_t len, const char *code); diff --git a/packages/runtime/src/scr_inspect.c b/packages/runtime/src/scr_inspect.c index 3903cabeb..c1673891b 100644 --- a/packages/runtime/src/scr_inspect.c +++ b/packages/runtime/src/scr_inspect.c @@ -1097,6 +1097,16 @@ static ScrStr *scr_insp_class_tag(const char *cls, const char *tail) { return ib_take(&out); } +/* Node prints a @@toStringTag that ends with "." and the constructor name + * (WebAssembly.Module for Module) in place of the name, without the + * bracketed tag. */ +static bool insp_tag_names_class(const char *tag, const char *cls) { + if (!tag) return false; + size_t tag_len = strlen(tag), cls_len = strlen(cls); + return tag_len > cls_len + 1 && tag[tag_len - cls_len - 1] == '.' && + memcmp(tag + tag_len - cls_len, cls, cls_len) == 0; +} + /* A native Set or Map held as a checked-dynamic value: `Set(n) { a, b }`, * `Map(n) { k => v }`, at most 100 entries like Node's maxArrayLength. */ /* Node's formatWeakCollection: the entries of a WeakMap or WeakSet are not @@ -1495,11 +1505,15 @@ ScrStr *scr_insp_dyn(ScrDyn *d, double recurse, double depth) { ScrStr *body = scr_insp_dyn(view, recurse, depth); scr_dyn_release(view); InspBuf out = {0}; - ib_cstr(&out, ops->cls); - if (ops->to_string_tag) { - ib_cstr(&out, " ["); + if (insp_tag_names_class(ops->to_string_tag, ops->cls)) { ib_cstr(&out, ops->to_string_tag); - ib_char(&out, ']'); + } else { + ib_cstr(&out, ops->cls); + if (ops->to_string_tag) { + ib_cstr(&out, " ["); + ib_cstr(&out, ops->to_string_tag); + ib_char(&out, ']'); + } } ib_char(&out, ' '); ib_bytes(&out, body->data, body->len); diff --git a/packages/runtime/src/scr_json.c b/packages/runtime/src/scr_json.c index f2b469667..9746e8eb1 100644 --- a/packages/runtime/src/scr_json.c +++ b/packages/runtime/src/scr_json.c @@ -4428,6 +4428,7 @@ static void scr_dyn_descriptor_fields_drop(ScrDyn **fields) { } static bool scr_dyn_key_is_index(const char *key, size_t len, double *out); static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key); +static void scr_error_sync_slots(const ScrDyn *view, ScrDyn *obj, const ScrStr *key); /* Property tables belong to closures, not temporary checked wrappers. Seed * the configurable, non-writable builtin members once so redefinitions and @@ -6719,6 +6720,10 @@ ScrStr *scr_dyn_format_j(const ScrDyn *d) { typedef struct { ScrError *err; /* retained (pins the address — no pointer reuse) */ ScrDyn *dyn; /* retained */ + /* An own `code` that is not a string (`err.code = undefined`), retained, + * or NULL. The code slot holds only strings, and a subclass's typed view + * rebuilds its properties from the slots on every read. */ + ScrDyn *code; } ScrErrDynEnt; static SCR_TL ScrErrDynEnt *scr_errdyn_cache = NULL; @@ -6822,6 +6827,7 @@ static void scr_errdyn_sweep(void) { for (size_t i = 0; i < n_dead; i++) { scr_error_release(dead[i].err); scr_errdyn_release_node(dead[i].dyn); + scr_dyn_release(dead[i].code); } free(dead); } @@ -6842,6 +6848,7 @@ static void scr_errdyn_append(ScrError *e, ScrDyn *d) { } scr_errdyn_cache[scr_errdyn_n].err = scr_error_retain(e); scr_errdyn_cache[scr_errdyn_n].dyn = scr_dyn_retain(d); + scr_errdyn_cache[scr_errdyn_n].code = NULL; scr_errdyn_n++; if (scr_errdyn_n * 2 > scr_errdyn_slots) { free(scr_errdyn_by_err); @@ -6897,6 +6904,7 @@ static void scr_errdyn_teardown(void) { for (size_t i = 0; i < n; i++) { scr_error_release(cache[i].err); scr_errdyn_release_node(cache[i].dyn); + scr_dyn_release(cache[i].code); } free(cache); } @@ -7048,7 +7056,13 @@ ScrDyn *scr_error_dyn_fields(const ScrError *e) { /* errno rides fs errors (with syscall) and zlib errors (without). */ if (e->system_call || e->system_errno != 0) scr_dyn_obj_set(d, "errno", 5, scr_dyn_new_num(e->system_errno)); - if (e->code) scr_dyn_obj_set(d, "code", 4, scr_dyn_new_str(e->code)); + if (e->code) { + scr_dyn_obj_set(d, "code", 4, scr_dyn_new_str(e->code)); + } else { + size_t hit = scr_errdyn_find(e, true); + if (hit != SIZE_MAX && scr_errdyn_cache[hit].code != NULL) + scr_dyn_obj_set(d, "code", 4, scr_dyn_retain(scr_errdyn_cache[hit].code)); + } if (e->system_call) scr_dyn_obj_set(d, "syscall", 7, scr_dyn_new_str(e->system_call)); } if (!e->errno_order && e->system_path) scr_dyn_obj_set(d, "path", 4, scr_dyn_new_str(e->system_path)); @@ -7250,18 +7264,35 @@ ScrError *scr_errdyn_err_of(const ScrDyn *d) { void scr_errdyn_put(ScrError *e, ScrDyn *d) { scr_errdyn_append(e, d); } -/* Error.cause has one live value even when the Error already crossed a - * checked-value boundary. Reflective data-property edits update its slot. */ -static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key) { +/* An Error's slots (name, message, stack, cause, code) have one live value + * even when the Error already crossed a checked-value boundary: writes and + * deletes of those own properties through its checked-dynamic node update + * the slots typed reads use. `view` is the error's node; `obj` holds the + * properties (the node itself, or a typed view's materialized object). */ +static void scr_error_sync_slots(const ScrDyn *view, ScrDyn *obj, const ScrStr *key) { bool cause = key->len == 5 && memcmp(key->data, "cause", 5) == 0; bool stack = key->len == 5 && memcmp(key->data, "stack", 5) == 0; bool name = key->len == 4 && memcmp(key->data, "name", 4) == 0; bool message = key->len == 7 && memcmp(key->data, "message", 7) == 0; - if (!cause && !stack && !name && !message) return; + bool code = key->len == 4 && memcmp(key->data, "code", 4) == 0; + if (!cause && !stack && !name && !message && !code) return; + if (obj == NULL || obj->kind != SCR_DYN_OBJ) return; size_t hit = scr_errdyn_find(view, false); if (hit == SIZE_MAX) return; - ScrDynEntry *entry = scr_dyn_entry(view, key); + ScrDynEntry *entry = scr_dyn_entry(obj, key); ScrError *e = scr_errdyn_cache[hit].err; + if (code) { + /* A string takes the slot; any other value clears it and stays an own + * property, which the entry keeps for views rebuilt from the slots. */ + bool string = entry && !entry->accessor && entry->value->kind == SCR_DYN_STR; + ScrStr *next = string ? scr_str_retain(entry->value->v.str) : NULL; + scr_str_release(e->code); + e->code = next; + ScrDyn *other = entry && !string && !entry->accessor ? scr_dyn_retain(entry->value) : NULL; + scr_dyn_release(scr_errdyn_cache[hit].code); + scr_errdyn_cache[hit].code = other; + return; + } if (name || message) { /* The native error's toString and inspect read these fields. */ if (!entry || entry->accessor || entry->value->kind != SCR_DYN_STR) return; @@ -7292,6 +7323,10 @@ static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key) { e->cause_enumerable = entry && entry->enumerable; } +static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key) { + scr_error_sync_slots(view, view, key); +} + /* Error.prototype.toString over the checked-dynamic error encoding (an * object carrying the reserved "%error" marker): `name` defaults to "Error" * and `message` to "", both read through the prototype; either empty leaves @@ -8323,7 +8358,12 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) { if (scr_event_ref_hooks && scr_event_ref_hooks->set(recv, key, value)) return; ScrDyn *materialized = scr_dyn_typed_ref_materialize(recv); scr_dyn_key_set(materialized, key, value); - if (!scr_exc_pending()) scr_dyn_typed_ref_commit(recv); + if (!scr_exc_pending()) { + scr_dyn_typed_ref_commit(recv); + /* An Error subclass's class commit writes its declared fields; the + * slots it inherits from Error take the write here. */ + scr_error_sync_slots(recv, materialized, key); + } scr_dyn_release(materialized); return; } @@ -10097,7 +10137,10 @@ void scr_dyn_key_delete(ScrDyn *recv, const ScrStr *key, bool strict) { scr_dyn_entry(materialized, key) != NULL; if (!scr_exc_pending()) scr_dyn_key_delete(materialized, key, strict); bool deleted = own && !scr_exc_pending(); - if (!scr_exc_pending()) scr_dyn_typed_ref_commit(recv); + if (!scr_exc_pending()) { + scr_dyn_typed_ref_commit(recv); + scr_error_sync_slots(recv, materialized, key); + } scr_dyn_release(materialized); if (deleted && scr_exc_pending()) { /* The native layout requires this field, so the commit rejected the @@ -12478,7 +12521,17 @@ ScrDyn *scr_dyn_assign(ScrDyn *target, const ScrDyn *src) { if (target->kind == SCR_DYN_TYPED_REF) { ScrDyn *materialized = scr_dyn_typed_ref_materialize(target); ScrDyn *assigned = scr_dyn_assign(materialized, src); - if (!scr_exc_pending()) scr_dyn_typed_ref_commit(target); + if (!scr_exc_pending()) { + scr_dyn_typed_ref_commit(target); + /* An Error subclass's inherited slots take the copied values. */ + static const char *const slots[] = { "name", "message", "stack", "cause", "code" }; + for (size_t i = 0; i < sizeof slots / sizeof slots[0]; i++) { + ScrStr *key = scr_str_new(slots[i], strlen(slots[i])); + if (materialized->kind == SCR_DYN_OBJ && scr_dyn_entry(materialized, key) != NULL) + scr_error_sync_slots(target, materialized, key); + scr_str_release(key); + } + } scr_dyn_release(assigned); scr_dyn_release(materialized); return scr_exc_pending() ? NULL : scr_dyn_retain(target); @@ -14603,3 +14656,80 @@ ScrDyn *scr_dyn_iter_take(const ScrDyn *src, size_t n, const char *spell) { bool scr_dyn_iterates_by_protocol(const ScrDyn *value) { return scr_dyn_sync_generator(value); } + +/* The program's writes onto compiled errors (scr_error.h). Kept at the end + * of the file, after every function they call, so the rest of the unit + * emits in its existing order. */ + +/* `err.code = s` from the program (an Error asserted to carry `code`): + * the same slot every coded throw stamps, so reads and `'code' in err` + * observe the write. Borrows both. */ +void scr_error_set_code_value(ScrError *e, ScrStr *code) { + scr_str_release(e->code); + e->code = scr_str_retain(code); + /* An error that already crossed into the checked-dynamic tree renders + * and reads through that node, so the write lands there too. */ + ScrDyn *view = scr_errdyn_view_of(e); + if (view != NULL && view->kind == SCR_DYN_OBJ) scr_dyn_obj_set(view, "code", 4, scr_dyn_new_str(code)); +} + +void scr_error_set_code_dyn(ScrError *e, ScrDyn *value) { + if (value != NULL && value->kind == SCR_DYN_STR) { + scr_error_set_code_value(e, value->v.str); + return; + } + scr_str_release(e->code); + e->code = NULL; + ScrDyn *view = scr_dyn_from_error(e); + ScrStr *key = scr_str_new("code", 4); + scr_dyn_key_set(view, key, value); + scr_str_release(key); + scr_dyn_release(view); +} + +/* Object.assign(err, ...sources) onto a compiled error: each source's own + * members land on the error's checked-dynamic node, then the slots that + * typed reads use (name, message, stack, cause, code) take the result. + * Borrows both; throws what the copy throws (a nullish source is skipped, + * as in JS). */ +void scr_error_assign_dyn(ScrError *e, const ScrDyn *sources) { + ScrDyn *view = scr_dyn_from_error(e); + ScrDyn *r = scr_dyn_assign_all(view, sources); + if (r != NULL) { + scr_dyn_release(r); + if (view->kind == SCR_DYN_OBJ) { + scr_error_commit_dyn(e, view); + if (!scr_exc_pending()) { + ScrDyn *code = scr_dyn_obj_get(view, "code", 4); + ScrStr *next = code != NULL && code->kind == SCR_DYN_STR ? scr_str_retain(code->v.str) : NULL; + scr_str_release(e->code); + e->code = next; + } + } + } + scr_dyn_release(view); +} + +/* `'code' in err`: the code slot holds a string, or the error has an own + * `code` property with another value (`err.code = undefined`), which lives + * on its checked-dynamic node. Borrows; never throws. */ +bool scr_error_has_code(ScrError *e) { + if (e->code != NULL) return true; + const ScrDyn *view = scr_errdyn_view_of(e); + if (view == NULL) return false; + ScrStr *key = scr_str_new("code", 4); + bool own = scr_dyn_has_own(view, key); + scr_str_release(key); + return own; +} + +/* `key in err` for a key no compiled class of the receiver declares: an own + * property set at runtime, which lives on the error's checked-dynamic node + * (that node exists once anything reflected or wrote through it), or a + * member of Object.prototype. Borrows both; never throws. */ +bool scr_error_has_key(ScrError *e, const ScrStr *key) { + const ScrDyn *view = scr_errdyn_view_of(e); + if (view != NULL && view->kind == SCR_DYN_OBJ && scr_dyn_find_entry(view, key->data, key->len) != NULL) + return true; + return scr_dyn_object_proto_name(key); +} diff --git a/packages/runtime/src/scr_lib.h b/packages/runtime/src/scr_lib.h index 690f84875..bae678292 100644 --- a/packages/runtime/src/scr_lib.h +++ b/packages/runtime/src/scr_lib.h @@ -174,6 +174,21 @@ double scr_process_uptime(void); /* perf_hooks performance.now(): fractional ms since process start (the * uptime anchor — Node's timeOrigin for a compiled program). */ double scr_perf_now(void); +/* perf_hooks event-loop metrics (scr_perf_loop.c). loop_mark records the + * loop's start (the emitted main calls it before the loop runs, only in + * programs that read the metric); loop_start answers it (0 before) and + * idle_time the idle ms since. The eld_* family is monitorEventLoopDelay's + * IntervalHistogram over a handle; eld_percentile expects 0 < p <= 100; eld_stat which: 0 min, 1 max, 2 mean, 3 stddev, + * 4 count, 5 exceeds. */ +void scr_perf_loop_mark(void); +double scr_perf_loop_start(void); +double scr_perf_idle_time(void); +double scr_eld_new(double resolution); +bool scr_eld_enable(double handle); +bool scr_eld_disable(double handle); +void scr_eld_reset(double handle); +double scr_eld_percentile(double handle, double percentile); +double scr_eld_stat(double handle, double which); /* perf_hooks user timing (scr_perf.c): mark, measure, the getEntries * family and the clears take the call's dyn argument vector (borrowed) * and apply Node's validation and errors. mark and measure answer 1 and diff --git a/packages/runtime/src/scr_perf_loop.c b/packages/runtime/src/scr_perf_loop.c new file mode 100644 index 000000000..68d3bf10f --- /dev/null +++ b/packages/runtime/src/scr_perf_loop.c @@ -0,0 +1,327 @@ +/* node:perf_hooks event-loop metrics: performance.eventLoopUtilization() + * and monitorEventLoopDelay()'s IntervalHistogram. + * + * Event-loop utilization. Node measures idle time as the time its loop + * spends blocked in the poll phase. A compiled program's main thread is + * busy exactly while it runs on the CPU (or blocks in a synchronous call), + * so the thread's CPU time stands in for Node's active time: idle is the + * wall time since the loop started minus that CPU time. The loop start is + * marked by the emitted main just before the loop runs, and only in + * programs that ask for the metric; before it, utilization is all zeros, + * like Node during the main module's synchronous evaluation. + * + * Event-loop delay. Each histogram samples on an unref'd interval at its + * resolution and records the time between samples in nanoseconds, like + * Node's ELDHistogram (Histogram::RecordDelta). Values land in an + * HdrHistogram-shaped counts array (lowest 1, three significant figures: + * 2048 sub-buckets per power of two), so min, max, mean, stddev and + * percentiles answer the bucket values Node's hdr_histogram answers. */ + +#include "scr_runtime.h" + +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +/* ── event-loop utilization ─────────────────────────────────────────── */ + +static SCR_TL double scr_perf_loop_start_ms = 0; /* performance.now() at loop start */ +static SCR_TL double scr_perf_loop_cpu0_ms = 0; /* thread CPU time at loop start */ + +/* The calling thread's CPU time in milliseconds; 0 where unavailable. */ +static double scr_perf_thread_cpu_ms(void) { +#if defined(_WIN32) + FILETIME created, exited, kernel, user; + if (!GetThreadTimes(GetCurrentThread(), &created, &exited, &kernel, &user)) return 0; + ULARGE_INTEGER k, u; + k.LowPart = kernel.dwLowDateTime; + k.HighPart = kernel.dwHighDateTime; + u.LowPart = user.dwLowDateTime; + u.HighPart = user.dwHighDateTime; + return (double)(k.QuadPart + u.QuadPart) / 1e4; /* 100ns units */ +#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__wasi__) + struct timespec ts; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) return 0; + return (double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec / 1e6; +#else + return 0; +#endif +} + +void scr_perf_loop_mark(void) { + if (scr_perf_loop_start_ms > 0) return; + scr_perf_loop_cpu0_ms = scr_perf_thread_cpu_ms(); + double now = scr_perf_now(); + /* Node's loopStart is positive once set; a mark at the very first + * microsecond still counts as started. */ + scr_perf_loop_start_ms = now > 0 ? now : 1e-6; +} + +double scr_perf_loop_start(void) { return scr_perf_loop_start_ms; } + +double scr_perf_idle_time(void) { + if (scr_perf_loop_start_ms <= 0) return 0; + double wall = scr_perf_now() - scr_perf_loop_start_ms; + double busy = scr_perf_thread_cpu_ms() - scr_perf_loop_cpu0_ms; + double idle = wall - busy; + if (idle < 0) idle = 0; + if (idle > wall) idle = wall; + return idle; +} + +/* ── HdrHistogram-shaped counts (lowest 1, 3 significant figures) ───── */ + +#define SCR_HDR_SUB_BUCKET_HALF_MAG 10 +#define SCR_HDR_SUB_BUCKET_HALF (1 << SCR_HDR_SUB_BUCKET_HALF_MAG) /* 1024 */ +#define SCR_HDR_SUB_BUCKET_COUNT (SCR_HDR_SUB_BUCKET_HALF * 2) /* 2048 */ +#define SCR_HDR_SUB_BUCKET_MASK ((int64_t)SCR_HDR_SUB_BUCKET_COUNT - 1) + +typedef struct { + int64_t *counts; /* owned, grown on demand */ + size_t counts_len; + int64_t total; + int64_t min_value; /* INT64_MAX while empty */ + int64_t max_value; /* 0 while empty */ + double count; /* Node's count_ (successful records) */ + uint64_t prev_ns; /* RecordDelta's previous sample; 0 = none */ + double resolution; /* ms */ + double timer; /* the sampling interval's handle while enabled, else 0 */ + ScrClosure *tick; /* owned: the sampling callback, identifies this histogram */ + bool enabled; +} ScrEld; + +static int scr_hdr_bucket_index(int64_t value) { + int pow2ceiling = 64 - __builtin_clzll((uint64_t)(value | SCR_HDR_SUB_BUCKET_MASK)); + return pow2ceiling - (SCR_HDR_SUB_BUCKET_HALF_MAG + 1); +} + +static size_t scr_hdr_counts_index(int64_t value) { + int bucket = scr_hdr_bucket_index(value); + int64_t sub = value >> bucket; + return (size_t)(((int64_t)(bucket + 1) << SCR_HDR_SUB_BUCKET_HALF_MAG) + (sub - SCR_HDR_SUB_BUCKET_HALF)); +} + +static int64_t scr_hdr_value_at_index(size_t index) { + int bucket = (int)(index >> SCR_HDR_SUB_BUCKET_HALF_MAG) - 1; + int64_t sub = (int64_t)(index & (SCR_HDR_SUB_BUCKET_HALF - 1)) + SCR_HDR_SUB_BUCKET_HALF; + if (bucket < 0) { + sub -= SCR_HDR_SUB_BUCKET_HALF; + bucket = 0; + } + return sub << bucket; +} + +static int64_t scr_hdr_range_size(int64_t value) { + int bucket = scr_hdr_bucket_index(value); + int64_t sub = value >> bucket; + int adjusted = sub >= SCR_HDR_SUB_BUCKET_COUNT ? bucket + 1 : bucket; + return (int64_t)1 << adjusted; +} + +static int64_t scr_hdr_lowest_equivalent(int64_t value) { + int bucket = scr_hdr_bucket_index(value); + int64_t sub = value >> bucket; + return sub << bucket; +} + +static int64_t scr_hdr_highest_equivalent(int64_t value) { + return scr_hdr_lowest_equivalent(value) + scr_hdr_range_size(value) - 1; +} + +static int64_t scr_hdr_median_equivalent(int64_t value) { + return scr_hdr_lowest_equivalent(value) + (scr_hdr_range_size(value) >> 1); +} + +/* Newton's square root: keeps this unit free of a libm reference. */ +static double scr_eld_sqrt(double x) { + if (!(x > 0)) return x == 0 ? 0 : NAN; + double r = x >= 1 ? x : 1; + for (int i = 0; i < 64; i++) { + double next = 0.5 * (r + x / r); + if (next == r) break; + r = next; + } + return r; +} + +static void scr_eld_record(ScrEld *h, int64_t value) { + if (value < 0) return; + size_t index = scr_hdr_counts_index(value); + if (index >= h->counts_len) { + size_t len = h->counts_len ? h->counts_len : SCR_HDR_SUB_BUCKET_COUNT; + while (len <= index) len *= 2; + int64_t *grown = realloc(h->counts, len * sizeof(int64_t)); + if (grown == NULL) return; + for (size_t i = h->counts_len; i < len; i++) grown[i] = 0; + h->counts = grown; + h->counts_len = len; + } + h->counts[index]++; + h->total++; + if (value != 0 && value < h->min_value) h->min_value = value; + if (value > h->max_value) h->max_value = value; + h->count += 1; +} + +static void scr_eld_clear(ScrEld *h) { + for (size_t i = 0; i < h->counts_len; i++) h->counts[i] = 0; + h->total = 0; + h->min_value = INT64_MAX; + h->max_value = 0; + h->count = 0; + h->prev_ns = 0; +} + +/* ── monitorEventLoopDelay ──────────────────────────────────────────── */ + +static SCR_TL ScrEld **scr_elds; +static SCR_TL size_t scr_elds_len; + +static ScrEld *scr_eld_of(double handle) { + if (!(handle >= 1) || handle > (double)scr_elds_len) return NULL; + return scr_elds[(size_t)handle - 1]; +} + +static void scr_eld_tick(ScrClosure *self) { + for (size_t i = 0; i < scr_elds_len; i++) { + ScrEld *h = scr_elds[i]; + if (h->tick != self) continue; + uint64_t now = scr_hrtime_ns(); + if (h->prev_ns > 0 && now > h->prev_ns) scr_eld_record(h, (int64_t)(now - h->prev_ns)); + h->prev_ns = now; + return; + } +} + +/* Histograms live for the thread's lifetime (Node frees them with their + * JS object); release them when the script ends so their callbacks and + * counts do not outlive it. */ +static void scr_eld_cleanup(void) { + for (size_t i = 0; i < scr_elds_len; i++) { + ScrEld *h = scr_elds[i]; + scr_closure_release(h->tick); + free(h->counts); + free(h); + } + free(scr_elds); + scr_elds = NULL; + scr_elds_len = 0; +} + +/* Node's validateInteger(resolution, 'options.resolution', 1): a catchable + * RangeError (ERR_OUT_OF_RANGE) for a non-integer or a value out of range, + * with the value as util.inspect renders it ("-0" included). */ +static bool scr_eld_resolution_ok(double resolution) { + bool integer = isfinite(resolution) && trunc(resolution) == resolution; + if (integer && resolution >= 1 && resolution <= 9007199254740991.0) return true; + char received[48]; + if (resolution == 0 && signbit(resolution)) + memcpy(received, "-0", 3); + else + scr_num_received(resolution, received); + char msg[192]; + int len = snprintf(msg, sizeof msg, + "The value of \"options.resolution\" is out of range. It must be %s. Received %s", + integer ? ">= 1 && <= 9007199254740991" : "an integer", received); + scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)len, "ERR_OUT_OF_RANGE"); + return false; +} + +double scr_eld_new(double resolution) { + if (!scr_eld_resolution_ok(resolution)) return 0; + if (scr_elds_len == 0 && scr_elds == NULL) scr_atexit(scr_eld_cleanup); + ScrEld *h = calloc(1, sizeof(ScrEld)); + ScrEld **grown = realloc(scr_elds, (scr_elds_len + 1) * sizeof(ScrEld *)); + if (h == NULL || grown == NULL) { + free(h); + if (grown != NULL) scr_elds = grown; + return 0; + } + scr_elds = grown; + h->min_value = INT64_MAX; + h->resolution = resolution; + h->tick = scr_closure_new((void *)scr_eld_tick, 0); + scr_elds[scr_elds_len++] = h; + return (double)scr_elds_len; +} + +bool scr_eld_enable(double handle) { + ScrEld *h = scr_eld_of(handle); + if (h == NULL || h->enabled) return false; + h->enabled = true; + h->timer = scr_set_interval(scr_closure_retain(h->tick), h->resolution); + scr_timer_unref(h->timer); + return true; +} + +bool scr_eld_disable(double handle) { + ScrEld *h = scr_eld_of(handle); + if (h == NULL || !h->enabled) return false; + h->enabled = false; + scr_clear_interval(h->timer); + h->timer = 0; + return true; +} + +void scr_eld_reset(double handle) { + ScrEld *h = scr_eld_of(handle); + if (h != NULL) scr_eld_clear(h); +} + +/* hdr_value_at_percentile; the compiler checked Node's 0 < p <= 100 range. */ +double scr_eld_percentile(double handle, double percentile) { + ScrEld *h = scr_eld_of(handle); + if (h == NULL || h->total == 0) return 0; + double requested = percentile < 100.0 ? percentile : 100.0; + int64_t wanted = (int64_t)((requested / 100.0) * (double)h->total + 0.5); + if (wanted < 1) wanted = 1; + int64_t seen = 0; + for (size_t i = 0; i < h->counts_len; i++) { + seen += h->counts[i]; + if (seen >= wanted) return (double)scr_hdr_highest_equivalent(scr_hdr_value_at_index(i)); + } + return 0; +} + +/* which: 0 min, 1 max, 2 mean, 3 stddev, 4 count, 5 exceeds. */ +double scr_eld_stat(double handle, double which) { + ScrEld *h = scr_eld_of(handle); + int w = (int)which; + if (h == NULL) return w == 0 ? (double)INT64_MAX : w >= 2 && w <= 3 ? NAN : 0; + switch (w) { + case 0: + if (h->counts_len > 0 && h->counts[0] > 0) return 0; + return h->min_value == INT64_MAX ? (double)INT64_MAX + : (double)scr_hdr_lowest_equivalent(h->min_value); + case 1: + return h->max_value == 0 ? 0 : (double)scr_hdr_highest_equivalent(h->max_value); + case 2: + case 3: { + if (h->total == 0) return NAN; + double sum = 0; + for (size_t i = 0; i < h->counts_len; i++) { + if (h->counts[i] == 0) continue; + sum += (double)h->counts[i] * (double)scr_hdr_median_equivalent(scr_hdr_value_at_index(i)); + } + double mean = sum / (double)h->total; + if (w == 2) return mean; + double geo = 0; + for (size_t i = 0; i < h->counts_len; i++) { + if (h->counts[i] == 0) continue; + double dev = (double)scr_hdr_median_equivalent(scr_hdr_value_at_index(i)) - mean; + geo += dev * dev * (double)h->counts[i]; + } + return scr_eld_sqrt(geo / (double)h->total); + } + case 4: + return h->count; + default: + return 0; + } +} diff --git a/packages/runtime/src/scr_runtime.h b/packages/runtime/src/scr_runtime.h index 59cafe208..bf01a4a9b 100644 --- a/packages/runtime/src/scr_runtime.h +++ b/packages/runtime/src/scr_runtime.h @@ -75,5 +75,7 @@ #include "scr_assert.h" #include "scr_console.h" #include "scr_fs_cp.h" +#include "scr_wasm_abi.h" +#include "scr_wasm.h" #endif /* SCR_RUNTIME_H */ diff --git a/packages/runtime/src/scr_stream.c b/packages/runtime/src/scr_stream.c index 5f0bb493d..56f9fd54b 100644 --- a/packages/runtime/src/scr_stream.c +++ b/packages/runtime/src/scr_stream.c @@ -6451,8 +6451,10 @@ static ScrDyn *scr_stream_view_call(ScrClosure *cb, ScrDyn *const *args, size_t end = option->kind == SCR_DYN_UNDEF || scr_dyn_truthy(option); scr_dyn_release(option); } + /* scr_stream_pipe_general: a JavaScript caller can pipe into the + * converted process.stdout / process.stderr, which a pipe never ends. */ ScrStream *returned = !strcmp(method, "pipe") - ? scr_stream_pipe(stream, destination, end) : scr_stream_unpipe(stream, destination); + ? scr_stream_pipe_general(stream, destination, end) : scr_stream_unpipe(stream, destination); scr_stream_release(returned); if (!strcmp(method, "pipe") && !scr_exc_pending()) result = scr_dyn_retain(first); } @@ -6619,3 +6621,104 @@ ScrStream *scr_crypto_hash_stream_piped(ScrCryptoHash *hash) { if (s) scr_crypto_hash_stream_hold(hash); return s; } + +/* ── the compiler's general stream representation ───────────────────── + * NodeJS.ReadableStream / NodeJS.WritableStream slots that also hold other + * streams compile as this unit's classes; the stdio handles convert into + * them where they are read or flow. Both entry points sit last in the unit + * and reference only global symbols and no new constant data, so programs + * that never convert link the same bytes as before. */ + +/* destroy() on a bridged child stdin closes the pipe, as Node's does. */ +static void scr_stream_child_stdin_destroy(ScrClosure *cb, ScrStream *s, ScrError *err) { + ScrChildWriter *writer = scr_box_get_ref(cb->caps[0]); + scr_child_writer_destroy(writer); + scr_child_writer_release(writer); + scr_stream_destroy_done(s, err ? scr_error_retain(err) : NULL); +} + +/* A child stdio read (the child.stdioStream libCall): the bridged stream + * the checked-dynamic ChildProcess view answers for the same key ("stdin", + * "stdout" or "stderr", passed by the compiled program), so both views + * share one stream per slot. The stdin stream (the only five-byte key) + * gains the destroy hook that closes the pipe. +1, or NULL for an unpiped + * slot or a throw. */ +ScrStream *scr_stream_child_stdio(void *child, const char *key, size_t key_len) { + ScrDyn *handle = scr_dyn_new_handle(child, SCR_DYNH_CHILD); + ScrDyn *box = scr_dyn_handle_ops_of(handle)->get(child, key, key_len); + scr_dyn_release(handle); + if (box == NULL) return NULL; + ScrStream *stream = box->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_unbox(box) : NULL; + scr_dyn_release(box); + if (stream != NULL && key_len == 5 && stream->st->destroy_cb == NULL) { + ScrChildWriter *writer = scr_child_stdin(child); + if (writer != NULL) { + ScrClosure *destroy = scr_closure_new((void *)scr_stream_child_stdin_destroy, 1); + destroy->caps[0] = scr_box_new_obj(scr_child_writer_retain_v, scr_child_writer_release_v, NULL); + scr_box_set_ref(destroy->caps[0], writer); + stream->st->destroy_cb = destroy; + stream->st->destroy_inv = scr_stream_child_stdin_destroy; + } + } + return stream; +} + +/* process.stdout / process.stderr flowing into a Writable slot (the + * stream.stdioWritable libCall): a Writable whose _write hands each chunk + * to the descriptor through process.stdout.write's synchronous path and + * completes at once, so ordering against console output and direct writes + * is unchanged. The closure keeps the fd as given (1 or 2). Each thread + * keeps one per descriptor, so every conversion of process.stdout answers + * the same stream, as Node's process.stdout is one object: listeners, + * writable state and identity are shared. The cache is released at exit. */ +static SCR_TL ScrStream *scr_stream_stdio_writables[2]; +static void scr_stream_stdio_write(ScrClosure *cb, ScrStream *s, ScrBytes *chunk) { + int fd = (int)scr_box_get_f64(cb->caps[0]); + (void)scr_stdio_write(fd == 2 ? 2 : 1, chunk->data, chunk->len * scr_bytes_elem_size(chunk->elem)); + scr_stream_write_done(s, NULL); +} +static void scr_stream_stdio_writables_free(void) { + for (int i = 0; i < 2; i++) { + ScrStream *s = scr_stream_stdio_writables[i]; + scr_stream_stdio_writables[i] = NULL; + if (s) scr_stream_release(s); + } +} +ScrStream *scr_stream_stdio_writable(double fd) { + int i = fd == 2 ? 1 : 0; + if (scr_stream_stdio_writables[i] == NULL) { + if (scr_stream_stdio_writables[1 - i] == NULL) scr_atexit(scr_stream_stdio_writables_free); + ScrClosure *write = scr_closure_new((void *)scr_stream_stdio_write, 1); + write->caps[0] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(write->caps[0], i ? 2 : 1); + scr_stream_stdio_writables[i] = scr_stream_new_writable(-1, true, true, write, + scr_stream_stdio_write, NULL, NULL, NULL, NULL); + } + return scr_stream_retain(scr_stream_stdio_writables[i]); +} + +/* readable.pipe() into a Writable slot under the general representation + * (the readable.pipeGeneral libCall), and pipe() called from JavaScript on + * a native stream: Node never ends process.stdout or process.stderr from a + * pipe, so their converted Writable keeps `end` off. */ +ScrStream *scr_stream_pipe_general(ScrStream *src, ScrStream *dst, bool end) { + if (dst == scr_stream_stdio_writables[0] || dst == scr_stream_stdio_writables[1]) end = false; + return scr_stream_pipe(src, dst, end); +} + +/* A pipeline() stage that arrives as a checked-dynamic value (the + * stream.unboxDyn libCall): a boxed native stream unwraps by identity + * (+1); any other value throws the compiled program's not-supported + * message (Node also takes iterables and functions there). */ +ScrStream *scr_stream_unbox_dyn(const ScrDyn *value, const ScrStr *message) { + if (value->kind == SCR_DYN_TYPED_REF && value->v.typed_ref.type_key_len > 7 && + !memcmp(value->v.typed_ref.type_key, "object:", 7)) { + ScrStream *stream = scr_dyn_typed_ref_unbox(value); + const ScrVt *vt = stream->vt; + if ((vt->pre >= scr_readable_vt.pre && vt->pre <= scr_readable_vt.post) || + (vt->pre >= scr_writable_vt.pre && vt->pre <= scr_writable_vt.post)) return stream; + value->v.typed_ref.release(stream); + } + scr_throw_error_msg_code(SCR_ERR_ERROR, message->data, message->len, "SC2020"); + return NULL; +} diff --git a/packages/runtime/src/scr_stream.h b/packages/runtime/src/scr_stream.h index 82727c1dc..69da3dc0e 100644 --- a/packages/runtime/src/scr_stream.h +++ b/packages/runtime/src/scr_stream.h @@ -125,6 +125,17 @@ void scr_stream_init_passthrough(ScrStream *s, double rhwm, double whwm, bool au ScrStream *scr_stream_new_readable_dyn(struct ScrDyn *opts); void scr_stream_worker_stdio(void); ScrStream *scr_stream_new_writable_dyn(struct ScrDyn *opts); +/* The general stream representation's conversions (+1): a child's bridged + * stdio stream by key (NULL when unpiped), and process.stdout/stderr as a + * Writable (fd 1 or 2). */ +ScrStream *scr_stream_child_stdio(void *child, const char *key, size_t key_len); +ScrStream *scr_stream_stdio_writable(double fd); +/* readable.pipe() under the general representation: a converted + * process.stdout / process.stderr destination is never ended (dst +1). */ +ScrStream *scr_stream_pipe_general(ScrStream *src, ScrStream *dst, bool end); +/* A boxed native stream out of a checked-dynamic pipeline stage (+1), or + * NULL with `message` thrown as the not-supported Error. */ +ScrStream *scr_stream_unbox_dyn(const struct ScrDyn *value, const ScrStr *message); ScrStream *scr_stream_new_duplex_dyn(struct ScrDyn *opts); ScrStream *scr_stream_new_transform_dyn(struct ScrDyn *opts); ScrStream *scr_stream_new_passthrough_dyn(struct ScrDyn *opts); diff --git a/packages/runtime/src/scr_wasm.c b/packages/runtime/src/scr_wasm.c new file mode 100644 index 000000000..8f9244c28 --- /dev/null +++ b/packages/runtime/src/scr_wasm.c @@ -0,0 +1,2531 @@ +/* The JavaScript WebAssembly API over modules translated to native code + * when the program was built (scr_wasm_abi.h is the contract with the + * translator). + * + * WebAssembly.compile, instantiate, validate and new Module hash the bytes + * they are given and look the module up by SHA-256 and length in + * scr_wasm_registry, which the compiler emits; bytes that were not + * translated at build time reject with a CompileError that says so. + * Nothing is interpreted or compiled at run time, and a translated + * module's bytes were validated when the program was built. + * + * Values: Module, Instance, Memory, Table and Global are native handles in + * the checked-dynamic representation (the SCR_DYNH_WASM_* tags, installed + * per thread on first use). An instance's exports object is a frozen + * null-prototype object whose functions call the translated code through + * its thunks under a trap guard; imports are checked-dynamic callables + * called with `this` undefined, ToJSValue arguments and ToWebAssemblyValue + * results. + * + * Traps. Translated code calls scr_wasm_trap, which siglongjmps to the + * innermost export entry (scr_wasm_enter); the entry throws Node's + * WebAssembly.RuntimeError. With guard pages, an out-of-bounds access + * faults inside the memory's reservation and stack exhaustion faults near + * the stack pointer: the SIGSEGV/SIGBUS handler (installed when the first + * guarded instance is created, on a per-thread alternate stack, chaining + * to the previous handler for every other fault) moves the interrupted + * context to a trampoline that traps the same way, so the handler itself + * returns normally. Async fibers' stacks have no guard page of their own, + * so the first export call on one protects the lowest page of its mapping + * (scr_wasm_guard_fiber). An exception thrown by an import unwinds the + * translated frames the same way and propagates unchanged. Translated + * frames own nothing, so abandoning them leaks nothing; the module's own + * shadow stack pointer is not restored, exactly as in V8. + * + * The error classes are Errors whose inherited name is CompileError, + * LinkError or RuntimeError (not an own property, as in Node), which is + * the brand instanceof tests. + * + * The Memory, Table and Global constructors build the same objects an + * instance exports, so either kind can be imported; WebAssembly.Module. + * imports, exports and customSections read the descriptor. + * + * Gaps (results/opt-wasm-design/DESIGN.md, stages W6-W9): Memory.grow + * does not detach the previous ArrayBuffer (the memory never moves with + * guard pages, and explicit-bounds memories keep their previous blocks, so + * old views stay valid with their old length); shared memories are not + * constructed; instances, their imports and exports are never freed (the + * cycle collector does not trace them yet). */ +#if !defined(_GNU_SOURCE) && defined(__linux__) +#define _GNU_SOURCE /* REG_RIP and friends in */ +#endif +#include "scr_runtime.h" +#include "scr_wasm_abi.h" + +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +#if !defined(_WIN32) +#define SCR_WASM_SIGNALS 1 +#include +#include +#include +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define SCR_WASM_ASAN 1 +#endif +#endif +#if !defined(SCR_WASM_ASAN) && defined(__SANITIZE_ADDRESS__) +#define SCR_WASM_ASAN 1 +#endif + +ScrPromise *scr_wasm_compile(ScrDyn *bytes); +bool scr_wasm_validate(ScrDyn *bytes); +ScrPromise *scr_wasm_instantiate(ScrDyn *source, ScrDyn *imports); +ScrDyn *scr_wasm_module_new(ScrDyn *bytes); +ScrDyn *scr_wasm_instance_new(ScrDyn *module, ScrDyn *imports); +bool scr_wasm_is(const ScrDyn *value, double kind); +ScrDyn *scr_wasm_error_new(double kind, ScrDyn *message, ScrDyn *options); +ScrDyn *scr_wasm_function(double kind); +ScrDyn *scr_wasm_namespace(void); +ScrDyn *scr_wasm_global_view(void); +ScrDyn *scr_wasm_memory_construct(ScrDyn *descriptor); +ScrDyn *scr_wasm_table_construct(ScrDyn *descriptor, ScrDyn *value); +ScrDyn *scr_wasm_global_construct(ScrDyn *descriptor, ScrDyn *value); +ScrDyn *scr_wasm_construct_without_new(double kind, ScrDyn *arg0, ScrDyn *arg1); +ScrDyn *scr_wasm_module_imports(ScrDyn *module); +ScrDyn *scr_wasm_module_exports(ScrDyn *module); +ScrDyn *scr_wasm_module_custom_sections(ScrDyn *module, ScrDyn *name); +ScrDyn *scr_wasm_value_of(ScrDyn *value); + +/* Entry points of translated code. */ +/* Sanitized builds do not declare it noreturn: AddressSanitizer would + * call __asan_handle_no_return before every call, which warns on the + * runtime's async fibers. */ +#ifdef SCR_WASM_ASAN +void scr_wasm_trap(int32_t code); +#else +_Noreturn void scr_wasm_trap(int32_t code); +#endif +void scr_wasm_import_call(void *host, int32_t index, const uint64_t *args, uint64_t *results); +int32_t scr_wasm_memory_grow(void *inst, int32_t delta); +void scr_wasm_memory_fill(void *inst, int32_t d, int32_t value, int32_t n); +void scr_wasm_memory_copy(void *inst, int32_t d, int32_t s, int32_t n); +void scr_wasm_memory_init(void *inst, int32_t seg, int32_t d, int32_t s, int32_t n); +void scr_wasm_data_drop(void *inst, int32_t seg); +void *scr_wasm_table_get(void *inst, int32_t t, int32_t i); +void scr_wasm_table_set(void *inst, int32_t t, int32_t i, void *value); +int32_t scr_wasm_table_grow(void *inst, int32_t t, void *init, int32_t n); +void scr_wasm_table_fill(void *inst, int32_t t, int32_t i, void *value, int32_t n); +void scr_wasm_table_copy(void *inst, int32_t dt, int32_t st, int32_t d, int32_t s, int32_t n); +void scr_wasm_table_init(void *inst, int32_t t, int32_t seg, int32_t d, int32_t s, int32_t n); +void scr_wasm_elem_drop(void *inst, int32_t seg); +void scr_wasm_global_set_ref(void *cell, void *value); + +#define SCR_WASM_PAGE 65536u +#define SCR_WASM_MAX_PAGES 65536u +#define SCR_WASM_MAX_TABLE 10000000u +/* Every `base + zext(i32) + offset(u32) + size` the translated code can + * form stays inside this reservation, so an access past the memory faults + * on a PROT_NONE page instead of reaching other mappings. */ +#define SCR_WASM_GUARD_RESERVATION ((uint64_t)8 << 30 | (uint64_t)SCR_WASM_PAGE) + +/* ── instance state ──────────────────────────────────────────────────── */ + +typedef struct ScrWasmInst { + size_t rc; + const ScrWasmModuleDesc *desc; + void **inst; /* the translated code's instance (layout in scr_wasm_abi.h) */ + ScrDyn **funcs; /* imported function values, by function index */ + ScrWasmMemory *memory; + ScrWasmTable **tables; + ScrWasmGlobal **globals; + ScrWasmFuncRef *funcrefs; + ScrDyn **export_fns; /* exported function values, by function index (lazy) */ + char **export_names; + bool *data_dropped; + bool *elem_dropped; + ScrDyn *exports; + /* The Memory, Table and Global objects of the instance, by index: the + * imported object itself, or the one created when the module exports it, + * so every export of the same index is the same object, as in V8. */ + ScrDyn *memory_obj; + ScrDyn **table_objs; + ScrDyn **global_objs; +} ScrWasmInst; + +static ScrWasmInst *scr_wasm_host_of(void *inst) { return ((ScrWasmInst **)inst)[0]; } + +#ifdef SCR_RC_AUDIT +/* Instances are never freed yet (stage W6), so the sanitized lane's RC + * audit would report everything they hold. Audited builds tear every + * instance down at exit instead. */ +static SCR_TL ScrWasmInst **scr_wasm_hosts; +static SCR_TL size_t scr_wasm_host_count, scr_wasm_host_cap; +static void scr_wasm_teardown(void); + +static void scr_wasm_note_host(ScrWasmInst *host) { + if (scr_wasm_host_count == 0 && scr_wasm_host_cap == 0) scr_atexit(scr_wasm_teardown); + if (scr_wasm_host_count == scr_wasm_host_cap) { + size_t cap = scr_wasm_host_cap ? scr_wasm_host_cap * 2 : 8; + ScrWasmInst **grown = realloc(scr_wasm_hosts, cap * sizeof *grown); + if (!grown) scr_trap("scriptc: out of memory\n"); + scr_wasm_hosts = grown; + scr_wasm_host_cap = cap; + } + scr_wasm_hosts[scr_wasm_host_count++] = host; +} +#endif + +/* ── SHA-256 (FIPS 180-4) ────────────────────────────────────────────── */ + +typedef struct { + uint32_t h[8]; +} ScrWasmSha; + +static const uint32_t scr_wasm_sha_k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +static uint32_t scr_wasm_rotr(uint32_t x, unsigned n) { return (x >> n) | (x << (32 - n)); } + +static void scr_wasm_sha_block(ScrWasmSha *s, const uint8_t *p) { + uint32_t w[64]; + for (int i = 0; i < 16; i++) + w[i] = (uint32_t)p[4 * i] << 24 | (uint32_t)p[4 * i + 1] << 16 | (uint32_t)p[4 * i + 2] << 8 | p[4 * i + 3]; + for (int i = 16; i < 64; i++) { + uint32_t s0 = scr_wasm_rotr(w[i - 15], 7) ^ scr_wasm_rotr(w[i - 15], 18) ^ (w[i - 15] >> 3); + uint32_t s1 = scr_wasm_rotr(w[i - 2], 17) ^ scr_wasm_rotr(w[i - 2], 19) ^ (w[i - 2] >> 10); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + uint32_t a = s->h[0], b = s->h[1], c = s->h[2], d = s->h[3], e = s->h[4], f = s->h[5], g = s->h[6], h = s->h[7]; + for (int i = 0; i < 64; i++) { + uint32_t t1 = h + (scr_wasm_rotr(e, 6) ^ scr_wasm_rotr(e, 11) ^ scr_wasm_rotr(e, 25)) + ((e & f) ^ (~e & g)) + + scr_wasm_sha_k[i] + w[i]; + uint32_t t2 = (scr_wasm_rotr(a, 2) ^ scr_wasm_rotr(a, 13) ^ scr_wasm_rotr(a, 22)) + ((a & b) ^ (a & c) ^ (b & c)); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + s->h[0] += a; + s->h[1] += b; + s->h[2] += c; + s->h[3] += d; + s->h[4] += e; + s->h[5] += f; + s->h[6] += g; + s->h[7] += h; +} + +static void scr_wasm_sha256(const uint8_t *data, size_t len, uint8_t out[32]) { + ScrWasmSha s = {{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}}; + size_t i = 0; + for (; i + 64 <= len; i += 64) scr_wasm_sha_block(&s, data + i); + uint8_t tail[128] = {0}; + size_t rest = len - i; + if (rest) memcpy(tail, data + i, rest); + tail[rest] = 0x80; + size_t total = rest + 1 + 8 <= 64 ? 64 : 128; + uint64_t bits = (uint64_t)len * 8; + for (int k = 0; k < 8; k++) tail[total - 1 - k] = (uint8_t)(bits >> (8 * k)); + scr_wasm_sha_block(&s, tail); + if (total == 128) scr_wasm_sha_block(&s, tail + 64); + for (int k = 0; k < 8; k++) { + out[4 * k] = (uint8_t)(s.h[k] >> 24); + out[4 * k + 1] = (uint8_t)(s.h[k] >> 16); + out[4 * k + 2] = (uint8_t)(s.h[k] >> 8); + out[4 * k + 3] = (uint8_t)s.h[k]; + } +} + +/* ── errors ──────────────────────────────────────────────────────────── */ + +enum { SCR_WASM_COMPILE_ERROR, SCR_WASM_LINK_ERROR, SCR_WASM_RUNTIME_ERROR }; +static const char *const scr_wasm_error_names[] = {"CompileError", "LinkError", "RuntimeError"}; + +/* A WebAssembly error: an Error whose inherited (not own) name is the + * class's. Borrows message. +1. */ +static ScrError *scr_wasm_error_make(int which, ScrStr *message) { + ScrError *e = scr_error_new(SCR_ERR_ERROR, message); + scr_str_release(e->name); + const char *name = scr_wasm_error_names[which]; + e->name = scr_str_new(name, strlen(name)); + e->name_present = false; + return e; +} + +static void scr_wasm_throw_kind(int which, const char *msg) { + ScrStr *s = scr_str_new(msg, strlen(msg)); + ScrError *e = scr_wasm_error_make(which, s); + scr_str_release(s); + scr_throw_obj(e, &scr_error_retain_v, &scr_error_release_v, scr_error_trace_arg()); +} + +static int scr_wasm_error_brand(const ScrError *e) { + if (!e || e->vt != &scr_error_vts[SCR_ERR_ERROR] || e->name_present || !e->name) return -1; + for (int i = 0; i < 3; i++) { + size_t n = strlen(scr_wasm_error_names[i]); + if (e->name->len == n && !memcmp(e->name->data, scr_wasm_error_names[i], n)) return i; + } + return -1; +} + +static void scr_wasm_type_error(const char *msg) { scr_throw_error_msg(SCR_ERR_TYPE, msg, strlen(msg)); } +static void scr_wasm_range_error(const char *msg) { scr_throw_error_msg(SCR_ERR_RANGE, msg, strlen(msg)); } + +static const char *scr_wasm_trap_message(int code) { + switch (code) { + case SCR_WASM_TRAP_MEMORY_OOB: return "memory access out of bounds"; + case SCR_WASM_TRAP_DIV_BY_ZERO: return "divide by zero"; + case SCR_WASM_TRAP_DIV_UNREPRESENTABLE: return "divide result unrepresentable"; + case SCR_WASM_TRAP_REM_BY_ZERO: return "remainder by zero"; + case SCR_WASM_TRAP_FLOAT_UNREPRESENTABLE: return "float unrepresentable in integer range"; + case SCR_WASM_TRAP_TABLE_OOB: return "table index is out of bounds"; + case SCR_WASM_TRAP_SIGNATURE: return "null function or function signature mismatch"; + case SCR_WASM_TRAP_NULL: return "dereferencing a null pointer"; + case SCR_WASM_TRAP_ELEM_SEGMENT: return "element segment out of bounds"; + default: return "unreachable"; + } +} + +/* Throws the JavaScript error for a trap code (nothing for HOST: its + * exception is already pending). */ +static void scr_wasm_throw_trap(int code) { + if (code == SCR_WASM_TRAP_HOST) return; + if (code == SCR_WASM_TRAP_EXHAUSTION) { + scr_wasm_range_error("Maximum call stack size exceeded"); + return; + } + scr_wasm_throw_kind(SCR_WASM_RUNTIME_ERROR, scr_wasm_trap_message(code)); +} + +/* ── the trap guard ──────────────────────────────────────────────────── */ + +/* AddressSanitizer intercepts siglongjmp and warns when it cannot tell the + * extent of the running stack, as on the runtime's async fibers. Sanitized + * builds therefore jump with the compiler's builtin pair, which no runtime + * intercepts, and unpoison the abandoned frames themselves. */ +#ifdef SCR_WASM_ASAN +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +typedef void *ScrWasmJmp[5]; +#define SCR_WASM_SETJMP(buf) __builtin_setjmp(buf) +#define SCR_WASM_LONGJMP(buf) __builtin_longjmp(buf, 1) +#elif defined(_WIN32) +typedef jmp_buf ScrWasmJmp; +#define SCR_WASM_SETJMP(buf) setjmp(buf) +#define SCR_WASM_LONGJMP(buf) longjmp(buf, 1) +#else +typedef sigjmp_buf ScrWasmJmp; +#define SCR_WASM_SETJMP(buf) sigsetjmp(buf, 0) +#define SCR_WASM_LONGJMP(buf) siglongjmp(buf, 1) +#endif + +typedef struct ScrWasmEntry { + ScrWasmJmp jmp; + struct ScrWasmEntry *prev; + uintptr_t frame; /* the entry's frame address: exhaustion resumes below it */ +} ScrWasmEntry; + +/* Thread-local in every build: each thread runs its own instances, and + * the fault handler reads them. */ +static _Thread_local ScrWasmEntry *scr_wasm_top; +static _Thread_local bool scr_wasm_running; /* translated code (not an import) is on top */ +static _Thread_local int scr_wasm_trap_code; + +/* Externref values an import returned: translated code holds them without + * a reference, so they stay alive until the outermost export call + * returns. */ +static _Thread_local ScrDyn **scr_wasm_kept; +static _Thread_local size_t scr_wasm_kept_count, scr_wasm_kept_cap; + +static void scr_wasm_keep(ScrDyn *d) { + if (scr_wasm_kept_count == scr_wasm_kept_cap) { + size_t cap = scr_wasm_kept_cap ? scr_wasm_kept_cap * 2 : 16; + ScrDyn **grown = realloc(scr_wasm_kept, cap * sizeof *grown); + if (!grown) scr_trap("scriptc: out of memory\n"); + scr_wasm_kept = grown; + scr_wasm_kept_cap = cap; + } + scr_wasm_kept[scr_wasm_kept_count++] = scr_dyn_retain(d); +} + +static void scr_wasm_release_kept(void) { + while (scr_wasm_kept_count) scr_dyn_release(scr_wasm_kept[--scr_wasm_kept_count]); +} + +#ifdef SCR_WASM_ASAN +/* Uninstrumented, so the sanitizer inserts no __asan_handle_no_return + * before the jump; the abandoned frames are unpoisoned below. */ +__attribute__((no_sanitize("address"))) +#else +_Noreturn +#endif +void scr_wasm_trap(int32_t code) { + ScrWasmEntry *top = scr_wasm_top; + if (!top) scr_trap("scriptc: WebAssembly trap outside an export call\n"); + scr_wasm_running = false; + scr_wasm_trap_code = code; +#ifdef SCR_WASM_ASAN + /* The real frame address: a local's address may be on the sanitizer's + * fake stack. */ + uintptr_t low = ((uintptr_t)__builtin_frame_address(0) & ~(uintptr_t)15) - 256; + if (top->frame > low && top->frame - low < ((uintptr_t)256 << 20)) + __asan_unpoison_memory_region((void *)low, top->frame - low); +#endif + SCR_WASM_LONGJMP(top->jmp); +} + +#if SCR_WASM_SIGNALS +static void scr_wasm_thread_init(void); +static void scr_wasm_guard_fiber(uintptr_t frame); +#endif + +/* Code with explicit bounds checks: the lowest stack address translated + * code may use before it traps with stack exhaustion (translate.ts checks + * it in the entry of every function through which the stack can grow + * without bound): the runtime's own stack guard for the running stack + * (thread or async fiber), read at each outermost export call. */ +_Thread_local uint64_t scr_wasm_stack_limit; + +static void scr_wasm_set_stack_limit(void) { +#if !defined(_WIN32) && !defined(__wasi__) + if (!scr_stack_guard) scr_stack_guard_init(); + scr_wasm_stack_limit = scr_stack_guard; +#endif +} + +/* Calls a thunk (or `call` on `code`, a function reference's code) with + * traps caught; answers a SCR_WASM_TRAP_* code. */ +static __attribute__((noinline)) int scr_wasm_enter_ref(ScrWasmThunk fn, ScrWasmCallThunk call, void *ref_code, + void *inst, const uint64_t *args, uint64_t *results) { +#if SCR_WASM_SIGNALS + scr_wasm_thread_init(); +#endif + ScrWasmEntry entry; + entry.prev = scr_wasm_top; + entry.frame = (uintptr_t)__builtin_frame_address(0); + if (!entry.prev) { + scr_wasm_set_stack_limit(); +#if SCR_WASM_SIGNALS + scr_wasm_guard_fiber(entry.frame); +#endif + } + bool was_running = scr_wasm_running; + scr_wasm_top = &entry; + int code = 0; + if (SCR_WASM_SETJMP(entry.jmp) == 0) { + scr_wasm_running = true; + if (call) call(ref_code, inst, args, results); + else fn(inst, args, results); + } else { + code = scr_wasm_trap_code; + } + scr_wasm_running = was_running; + scr_wasm_top = entry.prev; + return code; +} + +static int scr_wasm_enter(ScrWasmThunk fn, void *inst, const uint64_t *args, uint64_t *results) { + return scr_wasm_enter_ref(fn, NULL, NULL, inst, args, results); +} + +/* Called by each caller of scr_wasm_enter once it has converted the + * call's results: after the outermost call, the references kept for it + * (import results, and references a table or global replaced while the + * guest could still hold them) are released. The results' externrefs are + * borrowed from that list until then. */ +static void scr_wasm_leave(void) { + if (!scr_wasm_top && scr_wasm_kept_count) scr_wasm_release_kept(); +} + +static void scr_wasm_init_thunk(void *inst, const uint64_t *args, uint64_t *results) { + (void)args; + (void)results; + scr_wasm_host_of(inst)->desc->init(inst); +} + +static void scr_wasm_start_thunk(void *inst, const uint64_t *args, uint64_t *results) { + (void)args; + (void)results; + scr_wasm_host_of(inst)->desc->start(inst); +} + +/* ── memories and the fault handler ──────────────────────────────────── */ + +#if SCR_WASM_SIGNALS +/* Reservations of this thread's guarded memories, read by the fault + * handler (faults are synchronous, so nothing changes under it). */ +typedef struct { + uintptr_t start, end; +} ScrWasmRange; +static _Thread_local ScrWasmRange *scr_wasm_ranges; +static _Thread_local size_t scr_wasm_range_count, scr_wasm_range_cap; +static _Thread_local bool scr_wasm_altstack_ready; + +static struct sigaction scr_wasm_prev_segv, scr_wasm_prev_bus; +static pthread_once_t scr_wasm_handler_once = PTHREAD_ONCE_INIT; +static bool scr_wasm_handler_installed; + +static void scr_wasm_range_add(uint8_t *base, uint64_t len) { + if (scr_wasm_range_count == scr_wasm_range_cap) { + size_t cap = scr_wasm_range_cap ? scr_wasm_range_cap * 2 : 8; + ScrWasmRange *grown = realloc(scr_wasm_ranges, cap * sizeof *grown); + if (!grown) scr_trap("scriptc: out of memory\n"); + scr_wasm_ranges = grown; + scr_wasm_range_cap = cap; + } + scr_wasm_ranges[scr_wasm_range_count++] = (ScrWasmRange){(uintptr_t)base, (uintptr_t)base + len}; +} + +static void scr_wasm_range_remove(uint8_t *base) { + for (size_t i = 0; i < scr_wasm_range_count; i++) { + if (scr_wasm_ranges[i].start == (uintptr_t)base) { + scr_wasm_ranges[i] = scr_wasm_ranges[--scr_wasm_range_count]; + return; + } + } +} + +static _Noreturn __attribute__((noinline, used)) void scr_wasm_fault_trampoline(int32_t code) { + scr_wasm_trap(code); + __builtin_unreachable(); +} + +/* Moves the interrupted context to scr_wasm_fault_trampoline(code). With + * `stack` nonzero the trampoline runs at that stack address (exhaustion); + * otherwise below the interrupted stack pointer. */ +static bool scr_wasm_redirect(void *context, int32_t code, uintptr_t stack) { + ucontext_t *uc = context; + uintptr_t target = (uintptr_t)&scr_wasm_fault_trampoline; +#if defined(__APPLE__) && defined(__x86_64__) + uintptr_t sp = stack ? stack : (uintptr_t)uc->uc_mcontext->__ss.__rsp - 256; + sp = (sp & ~(uintptr_t)15) - 8; /* as after a call */ + uc->uc_mcontext->__ss.__rsp = sp; + uc->uc_mcontext->__ss.__rdi = (uint64_t)(uint32_t)code; + uc->uc_mcontext->__ss.__rip = target; + return true; +#elif defined(__APPLE__) && defined(__aarch64__) + uintptr_t sp = stack ? stack : (uintptr_t)__darwin_arm_thread_state64_get_sp(uc->uc_mcontext->__ss) - 256; + sp &= ~(uintptr_t)15; + __darwin_arm_thread_state64_set_sp(uc->uc_mcontext->__ss, sp); + uc->uc_mcontext->__ss.__x[0] = (uint64_t)(uint32_t)code; + __darwin_arm_thread_state64_set_lr_fptr(uc->uc_mcontext->__ss, (void *)target); + __darwin_arm_thread_state64_set_pc_fptr(uc->uc_mcontext->__ss, (void *)target); + return true; +#elif defined(__linux__) && defined(__x86_64__) + uintptr_t sp = stack ? stack : (uintptr_t)uc->uc_mcontext.gregs[REG_RSP] - 256; + sp = (sp & ~(uintptr_t)15) - 8; + uc->uc_mcontext.gregs[REG_RSP] = (greg_t)sp; + uc->uc_mcontext.gregs[REG_RDI] = (greg_t)(uint32_t)code; + uc->uc_mcontext.gregs[REG_RIP] = (greg_t)target; + return true; +#elif defined(__linux__) && defined(__aarch64__) + uintptr_t sp = stack ? stack : (uintptr_t)uc->uc_mcontext.sp - 256; + sp &= ~(uintptr_t)15; + uc->uc_mcontext.sp = sp; + uc->uc_mcontext.regs[0] = (uint64_t)(uint32_t)code; + uc->uc_mcontext.regs[30] = target; + uc->uc_mcontext.pc = target; + return true; +#else + (void)uc; + (void)target; + (void)code; + (void)stack; + return false; +#endif +} + +static uintptr_t scr_wasm_context_sp(void *context) { + ucontext_t *uc = context; +#if defined(__APPLE__) && defined(__x86_64__) + return (uintptr_t)uc->uc_mcontext->__ss.__rsp; +#elif defined(__APPLE__) && defined(__aarch64__) + return (uintptr_t)__darwin_arm_thread_state64_get_sp(uc->uc_mcontext->__ss); +#elif defined(__linux__) && defined(__x86_64__) + return (uintptr_t)uc->uc_mcontext.gregs[REG_RSP]; +#elif defined(__linux__) && defined(__aarch64__) + return (uintptr_t)uc->uc_mcontext.sp; +#else + (void)uc; + return 0; +#endif +} + +static void scr_wasm_chain(int sig, siginfo_t *info, void *context) { + struct sigaction *prev = sig == SIGBUS ? &scr_wasm_prev_bus : &scr_wasm_prev_segv; + if (prev->sa_flags & SA_SIGINFO) { + if (prev->sa_sigaction) { + prev->sa_sigaction(sig, info, context); + return; + } + } else if (prev->sa_handler != SIG_DFL && prev->sa_handler != SIG_IGN) { + prev->sa_handler(sig); + return; + } + /* The default action: restore it and let the faulting instruction run + * again, so the process dies of the original signal. */ + sigaction(sig, prev, NULL); +} + +static void scr_wasm_fault(int sig, siginfo_t *info, void *context) { + if (scr_wasm_running && scr_wasm_top) { + uintptr_t addr = (uintptr_t)info->si_addr; + for (size_t i = 0; i < scr_wasm_range_count; i++) { + if (addr >= scr_wasm_ranges[i].start && addr < scr_wasm_ranges[i].end) { + if (scr_wasm_redirect(context, SCR_WASM_TRAP_MEMORY_OOB, 0)) return; + } + } + uintptr_t sp = scr_wasm_context_sp(context); + if (sp && addr + 65536 >= sp && addr <= sp + 65536) { + /* Stack exhaustion: resume below the export entry's frame, over the + * abandoned translated frames. */ + uintptr_t below = scr_wasm_top->frame - 4096; + if (scr_wasm_redirect(context, SCR_WASM_TRAP_EXHAUSTION, below)) return; + } + } + scr_wasm_chain(sig, info, context); +} + +static void scr_wasm_install_handler(void) { + struct sigaction sa; + memset(&sa, 0, sizeof sa); + sa.sa_sigaction = scr_wasm_fault; + sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGSEGV, &sa, &scr_wasm_prev_segv) == 0 && sigaction(SIGBUS, &sa, &scr_wasm_prev_bus) == 0) + scr_wasm_handler_installed = true; +} + +/* The thread's own stack, which the system ends with a guard page. */ +static _Thread_local uintptr_t scr_wasm_thread_low, scr_wasm_thread_high; +/* The stack guard of the last stack an outermost export call ran on. */ +static _Thread_local uintptr_t scr_wasm_guarded_stack; + +/* Async fibers run on SCR_FIBER_STACK-byte mappings without a guard page + * (compiled code checks scr_stack_guard instead), so recursion in + * translated code there would run past the mapping. The first export call + * on a fiber therefore protects the lowest page of its mapping, which the + * fault handler then reports as stack exhaustion; scr_stack_guard, which + * sits scr_stack_guard_for's reserve above that page, locates it. The + * page stays protected while the runtime reuses the stack. A stack that + * does not match the fiber layout is left alone. */ +static void scr_wasm_guard_fiber(uintptr_t frame) { + if (!scr_wasm_handler_installed) return; + uintptr_t guard = scr_stack_guard; + if (!guard || guard == scr_wasm_guarded_stack) return; + scr_wasm_guarded_stack = guard; + if (!scr_wasm_thread_high) { +#if defined(__APPLE__) + pthread_t self = pthread_self(); + scr_wasm_thread_high = (uintptr_t)pthread_get_stackaddr_np(self); + scr_wasm_thread_low = scr_wasm_thread_high - pthread_get_stacksize_np(self); +#else + pthread_attr_t attr; + if (pthread_getattr_np(pthread_self(), &attr) == 0) { + void *addr; + size_t size; + if (pthread_attr_getstack(&attr, &addr, &size) == 0) { + scr_wasm_thread_low = (uintptr_t)addr; + scr_wasm_thread_high = (uintptr_t)addr + size; + } + pthread_attr_destroy(&attr); + } +#endif + } + if (frame >= scr_wasm_thread_low && frame < scr_wasm_thread_high) return; + uintptr_t low = guard - (scr_stack_guard_for(0, SCR_FIBER_STACK)); + long page = sysconf(_SC_PAGESIZE); + if (page <= 0 || (low & ((uintptr_t)page - 1)) != 0) return; + if (frame <= low + (uintptr_t)page || frame >= low + SCR_FIBER_STACK) return; + (void)mprotect((void *)low, (size_t)page, PROT_NONE); +} + +/* Per thread: an alternate signal stack, so exhaustion faults can be + * handled. A thread that already has one keeps it. */ +static void scr_wasm_thread_init(void) { + if (scr_wasm_altstack_ready || !scr_wasm_handler_installed) return; + scr_wasm_altstack_ready = true; + stack_t current; + if (sigaltstack(NULL, ¤t) == 0 && !(current.ss_flags & SS_DISABLE) && current.ss_size >= 32768) return; + size_t size = 65536; + void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (mem == MAP_FAILED) return; + stack_t ss = {.ss_sp = mem, .ss_size = size, .ss_flags = 0}; + sigaltstack(&ss, NULL); +} +#endif + +/* Checked memories (explicit bounds checks, no guard pages) keep one base + * address for their whole life: the ArrayBuffer of `memory.buffer` and + * every view of it alias the storage, so growing must not move it. The + * address space for the memory's largest size is reserved once and pages + * are committed as the memory grows. Hosts without address-space + * reservation (WASI) move the storage only while no buffer has been + * handed out; after that, growth that would move it fails (-1, a + * RangeError for Memory.prototype.grow). */ +#if defined(_WIN32) +#define SCR_WASM_STABLE_RESERVE 1 +static uint8_t *scr_wasm_reserve(uint64_t bytes) { + return VirtualAlloc(NULL, (SIZE_T)bytes, MEM_RESERVE, PAGE_NOACCESS); +} +static bool scr_wasm_commit(uint8_t *base, uint64_t from, uint64_t to) { + return to == from || VirtualAlloc(base + from, (SIZE_T)(to - from), MEM_COMMIT, PAGE_READWRITE) != NULL; +} +static void scr_wasm_unreserve(ScrWasmMemory *m) { + if (m->base) VirtualFree(m->base, 0, MEM_RELEASE); +} +#elif !defined(__wasi__) +#define SCR_WASM_STABLE_RESERVE 1 +static uint8_t *scr_wasm_reserve(uint64_t bytes) { +#if !defined(MAP_NORESERVE) +#define MAP_NORESERVE 0 +#endif + void *base = mmap(NULL, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); + return base == MAP_FAILED ? NULL : base; +} +static bool scr_wasm_commit(uint8_t *base, uint64_t from, uint64_t to) { + return to == from || mprotect(base + from, to - from, PROT_READ | PROT_WRITE) == 0; +} +static void scr_wasm_unreserve(ScrWasmMemory *m) { + if (m->base) munmap(m->base, m->reserved); +} +#else +static void scr_wasm_unreserve(ScrWasmMemory *m) { free(m->base); } +#endif + +static ScrWasmMemory *scr_wasm_memory_retain(ScrWasmMemory *m) { + m->rc++; + return m; +} + +/* True when JavaScript holds none of the memory's ArrayBuffers or views + * over them: each byte store's only reference is the memory's own. */ +static bool scr_wasm_memory_unexposed(const ScrWasmMemory *m) { + for (size_t i = 0; i < m->exposed_count; i++) + if (m->exposed[i]->rc != 1) return false; + return true; +} + +static void scr_wasm_memory_free(ScrWasmMemory *m) { + for (size_t i = 0; i < m->exposed_count; i++) scr_bytes_release(m->exposed[i]); + free(m->exposed); +#if SCR_WASM_SIGNALS + if (m->guarded) { + scr_wasm_range_remove(m->base); + munmap(m->base, m->reserved); + } else +#endif + scr_wasm_unreserve(m); + free(m); +} + +/* Released memories whose storage JavaScript still reaches through a + * buffer; freed once it no longer does (checked whenever a memory is + * created or released). */ +static _Thread_local ScrWasmMemory *scr_wasm_parked; + +static void scr_wasm_sweep_parked(void) { + for (ScrWasmMemory **p = &scr_wasm_parked; *p;) { + ScrWasmMemory *m = *p; + if (scr_wasm_memory_unexposed(m)) { + *p = m->next_parked; + scr_wasm_memory_free(m); + } else { + p = &m->next_parked; + } + } +} + +static void scr_wasm_memory_release(ScrWasmMemory *m) { + if (!m || --m->rc) return; + scr_dyn_release(m->buffer); + m->buffer = NULL; + scr_wasm_sweep_parked(); + if (scr_wasm_memory_unexposed(m)) { + scr_wasm_memory_free(m); + } else { + m->next_parked = scr_wasm_parked; + scr_wasm_parked = m; + } +} + +/* A memory of `min` pages growing to at most `max` pages (UINT64_MAX: + * no declared maximum); NULL with Node's RangeError pending when the + * address space or memory is short. */ +static ScrWasmMemory *scr_wasm_memory_new(uint64_t min, uint64_t max, bool guarded, const char *what) { + if (scr_wasm_parked) scr_wasm_sweep_parked(); + ScrWasmMemory *m = calloc(1, sizeof *m); + if (!m) scr_trap("scriptc: out of memory\n"); + m->rc = 1; + m->declared_max = max; + m->max_pages = max > SCR_WASM_MAX_PAGES ? SCR_WASM_MAX_PAGES : max; + m->size = min * SCR_WASM_PAGE; +#if SCR_WASM_SIGNALS + if (guarded) { +#if !defined(MAP_NORESERVE) +#define MAP_NORESERVE 0 +#endif + void *base = mmap(NULL, SCR_WASM_GUARD_RESERVATION, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); + if (base == MAP_FAILED || + (m->size && mprotect(base, m->size, PROT_READ | PROT_WRITE) != 0)) { + if (base != MAP_FAILED) munmap(base, SCR_WASM_GUARD_RESERVATION); + free(m); + char msg[200]; + snprintf(msg, sizeof msg, "%s: Out of memory: Cannot allocate Wasm memory for new instance", what); + scr_wasm_range_error(msg); + return NULL; + } + m->base = base; + m->reserved = SCR_WASM_GUARD_RESERVATION; + m->guarded = true; + scr_wasm_range_add(m->base, m->reserved); + return m; + } +#else + (void)guarded; +#endif +#if SCR_WASM_STABLE_RESERVE + uint64_t reserve = m->max_pages * SCR_WASM_PAGE; + m->base = reserve ? scr_wasm_reserve(reserve) : NULL; + if (reserve && (!m->base || !scr_wasm_commit(m->base, 0, m->size))) { + if (m->base) { + m->reserved = reserve; + scr_wasm_unreserve(m); + } +#else + m->base = m->size ? calloc(1, m->size) : NULL; + if (m->size && !m->base) { +#endif + free(m); + char msg[200]; + snprintf(msg, sizeof msg, "%s: Out of memory: Cannot allocate Wasm memory for new instance", what); + scr_wasm_range_error(msg); + return NULL; + } +#if SCR_WASM_STABLE_RESERVE + m->reserved = reserve; +#else + m->reserved = m->size; +#endif + return m; +} + +/* Grows by `delta` pages; answers the previous page count or -1. */ +static int64_t scr_wasm_memory_grow_by(ScrWasmMemory *m, uint64_t delta) { + uint64_t old = m->size / SCR_WASM_PAGE; + if (delta > m->max_pages || old + delta > m->max_pages) return -1; + if (delta == 0) return (int64_t)old; + uint64_t size = (old + delta) * SCR_WASM_PAGE; +#if SCR_WASM_SIGNALS + if (m->guarded) { + if (mprotect(m->base + m->size, size - m->size, PROT_READ | PROT_WRITE) != 0) return -1; + m->size = size; + return (int64_t)old; + } +#endif +#if SCR_WASM_STABLE_RESERVE + /* Committed pages read as zero; the base never moves. */ + if (size > m->reserved || !scr_wasm_commit(m->base, m->size, size)) return -1; + m->size = size; +#else + /* A buffer handed out aliases the storage: moving it would leave the + * buffer's views reading freed memory. */ + if (m->buffer_exposed) return -1; + uint8_t *grown = realloc(m->base, size); + if (!grown) return -1; + memset(grown + m->size, 0, size - m->size); + m->base = grown; + m->reserved = size; + m->size = size; +#endif + return (int64_t)old; +} + +static ScrWasmMemory *scr_wasm_inst_memory(void *inst) { return ((ScrWasmMemory **)inst)[2]; } + +int32_t scr_wasm_memory_grow(void *inst, int32_t delta) { + ScrWasmMemory *m = scr_wasm_inst_memory(inst); + int64_t old = scr_wasm_memory_grow_by(m, (uint32_t)delta); + ((void **)inst)[1] = m->base; + return (int32_t)old; +} + +static void scr_wasm_check_memory(ScrWasmMemory *m, uint32_t at, uint32_t n) { + if ((uint64_t)at + n > m->size) scr_wasm_trap(SCR_WASM_TRAP_MEMORY_OOB); +} + +void scr_wasm_memory_fill(void *inst, int32_t d, int32_t value, int32_t n) { + ScrWasmMemory *m = scr_wasm_inst_memory(inst); + scr_wasm_check_memory(m, (uint32_t)d, (uint32_t)n); + if (n) memset(m->base + (uint32_t)d, value & 0xff, (uint32_t)n); +} + +void scr_wasm_memory_copy(void *inst, int32_t d, int32_t s, int32_t n) { + ScrWasmMemory *m = scr_wasm_inst_memory(inst); + scr_wasm_check_memory(m, (uint32_t)d, (uint32_t)n); + scr_wasm_check_memory(m, (uint32_t)s, (uint32_t)n); + if (n) memmove(m->base + (uint32_t)d, m->base + (uint32_t)s, (uint32_t)n); +} + +/* Instantiation reports an active data segment's failure with its + * details (V8's "data segment N is out of bounds (offset ...)"). */ +static _Thread_local bool scr_wasm_instantiating; +static _Thread_local struct { + uint32_t seg, offset, length; + uint64_t size; +} scr_wasm_segment_failure; + +void scr_wasm_memory_init(void *inst, int32_t seg, int32_t d, int32_t s, int32_t n) { + ScrWasmInst *host = scr_wasm_host_of(inst); + const ScrWasmDataDesc *data = &host->desc->datas[seg]; + uint64_t len = host->data_dropped[seg] ? 0 : data->len; + ScrWasmMemory *m = scr_wasm_inst_memory(inst); + if ((uint64_t)(uint32_t)s + (uint32_t)n > len || (uint64_t)(uint32_t)d + (uint32_t)n > m->size) { + if (scr_wasm_instantiating) { + scr_wasm_segment_failure.seg = (uint32_t)seg; + scr_wasm_segment_failure.offset = (uint32_t)d; + scr_wasm_segment_failure.length = (uint32_t)n; + scr_wasm_segment_failure.size = m->size; + scr_wasm_trap(SCR_WASM_TRAP_DATA_SEGMENT); + } + scr_wasm_trap(SCR_WASM_TRAP_MEMORY_OOB); + } + if (n) memcpy(m->base + (uint32_t)d, data->data + (uint32_t)s, (uint32_t)n); +} + +void scr_wasm_data_drop(void *inst, int32_t seg) { scr_wasm_host_of(inst)->data_dropped[seg] = true; } + +/* ── tables ──────────────────────────────────────────────────────────── */ + +static ScrWasmTable *scr_wasm_table_new(char elem, uint64_t min, uint64_t max) { + ScrWasmTable *t = calloc(1, sizeof *t); + if (!t) scr_trap("scriptc: out of memory\n"); + t->rc = 1; + t->elem = elem; + t->size = (uint32_t)min; + t->declared_max = max; + t->max = max > SCR_WASM_MAX_TABLE ? SCR_WASM_MAX_TABLE : (uint32_t)max; + t->elems = calloc(min ? min : 1, sizeof *t->elems); + if (!t->elems) scr_trap("scriptc: out of memory\n"); + return t; +} + +static ScrWasmTable *scr_wasm_table_retain(ScrWasmTable *t) { + t->rc++; + return t; +} + +static void scr_wasm_table_release(ScrWasmTable *t) { + if (!t || --t->rc) return; + if (t->elem == 'x') + for (uint32_t i = 0; i < t->size; i++) scr_dyn_release(t->elems[i]); + free(t->elems); + free(t); +} + +static void *scr_wasm_ref_retain(char elem, void *v) { + if (elem == 'x' && v) scr_dyn_retain(v); + return v; +} + +/* The reference a table or global slot drops: while a call runs, the guest + * may still hold it in a local or on its operand stack (it read the slot + * before the store), so it stays alive until the outermost call returns. */ +static void scr_wasm_drop_ref(ScrDyn *old) { + if (!old) return; + if (scr_wasm_top) scr_wasm_keep(old); + scr_dyn_release(old); +} + +static void scr_wasm_table_store(ScrWasmTable *t, uint32_t i, void *v) { + void *old = t->elems[i]; + t->elems[i] = scr_wasm_ref_retain(t->elem, v); + if (t->elem == 'x') scr_wasm_drop_ref(old); +} + +static ScrWasmTable *scr_wasm_inst_table(void *inst, int32_t t) { return ((ScrWasmTable **)inst)[4 + t]; } + +void *scr_wasm_table_get(void *inst, int32_t ti, int32_t i) { + ScrWasmTable *t = scr_wasm_inst_table(inst, ti); + if ((uint32_t)i >= t->size) scr_wasm_trap(SCR_WASM_TRAP_TABLE_OOB); + return t->elems[(uint32_t)i]; +} + +void scr_wasm_table_set(void *inst, int32_t ti, int32_t i, void *value) { + ScrWasmTable *t = scr_wasm_inst_table(inst, ti); + if ((uint32_t)i >= t->size) scr_wasm_trap(SCR_WASM_TRAP_TABLE_OOB); + scr_wasm_table_store(t, (uint32_t)i, value); +} + +static int64_t scr_wasm_table_grow_by(ScrWasmTable *t, uint32_t n, void *init) { + uint32_t old = t->size; + if ((uint64_t)old + n > t->max) return -1; + if (n == 0) return old; + void **grown = realloc(t->elems, ((size_t)old + n) * sizeof *grown); + if (!grown) return -1; + t->elems = grown; + for (uint32_t i = 0; i < n; i++) grown[old + i] = scr_wasm_ref_retain(t->elem, init); + t->size = old + n; + return old; +} + +int32_t scr_wasm_table_grow(void *inst, int32_t ti, void *init, int32_t n) { + return (int32_t)scr_wasm_table_grow_by(scr_wasm_inst_table(inst, ti), (uint32_t)n, init); +} + +void scr_wasm_table_fill(void *inst, int32_t ti, int32_t i, void *value, int32_t n) { + ScrWasmTable *t = scr_wasm_inst_table(inst, ti); + if ((uint64_t)(uint32_t)i + (uint32_t)n > t->size) scr_wasm_trap(SCR_WASM_TRAP_TABLE_OOB); + for (uint32_t k = 0; k < (uint32_t)n; k++) scr_wasm_table_store(t, (uint32_t)i + k, value); +} + +void scr_wasm_table_copy(void *inst, int32_t dti, int32_t sti, int32_t d, int32_t s, int32_t n) { + ScrWasmTable *dt = scr_wasm_inst_table(inst, dti), *st = scr_wasm_inst_table(inst, sti); + uint32_t ud = (uint32_t)d, us = (uint32_t)s, un = (uint32_t)n; + if ((uint64_t)ud + un > dt->size || (uint64_t)us + un > st->size) scr_wasm_trap(SCR_WASM_TRAP_TABLE_OOB); + if (ud <= us) { + for (uint32_t k = 0; k < un; k++) scr_wasm_table_store(dt, ud + k, st->elems[us + k]); + } else { + for (uint32_t k = un; k-- > 0;) scr_wasm_table_store(dt, ud + k, st->elems[us + k]); + } +} + +static void *scr_wasm_elem_item(ScrWasmInst *host, int64_t item) { + if (item >= 0) return &host->funcrefs[item]; + if (item == -1) return NULL; + return (void *)(uintptr_t)host->globals[-(item + 2)]->value; +} + +void scr_wasm_table_init(void *inst, int32_t ti, int32_t seg, int32_t d, int32_t s, int32_t n) { + ScrWasmInst *host = scr_wasm_host_of(inst); + ScrWasmTable *t = scr_wasm_inst_table(inst, ti); + const ScrWasmElemDesc *e = &host->desc->elems[seg]; + uint64_t len = host->elem_dropped[seg] ? 0 : e->count; + uint32_t ud = (uint32_t)d, us = (uint32_t)s, un = (uint32_t)n; + if ((uint64_t)ud + un > t->size) scr_wasm_trap(SCR_WASM_TRAP_TABLE_OOB); + if ((uint64_t)us + un > len) scr_wasm_trap(SCR_WASM_TRAP_ELEM_SEGMENT); + for (uint32_t k = 0; k < un; k++) scr_wasm_table_store(t, ud + k, scr_wasm_elem_item(host, e->items[us + k])); +} + +void scr_wasm_elem_drop(void *inst, int32_t seg) { scr_wasm_host_of(inst)->elem_dropped[seg] = true; } + +/* ── globals ─────────────────────────────────────────────────────────── */ + +static ScrWasmGlobal *scr_wasm_global_new(char type, bool mutable_) { + ScrWasmGlobal *g = calloc(1, sizeof *g); + if (!g) scr_trap("scriptc: out of memory\n"); + g->rc = 1; + g->type = type; + g->mutable_ = mutable_; + return g; +} + +static ScrWasmGlobal *scr_wasm_global_retain(ScrWasmGlobal *g) { + g->rc++; + return g; +} + +static void scr_wasm_global_release(ScrWasmGlobal *g) { + if (!g || --g->rc) return; + if (g->type == 'x') scr_dyn_release((ScrDyn *)(uintptr_t)g->value); + free(g); +} + +void scr_wasm_global_set_ref(void *cell, void *value) { + ScrWasmGlobal *g = cell; + ScrDyn *old = (ScrDyn *)(uintptr_t)g->value; + if (value) scr_dyn_retain(value); + g->value = (uint64_t)(uintptr_t)value; + scr_wasm_drop_ref(old); +} + +/* ── handles ─────────────────────────────────────────────────────────── */ + +enum { SCR_WASM_K_MODULE, SCR_WASM_K_INSTANCE, SCR_WASM_K_MEMORY, SCR_WASM_K_TABLE, SCR_WASM_K_GLOBAL }; + +typedef struct ScrWasmObj { + size_t rc; + int kind; + const ScrWasmModuleDesc *desc; /* Module */ + ScrWasmInst *inst; /* Instance; the owner of exported objects */ + ScrWasmMemory *memory; + ScrWasmTable *table; + ScrWasmGlobal *global; +} ScrWasmObj; + +/* Instances are never freed yet (stage W6 traces them for the cycle + * collector), so the references their handles and exported functions hold + * are not counted. */ +static void *scr_wasm_inst_retain(void *p) { return p; } + +static void scr_wasm_inst_release(void *p) { (void)p; } + +static void *scr_wasm_obj_retain(void *p) { + ((ScrWasmObj *)p)->rc++; + return p; +} + +static void scr_wasm_obj_release(void *p) { + ScrWasmObj *o = p; + if (--o->rc) return; + if (o->inst) scr_wasm_inst_release(o->inst); + scr_wasm_memory_release(o->memory); + scr_wasm_table_release(o->table); + scr_wasm_global_release(o->global); + free(o); +} + +static ScrWasmObj *scr_wasm_obj_new(int kind) { + ScrWasmObj *o = calloc(1, sizeof *o); + if (!o) scr_trap("scriptc: out of memory\n"); + o->rc = 1; + o->kind = kind; + return o; +} + +static ScrDyn *scr_wasm_empty_view(void *h) { + (void)h; + return scr_dyn_new_obj(); +} + +static const ScrDynHandleTag scr_wasm_tags[] = {SCR_DYNH_WASM_MODULE, SCR_DYNH_WASM_INSTANCE, SCR_DYNH_WASM_MEMORY, + SCR_DYNH_WASM_TABLE, SCR_DYNH_WASM_GLOBAL}; + +static void scr_wasm_install(void); + +static ScrDyn *scr_wasm_box(ScrWasmObj *o) { + scr_wasm_install(); + ScrDyn *d = scr_dyn_new_handle(o, scr_wasm_tags[o->kind]); + scr_wasm_obj_release(o); + return d; +} + +static ScrWasmObj *scr_wasm_unbox(const ScrDyn *v, int kind) { + if (!v || v->kind != SCR_DYN_HANDLE || v->v.handle.tag != scr_wasm_tags[kind]) return NULL; + return v->v.handle.ptr; +} + +/* ── values ──────────────────────────────────────────────────────────── */ + +static ScrDyn *scr_wasm_function_value(ScrWasmInst *host, uint32_t func); + +/* ToJSValue (+1; NULL with an exception pending). */ +static ScrDyn *scr_wasm_to_js(char t, uint64_t v) { + switch (t) { + case 'i': return scr_dyn_new_num((double)(int32_t)(uint32_t)v); + case 'I': { + ScrBigInt *b = scr_bigint_from_i64((int64_t)v); + ScrDyn *d = scr_dyn_new_bigint(b); + scr_bigint_release(b); + return d; + } + case 'f': { + uint32_t bits = (uint32_t)v; + float f; + memcpy(&f, &bits, 4); + return scr_dyn_new_num((double)f); + } + case 'F': { + double d; + memcpy(&d, &v, 8); + return scr_dyn_new_num(d); + } + case 'r': { + ScrWasmFuncRef *ref = (ScrWasmFuncRef *)(uintptr_t)v; + if (!ref) return scr_dyn_new_null(); + ScrWasmInst *host = scr_wasm_host_of(ref->inst); + return scr_wasm_function_value(host, (uint32_t)(ref - host->funcrefs)); + } + default: { + ScrDyn *d = (ScrDyn *)(uintptr_t)v; + return d ? scr_dyn_retain(d) : scr_dyn_new_null(); + } + } +} + +static uint32_t scr_wasm_to_int32(double n) { + if (!isfinite(n)) return 0; + double t = trunc(n); + double m = fmod(t, 4294967296.0); + if (m < 0) m += 4294967296.0; + return (uint32_t)m; +} + +static ScrWasmFuncRef *scr_wasm_funcref_of(const ScrDyn *v); + +/* V8's message for a value that is neither null nor an exported + * WebAssembly function where a funcref is expected (behind a prefix that + * names the operation). */ +#define SCR_WASM_FUNCREF_EXPECTED "function-typed object must be null (if nullable) or a Wasm function object" + +/* ToWebAssemblyValue: false with an exception pending. References are + * borrowed from `v`. A funcref mismatch throws a TypeError with + * `funcref_error` (the export-call message when NULL). */ +static bool scr_wasm_from_js_as(char t, const ScrDyn *v, uint64_t *out, const char *funcref_error) { + if (!v) v = scr_dyn_undefined(); + switch (t) { + case 'i': { + double n; + if (!scr_dyn_number_coerce_js(v, &n)) return false; + *out = scr_wasm_to_int32(n); + return true; + } + case 'f': { + double n; + if (!scr_dyn_number_coerce_js(v, &n)) return false; + float f = (float)n; + uint32_t b; + memcpy(&b, &f, 4); + *out = b; + return true; + } + case 'F': { + double n; + if (!scr_dyn_number_coerce_js(v, &n)) return false; + memcpy(out, &n, 8); + return true; + } + case 'I': { + ScrBigInt *b = scr_dyn_bigint_coerce(v); + if (!b) return false; + *out = (uint64_t)scr_bigint_to_i64(b); + scr_bigint_release(b); + return true; + } + case 'r': { + if (v->kind == SCR_DYN_NULL) { + *out = 0; + return true; + } + ScrWasmFuncRef *ref = scr_wasm_funcref_of(v); + if (!ref) { + scr_wasm_type_error(funcref_error ? funcref_error : "type incompatibility when transforming from/to JS"); + return false; + } + *out = (uint64_t)(uintptr_t)ref; + return true; + } + default: + if (v->kind == SCR_DYN_NULL) { + *out = 0; + return true; + } + *out = (uint64_t)(uintptr_t)v; + return true; + } +} + +static bool scr_wasm_from_js(char t, const ScrDyn *v, uint64_t *out) { return scr_wasm_from_js_as(t, v, out, NULL); } + +/* DefaultValue(type): what a missing initial value of a constructed + * global or table, or a missing table.grow/set value, stands for. */ +static uint64_t scr_wasm_default_value(char t) { + return t == 'x' ? (uint64_t)(uintptr_t)scr_dyn_undefined() : 0; +} + +static size_t scr_wasm_params(const char *sig) { + size_t n = 0; + while (sig[n] && sig[n] != ':') n++; + return n; +} + +/* ── exported functions ──────────────────────────────────────────────── */ + +typedef struct { + ScrWasmInst *host; + uint32_t func; + ScrWasmThunk thunk; +} ScrWasmExportCtx; + +static ScrDyn *scr_wasm_export_call(ScrClosure *clo, ScrDyn *const *args, size_t argc) { + ScrWasmInst *host = scr_box_get_ref(clo->caps[0]); + uint32_t func = (uint32_t)scr_box_get_f64(clo->caps[1]); + const char *sig = host->desc->func_sigs[func]; + ScrWasmThunk thunk = NULL; + for (uint64_t i = 0; i < host->desc->export_count; i++) { + const ScrWasmExportDesc *ex = &host->desc->exports[i]; + if (ex->kind == SCR_WASM_FUNC && ex->index == func) { + thunk = ex->call; + break; + } + } + size_t np = scr_wasm_params(sig); + const char *res = sig[np] == ':' ? sig + np + 1 : ""; + size_t nr = strlen(res); + uint64_t stack_args[16], stack_res[8] = {0}; + uint64_t *a = np <= 16 ? stack_args : malloc(np * sizeof *a); + uint64_t *r = nr <= 8 ? stack_res : calloc(nr, sizeof *r); + if (!a || !r) scr_trap("scriptc: out of memory\n"); + ScrDyn *result = NULL; + bool ok = true; + for (size_t i = 0; i < np && ok; i++) ok = scr_wasm_from_js(sig[i], i < argc ? args[i] : NULL, &a[i]); + if (ok) { + /* A function the module does not export runs through its signature's + * call thunk, on the code its reference record names. */ + int trap = thunk ? scr_wasm_enter(thunk, host->inst, a, r) + : scr_wasm_enter_ref(NULL, host->desc->func_call_thunks[func], host->funcrefs[func].code, + host->inst, a, r); + if (trap) { + scr_wasm_throw_trap(trap); + } else if (nr == 0) { + result = scr_dyn_retain(scr_dyn_undefined()); + } else if (nr == 1) { + result = scr_wasm_to_js(res[0], r[0]); + } else { + result = scr_dyn_new_arr(); + for (size_t i = 0; i < nr; i++) scr_dyn_arr_push(result, scr_wasm_to_js(res[i], r[i])); + } + scr_wasm_leave(); + } + if (a != stack_args) free(a); + if (r != stack_res) free(r); + scr_wasm_inst_release(host); + return result; +} + +/* The function value of function `func` (+1), created once per instance + * and function: exported functions call through their export thunk, other + * referenced functions through their signature's call thunk. */ +static ScrDyn *scr_wasm_function_value(ScrWasmInst *host, uint32_t func) { + if (host->export_fns[func]) return scr_dyn_retain(host->export_fns[func]); + bool callable = host->desc->func_call_thunks[func] != NULL && host->funcrefs[func].code != NULL; + for (uint64_t i = 0; i < host->desc->export_count && !callable; i++) { + const ScrWasmExportDesc *ex = &host->desc->exports[i]; + if (ex->kind == SCR_WASM_FUNC && ex->index == func) callable = true; + } + if (!callable) { + /* Unreachable for valid modules: every function a reference can name + * is exported or has a call thunk. */ + scr_wasm_type_error("type incompatibility when transforming from/to JS"); + return NULL; + } + char name[24]; + snprintf(name, sizeof name, "%u", func); + size_t name_len = strlen(name) + 1; + host->export_names[func] = malloc(name_len); + if (!host->export_names[func]) scr_trap("scriptc: out of memory\n"); + memcpy(host->export_names[func], name, name_len); + ScrClosure *closure = scr_closure_new(NULL, 2); + closure->caps[0] = scr_box_new_obj(scr_wasm_inst_retain, scr_wasm_inst_release, NULL); + scr_box_set_ref(closure->caps[0], scr_wasm_inst_retain(host)); + closure->caps[1] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(closure->caps[1], (double)func); + uint32_t arity = (uint32_t)scr_wasm_params(host->desc->func_sigs[func]); + host->export_fns[func] = scr_dyn_new_func(closure, scr_wasm_export_call, arity, "", host->export_names[func]); + return scr_dyn_retain(host->export_fns[func]); +} + +static ScrWasmFuncRef *scr_wasm_funcref_of(const ScrDyn *v) { + if (!v || v->kind != SCR_DYN_FUNC || v->v.fn.thunk != scr_wasm_export_call) return NULL; + ScrClosure *clo = v->v.fn.clo; + ScrWasmInst *host = scr_box_get_ref(clo->caps[0]); + uint32_t func = (uint32_t)scr_box_get_f64(clo->caps[1]); + scr_wasm_inst_release(host); + return &host->funcrefs[func]; +} + +/* ── imported functions ──────────────────────────────────────────────── */ + +void scr_wasm_import_call(void *hostp, int32_t index, const uint64_t *args, uint64_t *results) { + ScrWasmInst *host = hostp; + const char *sig = host->desc->func_sigs[index]; + size_t np = scr_wasm_params(sig); + ScrDyn *stack_argv[16]; + ScrDyn **argv = np <= 16 ? stack_argv : malloc(np * sizeof *argv); + if (!argv) scr_trap("scriptc: out of memory\n"); + bool ok = true; + size_t made = 0; + for (; made < np; made++) { + argv[made] = scr_wasm_to_js(sig[made], args[made]); + if (!argv[made]) { + ok = false; + break; + } + } + scr_wasm_running = false; + ScrDyn *res = NULL; + if (ok) { + scr_dyn_this_push_dyn(scr_dyn_undefined()); + res = scr_dyn_call(host->funcs[index], argv, np, "WebAssembly import"); + scr_dyn_this_pop(); + } + for (size_t i = 0; i < made; i++) scr_dyn_release(argv[i]); + if (argv != stack_argv) free(argv); + if (res) { + const char *want = sig[np] == ':' ? sig + np + 1 : ""; + size_t nr = strlen(want); + if (nr == 1) { + ok = scr_wasm_from_js(want[0], res, &results[0]); + if (ok && want[0] == 'x' && results[0]) scr_wasm_keep((ScrDyn *)(uintptr_t)results[0]); + } else if (nr > 1) { + for (size_t i = 0; ok && i < nr; i++) { + ScrDyn *item = scr_dyn_index_get(res, (double)i); + ok = item && scr_wasm_from_js(want[i], item, &results[i]); + if (ok && want[i] == 'x' && results[i]) scr_wasm_keep((ScrDyn *)(uintptr_t)results[i]); + scr_dyn_release(item); + } + } + scr_dyn_release(res); + } else { + ok = false; + } + if (!ok) scr_wasm_trap(SCR_WASM_TRAP_HOST); + scr_wasm_running = true; +} + +/* ── handle members ──────────────────────────────────────────────────── */ + +static ScrDyn *scr_wasm_memory_buffer(ScrWasmMemory *m) { + /* memory.grow in translated code changes the size without telling the + * cached buffer. */ + if (m->buffer && m->buffer_size != m->size) { + scr_dyn_release(m->buffer); + m->buffer = NULL; + } + if (!m->buffer) { + m->buffer_exposed = true; + m->buffer_size = m->size; + ScrBytes *bytes = scr_bytes_from_external(m->base, (size_t)m->size); + /* Earlier buffers JavaScript no longer holds need no tracking. */ + size_t kept = 0; + for (size_t i = 0; i < m->exposed_count; i++) { + if (m->exposed[i]->rc == 1) scr_bytes_release(m->exposed[i]); + else m->exposed[kept++] = m->exposed[i]; + } + m->exposed_count = kept; + ScrBytes **grown = realloc(m->exposed, (m->exposed_count + 1) * sizeof *grown); + if (!grown) scr_trap("scriptc: out of memory\n"); + m->exposed = grown; + m->exposed[m->exposed_count++] = bytes; /* the memory's reference */ + m->buffer = scr_array_buffer_from_bytes(bytes); + } + return scr_dyn_retain(m->buffer); +} + +static ScrDyn *scr_wasm_global_value(ScrWasmGlobal *g) { return scr_wasm_to_js(g->type, g->value); } + +static ScrDyn *scr_wasm_get(void *h, const char *key, size_t len) { + ScrWasmObj *o = h; + switch (o->kind) { + case SCR_WASM_K_INSTANCE: + if (len == 7 && !memcmp(key, "exports", 7)) return scr_dyn_retain(o->inst->exports); + return NULL; + case SCR_WASM_K_MEMORY: + if (len == 6 && !memcmp(key, "buffer", 6)) return scr_wasm_memory_buffer(o->memory); + return NULL; + case SCR_WASM_K_TABLE: + if (len == 6 && !memcmp(key, "length", 6)) return scr_dyn_new_num(o->table->size); + return NULL; + case SCR_WASM_K_GLOBAL: + if (len == 5 && !memcmp(key, "value", 5)) return scr_wasm_global_value(o->global); + return NULL; + default: + return NULL; + } +} + +static bool scr_wasm_global_assign(ScrWasmGlobal *g, const ScrDyn *value) { + if (!g->mutable_) { + scr_wasm_type_error("set WebAssembly.Global.value): Can't set the value of an immutable global."); + return false; + } + uint64_t v; + if (!scr_wasm_from_js_as(g->type, value, &v, "set WebAssembly.Global.value): " SCR_WASM_FUNCREF_EXPECTED)) + return false; + if (g->type == 'x') scr_wasm_global_set_ref(g, (void *)(uintptr_t)v); + else g->value = v; + return true; +} + +static bool scr_wasm_set(void *h, const char *key, size_t len, const ScrDyn *value) { + ScrWasmObj *o = h; + if (o->kind == SCR_WASM_K_GLOBAL && len == 5 && !memcmp(key, "value", 5)) { + scr_wasm_global_assign(o->global, value); + return true; + } + return false; +} + +/* V8's EnforceUint32: ToNumber (its own TypeError for symbols and + * BigInts), then finite, non-negative and at most 2^32-1, truncated. + * `what` names the value ("WebAssembly.Memory.grow(): Argument 0", + * "WebAssembly.Memory(): Property 'initial'"). */ +static bool scr_wasm_u32_arg(const ScrDyn *v, const char *what, uint32_t *out) { + double n; + if (!scr_dyn_number_coerce_js(v ? v : scr_dyn_undefined(), &n)) return false; + const char *problem = !isfinite(n) ? "must be convertible to a valid number" + : n < 0 ? "must be non-negative" + : trunc(n) > 4294967295.0 ? "must be in the unsigned long range" + : NULL; + if (problem) { + char msg[200]; + snprintf(msg, sizeof msg, "%s %s", what, problem); + scr_wasm_type_error(msg); + return false; + } + *out = (uint32_t)trunc(n); + return true; +} + +static ScrDyn *scr_wasm_invoke(void *h, ScrDyn *self, const char *method, ScrDyn *const *args, size_t argc, + const char *what) { + (void)self; + ScrWasmObj *o = h; + if (o->kind == SCR_WASM_K_MEMORY && !strcmp(method, "grow")) { + uint32_t delta; + if (!scr_wasm_u32_arg(argc ? args[0] : NULL, "WebAssembly.Memory.grow(): Argument 0", &delta)) return NULL; + int64_t old = scr_wasm_memory_grow_by(o->memory, delta); + if (old < 0) { + scr_wasm_range_error("WebAssembly.Memory.grow(): Maximum memory size exceeded"); + return NULL; + } + if (o->inst && o->inst->memory == o->memory) o->inst->inst[1] = o->memory->base; + /* The previous buffer keeps its length (no detachment). */ + scr_dyn_release(o->memory->buffer); + o->memory->buffer = NULL; + return scr_dyn_new_num((double)old); + } + if (o->kind == SCR_WASM_K_TABLE) { + ScrWasmTable *t = o->table; + uint32_t index = 0; + uint64_t value = 0; + if (!strcmp(method, "get")) { + if (!scr_wasm_u32_arg(argc ? args[0] : NULL, "WebAssembly.Table.get(): Argument 0", &index)) return NULL; + if (index >= t->size) { + char msg[160]; + snprintf(msg, sizeof msg, "WebAssembly.Table.get(): invalid address %u in %s table of size %u", index, + t->elem == 'x' ? "externref" : "funcref", t->size); + scr_wasm_range_error(msg); + return NULL; + } + return scr_wasm_to_js(t->elem, (uint64_t)(uintptr_t)t->elems[index]); + } + if (!strcmp(method, "set")) { + if (!scr_wasm_u32_arg(argc ? args[0] : NULL, "WebAssembly.Table.set(): Argument 0", &index)) return NULL; + if (index >= t->size) { + char msg[160]; + snprintf(msg, sizeof msg, "WebAssembly.Table.set(): invalid address %u in %s table of size %u", index, + t->elem == 'x' ? "externref" : "funcref", t->size); + scr_wasm_range_error(msg); + return NULL; + } + if (argc > 1) { + if (!scr_wasm_from_js_as(t->elem, args[1], &value, + "WebAssembly.Table.set(): Argument 1 is invalid for table: " SCR_WASM_FUNCREF_EXPECTED)) + return NULL; + } else { + value = scr_wasm_default_value(t->elem); + } + scr_wasm_table_store(t, index, (void *)(uintptr_t)value); + return scr_dyn_retain(scr_dyn_undefined()); + } + if (!strcmp(method, "grow")) { + uint32_t delta; + if (!scr_wasm_u32_arg(argc ? args[0] : NULL, "WebAssembly.Table.grow(): Argument 0", &delta)) return NULL; + if (argc > 1) { + if (!scr_wasm_from_js_as(t->elem, args[1], &value, + "WebAssembly.Table.grow(): Argument 1 is invalid: " SCR_WASM_FUNCREF_EXPECTED)) + return NULL; + } else { + value = scr_wasm_default_value(t->elem); + } + int64_t old = scr_wasm_table_grow_by(t, delta, (void *)(uintptr_t)value); + if (old < 0) { + char msg[160]; + snprintf(msg, sizeof msg, "WebAssembly.Table.grow(): failed to grow table by %u", delta); + scr_wasm_range_error(msg); + return NULL; + } + return scr_dyn_new_num((double)old); + } + } + if (o->kind == SCR_WASM_K_GLOBAL && !strcmp(method, "valueOf")) return scr_wasm_global_value(o->global); + char msg[200]; + snprintf(msg, sizeof msg, "%s is not a function", what ? what : method); + scr_wasm_type_error(msg); + return NULL; +} + +/* Module transfer between threads (postMessage, workerData): a module is + * immutable code plus its descriptor, so the payload is the descriptor + * itself, which every thread of the executable shares. */ +static void *scr_wasm_module_share(void *h) { return (void *)((ScrWasmObj *)h)->desc; } + +static ScrDyn *scr_wasm_module_adopt(void *payload) { + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_MODULE); + o->desc = payload; + return scr_wasm_box(o); +} + +static void scr_wasm_module_drop(void *payload) { (void)payload; } + +static const ScrDynHandleTransfer scr_wasm_module_transfer = { + .share = scr_wasm_module_share, .adopt = scr_wasm_module_adopt, .drop = scr_wasm_module_drop}; + +#define SCR_WASM_OPS(name, tag, xfer) \ + static const ScrDynHandleOps scr_wasm_ops_##name = { \ + .cls = #name, .retain = scr_wasm_obj_retain, .release = scr_wasm_obj_release, \ + .invoke = scr_wasm_invoke, .get = scr_wasm_get, .set = scr_wasm_set, \ + .inspect_view = scr_wasm_empty_view, .json_empty_object = true, \ + .to_string_tag = tag, .inspect_view_empty = true, .transfer = xfer, \ + }; +SCR_WASM_OPS(Module, "WebAssembly.Module", &scr_wasm_module_transfer) +SCR_WASM_OPS(Instance, "WebAssembly.Instance", NULL) +SCR_WASM_OPS(Memory, "WebAssembly.Memory", NULL) +SCR_WASM_OPS(Table, "WebAssembly.Table", NULL) +SCR_WASM_OPS(Global, "WebAssembly.Global", NULL) + +static void scr_wasm_install(void) { + static SCR_TL bool installed; + if (installed) return; + installed = true; + scr_dyn_handle_install(SCR_DYNH_WASM_MODULE, &scr_wasm_ops_Module); + scr_dyn_handle_install(SCR_DYNH_WASM_INSTANCE, &scr_wasm_ops_Instance); + scr_dyn_handle_install(SCR_DYNH_WASM_MEMORY, &scr_wasm_ops_Memory); + scr_dyn_handle_install(SCR_DYNH_WASM_TABLE, &scr_wasm_ops_Table); + scr_dyn_handle_install(SCR_DYNH_WASM_GLOBAL, &scr_wasm_ops_Global); +} + +/* ── modules ─────────────────────────────────────────────────────────── */ + +/* The bytes of a BufferSource, or false with Node's TypeError pending. */ +static bool scr_wasm_bytes_of(const ScrDyn *v, const char *what, const char *expected, const uint8_t **data, + size_t *len) { + if (v && v->kind == SCR_DYN_BYTES) { + *data = v->v.bytes->data; + *len = (size_t)scr_bytes_byte_len(v->v.bytes); + return true; + } + if (v && v->kind == SCR_DYN_HANDLE && scr_array_buffer_is(v)) { + ScrBytes *b = v->v.handle.ptr; + *data = b->data; + *len = (size_t)scr_bytes_byte_len(b); + return true; + } + char msg[200]; + snprintf(msg, sizeof msg, "%s: Argument 0 must be %s", what, expected); + scr_wasm_type_error(msg); + return false; +} + +static const ScrWasmModuleDesc *scr_wasm_lookup(const uint8_t *data, size_t len) { + uint8_t digest[32]; + bool hashed = false; + for (uint64_t i = 0; i < scr_wasm_registry.count; i++) { + const ScrWasmModuleDesc *d = scr_wasm_registry.modules[i]; + if (d->byte_length != len || d->abi_version != SCR_WASM_ABI_VERSION) continue; + if (!hashed) { + scr_wasm_sha256(data, len, digest); + hashed = true; + } + if (!memcmp(d->sha256, digest, 32)) return d; + } + return NULL; +} + +static void scr_wasm_not_translated(const char *what) { + char msg[400]; + snprintf(msg, sizeof msg, + "%s: this module was not translated when the program was built (scriptc compiles WebAssembly ahead of " + "time and cannot compile modules whose bytes it did not see; see https://scriptc.dev/limitations)", + what); + scr_wasm_throw_kind(SCR_WASM_COMPILE_ERROR, msg); +} + +static ScrDyn *scr_wasm_module_from(ScrDyn *bytes, const char *what, const char *expected) { + const uint8_t *data; + size_t len; + if (!scr_wasm_bytes_of(bytes, what, expected, &data, &len)) return NULL; + const ScrWasmModuleDesc *desc = scr_wasm_lookup(data, len); + if (!desc) { + scr_wasm_not_translated(what); + return NULL; + } + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_MODULE); + o->desc = desc; + return scr_wasm_box(o); +} + +ScrDyn *scr_wasm_module_new(ScrDyn *bytes) { + return scr_wasm_module_from(bytes, "WebAssembly.Module()", "a buffer source"); +} + +bool scr_wasm_validate(ScrDyn *bytes) { + const uint8_t *data; + size_t len; + if (!scr_wasm_bytes_of(bytes, "WebAssembly.validate()", "a buffer source", &data, &len)) return false; + return scr_wasm_lookup(data, len) != NULL; +} + +/* ── instances ───────────────────────────────────────────────────────── */ + +/* A member of an import object (+1, NULL when absent or undefined, or with + * an exception pending from a getter). */ +static ScrDyn *scr_wasm_member(const ScrDyn *obj, const char *key, size_t len) { + ScrDyn *v = NULL; + switch (obj->kind) { + case SCR_DYN_OBJ: + case SCR_DYN_FUNC: + case SCR_DYN_ARR: + case SCR_DYN_PROXY: + v = scr_dyn_obj_read(obj, key, len); + break; + case SCR_DYN_TYPED_REF: { + ScrStr *k = scr_str_new(key, len); + v = scr_dyn_typed_ref_key_get(obj, k); + scr_str_release(k); + break; + } + case SCR_DYN_HANDLE: { + ScrStr *k = scr_str_new(key, len); + v = scr_dyn_handle_key_get(obj, k); + scr_str_release(k); + break; + } + default: + break; + } + if (v && v->kind == SCR_DYN_UNDEF) { + scr_dyn_release(v); + v = NULL; + } + return v; +} + +static bool scr_wasm_is_object(const ScrDyn *v) { + return v && (v->kind == SCR_DYN_OBJ || v->kind == SCR_DYN_TYPED_REF || v->kind == SCR_DYN_HANDLE || + v->kind == SCR_DYN_PROXY || v->kind == SCR_DYN_FUNC || v->kind == SCR_DYN_ARR); +} + +static void scr_wasm_link_error(const char *what, uint64_t i, const ScrWasmImportDesc *im, const char *reason) { + char msg[600]; + snprintf(msg, sizeof msg, "%s: Import #%llu \"%.*s\" \"%.*s\": %s", what, (unsigned long long)i, + (int)im->module_len, im->module, (int)im->name_len, im->name, reason); + scr_wasm_throw_kind(SCR_WASM_LINK_ERROR, msg); +} + +static bool scr_wasm_guarded(const ScrWasmModuleDesc *desc) { +#if SCR_WASM_SIGNALS + return !(desc->flags & SCR_WASM_DESC_BOUNDS_CHECKS); +#else + (void)desc; + return false; +#endif +} + +static ScrDyn *scr_wasm_instance_from(const ScrWasmModuleDesc *desc, ScrDyn *imports, const char *what) { + scr_wasm_install(); + char msg[400]; + bool have_imports = imports && imports->kind != SCR_DYN_UNDEF; + if (have_imports && !scr_wasm_is_object(imports)) { + snprintf(msg, sizeof msg, "%s: Argument 1 must be an object", what); + scr_wasm_type_error(msg); + return NULL; + } + if (desc->import_count && !have_imports) { + snprintf(msg, sizeof msg, "%s: Imports argument must be present and must be an object", what); + scr_wasm_type_error(msg); + return NULL; + } + /* Read every import value first (V8's order), then check memories, then + * the rest in order. */ + uint64_t n = desc->import_count; + ScrDyn **values = calloc(n ? n : 1, sizeof *values); + if (!values) scr_trap("scriptc: out of memory\n"); + bool ok = true; + for (uint64_t i = 0; ok && i < n; i++) { + const ScrWasmImportDesc *im = &desc->imports[i]; + ScrDyn *ns = scr_wasm_member(imports, im->module, (size_t)im->module_len); + if (scr_exc_pending()) { + ok = false; + } else if (!scr_wasm_is_object(ns)) { + snprintf(msg, sizeof msg, "%s: Import #%llu \"%.*s\": module is not an object or function", what, + (unsigned long long)i, (int)im->module_len, im->module); + scr_wasm_type_error(msg); + ok = false; + } else { + values[i] = scr_wasm_member(ns, im->name, (size_t)im->name_len); + if (scr_exc_pending()) ok = false; + } + scr_dyn_release(ns); + } + for (uint64_t i = 0; ok && i < n; i++) { + const ScrWasmImportDesc *im = &desc->imports[i]; + if (im->kind != SCR_WASM_MEMORY) continue; + ScrWasmObj *mo = scr_wasm_unbox(values[i], SCR_WASM_K_MEMORY); + if (!mo) { + scr_wasm_link_error(what, i, im, "memory import must be a WebAssembly.Memory object"); + ok = false; + break; + } + /* V8's limit checks, with its messages (a missing maximum prints as + * the unsigned -1). */ + char reason[200]; + uint64_t pages = mo->memory->size / SCR_WASM_PAGE; + if (pages < desc->memory_min) { + snprintf(reason, sizeof reason, "memory import has %llu pages which is smaller than the declared initial of %llu", + (unsigned long long)pages, (unsigned long long)desc->memory_min); + } else if (desc->memory_max != UINT64_MAX && mo->memory->declared_max == UINT64_MAX) { + snprintf(reason, sizeof reason, "memory import has no maximum limit, expected at most 4294967295"); + } else if (desc->memory_max != UINT64_MAX && mo->memory->declared_max > desc->memory_max) { + snprintf(reason, sizeof reason, "memory import has a larger maximum size %llu than the module's declared maximum %llu", + (unsigned long long)mo->memory->declared_max, (unsigned long long)desc->memory_max); + } else { + continue; + } + scr_wasm_link_error(what, i, im, reason); + ok = false; + } + for (uint64_t i = 0; ok && i < n; i++) { + const ScrWasmImportDesc *im = &desc->imports[i]; + const ScrDyn *v = values[i]; + if (im->kind == SCR_WASM_FUNC && !(v && scr_dyn_is_callable(v))) { + scr_wasm_link_error(what, i, im, "function import requires a callable"); + ok = false; + } else if (im->kind == SCR_WASM_FUNC && scr_wasm_funcref_of(v) && + scr_wasm_funcref_of(v)->type != desc->func_types[im->index]) { + /* An exported WebAssembly function keeps its signature. */ + scr_wasm_link_error(what, i, im, "imported function does not match the expected type"); + ok = false; + } else if (im->kind == SCR_WASM_TABLE) { + ScrWasmObj *t = scr_wasm_unbox(v, SCR_WASM_K_TABLE); + const ScrWasmTableDesc *td = &desc->tables[im->index]; + if (!t) { + scr_wasm_link_error(what, i, im, "table import requires a WebAssembly.Table"); + ok = false; + } else if (t->table->size < td->min || (td->max != UINT64_MAX && t->table->declared_max > td->max)) { + /* V8's size checks name the import by number only; the imported + * maximum prints in hexadecimal. */ + char msg[300]; + if (t->table->size < td->min) + snprintf(msg, sizeof msg, "%s: table import %llu is smaller than initial %llu, got %u", what, + (unsigned long long)i, (unsigned long long)td->min, t->table->size); + else if (t->table->declared_max == UINT64_MAX) + snprintf(msg, sizeof msg, "%s: table import %llu has no maximum length; required: %llu", what, + (unsigned long long)i, (unsigned long long)td->max); + else + snprintf(msg, sizeof msg, "%s: table import %llu has a larger maximum size %llx than the module's declared maximum %llu", + what, (unsigned long long)i, (unsigned long long)t->table->declared_max, + (unsigned long long)td->max); + scr_wasm_throw_kind(SCR_WASM_LINK_ERROR, msg); + ok = false; + } else if (t->table->elem != im->type[0]) { + scr_wasm_link_error(what, i, im, "imported table does not match the expected type"); + ok = false; + } + } else if (im->kind == SCR_WASM_GLOBAL) { + ScrWasmObj *g = scr_wasm_unbox(v, SCR_WASM_K_GLOBAL); + bool mutable_ = desc->globals[im->index].mutable_ != 0; + char type = im->type[0]; + if (g) { + if (g->global->mutable_ != mutable_) { + scr_wasm_link_error(what, i, im, "imported global does not match the expected mutability"); + ok = false; + } else if (g->global->type != type) { + scr_wasm_link_error(what, i, im, "imported global does not match the expected type"); + ok = false; + } + } else if (mutable_) { + scr_wasm_link_error(what, i, im, "imported mutable global must be a WebAssembly.Global object"); + ok = false; + } else if (type == 'r') { + if (!v || (v->kind != SCR_DYN_NULL && !scr_wasm_funcref_of(v))) { + scr_wasm_link_error(what, i, im, SCR_WASM_FUNCREF_EXPECTED); + ok = false; + } + } else if (type == 'I' ? !(v && v->kind == SCR_DYN_BIGINT) + : type == 'x' ? false + : !(v && v->kind == SCR_DYN_NUM)) { + scr_wasm_link_error(what, i, im, + "global import must be a number, valid Wasm reference, or WebAssembly.Global object"); + ok = false; + } + } + } + if (!ok) { + for (uint64_t k = 0; k < n; k++) scr_dyn_release(values[k]); + free(values); + return NULL; + } + + ScrWasmInst *host = calloc(1, sizeof *host); + if (!host) scr_trap("scriptc: out of memory\n"); + host->rc = 1; + host->desc = desc; + size_t nf = (size_t)desc->func_count; + size_t slots = 4 + (size_t)desc->table_count + (size_t)desc->global_count; + host->inst = calloc(slots, sizeof(void *)); + host->funcs = calloc(nf ? nf : 1, sizeof *host->funcs); + host->funcrefs = calloc(nf ? nf : 1, sizeof *host->funcrefs); + host->export_fns = calloc(nf ? nf : 1, sizeof *host->export_fns); + host->export_names = calloc(nf ? nf : 1, sizeof *host->export_names); + host->tables = calloc(desc->table_count ? desc->table_count : 1, sizeof *host->tables); + host->globals = calloc(desc->global_count ? desc->global_count : 1, sizeof *host->globals); + host->data_dropped = calloc(desc->data_count ? desc->data_count : 1, 1); + host->elem_dropped = calloc(desc->elem_count ? desc->elem_count : 1, 1); + host->table_objs = calloc(desc->table_count ? desc->table_count : 1, sizeof *host->table_objs); + host->global_objs = calloc(desc->global_count ? desc->global_count : 1, sizeof *host->global_objs); + if (!host->inst || !host->funcs || !host->funcrefs || !host->export_fns || !host->export_names || + !host->tables || !host->globals || !host->data_dropped || !host->elem_dropped || !host->table_objs || + !host->global_objs) + scr_trap("scriptc: out of memory\n"); + void **inst = host->inst; + inst[0] = host; +#ifdef SCR_RC_AUDIT + scr_wasm_note_host(host); +#endif + for (size_t f = 0; f < nf; f++) { + host->funcrefs[f].code = desc->func_codes[f]; + host->funcrefs[f].type = desc->func_types[f]; + host->funcrefs[f].inst = inst; + } + inst[3] = host->funcrefs; + for (uint64_t i = 0; i < n; i++) { + const ScrWasmImportDesc *im = &desc->imports[i]; + ScrDyn *v = values[i]; + switch (im->kind) { + case SCR_WASM_FUNC: + host->funcs[im->index] = v; + values[i] = NULL; + break; + case SCR_WASM_MEMORY: + host->memory = scr_wasm_memory_retain(scr_wasm_unbox(v, SCR_WASM_K_MEMORY)->memory); + host->memory_obj = v; + values[i] = NULL; + break; + case SCR_WASM_TABLE: + host->tables[im->index] = scr_wasm_table_retain(scr_wasm_unbox(v, SCR_WASM_K_TABLE)->table); + host->table_objs[im->index] = v; + values[i] = NULL; + break; + default: { + ScrWasmObj *g = scr_wasm_unbox(v, SCR_WASM_K_GLOBAL); + if (g) { + host->globals[im->index] = scr_wasm_global_retain(g->global); + host->global_objs[im->index] = v; + values[i] = NULL; + } else { + char type = im->type[0]; + ScrWasmGlobal *cell = scr_wasm_global_new(type, false); + uint64_t value = 0; + scr_wasm_from_js(type, v, &value); + if (type == 'x') scr_wasm_global_set_ref(cell, (void *)(uintptr_t)value); + else cell->value = value; + host->globals[im->index] = cell; + } + break; + } + } + scr_dyn_release(values[i]); + } + free(values); + if (desc->memory_count && !host->memory) { + host->memory = scr_wasm_memory_new(desc->memory_min, desc->memory_max, scr_wasm_guarded(desc), what); + if (!host->memory) return NULL; + } + if (host->memory) { + inst[1] = host->memory->base; + inst[2] = host->memory; + } + for (uint64_t t = 0; t < desc->table_count; t++) { + const ScrWasmTableDesc *td = &desc->tables[t]; + if (!host->tables[t]) host->tables[t] = scr_wasm_table_new((char)td->elem, td->min, td->max); + inst[4 + t] = host->tables[t]; + } + for (uint64_t g = 0; g < desc->global_count; g++) { + const ScrWasmGlobalDesc *gd = &desc->globals[g]; + if (!host->globals[g]) host->globals[g] = scr_wasm_global_new((char)gd->type, gd->mutable_ != 0); + inst[4 + desc->table_count + g] = host->globals[g]; + } +#if SCR_WASM_SIGNALS + if (scr_wasm_guarded(desc)) pthread_once(&scr_wasm_handler_once, scr_wasm_install_handler); +#endif + /* Globals and segments, then the start function. */ + bool was = scr_wasm_instantiating; + scr_wasm_instantiating = true; + int trap = scr_wasm_enter(scr_wasm_init_thunk, inst, NULL, NULL); + scr_wasm_leave(); + scr_wasm_instantiating = was; + if (trap) { + if (trap == SCR_WASM_TRAP_DATA_SEGMENT) { + snprintf(msg, sizeof msg, "%s: data segment %u is out of bounds (offset %u, length %u, memory size %llu)", what, + scr_wasm_segment_failure.seg, scr_wasm_segment_failure.offset, scr_wasm_segment_failure.length, + (unsigned long long)scr_wasm_segment_failure.size); + scr_wasm_throw_kind(SCR_WASM_RUNTIME_ERROR, msg); + } else if (trap == SCR_WASM_TRAP_TABLE_OOB) { + snprintf(msg, sizeof msg, "%s: table index is out of bounds", what); + scr_wasm_throw_kind(SCR_WASM_RUNTIME_ERROR, msg); + } else { + scr_wasm_throw_trap(trap); + } + return NULL; + } + if (desc->start) { + trap = scr_wasm_enter(scr_wasm_start_thunk, inst, NULL, NULL); + scr_wasm_leave(); + if (trap) { + scr_wasm_throw_trap(trap); + return NULL; + } + } + + ScrDyn *exports = scr_dyn_new_obj_null_proto(); + for (uint64_t i = 0; i < desc->export_count; i++) { + const ScrWasmExportDesc *ex = &desc->exports[i]; + ScrDyn *value; + if (ex->kind == SCR_WASM_FUNC) { + value = scr_wasm_function_value(host, (uint32_t)ex->index); + } else { + int kind = ex->kind == SCR_WASM_MEMORY ? SCR_WASM_K_MEMORY + : ex->kind == SCR_WASM_TABLE ? SCR_WASM_K_TABLE + : SCR_WASM_K_GLOBAL; + /* V8 exports an imported object itself, and one object per memory + * and table; a defined global gets a new object per export. */ + ScrDyn **slot = kind == SCR_WASM_K_MEMORY ? &host->memory_obj + : kind == SCR_WASM_K_TABLE ? &host->table_objs[ex->index] + : &host->global_objs[ex->index]; + if (*slot) { + value = scr_dyn_retain(*slot); + } else { + ScrWasmObj *o = scr_wasm_obj_new(kind); + o->inst = scr_wasm_inst_retain(host); + if (kind == SCR_WASM_K_MEMORY) o->memory = scr_wasm_memory_retain(host->memory); + else if (kind == SCR_WASM_K_TABLE) o->table = scr_wasm_table_retain(host->tables[ex->index]); + else o->global = scr_wasm_global_retain(host->globals[ex->index]); + value = scr_wasm_box(o); + if (kind != SCR_WASM_K_GLOBAL) *slot = scr_dyn_retain(value); + } + } + scr_dyn_obj_set(exports, ex->name, (size_t)ex->name_len, value); + } + ScrDyn *frozen = scr_dyn_freeze(exports); + scr_dyn_release(frozen); + host->exports = exports; + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_INSTANCE); + o->inst = host; /* takes the creation reference */ + return scr_wasm_box(o); +} + +ScrDyn *scr_wasm_instance_new(ScrDyn *module, ScrDyn *imports) { + scr_wasm_install(); + ScrWasmObj *m = scr_wasm_unbox(module, SCR_WASM_K_MODULE); + if (!m) { + scr_wasm_type_error("WebAssembly.Instance(): Argument 0 must be a WebAssembly.Module"); + return NULL; + } + return scr_wasm_instance_from(m->desc, imports, "WebAssembly.Instance()"); +} + +/* ── constructors and Module's static functions ────────────────────── */ + +/* Memories the program constructs are guarded exactly when the translated + * modules are (every module of a build shares the mode), so any of them + * can import one. */ +static bool scr_wasm_build_guarded(void) { +#if SCR_WASM_SIGNALS + return scr_wasm_registry.count > 0 && !(scr_wasm_registry.modules[0]->flags & SCR_WASM_DESC_BOUNDS_CHECKS); +#else + return false; +#endif +} + +/* V8's GetOptionalIntegerProperty: the descriptor's `name` property as an + * unsigned 32-bit integer within [lower, upper]. An absent or undefined + * property leaves *out unchanged, or throws "is required" when + * `required`. False with an exception pending. */ +static bool scr_wasm_limit(const ScrDyn *descriptor, const char *name, bool required, const char *what, + uint64_t lower, uint64_t upper, uint64_t *out) { + ScrDyn *v = scr_wasm_member(descriptor, name, strlen(name)); + if (scr_exc_pending()) return false; + char msg[240]; + if (!v) { + if (!required) return true; + snprintf(msg, sizeof msg, "%s: Property '%s' is required", what, name); + scr_wasm_type_error(msg); + return false; + } + char label[120]; + snprintf(label, sizeof label, "%s: Property '%s'", what, name); + uint32_t n; + bool ok = scr_wasm_u32_arg(v, label, &n); + scr_dyn_release(v); + if (!ok) return false; + /* V8 prints the lower bound in hexadecimal. */ + if (n < lower) { + snprintf(msg, sizeof msg, "%s: Property '%s': value %u is below the lower bound %llx", what, name, n, + (unsigned long long)lower); + scr_wasm_range_error(msg); + return false; + } + if (n > upper) { + snprintf(msg, sizeof msg, "%s: Property '%s': value %u is above the upper bound %llu", what, name, n, + (unsigned long long)upper); + scr_wasm_range_error(msg); + return false; + } + *out = n; + return true; +} + +/* ToString of a descriptor's type property (+1; NULL with an exception + * pending). An absent property reads as "undefined". */ +static ScrStr *scr_wasm_type_name(const ScrDyn *descriptor, const char *name) { + ScrDyn *v = scr_wasm_member(descriptor, name, strlen(name)); + if (scr_exc_pending()) return NULL; + if (!v) return scr_str_new("undefined", 9); + ScrStr *s = scr_dyn_string_coerce_js(v); + scr_dyn_release(v); + return s; +} + +static bool scr_wasm_str_is(const ScrStr *s, const char *text) { + size_t n = strlen(text); + return s->len == n && !memcmp(s->data, text, n); +} + +/* A descriptor's boolean property (ToBoolean; false when absent). */ +static bool scr_wasm_flag(const ScrDyn *descriptor, const char *name, bool *out) { + ScrDyn *v = scr_wasm_member(descriptor, name, strlen(name)); + if (scr_exc_pending()) return false; + *out = v && scr_dyn_truthy(v); + scr_dyn_release(v); + return true; +} + +static bool scr_wasm_absent(const ScrDyn *v) { return !v || v->kind == SCR_DYN_UNDEF; } + +ScrDyn *scr_wasm_memory_construct(ScrDyn *descriptor) { + scr_wasm_install(); + const char *what = "WebAssembly.Memory()"; + if (!scr_wasm_is_object(descriptor)) { + scr_wasm_type_error("WebAssembly.Memory(): Argument 0 must be a memory descriptor"); + return NULL; + } + uint64_t initial = 0, maximum = UINT64_MAX; + bool shared; + if (!scr_wasm_limit(descriptor, "initial", true, what, 0, SCR_WASM_MAX_PAGES, &initial) || + !scr_wasm_limit(descriptor, "maximum", false, what, initial, SCR_WASM_MAX_PAGES, &maximum) || + !scr_wasm_flag(descriptor, "shared", &shared)) + return NULL; + if (shared && maximum == UINT64_MAX) { + scr_wasm_type_error("WebAssembly.Memory(): If shared is true, maximum property should be defined."); + return NULL; + } + if (shared) { + scr_wasm_type_error("WebAssembly.Memory(): shared memories are not supported yet (scriptc does not translate " + "WebAssembly threads; see https://scriptc.dev/limitations)"); + return NULL; + } + ScrWasmMemory *m = scr_wasm_memory_new(initial, maximum, scr_wasm_build_guarded(), what); + if (!m) return NULL; + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_MEMORY); + o->memory = m; + return scr_wasm_box(o); +} + +ScrDyn *scr_wasm_table_construct(ScrDyn *descriptor, ScrDyn *value) { + scr_wasm_install(); + const char *what = "WebAssembly.Table()"; + if (!scr_wasm_is_object(descriptor)) { + scr_wasm_type_error("WebAssembly.Table(): Argument 0 must be a table descriptor"); + return NULL; + } + ScrStr *type = scr_wasm_type_name(descriptor, "element"); + if (!type) return NULL; + char elem = scr_wasm_str_is(type, "anyfunc") ? 'r' : scr_wasm_str_is(type, "externref") ? 'x' : 0; + scr_str_release(type); + if (!elem) { + scr_wasm_type_error("WebAssembly.Table(): Descriptor property 'element' must be a WebAssembly reference type"); + return NULL; + } + uint64_t initial = 0, maximum = UINT64_MAX; + if (!scr_wasm_limit(descriptor, "initial", true, what, 0, SCR_WASM_MAX_TABLE, &initial) || + !scr_wasm_limit(descriptor, "maximum", false, what, initial, 4294967295u, &maximum)) + return NULL; + uint64_t init = scr_wasm_default_value(elem); + if (!scr_wasm_absent(value) && + !scr_wasm_from_js_as(elem, value, &init, + "WebAssembly.Table(): Argument 2 must be undefined or a value of type compatible with the " + "type of the new table: " SCR_WASM_FUNCREF_EXPECTED ".")) + return NULL; + ScrWasmTable *t = scr_wasm_table_new(elem, initial, maximum); + for (uint32_t i = 0; i < t->size; i++) t->elems[i] = scr_wasm_ref_retain(elem, (void *)(uintptr_t)init); + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_TABLE); + o->table = t; + return scr_wasm_box(o); +} + +ScrDyn *scr_wasm_global_construct(ScrDyn *descriptor, ScrDyn *value) { + scr_wasm_install(); + if (!scr_wasm_is_object(descriptor)) { + scr_wasm_type_error("WebAssembly.Global(): Argument 0 must be a global descriptor"); + return NULL; + } + bool mutable_; + if (!scr_wasm_flag(descriptor, "mutable", &mutable_)) return NULL; + ScrStr *name = scr_wasm_type_name(descriptor, "value"); + if (!name) return NULL; + static const char *const names[] = {"i32", "i64", "f32", "f64", "externref", "anyfunc"}; + static const char letters[] = {'i', 'I', 'f', 'F', 'x', 'r'}; + char type = 0; + for (size_t i = 0; i < sizeof letters; i++) + if (scr_wasm_str_is(name, names[i])) type = letters[i]; + bool v128 = scr_wasm_str_is(name, "v128"); + scr_str_release(name); + if (v128) { + scr_wasm_type_error("WebAssembly.Global(): A global of type 'v128' cannot be created in JavaScript"); + return NULL; + } + if (!type) { + scr_wasm_type_error("WebAssembly.Global(): Descriptor property 'value' must be a WebAssembly type"); + return NULL; + } + uint64_t v = scr_wasm_default_value(type); + if (!scr_wasm_absent(value) && + !scr_wasm_from_js_as(type, value, &v, "WebAssembly.Global(): " SCR_WASM_FUNCREF_EXPECTED)) + return NULL; + ScrWasmGlobal *g = scr_wasm_global_new(type, mutable_); + if (type == 'x') scr_wasm_global_set_ref(g, (void *)(uintptr_t)v); + else g->value = v; + ScrWasmObj *o = scr_wasm_obj_new(SCR_WASM_K_GLOBAL); + o->global = g; + return scr_wasm_box(o); +} + +/* `WebAssembly.Module(...)` and the other classes called without new. */ +ScrDyn *scr_wasm_construct_without_new(double kind, ScrDyn *arg0, ScrDyn *arg1) { + (void)arg0; + (void)arg1; + static const char *const names[] = {"Module", "Instance", "Memory", "Table", "Global"}; + const char *name = names[(int)kind]; + char msg[160]; + snprintf(msg, sizeof msg, "WebAssembly.%s(): WebAssembly.%s must be invoked with 'new'", name, name); + scr_wasm_type_error(msg); + return NULL; +} + +static const ScrWasmModuleDesc *scr_wasm_module_arg(const ScrDyn *v, const char *what) { + ScrWasmObj *m = scr_wasm_unbox(v, SCR_WASM_K_MODULE); + if (m) return m->desc; + char msg[160]; + snprintf(msg, sizeof msg, "%s: Argument 0 must be a WebAssembly.Module", what); + scr_wasm_type_error(msg); + return NULL; +} + +static void scr_wasm_set_text(ScrDyn *obj, const char *key, const char *text, size_t len) { + ScrStr *s = scr_str_new(text, len); + scr_dyn_obj_set(obj, key, strlen(key), scr_dyn_new_str(s)); + scr_str_release(s); +} + +static const char *const scr_wasm_kind_names[] = {"function", "table", "memory", "global"}; + +ScrDyn *scr_wasm_module_imports(ScrDyn *module) { + const ScrWasmModuleDesc *desc = scr_wasm_module_arg(module, "WebAssembly.Module.imports()"); + if (!desc) return NULL; + ScrDyn *out = scr_dyn_new_arr(); + for (uint64_t i = 0; i < desc->import_count; i++) { + const ScrWasmImportDesc *im = &desc->imports[i]; + ScrDyn *row = scr_dyn_new_obj(); + scr_wasm_set_text(row, "module", im->module, (size_t)im->module_len); + scr_wasm_set_text(row, "name", im->name, (size_t)im->name_len); + scr_wasm_set_text(row, "kind", scr_wasm_kind_names[im->kind], strlen(scr_wasm_kind_names[im->kind])); + scr_dyn_arr_push(out, row); + } + return out; +} + +ScrDyn *scr_wasm_module_exports(ScrDyn *module) { + const ScrWasmModuleDesc *desc = scr_wasm_module_arg(module, "WebAssembly.Module.exports()"); + if (!desc) return NULL; + ScrDyn *out = scr_dyn_new_arr(); + for (uint64_t i = 0; i < desc->export_count; i++) { + const ScrWasmExportDesc *ex = &desc->exports[i]; + ScrDyn *row = scr_dyn_new_obj(); + scr_wasm_set_text(row, "name", ex->name, (size_t)ex->name_len); + scr_wasm_set_text(row, "kind", scr_wasm_kind_names[ex->kind], strlen(scr_wasm_kind_names[ex->kind])); + scr_dyn_arr_push(out, row); + } + return out; +} + +/* A fresh ArrayBuffer per matching custom section, in module order. */ +ScrDyn *scr_wasm_module_custom_sections(ScrDyn *module, ScrDyn *name) { + const ScrWasmModuleDesc *desc = scr_wasm_module_arg(module, "WebAssembly.Module.customSections()"); + if (!desc) return NULL; + if (scr_wasm_absent(name)) { + scr_wasm_type_error("WebAssembly.Module.customSections(): Argument 1 is required"); + return NULL; + } + ScrStr *wanted = scr_dyn_string_coerce_js(name); + if (!wanted) return NULL; + ScrDyn *out = scr_dyn_new_arr(); + for (uint64_t i = 0; i < desc->custom_count; i++) { + const ScrWasmCustomDesc *c = &desc->customs[i]; + if (c->name_len != wanted->len || memcmp(c->name, wanted->data, wanted->len) != 0) continue; + ScrBytes *bytes = scr_bytes_from_data(c->data, (size_t)c->len); + scr_dyn_arr_push(out, scr_array_buffer_from_bytes(bytes)); + scr_bytes_release(bytes); + } + scr_str_release(wanted); + return out; +} + +/* `v.valueOf()` on a WebAssembly-typed receiver: a Global's value; any + * other value answers what the generic valueOf answers. */ +ScrDyn *scr_wasm_value_of(ScrDyn *value) { + ScrWasmObj *g = scr_wasm_unbox(value, SCR_WASM_K_GLOBAL); + if (g) return scr_wasm_global_value(g->global); + ScrStr *what = scr_str_new("valueOf", 7); + ScrDyn *out = scr_dyn_value_of(value, what); + scr_str_release(what); + return out; +} + +/* ── promises ────────────────────────────────────────────────────────── */ + +/* A promise settled now: fulfilled with value, or rejected with the + * pending exception. */ +static ScrPromise *scr_wasm_settled(ScrDyn *value) { + if (value) { + ScrPromise *p = scr_promise_settled_ref(value, &scr_dyn_retain_v, &scr_dyn_release_v, &scr_dyn_trace_v); + return p; + } + ScrPromise *p = scr_promise_new(); + scr_promise_reject_pending(p); + return p; +} + +/* compile and instantiate over bytes settle on a later loop turn, after + * the current microtasks, as V8's compile task does. */ +enum { SCR_WASM_JOB_COMPILE, SCR_WASM_JOB_INSTANTIATE }; + +static void scr_wasm_job_fire(ScrClosure *clo) { + ScrPromise *p = scr_box_get_ref(clo->caps[0]); + ScrDyn *source = scr_box_get_ref(clo->caps[1]); + ScrDyn *imports = scr_box_get_ref(clo->caps[2]); + int job = (int)scr_box_get_f64(clo->caps[3]); + const char *what = job == SCR_WASM_JOB_COMPILE ? "WebAssembly.compile()" : "WebAssembly.instantiate()"; + ScrDyn *module = scr_wasm_module_from(source, what, "a buffer source"); + ScrDyn *result = module; + if (module && job == SCR_WASM_JOB_INSTANTIATE) { + ScrDyn *instance = scr_wasm_instance_from(scr_wasm_unbox(module, SCR_WASM_K_MODULE)->desc, imports, what); + if (instance) { + result = scr_dyn_new_obj(); + scr_dyn_obj_set(result, "module", 6, module); + scr_dyn_obj_set(result, "instance", 8, instance); + } else { + scr_dyn_release(module); + result = NULL; + } + } + if (result) { + scr_promise_resolve_dyn(p, result); /* moves result in */ + } else { + scr_promise_reject_pending(p); + } + scr_dyn_release(source); + scr_dyn_release(imports); + scr_promise_release(p); +} + +static ScrPromise *scr_wasm_defer(int job, ScrDyn *source, ScrDyn *imports) { + ScrPromise *p = scr_promise_new(); + ScrClosure *clo = scr_closure_new((void *)scr_wasm_job_fire, 4); + clo->caps[0] = scr_box_new_obj(scr_promise_retain_v, scr_promise_release_v, NULL); + scr_box_set_ref(clo->caps[0], scr_promise_retain(p)); + clo->caps[1] = scr_box_new_obj(scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v); + scr_box_set_ref(clo->caps[1], scr_dyn_retain(source ? source : scr_dyn_undefined())); + clo->caps[2] = scr_box_new_obj(scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v); + scr_box_set_ref(clo->caps[2], scr_dyn_retain(imports ? imports : scr_dyn_undefined())); + clo->caps[3] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(clo->caps[3], (double)job); + scr_loop_defer(clo); + return p; +} + +static bool scr_wasm_is_buffer_source(const ScrDyn *v) { + return v && (v->kind == SCR_DYN_BYTES || (v->kind == SCR_DYN_HANDLE && scr_array_buffer_is(v))); +} + +ScrPromise *scr_wasm_compile(ScrDyn *bytes) { + scr_wasm_install(); + if (!scr_wasm_is_buffer_source(bytes)) { + scr_wasm_type_error("WebAssembly.compile(): Argument 0 must be a buffer source"); + return scr_wasm_settled(NULL); + } + return scr_wasm_defer(SCR_WASM_JOB_COMPILE, bytes, NULL); +} + +ScrPromise *scr_wasm_instantiate(ScrDyn *source, ScrDyn *imports) { + scr_wasm_install(); + ScrWasmObj *m = scr_wasm_unbox(source, SCR_WASM_K_MODULE); + if (m) return scr_wasm_settled(scr_wasm_instance_from(m->desc, imports, "WebAssembly.instantiate()")); + if (!scr_wasm_is_buffer_source(source)) { + scr_wasm_type_error("WebAssembly.instantiate(): Argument 0 must be a buffer source or a WebAssembly.Module object"); + return scr_wasm_settled(NULL); + } + if (imports && imports->kind != SCR_DYN_UNDEF && !scr_wasm_is_object(imports)) { + scr_wasm_type_error("WebAssembly.instantiate(): Argument 1 must be an object"); + return scr_wasm_settled(NULL); + } + return scr_wasm_defer(SCR_WASM_JOB_INSTANTIATE, source, imports); +} + +/* ── instanceof and the error constructors ───────────────────────────── */ + +bool scr_wasm_is(const ScrDyn *value, double kind) { + int k = (int)kind; + if (k <= SCR_WASM_K_GLOBAL) return scr_wasm_unbox(value, k) != NULL; + ScrError *e = value ? scr_errdyn_err_of(value) : NULL; + if (!e) return false; + int brand = scr_wasm_error_brand(e); + scr_error_release(e); + return brand == k - 5; +} + +ScrDyn *scr_wasm_error_new(double kind, ScrDyn *message, ScrDyn *options) { + ScrStr *text = NULL; + if (message && message->kind != SCR_DYN_UNDEF) { + text = scr_dyn_string_coerce_js(message); + if (!text) return NULL; + } + ScrError *e = scr_wasm_error_make((int)kind - 5, text); + if (!text) e->message_present = false; + scr_str_release(text); + if (options && scr_wasm_is_object(options)) { + ScrDyn *cause = scr_wasm_member(options, "cause", 5); + if (cause) { + scr_error_define_cause(e, cause); + scr_dyn_release(cause); + } + } + ScrDyn *d = scr_dyn_from_error(e); + scr_error_release(e); + return d; +} + +/* ── the namespace and its functions as values ───────────────────────── */ + +enum { SCR_WASM_FN_COMPILE, SCR_WASM_FN_INSTANTIATE, SCR_WASM_FN_VALIDATE }; +static const char *const scr_wasm_fn_names[] = {"compile", "instantiate", "validate"}; + +static ScrDyn *scr_wasm_fn_call(ScrClosure *clo, ScrDyn *const *args, size_t argc) { + int kind = (int)scr_box_get_f64(clo->caps[0]); + ScrDyn *a0 = argc > 0 ? args[0] : scr_dyn_undefined(); + ScrDyn *a1 = argc > 1 ? args[1] : scr_dyn_undefined(); + if (kind == SCR_WASM_FN_VALIDATE) { + bool ok = scr_wasm_validate(a0); + if (scr_exc_pending()) return NULL; + return scr_dyn_new_bool(ok); + } + ScrPromise *p = kind == SCR_WASM_FN_COMPILE ? scr_wasm_compile(a0) : scr_wasm_instantiate(a0, a1); + ScrDyn *boxed = scr_dyn_new_promise(p); + scr_promise_release(p); + return boxed; +} + +/* WebAssembly.compile, instantiate and validate as function values (+1), + * one per thread and function, as in Node. */ +static SCR_TL ScrDyn *scr_wasm_fns[3]; +static SCR_TL ScrDyn *scr_wasm_ns; + +ScrDyn *scr_wasm_function(double kind) { + ScrDyn **fns = scr_wasm_fns; + int k = (int)kind; + if (!fns[k]) { + ScrClosure *closure = scr_closure_new(NULL, 1); + closure->caps[0] = scr_box_new(SCR_BOX_F64); + scr_box_set_f64(closure->caps[0], (double)k); + fns[k] = scr_dyn_new_func(closure, scr_wasm_fn_call, k == SCR_WASM_FN_INSTANTIATE ? 1 : 1, "", + scr_wasm_fn_names[k]); + } + return scr_dyn_retain(fns[k]); +} + +/* globalThis.WebAssembly as a value (+1): an object with the namespace's + * functions. The classes are not values yet: their constructors and + * instanceof lower at their use sites. */ +ScrDyn *scr_wasm_namespace(void) { + if (!scr_wasm_ns) { + scr_wasm_ns = scr_dyn_new_obj(); + for (int k = 0; k < 3; k++) + scr_dyn_obj_set(scr_wasm_ns, scr_wasm_fn_names[k], strlen(scr_wasm_fn_names[k]), scr_wasm_function(k)); + } + return scr_dyn_retain(scr_wasm_ns); +} + +/* The global object seen through a cast to a type with a `WebAssembly` + * member (`globalThis as unknown as { WebAssembly: ... }`): an object + * whose WebAssembly member is the namespace (+1). */ +ScrDyn *scr_wasm_global_view(void) { + ScrDyn *view = scr_dyn_new_obj(); + scr_dyn_obj_set(view, "WebAssembly", 11, scr_wasm_namespace()); + return view; +} + +#ifdef SCR_RC_AUDIT +static void scr_wasm_teardown(void) { + for (size_t i = 0; i < scr_wasm_host_count; i++) { + ScrWasmInst *host = scr_wasm_hosts[i]; + const ScrWasmModuleDesc *desc = host->desc; + scr_dyn_release(host->exports); + scr_dyn_release(host->memory_obj); + for (uint64_t t = 0; t < desc->table_count; t++) scr_dyn_release(host->table_objs[t]); + for (uint64_t g = 0; g < desc->global_count; g++) scr_dyn_release(host->global_objs[g]); + free(host->table_objs); + free(host->global_objs); + for (uint64_t f = 0; f < desc->func_count; f++) { + scr_dyn_release(host->export_fns[f]); + scr_dyn_release(host->funcs[f]); + free(host->export_names[f]); + } + scr_wasm_memory_release(host->memory); + for (uint64_t t = 0; t < desc->table_count; t++) scr_wasm_table_release(host->tables[t]); + for (uint64_t g = 0; g < desc->global_count; g++) scr_wasm_global_release(host->globals[g]); + free(host->funcs); + free(host->funcrefs); + free(host->export_fns); + free(host->export_names); + free(host->tables); + free(host->globals); + free(host->data_dropped); + free(host->elem_dropped); + free(host->inst); + free(host); + } + free(scr_wasm_hosts); + scr_wasm_hosts = NULL; + scr_wasm_host_count = scr_wasm_host_cap = 0; + for (int k = 0; k < 3; k++) { + scr_dyn_release(scr_wasm_fns[k]); + scr_wasm_fns[k] = NULL; + } + scr_dyn_release(scr_wasm_ns); + scr_wasm_ns = NULL; +} +#endif diff --git a/packages/runtime/src/scr_wasm.h b/packages/runtime/src/scr_wasm.h new file mode 100644 index 000000000..7b0a29689 --- /dev/null +++ b/packages/runtime/src/scr_wasm.h @@ -0,0 +1,23 @@ +/* scriptc runtime — the WebAssembly JavaScript API (scr_wasm.c): the entry + * points the LLVM backend calls for the wasm.* lib functions. Included by + * scr_runtime.h, which says where new declarations go. The contract with + * translated modules, including scr_wasm_registry, is in scr_wasm_abi.h. */ +#ifndef SCR_WASM_H +#define SCR_WASM_H + +#include "scr_async.h" +#include "scr_dyn.h" +#include "scr_wasm_abi.h" + +ScrPromise *scr_wasm_compile(ScrDyn *bytes); +bool scr_wasm_validate(ScrDyn *bytes); +ScrPromise *scr_wasm_instantiate(ScrDyn *source, ScrDyn *imports); +ScrDyn *scr_wasm_module_new(ScrDyn *bytes); +ScrDyn *scr_wasm_instance_new(ScrDyn *module, ScrDyn *imports); +bool scr_wasm_is(const ScrDyn *value, double kind); +ScrDyn *scr_wasm_error_new(double kind, ScrDyn *message, ScrDyn *options); +ScrDyn *scr_wasm_function(double kind); +ScrDyn *scr_wasm_namespace(void); +ScrDyn *scr_wasm_global_view(void); + +#endif /* SCR_WASM_H */ diff --git a/packages/runtime/src/scr_wasm_abi.h b/packages/runtime/src/scr_wasm_abi.h new file mode 100644 index 000000000..083a2f77a --- /dev/null +++ b/packages/runtime/src/scr_wasm_abi.h @@ -0,0 +1,221 @@ +/* The contract between translated WebAssembly modules and the runtime + * (scr_wasm.c). The compiler's translator (packages/compiler/src/wasm/ + * translate.ts) emits each module's code, an init function and one + * ScrWasmModuleDesc as LLVM IR in the program module, plus the registry + * scr_wasm_registry listing every translated module. The runtime + * implements the JavaScript API once, generically, over these + * descriptors; it never sees the translator's own data structures, and + * the translator never sees the runtime's. + * + * Every descriptor field is pointer- or 64-bit sized so the emitted LLVM + * structs and these C structs have the same layout without padding rules. + * Signatures are strings "params:results" over the letters i (i32), + * I (i64), f (f32), F (f64), r (funcref) and x (externref). Values travel + * in uint64_t slots: f32 and f64 as their bit patterns, references as + * pointers (externref: a borrowed ScrDyn *, NULL for null; funcref: a + * ScrWasmFuncRef *, NULL for null). + * + * Instance layout (the first argument of every translated function): + * 0 ScrWasmInst *host runtime state + * 8 uint8_t *memory_base memory 0's data + * 16 ScrWasmMemory *memory memory 0, or NULL + * 24 ScrWasmFuncRef *funcrefs one record per function + * 32 ScrWasmTable *tables[table_count] + * .. uint64_t *globals[global_count] one cell per global + * With guard pages (no SCR_WASM_DESC_BOUNDS_CHECKS) memory_base never + * changes: the memory is reserved once at its largest size plus a guard + * region, and grow only commits pages. With explicit bounds checks the + * memory is reserved at its largest size without a guard region, so + * memory_base does not change either where the host can reserve address + * space; the translated code still reloads memory_base and the byte + * length after every call. */ +#ifndef SCR_WASM_ABI_H +#define SCR_WASM_ABI_H +#include +#include +#include + +#define SCR_WASM_ABI_VERSION 2 + +enum { SCR_WASM_FUNC = 0, SCR_WASM_TABLE = 1, SCR_WASM_MEMORY = 2, SCR_WASM_GLOBAL = 3 }; + +/* Trap codes the translated code passes to scr_wasm_trap (translate.ts + * TRAP_*), plus the runtime's own. */ +enum { + SCR_WASM_TRAP_NONE = 0, + SCR_WASM_TRAP_UNREACHABLE = 1, + SCR_WASM_TRAP_MEMORY_OOB = 2, + SCR_WASM_TRAP_DIV_BY_ZERO = 3, + SCR_WASM_TRAP_DIV_UNREPRESENTABLE = 4, + SCR_WASM_TRAP_REM_BY_ZERO = 5, + SCR_WASM_TRAP_FLOAT_UNREPRESENTABLE = 6, + SCR_WASM_TRAP_TABLE_OOB = 7, + SCR_WASM_TRAP_SIGNATURE = 8, + SCR_WASM_TRAP_NULL = 9, + SCR_WASM_TRAP_ELEM_SEGMENT = 10, + /* Runtime-only codes. */ + SCR_WASM_TRAP_EXHAUSTION = 100, /* RangeError: Maximum call stack size exceeded */ + SCR_WASM_TRAP_HOST = 101, /* a JavaScript exception is pending */ + SCR_WASM_TRAP_DATA_SEGMENT = 102, /* instantiation: active data segment out of bounds */ +}; + +/* Descriptor flags. */ +#define SCR_WASM_DESC_BOUNDS_CHECKS 1u + +typedef void (*ScrWasmThunk)(void *inst, const uint64_t *args, uint64_t *results); +/* A signature's call thunk: calls `code` (a function of that signature, + * `(inst, params...) -> results`) with the arguments in slots. */ +typedef void (*ScrWasmCallThunk)(void *code, void *inst, const uint64_t *args, uint64_t *results); + +typedef struct { + const char *module; + uint64_t module_len; + const char *name; + uint64_t name_len; + uint64_t kind; + /* The index among imports of this kind (function imports: the function + * index). */ + uint64_t index; + /* Functions: the signature; tables: the element letter; globals: the + * value letter; memories: "". */ + const char *type; +} ScrWasmImportDesc; + +typedef struct { + const char *name; + uint64_t name_len; + uint64_t kind; + uint64_t index; /* function, table, memory or global index */ + const char *type; + ScrWasmThunk call; /* functions */ +} ScrWasmExportDesc; + +typedef struct { + uint64_t elem; /* 'r' or 'x' */ + uint64_t min; + uint64_t max; /* UINT64_MAX when absent */ + uint64_t imported; +} ScrWasmTableDesc; + +typedef struct { + uint64_t type; /* signature letter */ + uint64_t mutable_; + uint64_t imported; +} ScrWasmGlobalDesc; + +typedef struct { + const uint8_t *data; + uint64_t len; +} ScrWasmDataDesc; + +/* An element segment: per item a function index, -1 for null, or + * -(2 + g) for the value of global g. */ +typedef struct { + uint64_t elem; + uint64_t count; + const int64_t *items; +} ScrWasmElemDesc; + +/* A custom section: its name and payload, in module order. Only programs + * that call WebAssembly.Module.customSections carry them (the translator + * emits none otherwise, so debug sections cost nothing). */ +typedef struct { + const char *name; + uint64_t name_len; + const uint8_t *data; + uint64_t len; +} ScrWasmCustomDesc; + +typedef struct ScrWasmModuleDesc { + uint8_t sha256[32]; + uint64_t byte_length; + uint64_t abi_version; + uint64_t flags; + uint64_t import_count; + const ScrWasmImportDesc *imports; + uint64_t export_count; + const ScrWasmExportDesc *exports; + uint64_t func_count; /* imported + defined */ + uint64_t imported_func_count; + /* Per function: the native code `(inst, params...) -> results` for + * functions a reference can name (NULL otherwise), the canonical + * signature identity call_indirect compares, and the signature text. */ + void *const *func_codes; + const uint64_t *func_types; + const char *const *func_sigs; + uint64_t table_count; + const ScrWasmTableDesc *tables; + uint64_t memory_count; /* 0 or 1 */ + uint64_t memory_min; /* pages */ + uint64_t memory_max; /* pages, UINT64_MAX when absent */ + uint64_t global_count; + const ScrWasmGlobalDesc *globals; + uint64_t data_count; + const ScrWasmDataDesc *datas; + uint64_t elem_count; + const ScrWasmElemDesc *elems; + /* Globals, table initializers and active segments, under the trap + * guard; then the start function `void (inst)`, or NULL. */ + void (*init)(void *inst); + void (*start)(void *inst); + uint64_t custom_count; + const ScrWasmCustomDesc *customs; + /* Per function: the call thunk of its signature for referenced + * functions the module does not export (NULL otherwise), so any + * function reference can be called from JavaScript. */ + const ScrWasmCallThunk *func_call_thunks; +} ScrWasmModuleDesc; + +/* The registry the compiler emits in the program module of every program + * that uses the WebAssembly API (count may be 0). */ +typedef struct { + uint64_t count; + const ScrWasmModuleDesc *const *modules; +} ScrWasmRegistry; +extern const ScrWasmRegistry scr_wasm_registry; + +/* Runtime objects the translated code reads at fixed offsets. */ +typedef struct ScrWasmMemory { + uint8_t *base; /* 0 */ + uint64_t size; /* 8: bytes */ + uint64_t max_pages; /* 16 */ + uint64_t reserved; /* 24: bytes of address space reserved at base */ + size_t rc; + bool guarded; + struct ScrDyn *buffer; /* the cached ArrayBuffer */ + uint64_t buffer_size; /* the size it was created at */ + uint64_t declared_max; /* pages; UINT64_MAX when the memory has no maximum */ + bool buffer_exposed; /* a buffer over the storage was handed out */ + /* The byte stores of every ArrayBuffer handed out over this memory's + * storage (retained). The storage outlives the memory while JavaScript + * still holds one of them or a view over it. */ + struct ScrBytes **exposed; + size_t exposed_count; + struct ScrWasmMemory *next_parked; /* released, storage still exposed */ +} ScrWasmMemory; + +typedef struct ScrWasmFuncRef { + void *code; /* 0 */ + uint64_t type; /* 8 */ + void *inst; /* 16: the instance the code expects; its host and the + * record's position in its funcrefs name the function */ +} ScrWasmFuncRef; + +typedef struct ScrWasmTable { + void **elems; /* 0: ScrWasmFuncRef * or ScrDyn * (retained) */ + uint32_t size; /* 8 */ + uint32_t max; + size_t rc; + char elem; /* 'r' or 'x' */ + uint64_t declared_max; /* UINT64_MAX when the table has no maximum */ +} ScrWasmTable; + +/* A global's cell: the value in the low bytes of `value`. */ +typedef struct ScrWasmGlobal { + uint64_t value; /* 0 */ + size_t rc; + char type; + bool mutable_; +} ScrWasmGlobal; + +#endif diff --git a/tests/corpus/1052-comptime-records.ts b/tests/corpus/1052-comptime-records.ts index 47cccf7b3..658aaed32 100644 --- a/tests/corpus/1052-comptime-records.ts +++ b/tests/corpus/1052-comptime-records.ts @@ -43,3 +43,20 @@ const meta = comptime(() => { return { kind: "meta", tags, count: tags.length }; }); console.log(meta.kind, meta.tags.join("|"), meta.count); + +// A discriminated union whose arms both fit a "labeled" value without a +// label: the discriminant picks the arm. +type Item = { kind: "plain"; v: number } | { kind: "labeled"; v: number; label?: string }; +const items: Item[] = comptime( + () => + [ + { kind: "plain", v: 1 }, + { kind: "labeled", v: 2 }, + { kind: "labeled", v: 3, label: "x" }, + ] as Item[], +); +for (const item of items) { + if (item.kind === "labeled") console.log("labeled", item.v, item.label); + else console.log("plain", item.v); +} +console.log(JSON.stringify(items)); diff --git a/tests/corpus/5817-constructor-function-instanceof.cjs b/tests/corpus/5817-constructor-function-instanceof.cjs new file mode 100644 index 000000000..355f53a64 --- /dev/null +++ b/tests/corpus/5817-constructor-function-instanceof.cjs @@ -0,0 +1,15 @@ +// `this instanceof F` in a constructor function, in a program that uses no +// EventEmitter or stream constructor value: the call-without-new idiom +// returns a new instance, and instanceof follows the function's prototype. +"use strict"; +function Glob(pattern) { + if (!(this instanceof Glob)) return new Glob(pattern); + this.pattern = pattern; +} +Glob.prototype.describe = function () { + return `glob ${this.pattern}`; +}; +const called = Glob("*.ts"); +const constructed = new Glob("*.js"); +console.log(called.describe(), constructed.describe()); +console.log(called instanceof Glob, {} instanceof Glob, Object.create(Glob.prototype) instanceof Glob); diff --git a/tests/corpus/5818-constructor-function-emitter-defaults.cjs b/tests/corpus/5818-constructor-function-emitter-defaults.cjs new file mode 100644 index 000000000..d89383b3a --- /dev/null +++ b/tests/corpus/5818-constructor-function-emitter-defaults.cjs @@ -0,0 +1,53 @@ +// EventEmitter.defaultMaxListeners read and written through the untyped +// EventEmitter constructor (Node's accessor and its validation), and a +// legacy pipe whose destination emits 'close' synchronously from end(). +"use strict"; +const util = require("util"); +const EventEmitter = require("events"); +const Stream = require("stream"); + +function Bus() { + EventEmitter.call(this); +} +util.inherits(Bus, EventEmitter); + +console.log(EventEmitter.defaultMaxListeners); +console.log(new Bus().getMaxListeners()); +EventEmitter.defaultMaxListeners = 3; +console.log(EventEmitter.defaultMaxListeners, new Bus().getMaxListeners()); +for (const value of [-1, "4", Number.NaN]) { + try { + EventEmitter.defaultMaxListeners = value; + } catch (error) { + console.log(error.name, error.code, error.message); + } +} +console.log(EventEmitter.defaultMaxListeners); +EventEmitter.defaultMaxListeners = 10; + +function Source() { + Stream.call(this); + this.readable = true; +} +util.inherits(Source, Stream); + +function Sink() { + Stream.call(this); + this.writable = true; +} +util.inherits(Sink, Stream); +Sink.prototype.write = function (chunk) { + console.log("write", chunk); + return true; +}; +Sink.prototype.end = function () { + console.log("sink end"); + this.emit("close"); +}; + +const source = new Source(); +const sink = new Sink(); +source.pipe(sink); +source.emit("data", "a"); +console.log("emit end", source.emit("end")); +console.log("listeners", source.listenerCount("end"), source.listenerCount("data"), sink.listenerCount("close")); diff --git a/tests/corpus/6380-variadic-wrapper-arguments-apply.ts b/tests/corpus/6380-variadic-wrapper-arguments-apply.ts new file mode 100644 index 000000000..1a14b6e2f --- /dev/null +++ b/tests/corpus/6380-variadic-wrapper-arguments-apply.ts @@ -0,0 +1,77 @@ +// A generic higher-order wrapper over `(...args: any) => any` that forwards +// `arguments` with `fn.apply(this, arguments)`, and types its options with +// Parameters / ReturnType. Each call site specializes the wrapper to +// the wrapped function's exact signature. +type AnyFn = (...args: any) => any; + +interface TraceOptions { + name?: string; + tags?: (...args: Parameters) => Record; + onResult?: (result: ReturnType) => void; +} + +function trace(fn: F, opts: TraceOptions = {}): F { + return function (this: unknown) { + const args = arguments as unknown as Parameters; + const tags = opts.tags ? opts.tags(...args) : {}; + console.log("enter", opts.name ?? fn.name, JSON.stringify(tags)); + const result: ReturnType = fn.apply(this, arguments as any); + opts.onResult?.(result); + console.log("exit", opts.name ?? fn.name); + return result; + } as F; +} + +function add(a: number, b: number): number { + return a + b; +} +const tracedAdd = trace(add, { + tags: (a, b) => ({ a: String(a), b: String(b) }), + onResult: (r) => console.log("result", r), +}); +console.log(tracedAdd(2, 3)); +console.log(tracedAdd(10, -4)); + +// A wrapped function with an optional parameter: the omitted position +// arrives as undefined, in the wrapper and its tags callback alike. +function titled(name: string, title?: string): string { + return title ? `${title} ${name}` : name; +} +const tracedTitled = trace(titled, { tags: (name, title) => ({ name, title: title ?? "-" }) }); +console.log(tracedTitled("ada")); +console.log(tracedTitled("ada", "dr")); + +const greet = (who: string, punct: string): string => `hi ${who}${punct}`; +const tracedGreet = trace(greet); +console.log(tracedGreet("ada", "!")); + +const tick = trace(function tick(): number { + return 42; +}); +console.log(tick()); + +interface Point { + x: number; + y: number; +} +const norm = trace((p: Point, scale: number): Point => ({ x: p.x * scale, y: p.y * scale }), { + name: "norm", + tags: (p) => ({ x: String(p.x) }), +}); +console.log(JSON.stringify(norm({ x: 1, y: 2 }, 3))); + +// The arguments tuple spread straight into an optional callback. +function audit(fn: F, check?: (...args: Parameters) => boolean): F { + return function (this: unknown) { + console.log("audit", check?.(...(arguments as unknown as Parameters))); + return fn.apply(this, arguments as any); + } as F; +} +const audited = audit(add, (a, b) => a < b); +console.log(audited(1, 2), audited(5, 3)); +console.log(audit(add)(7, 8)); + +const logOnly = trace((msg: string): void => { + console.log("log:", msg); +}); +logOnly("done"); diff --git a/tests/corpus/6381-variadic-wrapper-async.ts b/tests/corpus/6381-variadic-wrapper-async.ts new file mode 100644 index 000000000..200454a5e --- /dev/null +++ b/tests/corpus/6381-variadic-wrapper-async.ts @@ -0,0 +1,81 @@ +// Variadic generic wrappers around async functions: the wrapper forwards +// `arguments`, awaits the wrapped promise and reports its settled value +// through an Awaited> callback; rejections propagate. +type AnyFn = (...args: any) => any; + +interface Opts { + name?: string; + tags?: (...args: Parameters) => Record; + onSettled?: (value: Awaited>) => void; +} + +function traceAsync Promise>(fn: F, opts: Opts = {}): F { + return async function (this: unknown) { + const args = arguments as unknown as Parameters; + const tags = opts.tags ? opts.tags(...args) : {}; + console.log("start", opts.name ?? fn.name, JSON.stringify(tags)); + try { + const value: Awaited> = await fn.apply(this, arguments as any); + opts.onSettled?.(value); + console.log("ok", opts.name ?? fn.name); + return value; + } catch (e) { + console.log("failed", opts.name ?? fn.name, (e as Error).message); + throw e; + } + } as F; +} + +// The settled result spelled as a conditional over ReturnType. +type Settled = ReturnType extends PromiseLike ? U : ReturnType; + +function summarized Promise>( + fn: F, + summarize: (value: Settled) => string, +): F { + return async function (this: unknown) { + const value: Settled = await fn.apply(this, arguments as any); + console.log("summary", summarize(value)); + return value; + } as F; +} + +async function fetchUser(id: number, prefix: string): Promise { + await Promise.resolve(); + if (id < 0) throw new Error(`bad id ${id}`); + return `${prefix}${id}`; +} + +const getUser = traceAsync(fetchUser, { + tags: (id) => ({ id: String(id) }), + onSettled: (v) => console.log("settled", v.toUpperCase()), +}); + +const sleepless = traceAsync(async (): Promise => 7, { name: "seven" }); + +interface Report { + ok: boolean; + items: string[]; +} +const report = summarized( + async (count: number): Promise => ({ ok: count > 0, items: ["a", "b"].slice(0, count) }), + (r) => `${r.ok}:${r.items.join("+")}`, +); +const counted = summarized(async (n: number): Promise => n * 2, (n) => `n=${n + 1}`); + +async function main(): Promise { + console.log(await getUser(1, "u-")); + console.log(await sleepless()); + console.log(JSON.stringify(await report(1))); + console.log(await counted(4)); + try { + await getUser(-2, "u-"); + } catch (e) { + console.log("caught", (e as Error).message); + } + const pending = getUser(3, "a-"); + const second = await getUser(4, "b-"); + console.log(second, await pending); +} + +main().then(() => console.log("main done")); diff --git a/tests/corpus/6382-variadic-wrapper-methods-this.ts b/tests/corpus/6382-variadic-wrapper-methods-this.ts new file mode 100644 index 000000000..54e043207 --- /dev/null +++ b/tests/corpus/6382-variadic-wrapper-methods-this.ts @@ -0,0 +1,46 @@ +// Variadic generic wrappers on methods: the wrapper passes its own `this` +// through `fn.apply(this, arguments)`, so a wrapped `function (this: C)` +// stored as a class property sees the receiver it was called on. +type AnyFn = (...args: any) => any; + +function logged(fn: F, label: string): F { + return function (this: unknown) { + console.log(`[${label}] call with ${arguments.length} args`); + return fn.apply(this, arguments as any); + } as F; +} + +class Counter { + count = 0; + step: number; + constructor(step: number) { + this.step = step; + } + bump = logged(function (this: Counter, times: number): number { + this.count += this.step * times; + return this.count; + }, "bump"); + reset = logged((): void => { + this.count = 0; + }, "reset"); +} + +const c = new Counter(5); +console.log(c.bump(1)); +console.log(c.bump(2)); +c.reset(); +console.log(c.count); + +class Repo { + base: string; + constructor(base: string) { + this.base = base; + } + load = logged(async function (this: Repo, id: string): Promise { + await Promise.resolve(); + return `${this.base}/${id}`; + }, "load"); +} + +const repo = new Repo("https://x.test"); +repo.load("7").then((url) => console.log("loaded", url)); diff --git a/tests/corpus/6383-variadic-wrapper-rest-tuple.ts b/tests/corpus/6383-variadic-wrapper-rest-tuple.ts new file mode 100644 index 000000000..64f1cbacc --- /dev/null +++ b/tests/corpus/6383-variadic-wrapper-rest-tuple.ts @@ -0,0 +1,54 @@ +// The type-safe variadic wrapper: rest tuples instead of `arguments`. +// `...args: A` with A bound to the wrapped function's parameter tuple +// flattens to that fixed signature; `fn.apply(this, args)`, `fn(...args)` +// and `opts.tags(...args)` forward the tuple's positions. +interface Opts { + name?: string; + tags?: (...args: A) => Record; + onResult?: (r: R) => void; +} + +function wrap(fn: (...args: A) => R, opts: Opts = {}): (...args: A) => R { + return function (this: unknown, ...args: A): R { + const tags = opts.tags ? opts.tags(...args) : {}; + console.log("enter", opts.name ?? fn.name, JSON.stringify(tags)); + const r = fn.apply(this, args); + opts.onResult?.(r); + return r; + }; +} + +function viaSpread(fn: (...args: A) => R): (...args: A) => R { + return (...args: A): R => { + console.log("spread", args.length); + return fn(...args); + }; +} + +function mul(a: number, b: number): number { + return a * b; +} +const m = wrap(mul, { tags: (a, b) => ({ a: String(a), b: String(b) }), onResult: (r) => console.log("r", r) }); +console.log(m(6, 7)); + +const concat = wrap((s: string, n: number, flag: boolean) => `${s}:${n}:${flag}`, { name: "concat" }); +console.log(concat("x", 1, true)); + +const opt = wrap((s: string, n?: number) => `${s}:${n ?? "none"}`, { tags: (s, n) => ({ s, n: String(n) }) }); +console.log(opt("a", undefined), opt("b", 2)); + +const zero = wrap(() => "nothing"); +console.log(zero()); + +const spreadMul = viaSpread(mul); +console.log(spreadMul(3, 3)); + +// A concrete tuple rest parameter has the same fixed signature. +function pair(...args: [string, number]): string { + return `${args[0]}=${args[1]}`; +} +console.log(pair("k", 9)); +const asValue: (k: string, v: number) => string = pair; +console.log(asValue("v", 1)); +const t: [string, number] = ["t", 2]; +console.log(pair(...t)); diff --git a/tests/corpus/6384-variadic-wrapper-nested.ts b/tests/corpus/6384-variadic-wrapper-nested.ts new file mode 100644 index 000000000..76f714402 --- /dev/null +++ b/tests/corpus/6384-variadic-wrapper-nested.ts @@ -0,0 +1,37 @@ +// Nested variadic wrappers: wrapping an already wrapped function, mixing +// the `arguments` form and the rest-tuple form. The inner wrapper's +// function binding gives the outer wrapper its `fn.name`. +type AnyFn = (...args: any) => any; + +function trace(fn: F, label?: string): F { + const wrapped = function (this: unknown) { + console.log("trace>", label ?? fn.name); + const out = fn.apply(this, arguments as any); + console.log("trace<", label ?? fn.name); + return out; + }; + return wrapped as unknown as F; +} + +function timed(fn: (...args: A) => R): (...args: A) => R { + return function (this: unknown, ...args: A): R { + console.log("timed>", fn.name, args.length); + return fn.apply(this, args); + }; +} + +function area(w: number, h: number): number { + return w * h; +} + +const twice = trace(trace(area)); +console.log(twice(2, 3)); + +const labelled = trace(trace(area, "inner"), "outer"); +console.log(labelled(4, 5)); + +const mixed = timed(trace(area)); +console.log(mixed(6, 7)); + +const mixed2 = trace(timed(area)); +console.log(mixed2(1, 9)); diff --git a/tests/corpus/6385-variadic-wrapper-shared-local-names.ts b/tests/corpus/6385-variadic-wrapper-shared-local-names.ts new file mode 100644 index 000000000..20712bc69 --- /dev/null +++ b/tests/corpus/6385-variadic-wrapper-shared-local-names.ts @@ -0,0 +1,75 @@ +// Variadic wrappers whose bodies declare the same local names: one only +// forwards its `arguments` (or its alias of them), the other also reads an +// element, so its tuple exists. Each wrapper forwards its own arguments, also +// when a block-local alias shadows an outer one in the same function. +type AnyFn = (...args: any) => any; + +function forward(fn: F): F { + return function (this: unknown) { + return fn.apply(this, arguments as any); + } as F; +} + +function logFirst(fn: F): F { + return function (this: unknown) { + console.log("first:", arguments[0], "of", arguments.length); + return fn.apply(this, arguments as any); + } as F; +} + +function forwardAlias(fn: F): F { + return function (this: unknown) { + const args = arguments as any; + return fn.apply(this, args); + } as F; +} + +function logFirstAlias(fn: F): F { + return function (this: unknown) { + const args = arguments as any; + console.log("alias first:", args[0]); + return fn.apply(this, args); + } as F; +} + +function shadowed(fn: F): F { + return function (this: unknown) { + const args = arguments as any; + console.log("outer first:", args[0]); + if (args.length > 1) { + const args = arguments as any; + return fn.apply(this, args); + } + return fn.apply(this, args); + } as F; +} + +function add3(a: number, b: number, c: number): number { + return a + b + c; +} + +function greet(name: string): string { + return "hi " + name; +} + +const sum = forward(add3); +console.log(sum(1, 2, 3)); +const hello = logFirst(greet); +console.log(hello("ada")); + +const sumAlias = forwardAlias(add3); +console.log(sumAlias(4, 5, 6)); +const helloAlias = logFirstAlias(greet); +console.log(helloAlias("grace")); + +// The other order: the wrapper that reads an element first. +const hello2 = logFirst(greet); +console.log(hello2("linus")); +const sum2 = forward(add3); +console.log(sum2(7, 8, 9)); + +// A block-local alias with the same name as the outer one. +const sumShadowed = shadowed(add3); +console.log(sumShadowed(10, 20, 30)); +const helloShadowed = shadowed(greet); +console.log(helloShadowed("ken")); diff --git a/tests/corpus/6390-catch-binding-predicate.ts b/tests/corpus/6390-catch-binding-predicate.ts new file mode 100644 index 000000000..82c8797b5 --- /dev/null +++ b/tests/corpus/6390-catch-binding-predicate.ts @@ -0,0 +1,42 @@ +// A catch binding narrowed by a user type predicate reads its fields. +interface ErrorLike { + message: string; + name: string; + code?: string; +} +function isErrorLike(value: unknown): value is ErrorLike { + return typeof value === "object" && value !== null && "message" in value && "name" in value; +} +interface Coded { + code: string; +} +function isCoded(value: unknown): value is Coded { + return typeof value === "object" && value !== null && typeof (value as Coded).code === "string"; +} +function report(fn: () => void): void { + try { + fn(); + } catch (err) { + if (isErrorLike(err)) { + console.log("error", { message: err ? err.message : "none", name: err.name, code: err.code ?? "-" }); + if (err.message.includes("disk")) console.log("disk problem"); + } else { + console.log("not error-like", String(err)); + } + if (isCoded(err) && err.code === "ENOSPC") console.log("coded", err.code); + } +} +report(() => { + throw new Error("disk full"); +}); +report(() => { + const e = new Error("no space") as Error & { code?: string }; + e.code = "ENOSPC"; + throw e; +}); +report(() => { + throw "plain"; +}); +report(() => { + throw { message: "obj", name: "Custom", code: "ENOSPC" }; +}); diff --git a/tests/corpus/6391-nullish-function-default.ts b/tests/corpus/6391-nullish-function-default.ts new file mode 100644 index 000000000..6721d97bf --- /dev/null +++ b/tests/corpus/6391-nullish-function-default.ts @@ -0,0 +1,13 @@ +// `??` with a function fallback whose signature differs from the optional +// callback's (fewer parameters, narrower result). +interface Opts { + tags?: (a: number, b: number) => Record; + label?: (n: number) => string; +} +function run(o: Opts, x: number, y: number): string { + const tags = o.tags ?? (() => ({})); + const label = o.label ?? ((n: number) => `#${n}`); + return `${label(x)} ${JSON.stringify(tags(x, y))}`; +} +console.log(run({}, 1, 2)); +console.log(run({ tags: (a, b) => ({ a, b }), label: (n) => `n${n}` }, 3, 4)); diff --git a/tests/corpus/6392-optional-chain-protocol-calls.ts b/tests/corpus/6392-optional-chain-protocol-calls.ts new file mode 100644 index 000000000..a08a4ee85 --- /dev/null +++ b/tests/corpus/6392-optional-chain-protocol-calls.ts @@ -0,0 +1,47 @@ +// Optional calls on an interface-typed method chain (a do-nothing tracer). +interface Span { + addTags(tags: Record): Span; +} +interface Scope { + active(): Span | null; +} +interface Tracer { + scope(): Scope; +} +class NoopSpan implements Span { + addTags(tags: Record): Span { + console.log("tags", JSON.stringify(tags)); + return this; + } +} +class NoopScope implements Scope { + span: Span | null; + constructor(span: Span | null) { + this.span = span; + } + active(): Span | null { + return this.span; + } +} +class NoopTracer implements Tracer { + s: Scope; + constructor(s: Scope) { + this.s = s; + } + scope(): Scope { + return this.s; + } +} +const quiet: Tracer = new NoopTracer(new NoopScope(null)); +const loud: Tracer = new NoopTracer(new NoopScope(new NoopSpan())); +function tagActiveSpan(tracer: Tracer, tags: Record): void { + tracer.scope().active()?.addTags(tags); +} +tagActiveSpan(quiet, { a: 1 }); +tagActiveSpan(loud, { b: 2 }); + +// Narrowed locals and non-null assertions reach the same protocol calls. +const scope2: Scope = new NoopScope(new NoopSpan()); +const current = scope2.active(); +current?.addTags({ c: 3 }); +scope2.active()!.addTags({ d: 4 }); diff --git a/tests/corpus/6393-function-types-any-params.ts b/tests/corpus/6393-function-types-any-params.ts new file mode 100644 index 000000000..ec7799c9d --- /dev/null +++ b/tests/corpus/6393-function-types-any-params.ts @@ -0,0 +1,8 @@ +// Function values whose parameters are typed any (optional or not). +function build(limit?: any): string { + return `limit=${limit ?? "none"}`; +} +const fns: Array<(limit?: any) => string> = [build]; +console.log(fns[0]!(), fns[0]!(5)); +const take: (v: any) => number = (v) => (typeof v === "number" ? v : -1); +console.log(take(3), take("x")); diff --git a/tests/corpus/6394-in-key-error-subclasses.ts b/tests/corpus/6394-in-key-error-subclasses.ts new file mode 100644 index 000000000..5ade6bcd1 --- /dev/null +++ b/tests/corpus/6394-in-key-error-subclasses.ts @@ -0,0 +1,31 @@ +// `'key' in err` on Error receivers, including subclasses that declare it. +class HttpError extends Error { + status: number; + constructor(message: string, status: number) { + super(message); + this.status = status; + } +} +function describe(err: Error): string { + if ("status" in err) return `status ${(err as HttpError).status}`; + if ("code" in err) return "has code"; + return `plain ${err.message}`; +} +console.log(describe(new Error("x"))); +console.log(describe(new HttpError("nf", 404))); +class Timeout extends HttpError { + get retryable(): boolean { + return true; + } +} +function retryable(err: Error): boolean { + return "retryable" in err; +} +console.log(retryable(new Error("x")), retryable(new HttpError("a", 500)), retryable(new Timeout("t", 504))); +console.log(describe(new Timeout("t", 504))); +// Keys every Error has: its own stack, and Error.prototype's and +// Object.prototype's members. +function inherent(err: Error): boolean[] { + return ["stack" in err, "toString" in err, "constructor" in err, "hasOwnProperty" in err]; +} +console.log(inherent(new Error("s")), inherent(new HttpError("h", 400)), inherent(new TypeError("t"))); diff --git a/tests/corpus/6395-generic-object-entries.ts b/tests/corpus/6395-generic-object-entries.ts new file mode 100644 index 000000000..772367a3a --- /dev/null +++ b/tests/corpus/6395-generic-object-entries.ts @@ -0,0 +1,7 @@ +// Object.entries over a generic record parameter. +function maskSecrets>(tags: T): Record { + return Object.fromEntries( + Object.entries(tags).map(([k, v]) => [k, k.includes("secret") ? "[redacted]" : v]), + ); +} +console.log(JSON.stringify(maskSecrets({ user: "ada", secretToken: "x", n: 1 }))); diff --git a/tests/corpus/6396-generic-any-instantiation.ts b/tests/corpus/6396-generic-any-instantiation.ts new file mode 100644 index 000000000..c3c9da060 --- /dev/null +++ b/tests/corpus/6396-generic-any-instantiation.ts @@ -0,0 +1,18 @@ +// A generic method instantiated at `any` from an untyped forwarding call. +type AnyFn = (...args: any) => any; +class Tracer { + trace(name: string, fn: () => T): T { + console.log("span", name); + return fn(); + } +} +const tracer = new Tracer(); +function traced(name: string, fn: F): F { + return function (this: unknown) { + const args = arguments; + const result = tracer.trace(name, () => fn.apply(this, args as any)); + return result; + } as F; +} +const add = traced("add", (a: number, b: number) => a + b); +console.log(add(1, 2)); diff --git a/tests/corpus/6397-event-loop-metrics.ts b/tests/corpus/6397-event-loop-metrics.ts new file mode 100644 index 000000000..8477dcc48 --- /dev/null +++ b/tests/corpus/6397-event-loop-metrics.ts @@ -0,0 +1,70 @@ +// Event-loop monitoring under @types/node: monitorEventLoopDelay's histogram, +// eventLoopUtilization deltas, and an unref'd interval typed NodeJS.Timeout. +import { monitorEventLoopDelay, performance } from "node:perf_hooks"; +import * as perfHooks from "node:perf_hooks"; +import { monitorEventLoopDelay as eld } from "node:perf_hooks"; + +const histogram = monitorEventLoopDelay({ resolution: 10 }); +console.log("enable", histogram.enable(), histogram.enable()); +const first = performance.eventLoopUtilization(); +console.log("before loop", first.idle, first.active, first.utilization); + +let last = performance.eventLoopUtilization(); +let ticks = 0; +// The unref'd interval keeps nothing alive; this timer holds the loop open +// until the third sample. +const keepAlive = setTimeout(() => console.log("never"), 10_000); +const interval = setInterval(() => { + const now = performance.eventLoopUtilization(); + const delta = performance.eventLoopUtilization(now, last); + last = now; + ticks++; + const p50 = histogram.percentile(50); + const p99 = histogram.percentile(99); + console.log( + "tick", + ticks, + delta.utilization >= 0 && delta.utilization <= 1, + delta.idle >= 0, + p50 > 0, + p99 >= p50, + histogram.max >= p99, + histogram.min <= p50, + histogram.count > 0, + ); + histogram.reset(); + console.log("after reset", histogram.count, histogram.max, histogram.min, Number.isNaN(histogram.mean)); + if (ticks === 3) { + clearInterval(interval); + clearTimeout(keepAlive); + console.log("disable", histogram.disable(), histogram.disable()); + const since = performance.eventLoopUtilization(first); + console.log("since", since.utilization > 0 && since.utilization <= 1, since.idle > 0); + try { + histogram.percentile(0); + } catch (e) { + console.log((e as Error).message, (e as { code?: string }).code); + } + } +}, 50); +interval.unref(); +console.log("hasRef", interval.hasRef()); + +// Other import spellings, and Node's resolution validation. +const aliased = eld(); +const namespaced = perfHooks.monitorEventLoopDelay({ resolution: 20 }); +console.log("spellings", aliased.enable(), namespaced.enable(), aliased.disable(), namespaced.disable()); +for (const resolution of [0, -0, -1, 1.5, NaN, Infinity, 1e16, 1]) { + try { + eld({ resolution }); + console.log("created", resolution); + } catch (e) { + console.log((e as Error).name, (e as { code?: string }).code, (e as Error).message); + } +} +// An undefined resolution takes Node's default. +function withResolution(resolution?: number): boolean { + const h = monitorEventLoopDelay({ resolution }); + return h.enable() && h.disable(); +} +console.log("defaults", withResolution(), withResolution(20), eld({ resolution: undefined }).enable()); diff --git a/tests/corpus/6398-conditional-fixed-arity.ts b/tests/corpus/6398-conditional-fixed-arity.ts new file mode 100644 index 000000000..b98bc146a --- /dev/null +++ b/tests/corpus/6398-conditional-fixed-arity.ts @@ -0,0 +1,66 @@ +// Conditional types over function types with fixed `any` and `any[]` +// parameters, as a generic wrapper's specialization sees them: a function +// that needs more arguments than the pattern passes takes the false +// branch, including through a tuple rest parameter, and a positional +// `any[]` parameter matches only functions whose parameter there accepts +// an array. +type FirstResult = F extends (a: any) => infer R ? R : "takes more"; +type NoArgResult = F extends () => infer R ? R : "takes some"; +type ArrayResult = F extends (items: any[]) => infer R ? R : "not array"; + +function label any>(fn: F, value: FirstResult): string { + const local: FirstResult = value; + return `${fn.name}: ${typeof local} ${String(local)}`; +} + +function labelNoArgs any>(fn: F, value: NoArgResult): string { + const local: NoArgResult = value; + return `${fn.name}: ${typeof local} ${String(local)}`; +} + +function labelArray any>(fn: F, value: ArrayResult): string { + const local: ArrayResult = value; + return `${fn.name}: ${typeof local} ${String(local)}`; +} + +function none(): boolean { + return true; +} +function one(a: string): number { + return a.length; +} +function two(a: string, b: string): number { + return a.length + b.length; +} +function optional(a: string, b?: string): number { + return a.length + (b?.length ?? 0); +} +function rest(a: string, ...more: string[]): number { + return a.length + more.length; +} +function pair(...args: [string, number]): number { + return args[0].length + args[1]; +} +function count(items: string[]): number { + return items.length; +} +function anything(value: unknown): string { + return typeof value; +} + +console.log(label(none, true)); +console.log(label(one, 3)); +console.log(label(two, "takes more")); +console.log(label(optional, 4)); +console.log(label(rest, 5)); +console.log(label(pair, "takes more")); +console.log(labelNoArgs(none, false)); +console.log(labelNoArgs(one, "takes some")); +console.log(labelNoArgs(optional, "takes some")); +console.log(labelNoArgs(pair, "takes some")); +console.log(labelArray(none, true)); +console.log(labelArray(one, "not array")); +console.log(labelArray(rest, "not array")); +console.log(labelArray(count, 7)); +console.log(labelArray(anything, "object")); +console.log(labelArray(two, "not array")); diff --git a/tests/corpus/6400-override-any-base.ts b/tests/corpus/6400-override-any-base.ts new file mode 100644 index 000000000..72b050425 --- /dev/null +++ b/tests/corpus/6400-override-any-base.ts @@ -0,0 +1,35 @@ +// Overrides that narrow an `any`-typed base result: a typed async override +// over an untyped base method, and a sync override returning a union. +class Pool { + name = "pool"; + acquire(): any { + return Promise.resolve("base"); + } + describe(): any { + return this.name; + } +} +class MeteredPool extends Pool { + waits = 0; + override async acquire(): Promise { + this.waits++; + await super.acquire(); + } + override describe(): string | undefined { + return this.waits > 1 ? `metered ${this.waits}` : undefined; + } +} +async function use(pool: Pool, label: string): Promise { + const got = await pool.acquire(); + console.log(label, got === undefined ? "undefined" : got, String(pool.describe())); +} +async function main(): Promise { + const metered = new MeteredPool(); + await use(new Pool(), "plain"); + await use(metered, "metered"); + await metered.acquire(); + console.log(metered.waits, metered.describe()); + const pools: Pool[] = [new Pool(), metered]; + for (const p of pools) console.log(typeof p.describe()); +} +main(); diff --git a/tests/corpus/6401-override-param-variance.ts b/tests/corpus/6401-override-param-variance.ts new file mode 100644 index 000000000..997207af8 --- /dev/null +++ b/tests/corpus/6401-override-param-variance.ts @@ -0,0 +1,33 @@ +// Overrides whose parameters differ from the base: a typed parameter over +// an `any` slot, a wider (contravariant) parameter, and a narrowed result. +class Handler { + handle(input: any): any { + return `base:${input}`; + } + score(value: string): number | undefined { + return value.length; + } +} +class TypedHandler extends Handler { + override handle(input: string): string { + return `typed:${input.toUpperCase()}`; + } + override score(value: string | number): number { + return typeof value === "string" ? value.length * 10 : value; + } +} +function run(h: Handler): void { + console.log(h.handle("abc"), h.score("xy")); +} +run(new Handler()); +run(new TypedHandler()); +const typed = new TypedHandler(); +console.log(typed.handle("q"), typed.score(7)); +try { + run2(new TypedHandler()); +} catch (e) { + console.log("caught", (e as Error).name); +} +function run2(h: Handler): void { + console.log(h.handle(42)); +} diff --git a/tests/corpus/6402-override-js-base/main.ts b/tests/corpus/6402-override-js-base/main.ts new file mode 100644 index 000000000..6821f09dd --- /dev/null +++ b/tests/corpus/6402-override-js-base/main.ts @@ -0,0 +1,26 @@ +// TypeScript overrides of an untyped JavaScript base: a typed async +// override over an untyped method, and a narrowed toString. +import { Pool } from "./pool.js"; + +class MeteredPool extends Pool { + waits = 0; + override async acquire(): Promise { + this.waits++; + const n: number = await super.acquire(); + return n * 10; + } + override toString(): string { + return `Metered(${this.waits})`; + } +} +async function main(): Promise { + const pools: Pool[] = [new Pool(2), new MeteredPool(3)]; + for (const pool of pools) { + const got = await pool.acquire(); + console.log(String(got), pool.toString(), `${pool}`); + pool.release(); + } + const metered = new MeteredPool(1); + console.log(await metered.acquire(), metered.waits); +} +main(); diff --git a/tests/corpus/6402-override-js-base/pool.js b/tests/corpus/6402-override-js-base/pool.js new file mode 100644 index 000000000..d1a337882 --- /dev/null +++ b/tests/corpus/6402-override-js-base/pool.js @@ -0,0 +1,17 @@ +// An untyped JavaScript base class, the shape of a small npm semaphore. +export class Pool { + constructor(size) { + this.size = size; + this.taken = 0; + } + async acquire() { + this.taken++; + return this.taken; + } + release() { + this.taken--; + } + toString() { + return `Pool(${this.taken}/${this.size})`; + } +} diff --git a/tests/corpus/6403-error-code-write.ts b/tests/corpus/6403-error-code-write.ts new file mode 100644 index 000000000..3d6efc2a0 --- /dev/null +++ b/tests/corpus/6403-error-code-write.ts @@ -0,0 +1,39 @@ +// Own properties written on Error values typed with an intersection. +const coded = new Error("c") as Error & { code?: string }; +coded.code = "E1"; +console.log(coded.code, "code" in coded); +function has(err: Error): boolean { + return "code" in err; +} +console.log(has(coded), has(new Error("plain"))); +try { + throw coded; +} catch (e) { + console.log((e as Error & { code?: string }).code); +} + +// System-error members first, then the code: reads stay consistent. +type SysError = Error & { code?: string; errno?: number; syscall?: string; path?: string }; +function sysError(message: string, code: string | undefined): SysError { + const err = new Error(message) as SysError; + err.errno = -2; + err.syscall = "open"; + err.path = "/missing"; + err.code = code; + return err; +} +const enoent = sysError("no such file", "ENOENT"); +console.log(enoent.code, enoent.errno, enoent.syscall, enoent.path, "code" in enoent); +console.log(enoent.message, enoent instanceof Error); +const uncoded = sysError("no code", undefined); +console.log(uncoded.code, uncoded.syscall); + +// A code that is only known at runtime. +function withCode(err: Error & { code?: string }, code: unknown): void { + err.code = code as string; +} +const late = new Error("late") as Error & { code?: string }; +withCode(late, "ELATE"); +console.log(late.code); +late.code = "EAGAIN"; +console.log(late.code, late.message); diff --git a/tests/corpus/6404-error-in-and-assign.ts b/tests/corpus/6404-error-in-and-assign.ts new file mode 100644 index 000000000..a9bb6d086 --- /dev/null +++ b/tests/corpus/6404-error-in-and-assign.ts @@ -0,0 +1,144 @@ +// `'key' in err` on Error values of every receiver form, and +// Object.assign onto a fresh Error. +class HttpError extends Error { + status = 404; + get retryable(): boolean { + return this.status >= 500; + } + describe(): string { + return `${this.status}`; + } +} + +// A receiver narrowed from unknown by instanceof. +function statusOf(value: unknown): unknown { + if (value instanceof Error) { + return "status" in value ? value.status : "none"; + } + return "not an error"; +} +console.log(statusOf(new HttpError("not found")), statusOf(new Error("plain")), statusOf("text")); + +// Parameters, call results and caught values; members a subclass declares +// as fields, accessors and methods; Error.prototype's own members. +function keys(err: Error): string { + return [ + "status" in err, + "retryable" in err, + "describe" in err, + "toString" in err, + "missing" in err, + "message" in err, + ].join(" "); +} +console.log(keys(new HttpError("h"))); +console.log(keys(new Error("e"))); +console.log(keys(new TypeError("t"))); +function latest(): Error { + return new HttpError("latest"); +} +console.log("status" in latest(), "message" in latest()); +function caught(fn: () => void): string { + try { + fn(); + return "ok"; + } catch (e) { + if (e instanceof Error && "status" in e) return `status ${String(e.status)}`; + return "plain"; + } +} +console.log( + caught(() => { + throw new HttpError("t"); + }), + caught(() => { + throw new Error("u"); + }), +); + +// Properties set at runtime are own properties too. +const expando = new Error("x"); +(expando as unknown as { status: number }).status = 1; +console.log(keys(expando)); + +// Object.assign copies the source's own properties onto the error and +// answers the error itself. +interface ErrorLike { + message: string; + status?: number; + code?: string; +} +function toError(error: ErrorLike | string): Error { + return typeof error === "string" + ? new Error(error) + : Object.assign(new Error(error.message), error); +} +const assigned = toError({ message: "boom", status: 500, code: "EBOOM" }); +console.log(assigned.message, (assigned as Error & { code?: string }).code, "status" in assigned); +console.log(statusOf(assigned), assigned instanceof Error, keys(assigned)); +const renamed = toError({ message: "renamed" }); +console.log(renamed.message, "status" in renamed, toError("text").message); +const fresh = new Error("before"); +console.log(Object.assign(fresh, { message: "after" }) === fresh, fresh.message); + +// An Error intersection carrying extra fields: Object.assign's result, +// read and written through its declared members. +interface ApiErrorFields { + status: number; + action: string | undefined; + code: string | undefined; + link: string | undefined; +} +function apiError(message: string, fields: ApiErrorFields) { + const error = Object.assign(new Error(message), fields); + return error; +} +const gateway = apiError("bad gateway", { status: 502, action: undefined, code: "E502", link: "https://example.com" }); +console.log(gateway.message, gateway.status, gateway.code, gateway.link, "action" in gateway, gateway.action); +gateway.status = 503; +console.log(gateway.status, gateway instanceof Error); +Object.assign(gateway, { status: 504, code: "E504" }); +console.log(gateway.status, gateway.code); +function describeApiError(error: Error & { status?: number }): string { + return `${error.message}:${error.status ?? "none"}`; +} +console.log(describeApiError(gateway), describeApiError(new Error("plain"))); + +// Object.assign into a record whose fields are wider than the source's. +interface BuildFailure { + message: string; + bail?: boolean; + code?: string; +} +function failure(message: string, bail: boolean): BuildFailure { + const err: BuildFailure = { message }; + if (bail) Object.assign(err, { bail: true }); + return Object.assign(err, { code: "E_BUILD" }); +} +for (const f of [failure("stop", true), failure("go", false)]) + console.log(f.message, f.bail, f.code); + +// A record given a member its type lacks and thrown at once. +interface FailureRecord { + from: string; + isGraceful: boolean; + errorValue: unknown; +} +function classifyFailure(err: unknown, from: string): FailureRecord { + return { from, isGraceful: from === "user", errorValue: err }; +} +function handleFailure(err: unknown, from: string): string { + const failure = classifyFailure(err, from); + if (failure.from === "build") { + throw Object.assign(failure, { bail: true }); + } + return `${failure.from} ${failure.isGraceful}`; +} +for (const from of ["build", "user"]) { + try { + console.log("handled", handleFailure(new Error("x"), from)); + } catch (e) { + const thrownRecord = e as { from: string; bail?: boolean; isGraceful: boolean }; + console.log("thrown", thrownRecord.from, thrownRecord.bail, thrownRecord.isGraceful); + } +} diff --git a/tests/corpus/6405-wrapped-default-parameters.ts b/tests/corpus/6405-wrapped-default-parameters.ts new file mode 100644 index 000000000..f607eb885 --- /dev/null +++ b/tests/corpus/6405-wrapped-default-parameters.ts @@ -0,0 +1,67 @@ +// Lambdas whose parameters take their type from an `any` default, passed +// through generic wrappers that forward their arguments. +function trace any>(name: string, fn: F): F { + return ((...args: Parameters) => { + console.log("span", name); + return fn(...args); + }) as F; +} +function traceArgs(name: string, fn: (...args: A) => R): (...args: A) => R { + return (...args: A) => { + console.log("span", name); + return fn(...args); + }; +} +function lookup(key: string): any { + return key === "set" ? 7 : undefined; +} + +const doubled = trace("doubled", (n = lookup("unset") ?? 5) => n * 2); +console.log(doubled(), doubled(4)); +const sum = trace("sum", (n = lookup("set") ?? 5, m = 1) => n * 4 + m); +console.log(sum(), sum(2), sum(2, 3)); +const label = trace("label", (prefix = lookup("unset") ?? "item", count: number = 0) => `${prefix}#${count}`); +console.log(label(), label("row"), label(undefined, 3)); +const tripled = traceArgs("tripled", (n: number = lookup("unset") ?? 5) => n * 3); +console.log(tripled(), tripled(2)); + +// A wrapper that also reports tags computed from the wrapped function's +// result, handing its untyped result on through `as never`. +function traceTagged any>( + name: string, + fn: F, + resultTags?: ( + result: ReturnType extends PromiseLike ? U : ReturnType, + ) => Record, +): F { + return ((...args: Parameters) => { + const result: unknown = fn(...args); + if (resultTags) console.log(name, JSON.stringify(resultTags(result as never))); + return result; + }) as F; +} +const summarize = traceTagged( + "summarize", + (limit = lookup("unset") ?? 2) => ({ kept: Number(limit), dropped: 1 }), + (r) => ({ total: r.kept + r.dropped }), +); +console.log(summarize().kept, summarize(5).kept); + +// The same through a function expression whose result is untyped. +function traceTaggedAny any>( + name: string, + fn: F, + resultTags: (result: ReturnType) => Record, +): F { + return function (this: unknown, ...args: Parameters) { + const result = fn.apply(this, args); + console.log(name, JSON.stringify(resultTags(result as never))); + return result; + } as F; +} +const measure = traceTaggedAny( + "measure", + (width = lookup("set") ?? 1, height = 2) => ({ area: Number(width) * height }), + (r) => ({ area: r.area }), +); +console.log(measure().area, measure(3, 4).area); diff --git a/tests/corpus/6406-npm-instance-receiver/main.ts b/tests/corpus/6406-npm-instance-receiver/main.ts new file mode 100644 index 000000000..3dc893548 --- /dev/null +++ b/tests/corpus/6406-npm-instance-receiver/main.ts @@ -0,0 +1,7 @@ +// A package's constructor function, compiled per call site, reads its own +// receiver while the constructor that reached it has a receiver too. +import { create } from "corked-writer"; +const w = create({ highWaterMark: 4 }); +console.log(w.uncork()); +console.log(w.uncork()); +console.log(create().uncork()); diff --git a/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.d.ts b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.d.ts new file mode 100644 index 000000000..1de006a3d --- /dev/null +++ b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.d.ts @@ -0,0 +1,4 @@ +export interface Writable { + uncork(): string; +} +export function create(options?: { highWaterMark?: number }): Writable; diff --git a/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.js b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.js new file mode 100644 index 000000000..6a7e75541 --- /dev/null +++ b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/index.js @@ -0,0 +1,45 @@ +'use strict'; + +// Constructor functions in the shape of a stream implementation: a request +// object built inside another constructor keeps its receiver in a var for +// a callback, and the writer is also exported as a value. + +function CorkedRequest(state) { + var _this = this; + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +module.exports = { + create: function (options) { + return new Writable(options); + }, + Writable: Writable, +}; +Writable.WritableState = WritableState; +function WritableState(options, stream) { + this.highWaterMark = options.highWaterMark || 16; + this.pending = 2; + this.stream = stream; + this.corkedRequestsFree = new CorkedRequest(this); +} +WritableState.prototype.getBuffer = function getBuffer() { + return this.pending; +}; +function Writable(options) { + this._writableState = new WritableState(options || {}, this); + this.label = "w"; +} +Writable.prototype.uncork = function () { + var state = this._writableState; + var req = state.corkedRequestsFree; + req.finish(); + state.corkedRequestsFree = new CorkedRequest(state); + return this.label + " " + req.next + " " + state.highWaterMark; +}; +function onCorkedFinish(corkReq, state) { + state.pending--; + corkReq.next = "finished:" + state.pending; +} diff --git a/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/package.json b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/package.json new file mode 100644 index 000000000..94a00403d --- /dev/null +++ b/tests/corpus/6406-npm-instance-receiver/node_modules/corked-writer/package.json @@ -0,0 +1 @@ +{ "name": "corked-writer", "version": "1.0.0", "main": "index.js", "types": "index.d.ts" } diff --git a/tests/corpus/6409-catch-binding-shapes.ts b/tests/corpus/6409-catch-binding-shapes.ts new file mode 100644 index 000000000..930c41f38 --- /dev/null +++ b/tests/corpus/6409-catch-binding-shapes.ts @@ -0,0 +1,69 @@ +// Catch bindings typed any, multi-statement guards over catch bindings, +// and writes into a caught error. +interface SafeFetchError extends Error { + kind: "safe-fetch"; + host: string; +} +function isSafeFetchError(e: unknown): e is SafeFetchError { + if (!(e instanceof Error)) return false; + return "kind" in e && e.kind === "safe-fetch"; +} +function blocked(host: string): Error { + return Object.assign(new Error(`blocked ${host}`), { kind: "safe-fetch", host }); +} +function run(fn: () => void): string { + try { + fn(); + return "ok"; + } catch (err) { + if (isSafeFetchError(err)) return `guarded ${err.host} ${err.message}`; + return `other ${err instanceof Error ? err.message : String(err)}`; + } +} +console.log(run(() => {})); +console.log(run(() => { + throw blocked("example.com"); +})); +console.log(run(() => { + throw new Error("plain"); +})); +console.log(run(() => { + throw "text"; +})); + +function annotate(fn: () => void): void { + try { + fn(); + } catch (e: any) { + e.message = `config: ${e.message}`; + if (e.code === "ENOPE") e.hint = "check the file"; + throw e; + } +} +for (const code of ["ENOPE", "EOTHER"]) { + try { + annotate(() => { + throw Object.assign(new Error("missing"), { code }); + }); + } catch (e) { + const err = e as Error & { code?: string; hint?: string }; + console.log(err.message, err.code, err.hint, err instanceof Error); + } +} + +// An assertion on a catch binding typed any. +function codeOf(fn: () => void): string { + try { + fn(); + return "none"; + } catch (e: any) { + const err = e as Error & { code?: string }; + return `${err.message}:${err.code ?? "-"}`; + } +} +console.log( + codeOf(() => { + throw Object.assign(new Error("coded"), { code: "E1" }); + }), + codeOf(() => {}), +); diff --git a/tests/corpus/6410-json-mixed-scalar-tables/extra.json b/tests/corpus/6410-json-mixed-scalar-tables/extra.json new file mode 100644 index 000000000..7af99c22f --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/extra.json @@ -0,0 +1 @@ +[["x", 1, "two", 3], [4, "five", null], ["six"], [null]] diff --git a/tests/corpus/6410-json-mixed-scalar-tables/main.ts b/tests/corpus/6410-json-mixed-scalar-tables/main.ts new file mode 100644 index 000000000..c60f962dc --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/main.ts @@ -0,0 +1,26 @@ +// JSON tables whose rows mix strings and numbers, the shape of a +// character-set table (`[["8140", 12288, 65292], ...]`) and of a +// code-point range map (`[[[0, 44], "disallowed"], [[65, 65], "mapped", +// [97]], ...]`). A package requires them at load or inside a function, and +// an ES module imports one; each row keeps its strings and numbers. +import { lookup, rowCount } from "code-table"; +import { mapChars, status } from "range-map"; +import extra from "./extra.json" with { type: "json" }; + +console.log(lookup("8150"), lookup("a1"), lookup("zzzz"), rowCount()); +const mapped = mapChars("AB-c9"); +console.log(mapped.text, mapped.error); +console.log(JSON.stringify(mapChars("a,b")), JSON.stringify(mapChars("{"))); +console.log(status(10), status(46), status(66), status(1000)); + +for (const row of extra) { + const head = row[0]; + const rest = row.slice(1); + console.log( + typeof head, + head, + rest.length, + rest.map((v) => (v === null ? "null" : typeof v === "number" ? v + 1 : v.toUpperCase())).join(","), + ); +} +console.log(JSON.stringify(extra)); diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.d.ts b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.d.ts new file mode 100644 index 000000000..ae7db1d98 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.d.ts @@ -0,0 +1,2 @@ +export declare function lookup(code: string): number | string; +export declare function rowCount(): number; diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.js b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.js new file mode 100644 index 000000000..dc10bb817 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/index.js @@ -0,0 +1,10 @@ +'use strict'; +const table = require('./table.json'); +exports.lookup = function (code) { + for (const row of table) if (row[0] === code) return row[1]; + return -1; +}; +exports.rowCount = function () { + // A second require of the same document answers the same rows. + return require('./table.json').length; +}; diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/package.json b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/package.json new file mode 100644 index 000000000..e15622d87 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/package.json @@ -0,0 +1 @@ +{ "name": "code-table", "version": "1.0.0", "main": "index.js", "types": "index.d.ts" } diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/table.json b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/table.json new file mode 100644 index 000000000..5abaa6772 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/code-table/table.json @@ -0,0 +1 @@ +[["8140", 12288, 65292], ["8150", 65507, 65340], ["a1", "。", 62]] diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.d.ts b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.d.ts new file mode 100644 index 000000000..322bd20e1 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.d.ts @@ -0,0 +1,2 @@ +export declare function mapChars(s: string): { text: string; error: boolean }; +export declare function status(cp: number): string; diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.js b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.js new file mode 100644 index 000000000..481d93ad4 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/index.js @@ -0,0 +1,37 @@ +'use strict'; +var table = require('./table.json'); +function findStatus(val) { + var start = 0; + var end = table.length - 1; + while (start <= end) { + var mid = Math.floor((start + end) / 2); + var target = table[mid]; + if (target[0][0] <= val && target[0][1] >= val) { + return target; + } else if (target[0][0] > val) { + end = mid - 1; + } else { + start = mid + 1; + } + } + return null; +} +exports.status = function (cp) { + var found = findStatus(cp); + return found === null ? 'unknown' : found[1]; +}; +exports.mapChars = function (s) { + var error = false; + var out = ''; + for (var i = 0; i < s.length; ++i) { + var cp = s.codePointAt(i); + var found = findStatus(cp); + if (found === null) { error = true; continue; } + switch (found[1]) { + case 'disallowed': error = true; out += String.fromCodePoint(cp); break; + case 'mapped': out += String.fromCodePoint.apply(String, found[2]); break; + case 'valid': out += String.fromCodePoint(cp); break; + } + } + return { text: out, error: error }; +}; diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/package.json b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/package.json new file mode 100644 index 000000000..bc877e1e8 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/package.json @@ -0,0 +1 @@ +{ "name": "range-map", "version": "1.0.0", "main": "index.js", "types": "index.d.ts" } diff --git a/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/table.json b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/table.json new file mode 100644 index 000000000..900f9e316 --- /dev/null +++ b/tests/corpus/6410-json-mixed-scalar-tables/node_modules/range-map/table.json @@ -0,0 +1 @@ +[[[0,44],"disallowed"],[[45,46],"valid"],[[47,47],"disallowed"],[[48,57],"valid"],[[65,65],"mapped",[97]],[[66,67],"mapped",[98,99]],[[97,122],"valid"]] diff --git a/tests/corpus/6410-wrapper-untyped-results.ts b/tests/corpus/6410-wrapper-untyped-results.ts new file mode 100644 index 000000000..f8df7683a --- /dev/null +++ b/tests/corpus/6410-wrapper-untyped-results.ts @@ -0,0 +1,50 @@ +// Generic wrappers returning their untyped result `as F`: async functions, +// records with unknown fields, and rejections passing through. +function trace any>(name: string, fn: F): F { + return ((...args: Parameters) => { + console.log("span", name); + return fn(...args); + }) as F; +} +function traceThis any>(name: string, fn: F): F { + return function (this: unknown, ...args: Parameters) { + const result: unknown = fn.apply(this, args); + console.log("span", name, typeof result); + return result; + } as F; +} +function lookup(key: string): any { + return key === "set" ? 7 : undefined; +} +const fetchCount = trace("fetchCount", async (base: number): Promise => { + await null; + return base + 1; +}); +const fetchUser = traceThis("fetchUser", async (id: string): Promise<{ id: string; admin: boolean }> => ({ + id, + admin: id === "root", +})); +const fails = trace("fails", async (why: string): Promise => { + throw new Error(why); +}); +const summarize = trace("summarize", (limit = lookup("unset") ?? 2) => ({ kept: limit, dropped: 1 })); +const measure = traceThis("measure", (n: number) => ({ size: n, label: lookup("set") })); +async function main(): Promise { + console.log(await fetchCount(1)); + const user = await fetchUser("root"); + console.log(user.id, user.admin); + try { + await fails("nope"); + } catch (e) { + console.log("caught", e instanceof Error ? e.message : String(e)); + } + const s = summarize(); + console.log(s.kept, s.dropped, summarize(5).kept); + const m = measure(3); + console.log(m.size, m.label); + const pending = fetchCount(10); + console.log("before"); + console.log(await pending); +} +main(); +export {}; diff --git a/tests/corpus/6411-prototype-reset-constructors/issues.js b/tests/corpus/6411-prototype-reset-constructors/issues.js new file mode 100644 index 000000000..1058d7188 --- /dev/null +++ b/tests/corpus/6411-prototype-reset-constructors/issues.js @@ -0,0 +1,27 @@ +// An Error subclass in the shape of a validation library's: the constructor +// resets the prototype to new.target's, as transpiled code does. +export class IssueError extends Error { + constructor(issues) { + super(); + this.issues = []; + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } else { + this.__proto__ = actualProto; + } + this.name = "IssueError"; + this.issues = issues; + } + get message() { + return JSON.stringify(this.issues); + } + get isEmpty() { + return this.issues.length === 0; + } +} +export class StrictIssueError extends IssueError { + get strict() { + return true; + } +} diff --git a/tests/corpus/6411-prototype-reset-constructors/main.ts b/tests/corpus/6411-prototype-reset-constructors/main.ts new file mode 100644 index 000000000..65f155e8d --- /dev/null +++ b/tests/corpus/6411-prototype-reset-constructors/main.ts @@ -0,0 +1,33 @@ +// Constructors that reset the instance prototype, the transpiled idiom for +// Error subclasses. +import { IssueError, StrictIssueError } from "./issues.js"; +class AppError extends Error { + constructor(message: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + this.name = "AppError"; + } + describe(): string { + return `${this.name}: ${this.message}`; + } +} +class NotFound extends AppError { + constructor(what: string) { + super(`${what} not found`); + Object.setPrototypeOf(this, NotFound.prototype); + this.name = "NotFound"; + } +} +const app = new AppError("boom"); +const missing = new NotFound("user"); +console.log(app.describe(), app instanceof AppError, app instanceof Error); +console.log(missing.describe(), missing instanceof NotFound, missing instanceof AppError); +const issues = new IssueError([{ path: "a" }]); +console.log(issues.message, issues.isEmpty, issues instanceof IssueError, issues.name); +const strict = new StrictIssueError([]); +console.log(strict.isEmpty, strict.strict, strict instanceof IssueError, String(strict instanceof StrictIssueError)); +try { + throw new NotFound("page"); +} catch (e) { + console.log(e instanceof NotFound ? e.describe() : "other"); +} diff --git a/tests/corpus/6411-union-array-tuple-destructuring.ts b/tests/corpus/6411-union-array-tuple-destructuring.ts new file mode 100644 index 000000000..f62eba996 --- /dev/null +++ b/tests/corpus/6411-union-array-tuple-destructuring.ts @@ -0,0 +1,42 @@ +// Array destructuring of a value whose type is a union of array and tuple +// types: a regex match or a default row (`re.exec(s) || ["", "", ""]`), and +// functions answering either a fixed tuple or a list. Each position reads +// the arm the value holds; positions past a tuple's end and past an array's +// end read undefined, and defaults fire exactly there. +function scan(text: string): string { + const [match, head, word] = /(\w*)-(\w+)/.exec(text) || ["", "", ""]; + return `${match}|${head}|${word.toUpperCase()}`; +} +console.log(scan("ab-cd"), scan("none"), scan("-x")); + +function pick(flag: boolean): [string, number] | string[] { + return flag ? ["a", 1] : ["b", "c"]; +} +const [p, q] = pick(true); +const [r, s = "dflt", t = "z"] = pick(false); +const [u, , w = "w"] = pick(true); +console.log(p, q, r, s, t, u, w); +console.log(typeof q, typeof s); + +function pair(n: number): number[] | [number, number] { + return n > 1 ? [n, n * 2] : [n]; +} +const [x, y] = pair(7); +const [x1, y1 = -1] = pair(1); +console.log(x, y, x1, y1); + +function row(kind: string): [string, boolean] | [string, boolean, number] { + return kind === "long" ? [kind, true, 3] : [kind, false]; +} +for (const k of ["long", "short"]) { + const [name, flag, count = 0] = row(k); + console.log(name, flag, count); +} + +// A match or an empty string (`re.exec(s) || ""`): a string destructures +// by code point, so the empty string binds undefined. +function firstHit(text: string): string { + const [hit] = /\d+/.exec(text) || ""; + return hit ? `hit ${hit}` : "none"; +} +console.log(firstHit("ab12"), firstHit("ab")); diff --git a/tests/corpus/6412-js-error-tostring-override/errors.js b/tests/corpus/6412-js-error-tostring-override/errors.js new file mode 100644 index 000000000..839b57a67 --- /dev/null +++ b/tests/corpus/6412-js-error-tostring-override/errors.js @@ -0,0 +1,22 @@ +// JavaScript Error subclasses whose toString overrides infer results that +// differ from Error.prototype.toString's string. +export class IssueError extends Error { + constructor(issues) { + super("invalid"); + this.issues = issues; + this.name = "IssueError"; + } + /** @returns {string | undefined} */ + toString() { + return this.issues.length > 0 ? this.issues.join("; ") : undefined; + } +} +export class LabelError extends Error { + constructor(label, detail) { + super(detail); + this.label = label; + } + toString() { + return this.label; + } +} diff --git a/tests/corpus/6412-js-error-tostring-override/main.ts b/tests/corpus/6412-js-error-tostring-override/main.ts new file mode 100644 index 000000000..15a857efd --- /dev/null +++ b/tests/corpus/6412-js-error-tostring-override/main.ts @@ -0,0 +1,9 @@ +// TypeScript callers of JavaScript toString overrides whose inferred +// results differ from the inherited string. +import { IssueError, LabelError } from "./errors.js"; +const issues = new IssueError(["a is required", "b must be a number"]); +console.log(issues.toString()); +console.log(String(issues), `${new IssueError([])}`); +const errors: Error[] = [issues, new LabelError("db", "down"), new Error("plain")]; +for (const e of errors) console.log(e.toString(), e instanceof IssueError); +console.log(errors.map((e) => String(e)).join(" | ")); diff --git a/tests/corpus/6413-override-js-async-base/lock.js b/tests/corpus/6413-override-js-async-base/lock.js new file mode 100644 index 000000000..1ea00239d --- /dev/null +++ b/tests/corpus/6413-override-js-async-base/lock.js @@ -0,0 +1,22 @@ +// An untyped JavaScript lock whose async acquire resolves to an untyped +// ticket. +export class Lock { + constructor() { + this.held = false; + this.log = []; + this.queue = makeQueue(this.log); + } + async acquire() { + const ticket = await this.queue.wait(); + this.held = true; + this.log.push("base acquire"); + return ticket; + } + release() { + this.held = false; + } +} + +function makeQueue(log) { + return { wait: () => new Promise((resolve) => setTimeout(() => resolve(log.length), 1)) }; +} diff --git a/tests/corpus/6413-override-js-async-base/main.ts b/tests/corpus/6413-override-js-async-base/main.ts new file mode 100644 index 000000000..da0c0b183 --- /dev/null +++ b/tests/corpus/6413-override-js-async-base/main.ts @@ -0,0 +1,30 @@ +// TypeScript overrides returning Promise over an untyped JavaScript +// async method: an async override and a promise-returning one. +import { Lock } from "./lock.js"; +class TimedLock extends Lock { + waits = 0; + async acquire(): Promise { + this.waits++; + await super.acquire(); + this.log.push("timed acquire"); + } +} +class EagerLock extends Lock { + acquire(): Promise { + this.log.push("eager"); + return Promise.resolve(); + } +} +async function main(): Promise { + const locks: Lock[] = [new TimedLock(), new EagerLock(), new Lock()]; + for (const lock of locks) { + await lock.acquire(); + console.log(lock.held, lock.log.join(",")); + } + const timed = new TimedLock(); + await timed.acquire(); + console.log(timed.waits, timed.held); + const viaBase: Lock = new TimedLock(); + console.log(await new Lock().acquire(), await viaBase.acquire()); +} +main(); diff --git a/tests/corpus/6414-catch-values-roundtrip.ts b/tests/corpus/6414-catch-values-roundtrip.ts new file mode 100644 index 000000000..ebf62980e --- /dev/null +++ b/tests/corpus/6414-catch-values-roundtrip.ts @@ -0,0 +1,114 @@ +// Thrown values of every kind read back through catch bindings: primitives, +// arrays, plain objects, Errors and subclasses, undefined and null, through +// un-narrowed reads and through typeof, instanceof, Array.isArray and +// predicate narrowing. +class AppError extends Error { + code: string; + constructor(message: string, code: string) { + super(message); + this.name = "AppError"; + this.code = code; + } +} +interface Shaped { + kind: string; + size: number; +} +function isShaped(value: unknown): value is Shaped { + return typeof value === "object" && value !== null && "kind" in value && "size" in value; +} +// Each value is thrown at its own static type (values thrown from `unknown` +// storage are covered separately). +const letters = ["a", "b", "c"]; +const none: string[] = []; +const shapedValue: Shaped = { kind: "box", size: 3 }; +const emptyObject = {}; +const plainError = new Error("plain"); +const typeError = new TypeError("typed"); +const appError = new AppError("app", "E_APP"); +const thrown: unknown[] = [ + 5, + 0, + -1.5, + "text", + "", + true, + false, + letters, + none, + shapedValue, + emptyObject, + plainError, + typeError, + appError, + undefined, + null, +]; +function throwAt(index: number): never { + switch (index) { + case 0: + throw 5; + case 1: + throw 0; + case 2: + throw -1.5; + case 3: + throw "text"; + case 4: + throw ""; + case 5: + throw true; + case 6: + throw false; + case 7: + throw letters; + case 8: + throw none; + case 9: + throw shapedValue; + case 10: + throw emptyObject; + case 11: + throw plainError; + case 12: + throw typeError; + case 13: + throw appError; + case 14: + throw undefined; + default: + throw null; + } +} +function describe(index: number): string { + try { + throwAt(index); + } catch (e) { + const parts: string[] = [String(e === thrown[index])]; + if (typeof e === "number") parts.push(`number ${e + 1}`); + else if (typeof e === "string") parts.push(`string ${e.length}`); + else if (typeof e === "boolean") parts.push(`boolean ${!e}`); + else if (Array.isArray(e)) parts.push(`array ${e.length} ${e.join("+")}`); + else if (e instanceof AppError) parts.push(`app ${e.code} ${e.message}`); + else if (e instanceof Error) parts.push(`error ${e.name} ${e.message}`); + else if (isShaped(e)) parts.push(`shaped ${e.kind} ${e.size}`); + else if (e === undefined) parts.push("undefined"); + else if (e === null) parts.push("null"); + else parts.push(`other ${typeof e}`); + return parts.join(" "); + } +} +for (let i = 0; i < thrown.length; i++) console.log(i, describe(i)); +for (let i = 0; i < 10; i++) { + try { + if (i === 5) throw i; + } catch (e) { + console.log("loop", e === 5, e); + } +} +try { + throw ["x", "y"]; +} catch (e) { + const list = e as string[]; + console.log(list[0], list[1], list.length); +} diff --git a/tests/corpus/6415-error-code-dynamic-writes.ts b/tests/corpus/6415-error-code-dynamic-writes.ts new file mode 100644 index 000000000..f4c4d5628 --- /dev/null +++ b/tests/corpus/6415-error-code-dynamic-writes.ts @@ -0,0 +1,64 @@ +// An Error's code written through a dynamic view (a `catch (e: any)` +// binding), copied onto an Error subclass with Object.assign, set to +// undefined, or deleted is what typed reads and `'code' in err` see, on +// Errors and on Error subclasses. +class CodedError extends Error {} + +const original = new Error("a") as NodeJS.ErrnoException; +try { + throw original; +} catch (e: any) { + e.code = "E_ANY"; +} +console.log("any write", original.code, "code" in original); + +try { + throw original; +} catch (e: any) { + delete e.code; +} +console.log("any delete", original.code, "code" in original); + +function codeOf(err: NodeJS.ErrnoException): string | undefined { + return err.code; +} +const sub = new CodedError("b"); +Object.assign(sub, { code: "E_ASSIGN" }); +console.log("subclass assign", codeOf(sub), "code" in sub); + +const plain = new Error("c") as NodeJS.ErrnoException; +Object.assign(plain, { code: "E_PLAIN" }); +console.log("assign", plain.code, "code" in plain); + +const cleared = new Error("d") as NodeJS.ErrnoException; +cleared.code = undefined; +console.log("undefined", cleared.code, "code" in cleared); +const fresh = new Error("e") as NodeJS.ErrnoException; +console.log("fresh", fresh.code, "code" in fresh); + +const subCleared = new CodedError("f") as NodeJS.ErrnoException; +subCleared.code = undefined; +console.log("subclass undefined", subCleared.code, "code" in subCleared); +try { + throw subCleared; +} catch (e: any) { + console.log("subclass undefined through any", e.code, "code" in e); +} +subCleared.code = "E_SUB"; +console.log("subclass string", subCleared.code, "code" in subCleared); +try { + throw subCleared; +} catch (e: any) { + e.code = undefined; +} +console.log("subclass any undefined", subCleared.code, "code" in subCleared); +try { + throw subCleared; +} catch (e: any) { + delete e.code; +} +console.log("subclass delete", subCleared.code, "code" in subCleared); + +const subAssigned = new CodedError("g"); +Object.assign(subAssigned, { code: undefined }); +console.log("subclass assign undefined", codeOf(subAssigned), "code" in subAssigned); diff --git a/tests/corpus/6453-constructor-function-emitter.cjs b/tests/corpus/6453-constructor-function-emitter.cjs new file mode 100644 index 000000000..d07453e14 --- /dev/null +++ b/tests/corpus/6453-constructor-function-emitter.cjs @@ -0,0 +1,114 @@ +// Constructor functions that inherit from EventEmitter the pre-class way: +// util.inherits and EventEmitter.call(this), the call-without-new guard, +// prototype methods that emit, and the listener API over the instance. +"use strict"; +const util = require("util"); +const { EventEmitter } = require("events"); + +util.inherits(Bus, EventEmitter); +function Bus(name) { + if (!(this instanceof Bus)) return new Bus(name); + EventEmitter.call(this); + this.name = name; + this.entries = []; +} +Bus.prototype.add = function (entry) { + this.entries.push(entry); + this.emit("added", entry, this.entries.length); + return this; +}; + +// A second level: Sub inherits Bus, and Bus's constructor runs through call. +function Sub(name) { + Bus.call(this, name); + this.sub = true; +} +util.inherits(Sub, Bus); +Sub.prototype.add = function (entry) { + return Bus.prototype.add.call(this, entry.toUpperCase()); +}; + +// Object.setPrototypeOf instead of util.inherits. +function Legacy() { + EventEmitter.call(this); +} +Object.setPrototypeOf(Legacy.prototype, EventEmitter.prototype); + +function main() { + const bus = Bus("main"); + console.log(bus instanceof Bus, bus instanceof EventEmitter, Bus.super_ === EventEmitter); + console.log(Object.keys(bus).join(","), bus._eventsCount, bus._maxListeners); + bus.on("added", function (entry, count) { + console.log("added", entry, count, this === bus); + }); + bus.once("added", (entry) => console.log("first only", entry)); + bus.prependListener("added", () => console.log("prepended")); + bus.prependOnceListener("added", () => console.log("prepended once")); + bus.add("a").add("b"); + console.log(bus.listenerCount("added"), bus.eventNames(), bus.getMaxListeners()); + + const handler = () => console.log("never"); + bus.on("x", handler); + bus.on("x", () => console.log("kept")); + bus.off("x", handler); + console.log(bus.emit("x"), bus.emit("nothing"), bus.listeners("x").length, bus.rawListeners("added").length); + + try { + bus.emit("error", new Error("boom")); + } catch (err) { + console.log("caught", err.message); + } + try { + bus.emit("error", "plain"); + } catch (err) { + console.log("caught", err.code, err.message); + } + bus.on("error", (err) => console.log("handled", err.message)); + bus.emit("error", new Error("quiet")); + + bus.on("newListener", (event, listener) => console.log("newListener", event, typeof listener)); + bus.on("removeListener", (event) => console.log("removeListener", event)); + bus.on("later", () => {}); + bus.removeAllListeners("added"); + console.log(bus.listenerCount("added"), bus.listenerCount("later")); + bus.removeAllListeners(); + console.log(bus.eventNames().length); + + const sub = new Sub("child"); + sub.on("added", (entry) => console.log("sub added", entry)); + sub.add("c"); + console.log(sub instanceof Sub, sub instanceof Bus, sub instanceof EventEmitter, sub.entries); + + const legacy = new Legacy(); + console.log("legacy", legacy instanceof EventEmitter, legacy.getMaxListeners()); + try { + legacy.setMaxListeners(-1); + } catch (err) { + console.log(err.name, err.code); + } + try { + legacy.on("bad", "not a function"); + } catch (err) { + console.log(err.name, err.code); + } + console.log(new Legacy()); + + // The leak warning goes to stderr with the process id: run it in a child + // and print its output with the id normalized. + const { spawnSync } = require("child_process"); + const child = spawnSync(process.execPath, [process.argv[1], "leak"], { encoding: "utf8" }); + console.log(child.stdout + child.stderr.replace(/\(node:\d+\)/g, "(node:)")); +} + +function leak() { + const legacy = new Legacy(); + legacy.setMaxListeners(1); + legacy.on("many", () => {}); + legacy.on("many", () => {}); + legacy.on("many", () => {}); + console.log("leak", legacy.listenerCount("many")); + setTimeout(() => console.log("leak done"), 1); +} + +if (process.argv[2] === "leak") leak(); +else main(); diff --git a/tests/corpus/6454-constructor-function-stream-bases.cjs b/tests/corpus/6454-constructor-function-stream-bases.cjs new file mode 100644 index 000000000..4b2bb6789 --- /dev/null +++ b/tests/corpus/6454-constructor-function-stream-bases.cjs @@ -0,0 +1,65 @@ +// The legacy Stream constructor as a constructor function's base: its +// EventEmitter state and the legacy pipe between two such streams. The +// stream classes take util.inherits, and instanceof follows the chain. +"use strict"; +const util = require("util"); +const Stream = require("stream"); +const { Readable, Writable, Duplex, Transform, PassThrough } = require("stream"); + +function Source(items) { + Stream.call(this); + this.items = items; + this.readable = true; +} +util.inherits(Source, Stream); +Source.prototype.start = function () { + for (const item of this.items) this.emit("data", item); + this.emit("end"); +}; + +function Sink() { + Stream.call(this); + this.writable = true; + this.chunks = []; +} +util.inherits(Sink, Stream); +Sink.prototype.write = function (chunk) { + this.chunks.push(chunk); + return true; +}; +Sink.prototype.end = function () { + console.log("sink end", this.chunks.join("+")); +}; + +const source = new Source(["a", "b", "c"]); +const sink = new Sink(); +sink.on("pipe", (from) => console.log("piped", from === source)); +console.log(source.pipe(sink) === sink, sink.listenerCount("pipe")); +source.start(); +console.log("after end", source.listenerCount("data"), sink.listenerCount("drain")); + +const kept = new Sink(); +const second = new Source(["x"]); +second.pipe(kept, { end: false }); +second.start(); +console.log("kept open", kept.chunks); + +function Reader() {} +util.inherits(Reader, Readable); +function Both() {} +util.inherits(Both, Duplex); +function Shift() {} +util.inherits(Shift, Transform); +function Through() {} +util.inherits(Through, PassThrough); +function Out() {} +util.inherits(Out, Writable); +console.log(Reader.super_ === Readable, Through.super_ === PassThrough, Out.super_ === Writable); +const reader = Object.create(Reader.prototype); +const through = Object.create(Through.prototype); +const out = Object.create(Out.prototype); +const both = Object.create(Both.prototype); +console.log(reader instanceof Readable, reader instanceof Writable); +console.log(through instanceof Transform, through instanceof Duplex, through instanceof Readable); +console.log(out instanceof Writable, out instanceof Readable, both instanceof Readable); +console.log(typeof Shift.prototype.constructor, Shift.prototype instanceof Duplex); diff --git a/tests/corpus/6463-node-readable-stream-producers.ts b/tests/corpus/6463-node-readable-stream-producers.ts new file mode 100644 index 000000000..4d06fac94 --- /dev/null +++ b/tests/corpus/6463-node-readable-stream-producers.ts @@ -0,0 +1,75 @@ +// NodeJS.ReadableStream is the interface every Node readable implements. +// One helper typed with it consumes a file stream, a Readable subclass, +// Readable.from, a gunzip Transform fed through pipe(), and a child's +// stdout. A program that mixes those producers compiles the interface as +// the node:stream Readable, with the child's pipe bridged into one. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { Readable } from "node:stream"; +import * as zlib from "node:zlib"; + +function drain(label: string, src: NodeJS.ReadableStream): Promise { + return new Promise((resolve, reject) => { + let text = ""; + let chunks = 0; + src.on("data", (chunk: Buffer | string) => { + chunks++; + text += typeof chunk === "string" ? `[s]${chunk}` : chunk.toString("utf8"); + }); + src.on("error", (err) => reject(err)); + src.on("end", () => { + console.log(label, "end", chunks > 0, src.readable); + resolve(text); + }); + }); +} + +class Countdown extends Readable { + private left = 3; + _read(): void { + this.push(this.left > 0 ? `t-${this.left--};` : null); + } +} + +function openText(file: string): NodeJS.ReadableStream { + return fs.createReadStream(file); +} + +function openDecoded(file: string): NodeJS.ReadableStream { + const stream = fs.createReadStream(file); + stream.setEncoding("utf8"); + return stream; +} + +async function main(): Promise { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-readable-")); + const plain = path.join(dir, "plain.txt"); + const packed = path.join(dir, "packed.gz"); + fs.writeFileSync(plain, "hello from a file\n"); + fs.writeFileSync(packed, zlib.gzipSync(Buffer.from("inflated text\n"))); + + console.log(JSON.stringify(await drain("file", openText(plain)))); + console.log(JSON.stringify(await drain("decoded", openDecoded(plain)))); + console.log(JSON.stringify(await drain("subclass", new Countdown()))); + console.log(JSON.stringify(await drain("from", Readable.from(["a", "b", "c"])))); + const gunzip = fs.createReadStream(packed).pipe(zlib.createGunzip()); + console.log(JSON.stringify(await drain("gunzip", gunzip))); + + const child = spawn("sh", ["-c", "printf 'child line\\n'"], { + stdio: ["ignore", "pipe", "inherit"], + }); + const out = child.stdout; + if (out !== null) console.log(JSON.stringify(await drain("child", out))); + console.log("same stdout", child.stdout === out); + + try { + await drain("missing", openText(path.join(dir, "missing.txt"))); + } catch (err) { + console.log("missing", (err as NodeJS.ErrnoException).code); + } + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/corpus/6464-node-writable-stream-producers.ts b/tests/corpus/6464-node-writable-stream-producers.ts new file mode 100644 index 000000000..bc9986b9b --- /dev/null +++ b/tests/corpus/6464-node-writable-stream-producers.ts @@ -0,0 +1,68 @@ +// NodeJS.WritableStream is the interface every Node writable implements: +// process.stdout/stderr, fs.WriteStream and the node:stream Writable +// family. Helpers typed with it accept all of them, a copy helper pipes a +// file stream into one, and readable.pipe(process.stdout) leaves the +// process stream open afterwards, as in Node. +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { Readable, Writable } from "node:stream"; + +function emit(dst: NodeJS.WritableStream, line: string): boolean { + return dst.write(`${line}\n`); +} + +function copy(src: NodeJS.ReadableStream, dst: NodeJS.WritableStream): Promise { + return new Promise((resolve, reject) => { + src.on("error", reject); + dst.on("error", reject); + dst.on("finish", () => resolve()); + src.pipe(dst); + }); +} + +class Collector extends Writable { + readonly parts: string[] = []; + _write(chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void { + this.parts.push(chunk.toString("utf8")); + callback(); + } +} + +function finished(stream: NodeJS.WritableStream): Promise { + return new Promise((resolve) => { + stream.end(() => resolve()); + }); +} + +async function main(): Promise { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-writable-")); + const target = path.join(dir, "out.txt"); + const file = fs.createWriteStream(target); + console.log("file write", emit(file, "to a file")); + console.log("stdout write", emit(process.stdout, "to stdout")); + emit(process.stderr, "to stderr"); + const collector = new Collector(); + emit(collector, "to a collector"); + await finished(file); + await finished(collector); + console.log(JSON.stringify(fs.readFileSync(target, "utf8"))); + console.log(JSON.stringify(collector.parts)); + + const source = path.join(dir, "source.txt"); + const copied = path.join(dir, "copied.txt"); + fs.writeFileSync(source, "copied through pipe\n"); + await copy(fs.createReadStream(source), fs.createWriteStream(copied)); + console.log(JSON.stringify(fs.readFileSync(copied, "utf8"))); + + await new Promise((resolve) => { + const piped = Readable.from(["piped ", "to ", "stdout\n"]); + piped.on("end", () => resolve()); + console.log("pipe answers stdout", piped.pipe(process.stdout) === process.stdout); + }); + // The pipe did not end process.stdout. + emit(process.stdout, "still writable"); + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/corpus/6465-node-stream-js-boundary/consume.js b/tests/corpus/6465-node-stream-js-boundary/consume.js new file mode 100644 index 000000000..ceb8f3abf --- /dev/null +++ b/tests/corpus/6465-node-stream-js-boundary/consume.js @@ -0,0 +1,12 @@ +export function streamToText(stream) { + return new Promise((resolve, reject) => { + const chunks = []; + stream.on("data", (chunk) => chunks.push(Buffer.from(chunk))); + stream.on("error", reject); + stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8"))); + }); +} + +export function describeStream(stream) { + console.log(typeof stream.on, typeof stream.pipe, stream.readable); +} diff --git a/tests/corpus/6465-node-stream-js-boundary/main.ts b/tests/corpus/6465-node-stream-js-boundary/main.ts new file mode 100644 index 000000000..0079c0733 --- /dev/null +++ b/tests/corpus/6465-node-stream-js-boundary/main.ts @@ -0,0 +1,33 @@ +// NodeJS.ReadableStream values crossing into untyped JavaScript and into +// 'unknown': a file stream and a child's stdout share one helper with a +// JavaScript stream consumer, which sees ordinary Node streams. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { describeStream, streamToText } from "./consume.js"; + +function open(file: string): NodeJS.ReadableStream { + return fs.createReadStream(file); +} + +function textOf(stream: NodeJS.ReadableStream): Promise { + return streamToText(stream); +} + +async function main(): Promise { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-stream-js-")); + const file = path.join(dir, "input.txt"); + fs.writeFileSync(file, "through javascript\n"); + const held: unknown = open(file); + console.log(typeof held); + describeStream(held); + console.log(JSON.stringify(await textOf(open(file)))); + const child = spawn("sh", ["-c", "printf 'child output\\n'"], { + stdio: ["ignore", "pipe", "inherit"], + }); + if (child.stdout !== null) console.log(JSON.stringify(await textOf(child.stdout))); + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/corpus/6465-optional-members-over-index-signature.ts b/tests/corpus/6465-optional-members-over-index-signature.ts new file mode 100644 index 000000000..df957c8d9 --- /dev/null +++ b/tests/corpus/6465-optional-members-over-index-signature.ts @@ -0,0 +1,73 @@ +// An index signature whose value admits undefined already describes an +// optional member of the same type (`interface Env extends Dict +// { TZ?: string }`, @types/node's ProcessEnv): such a record is one key +// set in insertion order, so spread, delete, `in` and every enumeration +// treat the declared member like any other key. +interface Env { + TZ?: string; + [key: string]: string | undefined; +} + +const base: Env = { A: "1", TZ: "UTC", B: "2" }; +const env = { ...base }; +env.C = "3"; +for (const key of ["A", "TZ", "MISSING"]) { + delete env[key]; +} +console.log(Object.entries(env), Object.keys(base)); +const probe = (key: string): boolean => key in env; +console.log(probe("TZ"), probe("B"), env.TZ, env.B); +env.TZ = "Europe/Berlin"; +console.log(JSON.stringify(env), env); + +const extended: Env = { ...base, D: "4" }; +delete extended.TZ; +extended.TZ = "Asia/Tokyo"; +console.log(extended, Object.keys(extended).join(",")); + +// A declared member written after another key comes after it. +interface Scores { + best?: number; + [name: string]: number | undefined; +} +const scores: Scores = {}; +scores["x"] = 1; +scores.best = 2; +console.log(Object.keys(scores), JSON.stringify(scores)); + +// The process environment has the same shape; a child environment built +// from it keeps the parent's keys in order. +process.env.SCX_FIRST = "first"; +process.env.SCX_DROP = "drop"; +process.env.SCX_LAST = "last"; +const DROP = ["SCX_DROP", "SCX_NOT_SET"]; +function childEnv(): string[] { + const runEnv = { ...process.env }; + runEnv.SCX_ADDED = "added"; + for (const key of DROP) { + delete runEnv[key]; + } + runEnv.SCX_FIRST = runEnv.SCX_FIRST ? `${runEnv.SCX_FIRST}!` : "none"; + return Object.entries(runEnv) + .filter(([key]) => key.startsWith("SCX_")) + .map(([key, value]) => `${key}=${value || ""}`); +} +console.log(childEnv()); + +// A record of declared optional members over a slot without undefined is +// the same key set: merging it over the process environment keeps both. +type Dictionary = { [key: string]: T }; +type BuildEnv = { CI?: string; DEBUG?: string } & Dictionary; +function merged(buildEnv: BuildEnv): string[] { + const env = { ...process.env, ...buildEnv }; + return [ + String(env.CI === "1" || env.SCX_FIRST === "first"), + `${env.DEBUG ?? "-"}`, + Object.keys(env) + .filter((key) => key.startsWith("SCX_") || key === "CI" || key === "DEBUG") + .join(","), + ]; +} +const buildEnv: BuildEnv = { SCX_BUILD: "b", CI: "1" }; +buildEnv.DEBUG = "yes"; +console.log(merged(buildEnv), Object.keys(buildEnv), buildEnv.CI, buildEnv["SCX_BUILD"]); diff --git a/tests/corpus/6466-never-assertion-argument.ts b/tests/corpus/6466-never-assertion-argument.ts new file mode 100644 index 000000000..8d2c1f2bf --- /dev/null +++ b/tests/corpus/6466-never-assertion-argument.ts @@ -0,0 +1,31 @@ +// `value as never` makes an unknown value fit any parameter: the argument +// is checked against the parameter's type like any unknown value the +// checker admits there, and a typed value passes unchanged. +type Out = { routes: { src: string; dest?: string }[]; count: number }; + +function show(tags: Record): void { + console.log(JSON.stringify(tags)); +} + +function report(tag: (result: Out) => Record, value: unknown): void { + show(tag(value as never)); +} + +const describe = (r: Out): Record => ({ count: r.count, first: r.routes[0]?.src }); +report(describe, JSON.parse('{"routes":[{"src":"/a"},{"src":"/b","dest":"/c"}],"count":2}')); + +// Through a promise of unknown, the way a wrapper tags an async result. +function later(value: Out): Promise { + return Promise.resolve(value); +} +later({ routes: [], count: 7 }).then((value) => { + show(describe(value as never)); +}); + +// A typed value keeps its identity through the assertion. +function bump(target: Out): void { + target.count++; +} +const typed: Out = { routes: [{ src: "/x" }], count: 1 }; +bump(typed as never); +console.log(typed.count); diff --git a/tests/corpus/6466-node-stdio-stream-surface.ts b/tests/corpus/6466-node-stdio-stream-surface.ts new file mode 100644 index 000000000..d3726360f --- /dev/null +++ b/tests/corpus/6466-node-stdio-stream-surface.ts @@ -0,0 +1,45 @@ +// The stdio handles reach the full stream surface when a program uses it: +// child.stdout piped to process.stdout, a file stream piped into a +// child's stdin, and an 'error' listener on a NodeJS.WritableStream +// parameter that only receives the process streams. Each of these +// compiles the NodeJS stream interfaces as the node:stream classes. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; + +function report(out: NodeJS.WritableStream, text: string): void { + out.on("error", (err) => console.log("error", err.message)); + out.write(`${text}\n`); +} + +function echo(text: string): Promise { + return new Promise((resolve) => { + const child = spawn("sh", ["-c", `echo ${text}`], { stdio: ["ignore", "pipe", "inherit"] }); + child.stdout?.pipe(process.stdout); + child.on("close", (code) => resolve(code)); + }); +} + +function cat(input: string): Promise { + return new Promise((resolve) => { + const child = spawn("cat", [], { stdio: ["pipe", "pipe", "inherit"] }); + child.stdout?.pipe(process.stdout); + child.on("close", (code) => resolve(code)); + if (child.stdin) fs.createReadStream(input).pipe(child.stdin); + }); +} + +async function main(): Promise { + report(process.stdout, "reported"); + report(process.stderr, "reported to stderr"); + console.log("echo exit", await echo("piped from a child")); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-stdio-")); + const input = path.join(dir, "input.txt"); + fs.writeFileSync(input, "file contents through cat\n"); + console.log("cat exit", await cat(input)); + report(process.stdout, "stdout stays open"); + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/corpus/6467-fromentries-record-assertion.ts b/tests/corpus/6467-fromentries-record-assertion.ts new file mode 100644 index 000000000..cf8f1c1ff --- /dev/null +++ b/tests/corpus/6467-fromentries-record-assertion.ts @@ -0,0 +1,43 @@ +// `Object.fromEntries(...) as T` for a declared record T keeps exactly +// the keys the entries created, in their order, as Node keeps the object +// itself, as long as the entries hold scalars or checked-dynamic values. +type Tags = { "error.type": string; "error.msg": string; "error.cause"?: string }; + +function scrub(input: string): string { + return input.replace(/secret/g, "***"); +} + +function redact(tags: Tags): Tags { + return Object.fromEntries( + Object.entries(tags).map(([key, value]) => [key, typeof value === "string" ? scrub(value) : value]), + ) as Tags; +} + +const e = new Error("a secret here"); +const plain = redact({ "error.type": e.name, "error.msg": e.message }); +console.log(plain, Object.keys(plain), "error.cause" in plain, plain["error.msg"].length); +const caused = redact({ "error.type": "TypeError", "error.msg": "m", "error.cause": "secret cause" }); +console.log(caused, JSON.stringify(caused)); + +// Keys the record does not declare stay with the object. +type Point = { x: number; y: number }; +const p = Object.fromEntries([ + ["y", 2], + ["x", 1], + ["z", 3], +]) as Point; +console.log(p, p.x + p.y, Object.keys(p), JSON.stringify(p)); + +// Entries held as unknown keep their identity: the object's members are +// the same array and record, and writes through either reach both. +type Holder = { list: number[]; point: { x: number } }; +const list = [1, 2]; +const point = { x: 1 }; +const entries: [string, unknown][] = [ + ["list", list], + ["point", point], +]; +const held = Object.fromEntries(entries) as Holder; +held.list.push(3); +held.point.x = 5; +console.log(list.length, point.x, held.list === list, held.point === point); diff --git a/tests/corpus/6467-node-stream-untyped-sources/main.ts b/tests/corpus/6467-node-stream-untyped-sources/main.ts new file mode 100644 index 000000000..5cb3a628d --- /dev/null +++ b/tests/corpus/6467-node-stream-untyped-sources/main.ts @@ -0,0 +1,58 @@ +// Streams that arrive untyped meet NodeJS stream interface slots: an +// untyped JavaScript function's stream returned as NodeJS.ReadableStream, +// a checked cast from 'unknown', pipe() and pipeline() into untyped +// destinations, and 'for await' over a NodeJS.ReadableStream +// parameter fed by a file stream and a child's stdout. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { pipeline } from "node:stream/promises"; +import * as zlib from "node:zlib"; +import { collector, joined, openUntyped } from "./sources.js"; + +function open(file: string): NodeJS.ReadableStream { + return openUntyped(file); +} + +function held(file: string): unknown { + return fs.createReadStream(file); +} + +async function collect(label: string, src: NodeJS.ReadableStream): Promise { + let text = ""; + for await (const chunk of src) text += chunk.toString(); + console.log(label, JSON.stringify(text)); +} + +async function main(): Promise { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-stream-untyped-")); + const plain = path.join(dir, "plain.txt"); + const packed = path.join(dir, "packed.gz"); + fs.writeFileSync(plain, "plain text\n"); + fs.writeFileSync(packed, zlib.gzipSync(Buffer.from("packed text\n"))); + + await collect("returned", open(plain)); + await collect("cast", held(plain) as NodeJS.ReadableStream); + const child = spawn("sh", ["-c", "printf 'child text\\n'"], { stdio: ["ignore", "pipe", "inherit"] }); + if (child.stdout) await collect("child", child.stdout); + + await new Promise((resolve) => { + const piped = fs.createReadStream(plain); + piped.on("end", () => resolve()); + piped.pipe(collector()); + }); + console.log("pipe", JSON.stringify(joined())); + + const sink = collector(); + await pipeline(openUntyped(packed), zlib.createGunzip(), sink); + console.log("pipeline", JSON.stringify(joined())); + try { + await pipeline(openUntyped(path.join(dir, "missing.gz")), zlib.createGunzip(), collector()); + } catch (err) { + console.log("pipeline error", (err as NodeJS.ErrnoException).code); + } + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/corpus/6467-node-stream-untyped-sources/sources.js b/tests/corpus/6467-node-stream-untyped-sources/sources.js new file mode 100644 index 000000000..ce4b5dcb7 --- /dev/null +++ b/tests/corpus/6467-node-stream-untyped-sources/sources.js @@ -0,0 +1,20 @@ +import * as fs from "node:fs"; +import { PassThrough } from "node:stream"; + +const parts = []; + +/** @returns {any} */ +export function openUntyped(file) { + return fs.createReadStream(file); +} + +/** @returns {any} */ +export function collector() { + const sink = new PassThrough(); + sink.on("data", (chunk) => parts.push(chunk.toString("utf8"))); + return sink; +} + +export function joined() { + return parts.splice(0).join(""); +} diff --git a/tests/corpus/6468-generic-unknown-record-entries.ts b/tests/corpus/6468-generic-unknown-record-entries.ts new file mode 100644 index 000000000..f0e57756a --- /dev/null +++ b/tests/corpus/6468-generic-unknown-record-entries.ts @@ -0,0 +1,33 @@ +// Inside a generic body, `Object.entries(tags)` over `T extends +// Record` reads `[string, T[keyof T]]` elements. An +// instance whose T is the unknown-valued record view reads every member +// as unknown; a record instance reads the union of its member types. +function upper(text: string): string { + return text.toUpperCase(); +} + +function scrub(text: string): string { + return text.replace(/secret/g, "***"); +} + +function describe>(tags: T): string[] { + return Object.entries(tags).map( + ([key, value]) => `${key}=${typeof value === "string" ? upper(value) : String(value)}`, + ); +} + +function redact>(tags: T): T { + return Object.fromEntries( + Object.entries(tags).map(([key, value]) => [key, typeof value === "string" ? scrub(value) : value]), + ) as T; +} + +function flatten(value: unknown): Record { + return typeof value === "object" && value !== null ? (value as Record) : { value }; +} + +console.log(describe(flatten({ b: 1, a: "x", c: true }))); +console.log(describe(flatten(5))); +console.log(describe({ name: "n", size: 3 })); +const cleaned = redact(flatten({ token: "secret", count: 2 })); +console.log(cleaned, Object.keys(cleaned)); diff --git a/tests/corpus/6468-node-stdio-writable-slot.ts b/tests/corpus/6468-node-stdio-writable-slot.ts new file mode 100644 index 000000000..a326344d1 --- /dev/null +++ b/tests/corpus/6468-node-stdio-writable-slot.ts @@ -0,0 +1,49 @@ +// process.stdout and process.stderr in NodeJS.WritableStream slots of a +// program that also passes other streams there: every slot holds the same +// stream object, a pipe through such a slot leaves the process stream +// open, and Writable's listener methods return the stream for chaining. +import { Readable, Writable } from "node:stream"; + +class Sink extends Writable { + _write(_chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void { + callback(); + } +} + +function same(a: NodeJS.WritableStream, b: NodeJS.WritableStream): boolean { + return a === b; +} + +function pipeInto(dst: NodeJS.WritableStream, parts: string[]): Promise { + return new Promise((resolve) => { + const src = Readable.from(parts); + src.on("end", () => resolve()); + src.pipe(dst); + }); +} + +function write(dst: NodeJS.WritableStream, text: string): boolean { + return dst.write(text); +} + +async function main(): Promise { + console.log("stdout same", same(process.stdout, process.stdout)); + console.log("stderr same", same(process.stderr, process.stderr)); + console.log("stdout and stderr", same(process.stdout, process.stderr)); + console.log("sink and stdout", same(new Sink(), process.stdout)); + + await pipeInto(process.stdout, ["piped ", "through ", "a slot\n"]); + // The pipe did not end process.stdout: writes through a slot still work. + console.log("write after pipe", write(process.stdout, "still open\n")); + await pipeInto(process.stderr, ["piped to stderr\n"]); + write(process.stderr, "stderr still open\n"); + + // Writable's listener methods return the stream. + const sink = new Sink(); + await new Promise((resolve) => { + sink.on("finish", () => resolve()).end("done"); + }); + console.log("sink finished", sink.writableFinished); +} + +void main(); diff --git a/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts b/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts new file mode 100644 index 000000000..258755f83 --- /dev/null +++ b/tests/corpus/6469-node-stdio-writable-js-pipe/main.ts @@ -0,0 +1,36 @@ +// process.stdout and process.stderr reach an untyped JavaScript helper +// through NodeJS.WritableStream slots, and the helper pipes into them. As +// in Node, the pipe leaves the process stream open, so later writes +// through the same slots still work. +import { Readable, Writable } from "node:stream"; +import { pipeAll } from "./pipe.js"; + +class Sink extends Writable { + readonly parts: string[] = []; + _write(chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void { + this.parts.push(chunk.toString("utf8")); + callback(); + } +} + +function into(destination: NodeJS.WritableStream, parts: string[]): Promise { + return new Promise((resolve) => { + pipeAll(Readable.from(parts), destination, () => resolve()); + }); +} + +function write(destination: NodeJS.WritableStream, text: string): boolean { + return destination.write(text); +} + +async function main(): Promise { + const sink = new Sink(); + await into(sink, ["to ", "a sink"]); + console.log("sink", JSON.stringify(sink.parts), sink.writableEnded); + await into(process.stdout, ["piped ", "by javascript\n"]); + console.log("write after pipe", write(process.stdout, "still open\n")); + await into(process.stderr, ["piped to stderr\n"]); + write(process.stderr, "stderr still open\n"); +} + +void main(); diff --git a/tests/corpus/6469-node-stdio-writable-js-pipe/pipe.js b/tests/corpus/6469-node-stdio-writable-js-pipe/pipe.js new file mode 100644 index 000000000..d48d592ad --- /dev/null +++ b/tests/corpus/6469-node-stdio-writable-js-pipe/pipe.js @@ -0,0 +1,4 @@ +export function pipeAll(source, destination, done) { + source.on("end", () => done()); + source.pipe(destination); +} diff --git a/tests/corpus/6470-stream-transform-any-data-callback.ts b/tests/corpus/6470-stream-transform-any-data-callback.ts new file mode 100644 index 000000000..cc4935a7e --- /dev/null +++ b/tests/corpus/6470-stream-transform-any-data-callback.ts @@ -0,0 +1,60 @@ +// Transform option callbacks whose completion callback declares an +// any-typed `data` (the @types/node TransformCallback spelling): the data +// passed back may be a Buffer, a string, or omitted. +import { PassThrough, Transform } from "node:stream"; +import { createGunzip, gzipSync } from "node:zlib"; + +type Done = (error?: Error | null, data?: any) => void; + +interface Progress { + bytes: number; + chunks: number; +} + +function counting(progress: Progress): Transform { + return new Transform({ + transform(chunk: Buffer, _encoding: string, callback: Done) { + progress.bytes += chunk.length; + progress.chunks++; + callback(null, chunk); + }, + }); +} + +const upper = new Transform({ + transform(chunk: Buffer, _encoding: string, callback: Done) { + const text = chunk.toString(); + if (text === "skip") { + callback(); + return; + } + callback(null, text.toUpperCase()); + }, + flush(callback: Done) { + callback(null, Buffer.from("!")); + }, +}); +upper.on("data", (d: Buffer) => console.log("upper", JSON.stringify(d.toString()))); +upper.on("end", () => console.log("upper end")); +upper.write("hello"); +upper.write("skip"); +upper.end("world"); + +const failing = new Transform({ + transform(chunk: Buffer, _encoding: string, callback: Done) { + callback(new Error(`refused ${chunk.length} bytes`)); + }, +}); +failing.on("error", (e: Error) => console.log("error", e.message)); +failing.write("abc"); + +const progress: Progress = { bytes: 0, chunks: 0 }; +const counter = counting(progress); +const out = new PassThrough(); +counter.pipe(createGunzip()).pipe(out); +const parts: string[] = []; +out.on("data", (d: Buffer) => parts.push(d.toString())); +out.on("end", () => { + console.log("gunzip", JSON.stringify(parts.join("")), progress.bytes > 0, progress.chunks); +}); +counter.end(gzipSync(Buffer.from("compressed payload"))); diff --git a/tests/corpus/6471-stream-data-buffer-or-string.ts b/tests/corpus/6471-stream-data-buffer-or-string.ts new file mode 100644 index 000000000..69289ced5 --- /dev/null +++ b/tests/corpus/6471-stream-data-buffer-or-string.ts @@ -0,0 +1,44 @@ +// 'data' listeners on runtime streams may declare the chunk as +// `Buffer | string` (the @types/node ReadStream listener type): the +// listener receives a Buffer, or a string once an encoding applies. +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { PassThrough, Readable } from "node:stream"; + +function describe(label: string, chunk: Buffer | string): void { + if (typeof chunk === "string") console.log(label, "string", JSON.stringify(chunk)); + else console.log(label, "buffer", chunk.length, JSON.stringify(chunk.toString())); +} + +const raw = new PassThrough(); +raw.on("data", (chunk: Buffer | string) => describe("raw", chunk)); +raw.write("abc"); +raw.end(Buffer.from("de")); + +const text = new PassThrough(); +text.setEncoding("utf8"); +text.on("data", (chunk: Buffer | string) => describe("text", chunk)); +text.end("héllo"); + +const r = new Readable({ read() {} }); +r.on("data", (chunk: Buffer | string) => describe("readable", chunk)); +r.on("end", () => console.log("readable end")); +r.push("one"); +r.push(null); + +const file = path.join(os.tmpdir(), `scriptc-6471-${process.pid}.txt`); +fs.writeFileSync(file, "file contents\n"); +const stream = fs.createReadStream(file); +const release = (): void => console.log("released"); +stream.on("data", (chunk: Buffer | string) => describe("file", chunk)); +stream.on("close", release); +stream.on("error", release); +stream.on("end", () => { + const encoded = fs.createReadStream(file, { encoding: "utf8" }); + encoded.on("data", (chunk: Buffer | string) => describe("file utf8", chunk)); + encoded.on("close", () => { + fs.unlinkSync(file); + console.log("done"); + }); +}); diff --git a/tests/corpus/6472-child-data-unknown-chunk.ts b/tests/corpus/6472-child-data-unknown-chunk.ts new file mode 100644 index 000000000..8308aa8cf --- /dev/null +++ b/tests/corpus/6472-child-data-unknown-chunk.ts @@ -0,0 +1,87 @@ +// A child stream 'data' listener whose chunk is unknown or any receives a +// Buffer, or a string when setEncoding ran before the listener registered. +import { spawn } from "node:child_process"; + +function report(code: number | null, kinds: string[], stdout: string, stderr: string): void { + console.log("code", code, "kinds", [...new Set(kinds)].join(",")); + console.log("stdout", JSON.stringify(stdout)); + console.log("stderr", JSON.stringify(stderr)); +} + +function runEncoded(script: string): Promise { + return new Promise((resolve) => { + const child = spawn("/bin/sh", ["-c", script], { stdio: "pipe" }); + let stdout = ""; + let stderr = ""; + const kinds: string[] = []; + if (child.stdout) { + child.stdout.setEncoding("utf8"); + child.stdout.on("data", (c: any) => { + kinds.push(typeof c); + stdout += c; + }); + } + const err = child.stderr; + if (err !== null) { + err.setEncoding("utf8"); + err.on("data", (c: unknown) => { + kinds.push(typeof c); + stderr += String(c); + }); + } + child.on("close", (code) => { + report(code, kinds, stdout, stderr); + resolve(); + }); + }); +} + +function runRaw(script: string): Promise { + return new Promise((resolve) => { + const child = spawn("/bin/sh", ["-c", script], { stdio: "pipe" }); + let stdout = ""; + let stderr = ""; + const kinds: string[] = []; + child.stdout?.on("data", (c: unknown) => { + kinds.push(Buffer.isBuffer(c) ? "buffer" : typeof c); + stdout += String(c); + }); + if (child.stderr) { + child.stderr.on("data", (c: any) => { + const chunk = String(c); + kinds.push(Buffer.isBuffer(c) ? "buffer" : typeof c); + stderr += chunk; + }); + } + child.on("close", (code) => { + report(code, kinds, stdout, stderr); + resolve(); + }); + }); +} + +// setEncoding through one const alias of the stream and the listener +// through another: both name child.stdout, so chunks are strings. +function runAliased(script: string): Promise { + return new Promise((resolve) => { + const child = spawn("/bin/sh", ["-c", script], { stdio: "pipe" }); + const encoded = child.stdout!; + const listened = child.stdout!; + let stdout = ""; + const kinds: string[] = []; + encoded.setEncoding("utf8"); + listened.on("data", (c: unknown) => { + kinds.push(typeof c); + stdout += String(c); + }); + child.on("close", (code) => { + report(code, kinds, stdout, ""); + resolve(); + }); + }); +} + +runEncoded("printf 'h\\303\\251llo'; echo warn >&2") + .then(() => runRaw("printf raw; echo oops >&2; exit 2")) + .then(() => runAliased("printf alias")) + .then(() => console.log("done")); diff --git a/tests/corpus/6490-literal-key-field-updates.ts b/tests/corpus/6490-literal-key-field-updates.ts new file mode 100644 index 000000000..f90739c31 --- /dev/null +++ b/tests/corpus/6490-literal-key-field-updates.ts @@ -0,0 +1,132 @@ +// Read-modify-write through a key whose type is a union of literal field +// names (`totals[side] += n`): every compound operator, ++/-- and logical +// assignment dispatch over the declared fields the key can name. The +// receiver and key evaluate once, before the right side. +type Side = "sent" | "received"; +interface Traffic { + sent: number; + received: number; + label: string; + updatedAt: number; +} + +const traffic: Traffic = { sent: 0, received: 0, label: "link", updatedAt: 0 }; + +function record(side: Side, bytes: number): void { + traffic[side] += bytes; + traffic.updatedAt++; +} +record("sent", 120); +record("received", 64); +record("sent", 8); +console.log(JSON.stringify(traffic)); + +function adjust(side: Side): string { + const parts: number[] = []; + parts.push((traffic[side] -= 3)); + parts.push((traffic[side] *= 2)); + parts.push((traffic[side] /= 4)); + parts.push((traffic[side] %= 7)); + parts.push((traffic[side] **= 2)); + parts.push((traffic[side] |= 1)); + parts.push((traffic[side] &= 0xff)); + parts.push((traffic[side] ^= 0x0f)); + parts.push((traffic[side] <<= 2)); + parts.push((traffic[side] >>= 1)); + parts.push((traffic[side] >>>= 1)); + return parts.join(","); +} +console.log(adjust("sent"), adjust("received")); + +// ++ and -- in statement and value positions, prefix and postfix. +const sides: Side[] = ["sent", "received", "sent"]; +for (const s of sides) traffic[s]++; +for (const s of sides) --traffic[s]; +const post = traffic[sides[1]!]--; +const pre = ++traffic[sides[0]!]; +console.log(post, pre, traffic.sent, traffic.received); + +// One literal key, spelled at the site or carried by a const. +traffic["sent"] += 1000; +const fixed = "received"; +traffic[fixed] -= 1; +traffic["received"]++; +console.log(traffic.sent, traffic.received); + +// Evaluation order: receiver, key, old value, right side, write. +let trace = ""; +function pick(s: Side): Side { + trace += `key:${s};`; + return s; +} +function target(): Traffic { + trace += "receiver;"; + return traffic; +} +function amount(n: number): number { + trace += `rhs:${n};`; + return n; +} +console.log((target()[pick("received")] += amount(5)), trace); +trace = ""; +console.log(target()[pick("sent")]++, trace); +trace = ""; +let current = traffic; +function swap(): number { + current = { sent: -1, received: -1, label: "other", updatedAt: 0 }; + return 1; +} +current[pick("sent")] += swap(); +console.log(traffic.sent, current.sent, trace); + +// The right side throws after the old value is read: nothing is written. +function fail(): number { + throw new Error("rhs failed"); +} +try { + traffic[pick("received")] *= fail(); +} catch (e) { + if (e instanceof Error) console.log(e.message, traffic.received); +} + +// String fields append. +type Part = "head" | "tail"; +const text: { head: string; tail: string; size: number } = { head: "a", tail: "z", size: 0 }; +function append(p: Part, s: string): string { + return (text[p] += s); +} +console.log(append("head", "bc"), append("tail", "yx"), append("head", "!")); +console.log(JSON.stringify(text)); + +// Optional fields with ??=: only a missing value takes the right side. +type Phase = "dns" | "connect" | "tls"; +const timings: { dns?: number; connect?: number; tls?: number; total: number } = { total: 0 }; +function mark(phase: Phase, at: number): number { + return (timings[phase] ??= at); +} +console.log(mark("dns", 4), mark("connect", 9), mark("dns", 12), mark("tls", 0), mark("tls", 7)); +console.log(timings.dns, timings.connect, timings.tls, timings.total); + +// ||= and &&= test truthiness and write only in the selected branch. +const flags = { quiet: false, verbose: true, color: false }; +type Flag = keyof typeof flags; +function settle(f: Flag, value: boolean): string { + const a = (flags[f] ||= value); + const b = (flags[f] &&= f !== "color"); + return `${f}:${a}:${b}`; +} +console.log(settle("quiet", true), settle("verbose", false), settle("color", true)); +console.log(JSON.stringify(flags)); + +// Nested receivers and keys from a typed lookup. +const stats = { day: { hits: 1, misses: 2 }, week: { hits: 10, misses: 20 } }; +type Window = keyof typeof stats; +type Outcome = "hits" | "misses"; +const events: [Window, Outcome][] = [ + ["day", "hits"], + ["week", "misses"], + ["day", "misses"], + ["day", "hits"], +]; +for (const [w, o] of events) stats[w][o] += 1; +console.log(JSON.stringify(stats)); diff --git a/tests/corpus/6491-index-record-updates.ts b/tests/corpus/6491-index-record-updates.ts new file mode 100644 index 000000000..108d34012 --- /dev/null +++ b/tests/corpus/6491-index-record-updates.ts @@ -0,0 +1,44 @@ +// Compound assignment and ++/-- through a string key of an +// index-signature record: a missing entry reads as undefined, which every +// numeric operator turns into NaN, and the write inserts or replaces it. +const counts: Record = {}; +const words = "the cat and the hat and the bat".split(" "); +for (const w of words) { + counts[w] ??= 0; + counts[w]++; +} +console.log(JSON.stringify(counts)); + +const sums: { [key: string]: number } = { a: 1, b: 2 }; +sums["a"] += 10; +sums.b *= 3; +const key = "a"; +sums[key] -= 1; +console.log(JSON.stringify(sums)); + +// A missing entry: undefined op number is NaN, and the value form yields it. +console.log((sums["missing"] += 1), sums["missing"], Number.isNaN(sums["missing"])); +const later = sums["gone"]++; +console.log(later, sums["gone"], Object.keys(sums).join(",")); + +// Totals keyed by a runtime string, with the key and right side evaluated once. +let trace = ""; +function name(n: string): string { + trace += `key:${n};`; + return n; +} +function size(n: number): number { + trace += `rhs:${n};`; + return n; +} +const totals: Record = { disk: 0, net: 0 }; +const samples: [string, number][] = [ + ["disk", 4], + ["net", 7], + ["disk", 2], +]; +for (const [k, v] of samples) totals[name(k)] += size(v); +console.log(JSON.stringify(totals), trace); +const before = totals["net"]--; +const after = --totals["net"]; +console.log(before, after, totals["net"]); diff --git a/tests/corpus/fs-extra-package/main.ts b/tests/corpus/fs-extra-package/main.ts index e152a287c..1c91a7000 100644 --- a/tests/corpus/fs-extra-package/main.ts +++ b/tests/corpus/fs-extra-package/main.ts @@ -139,6 +139,25 @@ async function main(): Promise { fs.copySync(linkSrc, relinkDest); console.log(shown(root, fs.readlinkSync(path.join(relinkDest, "entry")))); + // A destination directory symlink back into the source tree: each entry + // is checked against its destination, so the copy stops there instead + // of replacing the source's own file. + const loopSrc = path.join(root, "loop-src"); + fs.mkdirSync(path.join(loopSrc, "sub"), { recursive: true }); + fs.writeFileSync(path.join(loopSrc, "sub", "keep.txt"), "source"); + const loopDest = path.join(root, "loop-dest"); + fs.mkdirSync(loopDest); + fs.symlinkSync(path.join(loopSrc, "sub"), path.join(loopDest, "sub")); + for (const sync of [true, false]) { + try { + if (sync) fs.copySync(loopSrc, loopDest); + else await fs.copy(loopSrc, loopDest); + } catch (err) { + console.log(shown(root, (err as Error).message)); + } + console.log(fs.readFileSync(path.join(loopSrc, "sub", "keep.txt"), "utf8")); + } + console.log(await readStream(file)); console.log((await fs.promises.readFile(file, "utf8")).length); console.log(fs.readFileSync(file, "utf8").length); diff --git a/tests/corpus/webassembly-api.mjs b/tests/corpus/webassembly-api.mjs new file mode 100644 index 000000000..5215cd3a2 --- /dev/null +++ b/tests/corpus/webassembly-api.mjs @@ -0,0 +1,179 @@ +// The WebAssembly JavaScript API over modules translated to native code when +// the program is built: compile, instantiate, validate, Module, Instance, +// exported functions, memories, tables and globals, imports, linking two +// instances, every trap, link errors, the error classes, externref values +// and the asynchronous entry points. The modules are inline base64 literals +// (their text is in tests/wasm-spec/corpus/*.wat). +const api = Buffer.from("AGFzbQEAAAABLwlgAX8Bf2ACf38Bf2ABfwBgAABgAAF/YAJ+fgF+YAJ/fwJ/f2ABfQF9YAN/f38AAi0EA2VudgNsb2cAAgNlbnYEZmFpbAAAA2VudgRiYXNlA38AA2VudgNiaWcDfgADEhEAAAMBAQQFBgcAAAQAAAAICAQFAXABAggFBAEBAQQGFwN/AUEAC3wARAAAAAAAAApAC34AIwELB5kBEwZtZW1vcnkCAAV0YWJsZQEAB2NvdW50ZXIDAgJwaQMDBGJpZzIDBANhZGQABQVhcHBseQAGBGJ1bXAABwVtdWw2NAAIBmRpdm1vZAAJBm5hcnJvdwAKBnN0cmxlbgALBGdyb3cADAVwYWdlcwANCGNhbGxGYWlsAA4EdHJhcAAPB3JlY3Vyc2UAEARmaWxsABEEY29weQASCAEECQgBAEEACwICAwqHAhEHACAAQQJsCwcAIAAgAGwLBgAjABAACwcAIAAgAWoLCQAgASAAEQAACwsAIwJBAWokAiMCCwcAIAAgAX4LDAAgACABbSAAIAFvCwQAIAALIAEBfwJAA0AgACABai0AAEUNASABQQFqIQEMAAsLIAELBgAgAEAACwQAPwALCQAgABABQQFqC1kAAkACQAJAAkACQAJAAkAgAA4GAAECAwQFBgsAC0EBQQBuDwtB/////wcoAgAPC0EBQQJBABEBAA8LQQFBBxEAAA8LRAAAAAAAAPh/qg8LQYCAgIB4QX9tCwwAIABBAWoQEEEBagsLACAAIAEgAvwLAAsMACAAIAEgAvwKAAALCw4BAEEQCwhzY3JpcHRjAA==", "base64"); +const linked = Buffer.from("AGFzbQEAAAABFwRgAn9/AX9gAX8Bf2ABfwBgA39/fwF/AjYEA2FwaQZtZW1vcnkCAAEDYXBpBXRhYmxlAXAAAgNhcGkHY291bnRlcgN/AQNhcGkDYWRkAAADBQQBAAIDBycEBHJlYWQAAQh1c2VUYWJsZQACCnNldENvdW50ZXIAAwRhZGQzAAQKJwQHACAALQAACwkAIAEgABEBAAsGACAAJAALDAAgACABEAAgAhAACw==", "base64"); +const refs = Buffer.from("AGFzbQEAAAABHwZgAW8Bb2ACf28AYAF/AW9gAW8Bf2ACb38Bf2AAAX8DBwYAAQIDBAUEBQFvAQEKBgYBbwHQbwsHPAgEcmVmcwEABHNsb3QDAARrZWVwAAAFc3RvcmUAAQRsb2FkAAIGaXNOdWxsAAMEZ3JvdwAEBHNpemUABQosBgQAIAALCAAgACABJgALBgAgACUACwUAIADRCwkAIAAgAfwPAAsFAPwQAAs=", "base64"); + +const show = (v) => { + if (typeof v === "bigint") return `${v}n`; + if (Array.isArray(v)) return `[${v.map(show).join(", ")}]`; + return String(v); +}; +const attempt = (label, f) => { + try { + console.log(label, show(f())); + } catch (e) { + console.log(label, e instanceof Error ? `${e.name}: ${e.message}` : `threw ${show(e)}`); + } +}; + +console.log(WebAssembly.validate(api), WebAssembly.validate(new Uint8Array([1, 2, 3]))); +attempt("validate(5)", () => WebAssembly.validate(5)); +const module = new WebAssembly.Module(api); +console.log(module instanceof WebAssembly.Module, module instanceof WebAssembly.Instance, String(module)); +console.log(module); + +const logged = []; +const env = { + log: (v) => logged.push(`log ${v}`), + fail(v) { + if (v < 0) throw new RangeError(`negative ${v}`); + return v * 10; + }, + base: 41, + big: 9007199254740993n, +}; +const instance = new WebAssembly.Instance(module, { env }); +console.log(logged.join(","), instance instanceof WebAssembly.Instance); +const x = instance.exports; +console.log(Object.keys(x).join(","), Object.isFrozen(x), Object.getPrototypeOf(x)); +console.log(x.add.name, x.add.length, typeof x.add, x.add === instance.exports.add); + +attempt("add", () => x.add(2, 3)); +attempt("add coerced", () => x.add("40", { valueOf: () => 2 })); +attempt("add wraps", () => x.add(0x7fffffff, 1)); +attempt("add missing", () => x.add(5)); +attempt("apply double", () => x.apply(0, 21)); +attempt("apply square", () => x.apply(1, 12)); +attempt("bump", () => [x.bump(), x.bump(), x.counter.value]); +x.counter.value = 100; +attempt("bump after set", () => x.bump()); +attempt("pi", () => x.pi.value); +attempt("set pi", () => { + x.pi.value = 1; +}); +attempt("big2", () => x.big2.value); +attempt("mul64", () => x.mul64(123456789n, 1000000007n)); +attempt("mul64 wraps", () => x.mul64(-1n, 2n ** 63n)); +attempt("mul64 number", () => x.mul64(1, 2)); +attempt("divmod", () => x.divmod(-17, 5)); +attempt("narrow", () => x.narrow(0.1)); +attempt("strlen", () => x.strlen(16)); + +const bytes = new Uint8Array(x.memory.buffer); +console.log(bytes.length, String.fromCharCode(...bytes.subarray(16, 23))); +console.log(x.memory instanceof WebAssembly.Memory, x.table instanceof WebAssembly.Table, x.counter instanceof WebAssembly.Global); +attempt("grow", () => x.grow(1)); +attempt("pages", () => x.pages()); +console.log(x.memory.buffer.byteLength); +attempt("memory.grow", () => x.memory.grow(1)); +attempt("memory.grow too far", () => x.memory.grow(2)); +console.log(x.memory.buffer.byteLength, x.pages()); +attempt("grow too far in wasm", () => x.grow(5)); +x.fill(100, 0x41, 5); +x.copy(200, 100, 5); +console.log(String.fromCharCode(...new Uint8Array(x.memory.buffer, 200, 5))); +attempt("fill out of bounds", () => x.fill(x.memory.buffer.byteLength - 2, 0, 5)); + +attempt("callFail", () => x.callFail(4)); +attempt("callFail throws", () => x.callFail(-1)); +for (let k = 0; k <= 6; k++) attempt(`trap ${k}`, () => x.trap(k)); +attempt("recurse", () => x.recurse(0)); +try { + x.trap(0); +} catch (e) { + console.log( + e instanceof WebAssembly.RuntimeError, + e instanceof Error, + e instanceof WebAssembly.LinkError, + Object.keys(e).length, + Object.prototype.hasOwnProperty.call(e, "name"), + ); +} +attempt("after traps", () => x.add(1, 1)); + +console.log(x.table.length); +attempt("table.get out of range", () => x.table.get(5)); +attempt("table.grow", () => x.table.grow(1)); +console.log(x.table.length); +x.table.set(2, x.add); +console.log(x.table.get(2) === x.add, x.table.length); +attempt("table.get past the end", () => x.table.get(3)); + +const linkedInstance = new WebAssembly.Instance(new WebAssembly.Module(linked), { api: x }); +const y = linkedInstance.exports; +attempt("read", () => y.read(16)); +attempt("useTable", () => y.useTable(1, 9)); +attempt("useTable signature", () => y.useTable(2, 9)); +attempt("useTable null", () => y.useTable(3, 9)); +y.setCounter(7); +attempt("shared counter", () => x.counter.value); +attempt("add3", () => y.add3(1, 2, 3)); + +attempt("no imports", () => new WebAssembly.Instance(module)); +attempt("missing module", () => new WebAssembly.Instance(module, {})); +attempt("imports not an object", () => new WebAssembly.Instance(module, 5)); +attempt("not callable", () => new WebAssembly.Instance(module, { env: { ...env, log: 1 } })); +attempt("global type", () => new WebAssembly.Instance(module, { env: { ...env, base: "x" } })); +attempt("bigint global", () => new WebAssembly.Instance(module, { env: { ...env, big: 1 } })); +attempt("memory import", () => + new WebAssembly.Instance(new WebAssembly.Module(linked), { + api: { memory: {}, table: x.table, counter: x.counter, add: x.add }, + }), +); +attempt("mutable global as number", () => + new WebAssembly.Instance(new WebAssembly.Module(linked), { + api: { memory: x.memory, table: x.table, counter: 1, add: x.add }, + }), +); +attempt("signature mismatch", () => + new WebAssembly.Instance(new WebAssembly.Module(linked), { + api: { memory: x.memory, table: x.table, counter: x.counter, add: x.bump }, + }), +); +attempt("Instance(5)", () => new WebAssembly.Instance(5)); +attempt("Module(5)", () => new WebAssembly.Module(5)); +try { + new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 2, 0, 0, 0])); +} catch (e) { + console.log(e.name, e instanceof WebAssembly.CompileError, e instanceof Error); +} + +const custom = new WebAssembly.RuntimeError("custom", { cause: 5 }); +console.log(String(custom), custom.name, custom.message, custom.cause); +console.log(custom instanceof WebAssembly.RuntimeError, custom instanceof WebAssembly.CompileError, custom instanceof Error); +console.log(String(WebAssembly.LinkError("called")), String(new WebAssembly.CompileError())); + +const z = new WebAssembly.Instance(new WebAssembly.Module(refs)).exports; +const token = { id: 1 }; +console.log(z.keep(token) === token, z.keep(null), z.keep(undefined), z.isNull(null), z.isNull(undefined), z.isNull(0)); +z.store(0, token); +console.log(z.load(0) === token, z.refs.get(0) === token); +attempt("grow refs", () => z.grow("filler", 3)); +console.log(z.size(), z.load(2), z.refs.length); +z.slot.value = token; +console.log(z.slot.value === token); +attempt("store out of range", () => z.store(10, token)); + +const order = []; +const compiled = WebAssembly.compile(api) + .then((m) => { + order.push(`compiled ${m instanceof WebAssembly.Module}`); + return WebAssembly.instantiate(m, { env }); + }) + .then((i) => { + order.push(`instance ${i instanceof WebAssembly.Instance} ${i.exports.add(1, 1)}`); + }); +const pair = WebAssembly.instantiate(api, { env }).then((result) => { + order.push(`pair ${Object.keys(result).join(",")} ${result.instance.exports.add(2, 2)}`); +}); +const rejected = WebAssembly.compile(new Uint8Array([1])).catch((e) => order.push(`rejected ${e.name}`)); +const typeError = WebAssembly.instantiate(5).catch((e) => order.push(`${e.name}: ${e.message}`)); +const linkError = WebAssembly.instantiate(api, {}).catch((e) => order.push(`${e.name}: ${e.message}`)); +await Promise.all([compiled, pair, rejected, typeError, linkError]); +console.log(order.sort().join("\n")); +console.log(logged.length); diff --git a/tests/corpus/webassembly-dylink/LICENSE.quickjs-wasi b/tests/corpus/webassembly-dylink/LICENSE.quickjs-wasi new file mode 100644 index 000000000..5a2e99d85 --- /dev/null +++ b/tests/corpus/webassembly-dylink/LICENSE.quickjs-wasi @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Vercel, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tests/corpus/webassembly-dylink/extensions.js b/tests/corpus/webassembly-dylink/extensions.js new file mode 100644 index 000000000..8c6b26feb --- /dev/null +++ b/tests/corpus/webassembly-dylink/extensions.js @@ -0,0 +1,372 @@ +/** + * WASM Dynamic Linking - Extension Loader + * + * Loads WASM shared libraries (.so) compiled with wasi-sdk as extensions + * for the QuickJS WASM runtime. Extensions can call QuickJS C API functions + * directly through dynamic linking (shared memory + symbol resolution). + * + * Key concepts: + * - Extensions are WASM shared libraries with a `dylink.0` custom section + * - They share linear memory and the indirect function table with the main module + * - Symbol imports (env.*) are resolved against the main module's exports + * - Each extension gets a unique __memory_base and __table_base + * - Extensions export an init function (e.g., `qjs_ext_url_init`) + */ +const decoder = new TextDecoder(); +/** + * Parse a null-terminated "key=value\nkey=value" string from WASM memory + * into a Record. Used to read version info from extensions. + */ +function parseVersionString(memory, ptr) { + const mem = new Uint8Array(memory.buffer); + let end = ptr; + while (mem[end] !== 0) + end++; + if (end === ptr) + return {}; + const str = decoder.decode(mem.slice(ptr, end)); + const result = {}; + for (const line of str.split('\n')) { + const eq = line.indexOf('='); + if (eq > 0) { + result[line.slice(0, eq)] = line.slice(eq + 1); + } + } + return result; +} +/** + * Check if an extension exports a versions function and parse the result. + */ +function extractExtensionVersions(ext, memory) { + const versionsFnName = `qjs_ext_${ext.name.replace(/-/g, '_')}_versions`; + const versionsFn = ext.instance.exports[versionsFnName]; + if (typeof versionsFn !== 'function') + return undefined; + const ptr = versionsFn(); + if (ptr === 0) + return undefined; + return parseVersionString(memory, ptr); +} +// ---- dylink.0 parser ---- +/** Read a ULEB128-encoded integer from a byte array */ +function readULEB128(bytes, offset) { + let result = 0; + let shift = 0; + while (offset.value < bytes.length) { + const byte = bytes[offset.value++]; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) === 0) + break; + shift += 7; + } + return result; +} +/** Parse the dylink.0 custom section from a WASM module */ +export function parseDylink(module) { + const sections = WebAssembly.Module.customSections(module, 'dylink.0'); + if (sections.length === 0) + return null; + const bytes = new Uint8Array(sections[0]); + const offset = { value: 0 }; + const info = { + memorySize: 0, + memoryAlignment: 0, + tableSize: 0, + tableAlignment: 0, + needed: [], + }; + while (offset.value < bytes.length) { + const subsectionType = readULEB128(bytes, offset); + const subsectionSize = readULEB128(bytes, offset); + const subsectionEnd = offset.value + subsectionSize; + if (subsectionType === 1) { + // WASM_DYLINK_MEM_INFO + info.memorySize = readULEB128(bytes, offset); + info.memoryAlignment = readULEB128(bytes, offset); + info.tableSize = readULEB128(bytes, offset); + info.tableAlignment = readULEB128(bytes, offset); + } + else if (subsectionType === 2) { + // WASM_DYLINK_NEEDED + const count = readULEB128(bytes, offset); + for (let i = 0; i < count; i++) { + const len = readULEB128(bytes, offset); + const name = new TextDecoder().decode(bytes.slice(offset.value, offset.value + len)); + offset.value += len; + info.needed.push(name); + } + } + offset.value = subsectionEnd; + } + return info; +} +// ---- Alignment helper ---- +/** Align a value up to 2^align */ +function alignUp(value, align) { + if (align <= 0) + return value; + const mask = (1 << align) - 1; + return (value + mask) & ~mask; +} +// ---- Extension Loader ---- +/** + * Load a WASM shared library extension and link it against the main module. + * + * @param descriptor - Extension description (name, wasm bytes, init function) + * @param mainExports - The main QuickJS WASM module's exports + * @param wasiBuiltins - Built-in WASI implementations (lowest priority) + * @param wasiUserOverrides - User-provided WASI overrides (highest priority) + * @param memoryProxy - A memory proxy for extension WASI factories + * @param allocBase - Optional fixed memory/table bases (for snapshot restore) + */ +export async function loadExtension(descriptor, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy, allocBase) { + // Compile the extension module + let module; + if (descriptor.wasm instanceof WebAssembly.Module) { + module = descriptor.wasm; + } + else { + module = await WebAssembly.compile(descriptor.wasm); + } + // Parse dylink.0 section + const dylink = parseDylink(module); + if (!dylink) { + throw new Error(`Extension "${descriptor.name}" is not a WASM shared library (missing dylink.0 section)`); + } + const memory = mainExports.memory; + const table = mainExports.__indirect_function_table; + const stackPointer = mainExports.__stack_pointer; + const mallocFn = mainExports.malloc; + if (!memory) + throw new Error('Main module does not export memory'); + if (!table) + throw new Error('Main module does not export __indirect_function_table'); + if (!mallocFn) + throw new Error('Main module does not export malloc'); + // Allocate memory region for the extension's static data + let memoryBase; + let tableBase; + if (allocBase) { + // Restore mode: use the exact same bases as before + memoryBase = allocBase.memoryBase; + tableBase = allocBase.tableBase; + } + else { + // Fresh allocation + if (dylink.memorySize > 0) { + // Use malloc from the main module to allocate in the shared heap + memoryBase = mallocFn(dylink.memorySize); + if (memoryBase === 0) { + throw new Error(`Failed to allocate ${dylink.memorySize} bytes for extension "${descriptor.name}"`); + } + // Zero-initialize the region + new Uint8Array(memory.buffer, memoryBase, dylink.memorySize).fill(0); + } + else { + memoryBase = 0; + } + } + // Grow the function table if needed + if (allocBase) { + tableBase = allocBase.tableBase; + // Ensure table is large enough + if (tableBase + dylink.tableSize > table.length) { + table.grow(tableBase + dylink.tableSize - table.length); + } + } + else { + tableBase = table.length; + if (dylink.tableSize > 0) { + table.grow(dylink.tableSize); + } + } + // Build the import object + const extImports = WebAssembly.Module.imports(module); + const importObj = { + env: {}, + 'GOT.mem': {}, + 'GOT.func': {}, + }; + // Provide wasi_snapshot_preview1 imports to extensions that need them. + // Layered merge: builtins → extension-provided → user overrides. + const needsWasi = extImports.some((imp) => imp.module === 'wasi_snapshot_preview1'); + if (needsWasi) { + const extWasi = (descriptor.wasi && memoryProxy) ? descriptor.wasi(memoryProxy) : undefined; + importObj['wasi_snapshot_preview1'] = { + ...wasiBuiltins, // 1. Built-in defaults (lowest priority) + ...extWasi, // 2. Extension-provided + ...wasiUserOverrides // 3. User overrides (highest priority) + }; + } + // Collect names of functions the extension exports (for self-resolution) + const extExportNames = new Set(WebAssembly.Module.exports(module) + .filter((e) => e.kind === 'function') + .map((e) => e.name)); + const unresolvedFuncs = new Set(); + for (const imp of extImports) { + if (imp.module === 'env') { + if (imp.name === 'memory' && imp.kind === 'memory') { + importObj.env.memory = memory; + } + else if (imp.name === '__indirect_function_table' && + imp.kind === 'table') { + importObj.env.__indirect_function_table = table; + } + else if (imp.name === '__memory_base' && imp.kind === 'global') { + importObj.env.__memory_base = new WebAssembly.Global({ value: 'i32', mutable: false }, memoryBase); + } + else if (imp.name === '__table_base' && imp.kind === 'global') { + importObj.env.__table_base = new WebAssembly.Global({ value: 'i32', mutable: false }, tableBase); + } + else if (imp.name === '__stack_pointer' && imp.kind === 'global') { + importObj.env.__stack_pointer = stackPointer; + } + else if (imp.kind === 'function') { + // Resolve function imports from the main module's exports + const resolved = mainExports[imp.name]; + if (resolved && typeof resolved === 'function') { + importObj.env[imp.name] = resolved; + } + else { + // Provide a trap stub for unresolved symbols (e.g., C++ runtime + // functions like wstring methods that are imported but never called). + // If actually called at runtime, this will throw. + unresolvedFuncs.add(imp.name); + importObj.env[imp.name] = () => { + throw new Error(`Extension "${descriptor.name}" called unresolved symbol: env.${imp.name}`); + }; + } + } + else if (imp.kind === 'global') { + // Other globals - try to resolve from main exports + const resolved = mainExports[imp.name]; + if (resolved instanceof WebAssembly.Global) { + importObj.env[imp.name] = resolved; + } + else { + // Create a zero-initialized mutable global as fallback + importObj.env[imp.name] = new WebAssembly.Global({ value: 'i32', mutable: true }, 0); + } + } + } + else if (imp.module === 'GOT.mem' && imp.kind === 'global') { + // GOT.mem entries are mutable globals containing memory addresses of symbols + // Try to resolve the symbol's address - for now, create mutable globals + // that can be patched by __wasm_apply_data_relocs + importObj['GOT.mem'][imp.name] = new WebAssembly.Global({ value: 'i32', mutable: true }, 0); + } + else if (imp.module === 'GOT.func' && imp.kind === 'global') { + // GOT.func entries are mutable globals containing table indices of functions. + // We resolve these by finding the function in the main module's exports, + // adding it to the indirect function table, and providing the table index. + const resolved = mainExports[imp.name]; + if (resolved && typeof resolved === 'function') { + const idx = table.length; + table.grow(1); + table.set(idx, resolved); + importObj['GOT.func'][imp.name] = new WebAssembly.Global({ value: 'i32', mutable: true }, idx); + } + else { + importObj['GOT.func'][imp.name] = new WebAssembly.Global({ value: 'i32', mutable: true }, 0); + } + } + } + // Self-resolve: in WASM shared libraries, the linker with --allow-undefined + // may leave symbols as both imports and exports (e.g., C++ weak symbols from + // libc++ string.cpp.o that satisfy references from ada.o). We use indirection + // through mutable wrapper functions: first create wrappers that initially trap, + // then instantiate, then patch the wrappers to forward to the instance's own exports. + // This way all internal calls go through the wrappers which point to the final exports. + const selfResolvable = [...unresolvedFuncs].filter((name) => extExportNames.has(name)); + // For self-resolvable symbols, create mutable wrappers + const wrappers = {}; + for (const name of selfResolvable) { + const wrapper = { target: null }; + wrappers[name] = wrapper; + // Replace the trap stub with a wrapper that forwards to the target + importObj.env[name] = (...args) => { + if (!wrapper.target) { + throw new Error(`Extension "${descriptor.name}" called unresolved symbol during init: env.${name}`); + } + return wrapper.target(...args); + }; + } + const instance = await WebAssembly.instantiate(module, importObj); + const extExports = instance.exports; + // Patch wrappers to point to the instance's own exports + for (const name of selfResolvable) { + const selfExport = extExports[name]; + if (typeof selfExport === 'function') { + wrappers[name].target = selfExport; + } + } + // Apply data relocations if the extension has them + if (typeof extExports.__wasm_apply_data_relocs === 'function') { + extExports.__wasm_apply_data_relocs(); + } + // Call constructors if present + if (typeof extExports.__wasm_call_ctors === 'function') { + extExports.__wasm_call_ctors(); + } + const initFn = descriptor.initFn ?? `qjs_ext_${descriptor.name.replace(/-/g, '_')}_init`; + const ext = { + name: descriptor.name, + module, + instance, + dylink, + memoryBase, + tableBase, + initFn, + }; + // Check for version reporting + ext.versions = extractExtensionVersions(ext, memory); + return ext; +} +/** + * Call the extension's init function, passing the JSContext and JSRuntime + * pointers from the main module. + */ +export function initExtension(ext, mainExports) { + const initFunc = ext.instance.exports[ext.initFn]; + if (typeof initFunc !== 'function') { + throw new Error(`Extension "${ext.name}" does not export init function "${ext.initFn}"`); + } + // Get the JSContext and JSRuntime pointers from the main module + const ctxPtr = mainExports.qjs_get_context_ptr(); + const rtPtr = mainExports.qjs_get_runtime_ptr(); + // Call the extension's init function: qjs_ext_xxx_init(ctx, rt) + const result = initFunc(ctxPtr, rtPtr); + if (result !== 0) { + throw new Error(`Extension "${ext.name}" init function returned error code ${result}`); + } +} +/** + * Re-instantiate extensions for snapshot restore. + * + * During restore, we need to: + * 1. Instantiate extension modules with the same memory/table bases + * 2. Let them populate the function table (via elem segments and __wasm_apply_data_relocs) + * 3. Do NOT call the init function (the state is already in the snapshot memory) + * + * This reconstructs the function table entries that extensions need, without + * modifying linear memory (which will be overwritten by the snapshot). + */ +export async function restoreExtensions(descriptors, extensionMeta, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy) { + const loaded = []; + for (const meta of extensionMeta) { + // Find the descriptor for this extension + const descriptor = descriptors.find((d) => d.name === meta.name); + if (!descriptor) { + throw new Error(`Extension "${meta.name}" required by snapshot but not provided`); + } + // Load with fixed bases + const ext = await loadExtension(descriptor, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy, { + memoryBase: meta.memoryBase, + tableBase: meta.tableBase, + }); + ext.initFn = meta.initFn; + loaded.push(ext); + } + return loaded; +} +//# sourceMappingURL=extensions.js.map \ No newline at end of file diff --git a/tests/corpus/webassembly-dylink/main.mjs b/tests/corpus/webassembly-dylink/main.mjs new file mode 100644 index 000000000..42237b1f1 --- /dev/null +++ b/tests/corpus/webassembly-dylink/main.mjs @@ -0,0 +1,101 @@ +// quickjs-wasi's WebAssembly extension loader, run through its own code: +// extensions.js is dist/extensions.js of quickjs-wasi 3.6.2, unmodified +// (MIT, LICENSE.quickjs-wasi). It parses the dylink.0 custom section +// (WebAssembly.Module.customSections), reads the extension's imports and +// exports (Module.imports, Module.exports), allocates the extension's data +// in the main module's memory, grows the shared function table and stores +// main-module functions in it (table.grow, table.set), creates +// __memory_base, __table_base and GOT globals (new WebAssembly.Global), and +// instantiates the extension against the main module's memory, table and +// stack pointer. The two modules stand in for quickjs.wasm and an +// extension .so; their text is in tests/wasm-spec/corpus/dylink-*.wat. +import { initExtension, loadExtension, parseDylink } from "./extensions.js"; + +const mainBytes = Buffer.from( + "AGFzbQEAAAABEANgAX8Bf2AAAX9gAn9/AX8DBwYAAQECAgAEBAFwAAQFAwEAAgYTA38BQYCABAt/AUGACAt/AUEACweOAQkGbWVtb3J5AgAZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAD19fc3RhY2tfcG9pbnRlcgMABm1hbGxvYwAAE3Fqc19nZXRfY29udGV4dF9wdHIAARNxanNfZ2V0X3J1bnRpbWVfcHRyAAILanNfcmVnaXN0ZXIAAwdqc19jYWxsAAQGaGVscGVyAAUKXAYXAQF/IwEhASMBIABqQQ9qQXBxJAEgAQsFAEHkAAsFAEHIAQsZAEGABCMCQQRsaiABNgIAIwJBAWokAiMCCxMAIAFBgAQgAEEEbGooAgARAAALCAAgAEHoB2oL", + "base64", +); +const extBytes = Buffer.from( + "AGFzbQEAAAABEwRgAX8Bf2ACf38Bf2AAAGAAAX8C0AEKA2VudgZtZW1vcnkCAAEDZW52GV9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUBcAAAA2Vudg9fX3N0YWNrX3BvaW50ZXIDfwEDZW52DV9fbWVtb3J5X2Jhc2UDfwADZW52DF9fdGFibGVfYmFzZQN/AAdHT1QubWVtB2NvdW50ZXIDfwEIR09ULmZ1bmMGaGVscGVyA38BA2Vudgtqc19yZWdpc3RlcgABA2Vudg5taXNzaW5nX3N5bWJvbAAAA2VudgtzZWxmX3N5bWJvbAAAAwwLAAACAgEDAAAAAwMHogEJGF9fd2FzbV9hcHBseV9kYXRhX3JlbG9jcwAFEV9fd2FzbV9jYWxsX2N0b3JzAAYRcWpzX2V4dF9kZW1vX2luaXQABxVxanNfZXh0X2RlbW9fdmVyc2lvbnMACAtzZWxmX3N5bWJvbAAJCHVzZV9zZWxmAAoLdXNlX21pc3NpbmcACw1zdGFja19wb2ludGVyAAwMYnVtcF9jb3VudGVyAA0JCAEAIwILAgMECnYLBwAgAEEDbAsJACAAIwQRAAALCQAjAUEgaiQDCwkAIwNBBTYCAAsZACAAIwIQABogACMCQQFqEAAaIAFByAFrCwQAIwELBwAgAEEBagsGACAAEAILBgAgABABCwQAIwALFAAjAyMDKAIAQQFqNgIAIwMoAgALCxwBACMBCxZuYW1lPWRlbW8KdmVyc2lvbj0xLjIAABoIZHlsaW5rLjABBDACAgACCQEHbGliYy5zbw==", + "base64", +); +// A module without a dylink.0 section (tests/wasm-spec/corpus/jsapi-own.wat). +const plainBytes = Buffer.from( + "AGFzbQEAAAABBgFgAX8BfwMCAQAEBQFwAQIIBQQBAQEEBhICfwFBBwt8AEQAAAAAAAD4PwsHKgcDbWVtAgAEbWVtMgIAA3RhYgEAAWcDAAJnMgMABWZpeGVkAwECaWQAAAkHAQBBAQsBAAoGAQQAIAAL", + "base64", +); + +const failure = (e) => (e instanceof Error ? `${e.name}: ${e.message}` : `threw ${String(e)}`); + +const { instance } = await WebAssembly.instantiate(mainBytes, {}); +const mainExports = instance.exports; +const table = mainExports.__indirect_function_table; + +console.log("dylink", JSON.stringify(parseDylink(new WebAssembly.Module(extBytes)))); +console.log("plain dylink", parseDylink(new WebAssembly.Module(plainBytes))); + +const ext = await loadExtension({ name: "demo", wasm: extBytes }, mainExports, {}, {}, null); +console.log("loaded", ext.name, ext.memoryBase, ext.tableBase, ext.initFn); +console.log("versions", JSON.stringify(ext.versions)); +console.log("dylink", JSON.stringify(ext.dylink)); +console.log("table length", table.length, table.get(6) === mainExports.helper); +// The extension's own functions in the shared table, called from here. +const triple = table.get(4); +console.log("table functions", triple(14), table.get(5) === table.get(5), triple.name, triple.length); +console.log("module", ext.module instanceof WebAssembly.Module, ext.instance instanceof WebAssembly.Instance); + +initExtension(ext, mainExports); +console.log("js_call", mainExports.js_call(0, 7), mainExports.js_call(1, 5)); +const x = ext.instance.exports; +console.log("self symbol", x.use_self(41)); +try { + x.use_missing(1); +} catch (e) { + console.log("missing symbol", failure(e)); +} +console.log("stack pointer", x.stack_pointer(), mainExports.__stack_pointer.value); +mainExports.__stack_pointer.value = 60000; +console.log("shared stack pointer", x.stack_pointer()); +console.log("counter", x.bump_counter(), x.bump_counter()); +console.log("memory", new Uint32Array(mainExports.memory.buffer, ext.memoryBase + 32, 1)[0]); + +// Snapshot restore (what restoreExtensions does per extension): the same +// bases, from a compiled Module, without init. +const restored = await loadExtension( + { name: "demo", wasm: new WebAssembly.Module(extBytes) }, + mainExports, + {}, + {}, + null, + { memoryBase: ext.memoryBase, tableBase: ext.tableBase }, +); +console.log("restored", restored.memoryBase, restored.tableBase, table.length); +console.log("restored counter", restored.instance.exports.bump_counter()); + +// A second extension instance gets its own bases. +const second = await loadExtension({ name: "demo", wasm: extBytes }, mainExports, {}, {}, null); +console.log("second", second.memoryBase, second.tableBase, table.length); +initExtension(second, mainExports); +console.log("js_call", mainExports.js_call(2, 10), mainExports.js_call(3, 10)); + +async function tryLoad(label, wasm, exports) { + try { + await loadExtension({ name: label, wasm }, exports, {}, {}, null); + console.log(label, "loaded"); + } catch (e) { + console.log(label, failure(e)); + } +} +await tryLoad("plain", plainBytes, mainExports); +await tryLoad("no memory", extBytes, { ...mainExports, memory: undefined }); +await tryLoad("no table", extBytes, { ...mainExports, __indirect_function_table: undefined }); +try { + initExtension({ ...ext, initFn: "qjs_ext_none_init" }, mainExports); +} catch (e) { + console.log("init", failure(e)); +} +try { + initExtension(ext, { ...mainExports, qjs_get_runtime_ptr: () => 201 }); +} catch (e) { + console.log("init", failure(e)); +} diff --git a/tests/corpus/webassembly-externref-lifetimes.mjs b/tests/corpus/webassembly-externref-lifetimes.mjs new file mode 100644 index 000000000..6d61d9c93 --- /dev/null +++ b/tests/corpus/webassembly-externref-lifetimes.mjs @@ -0,0 +1,44 @@ +// Externref values the guest holds stay alive until it is done with them: +// an import's result returned through an export, and a table's or global's +// reference read into a local before the guest or JavaScript replaces it. +// Each object is created fresh, so the runtime holds the only reference. +// (The module's text is in tests/wasm-spec/corpus/externref-lifetimes.wat.) +const bytes = Buffer.from("AGFzbQEAAAABCAJgAAFvYAAAAhgCA2VudgRtYWtlAAADZW52BWNsZWFyAAEDBQQAAAAABAQBbwABBgYBbwHQbwsHQQYEc2xvdAMABWNlbGxzAQAEcGFzcwACCnRha2VHbG9iYWwAAwl0YWtlVGFibGUABA50YWtlQWNyb3NzQ2FsbAAFCjUEBAAQAAsOAQFvIwAhANBvJAAgAAsSAQFvQQAlACEAQQDQbyYAIAALDAEBbyMAIQAQASAACw==", "base64"); + +let made = 0; +let exports; +const env = { + make: () => ({ id: ++made, label: `made ${made}`, items: [made, made * 2] }), + clear: () => { + exports.slot.value = null; + }, +}; +exports = new WebAssembly.Instance(new WebAssembly.Module(bytes), { env }).exports; + +const describe = (v) => (v === null ? "null" : `${v.id} ${v.label} ${v.items.join("+")}`); +const fresh = (n) => ({ id: n, label: `fresh ${n}`, items: [n, n + 1] }); + +const passed = []; +for (let i = 0; i < 200; i++) passed.push(describe(exports.pass())); +console.log("pass", passed.length, passed[0], passed[199]); + +const fromGlobal = []; +for (let i = 0; i < 200; i++) { + exports.slot.value = fresh(i); + fromGlobal.push(describe(exports.takeGlobal())); +} +console.log("global", fromGlobal[0], fromGlobal[199], describe(exports.slot.value)); + +const fromTable = []; +for (let i = 0; i < 200; i++) { + exports.cells.set(0, fresh(1000 + i)); + fromTable.push(describe(exports.takeTable())); +} +console.log("table", fromTable[0], fromTable[199], describe(exports.cells.get(0))); + +const acrossCall = []; +for (let i = 0; i < 200; i++) { + exports.slot.value = fresh(2000 + i); + acrossCall.push(describe(exports.takeAcrossCall())); +} +console.log("across call", acrossCall[0], acrossCall[199], describe(exports.slot.value)); diff --git a/tests/corpus/webassembly-feature-probe.js b/tests/corpus/webassembly-feature-probe.js index 7a164fd90..053e5c0c6 100644 --- a/tests/corpus/webassembly-feature-probe.js +++ b/tests/corpus/webassembly-feature-probe.js @@ -1,7 +1,6 @@ -// @deferred-fences: 2 // A JavaScript dependency's WebAssembly glue: the feature probe answers as -// in Node, and the loader that would instantiate a module is never reached -// (reaching it would throw scriptc's located WebAssembly fence). +// in Node, and the loader that would instantiate a module compiles (it is +// not reached here). function supportsWasm() { return typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function"; } diff --git a/tests/corpus/webassembly-jsapi.mjs b/tests/corpus/webassembly-jsapi.mjs new file mode 100644 index 000000000..ad9739972 --- /dev/null +++ b/tests/corpus/webassembly-jsapi.mjs @@ -0,0 +1,356 @@ +// The WebAssembly JavaScript API's constructors and reflection: new +// WebAssembly.Memory, Table and Global (descriptors, defaults, conversions +// and every error), using them as imports (limits, types and mutability +// checked with Node's LinkError messages), the identity of exported +// objects, WebAssembly.Module.imports, exports and customSections, and the +// classes called without new. The modules are inline base64 literals +// (their text is in tests/wasm-spec/corpus/jsapi.wat and jsapi-own.wat). +const jsapi = Buffer.from("AGFzbQEAAAABKglgAX8Bf2ABfwBgAAF/YAF8AXxgAX4AYAABb2ABbwBgAn9/AX9gAn9/AAJbBwNlbnYDbG9nAAEDZW52Bm1lbW9yeQIBAQQDZW52BXRhYmxlAXABAggDZW52B2NvdW50ZXIDfwEDZW52BXNjYWxlA3wAA2VudgNiaWcDfgEDZW52A3JlZgNvAQMPDgAAAgMEBQYHCAACAAIBB5UBEQRidW1wAAMGc2NhbGVkAAQGYmlnQWRkAAUGZ2V0UmVmAAYGc2V0UmVmAAcFYXBwbHkACAVzdG9yZQAJBGxvYWQACgRzaXplAAsEZ3JvdwAMCXRhYmxlU2l6ZQANA3NheQAOBm1lbW9yeQIABXRhYmxlAQAHY291bnRlcgMAC2Fsc29Db3VudGVyAwAGZG91YmxlAAEJCAEAQQALAgECCnAOBwAgAEECbAsHACAAIABsCwsAIwBBAWokACMACwcAIAAjAaILCQAjAiAAfCQCCwQAIwMLBgAgACQDCwkAIAEgABEAAAsJACAAIAE6AAALBwAgAC0AAAsEAD8ACwYAIABAAAsFAPwQAAsGACAAEAALAAwIZHlsaW5rLjABAgMACgRtZXRhaGVsbG8ACwhkeWxpbmsuMAQFAAEA", "base64"); +const own = Buffer.from("AGFzbQEAAAABBgFgAX8BfwMCAQAEBQFwAQIIBQQBAQEEBhICfwFBBwt8AEQAAAAAAAD4PwsHKgcDbWVtAgAEbWVtMgIAA3RhYgEAAWcDAAJnMgMABWZpeGVkAwECaWQAAAkHAQBBAQsBAAoGAQQAIAAL", "base64"); + +const show = (v) => { + if (typeof v === "bigint") return `${v}n`; + if (typeof v === "number") return Object.is(v, -0) ? "-0" : String(v); + if (typeof v === "function") return "function"; + if (Array.isArray(v)) return `[${v.map(show).join(", ")}]`; + if (v instanceof WebAssembly.Memory) return "Memory"; + if (v instanceof WebAssembly.Table) return "Table"; + if (v instanceof WebAssembly.Global) return "Global"; + if (v instanceof ArrayBuffer) return `ArrayBuffer(${v.byteLength})`; + if (v !== null && typeof v === "object") return JSON.stringify(v); + return String(v); +}; +const attempt = (label, f) => { + try { + console.log(label, show(f())); + } catch (e) { + console.log(label, e instanceof Error ? `${e.name}: ${e.message}` : `threw ${show(e)}`); + } +}; + +// ── WebAssembly.Global ──────────────────────────────────────────────────── +console.log("Global"); +attempt("i32 default", () => new WebAssembly.Global({ value: "i32" }).value); +attempt("i64 default", () => new WebAssembly.Global({ value: "i64" }).value); +attempt("f32", () => new WebAssembly.Global({ value: "f32" }, 1.1).value); +attempt("f64", () => new WebAssembly.Global({ value: "f64" }, 1.1).value); +attempt("f64 undefined", () => new WebAssembly.Global({ value: "f64" }, undefined).value); +attempt("f64 null", () => new WebAssembly.Global({ value: "f64" }, null).value); +attempt("i32 string", () => new WebAssembly.Global({ value: "i32" }, "7").value); +attempt("i32 wraps", () => new WebAssembly.Global({ value: "i32" }, 2 ** 32 + 3).value); +attempt("i32 object", () => new WebAssembly.Global({ value: "i32" }, { valueOf: () => 9 }).value); +attempt("i64 bigint", () => new WebAssembly.Global({ value: "i64" }, 2n ** 63n).value); +attempt("i64 string", () => new WebAssembly.Global({ value: "i64" }, "12").value); +attempt("i64 number", () => new WebAssembly.Global({ value: "i64" }, 5).value); +attempt("i64 null", () => new WebAssembly.Global({ value: "i64" }, null).value); +attempt("i32 bigint", () => new WebAssembly.Global({ value: "i32" }, 5n).value); +attempt("externref default", () => new WebAssembly.Global({ value: "externref" }).value); +attempt("externref object", () => new WebAssembly.Global({ value: "externref" }, { a: 1 }).value); +attempt("anyfunc default", () => new WebAssembly.Global({ value: "anyfunc" }).value); +attempt("anyfunc arrow", () => new WebAssembly.Global({ value: "anyfunc" }, () => 1)); +attempt("anyfunc number", () => new WebAssembly.Global({ value: "anyfunc" }, 1)); +attempt("funcref name", () => new WebAssembly.Global({ value: "funcref" })); +attempt("v128", () => new WebAssembly.Global({ value: "v128" })); +attempt("bad type", () => new WebAssembly.Global({ value: "i16" })); +attempt("no value", () => new WebAssembly.Global({})); +attempt("no descriptor", () => new WebAssembly.Global()); +attempt("number descriptor", () => new WebAssembly.Global(1)); +attempt("toString type", () => new WebAssembly.Global({ value: { toString: () => "f64" } }, 2.5).value); +const order = []; +new WebAssembly.Global( + { + get value() { + order.push("value"); + return { toString: () => (order.push("value toString"), "f64") }; + }, + get mutable() { + order.push("mutable"); + return false; + }, + }, + { valueOf: () => (order.push("valueOf"), 1) }, +); +console.log("order", order.join(",")); +const immutable = new WebAssembly.Global({ value: "i32" }, 4); +attempt("immutable set", () => { + immutable.value = 5; +}); +console.log("immutable after", immutable.value, immutable.valueOf()); +const mutable = new WebAssembly.Global({ value: "i32", mutable: 1 }, 4); +mutable.value = 2.9; +console.log("mutable", mutable.value, mutable.valueOf()); +mutable.value = "x"; +console.log("mutable NaN", mutable.value); +const mutable64 = new WebAssembly.Global({ value: "i64", mutable: true }); +mutable64.value = true; +console.log("mutable64", show(mutable64.value)); +attempt("i64 set number", () => { + mutable64.value = 3; +}); +const mutableF32 = new WebAssembly.Global({ value: "f32", mutable: true }, 1); +mutableF32.value = undefined; +console.log("f32 set undefined", mutableF32.value); +const mutableRef = new WebAssembly.Global({ value: "externref", mutable: true }, "start"); +mutableRef.value = undefined; +console.log("externref set undefined", mutableRef.value); +const mutableFunc = new WebAssembly.Global({ value: "anyfunc", mutable: true }); +attempt("anyfunc set arrow", () => { + mutableFunc.value = () => 2; +}); +console.log(String(immutable), Object.prototype.toString.call(immutable), immutable instanceof WebAssembly.Global); +console.log(immutable); +// @ts-ignore: called without new, as Node reports +attempt("Global()", () => WebAssembly.Global({ value: "i32" })); + +// ── WebAssembly.Memory ──────────────────────────────────────────────────── +console.log("Memory"); +attempt("bytes", () => new WebAssembly.Memory({ initial: 1 }).buffer.byteLength); +attempt("zero", () => new WebAssembly.Memory({ initial: 0 }).buffer.byteLength); +attempt("string initial", () => new WebAssembly.Memory({ initial: "2" }).buffer.byteLength); +attempt("fractional", () => new WebAssembly.Memory({ initial: 1.9 }).buffer.byteLength); +attempt("null initial", () => new WebAssembly.Memory({ initial: null }).buffer.byteLength); +attempt("missing", () => new WebAssembly.Memory({})); +attempt("minimum only", () => new WebAssembly.Memory({ minimum: 1 })); +attempt("undefined initial", () => new WebAssembly.Memory({ initial: undefined })); +attempt("negative", () => new WebAssembly.Memory({ initial: -1 })); +attempt("negative fraction", () => new WebAssembly.Memory({ initial: -0.5 })); +attempt("NaN", () => new WebAssembly.Memory({ initial: NaN })); +attempt("Infinity", () => new WebAssembly.Memory({ initial: Infinity })); +attempt("2^32", () => new WebAssembly.Memory({ initial: 2 ** 32 })); +attempt("too many pages", () => new WebAssembly.Memory({ initial: 65537 })); +attempt("max below initial", () => new WebAssembly.Memory({ initial: 20, maximum: 1 })); +attempt("max too large", () => new WebAssembly.Memory({ initial: 1, maximum: 65537 })); +attempt("max 2^32", () => new WebAssembly.Memory({ initial: 1, maximum: 2 ** 32 })); +attempt("max null", () => new WebAssembly.Memory({ initial: 1, maximum: null })); +attempt("bigint initial", () => new WebAssembly.Memory({ initial: 1n })); +attempt("throwing initial", () => + new WebAssembly.Memory({ + initial: { + valueOf() { + throw new Error("boom"); + }, + }, + }), +); +attempt("shared without maximum", () => new WebAssembly.Memory({ initial: 1, shared: true })); +attempt("no descriptor", () => new WebAssembly.Memory()); +attempt("string descriptor", () => new WebAssembly.Memory("x")); +const memoryOrder = []; +new WebAssembly.Memory({ + get initial() { + memoryOrder.push("initial"); + return { valueOf: () => (memoryOrder.push("initial valueOf"), 1) }; + }, + get maximum() { + memoryOrder.push("maximum"); + return { valueOf: () => (memoryOrder.push("maximum valueOf"), 3) }; + }, + get shared() { + memoryOrder.push("shared"); + return false; + }, +}); +console.log("order", memoryOrder.join(",")); +const grown = new WebAssembly.Memory({ initial: 1, maximum: 2 }); +const before = grown.buffer; +new Uint8Array(before)[5] = 7; +console.log("same buffer", grown.buffer === grown.buffer); +attempt("grow", () => grown.grow(1)); +console.log("after grow", grown.buffer.byteLength, new Uint8Array(grown.buffer)[5], before === grown.buffer); +attempt("grow past maximum", () => grown.grow(1)); +attempt("grow negative", () => grown.grow(-1)); +attempt("grow missing", () => grown.grow()); +attempt("grow NaN", () => grown.grow(NaN)); +attempt("grow 2^32", () => grown.grow(2 ** 32)); +attempt("grow zero", () => grown.grow(0)); +attempt("unbounded grow", () => new WebAssembly.Memory({ initial: 1, maximum: undefined }).grow(3)); +console.log(String(grown), grown instanceof WebAssembly.Memory); +console.log(grown); +// @ts-ignore: called without new, as Node reports +attempt("Memory()", () => WebAssembly.Memory({ initial: 1 })); + +// ── WebAssembly.Table ───────────────────────────────────────────────────── +console.log("Table"); +attempt("anyfunc", () => new WebAssembly.Table({ initial: 2, element: "anyfunc" }).get(1)); +attempt("externref", () => new WebAssembly.Table({ initial: 1, element: "externref" }).get(0)); +attempt("externref init", () => new WebAssembly.Table({ initial: 2, element: "externref" }, "hi").get(1)); +attempt("externref undefined", () => new WebAssembly.Table({ initial: 2, element: "externref" }, undefined).get(1)); +attempt("anyfunc null", () => new WebAssembly.Table({ initial: 2, element: "anyfunc" }, null).get(1)); +attempt("anyfunc arrow", () => new WebAssembly.Table({ initial: 2, element: "anyfunc" }, () => 1)); +attempt("anyfunc number", () => new WebAssembly.Table({ initial: 2, element: "anyfunc" }, 5)); +attempt("funcref name", () => new WebAssembly.Table({ initial: 1, element: "funcref" })); +attempt("i32 element", () => new WebAssembly.Table({ initial: 1, element: "i32" })); +attempt("no element", () => new WebAssembly.Table({ initial: 1 })); +attempt("no initial", () => new WebAssembly.Table({ element: "anyfunc" })); +// @ts-ignore: an incomplete descriptor +attempt("empty", () => new WebAssembly.Table({})); +attempt("no descriptor", () => new WebAssembly.Table()); +attempt("max below initial", () => new WebAssembly.Table({ initial: 2, maximum: 1, element: "anyfunc" })); +attempt("bad init and descriptor", () => new WebAssembly.Table({ initial: 3, maximum: 2, element: "anyfunc" }, 37)); +attempt("too large", () => new WebAssembly.Table({ initial: 10000001, element: "anyfunc" })); +attempt("large maximum", () => new WebAssembly.Table({ initial: 1, maximum: 10000001, element: "anyfunc" }).length); +attempt("max 2^32", () => new WebAssembly.Table({ initial: 1, maximum: 2 ** 32, element: "anyfunc" })); +attempt("toString element", () => new WebAssembly.Table({ element: { toString: () => "anyfunc" }, initial: 1 }).length); +const tableOrder = []; +new WebAssembly.Table({ + get element() { + tableOrder.push("element"); + return { toString: () => (tableOrder.push("element toString"), "anyfunc") }; + }, + get initial() { + tableOrder.push("initial"); + return { valueOf: () => (tableOrder.push("initial valueOf"), 1) }; + }, + get maximum() { + tableOrder.push("maximum"); + return { valueOf: () => (tableOrder.push("maximum valueOf"), 3) }; + }, +}); +console.log("order", tableOrder.join(",")); +const refs = new WebAssembly.Table({ initial: 1, maximum: 4, element: "externref" }, 3); +attempt("set default", () => { + refs.set(0); + return refs.get(0); +}); +attempt("grow default", () => [refs.grow(1), refs.get(1), refs.length]); +attempt("grow value", () => [refs.grow(1, "z"), refs.get(2), refs.length]); +attempt("grow past maximum", () => refs.grow(2)); +attempt("get negative", () => refs.get(-1)); +attempt("get missing", () => refs.get()); +attempt("get out of range", () => refs.get(5)); +attempt("set out of range", () => refs.set(9, 1)); +const funcs = new WebAssembly.Table({ initial: 1, element: "anyfunc" }); +attempt("set arrow", () => funcs.set(0, () => 1)); +attempt("set number", () => funcs.set(0, 7)); +attempt("grow arrow", () => funcs.grow(1, () => 1)); +attempt("grow negative", () => funcs.grow(-1)); +console.log(String(funcs), funcs instanceof WebAssembly.Table); +console.log(funcs); +// @ts-ignore: called without new, as Node reports +attempt("Table()", () => WebAssembly.Table({ initial: 1, element: "anyfunc" })); + +// ── WebAssembly.Module's static functions ──────────────────────────────── +console.log("Module"); +const module = new WebAssembly.Module(jsapi); +console.log(JSON.stringify(WebAssembly.Module.imports(module))); +console.log(JSON.stringify(WebAssembly.Module.exports(module))); +const firstImport = WebAssembly.Module.imports(module)[0]; +console.log(Object.keys(firstImport).join(","), Array.isArray(WebAssembly.Module.imports(module))); +firstImport.module = "changed"; +console.log("fresh", WebAssembly.Module.imports(module)[0].module); +const dylink = WebAssembly.Module.customSections(module, "dylink.0"); +console.log( + "dylink.0", + dylink.length, + dylink.map((b) => `${show(b)} ${[...new Uint8Array(b)].join(" ")}`).join(" | "), +); +console.log("meta", new TextDecoder().decode(WebAssembly.Module.customSections(module, "meta")[0])); +console.log("empty name", WebAssembly.Module.customSections(module, "").length); +console.log("missing", WebAssembly.Module.customSections(module, "nope").length); +console.log("toString", WebAssembly.Module.customSections(module, { toString: () => "meta" }).length); +console.log("null", WebAssembly.Module.customSections(module, null).length); +const copy = WebAssembly.Module.customSections(module, "meta")[0]; +new Uint8Array(copy)[0] = 0; +console.log( + "copies", + new Uint8Array(WebAssembly.Module.customSections(module, "meta")[0])[0], + copy === WebAssembly.Module.customSections(module, "meta")[0], +); +attempt("customSections missing name", () => WebAssembly.Module.customSections(module)); +attempt("customSections symbol", () => WebAssembly.Module.customSections(module, Symbol("x"))); +attempt("customSections number", () => WebAssembly.Module.customSections(1, "x")); +attempt("imports object", () => WebAssembly.Module.imports({})); +attempt("exports missing", () => WebAssembly.Module.exports()); +attempt("imports stray", () => WebAssembly.Module.imports(module, 1).length); +console.log("own", JSON.stringify(WebAssembly.Module.imports(new WebAssembly.Module(own)))); +console.log("own", JSON.stringify(WebAssembly.Module.exports(new WebAssembly.Module(own)))); +// @ts-ignore: called without new, as Node reports +attempt("Module()", () => WebAssembly.Module(jsapi)); +// @ts-ignore: called without new, as Node reports +attempt("Instance()", () => WebAssembly.Instance(module, {})); + +// ── constructed objects as imports ──────────────────────────────────────── +console.log("imports"); +const logged = []; +const memory = new WebAssembly.Memory({ initial: 1, maximum: 4 }); +const table = new WebAssembly.Table({ initial: 2, maximum: 8, element: "anyfunc" }); +const counter = new WebAssembly.Global({ value: "i32", mutable: true }, 10); +const big = new WebAssembly.Global({ value: "i64", mutable: true }, 1n); +const ref = new WebAssembly.Global({ value: "externref", mutable: true }, "first"); +const env = { log: (v) => logged.push(v), memory, table, counter, scale: 2.5, big, ref }; +const instance = new WebAssembly.Instance(module, { env }); +const x = instance.exports; +console.log( + "identity", + x.memory === memory, + x.table === table, + x.counter === counter, + x.alsoCounter === counter, +); +attempt("bump", () => [x.bump(), x.bump(), counter.value]); +counter.value = 100; +attempt("bump after set", () => x.bump()); +attempt("scaled", () => x.scaled(4)); +x.bigAdd(41n); +console.log("big", show(big.value)); +attempt("getRef", () => x.getRef()); +x.setRef({ hello: "world" }); +console.log("ref", JSON.stringify(ref.value)); +ref.value = 42; +attempt("getRef after set", () => x.getRef()); +attempt("apply double", () => x.apply(0, 21)); +attempt("apply square", () => x.apply(1, 12)); +console.log("table get", table.get(0) === x.double); +// A function the module does not export, reached through the table. +const square = table.get(1); +console.log("unexported", square(5), square === table.get(1), square.name, square.length, typeof square); +x.store(3, 99); +console.log("memory", new Uint8Array(memory.buffer)[3], x.load(3)); +new Uint8Array(memory.buffer)[4] = 55; +console.log("memory from js", x.load(4)); +attempt("grow in wasm", () => [x.grow(1), x.size(), memory.buffer.byteLength]); +attempt("grow from js", () => [memory.grow(1), x.size(), memory.buffer.byteLength]); +attempt("table grow", () => [table.grow(2), x.tableSize(), table.length]); +const global = new WebAssembly.Global({ value: "anyfunc", mutable: true }, x.double); +console.log("funcref global", global.value === x.double); +global.value = null; +console.log("funcref null", global.value); +table.set(1, x.double); +attempt("apply after set", () => x.apply(1, 8)); +x.say(5); +console.log("logged", logged.join(",")); + +// Another instance's exports as imports, and the same objects again. +const provider = new WebAssembly.Instance(new WebAssembly.Module(own)).exports; +console.log("own identity", provider.mem === provider.mem2, provider.g === provider.g2, provider.mem instanceof WebAssembly.Memory); +const second = new WebAssembly.Instance(module, { + env: { ...env, memory: provider.mem, table: provider.tab, counter: provider.g }, +}).exports; +console.log("re-exported", second.memory === provider.mem, second.table === provider.tab, second.counter === provider.g); +attempt("bump provider global", () => [second.bump(), provider.g.value]); +attempt("apply provider table", () => second.apply(1, 3)); + +// ── link errors ─────────────────────────────────────────────────────────── +console.log("link errors"); +const link = (label, overrides) => + attempt(label, () => new WebAssembly.Instance(module, { env: { ...env, ...overrides } }) && "linked"); +link("memory too small", { memory: new WebAssembly.Memory({ initial: 0, maximum: 4 }) }); +link("memory without maximum", { memory: new WebAssembly.Memory({ initial: 1 }) }); +link("memory maximum too large", { memory: new WebAssembly.Memory({ initial: 1, maximum: 5 }) }); +link("memory larger initial", { memory: new WebAssembly.Memory({ initial: 3, maximum: 4 }) }); +link("memory number", { memory: 5 }); +link("table too small", { table: new WebAssembly.Table({ initial: 1, maximum: 8, element: "anyfunc" }) }); +link("table without maximum", { table: new WebAssembly.Table({ initial: 2, element: "anyfunc" }) }); +link("table maximum too large", { table: new WebAssembly.Table({ initial: 2, maximum: 12, element: "anyfunc" }) }); +link("table externref", { table: new WebAssembly.Table({ initial: 2, maximum: 8, element: "externref" }) }); +link("table small externref", { table: new WebAssembly.Table({ initial: 1, maximum: 8, element: "externref" }) }); +link("table number", { table: 3 }); +link("global immutable", { counter: new WebAssembly.Global({ value: "i32" }, 1) }); +link("global type", { counter: new WebAssembly.Global({ value: "i64", mutable: true }, 1n) }); +link("global both", { counter: new WebAssembly.Global({ value: "f64" }, 1) }); +link("global number", { counter: 1 }); +link("immutable global object", { scale: new WebAssembly.Global({ value: "f64" }, 4) }); +link("immutable global mutable", { scale: new WebAssembly.Global({ value: "f64", mutable: true }, 4) }); +link("immutable global bigint", { scale: 4n }); +link("i64 number", { big: 4 }); +link("externref anything", { ref: new WebAssembly.Global({ value: "externref", mutable: true }, null) }); diff --git a/tests/corpus/webassembly-lifetimes.mjs b/tests/corpus/webassembly-lifetimes.mjs new file mode 100644 index 000000000..6a7adc860 --- /dev/null +++ b/tests/corpus/webassembly-lifetimes.mjs @@ -0,0 +1,43 @@ +// Lifetimes across the WebAssembly boundary: an externref read from a table +// or global outlives the slot being cleared, a fresh import result reaches +// JavaScript from an export, a load with an explicit memory index reads its +// own offset, and a Memory's buffer outlives the Memory. The module's text +// is in tests/wasm-spec/corpus/lifetimes.wat. +const lifetimes = Buffer.from( + "AGFzbQEAAAABDQNgAW8AYAABb2AAAX8CDAEDZW52BG1ha2UAAQMHBgABAAEBAgQEAW8AAQUDAQABBgYBbwHQbwsHLAYDcHV0AAEEdGFrZQACBHB1dGcAAwV0YWtlZwAEBWZyZXNoAAUEbG9hZAAGCjsGCABBACAAJgALEgEBb0EAJQAhAEEA0G8mACAACwYAIAAkAAsIACMA0G8kAAsEABAACwgAQQAoQgAICwsKAQBBCAsEYWJjZA==", + "base64", +); + +const { instance } = await WebAssembly.instantiate(lifetimes, { + env: { make: () => ({ made: [1, 2, 3] }) }, +}); +const x = instance.exports; + +x.put({ from: "table" }); +console.log(x.take()); +x.putg({ from: "global" }); +console.log(x.takeg()); +console.log(x.fresh()); +console.log(x.fresh().made.length); +console.log(x.load().toString(16)); + +function viewOfDroppedMemory() { + const memory = new WebAssembly.Memory({ initial: 1 }); + const bytes = new Uint8Array(memory.buffer); + bytes[0] = 7; + bytes[65535] = 9; + return bytes; +} +const view = viewOfDroppedMemory(); +const filler = []; +for (let i = 0; i < 32; i++) filler.push(new Uint8Array(65536).fill(1)); +view[1] = 5; +console.log(view.length, view[0], view[1], view[65535], filler.length); + +function bufferOfDroppedMemory() { + const memory = new WebAssembly.Memory({ initial: 1, maximum: 4 }); + new Uint8Array(memory.buffer)[3] = 42; + return memory.buffer; +} +const buffer = bufferOfDroppedMemory(); +console.log(buffer.byteLength, new Uint8Array(buffer)[3]); diff --git a/tests/corpus/webassembly-spec-control/data.mjs b/tests/corpus/webassembly-spec-control/data.mjs new file mode 100644 index 000000000..0be8faedb --- /dev/null +++ b/tests/corpus/webassembly-spec-control/data.mjs @@ -0,0 +1,48 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * block.wast, br.wast, br_if.wast, br_table.wast, call.wast, call_indirect.wast, fac.wast, forward.wast, func.wast, func_ptrs.wast, if.wast, labels.wast, loop.wast, local_get.wast, local_set.wast, local_tee.wast, nop.wast, return.wast, select.wast, stack.wast, switch.wast, unreachable.wast, unwind.wast, left-to-right.wast, global.wast, start.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABPQtgAn9/AX9gAABgAAF/YAF/AGADf3x/A398f2AAA39+f2ABfwF/YAACf39gAAJ9fWAAA39/fmACf38Cf38DODcBAQICAgICAgICAgIBAgICAgICAAICAgEBAgYCAgECAgICAgICAgICAgICAgkCAgICAgICAgIBBAUBcAEBAQUDAQABBgYBfwFBCgsH0AY0BWVtcHR5AAEIc2luZ3VsYXIAAgVtdWx0aQADBm5lc3RlZAAEBGRlZXAABQ9hcy1zZWxlY3QtZmlyc3QABg1hcy1zZWxlY3QtbWlkAAcOYXMtc2VsZWN0LWxhc3QACA1hcy1sb29wLWZpcnN0AAkLYXMtbG9vcC1taWQACgxhcy1sb29wLWxhc3QACw9hcy1pZi1jb25kaXRpb24ADAphcy1pZi10aGVuAA0KYXMtaWYtZWxzZQAODmFzLWJyX2lmLWZpcnN0AA8NYXMtYnJfaWYtbGFzdAAQEWFzLWJyX3RhYmxlLWZpcnN0ABEQYXMtYnJfdGFibGUtbGFzdAASFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAFBRhcy1jYWxsX2luZGlyZWN0LW1pZAAVFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAWDmFzLXN0b3JlLWZpcnN0ABcNYXMtc3RvcmUtbGFzdAAYFGFzLW1lbW9yeS5ncm93LXZhbHVlABkNYXMtY2FsbC12YWx1ZQAbD2FzLXJldHVybi12YWx1ZQAcD2FzLWRyb3Atb3BlcmFuZAAdC2FzLWJyLXZhbHVlAB4SYXMtbG9jYWwuc2V0LXZhbHVlAB8SYXMtbG9jYWwudGVlLXZhbHVlACATYXMtZ2xvYmFsLnNldC12YWx1ZQAhD2FzLWxvYWQtb3BlcmFuZAAiEGFzLXVuYXJ5LW9wZXJhbmQAIxFhcy1iaW5hcnktb3BlcmFuZAAkD2FzLXRlc3Qtb3BlcmFuZAAlEmFzLWNvbXBhcmUtb3BlcmFuZAAmEmFzLWJpbmFyeS1vcGVyYW5kcwAnE2FzLWNvbXBhcmUtb3BlcmFuZHMAKBFhcy1taXhlZC1vcGVyYW5kcwApCmJyZWFrLWJhcmUAKgticmVhay12YWx1ZQArEWJyZWFrLW11bHRpLXZhbHVlACwOYnJlYWstcmVwZWF0ZWQALQticmVhay1pbm5lcgAuBXBhcmFtAC8GcGFyYW1zADAJcGFyYW1zLWlkADELcGFyYW0tYnJlYWsAMgxwYXJhbXMtYnJlYWsAMw9wYXJhbXMtaWQtYnJlYWsANAdlZmZlY3RzADUIdHlwZS11c2UANgkHAQBBAAsBEwrSCDcCAAsIAAJACwJACwsLAAJAAQsCf0EHCws+AAJAEAAQABAAEAALAn8QABAAEABBBxAACxoCBRAAEAAQAEEIEAAQABAAEABCBxAAEAAQABAAQQkQAAsaGgsVAAJ/AkAQAAJACwELAn8QAEEJCwsLeQACfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/An8CfwJ/EABBlgELCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsMAAJ/QQELQQJBAxsLDABBAgJ/QQELQQMbCwwAQQJBAwJ/QQELGwsOAAN/An9BAQsQABAACwsOAAN/EAACf0EBCxAACwsOAAN/EAAQAAJ/QQELCwsMAAJ/QQELBEAQAAsLDwBBAQR/An9BAQsFQQILCw8AQQEEf0ECBQJ/QQELCwsOAAJ/An9BAQtBAg0ACwsOAAJ/QQICf0EBCw0ACwsQAAJ/An9BAQtBAg4BAAALCxAAAn9BAgJ/QQELDgEAAAsLBAAgAAsRAAJ/An9BAQtBAkEAEQAACwsRAAJ/QQICf0EBC0EAEQAACwsRAAJ/QQFBAgJ/QQALEQAACwsMAAJ/QQELQQE2AgALDABBCgJ/QQELNgIACwkAAn9BAQtAAAsEACAACwkAAn9BAQsQGgsIAAJ/QQELDwsIAAJ/QQELGgsMAAJ/An9BAQsMAAsLDQEBfwJ/QQELIQAgAAsLAQF/An9BAQsiAAsLAAJ/QQELJAAjAAsKAAJ/QQELKAIACwoAAn8QAEENC2gLEQACfxAAQQMLAn8QAEEEC2wLCgACfxAAQQ0LRQsXAAJ9EABDAABAQAsCfRAAQwAAQEALXgsOAAIHEABBAxAAQQQLbAsUAAIIEABDAABAQBAAQwAAQEALXgsRAAIHEABBAxAAQQQLQQVqbAsmAAJADAAACwJAQQENAAALAkBBAA4AAAALAkBBAQ4CAAAAAAtBEwsLAAJ/QRIMAEETCwsTAAIJQRJBbkISDABBE0FtQhMLCzEAAn9BEgwAQRMMAEEUQQANABpBFEEBDQAaQRUMAEEWQQQOAABBF0EBDgIAAABBFQsLRQEBf0EAIQAgAAJ/An9BAQwBCwtqIQAgAAJ/AkAMAAtBAgtqIQAgAAJ/QQQMAGgLaiEAIAACfwJ/QQgMAQtoC2ohACAACwoAQQECBkECagsLCgBBAUECAgBqCwsKAEEBQQICCgtqCwwAQQECBkECagwACwsMAEEBQQICAGoMAAsLDABBAUECAgoMAAtqCy8BAX8CQEEBIQAgAEEDbCEAIABBBWshACAAQQdsIQAMACAAQeQAbCEACyAAQXJGCz0AAkALAn9BAAsCAxoLQQBEAAAAAAAAAABBAAIECxoaGgJ/QQALAgMaC0EARAAAAAAAAAAAQQACBAsaGhoL", + "AGFzbQEAAAABKwlgA39/fwF/YAAAYAABf2AAAX5gAAF9YAABfGAAAnx8YAACf35gAn9/AX8DS0oBAQEBAQEBAQECAwQFBgEBAQICAgICAQICAQICAwcCCAgICAICAAICAgICAgICAgICAgQDAgICAgICBAIDAgICAgICAgICAgICAgQFAXABAQEFAwEAAQYGAX8BQQoLB5IKSAh0eXBlLWkzMgABCHR5cGUtaTY0AAIIdHlwZS1mMzIAAwh0eXBlLWY2NAAEDHR5cGUtaTMyLWkzMgAFDHR5cGUtaTY0LWk2NAAGDHR5cGUtZjMyLWYzMgAHDHR5cGUtZjY0LWY2NAAIDnR5cGUtaTMyLXZhbHVlAAkOdHlwZS1pNjQtdmFsdWUACg50eXBlLWYzMi12YWx1ZQALDnR5cGUtZjY0LXZhbHVlAAwSdHlwZS1mNjQtZjY0LXZhbHVlAA0OYXMtYmxvY2stZmlyc3QADgxhcy1ibG9jay1taWQADw1hcy1ibG9jay1sYXN0ABAOYXMtYmxvY2stdmFsdWUAEQ1hcy1sb29wLWZpcnN0ABILYXMtbG9vcC1taWQAEwxhcy1sb29wLWxhc3QAFAthcy1ici12YWx1ZQAVDWFzLWJyX2lmLWNvbmQAFg5hcy1icl9pZi12YWx1ZQAXE2FzLWJyX2lmLXZhbHVlLWNvbmQAGBFhcy1icl90YWJsZS1pbmRleAAZEWFzLWJyX3RhYmxlLXZhbHVlABoXYXMtYnJfdGFibGUtdmFsdWUtaW5kZXgAGw9hcy1yZXR1cm4tdmFsdWUAHBBhcy1yZXR1cm4tdmFsdWVzAB0KYXMtaWYtY29uZAAeCmFzLWlmLXRoZW4AHwphcy1pZi1lbHNlACAPYXMtc2VsZWN0LWZpcnN0ACEQYXMtc2VsZWN0LXNlY29uZAAiDmFzLXNlbGVjdC1jb25kACMNYXMtc2VsZWN0LWFsbAAkDWFzLWNhbGwtZmlyc3QAJgthcy1jYWxsLW1pZAAnDGFzLWNhbGwtbGFzdAAoC2FzLWNhbGwtYWxsACkVYXMtY2FsbF9pbmRpcmVjdC1mdW5jACoWYXMtY2FsbF9pbmRpcmVjdC1maXJzdAArFGFzLWNhbGxfaW5kaXJlY3QtbWlkACwVYXMtY2FsbF9pbmRpcmVjdC1sYXN0AC0UYXMtY2FsbF9pbmRpcmVjdC1hbGwALhJhcy1sb2NhbC5zZXQtdmFsdWUALxJhcy1sb2NhbC50ZWUtdmFsdWUAMBNhcy1nbG9iYWwuc2V0LXZhbHVlADEPYXMtbG9hZC1hZGRyZXNzADIQYXMtbG9hZE4tYWRkcmVzcwAzEGFzLXN0b3JlLWFkZHJlc3MANA5hcy1zdG9yZS12YWx1ZQA1DWFzLXN0b3JlLWJvdGgANhFhcy1zdG9yZU4tYWRkcmVzcwA3D2FzLXN0b3JlTi12YWx1ZQA4DmFzLXN0b3JlTi1ib3RoADkQYXMtdW5hcnktb3BlcmFuZAA6DmFzLWJpbmFyeS1sZWZ0ADsPYXMtYmluYXJ5LXJpZ2h0ADwOYXMtYmluYXJ5LWJvdGgAPQ9hcy10ZXN0LW9wZXJhbmQAPg9hcy1jb21wYXJlLWxlZnQAPxBhcy1jb21wYXJlLXJpZ2h0AEAPYXMtY29tcGFyZS1ib3RoAEESYXMtY29udmVydC1vcGVyYW5kAEITYXMtbWVtb3J5Lmdyb3ctc2l6ZQBDEm5lc3RlZC1ibG9jay12YWx1ZQBED25lc3RlZC1ici12YWx1ZQBFEm5lc3RlZC1icl9pZi12YWx1ZQBGF25lc3RlZC1icl9pZi12YWx1ZS1jb25kAEcVbmVzdGVkLWJyX3RhYmxlLXZhbHVlAEgbbmVzdGVkLWJyX3RhYmxlLXZhbHVlLWluZGV4AEkJBwEAQQALASUK5QhKAgALCQACQAwAaBoLCwkAAkAMAHoaCwsJAAJADACMGgsLCQACQAwAmhoLCwkAAkAMAGoaCwsJAAJADAB8GgsLCQACQAwAkhoLCwkAAkAMAKAaCwsKAAJ/QQEMAGgLCwoAAn5CAgwAegsLDQACfUMAAEBADACMCwsRAAJ8RAAAAAAAABBADACaCwsjAAIGRAAAAAAAABBARAAAAAAAABRADACgRAAAAAAAABhACwsJAAJADAAQAAsLCwACQBAADAAQAAsLCgACQAEQAAwACwsMAAJ/ARAAQQIMAAsLDgACfwN/QQMMAUECCwsLEAACfwN/EABBBAwBQQILCwsPAAJ/A38BEABBBQwBCwsLCwACf0EJDAAMAAsLCQACQAwADQALCxAAAn9BCAwAQQENABpBBwsLEAACf0EGQQkMAA0AGkEHCwsMAAJADAAOAgAAAAsLEgACf0EKDABBAQ4CAAAAQQcLCxEAAn9BBkELDAAOAQAAQQcLCwoAAn5CBwwADwsLDgBBAgJ+QQFCBwwADwsLEQACf0ECDAAEf0EABUEBCwsLEQACfyAABH9BAwwBBSABCwsLEQACfyAABH8gAQVBBAwBCwsLDgACf0EFDAAgACABGwsLDgACfyAAQQYMACABGwsLDgACf0EAQQFBBwwAGwsLCgACf0EIDAAbCwsEAEF/Cw8AAn9BDAwAQQJBAxAlCwsPAAJ/QQFBDQwAQQMQJQsLDwACf0EBQQJBDgwAECULCwsAAn9BDwwAECULCxIAAn9BFAwAQQFBAkEDEQAACwsSAAJ/QQBBFQwAQQJBAxEAAAsLEgACf0EAQQFBFgwAQQMRAAALCxIAAn9BAEEBQQJBFwwAEQAACwsMAAJ/QRgMABEAAAsLDwEBfQJ/QREMACEAQX8LCw0BAX8Cf0EBDAAiAAsLCwACf0EBDAAkAAsLDwACfUOamdk/DAAqAgALCwwAAn5CHgwAMAAACwsXAAJ/QR4MAEQAAAAAAAAcQDkDAEF/CwsQAAJ/QQJBHwwANwMAQX8LCw4AAn9BIAwANwMAQX8LCxAAAn9BIAwAQQc6AABBfwsLEAACf0ECQSEMAD0BAEF/CwsOAAJ/QSIMAD0BAEF/CwsNAAJ9Q5qZWUAMAIwLCwwAAn9BAwwAQQpqCwsMAAJ+QgpCLQwAfQsLCgACf0EuDABqCwsKAAJ/QSwMAEULCxMAAn9BKwwARAAAAAAAACRAZQsLDwACf0MAACBBQSoMAFwLCwoAAn9BLAwAZQsLCgACf0EpDACnCwsLAAJ/QSgMAEAACwsRAEEBAn8QAEEEQQgMAGoLagsaAEEBAn9BAhoCf0EEGkEIDAEMAAsaQRALagsfAEEBAn9BAhoCf0EEGkEIDAFBAQ0AGkEgCxpBEAtqCxYAQQECf0ECGkEEQQgMAA0AGkEQC2oLHQBBAQJ/QQIaAn9BBBpBCAwBQQEOAAALGkEQC2oLFgBBAQJ/QQIaQQRBCAwADgAAQRALags=", + "AGFzbQEAAAABKQlgA39/fwF/YAAAYAABf2AAAX5gAAF9YAABfGABfwF/YAF/AGACf38AA0A/AQEBAQECAwQFBgYHBgYGBgYHAgECBgECAgMGCAgGBgIAAgICAAICAgIGBgYCAgICAgIFAgICAgICBgYGBgYGBAUBcAEBAQUDAQABBgYBfwFBCgsH0Qg8CHR5cGUtaTMyAAEIdHlwZS1pNjQAAgh0eXBlLWYzMgADCHR5cGUtZjY0AAQOdHlwZS1pMzItdmFsdWUABQ50eXBlLWk2NC12YWx1ZQAGDnR5cGUtZjMyLXZhbHVlAAcOdHlwZS1mNjQtdmFsdWUACA5hcy1ibG9jay1maXJzdAAJDGFzLWJsb2NrLW1pZAAKDWFzLWJsb2NrLWxhc3QACxRhcy1ibG9jay1maXJzdC12YWx1ZQAMEmFzLWJsb2NrLW1pZC12YWx1ZQANE2FzLWJsb2NrLWxhc3QtdmFsdWUADg1hcy1sb29wLWZpcnN0AA8LYXMtbG9vcC1taWQAEAxhcy1sb29wLWxhc3QAEQthcy1ici12YWx1ZQASDWFzLWJyX2lmLWNvbmQAEw5hcy1icl9pZi12YWx1ZQAUE2FzLWJyX2lmLXZhbHVlLWNvbmQAFRFhcy1icl90YWJsZS1pbmRleAAWEWFzLWJyX3RhYmxlLXZhbHVlABcXYXMtYnJfdGFibGUtdmFsdWUtaW5kZXgAGA9hcy1yZXR1cm4tdmFsdWUAGQphcy1pZi1jb25kABoKYXMtaWYtdGhlbgAbCmFzLWlmLWVsc2UAHA9hcy1zZWxlY3QtZmlyc3QAHRBhcy1zZWxlY3Qtc2Vjb25kAB4OYXMtc2VsZWN0LWNvbmQAHw1hcy1jYWxsLWZpcnN0ACELYXMtY2FsbC1taWQAIgxhcy1jYWxsLWxhc3QAIxVhcy1jYWxsX2luZGlyZWN0LWZ1bmMAJRZhcy1jYWxsX2luZGlyZWN0LWZpcnN0ACYUYXMtY2FsbF9pbmRpcmVjdC1taWQAJxVhcy1jYWxsX2luZGlyZWN0LWxhc3QAKBJhcy1sb2NhbC5zZXQtdmFsdWUAKRJhcy1sb2NhbC50ZWUtdmFsdWUAKhNhcy1nbG9iYWwuc2V0LXZhbHVlACsPYXMtbG9hZC1hZGRyZXNzACwQYXMtbG9hZE4tYWRkcmVzcwAtEGFzLXN0b3JlLWFkZHJlc3MALg5hcy1zdG9yZS12YWx1ZQAvEWFzLXN0b3JlTi1hZGRyZXNzADAPYXMtc3RvcmVOLXZhbHVlADEQYXMtdW5hcnktb3BlcmFuZAAyDmFzLWJpbmFyeS1sZWZ0ADMPYXMtYmluYXJ5LXJpZ2h0ADQPYXMtdGVzdC1vcGVyYW5kADUPYXMtY29tcGFyZS1sZWZ0ADYQYXMtY29tcGFyZS1yaWdodAA3E2FzLW1lbW9yeS5ncm93LXNpemUAOBJuZXN0ZWQtYmxvY2stdmFsdWUAOQ9uZXN0ZWQtYnItdmFsdWUAOhJuZXN0ZWQtYnJfaWYtdmFsdWUAOxduZXN0ZWQtYnJfaWYtdmFsdWUtY29uZAA8FW5lc3RlZC1icl90YWJsZS12YWx1ZQA9G25lc3RlZC1icl90YWJsZS12YWx1ZS1pbmRleAA+CQcBAEEACwEkCtoIPwIACw0AAkBBAEEBDQBoGgsLDQACQEIAQQENAHoaCwsQAAJAQwAAAABBAQ0AjBoLCxQAAkBEAAAAAAAAAABBAQ0AmhoLCwwAAn9BAUEBDQBoCwsMAAJ+QgJBAQ0AegsLDwACfUMAAEBAQQENAIwLCxMAAnxEAAAAAAAAEEBBAQ0AmgsLDgACQCAADQBBAg8LQQMLEAACQBAAIAANAEECDwtBAwsNAAJAEAAQACAADQALCw8AAn9BCiAADQAaQQsPCwsRAAJ/EABBFCAADQAaQRUPCwsPAAJ/EAAQAEELIAANAAsLEQACQANAIAANAUECDwsLQQMLEwACQANAEAAgAA0BQQIPCwtBBAsLAANAEAAgAA0BCwsNAAJ/QQFBAg0ADAALCw0AAkBBAUEBDQANAAsLEgACf0EBQQINAEEDDQAaQQQLCxIAAn9BAkEBIAANAA0AGkEECwsQAAJAQQFBAg0ADgIAAAALCxQAAn9BAUECDQBBAw4CAAAAQQQLCxMAAn9BAkEBQQMNAA4BAABBBAsLDAACfkIBQQINAA8LCxMAAn9BASAADQAEf0ECBUEDCwsLEQACQCAABEAgAQ0BBRAACwsLEQACQCAABEAQAAUgAQ0BCwsLEAACf0EDQQoNAEECIAAbCwsQAAJ/QQFBA0EKDQAgABsLCxAAAn9BAUECQQNBCg0AGwsLBABBfwsRAAJ/QQxBAQ0AQQJBAxAgCwsRAAJ/QQFBDUEBDQBBAxAgCwsRAAJ/QQFBAkEOQQENABAgCwsEACAACxQAAn9BBEEKDQBBAUECQQARAAALCxQAAn9BAUEEQQoNAEECQQARAAALCxQAAn9BAUECQQRBCg0AQQARAAALCxQAAn9BAUECQQNBBEEKDQARAAALCxEBAX8Cf0ERIAANACEAQX8LCxAAAn9BASAADQAiAEF/DwsLEAACf0EBIAANACQAQX8PCwsOAAJ/QQFBAQ0AKAIACwsOAAJ/QR5BAQ0ALAAACwsSAAJ/QR5BAQ0AQQc2AgBBfwsLEgACf0ECQR9BAQ0ANgIAQX8LCxIAAn9BIEEBDQBBBzoAAEF/CwsSAAJ/QQJBIUEBDQA7AQBBfwsLEwACfEQAAAAAAADwP0EBDQCaCwsOAAJ/QQFBAQ0AQQpqCwsOAAJ/QQpBAUEBDQBrCwsMAAJ/QQBBAQ0ARQsLDgACf0EBQQENAEEKTQsLDgACf0EKQQFBKg0ARwsLDQACf0EBQQENAEAACwsaAEEBAn9BAhpBBAJ/QQggAA0BGkEQC2oLagsbAEEBAn9BAhoCf0EIIAANARpBBAsMAEEQC2oLHgBBAQJ/QQIaAn9BCCAADQEaQQQLQQENABpBEAtqCx4AQQECf0ECGkEEAn9BCCAADQEaQQELDQAaQRALagseAEEBAn9BAhoCf0EIIAANARpBBAtBAQ4AAEEQC2oLHgBBAQJ/QQIaQQQCf0EIIAANARpBAQsOAABBEAtqCw==", + "AGFzbQEAAAABLAlgA39/fwF/YAAAYAABf2AAAX5gAAF9YAABfGABfwF/YAJ/fwF/YAJ/bwFvA0dGAQEBAQECAwQFBgYGBgYGBgEBAQICAgICAQICAQICAwIHBwcHAgACAgICAgICAgICBAMCAgICBAIDAgICAgIGBgYGBgYGCAQFAXABAQEFAwEAAQYGAX8BQQoLB7sJRAh0eXBlLWkzMgABCHR5cGUtaTY0AAIIdHlwZS1mMzIAAwh0eXBlLWY2NAAEDnR5cGUtaTMyLXZhbHVlAAUOdHlwZS1pNjQtdmFsdWUABg50eXBlLWYzMi12YWx1ZQAHDnR5cGUtZjY0LXZhbHVlAAgFZW1wdHkACQtlbXB0eS12YWx1ZQAKCXNpbmdsZXRvbgALD3NpbmdsZXRvbi12YWx1ZQAMCG11bHRpcGxlAA0ObXVsdGlwbGUtdmFsdWUADgVsYXJnZQAPDmFzLWJsb2NrLWZpcnN0ABAMYXMtYmxvY2stbWlkABENYXMtYmxvY2stbGFzdAASDmFzLWJsb2NrLXZhbHVlABMNYXMtbG9vcC1maXJzdAAUC2FzLWxvb3AtbWlkABUMYXMtbG9vcC1sYXN0ABYLYXMtYnItdmFsdWUAFw1hcy1icl9pZi1jb25kABgOYXMtYnJfaWYtdmFsdWUAGRNhcy1icl9pZi12YWx1ZS1jb25kABoRYXMtYnJfdGFibGUtaW5kZXgAGxFhcy1icl90YWJsZS12YWx1ZQAcF2FzLWJyX3RhYmxlLXZhbHVlLWluZGV4AB0PYXMtcmV0dXJuLXZhbHVlAB4KYXMtaWYtY29uZAAfCmFzLWlmLXRoZW4AIAphcy1pZi1lbHNlACEPYXMtc2VsZWN0LWZpcnN0ACIQYXMtc2VsZWN0LXNlY29uZAAjDmFzLXNlbGVjdC1jb25kACQNYXMtY2FsbC1maXJzdAAmC2FzLWNhbGwtbWlkACcMYXMtY2FsbC1sYXN0ACgWYXMtY2FsbF9pbmRpcmVjdC1maXJzdAApFGFzLWNhbGxfaW5kaXJlY3QtbWlkACoVYXMtY2FsbF9pbmRpcmVjdC1sYXN0ACsVYXMtY2FsbF9pbmRpcmVjdC1mdW5jACwSYXMtbG9jYWwuc2V0LXZhbHVlAC0SYXMtbG9jYWwudGVlLXZhbHVlAC4TYXMtZ2xvYmFsLnNldC12YWx1ZQAvD2FzLWxvYWQtYWRkcmVzcwAwEGFzLWxvYWROLWFkZHJlc3MAMRBhcy1zdG9yZS1hZGRyZXNzADIOYXMtc3RvcmUtdmFsdWUAMxFhcy1zdG9yZU4tYWRkcmVzcwA0D2FzLXN0b3JlTi12YWx1ZQA1EGFzLXVuYXJ5LW9wZXJhbmQANg5hcy1iaW5hcnktbGVmdAA3D2FzLWJpbmFyeS1yaWdodAA4D2FzLXRlc3Qtb3BlcmFuZAA5D2FzLWNvbXBhcmUtbGVmdAA6EGFzLWNvbXBhcmUtcmlnaHQAOxJhcy1jb252ZXJ0LW9wZXJhbmQAPBNhcy1tZW1vcnkuZ3Jvdy1zaXplAD0SbmVzdGVkLWJsb2NrLXZhbHVlAD4PbmVzdGVkLWJyLXZhbHVlAD8SbmVzdGVkLWJyX2lmLXZhbHVlAEAXbmVzdGVkLWJyX2lmLXZhbHVlLWNvbmQAQRVuZXN0ZWQtYnJfdGFibGUtdmFsdWUAQhtuZXN0ZWQtYnJfdGFibGUtdmFsdWUtaW5kZXgAQxpuZXN0ZWQtYnJfdGFibGUtbG9vcC1ibG9jawBEDm1lZXQtZXh0ZXJucmVmAEUJBwEAQQALASUK04kBRgIACw0AAkBBAA4BAABoGgsLDQACQEEADgEAAHoaCwsNAAJAQQAOAQAAjBoLCw0AAkBBAA4BAACaGgsLDgACf0EBQQAOAQAAaAsLDgACfkICQQAOAQAAegsLEQACfUMAAEBAQQAOAQAAjAsLFQACfEQAAAAAAAAQQEEADgEAAJoLCw8AAkAgAA4AAEEVDwtBFgsOAAJ/QSEgAA4AAEEfCwsWAAJAAkAgAA4BAQBBFQ8LQRQPC0EWCxYAAn8Cf0EhIAAOAQABQR8PCxpBIAsLMQACQAJAAkACQAJAIAAOBAMCAQAEQeMADwtB5AAPC0HlAA8LQeYADwtB5wAPC0HoAAtNAQF/An8CfwJ/An8Cf0HIASAADgQDAgEABCABQeMAag8LIQEgAUEKag8LIQEgAUELag8LIQEgAUEMag8LIQEgAUENag8LIQEgAUEOagusfgACQAJAIAAOlX4AAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABQX8PC0EADwtBAQ8LDgACQEEADgIAAAAQAAsLEAACQBAAQQAOAgAAABAACwsPAAJAARAAQQAOAgAAAAsLEQACfwEQAEECQQAOAgAAAAsLDwADf0EDQQAOAQEBQQELCxIAA38QAEEEQX8OAgEBAUECCwsRAAN/ARAAQQVBAQ4CAQEBCwsOAAJ/QQlBAA4AAAwACwsOAAJAQQEOAgAAAA0ACwsTAAJ/QQhBAA4AAEEBDQAaQQcLCxQAAn9BBkEJQQAOAQAADQAaQQcLCw8AAkBBAQ4AAA4CAAAACwsVAAJ/QQpBAA4AAEEBDgIAAABBBwsLFAACf0EGQQtBAQ4AAA4BAABBBwsLDQACfkIHQQAOAAAPCwsUAAJ/QQJBAA4AAAR/QQAFQQELCwsUAAJ/IAAEf0EDQQAOAAEFIAELCwsVAAJ/IAAEfyABBUEEQQAOAQEACwsLEQACf0EFQQAOAAAgACABGwsLEQACfyAAQQZBAQ4AACABGwsLEQACf0EAQQFBB0EBDgAAGwsLBABBfwsSAAJ/QQxBAQ4AAEECQQMQJQsLEgACf0EBQQ1BAQ4AAEEDECULCxIAAn9BAUECQQ5BAQ4AABAlCwsVAAJ/QRRBAQ4AAEEBQQJBAxEAAAsLFQACf0EAQRVBAQ4AAEECQQMRAAALCxUAAn9BAEEBQRZBAQ4AAEEDEQAACwsVAAJ/QQBBAUECQRdBAQ4AABEAAAsLEgEBfQJ/QRFBAQ4AACEAQX8LCxIBAX8Cf0EBQQEOAAAhAEF/CwsQAAJ/QQFBAQ4AACQAQX8LCxIAAn1DmpnZP0EBDgAAKgIACwsPAAJ+Qh5BAQ4AADAAAAsLGgACf0EeQQEOAABEAAAAAAAAHEA5AwBBfwsLEwACf0ECQR9BAQ4AADcDAEF/CwsTAAJ/QSBBAA4AAEEHOgAAQX8LCxMAAn9BAkEhQQAOAAA9AQBBfwsLEAACfUOamVlAQQAOAACMCwsQAAJ/QQNBAA4BAABBCmoLCw8AAn5CCkItQQAOAAB9CwsNAAJ/QSxBAA4AAEULCxcAAn9BK0EADgEAAEQAAAAAAAAkQGULCxIAAn9DAAAgQUEqQQAOAABcCwsNAAJ/QSlBAA4AAKcLCw4AAn9BKEEADgAAQAALCyMAAn9BfxpBAQJ/QQICf0EEGkEIQRAgAA4CAAECagtqC2oLCyIAAn9BAQJ/QQIaAn9BBBpBCCAADgICAQAMAAsaQRALagsLJwACf0EBAn9BAhoCf0EEGkEIIAAOAgABAkEBDQAaQSALGkEQC2oLCx4AAn9BAQJ/QQIaQQRBCCAADgIAAQANABpBEAtqCwsnAAJ/QQECf0ECGgJ/QQQaQQggAA4CAAECQQEOAABBIAsaQRALagsLHgACf0EBAn9BAhpBBEEIIAAOAgABAA4AAEEQC2oLCyIAA38CQCAADgIBAAALQQALIQADfwJAIAAOAgABAQtBAwsLEQACbwJvIAEgAA4CAQABCwsL", + "AGFzbQEAAAAB6QEZYAJ/fwF/YAABf2AAAX5gAAF9YAABfGAAAn9+YAF/AX9gAX4BfmABfQF9YAF8AXxgAn98An98YAJ/fwJ/f2ACfXwCfH1gAnx/An98YAJ9fwF/YAJ/fgF+YAJ8fQF9YAJ+fAF8YAACf3xgAAJ/f2AAAnx9YAJ+fgF+YAF+AX9gAABgZH1/f3x9fX18fX9/fXx+fn9+fn1+fn5/fX19fH1/fn18fH1/fX18fnx/fn18f39/fnx/fn58fHx8fHx/fXx8f359fX1/fHx8fHx9fn5/f399fH9+fX19f399fH59fH19fX99fn8BfwNPTgECAwQFBgcICQoLDA0ODxARAQIDBAUBAgMEAQIDBBITFBIBARMHFQcWFhcXFwEBAQEBAQEBAAEBARcXAQEXAQEBAQEGCAMBAQEBAQIYBgQFAXABAQEFAwEAAQYGAX8BQQoLB8oHOAh0eXBlLWkzMgARCHR5cGUtaTY0ABIIdHlwZS1mMzIAEwh0eXBlLWY2NAAUDHR5cGUtaTMyLWk2NAAVDnR5cGUtZmlyc3QtaTMyABYOdHlwZS1maXJzdC1pNjQAFw50eXBlLWZpcnN0LWYzMgAYDnR5cGUtZmlyc3QtZjY0ABkPdHlwZS1zZWNvbmQtaTMyABoPdHlwZS1zZWNvbmQtaTY0ABsPdHlwZS1zZWNvbmQtZjMyABwPdHlwZS1zZWNvbmQtZjY0AB0QdHlwZS1hbGwtaTMyLWY2NAAeEHR5cGUtYWxsLWkzMi1pMzIAHxB0eXBlLWFsbC1mMzItZjY0ACAQdHlwZS1hbGwtZjY0LWkzMgAhFmFzLWJpbmFyeS1hbGwtb3BlcmFuZHMAIhFhcy1taXhlZC1vcGVyYW5kcwAjFGFzLWNhbGwtYWxsLW9wZXJhbmRzACQDZmFjACUHZmFjLWFjYwAmA2ZpYgAnBGV2ZW4AKANvZGQAKQdydW5hd2F5ACoObXV0dWFsLXJ1bmF3YXkAKw9hcy1zZWxlY3QtZmlyc3QALQ1hcy1zZWxlY3QtbWlkAC4OYXMtc2VsZWN0LWxhc3QALw9hcy1pZi1jb25kaXRpb24AMA5hcy1icl9pZi1maXJzdAAxDWFzLWJyX2lmLWxhc3QAMhFhcy1icl90YWJsZS1maXJzdAAzEGFzLWJyX3RhYmxlLWxhc3QANBZhcy1jYWxsX2luZGlyZWN0LWZpcnN0ADYUYXMtY2FsbF9pbmRpcmVjdC1taWQANxVhcy1jYWxsX2luZGlyZWN0LWxhc3QAOA5hcy1zdG9yZS1maXJzdAA5DWFzLXN0b3JlLWxhc3QAOhRhcy1tZW1vcnkuZ3Jvdy12YWx1ZQA7D2FzLXJldHVybi12YWx1ZQA8D2FzLWRyb3Atb3BlcmFuZAA9C2FzLWJyLXZhbHVlAD4SYXMtbG9jYWwuc2V0LXZhbHVlAD8SYXMtbG9jYWwudGVlLXZhbHVlAEATYXMtZ2xvYmFsLnNldC12YWx1ZQBBD2FzLWxvYWQtb3BlcmFuZABCEGFzLXVuYXJ5LW9wZXJhbmQARQ5hcy1iaW5hcnktbGVmdABGD2FzLWJpbmFyeS1yaWdodABHD2FzLXRlc3Qtb3BlcmFuZABID2FzLWNvbXBhcmUtbGVmdABJEGFzLWNvbXBhcmUtcmlnaHQAShJhcy1jb252ZXJ0LW9wZXJhbmQASx5yZXR1cm4tZnJvbS1sb25nLWFyZ3VtZW50LWxpc3QATQkHAQBBAAsBNQr2CU4FAEGyAgsFAELkAgsHAEMAIHNFCwsARAAAAAAAyK5ACwgAQbICQuQCCwQAIAALBAAgAAsEACAACwQAIAALBgAgACABCwYAIAEgAAsGACABIAALBgAgASAACwQAIAELBAAgAQsEACABCwQAIAELBAAQAAsEABABCwQAEAILBAAQAwsEABAECwYAQSAQBQsHAELAABAGCwkAQ8P1qD8QBwsNAEQ9CtejcD36PxAICwsAQ2ZmAEJBIBANCwkAQSBCwAAQDgsSAEQAAAAAAABQQEMAAABCEA8LEABCwABEZmZmZmYGUEAQEAsPAEEgRD0K16NwPfo/EAkLCABBAUECEAoLEgBDAACAP0QAAAAAAAAAQBALCw8ARAAAAAAAAPA/QQIQDAsJAEEDQQQQCmoLDABBA0EEEApBBWpsCwoAQQNBBBAKEAoLFQAgAFAEfkIBBSAAIABCAX0QJX4LCxcAIABQBH4gAQUgAEIBfSAAIAF+ECYLCxwAIABCAVgEfkIBBSAAQgJ9ECcgAEIBfRAnfAsLEgAgAFAEf0EsBSAAQgF9ECkLCxMAIABQBH9B4wAFIABCAX0QKAsLBAAQKgsEABAsCwQAECsLCQAQAEECQQMbCwkAQQIQAEEDGwsJAEECQQMQABsLDAAQAAR/QQEFQQILCwsAAn8QAEECDQALCwsAAn9BAhAADQALCw0AAn8QAEECDgEAAAsLDQACf0ECEAAOAQAACwsEACAACw4AAn8QAEECQQARAAALCw4AAn9BAhAAQQARAAALCw4AAn9BAUECEAARAAALCwkAEABBATYCAAsJAEEKEAA2AgALBgAQAEAACwUAEAAPCwUAEAAaCwkAAn8QAAwACwsKAQF/EAAhACAACwgBAX8QACIACwgAEAAkACMACwcAEAAoAgALBAAgAAsEACAACw0AAn1DAAAAABBEkQsLDAACf0EBEENBCmoLCwwAAn9BCkEBEENrCwsKAAJ/QQEQQ0ULCwwAAn9BARBDQQpNCwsMAAJ/QQpBARBDRwsLCgACfkEBEEOsCwsEACBjC98DAEMAAAAAQQBBAEQAAAAAAAAAAEMAAAAAQwAAAABDAAAAAEQAAAAAAAAAAEMAAAAAQQBBAEMAAAAARAAAAAAAAAAAQgBCAEEAQgBCAEMAAAAAQgBCAEIAQQBDAAAAAEMAAAAAQwAAAABEAAAAAAAAAABDAAAAAEEAQgBDAAAAAEQAAAAAAAAAAEQAAAAAAAAAAEMAAAAAQQBDAAAAAEMAAAAARAAAAAAAAAAAQgBEAAAAAAAAAABBAEIAQwAAAABEAAAAAAAAAABBAEEAQQBCAEQAAAAAAAAAAEEAQgBCAEQAAAAAAAAAAEQAAAAAAAAAAEQAAAAAAAAAAEQAAAAAAAAAAEQAAAAAAAAAAEQAAAAAAAAAAEEAQwAAAABEAAAAAAAAAABEAAAAAAAAAABBAEIAQwAAAABDAAAAAEMAAAAAQQBEAAAAAAAAAABEAAAAAAAAAABEAAAAAAAAAABEAAAAAAAAAABEAAAAAAAAAABDAAAAAEIAQgBBAEEAQQBDAAAAAEQAAAAAAAAAAEEAQgBDAAAAAEMAAAAAQwAAAABBAEEAQwAAAABEAAAAAAAAAABCAEMAAAAARAAAAAAAAAAAQwAAAABDAAAAAEMAAAAAQQBDAAAAAEIAIAAQTAs=", + "AGFzbQEAAAABmAEdYAAAYAABf2AAAX5gAAF9YAABfGAAAnx/YAF/AX9gAX4BfmABfQF9YAF8AXxgAn98An98YAJ/fgJ+f2ACfX8Bf2ACf34BfmACfH0BfWACfnwBfGABfwF/YAF+AX5gAX0BfWABfAF8YAF+AGAEfnx/fgBgAX4Bf2AEfnx/fgF/YAACf3xgAAJ+f2ABfwF+YAF/AX1gAX8BfANRUAECAwQFBgcICQoLDQ8MDhAREhMAAQIDBAUCAQIDBAECAwQFGBkNGgYbHAcHBggJBggJBgYAAAABAQEBAgEDAQAAAQEAAwQEBAEDAQEBAQECBAUBcAEgIAUDAQABBg0BfAFEAAAAAAAAJEALB8QHOwh0eXBlLWkzMgAUCHR5cGUtaTY0ABUIdHlwZS1mMzIAFgh0eXBlLWY2NAAXDHR5cGUtZjY0LWkzMgAYCnR5cGUtaW5kZXgAGQ50eXBlLWZpcnN0LWkzMgAaDnR5cGUtZmlyc3QtaTY0ABsOdHlwZS1maXJzdC1mMzIAHA50eXBlLWZpcnN0LWY2NAAdD3R5cGUtc2Vjb25kLWkzMgAeD3R5cGUtc2Vjb25kLWk2NAAfD3R5cGUtc2Vjb25kLWYzMgAgD3R5cGUtc2Vjb25kLWY2NAAhEHR5cGUtYWxsLWY2NC1pMzIAIhB0eXBlLWFsbC1pMzItZjY0ACMQdHlwZS1hbGwtaTMyLWk2NAAkCGRpc3BhdGNoACUXZGlzcGF0Y2gtc3RydWN0dXJhbC1pNjQAJhdkaXNwYXRjaC1zdHJ1Y3R1cmFsLWkzMgAnF2Rpc3BhdGNoLXN0cnVjdHVyYWwtZjMyACgXZGlzcGF0Y2gtc3RydWN0dXJhbC1mNjQAKQdmYWMtaTY0ACoHZmliLWk2NAArB2ZhYy1pMzIALAdmYWMtZjMyAC0HZmFjLWY2NAAuB2ZpYi1pMzIALwdmaWItZjMyADAHZmliLWY2NAAxBGV2ZW4AMgNvZGQAMwdydW5hd2F5ADQObXV0dWFsLXJ1bmF3YXkANQ9hcy1zZWxlY3QtZmlyc3QANw1hcy1zZWxlY3QtbWlkADgOYXMtc2VsZWN0LWxhc3QAOQ9hcy1pZi1jb25kaXRpb24AOg5hcy1icl9pZi1maXJzdAA7DWFzLWJyX2lmLWxhc3QAPBFhcy1icl90YWJsZS1maXJzdAA9EGFzLWJyX3RhYmxlLWxhc3QAPg5hcy1zdG9yZS1maXJzdAA/DWFzLXN0b3JlLWxhc3QAQBRhcy1tZW1vcnkuZ3Jvdy12YWx1ZQBBD2FzLXJldHVybi12YWx1ZQBCD2FzLWRyb3Atb3BlcmFuZABDC2FzLWJyLXZhbHVlAEQSYXMtbG9jYWwuc2V0LXZhbHVlAEUSYXMtbG9jYWwudGVlLXZhbHVlAEYTYXMtZ2xvYmFsLnNldC12YWx1ZQBHD2FzLWxvYWQtb3BlcmFuZABIEGFzLXVuYXJ5LW9wZXJhbmQASQ5hcy1iaW5hcnktbGVmdABKD2FzLWJpbmFyeS1yaWdodABLD2FzLXRlc3Qtb3BlcmFuZABMD2FzLWNvbXBhcmUtbGVmdABNEGFzLWNvbXBhcmUtcmlnaHQAThJhcy1jb252ZXJ0LW9wZXJhbmQATwkmAQBBAAsgAAECAwUGBwgNCw4MKisyMzQ1Ng8QERIsLS4vMDEECQoK4QlQBQBBsgILBQBC5AILBwBDACBzRQsLAEQAAAAAAMiuQAsNAEQAAAAAAMiuQEEgCwQAIAALBAAgAAsEACAACwQAIAALBgAgACABCwYAIAEgAAsEACABCwQAIAELBAAgAQsEACABCwQAIAALBAAgAAsEACAACwQAIAALXQBBABEAAEIAQQARFABCAEQAAAAAAAAAAEEAQgBBABEVAEEAEQAAQQARAQBFGkEAEQEARRpCAEEAERYARRpCAEQAAAAAAAAAAEEAQgBBABEXAEUaQgBBABEHAFAaCwcAQQARAQALBwBBARECAAsHAEECEQMACwcAQQMRBAALBwBBHREFAAsKAELkAEEFEQcACwkAQSBBBBEGAAsKAELAAEEFEQcACwwAQ8P1qD9BBhEIAAsQAEQ9CtejcD36P0EHEQkACw4AQ2ZmAEJBIEEIEQwACwwAQSBCwABBCRENAAsVAEQAAAAAAABQQEMAAABCQQoRDgALEwBCwABEZmZmZmYGUEBBCxEPAAsHAEEdEQUACxIAQQFEAAAAAAAAAEBBHhEKAAsLAEEBQgJBHxELAAsJACABIAARBwALCQBCCSAAEREACwkAQQkgABEQAAsMAEMAABBBIAAREgALEABEAAAAAAAAIkAgABETAAsYACAAUAR+QgEFIAAgAEIBfUEMEQcAfgsLIgAgAEIBWAR+QgEFIABCAn1BDREHACAAQgF9QQ0RBwB8CwsYACAARQR/QQEFIAAgAEEBa0EXEQYAbAsLIwAgAEMAAAAAWwR9QwAAgD8FIAAgAEMAAIA/k0EYEQgAlAsLLwAgAEQAAAAAAAAAAGEEfEQAAAAAAADwPwUgACAARAAAAAAAAPA/oUEZEQkAogsLIgAgAEEBTQR/QQEFIABBAmtBGhEGACAAQQFrQRoRBgBqCwsuACAAQwAAgD9fBH1DAACAPwUgAEMAAABAk0EbEQgAIABDAACAP5NBGxEIAJILCz4AIABEAAAAAAAA8D9lBHxEAAAAAAAA8D8FIABEAAAAAAAAAEChQRwRCQAgAEQAAAAAAADwP6FBHBEJAKALCxUAIABFBH9BLAUgAEEBa0EPEQYACwsWACAARQR/QeMABSAAQQFrQQ4RBgALCwcAQRARAAALBwBBEhEAAAsHAEEREQAACwwAQQARAQBBAkEDGwsMAEECQQARAQBBAxsLDABBAkEDQQARAQAbCw8AQQARAQAEf0EBBUECCwsOAAJ+QQERAgBBAg0ACwsOAAJ/QQJBABEBAA0ACwsQAAJ9QQIRAwBBAg4BAAALCxAAAn9BAkEAEQEADgEAAAsLDABBABEBAEEBNgIACwwAQQpBAxEEADkDAAsJAEEAEQEAQAALCgBBAUEEEQYADwsKAEIBQQURBwAaCxEAAn1DAACAP0EGEQgADAALCxYBAXxEAAAAAAAA8D9BBxEJACEAIAALFAEBfEQAAAAAAADwP0EHEQkAIgALFABEAAAAAAAA8D9BBxEJACQAIwALCgBBABEBACgCAAsQAAJ9QwAAAABBBhEIAJELCw8AAn9BAUEEEQYAQQpqCwsPAAJ/QQpBAUEEEQYAawsLDQACf0EBQQQRBgBFCwsPAAJ/QQFBBBEGAEEKTQsLDwACf0EKQQFBBBEGAEcLCw0AAn5BAUEEEQYArAsL", + "AGFzbQEAAAABEQNgAn9/AX9gAABgA39/fwF/AwoJAAAAAAABAgICBAwDcAECAnABAwNwAAQHHAMGY2FsbC0xAAYGY2FsbC0yAAcGY2FsbC0zAAgJIwQAQQALAgABAgFBAAsAAwIDBAICQQALAAIBAgICQQMLAAEFClAJBwAgACABagsHACAAIAFrCwcAIAAgAWwLBwAgACABbgsHACAAIAFwCwIACwsAIAAgASACEQAACwsAIAAgASACEQABCwsAIAAgASACEQACCw==", + "AGFzbQEAAAABCAJgAABgAAF/AwwLAAAAAAAAAAAAAQEEBAFwAAEKZgsGAAARAAALBwAAEQAAAQsJAAARAAARAAALCQAAEQAAEQAACwwAABEAABEAABEAAAsGAAARAAALBgAAEQAACwkAABEAABEAAAsJAAARAAARAAALBwAAEQAAGwsKAAARAAAbEQAACw==", + "AGFzbQEAAAABGgRgAX4BfmABfgJ+fmACfn4Dfn5+YAJ+fgF+AwkIAAAAAAABAgAHSwYHZmFjLXJlYwAADWZhYy1yZWMtbmFtZWQAAQhmYWMtaXRlcgACDmZhYy1pdGVyLW5hbWVkAAMHZmFjLW9wdAAEB2ZhYy1zc2EABwrrAQgXACAAQgBRBH5CAQUgACAAQgF9EAB+CwsXACAAQgBRBH5CAQUgACAAQgF9EAF+CwsvAQJ+IAAhAUIBIQICQANAIAFCAFEEQAwCBSABIAJ+IQIgAUIBfSEBCwwACwsgAgsvAQJ+IAAhAUIBIQICQANAIAFCAFEEQAwCBSABIAJ+IQIgAUIBfSEBCwwACwsgAgssAQF+QgEhAQJAIABCAlMNAANAIAEgAH4hASAAQn98IQAgAEIBVQ0ACwsgAQsGACAAIAALCAAgACABIAALHABCASAAAwMQBhAGfhAGQgF9EAVCAFYNABoPCws=", + "AGFzbQEAAAABBgFgAX8BfwMDAgAABw4CBGV2ZW4AAANvZGQAAQorAhQAIABBAEYEf0EBBSAAQQFrEAELCxQAIABBAEYEf0EABSAAQQFrEAALCw==", + "AGFzbQEAAAABvAEcYAAAYAAAYAABf2ABfwBgA398fwF/YAAAYAN/fH4AYAJ/fABgBX99fn98AGAAA398fWAAAn98YAAFf31+f3xgBH99fn8Df35/YAABfmAAAX1gAAF8YAJ/fwF/YAJ+fgF+YAJ9fQF9YAJ8fAF8YAZ9f35/fH8BfGAAA39/f2AAAn9+YAF/AX9gAX8Cf35gAX8Cf39gAAJ/f2ARf359fX98fX9/f318fHx/f30QfH1/f39+fX9/fXx8f31/fANiYQAAAAAAAAAAAAAAAAAAAwMGBwgAAAIJCgsBAgMEAgMEAAUMAAINDg8CDQ4PDxAREhMQERITFAAAAg0ODwoVAAIWAAINDg8KFQIWAAINDg8KFQIWAxcYAxcYAxcZGwINDg8HlAlGAWYAAgFnAAQKdHlwZS11c2UtMQAZCnR5cGUtdXNlLTIAGgp0eXBlLXVzZS0zABsKdHlwZS11c2UtNAAcCnR5cGUtdXNlLTUAHQp0eXBlLXVzZS02AB4KdHlwZS11c2UtNwAfD2xvY2FsLWZpcnN0LWkzMgAkD2xvY2FsLWZpcnN0LWk2NAAlD2xvY2FsLWZpcnN0LWYzMgAmD2xvY2FsLWZpcnN0LWY2NAAnEGxvY2FsLXNlY29uZC1pMzIAKBBsb2NhbC1zZWNvbmQtaTY0ACkQbG9jYWwtc2Vjb25kLWYzMgAqEGxvY2FsLXNlY29uZC1mNjQAKwtsb2NhbC1taXhlZAAsD3BhcmFtLWZpcnN0LWkzMgAtD3BhcmFtLWZpcnN0LWk2NAAuD3BhcmFtLWZpcnN0LWYzMgAvD3BhcmFtLWZpcnN0LWY2NAAwEHBhcmFtLXNlY29uZC1pMzIAMRBwYXJhbS1zZWNvbmQtaTY0ADIQcGFyYW0tc2Vjb25kLWYzMgAzEHBhcmFtLXNlY29uZC1mNjQANAtwYXJhbS1taXhlZAA1BWVtcHR5ADYKdmFsdWUtdm9pZAA3CXZhbHVlLWkzMgA4CXZhbHVlLWk2NAA5CXZhbHVlLWYzMgA6CXZhbHVlLWY2NAA7DXZhbHVlLWkzMi1mNjQAPBF2YWx1ZS1pMzItaTMyLWkzMgA9EHZhbHVlLWJsb2NrLXZvaWQAPg92YWx1ZS1ibG9jay1pMzIAPxN2YWx1ZS1ibG9jay1pMzItaTY0AEAMcmV0dXJuLWVtcHR5AEEKcmV0dXJuLWkzMgBCCnJldHVybi1pNjQAQwpyZXR1cm4tZjMyAEQKcmV0dXJuLWY2NABFDnJldHVybi1pMzItZjY0AEYScmV0dXJuLWkzMi1pMzItaTMyAEcQcmV0dXJuLWJsb2NrLWkzMgBIFHJldHVybi1ibG9jay1pMzItaTY0AEkLYnJlYWstZW1wdHkASglicmVhay1pMzIASwlicmVhay1pNjQATAlicmVhay1mMzIATQlicmVhay1mNjQATg1icmVhay1pMzItZjY0AE8RYnJlYWstaTMyLWkzMi1pMzIAUA9icmVhay1ibG9jay1pMzIAURNicmVhay1ibG9jay1pMzItaTY0AFIRYnJlYWstYnJfaWYtZW1wdHkAUw9icmVhay1icl9pZi1udW0AVBNicmVhay1icl9pZi1udW0tbnVtAFUUYnJlYWstYnJfdGFibGUtZW1wdHkAVhJicmVhay1icl90YWJsZS1udW0AVxZicmVhay1icl90YWJsZS1udW0tbnVtAFgbYnJlYWstYnJfdGFibGUtbmVzdGVkLWVtcHR5AFkZYnJlYWstYnJfdGFibGUtbmVzdGVkLW51bQBaHWJyZWFrLWJyX3RhYmxlLW5lc3RlZC1udW0tbnVtAFsJbGFyZ2Utc2lnAFwOaW5pdC1sb2NhbC1pMzIAXQ5pbml0LWxvY2FsLWk2NABeDmluaXQtbG9jYWwtZjMyAF8OaW5pdC1sb2NhbC1mNjQAYAq3BmECAAsCAAsCAAsCAAsCAAsCAAsCAAsEAQF/CwQBAX8LCAMBfwF8AX4LBgIBfwF8CwwFAX8BfQF+AX8BfAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsDAAALAwAACwMAAAsDAAALAgALBABBAAsCAAsEAEEACwQAQQALAgALBABBAAsCAAsCAAsQBgF9AX8BfgF/AXwBfwAACxAGAX0BfwF+AX8BfAF/AAALBgECfyAACwYBAn4gAAsGAQJ9IAALBgECfCAACwYBAn8gAQsGAQJ+IAELBgECfSABCwYBAnwgAQsoBgF9AX8BfgF/AXwBfyAAjBogAUUaIAJQGiADRRogBJoaIAVFGiAECwQAIAALBAAgAAsEACAACwQAIAALBAAgAQsEACABCwQAIAELBAAgAQscACAAjBogAUUaIAJQGiADRRogBJoaIAVFGiAECwIACwQAEAALBQBBzQALBQBC4TwLBwBDZmabQgsLAEThehSuR3FTQAsOAEHNAEQAAAAAAAAcQAsIAEEBQQJBAwsJAAJAEAAQAAsLCgACfxAAQc0ACwsLAAIWEABBAUICCwsDAA8LBgBBzgAPCwYAQsY9DwsIAENmZp1CDwsMAERSuB6F67FTQA8LDwBBzgBEUrgeheuxU0APCwkAQQFBAkEDDwsLAAJ/EABBzQALDwsMAAIWEABBAUICCw8LBAAMAAsHAEHPAAwACwcAQqs+DAALCQBDzcyfQgwACw0ARMP1KFyP8lNADAALEABBzwBEw/UoXI/yU0AMAAsKAEEBQQJBAwwACwwAAn8QAEHNAAsMAAsNAAIWEABBAUICCwwACwYAIAANAAsLAEEyIAANABpBMwsQAEEyQjMgAA0AGhpBM0I0CwkAIAAOAgAAAAsMAEEyIAAOAQAAQTMLEABBMkIzIAAOAQAAQTNCNAsMAAJAIAAOAgABAAsLEwACf0EyIAAOAgABAEEzC0ECagsXAAIaQTJBMyAADgIAAQBBM0F9C2pBNAsiACAFIAIgACAIIAcgASADIAkgBCAGIA0gCyAPIBAgDiAMCwYBAX8gAAsGAQF+IAALBgEBfSAACwYBAXwgAAs=", + "AGFzbQEAAAABDANgAX8AYAABfGAAAAMGBQEAAAECCikFCwBEAAAAAAAAAAALAgALAgALCwBEAAAAAAAAAAALCQBBABACEAMaCw==", + "AGFzbQEAAAABCgJgAAF/YAF/AX8DBQQBAQEABw0DAWYAAAFnAAIBcAADCiEEBgEBfyABCwYBAX8gAQsGACAAEAELCgEBf0EqIQAgAAs=", + "AGFzbQEAAAABHQRgAABgAABgCH5+fH58fn1/AGAIfH58fnx+fX8AAwwLAAMAAwMCAgAAAAAEBQFwAQcHB3cEGXNpZ25hdHVyZS1leHBsaWNpdC1yZXVzZWQABxlzaWduYXR1cmUtaW1wbGljaXQtcmV1c2VkAAgcc2lnbmF0dXJlLWV4cGxpY2l0LWR1cGxpY2F0ZQAJHHNpZ25hdHVyZS1pbXBsaWNpdC1kdXBsaWNhdGUACgkNAQBBAAsHBAIBBAAFBgqFAgsCAAsCAAsCAAsCAAsCAAsCAAsCAAsMAEEBEQAAQQQRAAALiQEARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEAEQMARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEECEQMARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEDEQMACwcAQQERAQALTgBCAEIARAAAAAAAAAAAQgBEAAAAAAAAAABCAEMAAAAAQQBBBRECAEIAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEGEQIACw==", + "AGFzbQEAAAABGwdgAABgAABgAABgAAF/YAABf2ABfwF/YAF/AAIWAQhzcGVjdGVzdAlwcmludF9pMzIABgMHBgABBAUFBgccBANvbmUAAwN0d28ABAV0aHJlZQAFBGZvdXIABgojBgIACwIACwQAQQ0LBwAgAEEBagsHACAAQQJrCwYAIAAQAAs=", + "AGFzbQEAAAABDgNgAAF/YAABf2ABfwF/AwgHAAAAAQECAgQFAXABBwcHEQIFY2FsbHQABQVjYWxsdQAGCQ0BAEEACwcAAQIDBAACCioHBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwcAIAARAAALBwAgABEBAAs=", + "AGFzbQEAAAABCgJgAAF/YAF/AX8DBAMAAAEEBQFwAQICBwkBBWNhbGx0AAIJCAEAQQALAgABChMDBABBAQsEAEECCwcAIAARAAAL", + "AGFzbQEAAAABXRBgAn9/AX9gAABgAAF/YAF/AGADf3x/A398f2ABfwF/YAF/An9/YAADf35/YAACf39gAAJ9fWABfwN/f35gAAN/f35gAn9/An9/YAN+fn8Cfn9gAn5+AX5gAX4BfgM2NQEDBQYABQUFBQUFBQUFBQUABQUFAwMFBQUFAwUFBQUFBQAFAAUFBQIFCgUFBQUFBQUNDgEBBAUBcAEBAQUDAQABBgYBfwFBCgsHzgYyBWVtcHR5AAEIc2luZ3VsYXIAAgVtdWx0aQADBm5lc3RlZAAED2FzLXNlbGVjdC1maXJzdAAFDWFzLXNlbGVjdC1taWQABg5hcy1zZWxlY3QtbGFzdAAHDWFzLWxvb3AtZmlyc3QACAthcy1sb29wLW1pZAAJDGFzLWxvb3AtbGFzdAAKD2FzLWlmLWNvbmRpdGlvbgALDmFzLWJyX2lmLWZpcnN0AAwNYXMtYnJfaWYtbGFzdAANEWFzLWJyX3RhYmxlLWZpcnN0AA4QYXMtYnJfdGFibGUtbGFzdAAPFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAERRhcy1jYWxsX2luZGlyZWN0LW1pZAASFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAATDmFzLXN0b3JlLWZpcnN0ABQNYXMtc3RvcmUtbGFzdAAVFGFzLW1lbW9yeS5ncm93LXZhbHVlABYNYXMtY2FsbC12YWx1ZQAYD2FzLXJldHVybi12YWx1ZQAZD2FzLWRyb3Atb3BlcmFuZAAaC2FzLWJyLXZhbHVlABsSYXMtbG9jYWwuc2V0LXZhbHVlABwSYXMtbG9jYWwudGVlLXZhbHVlAB0TYXMtZ2xvYmFsLnNldC12YWx1ZQAeD2FzLWxvYWQtb3BlcmFuZAAfEGFzLXVuYXJ5LW9wZXJhbmQAIBFhcy1iaW5hcnktb3BlcmFuZAAhD2FzLXRlc3Qtb3BlcmFuZAAiEmFzLWNvbXBhcmUtb3BlcmFuZAAjEmFzLWJpbmFyeS1vcGVyYW5kcwAkE2FzLWNvbXBhcmUtb3BlcmFuZHMAJRFhcy1taXhlZC1vcGVyYW5kcwAmCmJyZWFrLWJhcmUAJwticmVhay12YWx1ZQAoEWJyZWFrLW11bHRpLXZhbHVlACkFcGFyYW0AKgZwYXJhbXMAKwlwYXJhbXMtaWQALAtwYXJhbS1icmVhawAtDHBhcmFtcy1icmVhawAuD3BhcmFtcy1pZC1icmVhawAvB2VmZmVjdHMAMBJhZGQ2NF91X3dpdGhfY2FycnkAMRFhZGQ2NF91X3NhdHVyYXRlZAAyCHR5cGUtdXNlADMSYXR5cGljYWwtY29uZGl0aW9uADQJBwEAQQALARAKxgs1AgALFgAgAARACyAABEALIAAEQAsgAARACwsaACAABEABCyAABEABBQELIAAEf0EHBUEICwtnACAABEAQABAAEAALIAAEQAUQABAAEAALIAAEfxAAEABBCBAABRAAEABBCRAACyAABAcQABAAQQEQABAAEABCAhAAEAAQAEEDEAAFEAAQAEF/EAAQABAAQn4QABAAEABBfRAACxoaC1IAIAAEfyABBEAQAAJACwELIAEEQAUQAAJACwELIAEEfxAAQQkFEABBCgsFIAEEQBAAAkALAQsgAQRABRAAAkALAQsgAQR/EABBCgUQAEELCwsLFQAgAAR/EABBAQUQAEEAC0ECQQMbCxUAQQIgAAR/EABBAQUQAEEAC0EDGwsVAEECQQMgAAR/EABBAQUQAEEACxsLFwADfyAABH8QAEEBBRAAQQALEAAQAAsLFwADfxAAIAAEfxAAQQEFEABBAAsQAAsLFwADfxAAEAAgAAR/EABBAQUQAEEACwsLGAAgAAR/QQEFQQALBH8QAEECBRAAQQMLCxoAAn8gAAR/EABBAQUQAEEAC0ECDQBBAw8LCxoAAn9BAiAABH8QAEEBBRAAQQALDQBBAw8LCxkAAn8gAAR/EABBAQUQAEEAC0ECDgEAAAsLGQACf0ECIAAEfxAAQQEFEABBAAsOAQAACwsEACAACxoAAn8gAAR/EABBAQUQAEEAC0ECQQARAAALCxoAAn9BAiAABH8QAEEBBRAAQQALQQARAAALCxoAAn9BAkEAIAAEfxAAQQEFEABBAAsRAAALCxUAIAAEfxAAQQEFEABBAAtBAjYCAAsVAEECIAAEfxAAQQEFEABBAAs2AgALDgAgAAR/QQEFQQALQAALBAAgAAsOACAABH9BAQVBAAsQFwsNACAABH9BAQVBAAsPCw0AIAAEf0EBBUEACxoLEQACfyAABH9BAQVBAAsMAAsLEgEBfyAABH9BAQVBAAshACAACw4AIAAEf0EBBUEACyIACxAAIAAEf0EBBUEACyQAIwALDwAgAAR/QQsFQQoLKAIACxEAIAAEfxAAQQ0FEABBcwtoCx8AIAAEfxAAQQMFEABBfQsgAQR/EABBBAUQAEF7C2wLEQAgAAR/EABBDQUQAEEAC0ULKwAgAAR9EABDAABAQAUQAEMAAEDACyABBH0QAEMAAIBABRAAQwAAgMALXgsZACAABAgQAEEDEABBBAUQAEEDEABBfAtsCyUAIAAECRAAQwAAQEAQAEMAAEBABRAAQwAAAMAQAEMAAEDAC14LHAAgAAQIEABBAxAAQQQFEABBfRAAQXwLQQVqbAtnAEEBBEAMAAALQQEEQAwAAAUAC0EABEAABQwAAAtBAQRAQQENAAALQQEEQEEBDQAABQALQQAEQAAFQQENAAALQQEEQEEADgAAAAtBAQRAQQAOAAAABQALQQAEQAAFQQAOAAAAC0ETCxQAIAAEf0ESDABBEwVBFQwAQRQLCyQAIAAEC0ESQW5CEgwAQRNBbUITBUFuQRJCbgwAQW1BE0JtCwsQAEEBIAAEBUECagVBfmoLCw4AQQFBAiAABABqBWsLCwwAQQFBAiAABAwLagsUAEEBIAAEBUECagwABUF+agwACwsSAEEBQQIgAAQAagwABWsMAAsLDgBBAUECIAAEDAwAC2oLUQEBfwJ/QQEhASAACwRAIAFBA2whASABQQVrIQEgAUEHbCEBDAAgAUHkAGwhAQUgAUEFbCEBIAFBB2shASABQQNsIQEMACABQegHbCEBCyABCxcBAX4gACABfCACrXwhAyADIAMgAFQPCxAAIAAgAUEAEDEEDxpCfwsLVQBBAQRAC0EBBH9BAAVBAgtBAQQDGgUaC0EARAAAAAAAAAAAQQBBAQQECxoaGkEBBH9BAAVBAgtBAQQDGgUaC0EARAAAAAAAAAAAQQBBAQQECxoaGgsNAEEABEALQQFFBEALCw==", + "AGFzbQEAAAABCgJgAAF/YAF/AX8DExIAAAAAAQAAAAABAQAAAAAAAAAHmgESBWJsb2NrAAAFbG9vcDEAAQVsb29wMgACBWxvb3AzAAMFbG9vcDQABAVsb29wNQAFBWxvb3A2AAYCaWYABwNpZjIACAZzd2l0Y2gACQZyZXR1cm4ACgZicl9pZjAACwZicl9pZjEADAZicl9pZjIADQZicl9pZjMADgJicgAPCXNoYWRvd2luZwAQDHJlZGVmaW5pdGlvbgARCoMGEgsAAn9BAQwAQQALCyMBAX9BACEAAn8DfyAAQQFqIQAgAEEFRgRAIAAMAgsMAAsLCzQBAX9BACEAAn8DfyAAQQFqIQAgAEEFRgRADAELIABBCEYEQCAADAILIABBAWohAAwACwsLIwEBf0EAIQACfwN/IABBAWohACAAQQVGBEAgAAwCCyAACwsLIwEBf0EBIQECfwN/IAEgAWohASABIABLBEAgAQwCCwwACwsLCgADf0EBC0EBagsLAAN/QQANAEEDCwuEAQEBf0EAIQACQEEBBEAMAEGaBSEACyAAQQFqIQBBAQRADABBmgUhAAVB+AYhAAsgAEEBaiEAQQEEQAwAQZoFIQAFQfgGIQALIABBAWohAEEABEBB+AYhAAUMAEGaBSEACyAAQQFqIQBBAARAQfgGIQAFDABBmgUhAAsgAEEBaiEACyAAC4QBAQF/QQAhAAJAQQEEQAwAQZoFIQALIABBAWohAEEBBEAMAEGaBSEABUH4BiEACyAAQQFqIQBBAQRADABBmgUhAAVB+AYhAAsgAEEBaiEAQQAEQEH4BiEABQwAQZoFIQALIABBAWohAEEABEBB+AYhAAUMAEGaBSEACyAAQQFqIQALIAALLQACf0EKAn8CQAJAAkACQAJAIAAOBAQAAQIDCwtBAgwDC0EDDAMLC0EFC2wLCxgAAkACQAJAIAAOAQABDAILQQAPCwtBAgtWAQF/QQAhAAJ/AkBBAA0AIABBAXIhAEEBDQAgAEECciEACwJ/IABBBHIhACAAC0EADQAaIABBCHIhAAJ/IABBEHIhACAAC0EBDQAaIABBIHIhACAACwsTAAJ/An9BAQwAC0EBDQAaQQALCxgAAn9BAQRAAn9BAQwAC0EBDQEaC0EACwskAQF/An8Cf0EBIQAgAAsCf0ECIQAgAAsNABpBAAtBAGoaIAALIQACf0EBBEACf0EBDAALDAEFAkACf0EBDAALGgsLQQELCwwAAn9BAQwAQQJzCwsSAAJ/An9BAgsCf0EDDAALagsL", + "AGFzbQEAAAABTg5gAn9/AX9gAABgAAF/YAF/AGADf3x/A398f2AAA39+f2ABfwF/YAACf39gAAJ9fWAAA39/fmADf39+AGACf38Cf39gAX4BfmACfX0BfQM5OAEBAgICAgICAgECAgICAgIAAgICAQECBgICAQICAgICAgICAgICAgICCQICAgICAgICAgIMDA0BBAUBcAEBAQUDAQABBgYBfwFBAAsHyAY1BWVtcHR5AAEIc2luZ3VsYXIAAgVtdWx0aQADBm5lc3RlZAAEBGRlZXAABQ9hcy1zZWxlY3QtZmlyc3QABg1hcy1zZWxlY3QtbWlkAAcOYXMtc2VsZWN0LWxhc3QACA9hcy1pZi1jb25kaXRpb24ACQphcy1pZi10aGVuAAoKYXMtaWYtZWxzZQALDmFzLWJyX2lmLWZpcnN0AAwNYXMtYnJfaWYtbGFzdAANEWFzLWJyX3RhYmxlLWZpcnN0AA4QYXMtYnJfdGFibGUtbGFzdAAPFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAERRhcy1jYWxsX2luZGlyZWN0LW1pZAASFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAATDmFzLXN0b3JlLWZpcnN0ABQNYXMtc3RvcmUtbGFzdAAVFGFzLW1lbW9yeS5ncm93LXZhbHVlABYNYXMtY2FsbC12YWx1ZQAYD2FzLXJldHVybi12YWx1ZQAZD2FzLWRyb3Atb3BlcmFuZAAaC2FzLWJyLXZhbHVlABsSYXMtbG9jYWwuc2V0LXZhbHVlABwSYXMtbG9jYWwudGVlLXZhbHVlAB0TYXMtZ2xvYmFsLnNldC12YWx1ZQAeD2FzLWxvYWQtb3BlcmFuZAAfEGFzLXVuYXJ5LW9wZXJhbmQAIBFhcy1iaW5hcnktb3BlcmFuZAAhD2FzLXRlc3Qtb3BlcmFuZAAiEmFzLWNvbXBhcmUtb3BlcmFuZAAjEmFzLWJpbmFyeS1vcGVyYW5kcwAkE2FzLWNvbXBhcmUtb3BlcmFuZHMAJRFhcy1taXhlZC1vcGVyYW5kcwAmCmJyZWFrLWJhcmUAJwticmVhay12YWx1ZQAoEWJyZWFrLW11bHRpLXZhbHVlACkOYnJlYWstcmVwZWF0ZWQAKgticmVhay1pbm5lcgArCmNvbnQtaW5uZXIALAVwYXJhbQAtBnBhcmFtcwAuCXBhcmFtcy1pZAAvC3BhcmFtLWJyZWFrADAMcGFyYW1zLWJyZWFrADEPcGFyYW1zLWlkLWJyZWFrADIHZWZmZWN0cwAzBXdoaWxlADQDZm9yADUHbmVzdGluZwA2CHR5cGUtdXNlADcJBwEAQQALARAKgws4AgALCAADQAsDQAsLCwADQAELA39BBwsLPAADQBAAEAAQABAACwN/EAAQAEEIEAALGgMFEAAQABAAQQgQABAAEAAQAEIHEAAQABAAEABBCRAACxoaCxUAA38DQBAAAkALAQsDfxAAQQkLCwt/AAN/An8DfwJ/A38CfwN/An8DfwJ/A38CfwN/An8DfwJ/A38CfwN/An8DfwJ/A38CfwN/An8DfwJ/A38CfwN/An8DfwJ/A38CfwN/An8DfwJ/EABBlgELCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwwAA39BAQtBAkEDGwsMAEECA39BAQtBAxsLDABBAkEDA39BAQsbCwwAA39BAQsEQBAACwsPAEEBBH8Df0EBCwVBAgsLDwBBAQR/QQIFA39BAQsLCw4AAn8Df0EBC0ECDQALCw4AAn9BAgN/QQELDQALCxAAAn8Df0EBC0ECDgEAAAsLEAACf0ECA39BAQsOAQAACwsEACAACxEAAn8Df0EBC0ECQQARAAALCxEAAn9BAgN/QQELQQARAAALCxEAAn9BAUECA39BAAsRAAALCwwAA39BAQtBATYCAAsMAEEKA39BAQs2AgALCQADf0EBC0AACwQAIAALCQADf0EBCxAXCwgAA39BAQsPCwgAA39BAQsaCwwAAn8Df0EBCwwACwsNAQF/A39BAQshACAACwsBAX8Df0EBCyIACwsAA39BAQskACMACwoAA39BAQsoAgALCgADfxAAQQ0LaAsRAAN/EABBAwsDfxAAQQQLbAsKAAN/EABBDQtFCxcAA30QAEMAAEBACwN9EABDAABAQAteCw4AAwcQAEEDEABBBAtsCxQAAwgQAEMAAEBAEABDAABAQAteCxEAAwcQAEEDEABBBAtBBWpsCzQAAkADQAwBDAAACwsCQANAQQENAQALCwJAA0BBAA4AAQALCwJAA0BBAQ4CAQEBAAsLQRMLFwACf0EAAwMCQEESDAILQRQMAAtBEwsLJwACCUEAQQBCAAMKAkBBEkFuQhIMAgtBFEFsQhQMAAtBE0FtQhMLCzQAAn8Df0ESDAFBEwwBQRRBAA0BGkEUQQENARpBFQwBQRZBAA4AAUEXQQEOAgEBAUEVCwsLZgEBf0EAIQAgAAJ/A38Cf0EBDAILCwtqIQAgAAJ/A38Df0ECDAILCwtqIQAgAAJ/A38CfwN/QQQMAQsLCwtqIQAgAAJ/A39BCAwBaAsLaiEAIAACfwN/A39BEAwCC2gLC2ohACAACzABAX9BACEAIAADfwN/DAELC2ohACAAA38MAGgLaiEAIAADfwN/DAELaAtqIQAgAAsKAEEBAwZBAmoLCwoAQQFBAgMAagsLCgBBAUECAwsLagsVAQF/QQEDBkEEaiIAIABBCkkNAAsLGAEBf0EBQQIDAGoiAEEDIABBCkkNABoLCx4BAX9BACEAQQFBAgMLIABBAWohACAAQQpJDQALagsyAQF/AkADQEEBIQAgAEEDbCEAIABBBWshACAAQQdsIQAMASAAQeQAbCEACwsgAEFyRgslAQF+QgEhAQJAA0AgAFANASAAIAF+IQEgAEIBfSEADAALCyABCysBAn5CASEBQgIhAgJAA0AgAiAAVg0BIAEgAn4hASACQgF8IQIMAAsLIAELWgECfQJAA0AgAEMAAAAAWw0BIAEhAgJAA0AgAkMAAAAAWw0BIAJDAAAAAF0NAyADIAKSIQMgAkMAAABAkyECDAALCyADIACVIQMgAEMAAIA/kyEADAALCyADCz0AA0ALA39BAAsDAxoLQQBEAAAAAAAAAABBAAMECxoaGgN/QQALAwMaC0EARAAAAAAAAAAAQQADBAsaGhoL", + "AGFzbQEAAAABNgpgAAF/YAABfmAAAX1gAAF8YAF/AX9gAX4BfmABfQF9YAF8AXxgBX59fH9/AGAFfn18f38BfAMUEwABAgMEBQYHCAkEBAQEBAQEBAQHswITDnR5cGUtbG9jYWwtaTMyAAAOdHlwZS1sb2NhbC1pNjQAAQ50eXBlLWxvY2FsLWYzMgACDnR5cGUtbG9jYWwtZjY0AAMOdHlwZS1wYXJhbS1pMzIABA50eXBlLXBhcmFtLWk2NAAFDnR5cGUtcGFyYW0tZjMyAAYOdHlwZS1wYXJhbS1mNjQABwp0eXBlLW1peGVkAAgEcmVhZAAJDmFzLWJsb2NrLXZhbHVlAAoNYXMtbG9vcC12YWx1ZQALC2FzLWJyLXZhbHVlAAwOYXMtYnJfaWYtdmFsdWUADRNhcy1icl9pZi12YWx1ZS1jb25kAA4RYXMtYnJfdGFibGUtdmFsdWUADw9hcy1yZXR1cm4tdmFsdWUAEAphcy1pZi10aGVuABEKYXMtaWYtZWxzZQASCo4CEwYBAX8gAAsGAQF+IAALBgEBfSAACwYBAXwgAAsEACAACwQAIAALBAAgAAsEACAACywDAX0CfgF8IABQGiABjBogApoaIANFGiAERRogBYwaIAZQGiAHUBogCJoaCz8DAX0CfgF8QwAAsEAhBUIGIQZEAAAAAAAAIEAhCCAAuiABuyACIAO4IAS3IAW7IAa6IAe6IAigoKCgoKCgoAsHAAJ/IAALCwcAA38gAAsLCQACfyAADAALCwsAAn8gAEEBDQALCwsAAn8gACAADQALCx0AAkACQAJAIAAOAgABAkEADwtBAQ8LQQIPC0EDCwUAIAAPCwwAIAAEfyAABUEACwsMACAABH9BAQUgAAsL", + "AGFzbQEAAAABJQdgAABgAX8AYAF+AGABfQBgAXwAYAV+fXx/fwBgBX59fH9/AX4DFBMAAAAAAQIDBAUGAQEBAQEBAQEBB7QCEw50eXBlLWxvY2FsLWkzMgAADnR5cGUtbG9jYWwtaTY0AAEOdHlwZS1sb2NhbC1mMzIAAg50eXBlLWxvY2FsLWY2NAADDnR5cGUtcGFyYW0taTMyAAQOdHlwZS1wYXJhbS1pNjQABQ50eXBlLXBhcmFtLWYzMgAGDnR5cGUtcGFyYW0tZjY0AAcKdHlwZS1taXhlZAAIBXdyaXRlAAkOYXMtYmxvY2stdmFsdWUACg1hcy1sb29wLXZhbHVlAAsLYXMtYnItdmFsdWUADA5hcy1icl9pZi12YWx1ZQANE2FzLWJyX2lmLXZhbHVlLWNvbmQADhFhcy1icl90YWJsZS12YWx1ZQAPD2FzLXJldHVybi12YWx1ZQAQCmFzLWlmLXRoZW4AEQphcy1pZi1lbHNlABIK0gITCAEBf0EAIQALCAEBfkIAIQALCwEBfUMAAAAAIQALDwEBfEQAAAAAAAAAACEACwYAQQohAAsGAEILIQALCQBDmpkxQSEACw0ARGZmZmZmZihAIQALQAMBfQJ+AXxCACEAQwAAAAAhAUQAAAAAAAAAACECQQAhA0EAIQRDAAAAACEFQgAhBkIAIQdEAAAAAAAAAAAhCAtPAwF9An4BfEOamZm+IQFBKCEDQXkhBEMAALBAIQVCBiEGRAAAAAAAACBAIQggALogAbsgAiADuCAEtyAFuyAGuiAHuiAIoKCgoKCgoKCwCwkAAkBBASEACwsJAANAQQMhAAsLCwACQEEJIQAMAAsLDQACQEEIIQBBAQ0ACwsNAAJAQQZBCSEADQALCw4AAkBBCiEAQQEOAAALCwcAQQchAA8LCwAgAARAQQMhAAsLDAAgAARABUEBIQALCw==", + "AGFzbQEAAAABWBBgA39/fwF/YAABf2AAAX5gAAF9YAABfGABfwF/YAF+AX5gAX0BfWABfAF8YAV+fXx/fwBgBX59fH9/AX5gBX59fH9/AXxgAABgAX8AYAJ/fwF/YAF+AX8DOjkBAgMEBQYHCAkKCwwFBQUFBQUFDQUFDQUFBQUFBQ4OBQAFBQUFBQUFDAUMBQUNDQ0NBwUFBQUFDwUEBQFwAQEBBQMBAAEGBgF/AUEACwfPBzcOdHlwZS1sb2NhbC1pMzIAAA50eXBlLWxvY2FsLWk2NAABDnR5cGUtbG9jYWwtZjMyAAIOdHlwZS1sb2NhbC1mNjQAAw50eXBlLXBhcmFtLWkzMgAEDnR5cGUtcGFyYW0taTY0AAUOdHlwZS1wYXJhbS1mMzIABg50eXBlLXBhcmFtLWY2NAAHCnR5cGUtbWl4ZWQACAV3cml0ZQAJBnJlc3VsdAAKDmFzLWJsb2NrLWZpcnN0AAwMYXMtYmxvY2stbWlkAA0NYXMtYmxvY2stbGFzdAAODWFzLWxvb3AtZmlyc3QADwthcy1sb29wLW1pZAAQDGFzLWxvb3AtbGFzdAARC2FzLWJyLXZhbHVlABINYXMtYnJfaWYtY29uZAATDmFzLWJyX2lmLXZhbHVlABQTYXMtYnJfaWYtdmFsdWUtY29uZAAVEWFzLWJyX3RhYmxlLWluZGV4ABYRYXMtYnJfdGFibGUtdmFsdWUAFxdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAYD2FzLXJldHVybi12YWx1ZQAZCmFzLWlmLWNvbmQAGgphcy1pZi10aGVuABsKYXMtaWYtZWxzZQAcD2FzLXNlbGVjdC1maXJzdAAdEGFzLXNlbGVjdC1zZWNvbmQAHg5hcy1zZWxlY3QtY29uZAAfDWFzLWNhbGwtZmlyc3QAIQthcy1jYWxsLW1pZAAiDGFzLWNhbGwtbGFzdAAjFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAJBRhcy1jYWxsX2luZGlyZWN0LW1pZAAlFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAmFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAJxJhcy1sb2NhbC5zZXQtdmFsdWUAKBJhcy1sb2NhbC50ZWUtdmFsdWUAKRNhcy1nbG9iYWwuc2V0LXZhbHVlACoPYXMtbG9hZC1hZGRyZXNzACsQYXMtbG9hZE4tYWRkcmVzcwAsEGFzLXN0b3JlLWFkZHJlc3MALQ5hcy1zdG9yZS12YWx1ZQAuEWFzLXN0b3JlTi1hZGRyZXNzAC8PYXMtc3RvcmVOLXZhbHVlADAQYXMtdW5hcnktb3BlcmFuZAAxDmFzLWJpbmFyeS1sZWZ0ADIPYXMtYmluYXJ5LXJpZ2h0ADMPYXMtdGVzdC1vcGVyYW5kADQPYXMtY29tcGFyZS1sZWZ0ADUQYXMtY29tcGFyZS1yaWdodAA2EmFzLWNvbnZlcnQtb3BlcmFuZAA3E2FzLW1lbW9yeS5ncm93LXNpemUAOAkHAQBBAAsBIAqDBzkIAQF/QQAiAAsIAQF+QgAiAAsLAQF9QwAAAAAiAAsPAQF8RAAAAAAAAAAAIgALBgBBCiIACwYAQgsiAAsJAEOamTFBIgALDQBEZmZmZmZmKEAiAAtSAwF9An4BfEIAIgBQGkMAAAAAIgGMGkQAAAAAAAAAACICmhpBACIDRRpBACIERRpDAAAAACIFjBpCACIGUBpCACIHUBpEAAAAAAAAAAAiCJoaC1UDAX0CfgF8Q5qZmb4iARpBKCIDGkF5IgQaQwAAsEAiBRpCBiIGGkQAAAAAAAAgQCIIGiAAuiABuyACIAO4IAS3IAW7IAa6IAe6IAigoKCgoKCgoLALTwMBfQJ+AXxCASIAukMAAABAIgG7RGZmZmZmZgpAIgJBBCIDuEEFIgS3QwAAsEAiBbtCBiIGukIAIge6RAAAAAAAACBAIgigoKCgoKCgoAsCAAsLAAJ/QQEiABALCwsNAAJ/EAtBASIAEAsLCw0AAn8QCxALQQEiAAsLCwADf0EDIgAQCwsLDQADfxALQQQiABALCwsNAAN/EAsQC0EFIgALCwsAAn9BCSIADAALCwsAAkBBASIADQALCxAAAn9BCCIAQQENABpBBwsLEAACf0EGQQkiAA0AGkEHCwsOAAJAQQAiAA4CAAAACwsSAAJ/QQoiAEEBDgIAAABBBwsLEQACf0EGQQsiAA4BAABBBwsLBwBBByIADwsOAEECIgAEf0EABUEBCwsOACAABH9BAyIABSAACwsOACAABH8gAAVBBCIACwsLAEEFIgAgACABGwsLACAAQQYiACABGwsLAEEAQQFBByIAGwsEAEF/CwwAQQwiAEECQQMQIAsMAEEBQQ0iAEEDECALDABBAUECQQ4iABAgCw8AQQEiAEECQQNBABEAAAsPAEEBQQIiAEEDQQARAAALDwBBAUECQQMiAEEAEQAACw8AQQFBAkEDQQAiABEAAAsKAQF/QQEiACEACwgAQQEiACIACwoBAX9BASIAJAALCQBBASIAKAIACwkAQQMiACwAAAsLAEEeIgBBBzYCAAsLAEECQQEiADYCAAsLAEEBIgBBBzoAAAsLAEECQQEiADsBAAsKAEPi8YB/IgCMCwkAQQMiAEEKagsJAEEKQQQiAGsLBwBBACIARQsJAEErIgBBCkwLCQBBCkEqIgBHCwcAQikiAKcLCABBKCIAQAAL", + "AGFzbQEAAAABIwdgAn9/AX9gAABgA39/fwF/YAABf2ABfwBgAX8Bf2ACf38AA1RTAQIDAwMDBAQEBQUFBQUDAwMDAwMDAwQEBAUFBQUFBQUFBQUFBQUFAgICAgIFBQUFBQUFBQUFBQUFBQUFBQADAwMDAwUFBQUFBQMDAwUFBQYGBgYEBQFwAQEBBQMBAAEGBgF/AUEACwfqC1ANYXMtZnVuYy1maXJzdAACC2FzLWZ1bmMtbWlkAAMMYXMtZnVuYy1sYXN0AAQSYXMtZnVuYy1ldmVyeXdoZXJlAAUNYXMtZHJvcC1maXJzdAAGDGFzLWRyb3AtbGFzdAAHEmFzLWRyb3AtZXZlcnl3aGVyZQAID2FzLXNlbGVjdC1maXJzdAAJDmFzLXNlbGVjdC1taWQxAAoOYXMtc2VsZWN0LW1pZDIACw5hcy1zZWxlY3QtbGFzdAAMFGFzLXNlbGVjdC1ldmVyeXdoZXJlAA0OYXMtYmxvY2stZmlyc3QADgxhcy1ibG9jay1taWQADw1hcy1ibG9jay1sYXN0ABATYXMtYmxvY2stZXZlcnl3aGVyZQARDWFzLWxvb3AtZmlyc3QAEgthcy1sb29wLW1pZAATDGFzLWxvb3AtbGFzdAAUEmFzLWxvb3AtZXZlcnl3aGVyZQAVD2FzLWlmLWNvbmRpdGlvbgAWCmFzLWlmLXRoZW4AFwphcy1pZi1lbHNlABgLYXMtYnItZmlyc3QAGQphcy1ici1sYXN0ABoQYXMtYnItZXZlcnl3aGVyZQAbDmFzLWJyX2lmLWZpcnN0ABwMYXMtYnJfaWYtbWlkAB0NYXMtYnJfaWYtbGFzdAAeE2FzLWJyX2lmLWV2ZXJ5d2hlcmUAHxFhcy1icl90YWJsZS1maXJzdAAgD2FzLWJyX3RhYmxlLW1pZAAhEGFzLWJyX3RhYmxlLWxhc3QAIhZhcy1icl90YWJsZS1ldmVyeXdoZXJlACMPYXMtcmV0dXJuLWZpcnN0ACQOYXMtcmV0dXJuLWxhc3QAJRRhcy1yZXR1cm4tZXZlcnl3aGVyZQAmDWFzLWNhbGwtZmlyc3QAJwxhcy1jYWxsLW1pZDEAKAxhcy1jYWxsLW1pZDIAKQxhcy1jYWxsLWxhc3QAKhJhcy1jYWxsLWV2ZXJ5d2hlcmUAKw5hcy11bmFyeS1maXJzdAAsDWFzLXVuYXJ5LWxhc3QALRNhcy11bmFyeS1ldmVyeXdoZXJlAC4PYXMtYmluYXJ5LWZpcnN0AC8NYXMtYmluYXJ5LW1pZAAwDmFzLWJpbmFyeS1sYXN0ADEUYXMtYmluYXJ5LWV2ZXJ5d2hlcmUAMg1hcy10ZXN0LWZpcnN0ADMMYXMtdGVzdC1sYXN0ADQSYXMtdGVzdC1ldmVyeXdoZXJlADUQYXMtY29tcGFyZS1maXJzdAA2DmFzLWNvbXBhcmUtbWlkADcPYXMtY29tcGFyZS1sYXN0ADgVYXMtY29tcGFyZS1ldmVyeXdoZXJlADkUYXMtbWVtb3J5Lmdyb3ctZmlyc3QAOhNhcy1tZW1vcnkuZ3Jvdy1sYXN0ADsZYXMtbWVtb3J5Lmdyb3ctZXZlcnl3aGVyZQA8FmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAPhVhcy1jYWxsX2luZGlyZWN0LW1pZDEAPxVhcy1jYWxsX2luZGlyZWN0LW1pZDIAQBVhcy1jYWxsX2luZGlyZWN0LWxhc3QAQRthcy1jYWxsX2luZGlyZWN0LWV2ZXJ5d2hlcmUAQhJhcy1sb2NhbC5zZXQtZmlyc3QAQxFhcy1sb2NhbC5zZXQtbGFzdABEF2FzLWxvY2FsLnNldC1ldmVyeXdoZXJlAEUSYXMtbG9jYWwudGVlLWZpcnN0AEYRYXMtbG9jYWwudGVlLWxhc3QARxdhcy1sb2NhbC50ZWUtZXZlcnl3aGVyZQBIE2FzLWdsb2JhbC5zZXQtZmlyc3QASRJhcy1nbG9iYWwuc2V0LWxhc3QAShhhcy1nbG9iYWwuc2V0LWV2ZXJ5d2hlcmUASw1hcy1sb2FkLWZpcnN0AEwMYXMtbG9hZC1sYXN0AE0SYXMtbG9hZC1ldmVyeXdoZXJlAE4OYXMtc3RvcmUtZmlyc3QATwxhcy1zdG9yZS1taWQAUA1hcy1zdG9yZS1sYXN0AFETYXMtc3RvcmUtZXZlcnl3aGVyZQBSCQcBAEEACwE9CqIHUwIACwoAIAAgASACa2oLBQABQQELBwAQAAFBAgsHABAAQQMBCwsAAQEQAAFBBAEBCwYAASAAGgsGACAAARoLCQABASAAAQEaCwoAASAAIAAgABsLCgAgAAEgACAAGwsKACAAIAABIAAbCwoAIAAgACAAARsLEAABIAABASAAAQEgAAEBGwsIAAJ/AUECCwsKAAJ/EAABQQILCwsAAn8BEABBAwELCw4AAn8BARAAAUEEAQELCwgAA38BQQILCwoAA38QAAFBAgsLCgADfxAAQQMBCwsOAAN/AQEQAAFBBAEBCwsKACAAAQRAEAALCwsAIAAEQAEFEAALCwsAIAAEQBAABQELCwoAAn8BIAAMAAsLCgACfyAAAQwACwsNAAJ/AQEgAAEBDAALCwwAAn8BIAAgAA0ACwsMAAJ/IAABIAANAAsLDAACfyAAIAABDQALCxEAAn8BASAAAQEgAAEBDQALCw4AAn8BIAAgAA4BAAALCw4AAn8gAAEgAA4BAAALCw4AAn8gACAAAQ4BAAALCxMAAn8BASAAAQEgAAEBDgEAAAsLBgABIAAPCwYAIAABDwsJAAEBIAABAQ8LCwABIAAgASACEAELCwAgAAEgASACEAELCwAgACABASACEAELCwAgACABIAIBEAELEgABASAAAQEgAQEBIAIBARABCwYAASAAaAsGACAAAWgLCQABASAAAQFoCwgAASAAIABqCwgAIAABIABqCwgAIAAgAAFqCwwAASAAAQEgAAEBagsGAAEgAEULBgAgAAFFCwkAAQEgAAEBRQsIAAEgACAARwsIACAAASAARwsIACAAIAABSQsMAAEgAAEBIAABAUwLBwABIABAAAsHACAAAUAACwoAAQEgAAEBQAALBAAgAAsPAAJ/AUEBQQJBABEAAAsLDwACf0EBAUECQQARAAALCw8AAn9BAUECAUEAEQAACwsPAAJ/QQFBAkEAAREAAAsLFgACfwEBQQEBAUECAQFBAAEBEQAACwsJAAFBAiEAIAALCQBBAgEhACAACwwAAQFBAgEBIQAgAAsHAAFBAiIACwcAQQIBIgALCgABAUECAQEiAAsJAAFBAiQAIwALCQBBAgEkACMACwwAAQFBAgEBJAAjAAsIAAEgACgCAAsIACAAASgCAAsLAAEBIAABASgCAAsKAAEgACABNgIACwoAIAABIAE2AgALCgAgACABATYCAAsPAAEBIAABASABAQE2AgAL", + "AGFzbQEAAAABIQdgA39/fwF/YAAAYAABf2AAAX5gAAF9YAABfGACf38BfwM+PQEBAQEBAgMEBQEFAgIBAgEBAQICAgICAQICAwICAwIGBgYGAgACAgICAgICAgICBAMCAgICBAIDAgICAgIEBQFwAQEBBQMBAAEGBgF/AUEACwf4BzsIdHlwZS1pMzIAAQh0eXBlLWk2NAACCHR5cGUtZjMyAAMIdHlwZS1mNjQABA50eXBlLWkzMi12YWx1ZQAFDnR5cGUtaTY0LXZhbHVlAAYOdHlwZS1mMzItdmFsdWUABw50eXBlLWY2NC12YWx1ZQAIB251bGxhcnkACQV1bmFyeQAKDWFzLWZ1bmMtZmlyc3QACwthcy1mdW5jLW1pZAAMDGFzLWZ1bmMtbGFzdAANDWFzLWZ1bmMtdmFsdWUADg5hcy1ibG9jay1maXJzdAAPDGFzLWJsb2NrLW1pZAAQDWFzLWJsb2NrLWxhc3QAEQ5hcy1ibG9jay12YWx1ZQASDWFzLWxvb3AtZmlyc3QAEwthcy1sb29wLW1pZAAUDGFzLWxvb3AtbGFzdAAVC2FzLWJyLXZhbHVlABYNYXMtYnJfaWYtY29uZAAXDmFzLWJyX2lmLXZhbHVlABgTYXMtYnJfaWYtdmFsdWUtY29uZAAZEWFzLWJyX3RhYmxlLWluZGV4ABoRYXMtYnJfdGFibGUtdmFsdWUAGxdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAcD2FzLXJldHVybi12YWx1ZQAdCmFzLWlmLWNvbmQAHgphcy1pZi10aGVuAB8KYXMtaWYtZWxzZQAgD2FzLXNlbGVjdC1maXJzdAAhEGFzLXNlbGVjdC1zZWNvbmQAIg5hcy1zZWxlY3QtY29uZAAjDWFzLWNhbGwtZmlyc3QAJQthcy1jYWxsLW1pZAAmDGFzLWNhbGwtbGFzdAAnFWFzLWNhbGxfaW5kaXJlY3QtZnVuYwAoFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAKRRhcy1jYWxsX2luZGlyZWN0LW1pZAAqFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAArEmFzLWxvY2FsLnNldC12YWx1ZQAsEmFzLWxvY2FsLnRlZS12YWx1ZQAtE2FzLWdsb2JhbC5zZXQtdmFsdWUALg9hcy1sb2FkLWFkZHJlc3MALxBhcy1sb2FkTi1hZGRyZXNzADAQYXMtc3RvcmUtYWRkcmVzcwAxDmFzLXN0b3JlLXZhbHVlADIRYXMtc3RvcmVOLWFkZHJlc3MAMw9hcy1zdG9yZU4tdmFsdWUANBBhcy11bmFyeS1vcGVyYW5kADUOYXMtYmluYXJ5LWxlZnQANg9hcy1iaW5hcnktcmlnaHQANw9hcy10ZXN0LW9wZXJhbmQAOA9hcy1jb21wYXJlLWxlZnQAORBhcy1jb21wYXJlLXJpZ2h0ADoSYXMtY29udmVydC1vcGVyYW5kADsTYXMtbWVtb3J5Lmdyb3ctc2l6ZQA8CQcBAEEACwEkCqkFPQIACwUAD2gaCwUAD3oaCwUAD4waCwUAD5oaCwkAAn9BAQ9oCwsJAAJ+QgIPegsLDAACfUMAAEBAD4wLCxAAAnxEAAAAAAAAEEAPmgsLAwAPCwwARAAAAAAAAAhADwsHAEEBD0ECCwkAEABBAg9BAwsGAAEQAA8LCAABEABBAw8LCAACQA8QAAsLCgACQBAADxAACwsJAAJAARAADwsLCwACfwEQAEECDwsLCgADf0EDD0ECCwsMAAN/EABBBA9BAgsLCwADfwEQAEEFDwsLCgACf0EJDwwACwsIAAJADw0ACwsPAAJ/QQgPQQENABpBBwsLDwACf0EGQQkPDQAaQQcLCw8AAkBCCQ8OAgAAAAtCfwsRAAJ/QQoPQQEOAgAAAEEHCwsQAAJ/QQZBCw8OAQAAQQcLCwYAQgcPDwsNAEECDwR/QQAFQQELCw0AIAAEf0EDDwUgAQsLDQAgAAR/IAEFQQQPCwsKAEEFDyAAIAEbCwoAIABBBg8gARsLCgBBAEEBQQcPGwsEAEF/CwsAQQwPQQJBAxAkCwsAQQFBDQ9BAxAkCwsAQQFBAkEODxAkCw4AQRQPQQFBAkEDEQAACw4AQQBBFQ9BAkEDEQAACw4AQQBBAUEWD0EDEQAACw4AQQBBAUECQRcPEQAACwsBAX1BEQ8hAEF/CwkBAX9BAQ8iAAsHAEEBDyQACwsAQ5qZ2T8PKgIACwgAQh4PMAAACxMAQR4PRAAAAAAAABxAOQMAQX8LDABBAkEfDzcDAEF/CwwAQSAPQQc6AABBfwsMAEECQSEPPQEAQX8LCQBDmplZQA+MCwgAQQMPQQpqCwgAQgpCLQ99CwYAQSwPRQsPAEErD0QAAAAAAAAkQGULCwBDAAAgQUEqD1wLBgBBKQ+nCwcAQSgPQAAL", + "AGFzbQEAAAABPQpgAn9/AX9gAABgA39/fwF/YAN+fn8BfmADfX1/AX1gA3x8fwF8YANwcH8BcGADb29/AW9gAX8Bf2ABfwADLy4BAgMEBQIDBAUGBwgICAgICAkICAgICAgACAgICQkICAgICQgICAgICAgICAgIBAkCcAEBAXABAQEFAwEAAQYGAX8BQQoLB/AFKwpzZWxlY3QtaTMyAAEKc2VsZWN0LWk2NAACCnNlbGVjdC1mMzIAAwpzZWxlY3QtZjY0AAQMc2VsZWN0LWkzMi10AAUMc2VsZWN0LWk2NC10AAYMc2VsZWN0LWYzMi10AAcMc2VsZWN0LWY2NC10AAgOc2VsZWN0LWZ1bmNyZWYACRBzZWxlY3QtZXh0ZXJucmVmAAoPYXMtc2VsZWN0LWZpcnN0AAsNYXMtc2VsZWN0LW1pZAAMDmFzLXNlbGVjdC1sYXN0AA0NYXMtbG9vcC1maXJzdAAOC2FzLWxvb3AtbWlkAA8MYXMtbG9vcC1sYXN0ABAPYXMtaWYtY29uZGl0aW9uABEKYXMtaWYtdGhlbgASCmFzLWlmLWVsc2UAEw5hcy1icl9pZi1maXJzdAAUDWFzLWJyX2lmLWxhc3QAFRFhcy1icl90YWJsZS1maXJzdAAWEGFzLWJyX3RhYmxlLWxhc3QAFxZhcy1jYWxsX2luZGlyZWN0LWZpcnN0ABkUYXMtY2FsbF9pbmRpcmVjdC1taWQAGhVhcy1jYWxsX2luZGlyZWN0LWxhc3QAGw5hcy1zdG9yZS1maXJzdAAcDWFzLXN0b3JlLWxhc3QAHRRhcy1tZW1vcnkuZ3Jvdy12YWx1ZQAeDWFzLWNhbGwtdmFsdWUAIA9hcy1yZXR1cm4tdmFsdWUAIQ9hcy1kcm9wLW9wZXJhbmQAIgthcy1ici12YWx1ZQAjEmFzLWxvY2FsLnNldC12YWx1ZQAkEmFzLWxvY2FsLnRlZS12YWx1ZQAlE2FzLWdsb2JhbC5zZXQtdmFsdWUAJg9hcy1sb2FkLW9wZXJhbmQAJxBhcy11bmFyeS1vcGVyYW5kACgRYXMtYmluYXJ5LW9wZXJhbmQAKQ9hcy10ZXN0LW9wZXJhbmQAKg9hcy1jb21wYXJlLWxlZnQAKxBhcy1jb21wYXJlLXJpZ2h0ACwSYXMtY29udmVydC1vcGVyYW5kAC0JDwIAQQALAQACAUEACwABGAqABS4CAAsJACAAIAEgAhsLCQAgACABIAIbCwkAIAAgASACGwsJACAAIAEgAhsLCwAgACABIAIcAX8LCwAgACABIAIcAX4LCwAgACABIAIcAX0LCwAgACABIAIcAXwLCwAgACABIAIcAXALCwAgACABIAIcAW8LDgBBAEEBIAAbQQJBAxsLDgBBAkEAQQEgABtBAxsLDgBBAkEDQQBBASAAGxsLEAADf0ECQQMgABsQABAACwsQAAN/EABBAkEDIAAbEAALCxAAA38QABAAQQJBAyAAGwsLDgBBAkEDIAAbBEAQAAsLEQBBAQR/QQJBAyAAGwVBBAsLEQBBAAR/QQIFQQJBAyAAGwsLEAACf0ECQQMgABtBBA0ACwsQAAJ/QQJBAkEDIAAbDQALCxIAAn9BAkEDIAAbQQIOAQAACwsSAAJ/QQJBAkEDIAAbDgEAAAsLBAAgAAsTAAJ/QQJBAyAAG0EBQQARAAELCxMAAn9BAUECQQMgABtBABEAAQsLEwACf0EBQQRBAkEDIAAbEQABCwsOAEEAQQQgABtBATYCAAsOAEEIQQFBAiAAGzYCAAsLAEEBQQIgABtAAAsEACAACwsAQQFBAiAAGxAfCwoAQQFBAiAAGw8LCgBBAUECIAAbGgsOAAJ/QQFBAiAAGwwACwsPAQF/QQFBAiAAGyEAIAALCwBBAUECIAAbIgALDQBBAUECIAAbJAAjAAsMAEEAQQQgABsoAgALCgBBAEEBIAAbRQsRAEEBQQIgABtBAUECIAAbbAsNAAJ/QQBBASAAG0ULCw8AAn9BAUECIAAbQQFMCwsPAAJ/QQFBAEEBIAAbRwsLDQACf0IBQgAgABunCws=", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAAEBAFwAAEKUAsEAAAbCwUAABsBCwUAABsbCwUAABsbCwYAABsbGwsGAAAcAX8LBgAAHAF/CwcAABwBfxsLCQAAHAF/HAF/CwcAABsRAQALCAAAGxEBABsL", + "AGFzbQEAAAABDQNgAX4BfmAAAX9gAAADCQgAAAAAAAECAQYGAX8BQQALB1cGCGZhYy1leHByAAAJZmFjLXN0YWNrAAENZmFjLXN0YWNrLXJhdwACCWZhYy1taXhlZAADDWZhYy1taXhlZC1yYXcABBBub3QtcXVpdGUtYS10cmVlAAcKjwIILwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILDQEBf0EBIwBqJAAjAAsFABAFGgsJABAFEAUQBmoL", + "AGFzbQEAAAABDANgAABgAX8AYAABfwMCAQAEBAFwAAEKtAMBsQMAAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBAEEAEQEACwNAQQBBABEBAAtBAARAQQBBABEBAAtBAARAQQBBABEBAAVBAEEAEQEACwJ/QQARAgALGgN/QQARAgALGkEABH9BABECAAVBABECAAsaAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBAEEAEQEACwNAQQBBABEBAAtBAARAQQBBABEBAAtBAARAQQBBABEBAAVBAEEAEQEACwJ/QQARAgALGgN/QQARAgALGkEABH9BABECAAVBABECAAsaAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALQQARAAAL", + "AGFzbQEAAAABDwNgAX8Bf2ABfgF+YAABfwMFBAABAAIHHgQEc3RtdAAABGV4cHIAAQNhcmcAAgZjb3JuZXIAAwreAQRXAQF/QeQAIQECQAJAAkACQAJAAkACQAJAAkACQCAADggAAQIDBAUGCAcLIAAPCwELC0EAIABrIQEMBQsMBAtB5QAhAQwDC0HlACEBC0HmACEBCwsgAQ8LTAEBfkLkACEBAn4CQAJAAkACQAJAAkACQAJAAkAgAKcOCAABAgMGBQQIBwsgAA8LAQsLQgAgAH0MBQtC5QAhAQsLCyABDAELQnsLDwsqAAJ/QQoCf0HkAAJ/QegHAn9BAiAAbEEDIABxDgMBAgMAC2oLagtqCw8LDAACQEEADgAAC0EBCw==", + "AGFzbQEAAAABIAdgA39/fwBgAABgAAF/YAABfmAAAX1gAAF8YAJ/fwF/Az08AQACAwQFAgIBAgICAQICAgIBAgIBAgIBAgICAgMCBgYGBgYCAQEBAQEBAQEEBAQDAQEBAQQCAwICAgICBAUBcAEBAQUDAQABBgkBfQFDAAAAAAsHjAg6CHR5cGUtaTMyAAIIdHlwZS1pNjQAAwh0eXBlLWYzMgAECHR5cGUtZjY0AAUNYXMtZnVuYy1maXJzdAAGC2FzLWZ1bmMtbWlkAAcMYXMtZnVuYy1sYXN0AAgNYXMtZnVuYy12YWx1ZQAJDmFzLWJsb2NrLWZpcnN0AAoMYXMtYmxvY2stbWlkAAsNYXMtYmxvY2stbGFzdAAMDmFzLWJsb2NrLXZhbHVlAA0OYXMtYmxvY2stYnJva2UADg1hcy1sb29wLWZpcnN0AA8LYXMtbG9vcC1taWQAEAxhcy1sb29wLWxhc3QAEQ1hcy1sb29wLWJyb2tlABILYXMtYnItdmFsdWUAEw1hcy1icl9pZi1jb25kABQOYXMtYnJfaWYtdmFsdWUAFRNhcy1icl9pZi12YWx1ZS1jb25kABYRYXMtYnJfdGFibGUtaW5kZXgAFxFhcy1icl90YWJsZS12YWx1ZQAYE2FzLWJyX3RhYmxlLXZhbHVlLTIAGRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAaG2FzLWJyX3RhYmxlLXZhbHVlLWFuZC1pbmRleAAbD2FzLXJldHVybi12YWx1ZQAcCmFzLWlmLWNvbmQAHQphcy1pZi10aGVuAB4KYXMtaWYtZWxzZQAfEmFzLWlmLXRoZW4tbm8tZWxzZQAgD2FzLXNlbGVjdC1maXJzdAAhEGFzLXNlbGVjdC1zZWNvbmQAIg5hcy1zZWxlY3QtY29uZAAjDWFzLWNhbGwtZmlyc3QAJAthcy1jYWxsLW1pZAAlDGFzLWNhbGwtbGFzdAAmFWFzLWNhbGxfaW5kaXJlY3QtZnVuYwAnFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAKBRhcy1jYWxsX2luZGlyZWN0LW1pZAApFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAqEmFzLWxvY2FsLnNldC12YWx1ZQArEmFzLWxvY2FsLnRlZS12YWx1ZQAsE2FzLWdsb2JhbC5zZXQtdmFsdWUALQ9hcy1sb2FkLWFkZHJlc3MALhBhcy1sb2FkTi1hZGRyZXNzAC8QYXMtc3RvcmUtYWRkcmVzcwAwDmFzLXN0b3JlLXZhbHVlADERYXMtc3RvcmVOLWFkZHJlc3MAMg9hcy1zdG9yZU4tdmFsdWUAMxBhcy11bmFyeS1vcGVyYW5kADQOYXMtYmluYXJ5LWxlZnQANQ9hcy1iaW5hcnktcmlnaHQANg9hcy10ZXN0LW9wZXJhbmQANw9hcy1jb21wYXJlLWxlZnQAOBBhcy1jb21wYXJlLXJpZ2h0ADkSYXMtY29udmVydC1vcGVyYW5kADoTYXMtbWVtb3J5Lmdyb3ctc2l6ZQA7CQcBAEEACwEBCrUEPAIACwIACwMAAAsDAAALAwAACwMAAAsFAABBfwsHABAAAEF/CwUAEAAACwUAEAAACwgAAn8AQQILCwoAAn8QAABBAgsLCQACQAEQAAALCwkAAn8BEAAACwsMAAJ/EABBAQwAAAsLCAADfwBBAgsLCgADfxAAAEECCwsJAANAARAAAAsLDwACfwN/EABBAQwBAAsLCwgAAn8ADAALCwgAAkAADQALCw0AAn8AQQENABpBBwsLDQACf0EGAA0AGkEHCwsLAAJAAA4CAAAACwsPAAJ/AEEBDgIAAABBBwsLDwACfwJ/AEEBDgEAAQsLCw4AAn9BBgAOAQAAQQcLCwwAAn8ADgEAAEEICwsEAAAPCwsAAAR/QQAFQQELCwsAIAAEfwAFIAELCwsAIAAEfyABBQALCwoAIAAEQAALIAELCAAAIAAgARsLCAAgAAAgARsLCABBAEEBABsLCQAAQQJBAxABCwkAQQEAQQMQAQsJAEEBQQIAEAELDAAAQQFBAkEDEQAACwwAQQAAQQJBAxEAAAsMAEEAQQEAQQMRAAALDABBAEEBQQIAEQAACwcBAX0AIQALBwEBfQAiAAsFAAAkAAsGAAAqAgALBgAAMAAACw8AAEQAAAAAAAAcQDkDAAsIAEECADcDAAsIAABBBzoAAAsIAEECAD0BAAsEAACMCwYAAEEKagsGAEIKAH0LBAAARQsNAABEAAAAAAAAJEBlCwkAQwAAIEEAXAsEAACnCwUAAEAACw==", + "AGFzbQEAAAABCAJgAABgAAF/AzIxAAABAAEAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQeUCjEaZnVuYy11bndpbmQtYnktdW5yZWFjaGFibGUAABFmdW5jLXVud2luZC1ieS1icgABF2Z1bmMtdW53aW5kLWJ5LWJyLXZhbHVlAAIUZnVuYy11bndpbmQtYnktYnJfaWYAAxpmdW5jLXVud2luZC1ieS1icl9pZi12YWx1ZQAEF2Z1bmMtdW53aW5kLWJ5LWJyX3RhYmxlAAUdZnVuYy11bndpbmQtYnktYnJfdGFibGUtdmFsdWUABhVmdW5jLXVud2luZC1ieS1yZXR1cm4ABxtibG9jay11bndpbmQtYnktdW5yZWFjaGFibGUACBJibG9jay11bndpbmQtYnktYnIACRhibG9jay11bndpbmQtYnktYnItdmFsdWUAChVibG9jay11bndpbmQtYnktYnJfaWYACxtibG9jay11bndpbmQtYnktYnJfaWYtdmFsdWUADBhibG9jay11bndpbmQtYnktYnJfdGFibGUADR5ibG9jay11bndpbmQtYnktYnJfdGFibGUtdmFsdWUADhZibG9jay11bndpbmQtYnktcmV0dXJuAA8iYmxvY2stbmVzdGVkLXVud2luZC1ieS11bnJlYWNoYWJsZQAQGWJsb2NrLW5lc3RlZC11bndpbmQtYnktYnIAER9ibG9jay1uZXN0ZWQtdW53aW5kLWJ5LWJyLXZhbHVlABIcYmxvY2stbmVzdGVkLXVud2luZC1ieS1icl9pZgATImJsb2NrLW5lc3RlZC11bndpbmQtYnktYnJfaWYtdmFsdWUAFB9ibG9jay1uZXN0ZWQtdW53aW5kLWJ5LWJyX3RhYmxlABUlYmxvY2stbmVzdGVkLXVud2luZC1ieS1icl90YWJsZS12YWx1ZQAWHWJsb2NrLW5lc3RlZC11bndpbmQtYnktcmV0dXJuABcXdW5hcnktYWZ0ZXItdW5yZWFjaGFibGUAGA51bmFyeS1hZnRlci1icgAZEXVuYXJ5LWFmdGVyLWJyX2lmABoUdW5hcnktYWZ0ZXItYnJfdGFibGUAGxJ1bmFyeS1hZnRlci1yZXR1cm4AHBhiaW5hcnktYWZ0ZXItdW5yZWFjaGFibGUAHQ9iaW5hcnktYWZ0ZXItYnIAHhJiaW5hcnktYWZ0ZXItYnJfaWYAHxViaW5hcnktYWZ0ZXItYnJfdGFibGUAIBNiaW5hcnktYWZ0ZXItcmV0dXJuACEYc2VsZWN0LWFmdGVyLXVucmVhY2hhYmxlACIPc2VsZWN0LWFmdGVyLWJyACMSc2VsZWN0LWFmdGVyLWJyX2lmACQVc2VsZWN0LWFmdGVyLWJyX3RhYmxlACUTc2VsZWN0LWFmdGVyLXJldHVybgAmHWJsb2NrLXZhbHVlLWFmdGVyLXVucmVhY2hhYmxlACcUYmxvY2stdmFsdWUtYWZ0ZXItYnIAKBdibG9jay12YWx1ZS1hZnRlci1icl9pZgApGmJsb2NrLXZhbHVlLWFmdGVyLWJyX3RhYmxlACoYYmxvY2stdmFsdWUtYWZ0ZXItcmV0dXJuACscbG9vcC12YWx1ZS1hZnRlci11bnJlYWNoYWJsZQAsE2xvb3AtdmFsdWUtYWZ0ZXItYnIALRZsb29wLXZhbHVlLWFmdGVyLWJyX2lmAC4ZbG9vcC12YWx1ZS1hZnRlci1icl90YWJsZQAvF2xvb3AtdmFsdWUtYWZ0ZXItcmV0dXJuADAKvAYxBwBBA0IBAAsIAEEDQgEMAAsKAEEDQgFBCQwACwwAQQNCAUEBDQAaGgsOAEEDQgFBCUEBDQAaGgsLAEEDQgFBAA4AAAsNAEEDQgFBCUEADgAACwkAQQNCAUEJDwsKAAJAQQNCAQALCw0AAkBBA0IBDAALQQkLDQACf0EDQgFBCQwACwsRAAJAQQNCAUEBDQAaGgtBCQsRAAJ/QQNCAUEJQQENABoaCwsQAAJAQQNCAUEADgAAC0EJCxAAAn9BA0IBQQlBAA4AAAsLDAACf0EDQgFBCQ8LCw0AAn9BAwJAQgEACwsLEQACQEEDAkBCAQwBCxoLQQkLEAACf0EDAkBCAUEJDAELCwsUAAJAQQMCQEIBQQENARoLGgtBCQsUAAJ/QQMCQEIBQQlBAQ0BGhoLCwsUAAJAQQMCQEIBQQEOAAELGgtBCQsTAAJ/QQMCQEIBQQlBAQ4AAQsLCw8AAn9BAwJAQgFBCQ8LCwsJAEMAAAAAAFALDwACf0MAAAAAQQkMAFALCw8AAn9CAEEJQQENABpQCwsTAAJ/QwAAAABBCUEADgEAAFALCwsAQwAAAABBCQ9QCxIAQwAAAABEAAAAAAAA8D8AUQsYAAJ/QwAAAABEAAAAAAAA8D9BCQwAUQsLEQACf0IAQgFBCUEBDQAaUQsLGwACf0MAAAAARAAAAAAAAPA/QQlBAA4AAFELCxQAQwAAAABEAAAAAAAA8D9BCQ9RCxQAQwAAAABEAAAAAAAA8D9CAAAbCxoAAn9DAAAAAEQAAAAAAADwP0IAQQkMABsLCxMAAn9BAEEBQQBBCUEBDQAaGwsLHQACf0MAAAAARAAAAAAAAPA/QgBBCUEADgAAGwsLFgBDAAAAAEQAAAAAAADwP0IBQQkPGwsLAAJ/QwAAAAAACwsOAAJ/QwAAAABBCQwACwsOAAJ/QQBBCUEBDQAaCwsSAAJ/QwAAAABBCUEADgEAAAsLDQACf0MAAAAAQQkPCwsLAAN/QwAAAAAACwsRAAJ/A39DAAAAAEEJDAELCwsRAAJ/A39BAEEJQQENARoLCwsVAAJ/A39DAAAAAEEJQQAOAQEBCwsLDQADf0MAAAAAQQkPCws=", + "AGFzbQEAAAABQA1gAn9/AX9gAn5+AX9gAn19AX9gAnx8AX9gAABgAAF/YAABfmAAAX1gAAF8YAJ/fwBgAn5+AGACfX0AYAJ8fAADhAGCAQAAAQECAgMDBAQFBQUFBQUGBgYFBQcHBwUFCAgIBQUJCgsMBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEBQFwAQgIBQMBAAEHqghfB2kzMl9hZGQAIwdpMzJfc3ViACQHaTMyX211bAAlCWkzMl9kaXZfcwAmCWkzMl9kaXZfdQAnCWkzMl9yZW1fcwAoCWkzMl9yZW1fdQApB2kzMl9hbmQAKgZpMzJfb3IAKwdpMzJfeG9yACwHaTMyX3NobAAtCWkzMl9zaHJfdQAuCWkzMl9zaHJfcwAvBmkzMl9lcQAwBmkzMl9uZQAxCGkzMl9sdF9zADIIaTMyX2xlX3MAMwhpMzJfbHRfdQA0CGkzMl9sZV91ADUIaTMyX2d0X3MANghpMzJfZ2VfcwA3CGkzMl9ndF91ADgIaTMyX2dlX3UAOQlpMzJfc3RvcmUAOgppMzJfc3RvcmU4ADsLaTMyX3N0b3JlMTYAPAhpMzJfY2FsbAA9EWkzMl9jYWxsX2luZGlyZWN0AD4KaTMyX3NlbGVjdAA/B2k2NF9hZGQAQAdpNjRfc3ViAEEHaTY0X211bABCCWk2NF9kaXZfcwBDCWk2NF9kaXZfdQBECWk2NF9yZW1fcwBFCWk2NF9yZW1fdQBGB2k2NF9hbmQARwZpNjRfb3IASAdpNjRfeG9yAEkHaTY0X3NobABKCWk2NF9zaHJfdQBLCWk2NF9zaHJfcwBMBmk2NF9lcQBNBmk2NF9uZQBOCGk2NF9sdF9zAE8IaTY0X2xlX3MAUAhpNjRfbHRfdQBRCGk2NF9sZV91AFIIaTY0X2d0X3MAUwhpNjRfZ2VfcwBUCGk2NF9ndF91AFUIaTY0X2dlX3UAVglpNjRfc3RvcmUAVwppNjRfc3RvcmU4AFgLaTY0X3N0b3JlMTYAWQtpNjRfc3RvcmUzMgBaCGk2NF9jYWxsAFsRaTY0X2NhbGxfaW5kaXJlY3QAXAppNjRfc2VsZWN0AF0HZjMyX2FkZABeB2YzMl9zdWIAXwdmMzJfbXVsAGAHZjMyX2RpdgBhDGYzMl9jb3B5c2lnbgBiBmYzMl9lcQBjBmYzMl9uZQBkBmYzMl9sdABlBmYzMl9sZQBmBmYzMl9ndABnBmYzMl9nZQBoB2YzMl9taW4AaQdmMzJfbWF4AGoJZjMyX3N0b3JlAGsIZjMyX2NhbGwAbBFmMzJfY2FsbF9pbmRpcmVjdABtCmYzMl9zZWxlY3QAbgdmNjRfYWRkAG8HZjY0X3N1YgBwB2Y2NF9tdWwAcQdmNjRfZGl2AHIMZjY0X2NvcHlzaWduAHMGZjY0X2VxAHQGZjY0X25lAHUGZjY0X2x0AHYGZjY0X2xlAHcGZjY0X2d0AHgGZjY0X2dlAHkHZjY0X21pbgB6B2Y2NF9tYXgAewlmNjRfc3RvcmUAfAhmNjRfY2FsbAB9EWY2NF9jYWxsX2luZGlyZWN0AH4KZjY0X3NlbGVjdAB/BWJyX2lmAIABCGJyX3RhYmxlAIEBCQ4BAEEACwgAAQIDBAUGBwqqDYIBBABBfwsEAEF+CwQAQX8LBABBfgsEAEF/CwQAQX4LBABBfwsEAEF+CwkAQQhBADYCAAsnAEELQQotAAA6AABBCkEJLQAAOgAAQQlBCC0AADoAAEEIQX06AAALBwBBCCgCAAsNABAJQQhBAToAAEEACw0AEAlBCEECOgAAQQELDQAQCUEIQQM6AABBAQsNABAJQQhBBDoAAEEACw0AEAlBCEEFOgAAQQALDQAQCUEIQQE6AABCAAsNABAJQQhBAjoAAEIBCw0AEAlBCEEDOgAAQgELDQAQCUEIQQQ6AABBAgsNABAJQQhBBToAAEEACxAAEAlBCEEBOgAAQwAAAAALEAAQCUEIQQI6AABDAACAPwsQABAJQQhBAzoAAEMAAIA/Cw0AEAlBCEEEOgAAQQQLDQAQCUEIQQU6AABBAAsUABAJQQhBAToAAEQAAAAAAAAAAAsUABAJQQhBAjoAAEQAAAAAAADwPwsUABAJQQhBAzoAAEQAAAAAAADwPwsNABAJQQhBBDoAAEEGCw0AEAlBCEEFOgAAQQALAgALAgALAgALAgALDAAQCBALEAxqGhAKCwwAEAgQCxAMaxoQCgsMABAIEAsQDGwaEAoLDAAQCBALEAxtGhAKCwwAEAgQCxAMbhoQCgsMABAIEAsQDG8aEAoLDAAQCBALEAxwGhAKCwwAEAgQCxAMcRoQCgsMABAIEAsQDHIaEAoLDAAQCBALEAxzGhAKCwwAEAgQCxAMdBoQCgsMABAIEAsQDHYaEAoLDAAQCBALEAx1GhAKCwwAEAgQCxAMRhoQCgsMABAIEAsQDEcaEAoLDAAQCBALEAxIGhAKCwwAEAgQCxAMTBoQCgsMABAIEAsQDEkaEAoLDAAQCBALEAxNGhAKCwwAEAgQCxAMShoQCgsMABAIEAsQDE4aEAoLDAAQCBALEAxLGhAKCwwAEAgQCxAMTxoQCgsNABAIEAsQDDYCABAKCw0AEAgQCxAMOgAAEAoLDQAQCBALEAw7AQAQCgsMABAIEAsQDBAfEAoLEAAQCBALEAwQDhEAABoQCgsOABAIEAsQDBAPGxoQCgsMABAIEBAQEXwaEAoLDAAQCBAQEBF9GhAKCwwAEAgQEBARfhoQCgsMABAIEBAQEX8aEAoLDAAQCBAQEBGAGhAKCwwAEAgQEBARgRoQCgsMABAIEBAQEYIaEAoLDAAQCBAQEBGDGhAKCwwAEAgQEBARhBoQCgsMABAIEBAQEYUaEAoLDAAQCBAQEBGGGhAKCwwAEAgQEBARiBoQCgsMABAIEBAQEYcaEAoLDAAQCBAQEBFRGhAKCwwAEAgQEBARUhoQCgsMABAIEBAQEVMaEAoLDAAQCBAQEBFXGhAKCwwAEAgQEBARVBoQCgsMABAIEBAQEVgaEAoLDAAQCBAQEBFVGhAKCwwAEAgQEBARWRoQCgsMABAIEBAQEVYaEAoLDAAQCBAQEBFaGhAKCw0AEAgQCxARNwMAEAoLDQAQCBALEBE8AAAQCgsNABAIEAsQET0BABAKCw0AEAgQCxARPgIAEAoLDAAQCBAQEBEQIBAKCxAAEAgQEBAREBMRAQAaEAoLDgAQCBAQEBEQFBsaEAoLDAAQCBAVEBaSGhAKCwwAEAgQFRAWkxoQCgsMABAIEBUQFpQaEAoLDAAQCBAVEBaVGhAKCwwAEAgQFRAWmBoQCgsMABAIEBUQFlsaEAoLDAAQCBAVEBZcGhAKCwwAEAgQFRAWXRoQCgsMABAIEBUQFl8aEAoLDAAQCBAVEBZeGhAKCwwAEAgQFRAWYBoQCgsMABAIEBUQFpYaEAoLDAAQCBAVEBaXGhAKCw0AEAgQCxAWOAIAEAoLDAAQCBAVEBYQIRAKCxAAEAgQFRAWEBgRAgAaEAoLDgAQCBAVEBYQGRsaEAoLDAAQCBAaEBugGhAKCwwAEAgQGhAboRoQCgsMABAIEBoQG6IaEAoLDAAQCBAaEBujGhAKCwwAEAgQGhAbphoQCgsMABAIEBoQG2EaEAoLDAAQCBAaEBtiGhAKCwwAEAgQGhAbYxoQCgsMABAIEBoQG2UaEAoLDAAQCBAaEBtkGhAKCwwAEAgQGhAbZhoQCgsMABAIEBoQG6QaEAoLDAAQCBAaEBulGhAKCw0AEAgQCxAbOQMAEAoLDAAQCBAaEBsQIhAKCxAAEAgQGhAbEB0RAwAaEAoLDgAQCBAaEBsQHhsaEAoLEwACfxAIEAsQDEEAcQ0AGhAKCwsVAAJ/EAgCfxALEAwOAQEACxoQCgsL", + "AGFzbQEAAAABNw1gAn9/AX9gAAF/YAABfmAAAW9gAX8AYAF+AGABbwBgAAF9YAABfGABfQBgAXwAYAAAYAF/AX8CLwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdApnbG9iYWxfaTY0A34AAzMyAQIDAwECAQIEBQYHCAcICQoLAQEBAQEBAQEBAQEBAQABAQELCwEBDAEBCwEMDAEBAQEEBQFwAQEBBQMBAAEGVg1/AEF+C30AQwAAQMALfABEAAAAAAAAEMALfgBCewt/AUF0C30BQwAAUMELfAFEAAAAAAAALMALfgFCcQt/ACMAC34AIwELbwDQbwtvAdBvC3AA0HALB7EFLwVnZXQtYQAABWdldC1iAAEFZ2V0LXIAAgZnZXQtbXIAAwVnZXQteAAEBWdldC15AAUGZ2V0LXoxAAYGZ2V0LXoyAAcFc2V0LXgACAVzZXQteQAJBnNldC1tcgAKBWdldC0zAAsFZ2V0LTQADAVnZXQtNwANBWdldC04AA4Fc2V0LTcADwVzZXQtOAAQD2FzLXNlbGVjdC1maXJzdAASDWFzLXNlbGVjdC1taWQAEw5hcy1zZWxlY3QtbGFzdAAUDWFzLWxvb3AtZmlyc3QAFQthcy1sb29wLW1pZAAWDGFzLWxvb3AtbGFzdAAXD2FzLWlmLWNvbmRpdGlvbgAYCmFzLWlmLXRoZW4AGQphcy1pZi1lbHNlABoOYXMtYnJfaWYtZmlyc3QAGw1hcy1icl9pZi1sYXN0ABwRYXMtYnJfdGFibGUtZmlyc3QAHRBhcy1icl90YWJsZS1sYXN0AB4WYXMtY2FsbF9pbmRpcmVjdC1maXJzdAAgFGFzLWNhbGxfaW5kaXJlY3QtbWlkACEVYXMtY2FsbF9pbmRpcmVjdC1sYXN0ACIOYXMtc3RvcmUtZmlyc3QAIw1hcy1zdG9yZS1sYXN0ACQPYXMtbG9hZC1vcGVyYW5kACUUYXMtbWVtb3J5Lmdyb3ctdmFsdWUAJg1hcy1jYWxsLXZhbHVlACgPYXMtcmV0dXJuLXZhbHVlACkPYXMtZHJvcC1vcGVyYW5kACoLYXMtYnItdmFsdWUAKxJhcy1sb2NhbC5zZXQtdmFsdWUALBJhcy1sb2NhbC50ZWUtdmFsdWUALRNhcy1nbG9iYWwuc2V0LXZhbHVlAC4QYXMtdW5hcnktb3BlcmFuZAAvEWFzLWJpbmFyeS1vcGVyYW5kADASYXMtY29tcGFyZS1vcGVyYW5kADEJBwEAQQALAR8KsAMyBAAjAgsEACMFCwQAIwwLBAAjDQsEACMGCwQAIwkLBAAjCgsEACMLCwYAIAAkBgsGACAAJAkLBgAgACQNCwQAIwMLBAAjBAsEACMHCwQAIwgLBgAgACQHCwYAIAAkCAsCAAsJACMGQQJBAxsLCQBBAiMGQQMbCwkAQQJBAyMGGwsLAAN/IwYQERARCwsLAAN/EBEjBhARCwsLAAN/EBEQESMGCwsQACMGBH8QEUECBRARQQMLCwwAQQEEfyMGBUECCwsMAEEABH9BAgUjBgsLDgACfyMGQQINAEEDDwsLDgACf0ECIwYNAEEDDwsLDQACfyMGQQIOAQAACwsNAAJ/QQIjBg4BAAALCwQAIAALDgACfyMGQQJBABEAAAsLDgACf0ECIwZBABEAAAsLDgACf0ECQQAjBhEAAAsLCQAjBkEBNgIACwkAQQAjBjYCAAsHACMGKAIACwYAIwZAAAsEACAACwYAIwYQJwsFACMGDwsFACMGGgsJAAJ/IwYMAAsLCAAjBiEAIAALBgAjBiIACwgAIwYkBiMGCwUAIwZFCwcAIwYjBmwLBwAjAEEBSws=", + "AGFzbQEAAAAGCQF9AUMAAAAACwcFAQFhAwA=", + "AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AA==", + "AGFzbQEAAAAGBgF/AEEACw==", + "AGFzbQEAAAABCAJgAABgAAF/AwQDAAEABQQBAQEBBw0CA2luYwAAA2dldAABCAECCiMDDwBBAEEALQAAQQFqOgAACwgAQQAtAAAPCwgAEAAQABAACwsHAQBBAAsBQQ==", + "AGFzbQEAAAABCAJgAX8AYAAAAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQgBAQoIAQYAQQEQAAs=", + "AGFzbQEAAAABCAJgAX8AYAAAAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQgBAQoIAQYAQQIQAAs=", + "AGFzbQEAAAABBAFgAAACEgEIc3BlY3Rlc3QFcHJpbnQAAAgBAA==", + "AGFzbQEAAAABBAFgAAADAgEACAEACgUBAwAACw==", +]; +export const script = "[[\"file\",\"block.wast\"],[\"module\",3,0],[\"invoke\",353,0,\"empty\",[]],[\"invoke\",354,0,\"singular\",[]],[\"invoke\",355,0,\"multi\",[]],[\"invoke\",356,0,\"nested\",[]],[\"invoke\",357,0,\"deep\",[]],[\"invoke\",359,0,\"as-select-first\",[]],[\"invoke\",360,0,\"as-select-mid\",[]],[\"invoke\",361,0,\"as-select-last\",[]],[\"invoke\",363,0,\"as-loop-first\",[]],[\"invoke\",364,0,\"as-loop-mid\",[]],[\"invoke\",365,0,\"as-loop-last\",[]],[\"invoke\",367,0,\"as-if-condition\",[]],[\"invoke\",368,0,\"as-if-then\",[]],[\"invoke\",369,0,\"as-if-else\",[]],[\"invoke\",371,0,\"as-br_if-first\",[]],[\"invoke\",372,0,\"as-br_if-last\",[]],[\"invoke\",374,0,\"as-br_table-first\",[]],[\"invoke\",375,0,\"as-br_table-last\",[]],[\"invoke\",377,0,\"as-call_indirect-first\",[]],[\"invoke\",378,0,\"as-call_indirect-mid\",[]],[\"invoke\",379,0,\"as-call_indirect-last\",[]],[\"invoke\",381,0,\"as-store-first\",[]],[\"invoke\",382,0,\"as-store-last\",[]],[\"invoke\",384,0,\"as-memory.grow-value\",[]],[\"invoke\",385,0,\"as-call-value\",[]],[\"invoke\",386,0,\"as-return-value\",[]],[\"invoke\",387,0,\"as-drop-operand\",[]],[\"invoke\",388,0,\"as-br-value\",[]],[\"invoke\",389,0,\"as-local.set-value\",[]],[\"invoke\",390,0,\"as-local.tee-value\",[]],[\"invoke\",391,0,\"as-global.set-value\",[]],[\"invoke\",392,0,\"as-load-operand\",[]],[\"invoke\",394,0,\"as-unary-operand\",[]],[\"invoke\",395,0,\"as-binary-operand\",[]],[\"invoke\",396,0,\"as-test-operand\",[]],[\"invoke\",397,0,\"as-compare-operand\",[]],[\"invoke\",398,0,\"as-binary-operands\",[]],[\"invoke\",399,0,\"as-compare-operands\",[]],[\"invoke\",400,0,\"as-mixed-operands\",[]],[\"invoke\",402,0,\"break-bare\",[]],[\"invoke\",403,0,\"break-value\",[]],[\"invoke\",404,0,\"break-multi-value\",[]],[\"invoke\",407,0,\"break-repeated\",[]],[\"invoke\",408,0,\"break-inner\",[]],[\"invoke\",410,0,\"param\",[]],[\"invoke\",411,0,\"params\",[]],[\"invoke\",412,0,\"params-id\",[]],[\"invoke\",413,0,\"param-break\",[]],[\"invoke\",414,0,\"params-break\",[]],[\"invoke\",415,0,\"params-id-break\",[]],[\"invoke\",417,0,\"effects\",[]],[\"invoke\",419,0,\"type-use\",[]],[\"file\",\"br.wast\"],[\"module\",3,1],[\"invoke\",372,0,\"type-i32\",[]],[\"invoke\",373,0,\"type-i64\",[]],[\"invoke\",374,0,\"type-f32\",[]],[\"invoke\",375,0,\"type-f64\",[]],[\"invoke\",376,0,\"type-i32-i32\",[]],[\"invoke\",377,0,\"type-i64-i64\",[]],[\"invoke\",378,0,\"type-f32-f32\",[]],[\"invoke\",379,0,\"type-f64-f64\",[]],[\"invoke\",381,0,\"type-i32-value\",[]],[\"invoke\",382,0,\"type-i64-value\",[]],[\"invoke\",383,0,\"type-f32-value\",[]],[\"invoke\",384,0,\"type-f64-value\",[]],[\"invoke\",385,0,\"type-f64-f64-value\",[]],[\"invoke\",387,0,\"as-block-first\",[]],[\"invoke\",388,0,\"as-block-mid\",[]],[\"invoke\",389,0,\"as-block-last\",[]],[\"invoke\",390,0,\"as-block-value\",[]],[\"invoke\",392,0,\"as-loop-first\",[]],[\"invoke\",393,0,\"as-loop-mid\",[]],[\"invoke\",394,0,\"as-loop-last\",[]],[\"invoke\",396,0,\"as-br-value\",[]],[\"invoke\",398,0,\"as-br_if-cond\",[]],[\"invoke\",399,0,\"as-br_if-value\",[]],[\"invoke\",400,0,\"as-br_if-value-cond\",[]],[\"invoke\",402,0,\"as-br_table-index\",[]],[\"invoke\",403,0,\"as-br_table-value\",[]],[\"invoke\",404,0,\"as-br_table-value-index\",[]],[\"invoke\",406,0,\"as-return-value\",[]],[\"invoke\",407,0,\"as-return-values\",[]],[\"invoke\",409,0,\"as-if-cond\",[]],[\"invoke\",410,0,\"as-if-then\",[\"i32:1\",\"i32:6\"]],[\"invoke\",411,0,\"as-if-then\",[\"i32:0\",\"i32:6\"]],[\"invoke\",412,0,\"as-if-else\",[\"i32:0\",\"i32:6\"]],[\"invoke\",413,0,\"as-if-else\",[\"i32:1\",\"i32:6\"]],[\"invoke\",415,0,\"as-select-first\",[\"i32:0\",\"i32:6\"]],[\"invoke\",416,0,\"as-select-first\",[\"i32:1\",\"i32:6\"]],[\"invoke\",417,0,\"as-select-second\",[\"i32:0\",\"i32:6\"]],[\"invoke\",418,0,\"as-select-second\",[\"i32:1\",\"i32:6\"]],[\"invoke\",419,0,\"as-select-cond\",[]],[\"invoke\",420,0,\"as-select-all\",[]],[\"invoke\",422,0,\"as-call-first\",[]],[\"invoke\",423,0,\"as-call-mid\",[]],[\"invoke\",424,0,\"as-call-last\",[]],[\"invoke\",425,0,\"as-call-all\",[]],[\"invoke\",427,0,\"as-call_indirect-func\",[]],[\"invoke\",428,0,\"as-call_indirect-first\",[]],[\"invoke\",429,0,\"as-call_indirect-mid\",[]],[\"invoke\",430,0,\"as-call_indirect-last\",[]],[\"invoke\",431,0,\"as-call_indirect-all\",[]],[\"invoke\",433,0,\"as-local.set-value\",[]],[\"invoke\",434,0,\"as-local.tee-value\",[]],[\"invoke\",435,0,\"as-global.set-value\",[]],[\"invoke\",437,0,\"as-load-address\",[]],[\"invoke\",438,0,\"as-loadN-address\",[]],[\"invoke\",440,0,\"as-store-address\",[]],[\"invoke\",441,0,\"as-store-value\",[]],[\"invoke\",442,0,\"as-store-both\",[]],[\"invoke\",443,0,\"as-storeN-address\",[]],[\"invoke\",444,0,\"as-storeN-value\",[]],[\"invoke\",445,0,\"as-storeN-both\",[]],[\"invoke\",447,0,\"as-unary-operand\",[]],[\"invoke\",449,0,\"as-binary-left\",[]],[\"invoke\",450,0,\"as-binary-right\",[]],[\"invoke\",451,0,\"as-binary-both\",[]],[\"invoke\",453,0,\"as-test-operand\",[]],[\"invoke\",455,0,\"as-compare-left\",[]],[\"invoke\",456,0,\"as-compare-right\",[]],[\"invoke\",457,0,\"as-compare-both\",[]],[\"invoke\",459,0,\"as-convert-operand\",[]],[\"invoke\",461,0,\"as-memory.grow-size\",[]],[\"invoke\",463,0,\"nested-block-value\",[]],[\"invoke\",464,0,\"nested-br-value\",[]],[\"invoke\",465,0,\"nested-br_if-value\",[]],[\"invoke\",466,0,\"nested-br_if-value-cond\",[]],[\"invoke\",467,0,\"nested-br_table-value\",[]],[\"invoke\",468,0,\"nested-br_table-value-index\",[]],[\"file\",\"br_if.wast\"],[\"module\",3,2],[\"invoke\",372,0,\"type-i32\",[]],[\"invoke\",373,0,\"type-i64\",[]],[\"invoke\",374,0,\"type-f32\",[]],[\"invoke\",375,0,\"type-f64\",[]],[\"invoke\",377,0,\"type-i32-value\",[]],[\"invoke\",378,0,\"type-i64-value\",[]],[\"invoke\",379,0,\"type-f32-value\",[]],[\"invoke\",380,0,\"type-f64-value\",[]],[\"invoke\",382,0,\"as-block-first\",[\"i32:0\"]],[\"invoke\",383,0,\"as-block-first\",[\"i32:1\"]],[\"invoke\",384,0,\"as-block-mid\",[\"i32:0\"]],[\"invoke\",385,0,\"as-block-mid\",[\"i32:1\"]],[\"invoke\",386,0,\"as-block-last\",[\"i32:0\"]],[\"invoke\",387,0,\"as-block-last\",[\"i32:1\"]],[\"invoke\",389,0,\"as-block-first-value\",[\"i32:0\"]],[\"invoke\",390,0,\"as-block-first-value\",[\"i32:1\"]],[\"invoke\",391,0,\"as-block-mid-value\",[\"i32:0\"]],[\"invoke\",392,0,\"as-block-mid-value\",[\"i32:1\"]],[\"invoke\",393,0,\"as-block-last-value\",[\"i32:0\"]],[\"invoke\",394,0,\"as-block-last-value\",[\"i32:1\"]],[\"invoke\",396,0,\"as-loop-first\",[\"i32:0\"]],[\"invoke\",397,0,\"as-loop-first\",[\"i32:1\"]],[\"invoke\",398,0,\"as-loop-mid\",[\"i32:0\"]],[\"invoke\",399,0,\"as-loop-mid\",[\"i32:1\"]],[\"invoke\",400,0,\"as-loop-last\",[\"i32:0\"]],[\"invoke\",401,0,\"as-loop-last\",[\"i32:1\"]],[\"invoke\",403,0,\"as-br-value\",[]],[\"invoke\",405,0,\"as-br_if-cond\",[]],[\"invoke\",406,0,\"as-br_if-value\",[]],[\"invoke\",407,0,\"as-br_if-value-cond\",[\"i32:0\"]],[\"invoke\",408,0,\"as-br_if-value-cond\",[\"i32:1\"]],[\"invoke\",410,0,\"as-br_table-index\",[]],[\"invoke\",411,0,\"as-br_table-value\",[]],[\"invoke\",412,0,\"as-br_table-value-index\",[]],[\"invoke\",414,0,\"as-return-value\",[]],[\"invoke\",416,0,\"as-if-cond\",[\"i32:0\"]],[\"invoke\",417,0,\"as-if-cond\",[\"i32:1\"]],[\"invoke\",418,0,\"as-if-then\",[\"i32:0\",\"i32:0\"]],[\"invoke\",419,0,\"as-if-then\",[\"i32:4\",\"i32:0\"]],[\"invoke\",420,0,\"as-if-then\",[\"i32:0\",\"i32:1\"]],[\"invoke\",421,0,\"as-if-then\",[\"i32:4\",\"i32:1\"]],[\"invoke\",422,0,\"as-if-else\",[\"i32:0\",\"i32:0\"]],[\"invoke\",423,0,\"as-if-else\",[\"i32:3\",\"i32:0\"]],[\"invoke\",424,0,\"as-if-else\",[\"i32:0\",\"i32:1\"]],[\"invoke\",425,0,\"as-if-else\",[\"i32:3\",\"i32:1\"]],[\"invoke\",427,0,\"as-select-first\",[\"i32:0\"]],[\"invoke\",428,0,\"as-select-first\",[\"i32:1\"]],[\"invoke\",429,0,\"as-select-second\",[\"i32:0\"]],[\"invoke\",430,0,\"as-select-second\",[\"i32:1\"]],[\"invoke\",431,0,\"as-select-cond\",[]],[\"invoke\",433,0,\"as-call-first\",[]],[\"invoke\",434,0,\"as-call-mid\",[]],[\"invoke\",435,0,\"as-call-last\",[]],[\"invoke\",437,0,\"as-call_indirect-func\",[]],[\"invoke\",438,0,\"as-call_indirect-first\",[]],[\"invoke\",439,0,\"as-call_indirect-mid\",[]],[\"invoke\",440,0,\"as-call_indirect-last\",[]],[\"invoke\",442,0,\"as-local.set-value\",[\"i32:0\"]],[\"invoke\",443,0,\"as-local.set-value\",[\"i32:1\"]],[\"invoke\",445,0,\"as-local.tee-value\",[\"i32:0\"]],[\"invoke\",446,0,\"as-local.tee-value\",[\"i32:1\"]],[\"invoke\",448,0,\"as-global.set-value\",[\"i32:0\"]],[\"invoke\",449,0,\"as-global.set-value\",[\"i32:1\"]],[\"invoke\",451,0,\"as-load-address\",[]],[\"invoke\",452,0,\"as-loadN-address\",[]],[\"invoke\",454,0,\"as-store-address\",[]],[\"invoke\",455,0,\"as-store-value\",[]],[\"invoke\",456,0,\"as-storeN-address\",[]],[\"invoke\",457,0,\"as-storeN-value\",[]],[\"invoke\",459,0,\"as-unary-operand\",[]],[\"invoke\",460,0,\"as-binary-left\",[]],[\"invoke\",461,0,\"as-binary-right\",[]],[\"invoke\",462,0,\"as-test-operand\",[]],[\"invoke\",463,0,\"as-compare-left\",[]],[\"invoke\",464,0,\"as-compare-right\",[]],[\"invoke\",465,0,\"as-memory.grow-size\",[]],[\"invoke\",467,0,\"nested-block-value\",[\"i32:0\"]],[\"invoke\",468,0,\"nested-block-value\",[\"i32:1\"]],[\"invoke\",469,0,\"nested-br-value\",[\"i32:0\"]],[\"invoke\",470,0,\"nested-br-value\",[\"i32:1\"]],[\"invoke\",471,0,\"nested-br_if-value\",[\"i32:0\"]],[\"invoke\",472,0,\"nested-br_if-value\",[\"i32:1\"]],[\"invoke\",473,0,\"nested-br_if-value-cond\",[\"i32:0\"]],[\"invoke\",474,0,\"nested-br_if-value-cond\",[\"i32:1\"]],[\"invoke\",475,0,\"nested-br_table-value\",[\"i32:0\"]],[\"invoke\",476,0,\"nested-br_table-value\",[\"i32:1\"]],[\"invoke\",477,0,\"nested-br_table-value-index\",[\"i32:0\"]],[\"invoke\",478,0,\"nested-br_table-value-index\",[\"i32:1\"]],[\"file\",\"br_table.wast\"],[\"module\",3,3],[\"invoke\",1007,0,\"type-i32\",[]],[\"invoke\",1008,0,\"type-i64\",[]],[\"invoke\",1009,0,\"type-f32\",[]],[\"invoke\",1010,0,\"type-f64\",[]],[\"invoke\",1012,0,\"type-i32-value\",[]],[\"invoke\",1013,0,\"type-i64-value\",[]],[\"invoke\",1014,0,\"type-f32-value\",[]],[\"invoke\",1015,0,\"type-f64-value\",[]],[\"invoke\",1017,0,\"empty\",[\"i32:0\"]],[\"invoke\",1018,0,\"empty\",[\"i32:1\"]],[\"invoke\",1019,0,\"empty\",[\"i32:11\"]],[\"invoke\",1020,0,\"empty\",[\"i32:4294967295\"]],[\"invoke\",1021,0,\"empty\",[\"i32:4294967196\"]],[\"invoke\",1022,0,\"empty\",[\"i32:4294967295\"]],[\"invoke\",1024,0,\"empty-value\",[\"i32:0\"]],[\"invoke\",1025,0,\"empty-value\",[\"i32:1\"]],[\"invoke\",1026,0,\"empty-value\",[\"i32:11\"]],[\"invoke\",1027,0,\"empty-value\",[\"i32:4294967295\"]],[\"invoke\",1028,0,\"empty-value\",[\"i32:4294967196\"]],[\"invoke\",1029,0,\"empty-value\",[\"i32:4294967295\"]],[\"invoke\",1031,0,\"singleton\",[\"i32:0\"]],[\"invoke\",1032,0,\"singleton\",[\"i32:1\"]],[\"invoke\",1033,0,\"singleton\",[\"i32:11\"]],[\"invoke\",1034,0,\"singleton\",[\"i32:4294967295\"]],[\"invoke\",1035,0,\"singleton\",[\"i32:4294967196\"]],[\"invoke\",1036,0,\"singleton\",[\"i32:4294967295\"]],[\"invoke\",1038,0,\"singleton-value\",[\"i32:0\"]],[\"invoke\",1039,0,\"singleton-value\",[\"i32:1\"]],[\"invoke\",1040,0,\"singleton-value\",[\"i32:11\"]],[\"invoke\",1041,0,\"singleton-value\",[\"i32:4294967295\"]],[\"invoke\",1042,0,\"singleton-value\",[\"i32:4294967196\"]],[\"invoke\",1043,0,\"singleton-value\",[\"i32:4294967295\"]],[\"invoke\",1045,0,\"multiple\",[\"i32:0\"]],[\"invoke\",1046,0,\"multiple\",[\"i32:1\"]],[\"invoke\",1047,0,\"multiple\",[\"i32:2\"]],[\"invoke\",1048,0,\"multiple\",[\"i32:3\"]],[\"invoke\",1049,0,\"multiple\",[\"i32:4\"]],[\"invoke\",1050,0,\"multiple\",[\"i32:5\"]],[\"invoke\",1051,0,\"multiple\",[\"i32:6\"]],[\"invoke\",1052,0,\"multiple\",[\"i32:10\"]],[\"invoke\",1053,0,\"multiple\",[\"i32:4294967295\"]],[\"invoke\",1054,0,\"multiple\",[\"i32:4294967295\"]],[\"invoke\",1056,0,\"multiple-value\",[\"i32:0\"]],[\"invoke\",1057,0,\"multiple-value\",[\"i32:1\"]],[\"invoke\",1058,0,\"multiple-value\",[\"i32:2\"]],[\"invoke\",1059,0,\"multiple-value\",[\"i32:3\"]],[\"invoke\",1060,0,\"multiple-value\",[\"i32:4\"]],[\"invoke\",1061,0,\"multiple-value\",[\"i32:5\"]],[\"invoke\",1062,0,\"multiple-value\",[\"i32:6\"]],[\"invoke\",1063,0,\"multiple-value\",[\"i32:10\"]],[\"invoke\",1064,0,\"multiple-value\",[\"i32:4294967295\"]],[\"invoke\",1065,0,\"multiple-value\",[\"i32:4294967295\"]],[\"invoke\",1067,0,\"large\",[\"i32:0\"]],[\"invoke\",1068,0,\"large\",[\"i32:1\"]],[\"invoke\",1069,0,\"large\",[\"i32:100\"]],[\"invoke\",1070,0,\"large\",[\"i32:101\"]],[\"invoke\",1071,0,\"large\",[\"i32:10000\"]],[\"invoke\",1072,0,\"large\",[\"i32:10001\"]],[\"invoke\",1073,0,\"large\",[\"i32:1000000\"]],[\"invoke\",1074,0,\"large\",[\"i32:1000001\"]],[\"invoke\",1076,0,\"as-block-first\",[]],[\"invoke\",1077,0,\"as-block-mid\",[]],[\"invoke\",1078,0,\"as-block-last\",[]],[\"invoke\",1079,0,\"as-block-value\",[]],[\"invoke\",1081,0,\"as-loop-first\",[]],[\"invoke\",1082,0,\"as-loop-mid\",[]],[\"invoke\",1083,0,\"as-loop-last\",[]],[\"invoke\",1085,0,\"as-br-value\",[]],[\"invoke\",1087,0,\"as-br_if-cond\",[]],[\"invoke\",1088,0,\"as-br_if-value\",[]],[\"invoke\",1089,0,\"as-br_if-value-cond\",[]],[\"invoke\",1091,0,\"as-br_table-index\",[]],[\"invoke\",1092,0,\"as-br_table-value\",[]],[\"invoke\",1093,0,\"as-br_table-value-index\",[]],[\"invoke\",1095,0,\"as-return-value\",[]],[\"invoke\",1097,0,\"as-if-cond\",[]],[\"invoke\",1098,0,\"as-if-then\",[\"i32:1\",\"i32:6\"]],[\"invoke\",1099,0,\"as-if-then\",[\"i32:0\",\"i32:6\"]],[\"invoke\",1100,0,\"as-if-else\",[\"i32:0\",\"i32:6\"]],[\"invoke\",1101,0,\"as-if-else\",[\"i32:1\",\"i32:6\"]],[\"invoke\",1103,0,\"as-select-first\",[\"i32:0\",\"i32:6\"]],[\"invoke\",1104,0,\"as-select-first\",[\"i32:1\",\"i32:6\"]],[\"invoke\",1105,0,\"as-select-second\",[\"i32:0\",\"i32:6\"]],[\"invoke\",1106,0,\"as-select-second\",[\"i32:1\",\"i32:6\"]],[\"invoke\",1107,0,\"as-select-cond\",[]],[\"invoke\",1109,0,\"as-call-first\",[]],[\"invoke\",1110,0,\"as-call-mid\",[]],[\"invoke\",1111,0,\"as-call-last\",[]],[\"invoke\",1113,0,\"as-call_indirect-first\",[]],[\"invoke\",1114,0,\"as-call_indirect-mid\",[]],[\"invoke\",1115,0,\"as-call_indirect-last\",[]],[\"invoke\",1116,0,\"as-call_indirect-func\",[]],[\"invoke\",1118,0,\"as-local.set-value\",[]],[\"invoke\",1119,0,\"as-local.tee-value\",[]],[\"invoke\",1120,0,\"as-global.set-value\",[]],[\"invoke\",1122,0,\"as-load-address\",[]],[\"invoke\",1123,0,\"as-loadN-address\",[]],[\"invoke\",1125,0,\"as-store-address\",[]],[\"invoke\",1126,0,\"as-store-value\",[]],[\"invoke\",1127,0,\"as-storeN-address\",[]],[\"invoke\",1128,0,\"as-storeN-value\",[]],[\"invoke\",1130,0,\"as-unary-operand\",[]],[\"invoke\",1132,0,\"as-binary-left\",[]],[\"invoke\",1133,0,\"as-binary-right\",[]],[\"invoke\",1135,0,\"as-test-operand\",[]],[\"invoke\",1137,0,\"as-compare-left\",[]],[\"invoke\",1138,0,\"as-compare-right\",[]],[\"invoke\",1140,0,\"as-convert-operand\",[]],[\"invoke\",1142,0,\"as-memory.grow-size\",[]],[\"invoke\",1144,0,\"nested-block-value\",[\"i32:0\"]],[\"invoke\",1145,0,\"nested-block-value\",[\"i32:1\"]],[\"invoke\",1146,0,\"nested-block-value\",[\"i32:2\"]],[\"invoke\",1147,0,\"nested-block-value\",[\"i32:10\"]],[\"invoke\",1148,0,\"nested-block-value\",[\"i32:4294967295\"]],[\"invoke\",1149,0,\"nested-block-value\",[\"i32:100000\"]],[\"invoke\",1151,0,\"nested-br-value\",[\"i32:0\"]],[\"invoke\",1152,0,\"nested-br-value\",[\"i32:1\"]],[\"invoke\",1153,0,\"nested-br-value\",[\"i32:2\"]],[\"invoke\",1154,0,\"nested-br-value\",[\"i32:11\"]],[\"invoke\",1155,0,\"nested-br-value\",[\"i32:4294967292\"]],[\"invoke\",1156,0,\"nested-br-value\",[\"i32:10213210\"]],[\"invoke\",1158,0,\"nested-br_if-value\",[\"i32:0\"]],[\"invoke\",1159,0,\"nested-br_if-value\",[\"i32:1\"]],[\"invoke\",1160,0,\"nested-br_if-value\",[\"i32:2\"]],[\"invoke\",1161,0,\"nested-br_if-value\",[\"i32:9\"]],[\"invoke\",1162,0,\"nested-br_if-value\",[\"i32:4294967287\"]],[\"invoke\",1163,0,\"nested-br_if-value\",[\"i32:999999\"]],[\"invoke\",1165,0,\"nested-br_if-value-cond\",[\"i32:0\"]],[\"invoke\",1166,0,\"nested-br_if-value-cond\",[\"i32:1\"]],[\"invoke\",1167,0,\"nested-br_if-value-cond\",[\"i32:2\"]],[\"invoke\",1168,0,\"nested-br_if-value-cond\",[\"i32:3\"]],[\"invoke\",1169,0,\"nested-br_if-value-cond\",[\"i32:4293967296\"]],[\"invoke\",1170,0,\"nested-br_if-value-cond\",[\"i32:9423975\"]],[\"invoke\",1172,0,\"nested-br_table-value\",[\"i32:0\"]],[\"invoke\",1173,0,\"nested-br_table-value\",[\"i32:1\"]],[\"invoke\",1174,0,\"nested-br_table-value\",[\"i32:2\"]],[\"invoke\",1175,0,\"nested-br_table-value\",[\"i32:9\"]],[\"invoke\",1176,0,\"nested-br_table-value\",[\"i32:4294967287\"]],[\"invoke\",1177,0,\"nested-br_table-value\",[\"i32:999999\"]],[\"invoke\",1179,0,\"nested-br_table-value-index\",[\"i32:0\"]],[\"invoke\",1180,0,\"nested-br_table-value-index\",[\"i32:1\"]],[\"invoke\",1181,0,\"nested-br_table-value-index\",[\"i32:2\"]],[\"invoke\",1182,0,\"nested-br_table-value-index\",[\"i32:3\"]],[\"invoke\",1183,0,\"nested-br_table-value-index\",[\"i32:4293967296\"]],[\"invoke\",1184,0,\"nested-br_table-value-index\",[\"i32:9423975\"]],[\"invoke\",1186,0,\"nested-br_table-loop-block\",[\"i32:1\"]],[\"invoke\",1188,0,\"meet-externref\",[\"i32:0\",\"externref:1\"]],[\"invoke\",1189,0,\"meet-externref\",[\"i32:1\",\"externref:1\"]],[\"invoke\",1190,0,\"meet-externref\",[\"i32:2\",\"externref:1\"]],[\"file\",\"call.wast\"],[\"module\",3,4],[\"invoke\",285,0,\"type-i32\",[]],[\"invoke\",286,0,\"type-i64\",[]],[\"invoke\",287,0,\"type-f32\",[]],[\"invoke\",288,0,\"type-f64\",[]],[\"invoke\",289,0,\"type-i32-i64\",[]],[\"invoke\",291,0,\"type-first-i32\",[]],[\"invoke\",292,0,\"type-first-i64\",[]],[\"invoke\",293,0,\"type-first-f32\",[]],[\"invoke\",294,0,\"type-first-f64\",[]],[\"invoke\",296,0,\"type-second-i32\",[]],[\"invoke\",297,0,\"type-second-i64\",[]],[\"invoke\",298,0,\"type-second-f32\",[]],[\"invoke\",299,0,\"type-second-f64\",[]],[\"invoke\",301,0,\"type-all-i32-f64\",[]],[\"invoke\",302,0,\"type-all-i32-i32\",[]],[\"invoke\",303,0,\"type-all-f32-f64\",[]],[\"invoke\",304,0,\"type-all-f64-i32\",[]],[\"invoke\",306,0,\"as-binary-all-operands\",[]],[\"invoke\",307,0,\"as-mixed-operands\",[]],[\"invoke\",308,0,\"as-call-all-operands\",[]],[\"invoke\",310,0,\"fac\",[\"i64:0\"]],[\"invoke\",311,0,\"fac\",[\"i64:1\"]],[\"invoke\",312,0,\"fac\",[\"i64:5\"]],[\"invoke\",313,0,\"fac\",[\"i64:25\"]],[\"invoke\",314,0,\"fac-acc\",[\"i64:0\",\"i64:1\"]],[\"invoke\",315,0,\"fac-acc\",[\"i64:1\",\"i64:1\"]],[\"invoke\",316,0,\"fac-acc\",[\"i64:5\",\"i64:1\"]],[\"invoke\",318,0,\"fac-acc\",[\"i64:25\",\"i64:1\"]],[\"invoke\",322,0,\"fib\",[\"i64:0\"]],[\"invoke\",323,0,\"fib\",[\"i64:1\"]],[\"invoke\",324,0,\"fib\",[\"i64:2\"]],[\"invoke\",325,0,\"fib\",[\"i64:5\"]],[\"invoke\",326,0,\"fib\",[\"i64:20\"]],[\"invoke\",328,0,\"even\",[\"i64:0\"]],[\"invoke\",329,0,\"even\",[\"i64:1\"]],[\"invoke\",330,0,\"even\",[\"i64:100\"]],[\"invoke\",331,0,\"even\",[\"i64:77\"]],[\"invoke\",332,0,\"odd\",[\"i64:0\"]],[\"invoke\",333,0,\"odd\",[\"i64:1\"]],[\"invoke\",334,0,\"odd\",[\"i64:200\"]],[\"invoke\",335,0,\"odd\",[\"i64:77\"]],[\"invoke\",337,0,\"runaway\",[]],[\"invoke\",338,0,\"mutual-runaway\",[]],[\"invoke\",340,0,\"as-select-first\",[]],[\"invoke\",341,0,\"as-select-mid\",[]],[\"invoke\",342,0,\"as-select-last\",[]],[\"invoke\",344,0,\"as-if-condition\",[]],[\"invoke\",346,0,\"as-br_if-first\",[]],[\"invoke\",347,0,\"as-br_if-last\",[]],[\"invoke\",349,0,\"as-br_table-first\",[]],[\"invoke\",350,0,\"as-br_table-last\",[]],[\"invoke\",352,0,\"as-call_indirect-first\",[]],[\"invoke\",353,0,\"as-call_indirect-mid\",[]],[\"invoke\",354,0,\"as-call_indirect-last\",[]],[\"invoke\",356,0,\"as-store-first\",[]],[\"invoke\",357,0,\"as-store-last\",[]],[\"invoke\",359,0,\"as-memory.grow-value\",[]],[\"invoke\",360,0,\"as-return-value\",[]],[\"invoke\",361,0,\"as-drop-operand\",[]],[\"invoke\",362,0,\"as-br-value\",[]],[\"invoke\",363,0,\"as-local.set-value\",[]],[\"invoke\",364,0,\"as-local.tee-value\",[]],[\"invoke\",365,0,\"as-global.set-value\",[]],[\"invoke\",366,0,\"as-load-operand\",[]],[\"invoke\",368,0,\"as-unary-operand\",[]],[\"invoke\",369,0,\"as-binary-left\",[]],[\"invoke\",370,0,\"as-binary-right\",[]],[\"invoke\",371,0,\"as-test-operand\",[]],[\"invoke\",372,0,\"as-compare-left\",[]],[\"invoke\",373,0,\"as-compare-right\",[]],[\"invoke\",374,0,\"as-convert-operand\",[]],[\"invoke\",376,0,\"return-from-long-argument-list\",[\"i32:42\"]],[\"file\",\"call_indirect.wast\"],[\"module\",3,5],[\"invoke\",471,0,\"type-i32\",[]],[\"invoke\",472,0,\"type-i64\",[]],[\"invoke\",473,0,\"type-f32\",[]],[\"invoke\",474,0,\"type-f64\",[]],[\"invoke\",475,0,\"type-f64-i32\",[]],[\"invoke\",477,0,\"type-index\",[]],[\"invoke\",479,0,\"type-first-i32\",[]],[\"invoke\",480,0,\"type-first-i64\",[]],[\"invoke\",481,0,\"type-first-f32\",[]],[\"invoke\",482,0,\"type-first-f64\",[]],[\"invoke\",484,0,\"type-second-i32\",[]],[\"invoke\",485,0,\"type-second-i64\",[]],[\"invoke\",486,0,\"type-second-f32\",[]],[\"invoke\",487,0,\"type-second-f64\",[]],[\"invoke\",489,0,\"type-all-f64-i32\",[]],[\"invoke\",490,0,\"type-all-i32-f64\",[]],[\"invoke\",491,0,\"type-all-i32-i64\",[]],[\"invoke\",493,0,\"dispatch\",[\"i32:5\",\"i64:2\"]],[\"invoke\",494,0,\"dispatch\",[\"i32:5\",\"i64:5\"]],[\"invoke\",495,0,\"dispatch\",[\"i32:12\",\"i64:5\"]],[\"invoke\",496,0,\"dispatch\",[\"i32:13\",\"i64:5\"]],[\"invoke\",497,0,\"dispatch\",[\"i32:20\",\"i64:2\"]],[\"invoke\",498,0,\"dispatch\",[\"i32:0\",\"i64:2\"]],[\"invoke\",499,0,\"dispatch\",[\"i32:15\",\"i64:2\"]],[\"invoke\",500,0,\"dispatch\",[\"i32:32\",\"i64:2\"]],[\"invoke\",501,0,\"dispatch\",[\"i32:4294967295\",\"i64:2\"]],[\"invoke\",502,0,\"dispatch\",[\"i32:1213432423\",\"i64:2\"]],[\"invoke\",504,0,\"dispatch-structural-i64\",[\"i32:5\"]],[\"invoke\",505,0,\"dispatch-structural-i64\",[\"i32:12\"]],[\"invoke\",506,0,\"dispatch-structural-i64\",[\"i32:13\"]],[\"invoke\",507,0,\"dispatch-structural-i64\",[\"i32:20\"]],[\"invoke\",508,0,\"dispatch-structural-i64\",[\"i32:11\"]],[\"invoke\",509,0,\"dispatch-structural-i64\",[\"i32:22\"]],[\"invoke\",511,0,\"dispatch-structural-i32\",[\"i32:4\"]],[\"invoke\",512,0,\"dispatch-structural-i32\",[\"i32:23\"]],[\"invoke\",513,0,\"dispatch-structural-i32\",[\"i32:26\"]],[\"invoke\",514,0,\"dispatch-structural-i32\",[\"i32:19\"]],[\"invoke\",515,0,\"dispatch-structural-i32\",[\"i32:9\"]],[\"invoke\",516,0,\"dispatch-structural-i32\",[\"i32:21\"]],[\"invoke\",518,0,\"dispatch-structural-f32\",[\"i32:6\"]],[\"invoke\",519,0,\"dispatch-structural-f32\",[\"i32:24\"]],[\"invoke\",520,0,\"dispatch-structural-f32\",[\"i32:27\"]],[\"invoke\",521,0,\"dispatch-structural-f32\",[\"i32:21\"]],[\"invoke\",522,0,\"dispatch-structural-f32\",[\"i32:8\"]],[\"invoke\",523,0,\"dispatch-structural-f32\",[\"i32:19\"]],[\"invoke\",525,0,\"dispatch-structural-f64\",[\"i32:7\"]],[\"invoke\",526,0,\"dispatch-structural-f64\",[\"i32:25\"]],[\"invoke\",527,0,\"dispatch-structural-f64\",[\"i32:28\"]],[\"invoke\",528,0,\"dispatch-structural-f64\",[\"i32:22\"]],[\"invoke\",529,0,\"dispatch-structural-f64\",[\"i32:10\"]],[\"invoke\",530,0,\"dispatch-structural-f64\",[\"i32:18\"]],[\"invoke\",532,0,\"fac-i64\",[\"i64:0\"]],[\"invoke\",533,0,\"fac-i64\",[\"i64:1\"]],[\"invoke\",534,0,\"fac-i64\",[\"i64:5\"]],[\"invoke\",535,0,\"fac-i64\",[\"i64:25\"]],[\"invoke\",537,0,\"fac-i32\",[\"i32:0\"]],[\"invoke\",538,0,\"fac-i32\",[\"i32:1\"]],[\"invoke\",539,0,\"fac-i32\",[\"i32:5\"]],[\"invoke\",540,0,\"fac-i32\",[\"i32:10\"]],[\"invoke\",542,0,\"fac-f32\",[\"f32:0\"]],[\"invoke\",543,0,\"fac-f32\",[\"f32:1065353216\"]],[\"invoke\",544,0,\"fac-f32\",[\"f32:1084227584\"]],[\"invoke\",545,0,\"fac-f32\",[\"f32:1092616192\"]],[\"invoke\",547,0,\"fac-f64\",[\"f64:0\"]],[\"invoke\",548,0,\"fac-f64\",[\"f64:4607182418800017408\"]],[\"invoke\",549,0,\"fac-f64\",[\"f64:4617315517961601024\"]],[\"invoke\",550,0,\"fac-f64\",[\"f64:4621819117588971520\"]],[\"invoke\",552,0,\"fib-i64\",[\"i64:0\"]],[\"invoke\",553,0,\"fib-i64\",[\"i64:1\"]],[\"invoke\",554,0,\"fib-i64\",[\"i64:2\"]],[\"invoke\",555,0,\"fib-i64\",[\"i64:5\"]],[\"invoke\",556,0,\"fib-i64\",[\"i64:20\"]],[\"invoke\",558,0,\"fib-i32\",[\"i32:0\"]],[\"invoke\",559,0,\"fib-i32\",[\"i32:1\"]],[\"invoke\",560,0,\"fib-i32\",[\"i32:2\"]],[\"invoke\",561,0,\"fib-i32\",[\"i32:5\"]],[\"invoke\",562,0,\"fib-i32\",[\"i32:20\"]],[\"invoke\",564,0,\"fib-f32\",[\"f32:0\"]],[\"invoke\",565,0,\"fib-f32\",[\"f32:1065353216\"]],[\"invoke\",566,0,\"fib-f32\",[\"f32:1073741824\"]],[\"invoke\",567,0,\"fib-f32\",[\"f32:1084227584\"]],[\"invoke\",568,0,\"fib-f32\",[\"f32:1101004800\"]],[\"invoke\",570,0,\"fib-f64\",[\"f64:0\"]],[\"invoke\",571,0,\"fib-f64\",[\"f64:4607182418800017408\"]],[\"invoke\",572,0,\"fib-f64\",[\"f64:4611686018427387904\"]],[\"invoke\",573,0,\"fib-f64\",[\"f64:4617315517961601024\"]],[\"invoke\",574,0,\"fib-f64\",[\"f64:4626322717216342016\"]],[\"invoke\",576,0,\"even\",[\"i32:0\"]],[\"invoke\",577,0,\"even\",[\"i32:1\"]],[\"invoke\",578,0,\"even\",[\"i32:100\"]],[\"invoke\",579,0,\"even\",[\"i32:77\"]],[\"invoke\",580,0,\"odd\",[\"i32:0\"]],[\"invoke\",581,0,\"odd\",[\"i32:1\"]],[\"invoke\",582,0,\"odd\",[\"i32:200\"]],[\"invoke\",583,0,\"odd\",[\"i32:77\"]],[\"invoke\",585,0,\"runaway\",[]],[\"invoke\",586,0,\"mutual-runaway\",[]],[\"invoke\",588,0,\"as-select-first\",[]],[\"invoke\",589,0,\"as-select-mid\",[]],[\"invoke\",590,0,\"as-select-last\",[]],[\"invoke\",592,0,\"as-if-condition\",[]],[\"invoke\",594,0,\"as-br_if-first\",[]],[\"invoke\",595,0,\"as-br_if-last\",[]],[\"invoke\",597,0,\"as-br_table-first\",[]],[\"invoke\",598,0,\"as-br_table-last\",[]],[\"invoke\",600,0,\"as-store-first\",[]],[\"invoke\",601,0,\"as-store-last\",[]],[\"invoke\",603,0,\"as-memory.grow-value\",[]],[\"invoke\",604,0,\"as-return-value\",[]],[\"invoke\",605,0,\"as-drop-operand\",[]],[\"invoke\",606,0,\"as-br-value\",[]],[\"invoke\",607,0,\"as-local.set-value\",[]],[\"invoke\",608,0,\"as-local.tee-value\",[]],[\"invoke\",609,0,\"as-global.set-value\",[]],[\"invoke\",610,0,\"as-load-operand\",[]],[\"invoke\",612,0,\"as-unary-operand\",[]],[\"invoke\",613,0,\"as-binary-left\",[]],[\"invoke\",614,0,\"as-binary-right\",[]],[\"invoke\",615,0,\"as-test-operand\",[]],[\"invoke\",616,0,\"as-compare-left\",[]],[\"invoke\",617,0,\"as-compare-right\",[]],[\"invoke\",618,0,\"as-convert-operand\",[]],[\"module\",623,6],[\"invoke\",650,0,\"call-1\",[\"i32:2\",\"i32:3\",\"i32:0\"]],[\"invoke\",651,0,\"call-1\",[\"i32:2\",\"i32:3\",\"i32:1\"]],[\"invoke\",652,0,\"call-1\",[\"i32:2\",\"i32:3\",\"i32:2\"]],[\"invoke\",654,0,\"call-2\",[\"i32:2\",\"i32:3\",\"i32:0\"]],[\"invoke\",655,0,\"call-2\",[\"i32:2\",\"i32:3\",\"i32:1\"]],[\"invoke\",656,0,\"call-2\",[\"i32:2\",\"i32:3\",\"i32:2\"]],[\"invoke\",657,0,\"call-2\",[\"i32:2\",\"i32:3\",\"i32:3\"]],[\"invoke\",659,0,\"call-3\",[\"i32:2\",\"i32:3\",\"i32:0\"]],[\"invoke\",660,0,\"call-3\",[\"i32:2\",\"i32:3\",\"i32:1\"]],[\"invoke\",661,0,\"call-3\",[\"i32:2\",\"i32:3\",\"i32:2\"]],[\"invoke\",662,0,\"call-3\",[\"i32:2\",\"i32:3\",\"i32:3\"]],[\"invoke\",663,0,\"call-3\",[\"i32:2\",\"i32:3\",\"i32:4\"]],[\"module\",1047,7],[\"file\",\"fac.wast\"],[\"module\",1,8],[\"invoke\",102,0,\"fac-rec\",[\"i64:25\"]],[\"invoke\",103,0,\"fac-iter\",[\"i64:25\"]],[\"invoke\",104,0,\"fac-rec-named\",[\"i64:25\"]],[\"invoke\",105,0,\"fac-iter-named\",[\"i64:25\"]],[\"invoke\",106,0,\"fac-opt\",[\"i64:25\"]],[\"invoke\",107,0,\"fac-ssa\",[\"i64:25\"]],[\"invoke\",109,0,\"fac-rec\",[\"i64:1073741824\"]],[\"file\",\"forward.wast\"],[\"module\",1,9],[\"invoke\",17,0,\"even\",[\"i32:13\"]],[\"invoke\",18,0,\"even\",[\"i32:20\"]],[\"invoke\",19,0,\"odd\",[\"i32:13\"]],[\"invoke\",20,0,\"odd\",[\"i32:20\"]],[\"file\",\"func.wast\"],[\"module\",3,10],[\"invoke\",241,0,\"type-use-1\",[]],[\"invoke\",242,0,\"type-use-2\",[]],[\"invoke\",243,0,\"type-use-3\",[\"i32:1\"]],[\"invoke\",245,0,\"type-use-4\",[\"i32:1\",\"f64:4607182418800017408\",\"i32:1\"]],[\"invoke\",248,0,\"type-use-5\",[]],[\"invoke\",249,0,\"type-use-6\",[\"i32:1\"]],[\"invoke\",251,0,\"type-use-7\",[\"i32:1\",\"f64:4607182418800017408\",\"i32:1\"]],[\"invoke\",255,0,\"local-first-i32\",[]],[\"invoke\",256,0,\"local-first-i64\",[]],[\"invoke\",257,0,\"local-first-f32\",[]],[\"invoke\",258,0,\"local-first-f64\",[]],[\"invoke\",259,0,\"local-second-i32\",[]],[\"invoke\",260,0,\"local-second-i64\",[]],[\"invoke\",261,0,\"local-second-f32\",[]],[\"invoke\",262,0,\"local-second-f64\",[]],[\"invoke\",263,0,\"local-mixed\",[]],[\"invoke\",266,0,\"param-first-i32\",[\"i32:2\",\"i32:3\"]],[\"invoke\",269,0,\"param-first-i64\",[\"i64:2\",\"i64:3\"]],[\"invoke\",272,0,\"param-first-f32\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",275,0,\"param-first-f64\",[\"f64:4611686018427387904\",\"f64:4613937818241073152\"]],[\"invoke\",278,0,\"param-second-i32\",[\"i32:2\",\"i32:3\"]],[\"invoke\",281,0,\"param-second-i64\",[\"i64:2\",\"i64:3\"]],[\"invoke\",284,0,\"param-second-f32\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",287,0,\"param-second-f64\",[\"f64:4611686018427387904\",\"f64:4613937818241073152\"]],[\"invoke\",291,0,\"param-mixed\",[\"f32:1065353216\",\"i32:2\",\"i64:3\",\"i32:4\",\"f64:4617878467915022336\",\"i32:6\"]],[\"invoke\",298,0,\"empty\",[]],[\"invoke\",299,0,\"value-void\",[]],[\"invoke\",300,0,\"value-i32\",[]],[\"invoke\",301,0,\"value-i64\",[]],[\"invoke\",302,0,\"value-f32\",[]],[\"invoke\",303,0,\"value-f64\",[]],[\"invoke\",304,0,\"value-i32-f64\",[]],[\"invoke\",305,0,\"value-i32-i32-i32\",[]],[\"invoke\",308,0,\"value-block-void\",[]],[\"invoke\",309,0,\"value-block-i32\",[]],[\"invoke\",310,0,\"value-block-i32-i64\",[]],[\"invoke\",312,0,\"return-empty\",[]],[\"invoke\",313,0,\"return-i32\",[]],[\"invoke\",314,0,\"return-i64\",[]],[\"invoke\",315,0,\"return-f32\",[]],[\"invoke\",316,0,\"return-f64\",[]],[\"invoke\",317,0,\"return-i32-f64\",[]],[\"invoke\",318,0,\"return-i32-i32-i32\",[]],[\"invoke\",321,0,\"return-block-i32\",[]],[\"invoke\",322,0,\"return-block-i32-i64\",[]],[\"invoke\",324,0,\"break-empty\",[]],[\"invoke\",325,0,\"break-i32\",[]],[\"invoke\",326,0,\"break-i64\",[]],[\"invoke\",327,0,\"break-f32\",[]],[\"invoke\",328,0,\"break-f64\",[]],[\"invoke\",329,0,\"break-i32-f64\",[]],[\"invoke\",330,0,\"break-i32-i32-i32\",[]],[\"invoke\",333,0,\"break-block-i32\",[]],[\"invoke\",334,0,\"break-block-i32-i64\",[]],[\"invoke\",336,0,\"break-br_if-empty\",[\"i32:0\"]],[\"invoke\",337,0,\"break-br_if-empty\",[\"i32:2\"]],[\"invoke\",338,0,\"break-br_if-num\",[\"i32:0\"]],[\"invoke\",339,0,\"break-br_if-num\",[\"i32:1\"]],[\"invoke\",340,0,\"break-br_if-num-num\",[\"i32:0\"]],[\"invoke\",343,0,\"break-br_if-num-num\",[\"i32:1\"]],[\"invoke\",347,0,\"break-br_table-empty\",[\"i32:0\"]],[\"invoke\",348,0,\"break-br_table-empty\",[\"i32:1\"]],[\"invoke\",349,0,\"break-br_table-empty\",[\"i32:5\"]],[\"invoke\",350,0,\"break-br_table-empty\",[\"i32:4294967295\"]],[\"invoke\",351,0,\"break-br_table-num\",[\"i32:0\"]],[\"invoke\",352,0,\"break-br_table-num\",[\"i32:1\"]],[\"invoke\",353,0,\"break-br_table-num\",[\"i32:10\"]],[\"invoke\",354,0,\"break-br_table-num\",[\"i32:4294967196\"]],[\"invoke\",355,0,\"break-br_table-num-num\",[\"i32:0\"]],[\"invoke\",358,0,\"break-br_table-num-num\",[\"i32:1\"]],[\"invoke\",361,0,\"break-br_table-num-num\",[\"i32:10\"]],[\"invoke\",364,0,\"break-br_table-num-num\",[\"i32:4294967196\"]],[\"invoke\",367,0,\"break-br_table-nested-empty\",[\"i32:0\"]],[\"invoke\",368,0,\"break-br_table-nested-empty\",[\"i32:1\"]],[\"invoke\",369,0,\"break-br_table-nested-empty\",[\"i32:3\"]],[\"invoke\",370,0,\"break-br_table-nested-empty\",[\"i32:4294967294\"]],[\"invoke\",372,0,\"break-br_table-nested-num\",[\"i32:0\"]],[\"invoke\",375,0,\"break-br_table-nested-num\",[\"i32:1\"]],[\"invoke\",378,0,\"break-br_table-nested-num\",[\"i32:2\"]],[\"invoke\",381,0,\"break-br_table-nested-num\",[\"i32:4294967293\"]],[\"invoke\",384,0,\"break-br_table-nested-num-num\",[\"i32:0\"]],[\"invoke\",388,0,\"break-br_table-nested-num-num\",[\"i32:1\"]],[\"invoke\",392,0,\"break-br_table-nested-num-num\",[\"i32:2\"]],[\"invoke\",396,0,\"break-br_table-nested-num-num\",[\"i32:4294967293\"]],[\"invoke\",401,0,\"large-sig\",[\"i32:0\",\"i64:1\",\"f32:1073741824\",\"f32:1077936128\",\"i32:4\",\"f64:4617315517961601024\",\"f32:1086324736\",\"i32:7\",\"i32:8\",\"i32:9\",\"f32:1092616192\",\"f64:4622382067542392832\",\"f64:4622945017495814144\",\"f64:4623507967449235456\",\"i32:14\",\"i32:15\",\"f32:1098907648\"]],[\"invoke\",414,0,\"init-local-i32\",[]],[\"invoke\",415,0,\"init-local-i64\",[]],[\"invoke\",416,0,\"init-local-f32\",[]],[\"invoke\",417,0,\"init-local-f64\",[]],[\"module\",422,11],[\"module\",459,12],[\"invoke\",483,0,\"f\",[\"i32:42\"]],[\"invoke\",484,0,\"g\",[\"i32:42\"]],[\"invoke\",485,0,\"p\",[]],[\"module\",488,13],[\"invoke\",551,0,\"signature-explicit-reused\",[]],[\"invoke\",552,0,\"signature-implicit-reused\",[]],[\"invoke\",553,0,\"signature-explicit-duplicate\",[]],[\"invoke\",554,0,\"signature-implicit-duplicate\",[]],[\"file\",\"func_ptrs.wast\"],[\"module\",1,14],[\"invoke\",27,0,\"one\",[]],[\"invoke\",28,0,\"two\",[\"i32:13\"]],[\"invoke\",29,0,\"three\",[\"i32:13\"]],[\"invoke\",30,0,\"four\",[\"i32:83\"]],[\"module\",51,15],[\"invoke\",71,0,\"callt\",[\"i32:0\"]],[\"invoke\",72,0,\"callt\",[\"i32:1\"]],[\"invoke\",73,0,\"callt\",[\"i32:2\"]],[\"invoke\",74,0,\"callt\",[\"i32:3\"]],[\"invoke\",75,0,\"callt\",[\"i32:4\"]],[\"invoke\",76,0,\"callt\",[\"i32:5\"]],[\"invoke\",77,0,\"callt\",[\"i32:6\"]],[\"invoke\",78,0,\"callt\",[\"i32:7\"]],[\"invoke\",79,0,\"callt\",[\"i32:100\"]],[\"invoke\",80,0,\"callt\",[\"i32:4294967295\"]],[\"invoke\",82,0,\"callu\",[\"i32:0\"]],[\"invoke\",83,0,\"callu\",[\"i32:1\"]],[\"invoke\",84,0,\"callu\",[\"i32:2\"]],[\"invoke\",85,0,\"callu\",[\"i32:3\"]],[\"invoke\",86,0,\"callu\",[\"i32:4\"]],[\"invoke\",87,0,\"callu\",[\"i32:5\"]],[\"invoke\",88,0,\"callu\",[\"i32:6\"]],[\"invoke\",89,0,\"callu\",[\"i32:7\"]],[\"invoke\",90,0,\"callu\",[\"i32:100\"]],[\"invoke\",91,0,\"callu\",[\"i32:4294967295\"]],[\"module\",93,16],[\"invoke\",105,0,\"callt\",[\"i32:0\"]],[\"invoke\",106,0,\"callt\",[\"i32:1\"]],[\"file\",\"if.wast\"],[\"module\",3,17],[\"invoke\",537,0,\"empty\",[\"i32:0\"]],[\"invoke\",538,0,\"empty\",[\"i32:1\"]],[\"invoke\",539,0,\"empty\",[\"i32:100\"]],[\"invoke\",540,0,\"empty\",[\"i32:4294967294\"]],[\"invoke\",542,0,\"singular\",[\"i32:0\"]],[\"invoke\",543,0,\"singular\",[\"i32:1\"]],[\"invoke\",544,0,\"singular\",[\"i32:10\"]],[\"invoke\",545,0,\"singular\",[\"i32:4294967286\"]],[\"invoke\",547,0,\"multi\",[\"i32:0\"]],[\"invoke\",548,0,\"multi\",[\"i32:1\"]],[\"invoke\",549,0,\"multi\",[\"i32:13\"]],[\"invoke\",550,0,\"multi\",[\"i32:4294967291\"]],[\"invoke\",552,0,\"nested\",[\"i32:0\",\"i32:0\"]],[\"invoke\",553,0,\"nested\",[\"i32:1\",\"i32:0\"]],[\"invoke\",554,0,\"nested\",[\"i32:0\",\"i32:1\"]],[\"invoke\",555,0,\"nested\",[\"i32:3\",\"i32:2\"]],[\"invoke\",556,0,\"nested\",[\"i32:0\",\"i32:4294967196\"]],[\"invoke\",557,0,\"nested\",[\"i32:10\",\"i32:10\"]],[\"invoke\",558,0,\"nested\",[\"i32:0\",\"i32:4294967295\"]],[\"invoke\",559,0,\"nested\",[\"i32:4294967185\",\"i32:4294967294\"]],[\"invoke\",561,0,\"as-select-first\",[\"i32:0\"]],[\"invoke\",562,0,\"as-select-first\",[\"i32:1\"]],[\"invoke\",563,0,\"as-select-mid\",[\"i32:0\"]],[\"invoke\",564,0,\"as-select-mid\",[\"i32:1\"]],[\"invoke\",565,0,\"as-select-last\",[\"i32:0\"]],[\"invoke\",566,0,\"as-select-last\",[\"i32:1\"]],[\"invoke\",568,0,\"as-loop-first\",[\"i32:0\"]],[\"invoke\",569,0,\"as-loop-first\",[\"i32:1\"]],[\"invoke\",570,0,\"as-loop-mid\",[\"i32:0\"]],[\"invoke\",571,0,\"as-loop-mid\",[\"i32:1\"]],[\"invoke\",572,0,\"as-loop-last\",[\"i32:0\"]],[\"invoke\",573,0,\"as-loop-last\",[\"i32:1\"]],[\"invoke\",575,0,\"as-if-condition\",[\"i32:0\"]],[\"invoke\",576,0,\"as-if-condition\",[\"i32:1\"]],[\"invoke\",578,0,\"as-br_if-first\",[\"i32:0\"]],[\"invoke\",579,0,\"as-br_if-first\",[\"i32:1\"]],[\"invoke\",580,0,\"as-br_if-last\",[\"i32:0\"]],[\"invoke\",581,0,\"as-br_if-last\",[\"i32:1\"]],[\"invoke\",583,0,\"as-br_table-first\",[\"i32:0\"]],[\"invoke\",584,0,\"as-br_table-first\",[\"i32:1\"]],[\"invoke\",585,0,\"as-br_table-last\",[\"i32:0\"]],[\"invoke\",586,0,\"as-br_table-last\",[\"i32:1\"]],[\"invoke\",588,0,\"as-call_indirect-first\",[\"i32:0\"]],[\"invoke\",589,0,\"as-call_indirect-first\",[\"i32:1\"]],[\"invoke\",590,0,\"as-call_indirect-mid\",[\"i32:0\"]],[\"invoke\",591,0,\"as-call_indirect-mid\",[\"i32:1\"]],[\"invoke\",592,0,\"as-call_indirect-last\",[\"i32:0\"]],[\"invoke\",593,0,\"as-call_indirect-last\",[\"i32:1\"]],[\"invoke\",595,0,\"as-store-first\",[\"i32:0\"]],[\"invoke\",596,0,\"as-store-first\",[\"i32:1\"]],[\"invoke\",597,0,\"as-store-last\",[\"i32:0\"]],[\"invoke\",598,0,\"as-store-last\",[\"i32:1\"]],[\"invoke\",600,0,\"as-memory.grow-value\",[\"i32:0\"]],[\"invoke\",601,0,\"as-memory.grow-value\",[\"i32:1\"]],[\"invoke\",603,0,\"as-call-value\",[\"i32:0\"]],[\"invoke\",604,0,\"as-call-value\",[\"i32:1\"]],[\"invoke\",606,0,\"as-return-value\",[\"i32:0\"]],[\"invoke\",607,0,\"as-return-value\",[\"i32:1\"]],[\"invoke\",609,0,\"as-drop-operand\",[\"i32:0\"]],[\"invoke\",610,0,\"as-drop-operand\",[\"i32:1\"]],[\"invoke\",612,0,\"as-br-value\",[\"i32:0\"]],[\"invoke\",613,0,\"as-br-value\",[\"i32:1\"]],[\"invoke\",615,0,\"as-local.set-value\",[\"i32:0\"]],[\"invoke\",616,0,\"as-local.set-value\",[\"i32:1\"]],[\"invoke\",618,0,\"as-local.tee-value\",[\"i32:0\"]],[\"invoke\",619,0,\"as-local.tee-value\",[\"i32:1\"]],[\"invoke\",621,0,\"as-global.set-value\",[\"i32:0\"]],[\"invoke\",622,0,\"as-global.set-value\",[\"i32:1\"]],[\"invoke\",624,0,\"as-load-operand\",[\"i32:0\"]],[\"invoke\",625,0,\"as-load-operand\",[\"i32:1\"]],[\"invoke\",627,0,\"as-unary-operand\",[\"i32:0\"]],[\"invoke\",628,0,\"as-unary-operand\",[\"i32:1\"]],[\"invoke\",629,0,\"as-unary-operand\",[\"i32:4294967295\"]],[\"invoke\",631,0,\"as-binary-operand\",[\"i32:0\",\"i32:0\"]],[\"invoke\",632,0,\"as-binary-operand\",[\"i32:0\",\"i32:1\"]],[\"invoke\",633,0,\"as-binary-operand\",[\"i32:1\",\"i32:0\"]],[\"invoke\",634,0,\"as-binary-operand\",[\"i32:1\",\"i32:1\"]],[\"invoke\",636,0,\"as-test-operand\",[\"i32:0\"]],[\"invoke\",637,0,\"as-test-operand\",[\"i32:1\"]],[\"invoke\",639,0,\"as-compare-operand\",[\"i32:0\",\"i32:0\"]],[\"invoke\",640,0,\"as-compare-operand\",[\"i32:0\",\"i32:1\"]],[\"invoke\",641,0,\"as-compare-operand\",[\"i32:1\",\"i32:0\"]],[\"invoke\",642,0,\"as-compare-operand\",[\"i32:1\",\"i32:1\"]],[\"invoke\",644,0,\"as-binary-operands\",[\"i32:0\"]],[\"invoke\",645,0,\"as-binary-operands\",[\"i32:1\"]],[\"invoke\",647,0,\"as-compare-operands\",[\"i32:0\"]],[\"invoke\",648,0,\"as-compare-operands\",[\"i32:1\"]],[\"invoke\",650,0,\"as-mixed-operands\",[\"i32:0\"]],[\"invoke\",651,0,\"as-mixed-operands\",[\"i32:1\"]],[\"invoke\",653,0,\"break-bare\",[]],[\"invoke\",654,0,\"break-value\",[\"i32:1\"]],[\"invoke\",655,0,\"break-value\",[\"i32:0\"]],[\"invoke\",656,0,\"break-multi-value\",[\"i32:0\"]],[\"invoke\",659,0,\"break-multi-value\",[\"i32:1\"]],[\"invoke\",663,0,\"param\",[\"i32:0\"]],[\"invoke\",664,0,\"param\",[\"i32:1\"]],[\"invoke\",665,0,\"params\",[\"i32:0\"]],[\"invoke\",666,0,\"params\",[\"i32:1\"]],[\"invoke\",667,0,\"params-id\",[\"i32:0\"]],[\"invoke\",668,0,\"params-id\",[\"i32:1\"]],[\"invoke\",669,0,\"param-break\",[\"i32:0\"]],[\"invoke\",670,0,\"param-break\",[\"i32:1\"]],[\"invoke\",671,0,\"params-break\",[\"i32:0\"]],[\"invoke\",672,0,\"params-break\",[\"i32:1\"]],[\"invoke\",673,0,\"params-id-break\",[\"i32:0\"]],[\"invoke\",674,0,\"params-id-break\",[\"i32:1\"]],[\"invoke\",676,0,\"effects\",[\"i32:1\"]],[\"invoke\",677,0,\"effects\",[\"i32:0\"]],[\"invoke\",680,0,\"add64_u_with_carry\",[\"i64:0\",\"i64:0\",\"i32:0\"]],[\"invoke\",684,0,\"add64_u_with_carry\",[\"i64:100\",\"i64:124\",\"i32:0\"]],[\"invoke\",688,0,\"add64_u_with_carry\",[\"i64:18446744073709551615\",\"i64:0\",\"i32:0\"]],[\"invoke\",692,0,\"add64_u_with_carry\",[\"i64:18446744073709551615\",\"i64:1\",\"i32:0\"]],[\"invoke\",696,0,\"add64_u_with_carry\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\",\"i32:0\"]],[\"invoke\",700,0,\"add64_u_with_carry\",[\"i64:18446744073709551615\",\"i64:0\",\"i32:1\"]],[\"invoke\",704,0,\"add64_u_with_carry\",[\"i64:18446744073709551615\",\"i64:1\",\"i32:1\"]],[\"invoke\",708,0,\"add64_u_with_carry\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\",\"i32:0\"]],[\"invoke\",713,0,\"add64_u_saturated\",[\"i64:0\",\"i64:0\"]],[\"invoke\",716,0,\"add64_u_saturated\",[\"i64:1230\",\"i64:23\"]],[\"invoke\",719,0,\"add64_u_saturated\",[\"i64:18446744073709551615\",\"i64:0\"]],[\"invoke\",722,0,\"add64_u_saturated\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",725,0,\"add64_u_saturated\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",728,0,\"add64_u_saturated\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",731,0,\"type-use\",[]],[\"invoke\",733,0,\"atypical-condition\",[]],[\"file\",\"labels.wast\"],[\"module\",1,18],[\"invoke\",291,0,\"block\",[]],[\"invoke\",292,0,\"loop1\",[]],[\"invoke\",293,0,\"loop2\",[]],[\"invoke\",294,0,\"loop3\",[]],[\"invoke\",295,0,\"loop4\",[\"i32:8\"]],[\"invoke\",296,0,\"loop5\",[]],[\"invoke\",297,0,\"loop6\",[]],[\"invoke\",298,0,\"if\",[]],[\"invoke\",299,0,\"if2\",[]],[\"invoke\",300,0,\"switch\",[\"i32:0\"]],[\"invoke\",301,0,\"switch\",[\"i32:1\"]],[\"invoke\",302,0,\"switch\",[\"i32:2\"]],[\"invoke\",303,0,\"switch\",[\"i32:3\"]],[\"invoke\",304,0,\"switch\",[\"i32:4\"]],[\"invoke\",305,0,\"switch\",[\"i32:5\"]],[\"invoke\",306,0,\"return\",[\"i32:0\"]],[\"invoke\",307,0,\"return\",[\"i32:1\"]],[\"invoke\",308,0,\"return\",[\"i32:2\"]],[\"invoke\",309,0,\"br_if0\",[]],[\"invoke\",310,0,\"br_if1\",[]],[\"invoke\",311,0,\"br_if2\",[]],[\"invoke\",312,0,\"br_if3\",[]],[\"invoke\",313,0,\"br\",[]],[\"invoke\",314,0,\"shadowing\",[]],[\"invoke\",315,0,\"redefinition\",[]],[\"file\",\"loop.wast\"],[\"module\",3,19],[\"invoke\",430,0,\"empty\",[]],[\"invoke\",431,0,\"singular\",[]],[\"invoke\",432,0,\"multi\",[]],[\"invoke\",433,0,\"nested\",[]],[\"invoke\",434,0,\"deep\",[]],[\"invoke\",436,0,\"as-select-first\",[]],[\"invoke\",437,0,\"as-select-mid\",[]],[\"invoke\",438,0,\"as-select-last\",[]],[\"invoke\",440,0,\"as-if-condition\",[]],[\"invoke\",441,0,\"as-if-then\",[]],[\"invoke\",442,0,\"as-if-else\",[]],[\"invoke\",444,0,\"as-br_if-first\",[]],[\"invoke\",445,0,\"as-br_if-last\",[]],[\"invoke\",447,0,\"as-br_table-first\",[]],[\"invoke\",448,0,\"as-br_table-last\",[]],[\"invoke\",450,0,\"as-call_indirect-first\",[]],[\"invoke\",451,0,\"as-call_indirect-mid\",[]],[\"invoke\",452,0,\"as-call_indirect-last\",[]],[\"invoke\",454,0,\"as-store-first\",[]],[\"invoke\",455,0,\"as-store-last\",[]],[\"invoke\",457,0,\"as-memory.grow-value\",[]],[\"invoke\",458,0,\"as-call-value\",[]],[\"invoke\",459,0,\"as-return-value\",[]],[\"invoke\",460,0,\"as-drop-operand\",[]],[\"invoke\",461,0,\"as-br-value\",[]],[\"invoke\",462,0,\"as-local.set-value\",[]],[\"invoke\",463,0,\"as-local.tee-value\",[]],[\"invoke\",464,0,\"as-global.set-value\",[]],[\"invoke\",465,0,\"as-load-operand\",[]],[\"invoke\",467,0,\"as-unary-operand\",[]],[\"invoke\",468,0,\"as-binary-operand\",[]],[\"invoke\",469,0,\"as-test-operand\",[]],[\"invoke\",470,0,\"as-compare-operand\",[]],[\"invoke\",471,0,\"as-binary-operands\",[]],[\"invoke\",472,0,\"as-compare-operands\",[]],[\"invoke\",473,0,\"as-mixed-operands\",[]],[\"invoke\",475,0,\"break-bare\",[]],[\"invoke\",476,0,\"break-value\",[]],[\"invoke\",477,0,\"break-multi-value\",[]],[\"invoke\",480,0,\"break-repeated\",[]],[\"invoke\",481,0,\"break-inner\",[]],[\"invoke\",483,0,\"param\",[]],[\"invoke\",484,0,\"params\",[]],[\"invoke\",485,0,\"params-id\",[]],[\"invoke\",486,0,\"param-break\",[]],[\"invoke\",487,0,\"params-break\",[]],[\"invoke\",488,0,\"params-id-break\",[]],[\"invoke\",490,0,\"effects\",[]],[\"invoke\",492,0,\"while\",[\"i64:0\"]],[\"invoke\",493,0,\"while\",[\"i64:1\"]],[\"invoke\",494,0,\"while\",[\"i64:2\"]],[\"invoke\",495,0,\"while\",[\"i64:3\"]],[\"invoke\",496,0,\"while\",[\"i64:5\"]],[\"invoke\",497,0,\"while\",[\"i64:20\"]],[\"invoke\",499,0,\"for\",[\"i64:0\"]],[\"invoke\",500,0,\"for\",[\"i64:1\"]],[\"invoke\",501,0,\"for\",[\"i64:2\"]],[\"invoke\",502,0,\"for\",[\"i64:3\"]],[\"invoke\",503,0,\"for\",[\"i64:5\"]],[\"invoke\",504,0,\"for\",[\"i64:20\"]],[\"invoke\",506,0,\"nesting\",[\"f32:0\",\"f32:1088421888\"]],[\"invoke\",507,0,\"nesting\",[\"f32:1088421888\",\"f32:0\"]],[\"invoke\",508,0,\"nesting\",[\"f32:1065353216\",\"f32:1065353216\"]],[\"invoke\",509,0,\"nesting\",[\"f32:1065353216\",\"f32:1073741824\"]],[\"invoke\",510,0,\"nesting\",[\"f32:1065353216\",\"f32:1077936128\"]],[\"invoke\",511,0,\"nesting\",[\"f32:1065353216\",\"f32:1082130432\"]],[\"invoke\",512,0,\"nesting\",[\"f32:1065353216\",\"f32:1120403456\"]],[\"invoke\",513,0,\"nesting\",[\"f32:1065353216\",\"f32:1120534528\"]],[\"invoke\",514,0,\"nesting\",[\"f32:1073741824\",\"f32:1065353216\"]],[\"invoke\",515,0,\"nesting\",[\"f32:1077936128\",\"f32:1065353216\"]],[\"invoke\",516,0,\"nesting\",[\"f32:1092616192\",\"f32:1065353216\"]],[\"invoke\",517,0,\"nesting\",[\"f32:1073741824\",\"f32:1073741824\"]],[\"invoke\",518,0,\"nesting\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",519,0,\"nesting\",[\"f32:1088421888\",\"f32:1082130432\"]],[\"invoke\",520,0,\"nesting\",[\"f32:1088421888\",\"f32:1120403456\"]],[\"invoke\",521,0,\"nesting\",[\"f32:1088421888\",\"f32:1120534528\"]],[\"invoke\",523,0,\"type-use\",[]],[\"file\",\"local_get.wast\"],[\"module\",3,20],[\"invoke\",109,0,\"type-local-i32\",[]],[\"invoke\",110,0,\"type-local-i64\",[]],[\"invoke\",111,0,\"type-local-f32\",[]],[\"invoke\",112,0,\"type-local-f64\",[]],[\"invoke\",114,0,\"type-param-i32\",[\"i32:2\"]],[\"invoke\",115,0,\"type-param-i64\",[\"i64:3\"]],[\"invoke\",116,0,\"type-param-f32\",[\"f32:1082969293\"]],[\"invoke\",117,0,\"type-param-f64\",[\"f64:4617878467915022336\"]],[\"invoke\",119,0,\"as-block-value\",[\"i32:6\"]],[\"invoke\",120,0,\"as-loop-value\",[\"i32:7\"]],[\"invoke\",122,0,\"as-br-value\",[\"i32:8\"]],[\"invoke\",123,0,\"as-br_if-value\",[\"i32:9\"]],[\"invoke\",124,0,\"as-br_if-value-cond\",[\"i32:10\"]],[\"invoke\",125,0,\"as-br_table-value\",[\"i32:1\"]],[\"invoke\",127,0,\"as-return-value\",[\"i32:0\"]],[\"invoke\",129,0,\"as-if-then\",[\"i32:1\"]],[\"invoke\",130,0,\"as-if-else\",[\"i32:0\"]],[\"invoke\",133,0,\"type-mixed\",[\"i64:1\",\"f32:1074580685\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"invoke\",139,0,\"read\",[\"i64:1\",\"f32:1073741824\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"file\",\"local_set.wast\"],[\"module\",3,21],[\"invoke\",107,0,\"type-local-i32\",[]],[\"invoke\",108,0,\"type-local-i64\",[]],[\"invoke\",109,0,\"type-local-f32\",[]],[\"invoke\",110,0,\"type-local-f64\",[]],[\"invoke\",112,0,\"type-param-i32\",[\"i32:2\"]],[\"invoke\",113,0,\"type-param-i64\",[\"i64:3\"]],[\"invoke\",114,0,\"type-param-f32\",[\"f32:1082969293\"]],[\"invoke\",115,0,\"type-param-f64\",[\"f64:4617878467915022336\"]],[\"invoke\",117,0,\"as-block-value\",[\"i32:0\"]],[\"invoke\",118,0,\"as-loop-value\",[\"i32:0\"]],[\"invoke\",120,0,\"as-br-value\",[\"i32:0\"]],[\"invoke\",121,0,\"as-br_if-value\",[\"i32:0\"]],[\"invoke\",122,0,\"as-br_if-value-cond\",[\"i32:0\"]],[\"invoke\",123,0,\"as-br_table-value\",[\"i32:0\"]],[\"invoke\",125,0,\"as-return-value\",[\"i32:0\"]],[\"invoke\",127,0,\"as-if-then\",[\"i32:1\"]],[\"invoke\",128,0,\"as-if-else\",[\"i32:0\"]],[\"invoke\",131,0,\"type-mixed\",[\"i64:1\",\"f32:1074580685\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"invoke\",137,0,\"write\",[\"i64:1\",\"f32:1073741824\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"file\",\"local_tee.wast\"],[\"module\",3,22],[\"invoke\",280,0,\"type-local-i32\",[]],[\"invoke\",281,0,\"type-local-i64\",[]],[\"invoke\",282,0,\"type-local-f32\",[]],[\"invoke\",283,0,\"type-local-f64\",[]],[\"invoke\",285,0,\"type-param-i32\",[\"i32:2\"]],[\"invoke\",286,0,\"type-param-i64\",[\"i64:3\"]],[\"invoke\",287,0,\"type-param-f32\",[\"f32:1082969293\"]],[\"invoke\",288,0,\"type-param-f64\",[\"f64:4617878467915022336\"]],[\"invoke\",290,0,\"as-block-first\",[\"i32:0\"]],[\"invoke\",291,0,\"as-block-mid\",[\"i32:0\"]],[\"invoke\",292,0,\"as-block-last\",[\"i32:0\"]],[\"invoke\",294,0,\"as-loop-first\",[\"i32:0\"]],[\"invoke\",295,0,\"as-loop-mid\",[\"i32:0\"]],[\"invoke\",296,0,\"as-loop-last\",[\"i32:0\"]],[\"invoke\",298,0,\"as-br-value\",[\"i32:0\"]],[\"invoke\",300,0,\"as-br_if-cond\",[\"i32:0\"]],[\"invoke\",301,0,\"as-br_if-value\",[\"i32:0\"]],[\"invoke\",302,0,\"as-br_if-value-cond\",[\"i32:0\"]],[\"invoke\",304,0,\"as-br_table-index\",[\"i32:0\"]],[\"invoke\",305,0,\"as-br_table-value\",[\"i32:0\"]],[\"invoke\",306,0,\"as-br_table-value-index\",[\"i32:0\"]],[\"invoke\",308,0,\"as-return-value\",[\"i32:0\"]],[\"invoke\",310,0,\"as-if-cond\",[\"i32:0\"]],[\"invoke\",311,0,\"as-if-then\",[\"i32:1\"]],[\"invoke\",312,0,\"as-if-else\",[\"i32:0\"]],[\"invoke\",314,0,\"as-select-first\",[\"i32:0\",\"i32:1\"]],[\"invoke\",315,0,\"as-select-second\",[\"i32:0\",\"i32:0\"]],[\"invoke\",316,0,\"as-select-cond\",[\"i32:0\"]],[\"invoke\",318,0,\"as-call-first\",[\"i32:0\"]],[\"invoke\",319,0,\"as-call-mid\",[\"i32:0\"]],[\"invoke\",320,0,\"as-call-last\",[\"i32:0\"]],[\"invoke\",322,0,\"as-call_indirect-first\",[\"i32:0\"]],[\"invoke\",323,0,\"as-call_indirect-mid\",[\"i32:0\"]],[\"invoke\",324,0,\"as-call_indirect-last\",[\"i32:0\"]],[\"invoke\",325,0,\"as-call_indirect-index\",[\"i32:0\"]],[\"invoke\",327,0,\"as-local.set-value\",[]],[\"invoke\",328,0,\"as-local.tee-value\",[\"i32:0\"]],[\"invoke\",329,0,\"as-global.set-value\",[]],[\"invoke\",331,0,\"as-load-address\",[\"i32:0\"]],[\"invoke\",332,0,\"as-loadN-address\",[\"i32:0\"]],[\"invoke\",333,0,\"as-store-address\",[\"i32:0\"]],[\"invoke\",334,0,\"as-store-value\",[\"i32:0\"]],[\"invoke\",335,0,\"as-storeN-address\",[\"i32:0\"]],[\"invoke\",336,0,\"as-storeN-value\",[\"i32:0\"]],[\"invoke\",338,0,\"as-unary-operand\",[\"f32:0\"]],[\"invoke\",339,0,\"as-binary-left\",[\"i32:0\"]],[\"invoke\",340,0,\"as-binary-right\",[\"i32:0\"]],[\"invoke\",341,0,\"as-test-operand\",[\"i32:0\"]],[\"invoke\",342,0,\"as-compare-left\",[\"i32:0\"]],[\"invoke\",343,0,\"as-compare-right\",[\"i32:0\"]],[\"invoke\",344,0,\"as-convert-operand\",[\"i64:0\"]],[\"invoke\",345,0,\"as-memory.grow-size\",[\"i32:0\"]],[\"invoke\",348,0,\"type-mixed\",[\"i64:1\",\"f32:1074580685\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"invoke\",354,0,\"write\",[\"i64:1\",\"f32:1073741824\",\"f64:4614613358185178726\",\"i32:4\",\"i32:5\"]],[\"invoke\",361,0,\"result\",[\"i64:18446744073709551615\",\"f32:3221225472\",\"f64:13837985395039954534\",\"i32:4294967292\",\"i32:4294967291\"]],[\"file\",\"nop.wast\"],[\"module\",3,23],[\"invoke\",306,0,\"as-func-first\",[]],[\"invoke\",307,0,\"as-func-mid\",[]],[\"invoke\",308,0,\"as-func-last\",[]],[\"invoke\",309,0,\"as-func-everywhere\",[]],[\"invoke\",311,0,\"as-drop-first\",[\"i32:0\"]],[\"invoke\",312,0,\"as-drop-last\",[\"i32:0\"]],[\"invoke\",313,0,\"as-drop-everywhere\",[\"i32:0\"]],[\"invoke\",315,0,\"as-select-first\",[\"i32:3\"]],[\"invoke\",316,0,\"as-select-mid1\",[\"i32:3\"]],[\"invoke\",317,0,\"as-select-mid2\",[\"i32:3\"]],[\"invoke\",318,0,\"as-select-last\",[\"i32:3\"]],[\"invoke\",319,0,\"as-select-everywhere\",[\"i32:3\"]],[\"invoke\",321,0,\"as-block-first\",[]],[\"invoke\",322,0,\"as-block-mid\",[]],[\"invoke\",323,0,\"as-block-last\",[]],[\"invoke\",324,0,\"as-block-everywhere\",[]],[\"invoke\",326,0,\"as-loop-first\",[]],[\"invoke\",327,0,\"as-loop-mid\",[]],[\"invoke\",328,0,\"as-loop-last\",[]],[\"invoke\",329,0,\"as-loop-everywhere\",[]],[\"invoke\",331,0,\"as-if-condition\",[\"i32:0\"]],[\"invoke\",332,0,\"as-if-condition\",[\"i32:4294967295\"]],[\"invoke\",333,0,\"as-if-then\",[\"i32:0\"]],[\"invoke\",334,0,\"as-if-then\",[\"i32:4\"]],[\"invoke\",335,0,\"as-if-else\",[\"i32:0\"]],[\"invoke\",336,0,\"as-if-else\",[\"i32:3\"]],[\"invoke\",338,0,\"as-br-first\",[\"i32:5\"]],[\"invoke\",339,0,\"as-br-last\",[\"i32:6\"]],[\"invoke\",340,0,\"as-br-everywhere\",[\"i32:7\"]],[\"invoke\",342,0,\"as-br_if-first\",[\"i32:4\"]],[\"invoke\",343,0,\"as-br_if-mid\",[\"i32:5\"]],[\"invoke\",344,0,\"as-br_if-last\",[\"i32:6\"]],[\"invoke\",345,0,\"as-br_if-everywhere\",[\"i32:7\"]],[\"invoke\",347,0,\"as-br_table-first\",[\"i32:4\"]],[\"invoke\",348,0,\"as-br_table-mid\",[\"i32:5\"]],[\"invoke\",349,0,\"as-br_table-last\",[\"i32:6\"]],[\"invoke\",350,0,\"as-br_table-everywhere\",[\"i32:7\"]],[\"invoke\",352,0,\"as-return-first\",[\"i32:5\"]],[\"invoke\",353,0,\"as-return-last\",[\"i32:6\"]],[\"invoke\",354,0,\"as-return-everywhere\",[\"i32:7\"]],[\"invoke\",356,0,\"as-call-first\",[\"i32:3\",\"i32:1\",\"i32:2\"]],[\"invoke\",357,0,\"as-call-mid1\",[\"i32:3\",\"i32:1\",\"i32:2\"]],[\"invoke\",358,0,\"as-call-mid2\",[\"i32:0\",\"i32:3\",\"i32:1\"]],[\"invoke\",359,0,\"as-call-last\",[\"i32:10\",\"i32:9\",\"i32:4294967295\"]],[\"invoke\",360,0,\"as-call-everywhere\",[\"i32:2\",\"i32:1\",\"i32:5\"]],[\"invoke\",362,0,\"as-unary-first\",[\"i32:30\"]],[\"invoke\",363,0,\"as-unary-last\",[\"i32:30\"]],[\"invoke\",364,0,\"as-unary-everywhere\",[\"i32:12\"]],[\"invoke\",366,0,\"as-binary-first\",[\"i32:3\"]],[\"invoke\",367,0,\"as-binary-mid\",[\"i32:3\"]],[\"invoke\",368,0,\"as-binary-last\",[\"i32:3\"]],[\"invoke\",369,0,\"as-binary-everywhere\",[\"i32:3\"]],[\"invoke\",371,0,\"as-test-first\",[\"i32:0\"]],[\"invoke\",372,0,\"as-test-last\",[\"i32:0\"]],[\"invoke\",373,0,\"as-test-everywhere\",[\"i32:0\"]],[\"invoke\",375,0,\"as-compare-first\",[\"i32:3\"]],[\"invoke\",376,0,\"as-compare-mid\",[\"i32:3\"]],[\"invoke\",377,0,\"as-compare-last\",[\"i32:3\"]],[\"invoke\",378,0,\"as-compare-everywhere\",[\"i32:3\"]],[\"invoke\",380,0,\"as-memory.grow-first\",[\"i32:0\"]],[\"invoke\",381,0,\"as-memory.grow-last\",[\"i32:2\"]],[\"invoke\",382,0,\"as-memory.grow-everywhere\",[\"i32:12\"]],[\"invoke\",384,0,\"as-call_indirect-first\",[]],[\"invoke\",385,0,\"as-call_indirect-mid1\",[]],[\"invoke\",386,0,\"as-call_indirect-mid2\",[]],[\"invoke\",387,0,\"as-call_indirect-last\",[]],[\"invoke\",388,0,\"as-call_indirect-everywhere\",[]],[\"invoke\",390,0,\"as-local.set-first\",[\"i32:1\"]],[\"invoke\",391,0,\"as-local.set-last\",[\"i32:1\"]],[\"invoke\",392,0,\"as-local.set-everywhere\",[\"i32:1\"]],[\"invoke\",394,0,\"as-local.tee-first\",[\"i32:1\"]],[\"invoke\",395,0,\"as-local.tee-last\",[\"i32:1\"]],[\"invoke\",396,0,\"as-local.tee-everywhere\",[\"i32:1\"]],[\"invoke\",398,0,\"as-global.set-first\",[]],[\"invoke\",399,0,\"as-global.set-last\",[]],[\"invoke\",400,0,\"as-global.set-everywhere\",[]],[\"invoke\",402,0,\"as-load-first\",[\"i32:100\"]],[\"invoke\",403,0,\"as-load-last\",[\"i32:100\"]],[\"invoke\",404,0,\"as-load-everywhere\",[\"i32:100\"]],[\"invoke\",406,0,\"as-store-first\",[\"i32:0\",\"i32:1\"]],[\"invoke\",407,0,\"as-store-mid\",[\"i32:0\",\"i32:2\"]],[\"invoke\",408,0,\"as-store-last\",[\"i32:0\",\"i32:3\"]],[\"invoke\",409,0,\"as-store-everywhere\",[\"i32:0\",\"i32:4\"]],[\"file\",\"return.wast\"],[\"module\",3,24],[\"invoke\",224,0,\"type-i32\",[]],[\"invoke\",225,0,\"type-i64\",[]],[\"invoke\",226,0,\"type-f32\",[]],[\"invoke\",227,0,\"type-f64\",[]],[\"invoke\",229,0,\"type-i32-value\",[]],[\"invoke\",230,0,\"type-i64-value\",[]],[\"invoke\",231,0,\"type-f32-value\",[]],[\"invoke\",232,0,\"type-f64-value\",[]],[\"invoke\",234,0,\"nullary\",[]],[\"invoke\",235,0,\"unary\",[]],[\"invoke\",237,0,\"as-func-first\",[]],[\"invoke\",238,0,\"as-func-mid\",[]],[\"invoke\",239,0,\"as-func-last\",[]],[\"invoke\",240,0,\"as-func-value\",[]],[\"invoke\",242,0,\"as-block-first\",[]],[\"invoke\",243,0,\"as-block-mid\",[]],[\"invoke\",244,0,\"as-block-last\",[]],[\"invoke\",245,0,\"as-block-value\",[]],[\"invoke\",247,0,\"as-loop-first\",[]],[\"invoke\",248,0,\"as-loop-mid\",[]],[\"invoke\",249,0,\"as-loop-last\",[]],[\"invoke\",251,0,\"as-br-value\",[]],[\"invoke\",253,0,\"as-br_if-cond\",[]],[\"invoke\",254,0,\"as-br_if-value\",[]],[\"invoke\",255,0,\"as-br_if-value-cond\",[]],[\"invoke\",257,0,\"as-br_table-index\",[]],[\"invoke\",258,0,\"as-br_table-value\",[]],[\"invoke\",259,0,\"as-br_table-value-index\",[]],[\"invoke\",261,0,\"as-return-value\",[]],[\"invoke\",263,0,\"as-if-cond\",[]],[\"invoke\",264,0,\"as-if-then\",[\"i32:1\",\"i32:6\"]],[\"invoke\",265,0,\"as-if-then\",[\"i32:0\",\"i32:6\"]],[\"invoke\",266,0,\"as-if-else\",[\"i32:0\",\"i32:6\"]],[\"invoke\",267,0,\"as-if-else\",[\"i32:1\",\"i32:6\"]],[\"invoke\",269,0,\"as-select-first\",[\"i32:0\",\"i32:6\"]],[\"invoke\",270,0,\"as-select-first\",[\"i32:1\",\"i32:6\"]],[\"invoke\",271,0,\"as-select-second\",[\"i32:0\",\"i32:6\"]],[\"invoke\",272,0,\"as-select-second\",[\"i32:1\",\"i32:6\"]],[\"invoke\",273,0,\"as-select-cond\",[]],[\"invoke\",275,0,\"as-call-first\",[]],[\"invoke\",276,0,\"as-call-mid\",[]],[\"invoke\",277,0,\"as-call-last\",[]],[\"invoke\",279,0,\"as-call_indirect-func\",[]],[\"invoke\",280,0,\"as-call_indirect-first\",[]],[\"invoke\",281,0,\"as-call_indirect-mid\",[]],[\"invoke\",282,0,\"as-call_indirect-last\",[]],[\"invoke\",284,0,\"as-local.set-value\",[]],[\"invoke\",285,0,\"as-local.tee-value\",[]],[\"invoke\",286,0,\"as-global.set-value\",[]],[\"invoke\",288,0,\"as-load-address\",[]],[\"invoke\",289,0,\"as-loadN-address\",[]],[\"invoke\",291,0,\"as-store-address\",[]],[\"invoke\",292,0,\"as-store-value\",[]],[\"invoke\",293,0,\"as-storeN-address\",[]],[\"invoke\",294,0,\"as-storeN-value\",[]],[\"invoke\",296,0,\"as-unary-operand\",[]],[\"invoke\",298,0,\"as-binary-left\",[]],[\"invoke\",299,0,\"as-binary-right\",[]],[\"invoke\",301,0,\"as-test-operand\",[]],[\"invoke\",303,0,\"as-compare-left\",[]],[\"invoke\",304,0,\"as-compare-right\",[]],[\"invoke\",306,0,\"as-convert-operand\",[]],[\"invoke\",308,0,\"as-memory.grow-size\",[]],[\"file\",\"select.wast\"],[\"module\",1,25],[\"invoke\",183,0,\"select-i32\",[\"i32:1\",\"i32:2\",\"i32:1\"]],[\"invoke\",184,0,\"select-i64\",[\"i64:2\",\"i64:1\",\"i32:1\"]],[\"invoke\",185,0,\"select-f32\",[\"f32:1065353216\",\"f32:1073741824\",\"i32:1\"]],[\"invoke\",186,0,\"select-f64\",[\"f64:4607182418800017408\",\"f64:4611686018427387904\",\"i32:1\"]],[\"invoke\",188,0,\"select-i32\",[\"i32:1\",\"i32:2\",\"i32:0\"]],[\"invoke\",189,0,\"select-i32\",[\"i32:2\",\"i32:1\",\"i32:0\"]],[\"invoke\",190,0,\"select-i64\",[\"i64:2\",\"i64:1\",\"i32:4294967295\"]],[\"invoke\",191,0,\"select-i64\",[\"i64:2\",\"i64:1\",\"i32:4042322160\"]],[\"invoke\",193,0,\"select-f32\",[\"f32:2143289344\",\"f32:1065353216\",\"i32:1\"]],[\"invoke\",195,0,\"select-f32\",[\"f32:2143289344\",\"f32:1065353216\",\"i32:0\"]],[\"invoke\",197,0,\"select-f32\",[\"f32:1073741824\",\"f32:2143289344\",\"i32:1\"]],[\"invoke\",199,0,\"select-f32\",[\"f32:1073741824\",\"f32:2143289344\",\"i32:0\"]],[\"invoke\",202,0,\"select-f64\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\",\"i32:1\"]],[\"invoke\",204,0,\"select-f64\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\",\"i32:0\"]],[\"invoke\",206,0,\"select-f64\",[\"f64:4611686018427387904\",\"f64:9221120237041090560\",\"i32:1\"]],[\"invoke\",208,0,\"select-f64\",[\"f64:4611686018427387904\",\"f64:9221120237041090560\",\"i32:0\"]],[\"invoke\",211,0,\"select-i32-t\",[\"i32:1\",\"i32:2\",\"i32:1\"]],[\"invoke\",212,0,\"select-i64-t\",[\"i64:2\",\"i64:1\",\"i32:1\"]],[\"invoke\",213,0,\"select-f32-t\",[\"f32:1065353216\",\"f32:1073741824\",\"i32:1\"]],[\"invoke\",214,0,\"select-f64-t\",[\"f64:4607182418800017408\",\"f64:4611686018427387904\",\"i32:1\"]],[\"invoke\",215,0,\"select-funcref\",[\"funcref:null\",\"funcref:null\",\"i32:1\"]],[\"invoke\",216,0,\"select-externref\",[\"externref:1\",\"externref:2\",\"i32:1\"]],[\"invoke\",218,0,\"select-i32-t\",[\"i32:1\",\"i32:2\",\"i32:0\"]],[\"invoke\",219,0,\"select-i32-t\",[\"i32:2\",\"i32:1\",\"i32:0\"]],[\"invoke\",220,0,\"select-i64-t\",[\"i64:2\",\"i64:1\",\"i32:4294967295\"]],[\"invoke\",221,0,\"select-i64-t\",[\"i64:2\",\"i64:1\",\"i32:4042322160\"]],[\"invoke\",222,0,\"select-externref\",[\"externref:1\",\"externref:2\",\"i32:0\"]],[\"invoke\",223,0,\"select-externref\",[\"externref:2\",\"externref:1\",\"i32:0\"]],[\"invoke\",225,0,\"select-f32-t\",[\"f32:2143289344\",\"f32:1065353216\",\"i32:1\"]],[\"invoke\",227,0,\"select-f32-t\",[\"f32:2143289344\",\"f32:1065353216\",\"i32:0\"]],[\"invoke\",229,0,\"select-f32-t\",[\"f32:1073741824\",\"f32:2143289344\",\"i32:1\"]],[\"invoke\",231,0,\"select-f32-t\",[\"f32:1073741824\",\"f32:2143289344\",\"i32:0\"]],[\"invoke\",234,0,\"select-f64-t\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\",\"i32:1\"]],[\"invoke\",236,0,\"select-f64-t\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\",\"i32:0\"]],[\"invoke\",238,0,\"select-f64-t\",[\"f64:4611686018427387904\",\"f64:9221120237041090560\",\"i32:1\"]],[\"invoke\",240,0,\"select-f64-t\",[\"f64:4611686018427387904\",\"f64:9221120237041090560\",\"i32:0\"]],[\"invoke\",243,0,\"as-select-first\",[\"i32:0\"]],[\"invoke\",244,0,\"as-select-first\",[\"i32:1\"]],[\"invoke\",245,0,\"as-select-mid\",[\"i32:0\"]],[\"invoke\",246,0,\"as-select-mid\",[\"i32:1\"]],[\"invoke\",247,0,\"as-select-last\",[\"i32:0\"]],[\"invoke\",248,0,\"as-select-last\",[\"i32:1\"]],[\"invoke\",250,0,\"as-loop-first\",[\"i32:0\"]],[\"invoke\",251,0,\"as-loop-first\",[\"i32:1\"]],[\"invoke\",252,0,\"as-loop-mid\",[\"i32:0\"]],[\"invoke\",253,0,\"as-loop-mid\",[\"i32:1\"]],[\"invoke\",254,0,\"as-loop-last\",[\"i32:0\"]],[\"invoke\",255,0,\"as-loop-last\",[\"i32:1\"]],[\"invoke\",257,0,\"as-if-condition\",[\"i32:0\"]],[\"invoke\",258,0,\"as-if-condition\",[\"i32:1\"]],[\"invoke\",259,0,\"as-if-then\",[\"i32:0\"]],[\"invoke\",260,0,\"as-if-then\",[\"i32:1\"]],[\"invoke\",261,0,\"as-if-else\",[\"i32:0\"]],[\"invoke\",262,0,\"as-if-else\",[\"i32:1\"]],[\"invoke\",264,0,\"as-br_if-first\",[\"i32:0\"]],[\"invoke\",265,0,\"as-br_if-first\",[\"i32:1\"]],[\"invoke\",266,0,\"as-br_if-last\",[\"i32:0\"]],[\"invoke\",267,0,\"as-br_if-last\",[\"i32:1\"]],[\"invoke\",269,0,\"as-br_table-first\",[\"i32:0\"]],[\"invoke\",270,0,\"as-br_table-first\",[\"i32:1\"]],[\"invoke\",271,0,\"as-br_table-last\",[\"i32:0\"]],[\"invoke\",272,0,\"as-br_table-last\",[\"i32:1\"]],[\"invoke\",274,0,\"as-call_indirect-first\",[\"i32:0\"]],[\"invoke\",275,0,\"as-call_indirect-first\",[\"i32:1\"]],[\"invoke\",276,0,\"as-call_indirect-mid\",[\"i32:0\"]],[\"invoke\",277,0,\"as-call_indirect-mid\",[\"i32:1\"]],[\"invoke\",278,0,\"as-call_indirect-last\",[\"i32:0\"]],[\"invoke\",279,0,\"as-call_indirect-last\",[\"i32:1\"]],[\"invoke\",281,0,\"as-store-first\",[\"i32:0\"]],[\"invoke\",282,0,\"as-store-first\",[\"i32:1\"]],[\"invoke\",283,0,\"as-store-last\",[\"i32:0\"]],[\"invoke\",284,0,\"as-store-last\",[\"i32:1\"]],[\"invoke\",286,0,\"as-memory.grow-value\",[\"i32:0\"]],[\"invoke\",287,0,\"as-memory.grow-value\",[\"i32:1\"]],[\"invoke\",289,0,\"as-call-value\",[\"i32:0\"]],[\"invoke\",290,0,\"as-call-value\",[\"i32:1\"]],[\"invoke\",291,0,\"as-return-value\",[\"i32:0\"]],[\"invoke\",292,0,\"as-return-value\",[\"i32:1\"]],[\"invoke\",293,0,\"as-drop-operand\",[\"i32:0\"]],[\"invoke\",294,0,\"as-drop-operand\",[\"i32:1\"]],[\"invoke\",295,0,\"as-br-value\",[\"i32:0\"]],[\"invoke\",296,0,\"as-br-value\",[\"i32:1\"]],[\"invoke\",297,0,\"as-local.set-value\",[\"i32:0\"]],[\"invoke\",298,0,\"as-local.set-value\",[\"i32:1\"]],[\"invoke\",299,0,\"as-local.tee-value\",[\"i32:0\"]],[\"invoke\",300,0,\"as-local.tee-value\",[\"i32:1\"]],[\"invoke\",301,0,\"as-global.set-value\",[\"i32:0\"]],[\"invoke\",302,0,\"as-global.set-value\",[\"i32:1\"]],[\"invoke\",303,0,\"as-load-operand\",[\"i32:0\"]],[\"invoke\",304,0,\"as-load-operand\",[\"i32:1\"]],[\"invoke\",306,0,\"as-unary-operand\",[\"i32:0\"]],[\"invoke\",307,0,\"as-unary-operand\",[\"i32:1\"]],[\"invoke\",308,0,\"as-binary-operand\",[\"i32:0\"]],[\"invoke\",309,0,\"as-binary-operand\",[\"i32:1\"]],[\"invoke\",310,0,\"as-test-operand\",[\"i32:0\"]],[\"invoke\",311,0,\"as-test-operand\",[\"i32:1\"]],[\"invoke\",312,0,\"as-compare-left\",[\"i32:0\"]],[\"invoke\",313,0,\"as-compare-left\",[\"i32:1\"]],[\"invoke\",314,0,\"as-compare-right\",[\"i32:0\"]],[\"invoke\",315,0,\"as-compare-right\",[\"i32:1\"]],[\"invoke\",316,0,\"as-convert-operand\",[\"i32:0\"]],[\"invoke\",317,0,\"as-convert-operand\",[\"i32:1\"]],[\"module\",518,26],[\"file\",\"stack.wast\"],[\"module\",1,27],[\"invoke\",146,0,\"fac-expr\",[\"i64:25\"]],[\"invoke\",147,0,\"fac-stack\",[\"i64:25\"]],[\"invoke\",148,0,\"fac-mixed\",[\"i64:25\"]],[\"invoke\",150,0,\"not-quite-a-tree\",[]],[\"invoke\",151,0,\"not-quite-a-tree\",[]],[\"module\",156,28],[\"file\",\"switch.wast\"],[\"module\",1,29],[\"invoke\",120,0,\"stmt\",[\"i32:0\"]],[\"invoke\",121,0,\"stmt\",[\"i32:1\"]],[\"invoke\",122,0,\"stmt\",[\"i32:2\"]],[\"invoke\",123,0,\"stmt\",[\"i32:3\"]],[\"invoke\",124,0,\"stmt\",[\"i32:4\"]],[\"invoke\",125,0,\"stmt\",[\"i32:5\"]],[\"invoke\",126,0,\"stmt\",[\"i32:6\"]],[\"invoke\",127,0,\"stmt\",[\"i32:7\"]],[\"invoke\",128,0,\"stmt\",[\"i32:4294967286\"]],[\"invoke\",130,0,\"expr\",[\"i64:0\"]],[\"invoke\",131,0,\"expr\",[\"i64:1\"]],[\"invoke\",132,0,\"expr\",[\"i64:2\"]],[\"invoke\",133,0,\"expr\",[\"i64:3\"]],[\"invoke\",134,0,\"expr\",[\"i64:6\"]],[\"invoke\",135,0,\"expr\",[\"i64:7\"]],[\"invoke\",136,0,\"expr\",[\"i64:18446744073709551606\"]],[\"invoke\",138,0,\"arg\",[\"i32:0\"]],[\"invoke\",139,0,\"arg\",[\"i32:1\"]],[\"invoke\",140,0,\"arg\",[\"i32:2\"]],[\"invoke\",141,0,\"arg\",[\"i32:3\"]],[\"invoke\",142,0,\"arg\",[\"i32:4\"]],[\"invoke\",143,0,\"arg\",[\"i32:5\"]],[\"invoke\",144,0,\"arg\",[\"i32:6\"]],[\"invoke\",145,0,\"arg\",[\"i32:7\"]],[\"invoke\",146,0,\"arg\",[\"i32:8\"]],[\"invoke\",148,0,\"corner\",[]],[\"file\",\"unreachable.wast\"],[\"module\",3,30],[\"invoke\",221,0,\"type-i32\",[]],[\"invoke\",222,0,\"type-i64\",[]],[\"invoke\",223,0,\"type-f32\",[]],[\"invoke\",224,0,\"type-f64\",[]],[\"invoke\",226,0,\"as-func-first\",[]],[\"invoke\",227,0,\"as-func-mid\",[]],[\"invoke\",228,0,\"as-func-last\",[]],[\"invoke\",229,0,\"as-func-value\",[]],[\"invoke\",231,0,\"as-block-first\",[]],[\"invoke\",232,0,\"as-block-mid\",[]],[\"invoke\",233,0,\"as-block-last\",[]],[\"invoke\",234,0,\"as-block-value\",[]],[\"invoke\",235,0,\"as-block-broke\",[]],[\"invoke\",237,0,\"as-loop-first\",[]],[\"invoke\",238,0,\"as-loop-mid\",[]],[\"invoke\",239,0,\"as-loop-last\",[]],[\"invoke\",240,0,\"as-loop-broke\",[]],[\"invoke\",242,0,\"as-br-value\",[]],[\"invoke\",244,0,\"as-br_if-cond\",[]],[\"invoke\",245,0,\"as-br_if-value\",[]],[\"invoke\",246,0,\"as-br_if-value-cond\",[]],[\"invoke\",248,0,\"as-br_table-index\",[]],[\"invoke\",249,0,\"as-br_table-value\",[]],[\"invoke\",250,0,\"as-br_table-value-2\",[]],[\"invoke\",251,0,\"as-br_table-value-index\",[]],[\"invoke\",252,0,\"as-br_table-value-and-index\",[]],[\"invoke\",254,0,\"as-return-value\",[]],[\"invoke\",256,0,\"as-if-cond\",[]],[\"invoke\",257,0,\"as-if-then\",[\"i32:1\",\"i32:6\"]],[\"invoke\",258,0,\"as-if-then\",[\"i32:0\",\"i32:6\"]],[\"invoke\",259,0,\"as-if-else\",[\"i32:0\",\"i32:6\"]],[\"invoke\",260,0,\"as-if-else\",[\"i32:1\",\"i32:6\"]],[\"invoke\",261,0,\"as-if-then-no-else\",[\"i32:1\",\"i32:6\"]],[\"invoke\",262,0,\"as-if-then-no-else\",[\"i32:0\",\"i32:6\"]],[\"invoke\",264,0,\"as-select-first\",[\"i32:0\",\"i32:6\"]],[\"invoke\",265,0,\"as-select-first\",[\"i32:1\",\"i32:6\"]],[\"invoke\",266,0,\"as-select-second\",[\"i32:0\",\"i32:6\"]],[\"invoke\",267,0,\"as-select-second\",[\"i32:1\",\"i32:6\"]],[\"invoke\",268,0,\"as-select-cond\",[]],[\"invoke\",270,0,\"as-call-first\",[]],[\"invoke\",271,0,\"as-call-mid\",[]],[\"invoke\",272,0,\"as-call-last\",[]],[\"invoke\",274,0,\"as-call_indirect-func\",[]],[\"invoke\",275,0,\"as-call_indirect-first\",[]],[\"invoke\",276,0,\"as-call_indirect-mid\",[]],[\"invoke\",277,0,\"as-call_indirect-last\",[]],[\"invoke\",279,0,\"as-local.set-value\",[]],[\"invoke\",280,0,\"as-local.tee-value\",[]],[\"invoke\",281,0,\"as-global.set-value\",[]],[\"invoke\",283,0,\"as-load-address\",[]],[\"invoke\",284,0,\"as-loadN-address\",[]],[\"invoke\",286,0,\"as-store-address\",[]],[\"invoke\",287,0,\"as-store-value\",[]],[\"invoke\",288,0,\"as-storeN-address\",[]],[\"invoke\",289,0,\"as-storeN-value\",[]],[\"invoke\",291,0,\"as-unary-operand\",[]],[\"invoke\",293,0,\"as-binary-left\",[]],[\"invoke\",294,0,\"as-binary-right\",[]],[\"invoke\",296,0,\"as-test-operand\",[]],[\"invoke\",298,0,\"as-compare-left\",[]],[\"invoke\",299,0,\"as-compare-right\",[]],[\"invoke\",301,0,\"as-convert-operand\",[]],[\"invoke\",303,0,\"as-memory.grow-size\",[]],[\"file\",\"unwind.wast\"],[\"module\",3,31],[\"invoke\",212,0,\"func-unwind-by-unreachable\",[]],[\"invoke\",213,0,\"func-unwind-by-br\",[]],[\"invoke\",214,0,\"func-unwind-by-br-value\",[]],[\"invoke\",215,0,\"func-unwind-by-br_if\",[]],[\"invoke\",216,0,\"func-unwind-by-br_if-value\",[]],[\"invoke\",217,0,\"func-unwind-by-br_table\",[]],[\"invoke\",218,0,\"func-unwind-by-br_table-value\",[]],[\"invoke\",219,0,\"func-unwind-by-return\",[]],[\"invoke\",221,0,\"block-unwind-by-unreachable\",[]],[\"invoke\",222,0,\"block-unwind-by-br\",[]],[\"invoke\",223,0,\"block-unwind-by-br-value\",[]],[\"invoke\",224,0,\"block-unwind-by-br_if\",[]],[\"invoke\",225,0,\"block-unwind-by-br_if-value\",[]],[\"invoke\",226,0,\"block-unwind-by-br_table\",[]],[\"invoke\",227,0,\"block-unwind-by-br_table-value\",[]],[\"invoke\",228,0,\"block-unwind-by-return\",[]],[\"invoke\",230,0,\"block-nested-unwind-by-unreachable\",[]],[\"invoke\",231,0,\"block-nested-unwind-by-br\",[]],[\"invoke\",232,0,\"block-nested-unwind-by-br-value\",[]],[\"invoke\",233,0,\"block-nested-unwind-by-br_if\",[]],[\"invoke\",234,0,\"block-nested-unwind-by-br_if-value\",[]],[\"invoke\",235,0,\"block-nested-unwind-by-br_table\",[]],[\"invoke\",236,0,\"block-nested-unwind-by-br_table-value\",[]],[\"invoke\",237,0,\"block-nested-unwind-by-return\",[]],[\"invoke\",239,0,\"unary-after-unreachable\",[]],[\"invoke\",240,0,\"unary-after-br\",[]],[\"invoke\",241,0,\"unary-after-br_if\",[]],[\"invoke\",242,0,\"unary-after-br_table\",[]],[\"invoke\",243,0,\"unary-after-return\",[]],[\"invoke\",245,0,\"binary-after-unreachable\",[]],[\"invoke\",246,0,\"binary-after-br\",[]],[\"invoke\",247,0,\"binary-after-br_if\",[]],[\"invoke\",248,0,\"binary-after-br_table\",[]],[\"invoke\",249,0,\"binary-after-return\",[]],[\"invoke\",251,0,\"select-after-unreachable\",[]],[\"invoke\",252,0,\"select-after-br\",[]],[\"invoke\",253,0,\"select-after-br_if\",[]],[\"invoke\",254,0,\"select-after-br_table\",[]],[\"invoke\",255,0,\"select-after-return\",[]],[\"invoke\",257,0,\"block-value-after-unreachable\",[]],[\"invoke\",258,0,\"block-value-after-br\",[]],[\"invoke\",259,0,\"block-value-after-br_if\",[]],[\"invoke\",260,0,\"block-value-after-br_table\",[]],[\"invoke\",261,0,\"block-value-after-return\",[]],[\"invoke\",263,0,\"loop-value-after-unreachable\",[]],[\"invoke\",264,0,\"loop-value-after-br\",[]],[\"invoke\",265,0,\"loop-value-after-br_if\",[]],[\"invoke\",266,0,\"loop-value-after-br_table\",[]],[\"invoke\",267,0,\"loop-value-after-return\",[]],[\"file\",\"left-to-right.wast\"],[\"module\",1,32],[\"invoke\",181,0,\"i32_add\",[]],[\"invoke\",181,0,\"i64_add\",[]],[\"invoke\",182,0,\"i32_sub\",[]],[\"invoke\",182,0,\"i64_sub\",[]],[\"invoke\",183,0,\"i32_mul\",[]],[\"invoke\",183,0,\"i64_mul\",[]],[\"invoke\",184,0,\"i32_div_s\",[]],[\"invoke\",184,0,\"i64_div_s\",[]],[\"invoke\",185,0,\"i32_div_u\",[]],[\"invoke\",185,0,\"i64_div_u\",[]],[\"invoke\",186,0,\"i32_rem_s\",[]],[\"invoke\",186,0,\"i64_rem_s\",[]],[\"invoke\",187,0,\"i32_rem_u\",[]],[\"invoke\",187,0,\"i64_rem_u\",[]],[\"invoke\",188,0,\"i32_and\",[]],[\"invoke\",188,0,\"i64_and\",[]],[\"invoke\",189,0,\"i32_or\",[]],[\"invoke\",189,0,\"i64_or\",[]],[\"invoke\",190,0,\"i32_xor\",[]],[\"invoke\",190,0,\"i64_xor\",[]],[\"invoke\",191,0,\"i32_shl\",[]],[\"invoke\",191,0,\"i64_shl\",[]],[\"invoke\",192,0,\"i32_shr_u\",[]],[\"invoke\",192,0,\"i64_shr_u\",[]],[\"invoke\",193,0,\"i32_shr_s\",[]],[\"invoke\",193,0,\"i64_shr_s\",[]],[\"invoke\",194,0,\"i32_eq\",[]],[\"invoke\",194,0,\"i64_eq\",[]],[\"invoke\",195,0,\"i32_ne\",[]],[\"invoke\",195,0,\"i64_ne\",[]],[\"invoke\",196,0,\"i32_lt_s\",[]],[\"invoke\",196,0,\"i64_lt_s\",[]],[\"invoke\",197,0,\"i32_le_s\",[]],[\"invoke\",197,0,\"i64_le_s\",[]],[\"invoke\",198,0,\"i32_lt_u\",[]],[\"invoke\",198,0,\"i64_lt_u\",[]],[\"invoke\",199,0,\"i32_le_u\",[]],[\"invoke\",199,0,\"i64_le_u\",[]],[\"invoke\",200,0,\"i32_gt_s\",[]],[\"invoke\",200,0,\"i64_gt_s\",[]],[\"invoke\",201,0,\"i32_ge_s\",[]],[\"invoke\",201,0,\"i64_ge_s\",[]],[\"invoke\",202,0,\"i32_gt_u\",[]],[\"invoke\",202,0,\"i64_gt_u\",[]],[\"invoke\",203,0,\"i32_ge_u\",[]],[\"invoke\",203,0,\"i64_ge_u\",[]],[\"invoke\",204,0,\"i32_store\",[]],[\"invoke\",204,0,\"i64_store\",[]],[\"invoke\",205,0,\"i32_store8\",[]],[\"invoke\",205,0,\"i64_store8\",[]],[\"invoke\",206,0,\"i32_store16\",[]],[\"invoke\",206,0,\"i64_store16\",[]],[\"invoke\",207,0,\"i64_store32\",[]],[\"invoke\",208,0,\"i32_call\",[]],[\"invoke\",208,0,\"i64_call\",[]],[\"invoke\",209,0,\"i32_call_indirect\",[]],[\"invoke\",210,0,\"i64_call_indirect\",[]],[\"invoke\",211,0,\"i32_select\",[]],[\"invoke\",211,0,\"i64_select\",[]],[\"invoke\",213,0,\"f32_add\",[]],[\"invoke\",213,0,\"f64_add\",[]],[\"invoke\",214,0,\"f32_sub\",[]],[\"invoke\",214,0,\"f64_sub\",[]],[\"invoke\",215,0,\"f32_mul\",[]],[\"invoke\",215,0,\"f64_mul\",[]],[\"invoke\",216,0,\"f32_div\",[]],[\"invoke\",216,0,\"f64_div\",[]],[\"invoke\",217,0,\"f32_copysign\",[]],[\"invoke\",217,0,\"f64_copysign\",[]],[\"invoke\",218,0,\"f32_eq\",[]],[\"invoke\",218,0,\"f64_eq\",[]],[\"invoke\",219,0,\"f32_ne\",[]],[\"invoke\",219,0,\"f64_ne\",[]],[\"invoke\",220,0,\"f32_lt\",[]],[\"invoke\",220,0,\"f64_lt\",[]],[\"invoke\",221,0,\"f32_le\",[]],[\"invoke\",221,0,\"f64_le\",[]],[\"invoke\",222,0,\"f32_gt\",[]],[\"invoke\",222,0,\"f64_gt\",[]],[\"invoke\",223,0,\"f32_ge\",[]],[\"invoke\",223,0,\"f64_ge\",[]],[\"invoke\",224,0,\"f32_min\",[]],[\"invoke\",224,0,\"f64_min\",[]],[\"invoke\",225,0,\"f32_max\",[]],[\"invoke\",225,0,\"f64_max\",[]],[\"invoke\",226,0,\"f32_store\",[]],[\"invoke\",226,0,\"f64_store\",[]],[\"invoke\",227,0,\"f32_call\",[]],[\"invoke\",227,0,\"f64_call\",[]],[\"invoke\",228,0,\"f32_call_indirect\",[]],[\"invoke\",229,0,\"f64_call_indirect\",[]],[\"invoke\",230,0,\"f32_select\",[]],[\"invoke\",230,0,\"f64_select\",[]],[\"invoke\",232,0,\"br_if\",[]],[\"invoke\",233,0,\"br_table\",[]],[\"file\",\"global.wast\"],[\"module\",3,33],[\"invoke\",196,0,\"get-a\",[]],[\"invoke\",197,0,\"get-b\",[]],[\"invoke\",198,0,\"get-r\",[]],[\"invoke\",199,0,\"get-mr\",[]],[\"invoke\",200,0,\"get-x\",[]],[\"invoke\",201,0,\"get-y\",[]],[\"invoke\",202,0,\"get-z1\",[]],[\"invoke\",203,0,\"get-z2\",[]],[\"invoke\",205,0,\"get-3\",[]],[\"invoke\",206,0,\"get-4\",[]],[\"invoke\",207,0,\"get-7\",[]],[\"invoke\",208,0,\"get-8\",[]],[\"invoke\",210,0,\"set-x\",[\"i32:6\"]],[\"invoke\",211,0,\"set-y\",[\"i64:7\"]],[\"invoke\",213,0,\"set-7\",[\"f32:1090519040\"]],[\"invoke\",214,0,\"set-8\",[\"f64:4621256167635550208\"]],[\"invoke\",216,0,\"get-x\",[]],[\"invoke\",217,0,\"get-y\",[]],[\"invoke\",218,0,\"get-7\",[]],[\"invoke\",219,0,\"get-8\",[]],[\"invoke\",221,0,\"set-7\",[\"f32:1090519040\"]],[\"invoke\",222,0,\"set-8\",[\"f64:4621256167635550208\"]],[\"invoke\",223,0,\"set-mr\",[\"externref:10\"]],[\"invoke\",225,0,\"get-x\",[]],[\"invoke\",226,0,\"get-y\",[]],[\"invoke\",227,0,\"get-7\",[]],[\"invoke\",228,0,\"get-8\",[]],[\"invoke\",229,0,\"get-mr\",[]],[\"invoke\",231,0,\"as-select-first\",[]],[\"invoke\",232,0,\"as-select-mid\",[]],[\"invoke\",233,0,\"as-select-last\",[]],[\"invoke\",235,0,\"as-loop-first\",[]],[\"invoke\",236,0,\"as-loop-mid\",[]],[\"invoke\",237,0,\"as-loop-last\",[]],[\"invoke\",239,0,\"as-if-condition\",[]],[\"invoke\",240,0,\"as-if-then\",[]],[\"invoke\",241,0,\"as-if-else\",[]],[\"invoke\",243,0,\"as-br_if-first\",[]],[\"invoke\",244,0,\"as-br_if-last\",[]],[\"invoke\",246,0,\"as-br_table-first\",[]],[\"invoke\",247,0,\"as-br_table-last\",[]],[\"invoke\",249,0,\"as-call_indirect-first\",[]],[\"invoke\",250,0,\"as-call_indirect-mid\",[]],[\"invoke\",251,0,\"as-call_indirect-last\",[]],[\"invoke\",253,0,\"as-store-first\",[]],[\"invoke\",254,0,\"as-store-last\",[]],[\"invoke\",255,0,\"as-load-operand\",[]],[\"invoke\",256,0,\"as-memory.grow-value\",[]],[\"invoke\",258,0,\"as-call-value\",[]],[\"invoke\",260,0,\"as-return-value\",[]],[\"invoke\",261,0,\"as-drop-operand\",[]],[\"invoke\",262,0,\"as-br-value\",[]],[\"invoke\",264,0,\"as-local.set-value\",[\"i32:1\"]],[\"invoke\",265,0,\"as-local.tee-value\",[\"i32:1\"]],[\"invoke\",266,0,\"as-global.set-value\",[]],[\"invoke\",268,0,\"as-unary-operand\",[]],[\"invoke\",269,0,\"as-binary-operand\",[]],[\"invoke\",270,0,\"as-compare-operand\",[]],[\"module\",283,34],[\"module\",284,34],[\"module\",375,35],[\"module\",405,36],[\"file\",\"start.wast\"],[\"module\",21,37],[\"invoke\",45,0,\"get\",[]],[\"invoke\",46,0,\"inc\",[]],[\"invoke\",47,0,\"get\",[]],[\"invoke\",48,0,\"inc\",[]],[\"invoke\",49,0,\"get\",[]],[\"module\",51,37],[\"invoke\",74,0,\"get\",[]],[\"invoke\",75,0,\"inc\",[]],[\"invoke\",76,0,\"get\",[]],[\"invoke\",77,0,\"inc\",[]],[\"invoke\",78,0,\"get\",[]],[\"module\",80,38],[\"module\",86,39],[\"module\",92,40],[\"instantiate\",98,41]]"; diff --git a/tests/corpus/webassembly-spec-control/main.mjs b/tests/corpus/webassembly-spec-control/main.mjs new file mode 100644 index 000000000..2451a5a1c --- /dev/null +++ b/tests/corpus/webassembly-spec-control/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (26 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-spec-float/data.mjs b/tests/corpus/webassembly-spec-float/data.mjs new file mode 100644 index 000000000..814d702e3 --- /dev/null +++ b/tests/corpus/webassembly-spec-float/data.mjs @@ -0,0 +1,113 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * f32.wast, f64.wast, f32_cmp.wast, f64_cmp.wast, f32_bitwise.wast, f64_bitwise.wast, float_exprs.wast, float_literals.wast, float_misc.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABDAJgAn19AX1gAX0BfQMMCwAAAAABAAABAQEBB00LA2FkZAAAA3N1YgABA211bAACA2RpdgADBHNxcnQABANtaW4ABQNtYXgABgRjZWlsAAcFZmxvb3IACAV0cnVuYwAJB25lYXJlc3QACgpPCwcAIAAgAZILBwAgACABkwsHACAAIAGUCwcAIAAgAZULBQAgAJELBwAgACABlgsHACAAIAGXCwUAIACNCwUAIACOCwUAIACPCwUAIACQCw==", + "AGFzbQEAAAABDAJgAnx8AXxgAXwBfAMMCwAAAAABAAABAQEBB00LA2FkZAAAA3N1YgABA211bAACA2RpdgADBHNxcnQABANtaW4ABQNtYXgABgRjZWlsAAcFZmxvb3IACAV0cnVuYwAJB25lYXJlc3QACgpPCwcAIAAgAaALBwAgACABoQsHACAAIAGiCwcAIAAgAaMLBQAgAJ8LBwAgACABpAsHACAAIAGlCwUAIACbCwUAIACcCwUAIACdCwUAIACeCw==", + "AGFzbQEAAAABBwFgAn19AX8DBwYAAAAAAAAHHwYCZXEAAAJuZQABAmx0AAICbGUAAwJndAAEAmdlAAUKMQYHACAAIAFbCwcAIAAgAVwLBwAgACABXQsHACAAIAFfCwcAIAAgAV4LBwAgACABYAs=", + "AGFzbQEAAAABBwFgAnx8AX8DBwYAAAAAAAAHHwYCZXEAAAJuZQABAmx0AAICbGUAAwJndAAEAmdlAAUKMQYHACAAIAFhCwcAIAAgAWILBwAgACABYwsHACAAIAFlCwcAIAAgAWQLBwAgACABZgs=", + "AGFzbQEAAAABDAJgAX0BfWACfX0BfQMEAwAAAQcYAwNhYnMAAANuZWcAAQhjb3B5c2lnbgACChUDBQAgAIsLBQAgAIwLBwAgACABmAs=", + "AGFzbQEAAAABDAJgAXwBfGACfHwBfAMEAwAAAQcYAwNhYnMAAANuZWcAAQhjb3B5c2lnbgACChUDBQAgAJkLBQAgAJoLBwAgACABpgs=", + "AGFzbQEAAAABCAFgA3x8fAF8AwIBAAcWARJmNjQubm9fY29udHJhY3Rpb24AAAoMAQoAIAAgAaIgAqAL", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBxsCCmYzMi5ub19mbWEAAApmNjQubm9fZm1hAAEKFwIKACAAIAGUIAKSCwoAIAAgAaIgAqAL", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfYWRkX3plcm8AABRmNjQubm9fZm9sZF9hZGRfemVybwABChsCCgAgAEMAAAAAkgsOACAARAAAAAAAAAAAoAs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfemVyb19zdWIAABRmNjQubm9fZm9sZF96ZXJvX3N1YgABChsCCgBDAAAAACAAkwsOAEQAAAAAAAAAACAAoQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfc3ViX3plcm8AABRmNjQubm9fZm9sZF9zdWJfemVybwABChsCCgAgAEMAAAAAkwsOACAARAAAAAAAAAAAoQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbXVsX3plcm8AABRmNjQubm9fZm9sZF9tdWxfemVybwABChsCCgAgAEMAAAAAlAsOACAARAAAAAAAAAAAogs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfbXVsX29uZQAAE2Y2NC5ub19mb2xkX211bF9vbmUAAQobAgoAIABDAACAP5QLDgAgAEQAAAAAAADwP6IL", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfemVyb19kaXYAABRmNjQubm9fZm9sZF96ZXJvX2RpdgABChsCCgBDAAAAACAAlQsOAEQAAAAAAAAAACAAows=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfZGl2X29uZQAAE2Y2NC5ub19mb2xkX2Rpdl9vbmUAAQobAgoAIABDAACAP5ULDgAgAEQAAAAAAADwP6ML", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X25lZzEAABRmNjQubm9fZm9sZF9kaXZfbmVnMQABChsCCgAgAEMAAIC/lQsOACAARAAAAAAAAPC/ows=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbmVnMF9zdWIAABRmNjQubm9fZm9sZF9uZWcwX3N1YgABChsCCgBDAAAAgCAAkwsOAEQAAAAAAAAAgCAAoQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbmVnMV9tdWwAABRmNjQubm9fZm9sZF9uZWcxX211bAABChsCCgBDAACAvyAAlAsOAEQAAAAAAADwvyAAogs=", + "AGFzbQEAAAABCwJgAX0Bf2ABfAF/AwMCAAEHLQITZjMyLm5vX2ZvbGRfZXFfc2VsZgAAE2Y2NC5ub19mb2xkX2VxX3NlbGYAAQoRAgcAIAAgAFsLBwAgACAAYQs=", + "AGFzbQEAAAABCwJgAX0Bf2ABfAF/AwMCAAEHLQITZjMyLm5vX2ZvbGRfbmVfc2VsZgAAE2Y2NC5ub19mb2xkX25lX3NlbGYAAQoRAgcAIAAgAFwLBwAgACAAYgs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfc3ViX3NlbGYAABRmNjQubm9fZm9sZF9zdWJfc2VsZgABChECBwAgACAAkwsHACAAIAChCw==", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X3NlbGYAABRmNjQubm9fZm9sZF9kaXZfc2VsZgABChECBwAgACAAlQsHACAAIACjCw==", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHKQIRZjMyLm5vX2ZvbGRfZGl2XzMAABFmNjQubm9fZm9sZF9kaXZfMwABChsCCgAgAEMAAEBAlQsOACAARAAAAAAAAAhAows=", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABByECDWYzMi5ub19mYWN0b3IAAA1mNjQubm9fZmFjdG9yAAEKHQINACAAIAKUIAEgApSSCw0AIAAgAqIgASACoqAL", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBykCEWYzMi5ub19kaXN0cmlidXRlAAARZjY0Lm5vX2Rpc3RyaWJ1dGUAAQoXAgoAIAAgAZIgApQLCgAgACABoCACogs=", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBzMCFmYzMi5ub19yZWdyb3VwX2Rpdl9tdWwAABZmNjQubm9fcmVncm91cF9kaXZfbXVsAAEKFwIKACAAIAEgApWUCwoAIAAgASACo6IL", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBzMCFmYzMi5ub19yZWdyb3VwX211bF9kaXYAABZmNjQubm9fcmVncm91cF9tdWxfZGl2AAEKFwIKACAAIAGUIAKVCwoAIAAgAaIgAqML", + "AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHMwIWZjMyLm5vX3JlYXNzb2NpYXRlX2FkZAAAFmY2NC5ub19yZWFzc29jaWF0ZV9hZGQAAQodAg0AIAAgAZIgApIgA5ILDQAgACABoCACoCADoAs=", + "AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHMwIWZjMyLm5vX3JlYXNzb2NpYXRlX211bAAAFmY2NC5ub19yZWFzc29jaWF0ZV9tdWwAAQodAg0AIAAgAZQgApQgA5QLDQAgACABoiACoiADogs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHKQIRZjMyLm5vX2ZvbGRfZGl2XzAAABFmNjQubm9fZm9sZF9kaXZfMAABChsCCgAgAEMAAAAAlQsOACAARAAAAAAAAAAAows=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X25lZzAAABRmNjQubm9fZm9sZF9kaXZfbmVnMAABChsCCgAgAEMAAACAlQsOACAARAAAAAAAAACAows=", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcvAhRmMzIubm9fZm9sZF90b19oeXBvdAAAFGY2NC5ub19mb2xkX3RvX2h5cG90AAEKHwIOACAAIACUIAEgAZSSkQsOACAAIACiIAEgAaKgnws=", + "AGFzbQEAAAABBgFgAX0BfQMCAQAHIQEdZjMyLm5vX2FwcHJveGltYXRlX3JlY2lwcm9jYWwAAAoMAQoAQwAAgD8gAJUL", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHRAIiZjMyLm5vX2FwcHJveGltYXRlX3JlY2lwcm9jYWxfc3FydAAAG2Y2NC5ub19mdXNlX3JlY2lwcm9jYWxfc3FydAABCh0CCwBDAACAPyAAkZULDwBEAAAAAAAA8D8gAJ+jCw==", + "AGFzbQEAAAABBgFgAX0BfQMCAQAHJgEiZjMyLm5vX2FwcHJveGltYXRlX3NxcnRfcmVjaXByb2NhbAAACg0BCwBDAACAPyAAlZEL", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdRBBFpMzIubm9fZm9sZF9mMzJfcwAAEWkzMi5ub19mb2xkX2YzMl91AAERaTY0Lm5vX2ZvbGRfZjY0X3MAAhFpNjQubm9fZm9sZF9mNjRfdQADCh0EBgAgALKoCwYAIACzqQsGACAAubALBgAgALqxCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9hZGRfc3ViAAATZjY0Lm5vX2ZvbGRfYWRkX3N1YgABChcCCgAgACABkiABkwsKACAAIAGgIAGhCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9zdWJfYWRkAAATZjY0Lm5vX2ZvbGRfc3ViX2FkZAABChcCCgAgACABkyABkgsKACAAIAGhIAGgCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9tdWxfZGl2AAATZjY0Lm5vX2ZvbGRfbXVsX2RpdgABChcCCgAgACABlCABlQsKACAAIAGiIAGjCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9kaXZfbXVsAAATZjY0Lm5vX2ZvbGRfZGl2X211bAABChcCCgAgACABlSABlAsKACAAIAGjIAGiCw==", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHMQIVZjMyLm5vX2ZvbGRfZGl2Ml9tdWwyAAAVZjY0Lm5vX2ZvbGRfZGl2Ml9tdWwyAAEKKwIQACAAQwAAAECVQwAAAECUCxgAIABEAAAAAAAAAECjRAAAAAAAAABAogs=", + "AGFzbQEAAAABBgFgAXwBfAMCAQAHGgEWbm9fZm9sZF9kZW1vdGVfcHJvbW90ZQAACggBBgAgALa7Cw==", + "AGFzbQEAAAABBgFgAX0BfQMCAQAHGgEWbm9fZm9sZF9wcm9tb3RlX2RlbW90ZQAACggBBgAgALu2Cw==", + "AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfYWRkAAAcbm9fZGVtb3RlX21peGVkX2FkZF9jb21tdXRlZAABChUCCQAgACABu6C2CwkAIAC7IAGgtgs=", + "AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfc3ViAAAcbm9fZGVtb3RlX21peGVkX3N1Yl9jb21tdXRlZAABChUCCQAgACABu6G2CwkAIAC7IAGhtgs=", + "AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfbXVsAAAcbm9fZGVtb3RlX21peGVkX211bF9jb21tdXRlZAABChUCCQAgACABu6K2CwkAIAC7IAGitgs=", + "AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfZGl2AAAcbm9fZGVtb3RlX21peGVkX2Rpdl9jb21tdXRlZAABChUCCQAgACABu6O2CwkAIAC7IAGjtgs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AxEQAAAAAAEBAQEAAAAAAQEBAQfBBBAhZjMyLmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAAhZjMyLmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAEhZjMyLmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAIhZjMyLmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAMhZjY0LmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAQhZjY0LmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAUhZjY0LmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAYhZjY0LmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAchZjMyLmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAghZjMyLmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAkhZjMyLmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAohZjMyLmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAshZjY0Lmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAwhZjY0Lmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAA0hZjY0Lmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF91AA4hZjY0Lmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF91AA8KcRAGACAAqLILBgAgAKmyCwYAIACoswsGACAAqbMLBgAgAKq3CwYAIACrtwsGACAAqrgLBgAgAKu4CwYAIACutAsGACAAr7QLBgAgAK61CwYAIACvtQsGACAAsLkLBgAgALG5CwYAIACwugsGACAAsboL", + "AGFzbQEAAAABCwJgAn99AGABfwF9AwQDAAABBQQBAQEBBxYDBGluaXQAAANydW4AAQVjaGVjawACCjkDCQAgACABOAIACyUBAX8CQANAIAIgAioCACABlTgCACACQQRqIQIgAiAASQ0ACwsLBwAgACoCAAs=", + "AGFzbQEAAAABCwJgAn98AGABfwF8AwQDAAABBQQBAQEBBxYDBGluaXQAAANydW4AAQVjaGVjawACCjkDCQAgACABOQMACyUBAX8CQANAIAIgAisDACABozkDACACQQhqIQIgAiAASQ0ACwsLBwAgACsDAAs=", + "AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQdRCAdmMzIudWx0AAAHZjMyLnVsZQABB2YzMi51Z3QAAgdmMzIudWdlAAMHZjY0LnVsdAAEB2Y2NC51bGUABQdmNjQudWd0AAYHZjY0LnVnZQAHCkkICAAgACABYEULCAAgACABXkULCAAgACABX0ULCAAgACABXUULCAAgACABZkULCAAgACABZEULCAAgACABZUULCAAgACABY0UL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDCQgAAAAAAQEBAQfBAQgVZjMyLm5vX2ZvbGRfbHRfc2VsZWN0AAAVZjMyLm5vX2ZvbGRfbGVfc2VsZWN0AAEVZjMyLm5vX2ZvbGRfZ3Rfc2VsZWN0AAIVZjMyLm5vX2ZvbGRfZ2Vfc2VsZWN0AAMVZjY0Lm5vX2ZvbGRfbHRfc2VsZWN0AAQVZjY0Lm5vX2ZvbGRfbGVfc2VsZWN0AAUVZjY0Lm5vX2ZvbGRfZ3Rfc2VsZWN0AAYVZjY0Lm5vX2ZvbGRfZ2Vfc2VsZWN0AAcKaQgMACAAIAEgACABXRsLDAAgACABIAAgAV8bCwwAIAAgASAAIAFeGwsMACAAIAEgACABYBsLDAAgACABIAAgAWMbCwwAIAAgASAAIAFlGwsMACAAIAEgACABZBsLDAAgACABIAAgAWYbCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDCQgAAAAAAQEBAQehAQgRZjMyLm5vX2ZvbGRfbHRfaWYAABFmMzIubm9fZm9sZF9sZV9pZgABEWYzMi5ub19mb2xkX2d0X2lmAAIRZjMyLm5vX2ZvbGRfZ2VfaWYAAxFmNjQubm9fZm9sZF9sdF9pZgAEEWY2NC5ub19mb2xkX2xlX2lmAAURZjY0Lm5vX2ZvbGRfZ3RfaWYABhFmNjQubm9fZm9sZF9nZV9pZgAHCoEBCA8AIAAgAV0EfSAABSABCwsPACAAIAFfBH0gAAUgAQsLDwAgACABXgR9IAAFIAELCw8AIAAgAWAEfSAABSABCwsPACAAIAFjBHwgAAUgAQsLDwAgACABZQR8IAAFIAELCw8AIAAgAWQEfCAABSABCwsPACAAIAFmBHwgAAUgAQsL", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwkIAAAAAAEBAQEH+QEIHGYzMi5ub19mb2xkX2x0X3NlbGVjdF90b19hYnMAABxmMzIubm9fZm9sZF9sZV9zZWxlY3RfdG9fYWJzAAEcZjMyLm5vX2ZvbGRfZ3Rfc2VsZWN0X3RvX2FicwACHGYzMi5ub19mb2xkX2dlX3NlbGVjdF90b19hYnMAAxxmNjQubm9fZm9sZF9sdF9zZWxlY3RfdG9fYWJzAAQcZjY0Lm5vX2ZvbGRfbGVfc2VsZWN0X3RvX2FicwAFHGY2NC5ub19mb2xkX2d0X3NlbGVjdF90b19hYnMABhxmNjQubm9fZm9sZF9nZV9zZWxlY3RfdG9fYWJzAAcKmQEIEAAgAIwgACAAQwAAAABdGwsQACAAjCAAIABDAAAAgF8bCxAAIAAgAIwgAEMAAACAXhsLEAAgACAAjCAAQwAAAABgGwsUACAAmiAAIABEAAAAAAAAAABjGwsUACAAmiAAIABEAAAAAAAAAIBlGwsUACAAIACaIABEAAAAAAAAAIBkGwsUACAAIACaIABEAAAAAAAAAABmGws=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwkIAAAAAAEBAQEH2QEIGGYzMi5ub19mb2xkX2x0X2lmX3RvX2FicwAAGGYzMi5ub19mb2xkX2xlX2lmX3RvX2FicwABGGYzMi5ub19mb2xkX2d0X2lmX3RvX2FicwACGGYzMi5ub19mb2xkX2dlX2lmX3RvX2FicwADGGY2NC5ub19mb2xkX2x0X2lmX3RvX2FicwAEGGY2NC5ub19mb2xkX2xlX2lmX3RvX2FicwAFGGY2NC5ub19mb2xkX2d0X2lmX3RvX2FicwAGGGY2NC5ub19mb2xkX2dlX2lmX3RvX2FicwAHCrEBCBMAIABDAAAAAF0EfSAAjAUgAAsLEwAgAEMAAACAXwR9IACMBSAACwsTACAAQwAAAIBeBH0gAAUgAIwLCxMAIABDAAAAAGAEfSAABSAAjAsLFwAgAEQAAAAAAAAAAGMEfCAAmgUgAAsLFwAgAEQAAAAAAAAAgGUEfCAAmgUgAAsLFwAgAEQAAAAAAAAAgGQEfCAABSAAmgsLFwAgAEQAAAAAAAAAAGYEfCAABSAAmgsL", + "AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBzcCGGYzMi5pbmNvcnJlY3RfY29ycmVjdGlvbgAAGGY2NC5pbmNvcnJlY3RfY29ycmVjdGlvbgABCkUCGQBDvp+qP0PNzJw/kkO+n6o/k0PNzJw/kwspAESHFtnO91P1P0SamZmZmZnzP6BEhxbZzvdT9T+hRJqZmZmZmfM/oQs=", + "AGFzbQEAAAABBQFgAAF9AwIBAAcNAQljYWxjdWxhdGUAAApKAUgBBX1DAEAcQyEAQ1VVUEMhAUMVx+M/IQIgAYwgAJQgACAClCABk5UhAyABjCAAlCAAIAKUIAGTlSEEAkAgAyAEWw0AAAsgBAs=", + "AGFzbQEAAAABBQFgAAF8AwIBAAcNAQljYWxjdWxhdGUAAApWAVQBBXxEAAAAAACIY0AhAERLBquqqgpqQCEBRJbQ46riePw/IQIgAZogAKIgACACoiABoaMhAyABmiAAoiAAIAKiIAGhoyEEAkAgAyAEYQ0AAAsgBAs=", + "AGFzbQEAAAABBgFgAX0BfQMCAQAHEAEMbGx2bV9wcjI2NzQ2AAAKEgEQAEMAAAAAQwAAAIAgAJOTCw==", + "AGFzbQEAAAABBgFgAX8BfQMCAQAHEAEMbGx2bV9wcjI3MTUzAAAKFAESACAAQf////8AcbJDAAAAy5IL", + "AGFzbQEAAAABBwFgAn9/AX0DAgEABxABDGxsdm1fcHIyNzAzNgAAChcBFQAgAEHL/4d0crIgAUGAgJAHcbKSCw==", + "AGFzbQEAAAABFwNgBHx8fHwBfGADfHx8AXxgA319fQF9AwQDAAECByIDCHRoZXBhc3QwAAAIdGhlcGFzdDEAAQh0aGVwYXN0MgACCiUDDQAgACABoiACIAOiowsKACAAIAGiIAKhCwoAIAAgAZQgApQL", + "AGFzbQEAAAABBgFgAX0BfQMCAQAHCwEHaW52ZXJzZQAACgwBCgBDAACAPyAAlQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHJwIQZjMyX3NxcnRfbWludXNfMgAAEGY2NF9zcXJ0X21pbnVzXzIAAQodAgsAIACRQwAAAECTCw8AIACfRAAAAAAAAABAoQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2ZvbGRfcmVjaXBfcmVjaXAAABdmNjQubm9fZm9sZF9yZWNpcF9yZWNpcAABCisCEABDAACAP0MAAIA/IACVlQsYAEQAAAAAAADwP0QAAAAAAADwPyAAo6ML", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc7AhpmMzIubm9fYWxnZWJyYWljX2ZhY3RvcmluZwAAGmY2NC5ub19hbGdlYnJhaWNfZmFjdG9yaW5nAAEKHQINACAAIAGSIAAgAZOUCw0AIAAgAaAgACABoaIL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc7AhpmMzIubm9fYWxnZWJyYWljX2ZhY3RvcmluZwAAGmY2NC5ub19hbGdlYnJhaWNfZmFjdG9yaW5nAAEKHQINACAAIACUIAEgAZSTCw0AIAAgAKIgASABoqEL", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfQMDAgABBQQBAQEBByACEWYzMi5zaW1wbGVfeDRfc3VtAAAIZjMyLmxvYWQAAQpuAmQBCH0gACoCACEDIAAqAgQhBCAAKgIIIQUgACoCDCEGIAEqAgAhByABKgIEIQggASoCCCEJIAEqAgwhCiACIAMgB5I4AgAgAiAEIAiSOAIEIAIgBSAJkjgCCCACIAYgCpI4AgwLBwAgACoCAAsLNgEAQQALMAEAAAABAACAAQAAAAEAAIABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfAMDAgABBQQBAQEBByACEWY2NC5zaW1wbGVfeDRfc3VtAAAIZjY0LmxvYWQAAQpuAmQBCHwgACsDACEDIAArAwghBCAAKwMQIQUgACsDGCEGIAErAwAhByABKwMIIQggASsDECEJIAErAxghCiACIAMgB6A5AwAgAiAEIAigOQMIIAIgBSAJoDkDECACIAYgCqA5AxgLBwAgACsDAAsLZgEAQQALYAEAAAAAAAAAAQAAAAAAAIABAAAAAAAAAAEAAAAAAACAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "AGFzbQEAAAABBwFgAn9/AX0DAwIAAAUEAQEBAQchAg1mMzIua2FoYW5fc3VtAAANZjMyLnBsYWluX3N1bQABCmICNwEDfQJAA0AgAyAAKgIAIASTIgSSIgIgA5MgBJMhBCAAQQRqIQAgAiEDIAFBf2oiAQ0ACwsgAgsoAQF9AkADQCACIAAqAgCSIQIgAEEEaiEAIAFBf2ohASABDQALCyACCwuHCAEAQQALgAjExVckpYTIC224Sy7ydhccykpWHhtucSJdFx5uv80UXMchVVE5nB+yUfCjk9fBLK5+qCg6ASH0CliT+EJ3n4M5al+69wrYUWo0yq3GNA7YJtxMMxztKZCoeA/RznYxI4O4NejyRLDTofy7MuGwumlECdbZff8uwFo2FDMUPqn6h22LvM6dp/3E6YU/3dfhGKZQJnJuP3MP+BKTIzRhdhJIwJsFk+usht6UPlXojOjd5PyVR75WAyEgTOa/e/Z/1bpzHMEUj8QnlrO9M/94QV/AWs72Z25zmhdmcAP4ziejUrKfO7/7ru3TWvg3V/D1bu+xTXA9VKcBmoUISJH1nQxgh1vZVB5RbYiOCIylcTpWCGdGj48TKizsLB+0YitvQQrEZUKiMWssfT67dayGlzDZSM2aH1bExuQSwJ377gKMzhzyHqF4I9vEHkkD03HMCFDF2Fzt1bVlrLXJIdLJKXbe8DAaWzzyO9s6OYI6FghvqPG+aWmZcaYF0xSTKhbyLxHHfiC7kUTu+OQBU8C5f/C/8AOcbbHfokQBbWtxK1yzIRlGXo/bkdN8eGu3EgCP672K9dQuxMEe33NjWUdJAwq3zyTPnA5Eep4U+0K/nTkwnqCrL9GunmqDQ+NVfYW/Y4r4lhAf/m3nIhvhaUaKRMjI+QwrGQelAj7yMBCahYpf74FFoHexAxBzS66YnUe/mi061Q8DZuM9U9lAzh9vMi8hKyMhbGLUpz6ozigxLQA9Z16voM8u0rlrhOtpCDxiNr4S/TZ/iD6tvAvAQcRQtuNQMejO4pZlVZwWRuawLTrogQWwvzT3vBAc+8w88YWXQp/rFI08v9cXiEmdiyuyOoPRTwSeoQ+tCJ1Ur9GCw+wyLwKPBSEtorfk9G8ugSsLnPzL/nQC+dv08+oAqOzRmXQm3dY01SWxRt2cqnH1YLCIyOALWVolTylm+eMu/una5RhPJ2L0zqQhlXTHV2Qnmkz9VH1hzsOsh0ac+v8JynmXZyR0ytQhgyYlGRI3ZBnlZeB0dY7dyO90x9ghK3kEUUZlYANd+tj0ZaSeXSPa14qSgKTeeDzxV0Jtzckv1aSeq0D0yxvXo8r866cBspppTkabGE7deaeqplI5Hu8wzJu9W+5MIW0wAHKwRl8Iz8W54D7CswzcjmTeGUJ5z0PqQ12OiPerFdw/yGcg27hksUcf3vLLP1mf2EaQ3K4vIvniMYnZnBxM06lKV4Scn+osPK48wx6L5U4XASXbNEZfFeoFDHzZRYwZ0HOKlhbdRPkFt1txsOYhNl91iZFzdat9rtNz7DfG6lV17+qri3sR3G0asmrEJc+q459JSYnLN5sKpwFgcNy3yIPhQvW+rWKUrY2h", + "AGFzbQEAAAABBwFgAn9/AXwDAwIAAAUEAQEBAQchAg1mNjQua2FoYW5fc3VtAAANZjY0LnBsYWluX3N1bQABCmICNwEDfAJAA0AgAyAAKwMAIAShIgSgIgIgA6EgBKEhBCAAQQhqIQAgAiEDIAFBf2oiAQ0ACwsgAgsoAQF8AkADQCACIAArAwCgIQIgAEEIaiEAIAFBf2ohASABDQALCyACCwuHEAEAQQALgBATBYRCXaIsxkPbVanN2lXjc/xY1rrVAP2DNUKIixNdOEpHDXJzoRrvxEUXV9jJRuCNbOE3cMiDW1VeWi1zHlbI4W1pFHgKilpkOgnHqIfF8NNd5gP8k74mytapkWC9sO2u9zB+kjpvp1mOqn2/Z1gqVPhO/u01WKZRv0LlS2YnJG1/Qi0okhjsCK7nVdqxpmWlclBHG7ipVNemBlsPQliDiheCxhBDoMAubbxahVNyf61EvDA8VbIkmnQ6nuHYD3D8qTrNk0vs437dXSfN+KCdHBHAVy79yBMyzDoafaNBVe3DgkkqBB7vc7kuLuNf9N/msjMMOT9vRGoDwUK5+rHI7aVYmX/ttHKeeev7Q4JFqruV0v8onvahrZXWVZUNb2ARx3g+SfJ+SPSicdATjrPemVLjRXTqdg4bKsjuFAHEUFs2PO+6cqKmCPh7Np357wvHVi1c8J1d3vy4rQ9kDpcVMibCMeYFHu/LFxttFQt0XdMu+GuGtLpzUlOZqXYgRclAgGsU7aH6gEbmJtLmmMRXv8QcpJB6NpQUuhWJbuacN4z03hIiXaF5UGcNPXrp1Koufyp6MD3qXRJI/uEYzaRXooc+tpqL29qdeJzPjbFPkLQ04J32yv5MO3htClwYn2G53bTgD3bgG2kNXlhzcF4OLaF9/yDrkTSSrDhyKh+OcS5q8a/HJ3DZxFf30jwduPDwZM/crr6jzD4ifU5pIWMX7QMCVJoPUE4TWjWhIqTfhsJ0eRa4aWmgUl0RZL1bk/xpoPQT0IFR3foMFcN6yWJ6qR3J5lqzW5cCPGQiEjwikGQtMFRMtKEiCVciXo44KwKorva+DSvyA636EAFxdyowApX2AD7QxI00GVAhCrxQ2jww1joxlI06/u8UV51LkwCWJAxv/bwjdgJs61JygBF+gDoTEjgdOEmVQCeKRHvo3G2MjI48tbMYDvYIGoRBNf+LuJNA6uFRHYmljUJoKeovwXpS65BdTdaA49d1SM7t0wEcjVullA14z/EGEy+YAqRtLmzy1XQpiUz5A/XHGK168Gj4XNZZh27WPwa+hiDjQZEi826L8GgcV6f8sHyemQuWGolf5g18CFGgomeaRwCTa/ko8GjbYvHgZSxTM+CnyhFCMPavAcFlPTIBb6suvtOLvhTD/+z78PnFDAVvAQlr4zQxDB9mpkK8GodJFhaMsJANNIwK4QleEKRrVszwybvcuFzO9syNdX6zB4gEL7ReyeNKI3MZYmyaA3ZEhpxg/Ntyjyeg3bPF2v/57Gqxe9PPUDfJengM5Dq29eb0mG5CfTVzi0XAVpfNbc7PrTGzw1T679XA9GpfVOdJPjMKMDj92QX/pT9XRhS1kRfKa5gjemWzbAK0zHldWNiz1ZSu9G11ZfeSv35HTDzu26zxMl37b0EcNMiDT8JYAb4FPmYWpgRtXU+GCSeCJRLNOs3Oa7zKrCib7molhp5FcMbSvTt9QuUnr8cd9IHIs3aKqDajrirmGOE2Iq32JXKwOYsBmiJ7hMMtX3KkmKwVcOfUGOJ90jB8MwjNysQihYh1gcZKdFiN4Oisxat1WvQoEvAYRVLyl7KTQW+Nf9tw+6NdH6eNmCArIp86AbWLG9LLFAMOFBTSGVofzl7NgXkVAcrec3SMViCfdy0lFvZhUR2kjpuYpcbsqEVXgll4DZC031Gww4KUzLNTCRVtlmw6QEe3SnoFL6EejJ2gIIj7Uref8/O7X+eKYachsaz6CaqkbLwkgLoq6WX/cP/M+mWHdvPFFc7L6EIxAAyRV9ngnTVUJK2k2PkIZ2PIz4HdkKLXxAdK5hBvZ+cn1CNZGPKonV/YlDCqVIZPh52CtSbKppa/z1X5nTcBGUhDxZRs83SXWEw8nQjoBMJYMHbhoPjq6cWuz3ieqQyss0RC4LxdG5xJWEocGUnBOur16zuBqUtwDMyeGtMvt1IvIDvrZFEdoC2yPr4ThUiSMi7bXKHnjEWRNQEKk8LrCc7z0iIk0IzMHZ04yE3jgsxkFQYt5wEvq7u1BEySHHrWP+hfMRUM3OQxtMQlPiqqAJ7I5SF6fynxwK8dXuhjOa34fmzIxX/CqJcnCtn0IWrqAwn795Y7g3lffEswn1Y13rRz1JXwFMN0Lw2jHU6NMSSzGoSFYlp7PBQ5F+Zt6zfCAFhbC+M8imLh+DVLVuKHYIu+pziRd1SpWiQlkJ+lQnfzXDnf/3QHdqHNH2ILgYForwXBwH8m7sCRo2p9KWFFJ+VXiNwNlwQaM6lEitoCEEU/jlWmdoxN4/GJg8jQ+JtQd59H30ycZg2qGLhfT8QBztyErEaeaeF2RWthieRdlLsRg5942ArS9X5dQ+q8EPE6yeJk+1Nl0Me0p/vUBVMl0M0piABWJSR9XbTzQZ/ptfeuZCzjyW3VhDpyErh62RsJ6DjaJk8EzgNxbopEe1yBWZzS5MO6WablKKePmuTVTrnKf8t1uCtDPrMVRrGlvJ2eOBXxvRshqvGCAJX8p3dHOaczQ5LXUkBLBoGKoL3xa5mEQlviO8VeElwoTbYOTshc6AGKxefknULuXZzE6+toCSeSlZoRVHPEEoD7ff7FCGB/NkHgELrWK2zxtBf+JjTjS/io45G+Tyr82oG45/7VJlBH8xplMoHgBbhPMjEmAEpTl8LDDi6hJlSrBY5WL32vIoRopYuX9qT9qMx1QZaG/Sc9KYaNf0zUjnNB9B7i3Vgnl86clM96BC/c7Q==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9uZWdfc3ViAAATZjY0Lm5vX2ZvbGRfbmVnX3N1YgABChMCCAAgACABk4wLCAAgACABoZoL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9uZWdfYWRkAAATZjY0Lm5vX2ZvbGRfbmVnX2FkZAABChMCCAAgACABkowLCAAgACABoJoL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc1AhdmMzIubm9fZm9sZF9hZGRfbmVnX25lZwAAF2Y2NC5ub19mb2xkX2FkZF9uZWdfbmVnAAEKFQIJACAAjCABjJILCQAgAJogAZqgCw==", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfYWRkX25lZwAAE2Y2NC5ub19mb2xkX2FkZF9uZWcAAQoTAggAIACMIACSCwgAIACaIACgCw==", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHMwIWZjMyLm5vX2ZvbGRfNnhfdmlhX2FkZAAAFmY2NC5ub19mb2xkXzZ4X3ZpYV9hZGQAAQopAhMAIAAgAJIgAJIgAJIgAJIgAJILEwAgACAAoCAAoCAAoCAAoCAAoAs=", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBy0CE2YzMi5ub19mb2xkX2Rpdl9kaXYAABNmNjQubm9fZm9sZF9kaXZfZGl2AAEKFwIKACAAIAGVIAKVCwoAIAAgAaMgAqML", + "AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbXVsX2RpdnMAABRmNjQubm9fZm9sZF9tdWxfZGl2cwABCh0CDQAgACABlSACIAOVlAsNACAAIAGjIAIgA6OiCw==", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBy8CFGYzMi5ub19mb2xkX2FkZF9kaXZzAAAUZjY0Lm5vX2ZvbGRfYWRkX2RpdnMAAQodAg0AIAAgApUgASAClZILDQAgACACoyABIAKjoAs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2ZvbGRfc3FydF9zcXVhcmUAABdmNjQubm9fZm9sZF9zcXJ0X3NxdWFyZQABChMCCAAgACAAlJELCAAgACAAop8L", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcxAhVmMzIubm9fZm9sZF9tdWxfc3FydHMAABVmNjQubm9fZm9sZF9tdWxfc3FydHMAAQoVAgkAIACRIAGRlAsJACAAnyABn6IL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcxAhVmMzIubm9fZm9sZF9kaXZfc3FydHMAABVmNjQubm9fZm9sZF9kaXZfc3FydHMAAQoVAgkAIACRIAGRlQsJACAAnyABn6ML", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc3AhhmMzIubm9fZm9sZF9tdWxfc3FydF9kaXYAABhmNjQubm9fZm9sZF9tdWxfc3FydF9kaXYAAQoZAgsAIAAgAZGUIAGVCwsAIAAgAZ+iIAGjCw==", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABB00CI2YzMi5ub19mbHVzaF9pbnRlcm1lZGlhdGVfc3Vibm9ybWFsAAAjZjY0Lm5vX2ZsdXNoX2ludGVybWVkaWF0ZV9zdWJub3JtYWwAAQoXAgoAIAAgAZQgApQLCgAgACABoiACogs=", + "AGFzbQEAAAABEwNgAn19AX9gAnx8AX9gAnx9AX0DCAcAAAABAQECB38HD2YzMi5yZWNvZGluZ19lcQAAD2YzMi5yZWNvZGluZ19sZQABD2YzMi5yZWNvZGluZ19sdAACD2Y2NC5yZWNvZGluZ19lcQADD2Y2NC5yZWNvZGluZ19sZQAED2Y2NC5yZWNvZGluZ19sdAAFD3JlY29kaW5nX2RlbW90ZQAGCkwHCgAgACABlCAAWwsKACAAIAGUIABfCwoAIAAgAZQgAF0LCgAgACABoiAAYQsKACAAIAGiIABlCwoAIAAgAaIgAGMLCAAgALYgAZQL", + "AGFzbQEAAAABDwJgA319fQF/YAN8fHwBfwMDAgABB0ECHWYzMi5ub19leHRlbmRlZF9wcmVjaXNpb25fZGl2AAAdZjY0Lm5vX2V4dGVuZGVkX3ByZWNpc2lvbl9kaXYAAQoXAgoAIAAgAZUgAlsLCgAgACABoyACYQs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2Rpc3RyaWJ1dGVfZXhhY3QAABdmNjQubm9fZGlzdHJpYnV0ZV9leGFjdAABCjECEwBDAAAAwSAAlEMAAABBIACUkgsbAEQAAAAAAAAgwCAAokQAAAAAAAAgQCAAoqAL", + "AGFzbQEAAAABKQZgAX0BfWAEfX19fQF9YAN9fX0BfWABfAF8YAR8fHx8AXxgA3x8fAF8AwsKAAECAgEDBAUFBAe1AQoIZjMyLnNxcnQAAA9mMzIueGtjZF9zcXJ0XzIAAQ9mMzIueGtjZF9zcXJ0XzMAAg9mMzIueGtjZF9zcXJ0XzUAAxZmMzIueGtjZF9iZXR0ZXJfc3FydF81AAQIZjY0LnNxcnQABQ9mNjQueGtjZF9zcXJ0XzIABg9mNjQueGtjZF9zcXJ0XzMABw9mNjQueGtjZF9zcXJ0XzUACBZmNjQueGtjZF9iZXR0ZXJfc3FydF81AAkKiQEKBQAgAJELEAAgACABlSACIAMgApOVkgsKACAAIAGUIAKVCw0AIAAgAZUgAiAAlZILEwAgACABIAKUkiADIAEgApSTlQsFACAAnwsQACAAIAGjIAIgAyACoaOgCwoAIAAgAaIgAqMLDQAgACABoyACIACjoAsTACAAIAEgAqKgIAMgASACoqGjCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcpAhFmMzIuY29tcHV0ZV9yYWRpeAAAEWY2NC5jb21wdXRlX3JhZGl4AAEKnQECQwADQCAAIACSIgBDAACAP5IgAJNDAACAv5JDAAAAAFsNAAsDQCAAIAFDAACAP5IiAZIgAJMgAZNDAAAAAFwNAAsgAQtXAANAIAAgAKAiAEQAAAAAAADwP6AgAKFEAAAAAAAA8L+gRAAAAAAAAAAAYQ0ACwNAIAAgAUQAAAAAAADwP6AiAaAgAKEgAaFEAAAAAAAAAABiDQALIAEL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc3AhhmMzIubm9fZm9sZF9zdWIxX211bF9hZGQAABhmNjQubm9fZm9sZF9zdWIxX211bF9hZGQAAQonAhAAIABDAACAP5MgAZQgAZILFAAgAEQAAAAAAADwP6EgAaIgAaAL", + "AGFzbQEAAAABDwJgA319fQF/YAN8fHwBfwMFBAAAAQEHiQEEH2YzMi5ub19mb2xkX2FkZF9sZV9tb25vdG9uaWNpdHkAAB9mMzIubm9fZm9sZF9hZGRfZ2VfbW9ub3RvbmljaXR5AAEfZjY0Lm5vX2ZvbGRfYWRkX2xlX21vbm90b25pY2l0eQACH2Y2NC5ub19mb2xkX2FkZF9nZV9tb25vdG9uaWNpdHkAAwo5BA0AIAAgApIgASACkl8LDQAgACACkiABIAKSYAsNACAAIAKgIAEgAqBlCw0AIAAgAqAgASACoGYL", + "AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQdpCApmMzIubm90X2x0AAAKZjMyLm5vdF9sZQABCmYzMi5ub3RfZ3QAAgpmMzIubm90X2dlAAMKZjY0Lm5vdF9sdAAECmY2NC5ub3RfbGUABQpmNjQubm90X2d0AAYKZjY0Lm5vdF9nZQAHCkkICAAgACABXUULCAAgACABX0ULCAAgACABXkULCAAgACABYEULCAAgACABY0ULCAAgACABZUULCAAgACABZEULCAAgACABZkUL", + "AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBx0CC2YzMi5lcHNpbG9uAAALZjY0LmVwc2lsb24AAQpVAh8AQwAAgD9DAABAQEMAAIBAQwAAQECVQwAAgD+TlJMLMwBEAAAAAAAA8D9EAAAAAAAACEBEAAAAAAAAEEBEAAAAAAAACECjRAAAAAAAAPA/oaKhCw==", + "AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBx0CC2YzMi5lcHNpbG9uAAALZjY0LmVwc2lsb24AAQpnAioBAn1DAACAPyEAA0AgACIBQwAAAD+UIgBDAACAP5JDAACAP14NAAsgAQs6AQJ8RAAAAAAAAPA/IQADQCAAIgFEAAAAAAAA4D+iIgBEAAAAAAAA8D+gRAAAAAAAAPA/ZA0ACyABCw==", + "AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQe5AQgUZjMyLm5vX3RyaWNob3RvbXlfbHQAABRmMzIubm9fdHJpY2hvdG9teV9sZQABFGYzMi5ub190cmljaG90b215X2d0AAIUZjMyLm5vX3RyaWNob3RvbXlfZ2UAAxRmNjQubm9fdHJpY2hvdG9teV9sdAAEFGY2NC5ub190cmljaG90b215X2xlAAUUZjY0Lm5vX3RyaWNob3RvbXlfZ3QABhRmNjQubm9fdHJpY2hvdG9teV9nZQAHCnEIDQAgACABXSAAIAFgcgsNACAAIAFfIAAgAV5yCw0AIAAgAV4gACABX3ILDQAgACABYCAAIAFdcgsNACAAIAFjIAAgAWZyCw0AIAAgAWUgACABZHILDQAgACABZCAAIAFlcgsNACAAIAFmIAAgAWNyCw==", + "AGFzbQEAAAABFwRgAn9/AX9gAX8Bf2ACfn4BfmABfgF+AxQTAAABAgIDAQEBAQEBAwMDAwMDAQfuAxMdZjMyLmFyaXRobWV0aWNfbmFuX2JpdHBhdHRlcm4AABxmMzIuY2Fub25pY2FsX25hbl9iaXRwYXR0ZXJuAAEgZjMyLm5vbmFyaXRobWV0aWNfbmFuX2JpdHBhdHRlcm4AAh1mNjQuYXJpdGhtZXRpY19uYW5fYml0cGF0dGVybgADHGY2NC5jYW5vbmljYWxfbmFuX2JpdHBhdHRlcm4ABCBmNjQubm9uYXJpdGhtZXRpY19uYW5fYml0cGF0dGVybgAFFGYzMi5ub19mb2xkX3N1Yl96ZXJvAAYUZjMyLm5vX2ZvbGRfbmVnMF9zdWIABxNmMzIubm9fZm9sZF9tdWxfb25lAAgUZjMyLm5vX2ZvbGRfbmVnMV9tdWwACRNmMzIubm9fZm9sZF9kaXZfb25lAAoUZjMyLm5vX2ZvbGRfZGl2X25lZzEACxRmNjQubm9fZm9sZF9zdWJfemVybwAMFGY2NC5ub19mb2xkX25lZzBfc3ViAA0TZjY0Lm5vX2ZvbGRfbXVsX29uZQAOFGY2NC5ub19mb2xkX25lZzFfbXVsAA8TZjY0Lm5vX2ZvbGRfZGl2X29uZQAQFGY2NC5ub19mb2xkX2Rpdl9uZWcxABEWbm9fZm9sZF9wcm9tb3RlX2RlbW90ZQASCpkDExEAIAC+IAG+lbxBgICA/gdxCxEAIAC+IAG+lbxB/////wdxCwcAIAC+jLwLFgAgAL8gAb+jvUKAgICAgICA/P8AgwsWACAAvyABv6O9Qv///////////wCDCwcAIAC/mr0LEwAgAL5DAAAAAJO8QYCAgP4HcQsTAEMAAACAIAC+k7xBgICA/gdxCxMAIAC+QwAAgD+UvEGAgID+B3ELEwBDAACAvyAAvpS8QYCAgP4HcQsTACAAvkMAAIA/lbxBgICA/gdxCxMAIAC+QwAAgL+VvEGAgID+B3ELHAAgAL9EAAAAAAAAAAChvUKAgICAgICA/P8AgwscAEQAAAAAAAAAgCAAv6G9QoCAgICAgID8/wCDCxwAIAC/RAAAAAAAAPA/or1CgICAgICAgPz/AIMLHABEAAAAAAAA8L8gAL+ivUKAgICAgICA/P8AgwscACAAv0QAAAAAAADwP6O9QoCAgICAgID8/wCDCxwAIAC/RAAAAAAAAPC/o71CgICAgICAgPz/AIMLDwAgAL67trxBgICA/gdxCw==", + "AGFzbQEAAAABDQFgCHx8fHx8fHx8AXwDAwIAAAcyAhNkb3RfcHJvZHVjdF9leGFtcGxlAAAYd2l0aF9iaW5hcnlfc3VtX2NvbGxhcHNlAAEKNQIZACAAIASiIAEgBaKgIAIgBqKgIAMgB6KgCxkAIAAgBKIgASAFoqAgAiAGoiADIAeioKAL", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcnAhBmMzIuY29udHJhY3QyZm1hAAAQZjY0LmNvbnRyYWN0MmZtYQABCh8CDgAgACAAlCABIAGUk5ELDgAgACAAoiABIAGioZ8L", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBz8CHGYzMi5kaXZpc2lvbl9ieV9zbWFsbF9udW1iZXIAABxmNjQuZGl2aXNpb25fYnlfc21hbGxfbnVtYmVyAAEKFwIKACAAIAEgApWTCwoAIAAgASACo6EL", + "AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBycCEGYzMi5nb2xkZW5fcmF0aW8AABBmNjQuZ29sZGVuX3JhdGlvAAEKGQILACAAIAEgApGSlAsLACAAIAEgAp+gogs=", + "AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHJwIQZjMyLnNpbHZlcl9tZWFucwAAEGY2NC5zaWx2ZXJfbWVhbnMAAQo5AhcAQwAAAD8gACAAIACUQwAAgECSkZKUCx8ARAAAAAAAAOA/IAAgACAAokQAAAAAAAAQQKCfoKIL", + "AGFzbQEAAAABBwFgAnx8AX8DAgEABw4BCnBvaW50X2ZvdXIAAAoTAREAIAAgAaNEmpmZmZmZ2T9jCw==", + "AGFzbQEAAAABBgFgAX8BfAMCAQAHBwEDdGF1AAAKywEByAEBBHxEAAAAAAAAAAAhAQJAIABBAUgNAEQAAAAAAADwPyECRAAAAAAAAAAAIQMDQCABIAJEAAAAAAAAIEAgA0QAAAAAAAAgQKIiBEQAAAAAAADwP6CjRAAAAAAAABBAIAREAAAAAAAAEECgo6FEAAAAAAAAAEAgBEQAAAAAAAAUQKCjoUQAAAAAAAAAQCAERAAAAAAAABhAoKOhoqAhASADRAAAAAAAAPA/oCEDIAJEAAAAAAAAsD+iIQIgAEF/aiIADQALCyABCw==", + "AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc9AhtmMzIubm9fZm9sZF9jb25kaXRpb25hbF9pbmMAABtmNjQubm9fZm9sZF9jb25kaXRpb25hbF9pbmMAAQo1AhUAIAAgAEMAAIA/kiABQwAAAABdGwsdACAAIABEAAAAAAAA8D+gIAFEAAAAAAAAAABjGws=", + "AGFzbQEAAAABEQRgAAF/YAABfmAAAX1gAAF8A2NiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAgICAgICAgICAgMDAwMDAwMDAwMHmQ5iB2YzMi5uYW4AABBmMzIucG9zaXRpdmVfbmFuAAEQZjMyLm5lZ2F0aXZlX25hbgACDWYzMi5wbGFpbl9uYW4AAyJmMzIuaW5mb3JtYWxseV9rbm93bl9hc19wbGFpbl9zbmFuAAQQZjMyLmFsbF9vbmVzX25hbgAFDGYzMi5taXNjX25hbgAGFWYzMi5taXNjX3Bvc2l0aXZlX25hbgAHFWYzMi5taXNjX25lZ2F0aXZlX25hbgAIDGYzMi5pbmZpbml0eQAJFWYzMi5wb3NpdGl2ZV9pbmZpbml0eQAKFWYzMi5uZWdhdGl2ZV9pbmZpbml0eQALCGYzMi56ZXJvAAwRZjMyLnBvc2l0aXZlX3plcm8ADRFmMzIubmVnYXRpdmVfemVybwAOCGYzMi5taXNjAA8QZjMyLm1pbl9wb3NpdGl2ZQAQDmYzMi5taW5fbm9ybWFsABEOZjMyLm1heF9maW5pdGUAEhFmMzIubWF4X3N1Ym5vcm1hbAATEGYzMi50cmFpbGluZ19kb3QAFAxmMzIubWlzY19pbnQAFQ1mMzIubGFyZ2VfaW50ABYNZjMyLm1pbl9pbnQzMgAXDWYzMi5taW5faW50NjQAGAxmMzJfZGVjLnplcm8AGRVmMzJfZGVjLnBvc2l0aXZlX3plcm8AGhVmMzJfZGVjLm5lZ2F0aXZlX3plcm8AGwxmMzJfZGVjLm1pc2MAHBRmMzJfZGVjLm1pbl9wb3NpdGl2ZQAdEmYzMl9kZWMubWluX25vcm1hbAAeFWYzMl9kZWMubWF4X3N1Ym5vcm1hbAAfEmYzMl9kZWMubWF4X2Zpbml0ZQAgFGYzMl9kZWMudHJhaWxpbmdfZG90ACEQZjMyX2RlYy5taXNjX2ludAAiEWYzMl9kZWMubGFyZ2VfaW50ACMRZjMyX2RlYy5taW5faW50MzIAJBFmMzJfZGVjLm1pbl9pbnQ2NAAlF2YzMl9kZWMucm9vdF9iZWVyX2Zsb2F0ACYHZjY0Lm5hbgAnEGY2NC5wb3NpdGl2ZV9uYW4AKBBmNjQubmVnYXRpdmVfbmFuACkNZjY0LnBsYWluX25hbgAqImY2NC5pbmZvcm1hbGx5X2tub3duX2FzX3BsYWluX3NuYW4AKxBmNjQuYWxsX29uZXNfbmFuACwMZjY0Lm1pc2NfbmFuAC0VZjY0Lm1pc2NfcG9zaXRpdmVfbmFuAC4VZjY0Lm1pc2NfbmVnYXRpdmVfbmFuAC8MZjY0LmluZmluaXR5ADAVZjY0LnBvc2l0aXZlX2luZmluaXR5ADEVZjY0Lm5lZ2F0aXZlX2luZmluaXR5ADIIZjY0Lnplcm8AMxFmNjQucG9zaXRpdmVfemVybwA0EWY2NC5uZWdhdGl2ZV96ZXJvADUIZjY0Lm1pc2MANhBmNjQubWluX3Bvc2l0aXZlADcOZjY0Lm1pbl9ub3JtYWwAOBFmNjQubWF4X3N1Ym5vcm1hbAA5DmY2NC5tYXhfZmluaXRlADoQZjY0LnRyYWlsaW5nX2RvdAA7DGY2NC5taXNjX2ludAA8DWY2NC5sYXJnZV9pbnQAPQ1mNjQubWluX2ludDMyAD4NZjY0Lm1pbl9pbnQ2NAA/DGY2NF9kZWMuemVybwBAFWY2NF9kZWMucG9zaXRpdmVfemVybwBBFWY2NF9kZWMubmVnYXRpdmVfemVybwBCDGY2NF9kZWMubWlzYwBDFGY2NF9kZWMubWluX3Bvc2l0aXZlAEQSZjY0X2RlYy5taW5fbm9ybWFsAEUVZjY0X2RlYy5tYXhfc3Vibm9ybWFsAEYSZjY0X2RlYy5tYXhfZmluaXRlAEcUZjY0X2RlYy50cmFpbGluZ19kb3QASBBmNjRfZGVjLm1pc2NfaW50AEkRZjY0X2RlYy5sYXJnZV9pbnQAShFmNjRfZGVjLm1pbl9pbnQzMgBLEWY2NF9kZWMubWluX2ludDY0AEwXZjY0X2RlYy5yb290X2JlZXJfZmxvYXQATQxmMzItZGVjLXNlcDEATgxmMzItZGVjLXNlcDIATwxmMzItZGVjLXNlcDMAUAxmMzItZGVjLXNlcDQAUQxmMzItZGVjLXNlcDUAUgxmMzItaGV4LXNlcDEAUwxmMzItaGV4LXNlcDIAVAxmMzItaGV4LXNlcDMAVQxmMzItaGV4LXNlcDQAVgxmMzItaGV4LXNlcDUAVwxmNjQtZGVjLXNlcDEAWAxmNjQtZGVjLXNlcDIAWQxmNjQtZGVjLXNlcDMAWgxmNjQtZGVjLXNlcDQAWwxmNjQtZGVjLXNlcDUAXAxmNjQtaGV4LXNlcDEAXQxmNjQtaGV4LXNlcDIAXgxmNjQtaGV4LXNlcDMAXwxmNjQtaGV4LXNlcDQAYAxmNjQtaGV4LXNlcDUAYQqjCGIIAEMAAMB/vAsIAEMAAMB/vAsIAEMAAMD/vAsIAEMAAMB/vAsIAEMAAKB/vAsIAEP/////vAsIAENFI4F/vAsIAENQQLB/vAsIAEPevKr/vAsIAEMAAIB/vAsIAEMAAIB/vAsIAEMAAID/vAsIAEMAAAAAvAsIAEMAAAAAvAsIAEMAAACAvAsIAEPbD8lAvAsIAEMBAAAAvAsIAEMAAIAAvAsIAEP//39/vAsIAEP//38AvAsIAEMAAIBEvAsIAEOAopFHvAsIAEMAAIBnvAsIAEMAAADPvAsIAEMAAADfvAsIAEMAAAAAvAsIAEMAAAAAvAsIAEMAAACAvAsIAEPbD8lAvAsIAEMBAAAAvAsIAEMAAIAAvAsIAEP//38AvAsIAEP//39/vAsIAEP5AhVQvAsIAEMA5EBGvAsIAEPseK1gvAsIAEMAAADPvAsIAEMAAADfvAsIAEMBAIA/vAsMAEQAAAAAAAD4f70LDABEAAAAAAAA+H+9CwwARAAAAAAAAPj/vQsMAEQAAAAAAAD4f70LDABEAAAAAAAA9H+9CwwARP//////////vQsMAES8mnhWNBLwf70LDABECQgHBgUE83+9CwwAREUjAe/Nq/L/vQsMAEQAAAAAAADwf70LDABEAAAAAAAA8H+9CwwARAAAAAAAAPD/vQsMAEQAAAAAAAAAAL0LDABEAAAAAAAAAAC9CwwARAAAAAAAAACAvQsMAEQYLURU+yEZQL0LDABEAQAAAAAAAAC9CwwARAAAAAAAABAAvQsMAET///////8PAL0LDABE////////73+9CwwARAAAAAAAADBGvQsMAEQAAAAAUDTyQL0LDABEAAAAAAAA8ES9CwwARAAAAAAAAODBvQsMAEQAAAAAAADgw70LDABEAAAAAAAAAAC9CwwARAAAAAAAAAAAvQsMAEQAAAAAAAAAgL0LDABEGC1EVPshGUC9CwwARAEAAAAAAAAAvQsMAEQAAAAAAAAQAL0LDABE////////DwC9CwwARP///////+9/vQsMAER9w5QlrUmyVL0LDABEAAAAAIAcyEC9CwwARECMtXgdrxVEvQsMAEQAAAAAAADgwb0LDABEAAAAAAAA4MO9CwwARCSe8R8AAPA/vQsHAEMAJHRJCwcAQwAAekQLBwBDEMl6RAsHAEOWGWFYCwcAQ3SuHW4LBwBDCvAgTQsHAEOAB9VHCwcAQ/H/IEcLBwBDAADwSQsHAEMowKtVCwsARAAAAACAhC5BCwsARAAAAAAAQI9ACwsARACL/PohWY9ACwsAREXMt1tzXNAmCwsARJzeW3LOtcNFCwsARDIzAQAe4CVDCwsARAAAAADwoPpACwsARECzNCj+H+RACwsARAAAAAAAAD5BCwsARABwnw8FeLVCCw==", + "AGFzbQEAAAABhYCAgAABYAABfAOCgICAAAEAB46AgIAAAQo0Mjk0OTY3MjQ5AAAKkYCAgAABi4CAgAAARAAAIPr//+9BCw==", + "AGFzbQEAAAABFwRgAn19AX1gAX0BfWACfHwBfGABfAF8Ax0cAAAAAAEBAQABAQEBAAACAgICAwMDAgMDAwMCAge3AhwHZjMyLmFkZAAAB2YzMi5zdWIAAQdmMzIubXVsAAIHZjMyLmRpdgADCGYzMi5zcXJ0AAQHZjMyLmFicwAFB2YzMi5uZWcABgxmMzIuY29weXNpZ24ABwhmMzIuY2VpbAAICWYzMi5mbG9vcgAJCWYzMi50cnVuYwAKC2YzMi5uZWFyZXN0AAsHZjMyLm1pbgAMB2YzMi5tYXgADQdmNjQuYWRkAA4HZjY0LnN1YgAPB2Y2NC5tdWwAEAdmNjQuZGl2ABEIZjY0LnNxcnQAEgdmNjQuYWJzABMHZjY0Lm5lZwAUDGY2NC5jb3B5c2lnbgAVCGY2NC5jZWlsABYJZjY0LmZsb29yABcJZjY0LnRydW5jABgLZjY0Lm5lYXJlc3QAGQdmNjQubWluABoHZjY0Lm1heAAbCsUBHAcAIAAgAZILBwAgACABkwsHACAAIAGUCwcAIAAgAZULBQAgAJELBQAgAIsLBQAgAIwLBwAgACABmAsFACAAjQsFACAAjgsFACAAjwsFACAAkAsHACAAIAGWCwcAIAAgAZcLBwAgACABoAsHACAAIAGhCwcAIAAgAaILBwAgACABowsFACAAnwsFACAAmQsFACAAmgsHACAAIAGmCwUAIACbCwUAIACcCwUAIACdCwUAIACeCwcAIAAgAaQLBwAgACABpQs=", +]; +export const script = "[[\"file\",\"f32.wast\"],[\"module\",5,0],[\"invoke\",19,0,\"add\",[\"f32:2147483648\",\"f32:2147483648\"]],[\"invoke\",25,0,\"add\",[\"f32:0\",\"f32:2147483649\"]],[\"invoke\",30,0,\"add\",[\"f32:0\",\"f32:8388608\"]],[\"invoke\",35,0,\"add\",[\"f32:2147483648\",\"f32:3212836864\"]],[\"invoke\",40,0,\"add\",[\"f32:2147483648\",\"f32:1086918619\"]],[\"invoke\",45,0,\"add\",[\"f32:0\",\"f32:4286578687\"]],[\"invoke\",50,0,\"add\",[\"f32:0\",\"f32:2139095040\"]],[\"invoke\",59,0,\"add\",[\"f32:2147483649\",\"f32:2147483648\"]],[\"invoke\",64,0,\"add\",[\"f32:2147483649\",\"f32:1\"]],[\"invoke\",69,0,\"add\",[\"f32:1\",\"f32:2155872256\"]],[\"invoke\",74,0,\"add\",[\"f32:1\",\"f32:1056964608\"]],[\"invoke\",79,0,\"add\",[\"f32:2147483649\",\"f32:3234402267\"]],[\"invoke\",85,0,\"add\",[\"f32:1\",\"f32:4286578687\"]],[\"invoke\",90,0,\"add\",[\"f32:1\",\"f32:2139095040\"]],[\"invoke\",99,0,\"add\",[\"f32:2155872256\",\"f32:2147483648\"]],[\"invoke\",104,0,\"add\",[\"f32:2155872256\",\"f32:1\"]],[\"invoke\",109,0,\"add\",[\"f32:8388608\",\"f32:2155872256\"]],[\"invoke\",114,0,\"add\",[\"f32:8388608\",\"f32:1056964608\"]],[\"invoke\",119,0,\"add\",[\"f32:2155872256\",\"f32:3234402267\"]],[\"invoke\",124,0,\"add\",[\"f32:2155872256\",\"f32:2139095039\"]],[\"invoke\",129,0,\"add\",[\"f32:8388608\",\"f32:4286578688\"]],[\"invoke\",137,0,\"add\",[\"f32:8388608\",\"f32:2143289344\"]],[\"invoke\",143,0,\"add\",[\"f32:3204448256\",\"f32:2147483649\"]],[\"invoke\",148,0,\"add\",[\"f32:3204448256\",\"f32:8388608\"]],[\"invoke\",154,0,\"add\",[\"f32:1056964608\",\"f32:1056964608\"]],[\"invoke\",159,0,\"add\",[\"f32:3204448256\",\"f32:3234402267\"]],[\"invoke\",164,0,\"add\",[\"f32:3204448256\",\"f32:2139095039\"]],[\"invoke\",169,0,\"add\",[\"f32:1056964608\",\"f32:4286578688\"]],[\"invoke\",177,0,\"add\",[\"f32:1056964608\",\"f32:2143289344\"]],[\"invoke\",183,0,\"add\",[\"f32:3212836864\",\"f32:2147483649\"]],[\"invoke\",188,0,\"add\",[\"f32:3212836864\",\"f32:8388608\"]],[\"invoke\",193,0,\"add\",[\"f32:1065353216\",\"f32:3204448256\"]],[\"invoke\",198,0,\"add\",[\"f32:1065353216\",\"f32:1065353216\"]],[\"invoke\",203,0,\"add\",[\"f32:3212836864\",\"f32:4286578687\"]],[\"invoke\",208,0,\"add\",[\"f32:3212836864\",\"f32:2139095040\"]],[\"invoke\",215,0,\"add\",[\"f32:1065353216\",\"f32:4290772992\"]],[\"invoke\",223,0,\"add\",[\"f32:3234402267\",\"f32:2147483649\"]],[\"invoke\",228,0,\"add\",[\"f32:3234402267\",\"f32:8388608\"]],[\"invoke\",233,0,\"add\",[\"f32:1086918619\",\"f32:3204448256\"]],[\"invoke\",238,0,\"add\",[\"f32:1086918619\",\"f32:1065353216\"]],[\"invoke\",243,0,\"add\",[\"f32:3234402267\",\"f32:4286578687\"]],[\"invoke\",248,0,\"add\",[\"f32:3234402267\",\"f32:2139095040\"]],[\"invoke\",255,0,\"add\",[\"f32:1086918619\",\"f32:4290772992\"]],[\"invoke\",262,0,\"add\",[\"f32:2139095039\",\"f32:0\"]],[\"invoke\",267,0,\"add\",[\"f32:4286578687\",\"f32:2155872256\"]],[\"invoke\",272,0,\"add\",[\"f32:4286578687\",\"f32:1056964608\"]],[\"invoke\",277,0,\"add\",[\"f32:2139095039\",\"f32:3212836864\"]],[\"invoke\",282,0,\"add\",[\"f32:2139095039\",\"f32:1086918619\"]],[\"invoke\",288,0,\"add\",[\"f32:4286578687\",\"f32:2139095040\"]],[\"invoke\",295,0,\"add\",[\"f32:2139095039\",\"f32:4290772992\"]],[\"invoke\",302,0,\"add\",[\"f32:2139095040\",\"f32:0\"]],[\"invoke\",307,0,\"add\",[\"f32:4286578688\",\"f32:2155872256\"]],[\"invoke\",312,0,\"add\",[\"f32:4286578688\",\"f32:1056964608\"]],[\"invoke\",317,0,\"add\",[\"f32:2139095040\",\"f32:3212836864\"]],[\"invoke\",322,0,\"add\",[\"f32:2139095040\",\"f32:1086918619\"]],[\"invoke\",327,0,\"add\",[\"f32:4286578688\",\"f32:4286578688\"]],[\"invoke\",333,0,\"add\",[\"f32:4286578688\",\"f32:2143289344\"]],[\"invoke\",343,0,\"add\",[\"f32:2143289344\",\"f32:2147483648\"]],[\"invoke\",353,0,\"add\",[\"f32:2143289344\",\"f32:1\"]],[\"invoke\",365,0,\"add\",[\"f32:4290772992\",\"f32:1056964608\"]],[\"invoke\",375,0,\"add\",[\"f32:2143289344\",\"f32:3212836864\"]],[\"invoke\",385,0,\"add\",[\"f32:2143289344\",\"f32:1086918619\"]],[\"invoke\",395,0,\"add\",[\"f32:4290772992\",\"f32:4286578688\"]],[\"invoke\",407,0,\"add\",[\"f32:4290772992\",\"f32:2143289344\"]],[\"invoke\",421,0,\"sub\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",426,0,\"sub\",[\"f32:0\",\"f32:1\"]],[\"invoke\",431,0,\"sub\",[\"f32:2147483648\",\"f32:3204448256\"]],[\"invoke\",436,0,\"sub\",[\"f32:2147483648\",\"f32:1065353216\"]],[\"invoke\",441,0,\"sub\",[\"f32:0\",\"f32:3234402267\"]],[\"invoke\",446,0,\"sub\",[\"f32:0\",\"f32:2139095039\"]],[\"invoke\",451,0,\"sub\",[\"f32:2147483648\",\"f32:4290772992\"]],[\"invoke\",461,0,\"sub\",[\"f32:1\",\"f32:2147483648\"]],[\"invoke\",466,0,\"sub\",[\"f32:1\",\"f32:1\"]],[\"invoke\",471,0,\"sub\",[\"f32:2147483649\",\"f32:3204448256\"]],[\"invoke\",476,0,\"sub\",[\"f32:2147483649\",\"f32:1065353216\"]],[\"invoke\",481,0,\"sub\",[\"f32:1\",\"f32:3234402267\"]],[\"invoke\",486,0,\"sub\",[\"f32:1\",\"f32:2139095039\"]],[\"invoke\",491,0,\"sub\",[\"f32:2147483649\",\"f32:4290772992\"]],[\"invoke\",500,0,\"sub\",[\"f32:2155872256\",\"f32:0\"]],[\"invoke\",505,0,\"sub\",[\"f32:8388608\",\"f32:2147483649\"]],[\"invoke\",510,0,\"sub\",[\"f32:8388608\",\"f32:8388608\"]],[\"invoke\",515,0,\"sub\",[\"f32:2155872256\",\"f32:3212836864\"]],[\"invoke\",520,0,\"sub\",[\"f32:2155872256\",\"f32:1086918619\"]],[\"invoke\",526,0,\"sub\",[\"f32:8388608\",\"f32:2139095039\"]],[\"invoke\",531,0,\"sub\",[\"f32:2155872256\",\"f32:4290772992\"]],[\"invoke\",540,0,\"sub\",[\"f32:3204448256\",\"f32:0\"]],[\"invoke\",545,0,\"sub\",[\"f32:1056964608\",\"f32:2147483649\"]],[\"invoke\",550,0,\"sub\",[\"f32:1056964608\",\"f32:8388608\"]],[\"invoke\",555,0,\"sub\",[\"f32:3204448256\",\"f32:3212836864\"]],[\"invoke\",560,0,\"sub\",[\"f32:3204448256\",\"f32:1086918619\"]],[\"invoke\",565,0,\"sub\",[\"f32:1056964608\",\"f32:4286578687\"]],[\"invoke\",570,0,\"sub\",[\"f32:1056964608\",\"f32:2139095040\"]],[\"invoke\",579,0,\"sub\",[\"f32:3212836864\",\"f32:2147483648\"]],[\"invoke\",584,0,\"sub\",[\"f32:3212836864\",\"f32:1\"]],[\"invoke\",589,0,\"sub\",[\"f32:1065353216\",\"f32:2155872256\"]],[\"invoke\",595,0,\"sub\",[\"f32:3212836864\",\"f32:3212836864\"]],[\"invoke\",600,0,\"sub\",[\"f32:3212836864\",\"f32:1086918619\"]],[\"invoke\",605,0,\"sub\",[\"f32:1065353216\",\"f32:4286578687\"]],[\"invoke\",610,0,\"sub\",[\"f32:1065353216\",\"f32:2139095040\"]],[\"invoke\",619,0,\"sub\",[\"f32:3234402267\",\"f32:2147483648\"]],[\"invoke\",624,0,\"sub\",[\"f32:3234402267\",\"f32:1\"]],[\"invoke\",629,0,\"sub\",[\"f32:1086918619\",\"f32:2155872256\"]],[\"invoke\",634,0,\"sub\",[\"f32:1086918619\",\"f32:1056964608\"]],[\"invoke\",639,0,\"sub\",[\"f32:3234402267\",\"f32:3234402267\"]],[\"invoke\",644,0,\"sub\",[\"f32:3234402267\",\"f32:2139095039\"]],[\"invoke\",649,0,\"sub\",[\"f32:1086918619\",\"f32:4286578688\"]],[\"invoke\",659,0,\"sub\",[\"f32:4286578687\",\"f32:2147483648\"]],[\"invoke\",664,0,\"sub\",[\"f32:4286578687\",\"f32:1\"]],[\"invoke\",669,0,\"sub\",[\"f32:2139095039\",\"f32:2155872256\"]],[\"invoke\",674,0,\"sub\",[\"f32:2139095039\",\"f32:1056964608\"]],[\"invoke\",679,0,\"sub\",[\"f32:4286578687\",\"f32:3234402267\"]],[\"invoke\",684,0,\"sub\",[\"f32:4286578687\",\"f32:2139095039\"]],[\"invoke\",689,0,\"sub\",[\"f32:2139095039\",\"f32:4286578688\"]],[\"invoke\",697,0,\"sub\",[\"f32:2139095039\",\"f32:2143289344\"]],[\"invoke\",703,0,\"sub\",[\"f32:4286578688\",\"f32:2147483649\"]],[\"invoke\",708,0,\"sub\",[\"f32:4286578688\",\"f32:8388608\"]],[\"invoke\",713,0,\"sub\",[\"f32:2139095040\",\"f32:3204448256\"]],[\"invoke\",718,0,\"sub\",[\"f32:2139095040\",\"f32:1065353216\"]],[\"invoke\",724,0,\"sub\",[\"f32:4286578688\",\"f32:2139095039\"]],[\"invoke\",729,0,\"sub\",[\"f32:2139095040\",\"f32:4286578688\"]],[\"invoke\",737,0,\"sub\",[\"f32:2139095040\",\"f32:2143289344\"]],[\"invoke\",747,0,\"sub\",[\"f32:4290772992\",\"f32:2147483649\"]],[\"invoke\",757,0,\"sub\",[\"f32:4290772992\",\"f32:8388608\"]],[\"invoke\",767,0,\"sub\",[\"f32:2143289344\",\"f32:3204448256\"]],[\"invoke\",777,0,\"sub\",[\"f32:2143289344\",\"f32:1065353216\"]],[\"invoke\",787,0,\"sub\",[\"f32:4290772992\",\"f32:4286578687\"]],[\"invoke\",797,0,\"sub\",[\"f32:4290772992\",\"f32:2139095040\"]],[\"invoke\",811,0,\"sub\",[\"f32:2143289344\",\"f32:4290772992\"]],[\"invoke\",822,0,\"mul\",[\"f32:0\",\"f32:0\"]],[\"invoke\",827,0,\"mul\",[\"f32:2147483648\",\"f32:2155872256\"]],[\"invoke\",833,0,\"mul\",[\"f32:0\",\"f32:3204448256\"]],[\"invoke\",838,0,\"mul\",[\"f32:0\",\"f32:1065353216\"]],[\"invoke\",843,0,\"mul\",[\"f32:2147483648\",\"f32:4286578687\"]],[\"invoke\",848,0,\"mul\",[\"f32:2147483648\",\"f32:2139095040\"]],[\"invoke\",855,0,\"mul\",[\"f32:0\",\"f32:4290772992\"]],[\"invoke\",862,0,\"mul\",[\"f32:1\",\"f32:0\"]],[\"invoke\",867,0,\"mul\",[\"f32:2147483649\",\"f32:2155872256\"]],[\"invoke\",872,0,\"mul\",[\"f32:2147483649\",\"f32:1056964608\"]],[\"invoke\",877,0,\"mul\",[\"f32:1\",\"f32:3212836864\"]],[\"invoke\",882,0,\"mul\",[\"f32:1\",\"f32:1086918619\"]],[\"invoke\",887,0,\"mul\",[\"f32:2147483649\",\"f32:4286578688\"]],[\"invoke\",893,0,\"mul\",[\"f32:2147483649\",\"f32:2143289344\"]],[\"invoke\",902,0,\"mul\",[\"f32:8388608\",\"f32:0\"]],[\"invoke\",907,0,\"mul\",[\"f32:2155872256\",\"f32:2155872256\"]],[\"invoke\",912,0,\"mul\",[\"f32:2155872256\",\"f32:1056964608\"]],[\"invoke\",917,0,\"mul\",[\"f32:8388608\",\"f32:3212836864\"]],[\"invoke\",922,0,\"mul\",[\"f32:8388608\",\"f32:1086918619\"]],[\"invoke\",927,0,\"mul\",[\"f32:2155872256\",\"f32:4286578688\"]],[\"invoke\",933,0,\"mul\",[\"f32:2155872256\",\"f32:2143289344\"]],[\"invoke\",941,0,\"mul\",[\"f32:1056964608\",\"f32:2147483648\"]],[\"invoke\",946,0,\"mul\",[\"f32:1056964608\",\"f32:1\"]],[\"invoke\",951,0,\"mul\",[\"f32:3204448256\",\"f32:3204448256\"]],[\"invoke\",956,0,\"mul\",[\"f32:3204448256\",\"f32:1065353216\"]],[\"invoke\",962,0,\"mul\",[\"f32:1056964608\",\"f32:1086918619\"]],[\"invoke\",967,0,\"mul\",[\"f32:3204448256\",\"f32:4286578688\"]],[\"invoke\",973,0,\"mul\",[\"f32:3204448256\",\"f32:2143289344\"]],[\"invoke\",981,0,\"mul\",[\"f32:1065353216\",\"f32:2147483648\"]],[\"invoke\",986,0,\"mul\",[\"f32:1065353216\",\"f32:1\"]],[\"invoke\",991,0,\"mul\",[\"f32:3212836864\",\"f32:3204448256\"]],[\"invoke\",996,0,\"mul\",[\"f32:3212836864\",\"f32:1065353216\"]],[\"invoke\",1001,0,\"mul\",[\"f32:1065353216\",\"f32:3234402267\"]],[\"invoke\",1006,0,\"mul\",[\"f32:1065353216\",\"f32:2139095039\"]],[\"invoke\",1011,0,\"mul\",[\"f32:3212836864\",\"f32:4290772992\"]],[\"invoke\",1020,0,\"mul\",[\"f32:3234402267\",\"f32:0\"]],[\"invoke\",1025,0,\"mul\",[\"f32:1086918619\",\"f32:2147483649\"]],[\"invoke\",1031,0,\"mul\",[\"f32:3234402267\",\"f32:3204448256\"]],[\"invoke\",1036,0,\"mul\",[\"f32:3234402267\",\"f32:1065353216\"]],[\"invoke\",1041,0,\"mul\",[\"f32:1086918619\",\"f32:3234402267\"]],[\"invoke\",1046,0,\"mul\",[\"f32:1086918619\",\"f32:2139095039\"]],[\"invoke\",1051,0,\"mul\",[\"f32:3234402267\",\"f32:4290772992\"]],[\"invoke\",1060,0,\"mul\",[\"f32:4286578687\",\"f32:0\"]],[\"invoke\",1065,0,\"mul\",[\"f32:2139095039\",\"f32:2147483649\"]],[\"invoke\",1070,0,\"mul\",[\"f32:2139095039\",\"f32:8388608\"]],[\"invoke\",1075,0,\"mul\",[\"f32:4286578687\",\"f32:3212836864\"]],[\"invoke\",1080,0,\"mul\",[\"f32:4286578687\",\"f32:1086918619\"]],[\"invoke\",1085,0,\"mul\",[\"f32:2139095039\",\"f32:4286578687\"]],[\"invoke\",1090,0,\"mul\",[\"f32:2139095039\",\"f32:2139095040\"]],[\"invoke\",1100,0,\"mul\",[\"f32:4286578688\",\"f32:0\"]],[\"invoke\",1105,0,\"mul\",[\"f32:2139095040\",\"f32:2147483649\"]],[\"invoke\",1110,0,\"mul\",[\"f32:2139095040\",\"f32:8388608\"]],[\"invoke\",1115,0,\"mul\",[\"f32:4286578688\",\"f32:3212836864\"]],[\"invoke\",1120,0,\"mul\",[\"f32:4286578688\",\"f32:1086918619\"]],[\"invoke\",1125,0,\"mul\",[\"f32:2139095040\",\"f32:4286578687\"]],[\"invoke\",1130,0,\"mul\",[\"f32:2139095040\",\"f32:2139095040\"]],[\"invoke\",1139,0,\"mul\",[\"f32:4290772992\",\"f32:2147483648\"]],[\"invoke\",1149,0,\"mul\",[\"f32:4290772992\",\"f32:1\"]],[\"invoke\",1159,0,\"mul\",[\"f32:2143289344\",\"f32:2155872256\"]],[\"invoke\",1169,0,\"mul\",[\"f32:2143289344\",\"f32:1056964608\"]],[\"invoke\",1179,0,\"mul\",[\"f32:4290772992\",\"f32:3234402267\"]],[\"invoke\",1191,0,\"mul\",[\"f32:2143289344\",\"f32:4286578687\"]],[\"invoke\",1201,0,\"mul\",[\"f32:2143289344\",\"f32:2139095040\"]],[\"invoke\",1219,0,\"div\",[\"f32:2147483648\",\"f32:2147483648\"]],[\"invoke\",1224,0,\"div\",[\"f32:2147483648\",\"f32:1\"]],[\"invoke\",1229,0,\"div\",[\"f32:0\",\"f32:2155872256\"]],[\"invoke\",1234,0,\"div\",[\"f32:0\",\"f32:1056964608\"]],[\"invoke\",1239,0,\"div\",[\"f32:2147483648\",\"f32:3234402267\"]],[\"invoke\",1244,0,\"div\",[\"f32:2147483648\",\"f32:2139095039\"]],[\"invoke\",1249,0,\"div\",[\"f32:0\",\"f32:4286578688\"]],[\"invoke\",1257,0,\"div\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1263,0,\"div\",[\"f32:2147483649\",\"f32:2147483649\"]],[\"invoke\",1269,0,\"div\",[\"f32:1\",\"f32:2155872256\"]],[\"invoke\",1274,0,\"div\",[\"f32:1\",\"f32:1056964608\"]],[\"invoke\",1279,0,\"div\",[\"f32:2147483649\",\"f32:3234402267\"]],[\"invoke\",1284,0,\"div\",[\"f32:2147483649\",\"f32:2139095039\"]],[\"invoke\",1289,0,\"div\",[\"f32:1\",\"f32:4286578688\"]],[\"invoke\",1297,0,\"div\",[\"f32:1\",\"f32:2143289344\"]],[\"invoke\",1303,0,\"div\",[\"f32:2155872256\",\"f32:2147483649\"]],[\"invoke\",1308,0,\"div\",[\"f32:2155872256\",\"f32:8388608\"]],[\"invoke\",1313,0,\"div\",[\"f32:8388608\",\"f32:3204448256\"]],[\"invoke\",1318,0,\"div\",[\"f32:8388608\",\"f32:1065353216\"]],[\"invoke\",1323,0,\"div\",[\"f32:2155872256\",\"f32:4286578687\"]],[\"invoke\",1328,0,\"div\",[\"f32:2155872256\",\"f32:2139095040\"]],[\"invoke\",1337,0,\"div\",[\"f32:8388608\",\"f32:2143289344\"]],[\"invoke\",1343,0,\"div\",[\"f32:3204448256\",\"f32:2147483649\"]],[\"invoke\",1348,0,\"div\",[\"f32:3204448256\",\"f32:8388608\"]],[\"invoke\",1353,0,\"div\",[\"f32:1056964608\",\"f32:3204448256\"]],[\"invoke\",1358,0,\"div\",[\"f32:1056964608\",\"f32:1065353216\"]],[\"invoke\",1363,0,\"div\",[\"f32:3204448256\",\"f32:4286578687\"]],[\"invoke\",1368,0,\"div\",[\"f32:3204448256\",\"f32:2139095040\"]],[\"invoke\",1375,0,\"div\",[\"f32:1056964608\",\"f32:4290772992\"]],[\"invoke\",1382,0,\"div\",[\"f32:1065353216\",\"f32:0\"]],[\"invoke\",1387,0,\"div\",[\"f32:3212836864\",\"f32:2155872256\"]],[\"invoke\",1392,0,\"div\",[\"f32:3212836864\",\"f32:1056964608\"]],[\"invoke\",1397,0,\"div\",[\"f32:1065353216\",\"f32:3212836864\"]],[\"invoke\",1403,0,\"div\",[\"f32:3212836864\",\"f32:4286578687\"]],[\"invoke\",1408,0,\"div\",[\"f32:3212836864\",\"f32:2139095040\"]],[\"invoke\",1415,0,\"div\",[\"f32:1065353216\",\"f32:4290772992\"]],[\"invoke\",1422,0,\"div\",[\"f32:1086918619\",\"f32:0\"]],[\"invoke\",1427,0,\"div\",[\"f32:3234402267\",\"f32:2155872256\"]],[\"invoke\",1432,0,\"div\",[\"f32:3234402267\",\"f32:1056964608\"]],[\"invoke\",1437,0,\"div\",[\"f32:1086918619\",\"f32:3212836864\"]],[\"invoke\",1442,0,\"div\",[\"f32:1086918619\",\"f32:1086918619\"]],[\"invoke\",1447,0,\"div\",[\"f32:3234402267\",\"f32:4286578688\"]],[\"invoke\",1453,0,\"div\",[\"f32:3234402267\",\"f32:2143289344\"]],[\"invoke\",1461,0,\"div\",[\"f32:2139095039\",\"f32:2147483648\"]],[\"invoke\",1466,0,\"div\",[\"f32:2139095039\",\"f32:1\"]],[\"invoke\",1472,0,\"div\",[\"f32:4286578687\",\"f32:1056964608\"]],[\"invoke\",1477,0,\"div\",[\"f32:2139095039\",\"f32:3212836864\"]],[\"invoke\",1482,0,\"div\",[\"f32:2139095039\",\"f32:1086918619\"]],[\"invoke\",1487,0,\"div\",[\"f32:4286578687\",\"f32:4286578688\"]],[\"invoke\",1493,0,\"div\",[\"f32:4286578687\",\"f32:2143289344\"]],[\"invoke\",1501,0,\"div\",[\"f32:2139095040\",\"f32:2147483648\"]],[\"invoke\",1506,0,\"div\",[\"f32:2139095040\",\"f32:1\"]],[\"invoke\",1511,0,\"div\",[\"f32:4286578688\",\"f32:3204448256\"]],[\"invoke\",1516,0,\"div\",[\"f32:4286578688\",\"f32:1065353216\"]],[\"invoke\",1521,0,\"div\",[\"f32:2139095040\",\"f32:3234402267\"]],[\"invoke\",1526,0,\"div\",[\"f32:2139095040\",\"f32:2139095039\"]],[\"invoke\",1531,0,\"div\",[\"f32:4286578688\",\"f32:4290772992\"]],[\"invoke\",1543,0,\"div\",[\"f32:2143289344\",\"f32:2147483648\"]],[\"invoke\",1553,0,\"div\",[\"f32:2143289344\",\"f32:1\"]],[\"invoke\",1563,0,\"div\",[\"f32:4290772992\",\"f32:3204448256\"]],[\"invoke\",1573,0,\"div\",[\"f32:4290772992\",\"f32:1065353216\"]],[\"invoke\",1583,0,\"div\",[\"f32:2143289344\",\"f32:3234402267\"]],[\"invoke\",1593,0,\"div\",[\"f32:2143289344\",\"f32:2139095039\"]],[\"invoke\",1603,0,\"div\",[\"f32:4290772992\",\"f32:4290772992\"]],[\"invoke\",1620,0,\"min\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",1625,0,\"min\",[\"f32:0\",\"f32:2147483649\"]],[\"invoke\",1630,0,\"min\",[\"f32:0\",\"f32:8388608\"]],[\"invoke\",1635,0,\"min\",[\"f32:2147483648\",\"f32:3212836864\"]],[\"invoke\",1641,0,\"min\",[\"f32:0\",\"f32:3234402267\"]],[\"invoke\",1646,0,\"min\",[\"f32:0\",\"f32:2139095039\"]],[\"invoke\",1651,0,\"min\",[\"f32:2147483648\",\"f32:4290772992\"]],[\"invoke\",1660,0,\"min\",[\"f32:2147483649\",\"f32:0\"]],[\"invoke\",1665,0,\"min\",[\"f32:1\",\"f32:2147483649\"]],[\"invoke\",1670,0,\"min\",[\"f32:1\",\"f32:8388608\"]],[\"invoke\",1675,0,\"min\",[\"f32:2147483649\",\"f32:3212836864\"]],[\"invoke\",1680,0,\"min\",[\"f32:2147483649\",\"f32:1086918619\"]],[\"invoke\",1685,0,\"min\",[\"f32:1\",\"f32:4286578687\"]],[\"invoke\",1690,0,\"min\",[\"f32:1\",\"f32:2139095040\"]],[\"invoke\",1699,0,\"min\",[\"f32:2155872256\",\"f32:2147483648\"]],[\"invoke\",1704,0,\"min\",[\"f32:2155872256\",\"f32:1\"]],[\"invoke\",1710,0,\"min\",[\"f32:8388608\",\"f32:8388608\"]],[\"invoke\",1715,0,\"min\",[\"f32:2155872256\",\"f32:3212836864\"]],[\"invoke\",1720,0,\"min\",[\"f32:2155872256\",\"f32:1086918619\"]],[\"invoke\",1725,0,\"min\",[\"f32:8388608\",\"f32:4286578687\"]],[\"invoke\",1730,0,\"min\",[\"f32:8388608\",\"f32:2139095040\"]],[\"invoke\",1739,0,\"min\",[\"f32:3204448256\",\"f32:2147483648\"]],[\"invoke\",1744,0,\"min\",[\"f32:3204448256\",\"f32:1\"]],[\"invoke\",1749,0,\"min\",[\"f32:1056964608\",\"f32:2155872256\"]],[\"invoke\",1754,0,\"min\",[\"f32:1056964608\",\"f32:1056964608\"]],[\"invoke\",1759,0,\"min\",[\"f32:3204448256\",\"f32:3234402267\"]],[\"invoke\",1764,0,\"min\",[\"f32:3204448256\",\"f32:2139095039\"]],[\"invoke\",1769,0,\"min\",[\"f32:1056964608\",\"f32:4286578688\"]],[\"invoke\",1779,0,\"min\",[\"f32:3212836864\",\"f32:2147483648\"]],[\"invoke\",1784,0,\"min\",[\"f32:3212836864\",\"f32:1\"]],[\"invoke\",1789,0,\"min\",[\"f32:1065353216\",\"f32:2155872256\"]],[\"invoke\",1794,0,\"min\",[\"f32:1065353216\",\"f32:1056964608\"]],[\"invoke\",1799,0,\"min\",[\"f32:3212836864\",\"f32:3234402267\"]],[\"invoke\",1804,0,\"min\",[\"f32:3212836864\",\"f32:2139095039\"]],[\"invoke\",1809,0,\"min\",[\"f32:1065353216\",\"f32:4286578688\"]],[\"invoke\",1817,0,\"min\",[\"f32:1065353216\",\"f32:2143289344\"]],[\"invoke\",1823,0,\"min\",[\"f32:3234402267\",\"f32:2147483649\"]],[\"invoke\",1828,0,\"min\",[\"f32:3234402267\",\"f32:8388608\"]],[\"invoke\",1833,0,\"min\",[\"f32:1086918619\",\"f32:3204448256\"]],[\"invoke\",1838,0,\"min\",[\"f32:1086918619\",\"f32:1065353216\"]],[\"invoke\",1844,0,\"min\",[\"f32:3234402267\",\"f32:2139095039\"]],[\"invoke\",1849,0,\"min\",[\"f32:1086918619\",\"f32:4286578688\"]],[\"invoke\",1857,0,\"min\",[\"f32:1086918619\",\"f32:2143289344\"]],[\"invoke\",1863,0,\"min\",[\"f32:4286578687\",\"f32:2147483649\"]],[\"invoke\",1868,0,\"min\",[\"f32:4286578687\",\"f32:8388608\"]],[\"invoke\",1873,0,\"min\",[\"f32:2139095039\",\"f32:3204448256\"]],[\"invoke\",1878,0,\"min\",[\"f32:2139095039\",\"f32:1065353216\"]],[\"invoke\",1883,0,\"min\",[\"f32:4286578687\",\"f32:4286578687\"]],[\"invoke\",1888,0,\"min\",[\"f32:4286578687\",\"f32:2139095040\"]],[\"invoke\",1895,0,\"min\",[\"f32:2139095039\",\"f32:4290772992\"]],[\"invoke\",1902,0,\"min\",[\"f32:2139095040\",\"f32:0\"]],[\"invoke\",1908,0,\"min\",[\"f32:4286578688\",\"f32:8388608\"]],[\"invoke\",1913,0,\"min\",[\"f32:2139095040\",\"f32:3204448256\"]],[\"invoke\",1918,0,\"min\",[\"f32:2139095040\",\"f32:1065353216\"]],[\"invoke\",1923,0,\"min\",[\"f32:4286578688\",\"f32:4286578687\"]],[\"invoke\",1928,0,\"min\",[\"f32:4286578688\",\"f32:2139095040\"]],[\"invoke\",1935,0,\"min\",[\"f32:2139095040\",\"f32:4290772992\"]],[\"invoke\",1945,0,\"min\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",1955,0,\"min\",[\"f32:4290772992\",\"f32:2155872256\"]],[\"invoke\",1965,0,\"min\",[\"f32:4290772992\",\"f32:1056964608\"]],[\"invoke\",1975,0,\"min\",[\"f32:2143289344\",\"f32:3212836864\"]],[\"invoke\",1985,0,\"min\",[\"f32:2143289344\",\"f32:1086918619\"]],[\"invoke\",1995,0,\"min\",[\"f32:4290772992\",\"f32:4286578688\"]],[\"invoke\",2011,0,\"min\",[\"f32:2143289344\",\"f32:4290772992\"]],[\"invoke\",2022,0,\"max\",[\"f32:0\",\"f32:0\"]],[\"invoke\",2027,0,\"max\",[\"f32:2147483648\",\"f32:2155872256\"]],[\"invoke\",2032,0,\"max\",[\"f32:2147483648\",\"f32:1056964608\"]],[\"invoke\",2037,0,\"max\",[\"f32:0\",\"f32:3212836864\"]],[\"invoke\",2042,0,\"max\",[\"f32:0\",\"f32:1086918619\"]],[\"invoke\",2047,0,\"max\",[\"f32:2147483648\",\"f32:4286578688\"]],[\"invoke\",2053,0,\"max\",[\"f32:2147483648\",\"f32:2143289344\"]],[\"invoke\",2061,0,\"max\",[\"f32:1\",\"f32:2147483648\"]],[\"invoke\",2066,0,\"max\",[\"f32:1\",\"f32:1\"]],[\"invoke\",2071,0,\"max\",[\"f32:2147483649\",\"f32:3204448256\"]],[\"invoke\",2076,0,\"max\",[\"f32:2147483649\",\"f32:1065353216\"]],[\"invoke\",2082,0,\"max\",[\"f32:1\",\"f32:1086918619\"]],[\"invoke\",2087,0,\"max\",[\"f32:2147483649\",\"f32:4286578688\"]],[\"invoke\",2093,0,\"max\",[\"f32:2147483649\",\"f32:2143289344\"]],[\"invoke\",2101,0,\"max\",[\"f32:8388608\",\"f32:2147483648\"]],[\"invoke\",2106,0,\"max\",[\"f32:8388608\",\"f32:1\"]],[\"invoke\",2111,0,\"max\",[\"f32:2155872256\",\"f32:3204448256\"]],[\"invoke\",2116,0,\"max\",[\"f32:2155872256\",\"f32:1065353216\"]],[\"invoke\",2121,0,\"max\",[\"f32:8388608\",\"f32:3234402267\"]],[\"invoke\",2126,0,\"max\",[\"f32:8388608\",\"f32:2139095039\"]],[\"invoke\",2131,0,\"max\",[\"f32:2155872256\",\"f32:4290772992\"]],[\"invoke\",2140,0,\"max\",[\"f32:3204448256\",\"f32:0\"]],[\"invoke\",2145,0,\"max\",[\"f32:1056964608\",\"f32:2147483649\"]],[\"invoke\",2151,0,\"max\",[\"f32:3204448256\",\"f32:3204448256\"]],[\"invoke\",2156,0,\"max\",[\"f32:3204448256\",\"f32:1065353216\"]],[\"invoke\",2161,0,\"max\",[\"f32:1056964608\",\"f32:3234402267\"]],[\"invoke\",2166,0,\"max\",[\"f32:1056964608\",\"f32:2139095039\"]],[\"invoke\",2171,0,\"max\",[\"f32:3204448256\",\"f32:4290772992\"]],[\"invoke\",2180,0,\"max\",[\"f32:3212836864\",\"f32:0\"]],[\"invoke\",2185,0,\"max\",[\"f32:1065353216\",\"f32:2147483649\"]],[\"invoke\",2190,0,\"max\",[\"f32:1065353216\",\"f32:8388608\"]],[\"invoke\",2195,0,\"max\",[\"f32:3212836864\",\"f32:3212836864\"]],[\"invoke\",2200,0,\"max\",[\"f32:3212836864\",\"f32:1086918619\"]],[\"invoke\",2205,0,\"max\",[\"f32:1065353216\",\"f32:4286578687\"]],[\"invoke\",2211,0,\"max\",[\"f32:3212836864\",\"f32:4290772992\"]],[\"invoke\",2220,0,\"max\",[\"f32:3234402267\",\"f32:0\"]],[\"invoke\",2225,0,\"max\",[\"f32:1086918619\",\"f32:2147483649\"]],[\"invoke\",2230,0,\"max\",[\"f32:1086918619\",\"f32:8388608\"]],[\"invoke\",2235,0,\"max\",[\"f32:3234402267\",\"f32:3212836864\"]],[\"invoke\",2240,0,\"max\",[\"f32:3234402267\",\"f32:1086918619\"]],[\"invoke\",2245,0,\"max\",[\"f32:1086918619\",\"f32:4286578687\"]],[\"invoke\",2250,0,\"max\",[\"f32:1086918619\",\"f32:2139095040\"]],[\"invoke\",2259,0,\"max\",[\"f32:4286578687\",\"f32:2147483648\"]],[\"invoke\",2264,0,\"max\",[\"f32:4286578687\",\"f32:1\"]],[\"invoke\",2269,0,\"max\",[\"f32:2139095039\",\"f32:2155872256\"]],[\"invoke\",2274,0,\"max\",[\"f32:2139095039\",\"f32:1056964608\"]],[\"invoke\",2280,0,\"max\",[\"f32:4286578687\",\"f32:1086918619\"]],[\"invoke\",2285,0,\"max\",[\"f32:2139095039\",\"f32:4286578687\"]],[\"invoke\",2290,0,\"max\",[\"f32:2139095039\",\"f32:2139095040\"]],[\"invoke\",2299,0,\"max\",[\"f32:4286578688\",\"f32:2147483648\"]],[\"invoke\",2304,0,\"max\",[\"f32:4286578688\",\"f32:1\"]],[\"invoke\",2309,0,\"max\",[\"f32:2139095040\",\"f32:2155872256\"]],[\"invoke\",2314,0,\"max\",[\"f32:2139095040\",\"f32:1056964608\"]],[\"invoke\",2319,0,\"max\",[\"f32:4286578688\",\"f32:3234402267\"]],[\"invoke\",2324,0,\"max\",[\"f32:4286578688\",\"f32:2139095039\"]],[\"invoke\",2329,0,\"max\",[\"f32:2139095040\",\"f32:4286578688\"]],[\"invoke\",2337,0,\"max\",[\"f32:2139095040\",\"f32:2143289344\"]],[\"invoke\",2347,0,\"max\",[\"f32:4290772992\",\"f32:2147483649\"]],[\"invoke\",2359,0,\"max\",[\"f32:2143289344\",\"f32:2155872256\"]],[\"invoke\",2369,0,\"max\",[\"f32:2143289344\",\"f32:1056964608\"]],[\"invoke\",2379,0,\"max\",[\"f32:4290772992\",\"f32:3234402267\"]],[\"invoke\",2389,0,\"max\",[\"f32:4290772992\",\"f32:2139095039\"]],[\"invoke\",2399,0,\"max\",[\"f32:2143289344\",\"f32:4286578688\"]],[\"invoke\",2415,0,\"max\",[\"f32:2143289344\",\"f32:2143289344\"]],[\"invoke\",2423,0,\"sqrt\",[\"f32:2155872256\"]],[\"invoke\",2428,0,\"sqrt\",[\"f32:1065353216\"]],[\"invoke\",2433,0,\"sqrt\",[\"f32:4286578688\"]],[\"invoke\",2440,0,\"floor\",[\"f32:0\"]],[\"invoke\",2445,0,\"floor\",[\"f32:3204448256\"]],[\"invoke\",2450,0,\"floor\",[\"f32:1086918619\"]],[\"invoke\",2457,0,\"floor\",[\"f32:2143289344\"]],[\"invoke\",2463,0,\"ceil\",[\"f32:2155872256\"]],[\"invoke\",2468,0,\"ceil\",[\"f32:1065353216\"]],[\"invoke\",2473,0,\"ceil\",[\"f32:4286578688\"]],[\"invoke\",2480,0,\"trunc\",[\"f32:0\"]],[\"invoke\",2485,0,\"trunc\",[\"f32:3204448256\"]],[\"invoke\",2490,0,\"trunc\",[\"f32:1086918619\"]],[\"invoke\",2495,0,\"trunc\",[\"f32:4290772992\"]],[\"invoke\",2502,0,\"nearest\",[\"f32:1\"]],[\"invoke\",2507,0,\"nearest\",[\"f32:3212836864\"]],[\"invoke\",2512,0,\"nearest\",[\"f32:2139095039\"]],[\"file\",\"f64.wast\"],[\"module\",5,1],[\"invoke\",19,0,\"add\",[\"f64:9223372036854775808\",\"f64:9223372036854775808\"]],[\"invoke\",25,0,\"add\",[\"f64:0\",\"f64:9223372036854775809\"]],[\"invoke\",30,0,\"add\",[\"f64:0\",\"f64:4503599627370496\"]],[\"invoke\",35,0,\"add\",[\"f64:9223372036854775808\",\"f64:13830554455654793216\"]],[\"invoke\",40,0,\"add\",[\"f64:9223372036854775808\",\"f64:4618760256179416344\"]],[\"invoke\",45,0,\"add\",[\"f64:0\",\"f64:18442240474082181119\"]],[\"invoke\",50,0,\"add\",[\"f64:0\",\"f64:9218868437227405312\"]],[\"invoke\",59,0,\"add\",[\"f64:9223372036854775809\",\"f64:9223372036854775808\"]],[\"invoke\",64,0,\"add\",[\"f64:9223372036854775809\",\"f64:1\"]],[\"invoke\",69,0,\"add\",[\"f64:1\",\"f64:9227875636482146304\"]],[\"invoke\",74,0,\"add\",[\"f64:1\",\"f64:4602678819172646912\"]],[\"invoke\",79,0,\"add\",[\"f64:9223372036854775809\",\"f64:13842132293034192152\"]],[\"invoke\",85,0,\"add\",[\"f64:1\",\"f64:18442240474082181119\"]],[\"invoke\",90,0,\"add\",[\"f64:1\",\"f64:9218868437227405312\"]],[\"invoke\",99,0,\"add\",[\"f64:9227875636482146304\",\"f64:9223372036854775808\"]],[\"invoke\",104,0,\"add\",[\"f64:9227875636482146304\",\"f64:1\"]],[\"invoke\",109,0,\"add\",[\"f64:4503599627370496\",\"f64:9227875636482146304\"]],[\"invoke\",114,0,\"add\",[\"f64:4503599627370496\",\"f64:4602678819172646912\"]],[\"invoke\",119,0,\"add\",[\"f64:9227875636482146304\",\"f64:13842132293034192152\"]],[\"invoke\",124,0,\"add\",[\"f64:9227875636482146304\",\"f64:9218868437227405311\"]],[\"invoke\",129,0,\"add\",[\"f64:4503599627370496\",\"f64:18442240474082181120\"]],[\"invoke\",137,0,\"add\",[\"f64:4503599627370496\",\"f64:9221120237041090560\"]],[\"invoke\",143,0,\"add\",[\"f64:13826050856027422720\",\"f64:9223372036854775809\"]],[\"invoke\",148,0,\"add\",[\"f64:13826050856027422720\",\"f64:4503599627370496\"]],[\"invoke\",154,0,\"add\",[\"f64:4602678819172646912\",\"f64:4602678819172646912\"]],[\"invoke\",159,0,\"add\",[\"f64:13826050856027422720\",\"f64:13842132293034192152\"]],[\"invoke\",164,0,\"add\",[\"f64:13826050856027422720\",\"f64:9218868437227405311\"]],[\"invoke\",169,0,\"add\",[\"f64:4602678819172646912\",\"f64:18442240474082181120\"]],[\"invoke\",177,0,\"add\",[\"f64:4602678819172646912\",\"f64:9221120237041090560\"]],[\"invoke\",183,0,\"add\",[\"f64:13830554455654793216\",\"f64:9223372036854775809\"]],[\"invoke\",188,0,\"add\",[\"f64:13830554455654793216\",\"f64:4503599627370496\"]],[\"invoke\",193,0,\"add\",[\"f64:4607182418800017408\",\"f64:13826050856027422720\"]],[\"invoke\",198,0,\"add\",[\"f64:4607182418800017408\",\"f64:4607182418800017408\"]],[\"invoke\",203,0,\"add\",[\"f64:13830554455654793216\",\"f64:18442240474082181119\"]],[\"invoke\",208,0,\"add\",[\"f64:13830554455654793216\",\"f64:9218868437227405312\"]],[\"invoke\",215,0,\"add\",[\"f64:4607182418800017408\",\"f64:18444492273895866368\"]],[\"invoke\",223,0,\"add\",[\"f64:13842132293034192152\",\"f64:9223372036854775809\"]],[\"invoke\",228,0,\"add\",[\"f64:13842132293034192152\",\"f64:4503599627370496\"]],[\"invoke\",233,0,\"add\",[\"f64:4618760256179416344\",\"f64:13826050856027422720\"]],[\"invoke\",238,0,\"add\",[\"f64:4618760256179416344\",\"f64:4607182418800017408\"]],[\"invoke\",243,0,\"add\",[\"f64:13842132293034192152\",\"f64:18442240474082181119\"]],[\"invoke\",248,0,\"add\",[\"f64:13842132293034192152\",\"f64:9218868437227405312\"]],[\"invoke\",255,0,\"add\",[\"f64:4618760256179416344\",\"f64:18444492273895866368\"]],[\"invoke\",262,0,\"add\",[\"f64:9218868437227405311\",\"f64:0\"]],[\"invoke\",267,0,\"add\",[\"f64:18442240474082181119\",\"f64:9227875636482146304\"]],[\"invoke\",272,0,\"add\",[\"f64:18442240474082181119\",\"f64:4602678819172646912\"]],[\"invoke\",277,0,\"add\",[\"f64:9218868437227405311\",\"f64:13830554455654793216\"]],[\"invoke\",282,0,\"add\",[\"f64:9218868437227405311\",\"f64:4618760256179416344\"]],[\"invoke\",288,0,\"add\",[\"f64:18442240474082181119\",\"f64:9218868437227405312\"]],[\"invoke\",295,0,\"add\",[\"f64:9218868437227405311\",\"f64:18444492273895866368\"]],[\"invoke\",302,0,\"add\",[\"f64:9218868437227405312\",\"f64:0\"]],[\"invoke\",307,0,\"add\",[\"f64:18442240474082181120\",\"f64:9227875636482146304\"]],[\"invoke\",312,0,\"add\",[\"f64:18442240474082181120\",\"f64:4602678819172646912\"]],[\"invoke\",317,0,\"add\",[\"f64:9218868437227405312\",\"f64:13830554455654793216\"]],[\"invoke\",322,0,\"add\",[\"f64:9218868437227405312\",\"f64:4618760256179416344\"]],[\"invoke\",327,0,\"add\",[\"f64:18442240474082181120\",\"f64:18442240474082181120\"]],[\"invoke\",333,0,\"add\",[\"f64:18442240474082181120\",\"f64:9221120237041090560\"]],[\"invoke\",343,0,\"add\",[\"f64:9221120237041090560\",\"f64:9223372036854775808\"]],[\"invoke\",353,0,\"add\",[\"f64:9221120237041090560\",\"f64:1\"]],[\"invoke\",365,0,\"add\",[\"f64:18444492273895866368\",\"f64:4602678819172646912\"]],[\"invoke\",375,0,\"add\",[\"f64:9221120237041090560\",\"f64:13830554455654793216\"]],[\"invoke\",385,0,\"add\",[\"f64:9221120237041090560\",\"f64:4618760256179416344\"]],[\"invoke\",395,0,\"add\",[\"f64:18444492273895866368\",\"f64:18442240474082181120\"]],[\"invoke\",407,0,\"add\",[\"f64:18444492273895866368\",\"f64:9221120237041090560\"]],[\"invoke\",421,0,\"sub\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",426,0,\"sub\",[\"f64:0\",\"f64:1\"]],[\"invoke\",431,0,\"sub\",[\"f64:9223372036854775808\",\"f64:13826050856027422720\"]],[\"invoke\",436,0,\"sub\",[\"f64:9223372036854775808\",\"f64:4607182418800017408\"]],[\"invoke\",441,0,\"sub\",[\"f64:0\",\"f64:13842132293034192152\"]],[\"invoke\",446,0,\"sub\",[\"f64:0\",\"f64:9218868437227405311\"]],[\"invoke\",451,0,\"sub\",[\"f64:9223372036854775808\",\"f64:18444492273895866368\"]],[\"invoke\",461,0,\"sub\",[\"f64:1\",\"f64:9223372036854775808\"]],[\"invoke\",466,0,\"sub\",[\"f64:1\",\"f64:1\"]],[\"invoke\",471,0,\"sub\",[\"f64:9223372036854775809\",\"f64:13826050856027422720\"]],[\"invoke\",476,0,\"sub\",[\"f64:9223372036854775809\",\"f64:4607182418800017408\"]],[\"invoke\",481,0,\"sub\",[\"f64:1\",\"f64:13842132293034192152\"]],[\"invoke\",486,0,\"sub\",[\"f64:1\",\"f64:9218868437227405311\"]],[\"invoke\",491,0,\"sub\",[\"f64:9223372036854775809\",\"f64:18444492273895866368\"]],[\"invoke\",500,0,\"sub\",[\"f64:9227875636482146304\",\"f64:0\"]],[\"invoke\",505,0,\"sub\",[\"f64:4503599627370496\",\"f64:9223372036854775809\"]],[\"invoke\",510,0,\"sub\",[\"f64:4503599627370496\",\"f64:4503599627370496\"]],[\"invoke\",515,0,\"sub\",[\"f64:9227875636482146304\",\"f64:13830554455654793216\"]],[\"invoke\",520,0,\"sub\",[\"f64:9227875636482146304\",\"f64:4618760256179416344\"]],[\"invoke\",526,0,\"sub\",[\"f64:4503599627370496\",\"f64:9218868437227405311\"]],[\"invoke\",531,0,\"sub\",[\"f64:9227875636482146304\",\"f64:18444492273895866368\"]],[\"invoke\",540,0,\"sub\",[\"f64:13826050856027422720\",\"f64:0\"]],[\"invoke\",545,0,\"sub\",[\"f64:4602678819172646912\",\"f64:9223372036854775809\"]],[\"invoke\",550,0,\"sub\",[\"f64:4602678819172646912\",\"f64:4503599627370496\"]],[\"invoke\",555,0,\"sub\",[\"f64:13826050856027422720\",\"f64:13830554455654793216\"]],[\"invoke\",560,0,\"sub\",[\"f64:13826050856027422720\",\"f64:4618760256179416344\"]],[\"invoke\",565,0,\"sub\",[\"f64:4602678819172646912\",\"f64:18442240474082181119\"]],[\"invoke\",570,0,\"sub\",[\"f64:4602678819172646912\",\"f64:9218868437227405312\"]],[\"invoke\",579,0,\"sub\",[\"f64:13830554455654793216\",\"f64:9223372036854775808\"]],[\"invoke\",584,0,\"sub\",[\"f64:13830554455654793216\",\"f64:1\"]],[\"invoke\",589,0,\"sub\",[\"f64:4607182418800017408\",\"f64:9227875636482146304\"]],[\"invoke\",595,0,\"sub\",[\"f64:13830554455654793216\",\"f64:13830554455654793216\"]],[\"invoke\",600,0,\"sub\",[\"f64:13830554455654793216\",\"f64:4618760256179416344\"]],[\"invoke\",605,0,\"sub\",[\"f64:4607182418800017408\",\"f64:18442240474082181119\"]],[\"invoke\",610,0,\"sub\",[\"f64:4607182418800017408\",\"f64:9218868437227405312\"]],[\"invoke\",619,0,\"sub\",[\"f64:13842132293034192152\",\"f64:9223372036854775808\"]],[\"invoke\",624,0,\"sub\",[\"f64:13842132293034192152\",\"f64:1\"]],[\"invoke\",629,0,\"sub\",[\"f64:4618760256179416344\",\"f64:9227875636482146304\"]],[\"invoke\",634,0,\"sub\",[\"f64:4618760256179416344\",\"f64:4602678819172646912\"]],[\"invoke\",639,0,\"sub\",[\"f64:13842132293034192152\",\"f64:13842132293034192152\"]],[\"invoke\",644,0,\"sub\",[\"f64:13842132293034192152\",\"f64:9218868437227405311\"]],[\"invoke\",649,0,\"sub\",[\"f64:4618760256179416344\",\"f64:18442240474082181120\"]],[\"invoke\",659,0,\"sub\",[\"f64:18442240474082181119\",\"f64:9223372036854775808\"]],[\"invoke\",664,0,\"sub\",[\"f64:18442240474082181119\",\"f64:1\"]],[\"invoke\",669,0,\"sub\",[\"f64:9218868437227405311\",\"f64:9227875636482146304\"]],[\"invoke\",674,0,\"sub\",[\"f64:9218868437227405311\",\"f64:4602678819172646912\"]],[\"invoke\",679,0,\"sub\",[\"f64:18442240474082181119\",\"f64:13842132293034192152\"]],[\"invoke\",684,0,\"sub\",[\"f64:18442240474082181119\",\"f64:9218868437227405311\"]],[\"invoke\",689,0,\"sub\",[\"f64:9218868437227405311\",\"f64:18442240474082181120\"]],[\"invoke\",697,0,\"sub\",[\"f64:9218868437227405311\",\"f64:9221120237041090560\"]],[\"invoke\",703,0,\"sub\",[\"f64:18442240474082181120\",\"f64:9223372036854775809\"]],[\"invoke\",708,0,\"sub\",[\"f64:18442240474082181120\",\"f64:4503599627370496\"]],[\"invoke\",713,0,\"sub\",[\"f64:9218868437227405312\",\"f64:13826050856027422720\"]],[\"invoke\",718,0,\"sub\",[\"f64:9218868437227405312\",\"f64:4607182418800017408\"]],[\"invoke\",724,0,\"sub\",[\"f64:18442240474082181120\",\"f64:9218868437227405311\"]],[\"invoke\",729,0,\"sub\",[\"f64:9218868437227405312\",\"f64:18442240474082181120\"]],[\"invoke\",737,0,\"sub\",[\"f64:9218868437227405312\",\"f64:9221120237041090560\"]],[\"invoke\",747,0,\"sub\",[\"f64:18444492273895866368\",\"f64:9223372036854775809\"]],[\"invoke\",757,0,\"sub\",[\"f64:18444492273895866368\",\"f64:4503599627370496\"]],[\"invoke\",767,0,\"sub\",[\"f64:9221120237041090560\",\"f64:13826050856027422720\"]],[\"invoke\",777,0,\"sub\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\"]],[\"invoke\",787,0,\"sub\",[\"f64:18444492273895866368\",\"f64:18442240474082181119\"]],[\"invoke\",797,0,\"sub\",[\"f64:18444492273895866368\",\"f64:9218868437227405312\"]],[\"invoke\",811,0,\"sub\",[\"f64:9221120237041090560\",\"f64:18444492273895866368\"]],[\"invoke\",822,0,\"mul\",[\"f64:0\",\"f64:0\"]],[\"invoke\",827,0,\"mul\",[\"f64:9223372036854775808\",\"f64:9227875636482146304\"]],[\"invoke\",833,0,\"mul\",[\"f64:0\",\"f64:13826050856027422720\"]],[\"invoke\",838,0,\"mul\",[\"f64:0\",\"f64:4607182418800017408\"]],[\"invoke\",843,0,\"mul\",[\"f64:9223372036854775808\",\"f64:18442240474082181119\"]],[\"invoke\",848,0,\"mul\",[\"f64:9223372036854775808\",\"f64:9218868437227405312\"]],[\"invoke\",855,0,\"mul\",[\"f64:0\",\"f64:18444492273895866368\"]],[\"invoke\",862,0,\"mul\",[\"f64:1\",\"f64:0\"]],[\"invoke\",867,0,\"mul\",[\"f64:9223372036854775809\",\"f64:9227875636482146304\"]],[\"invoke\",872,0,\"mul\",[\"f64:9223372036854775809\",\"f64:4602678819172646912\"]],[\"invoke\",877,0,\"mul\",[\"f64:1\",\"f64:13830554455654793216\"]],[\"invoke\",882,0,\"mul\",[\"f64:1\",\"f64:4618760256179416344\"]],[\"invoke\",887,0,\"mul\",[\"f64:9223372036854775809\",\"f64:18442240474082181120\"]],[\"invoke\",893,0,\"mul\",[\"f64:9223372036854775809\",\"f64:9221120237041090560\"]],[\"invoke\",902,0,\"mul\",[\"f64:4503599627370496\",\"f64:0\"]],[\"invoke\",907,0,\"mul\",[\"f64:9227875636482146304\",\"f64:9227875636482146304\"]],[\"invoke\",912,0,\"mul\",[\"f64:9227875636482146304\",\"f64:4602678819172646912\"]],[\"invoke\",917,0,\"mul\",[\"f64:4503599627370496\",\"f64:13830554455654793216\"]],[\"invoke\",922,0,\"mul\",[\"f64:4503599627370496\",\"f64:4618760256179416344\"]],[\"invoke\",927,0,\"mul\",[\"f64:9227875636482146304\",\"f64:18442240474082181120\"]],[\"invoke\",933,0,\"mul\",[\"f64:9227875636482146304\",\"f64:9221120237041090560\"]],[\"invoke\",941,0,\"mul\",[\"f64:4602678819172646912\",\"f64:9223372036854775808\"]],[\"invoke\",946,0,\"mul\",[\"f64:4602678819172646912\",\"f64:1\"]],[\"invoke\",951,0,\"mul\",[\"f64:13826050856027422720\",\"f64:13826050856027422720\"]],[\"invoke\",956,0,\"mul\",[\"f64:13826050856027422720\",\"f64:4607182418800017408\"]],[\"invoke\",962,0,\"mul\",[\"f64:4602678819172646912\",\"f64:4618760256179416344\"]],[\"invoke\",967,0,\"mul\",[\"f64:13826050856027422720\",\"f64:18442240474082181120\"]],[\"invoke\",973,0,\"mul\",[\"f64:13826050856027422720\",\"f64:9221120237041090560\"]],[\"invoke\",981,0,\"mul\",[\"f64:4607182418800017408\",\"f64:9223372036854775808\"]],[\"invoke\",986,0,\"mul\",[\"f64:4607182418800017408\",\"f64:1\"]],[\"invoke\",991,0,\"mul\",[\"f64:13830554455654793216\",\"f64:13826050856027422720\"]],[\"invoke\",996,0,\"mul\",[\"f64:13830554455654793216\",\"f64:4607182418800017408\"]],[\"invoke\",1001,0,\"mul\",[\"f64:4607182418800017408\",\"f64:13842132293034192152\"]],[\"invoke\",1006,0,\"mul\",[\"f64:4607182418800017408\",\"f64:9218868437227405311\"]],[\"invoke\",1011,0,\"mul\",[\"f64:13830554455654793216\",\"f64:18444492273895866368\"]],[\"invoke\",1020,0,\"mul\",[\"f64:13842132293034192152\",\"f64:0\"]],[\"invoke\",1025,0,\"mul\",[\"f64:4618760256179416344\",\"f64:9223372036854775809\"]],[\"invoke\",1031,0,\"mul\",[\"f64:13842132293034192152\",\"f64:13826050856027422720\"]],[\"invoke\",1036,0,\"mul\",[\"f64:13842132293034192152\",\"f64:4607182418800017408\"]],[\"invoke\",1041,0,\"mul\",[\"f64:4618760256179416344\",\"f64:13842132293034192152\"]],[\"invoke\",1046,0,\"mul\",[\"f64:4618760256179416344\",\"f64:9218868437227405311\"]],[\"invoke\",1051,0,\"mul\",[\"f64:13842132293034192152\",\"f64:18444492273895866368\"]],[\"invoke\",1060,0,\"mul\",[\"f64:18442240474082181119\",\"f64:0\"]],[\"invoke\",1065,0,\"mul\",[\"f64:9218868437227405311\",\"f64:9223372036854775809\"]],[\"invoke\",1070,0,\"mul\",[\"f64:9218868437227405311\",\"f64:4503599627370496\"]],[\"invoke\",1075,0,\"mul\",[\"f64:18442240474082181119\",\"f64:13830554455654793216\"]],[\"invoke\",1080,0,\"mul\",[\"f64:18442240474082181119\",\"f64:4618760256179416344\"]],[\"invoke\",1085,0,\"mul\",[\"f64:9218868437227405311\",\"f64:18442240474082181119\"]],[\"invoke\",1090,0,\"mul\",[\"f64:9218868437227405311\",\"f64:9218868437227405312\"]],[\"invoke\",1100,0,\"mul\",[\"f64:18442240474082181120\",\"f64:0\"]],[\"invoke\",1105,0,\"mul\",[\"f64:9218868437227405312\",\"f64:9223372036854775809\"]],[\"invoke\",1110,0,\"mul\",[\"f64:9218868437227405312\",\"f64:4503599627370496\"]],[\"invoke\",1115,0,\"mul\",[\"f64:18442240474082181120\",\"f64:13830554455654793216\"]],[\"invoke\",1120,0,\"mul\",[\"f64:18442240474082181120\",\"f64:4618760256179416344\"]],[\"invoke\",1125,0,\"mul\",[\"f64:9218868437227405312\",\"f64:18442240474082181119\"]],[\"invoke\",1130,0,\"mul\",[\"f64:9218868437227405312\",\"f64:9218868437227405312\"]],[\"invoke\",1139,0,\"mul\",[\"f64:18444492273895866368\",\"f64:9223372036854775808\"]],[\"invoke\",1149,0,\"mul\",[\"f64:18444492273895866368\",\"f64:1\"]],[\"invoke\",1159,0,\"mul\",[\"f64:9221120237041090560\",\"f64:9227875636482146304\"]],[\"invoke\",1169,0,\"mul\",[\"f64:9221120237041090560\",\"f64:4602678819172646912\"]],[\"invoke\",1179,0,\"mul\",[\"f64:18444492273895866368\",\"f64:13842132293034192152\"]],[\"invoke\",1191,0,\"mul\",[\"f64:9221120237041090560\",\"f64:18442240474082181119\"]],[\"invoke\",1201,0,\"mul\",[\"f64:9221120237041090560\",\"f64:9218868437227405312\"]],[\"invoke\",1219,0,\"div\",[\"f64:9223372036854775808\",\"f64:9223372036854775808\"]],[\"invoke\",1224,0,\"div\",[\"f64:9223372036854775808\",\"f64:1\"]],[\"invoke\",1229,0,\"div\",[\"f64:0\",\"f64:9227875636482146304\"]],[\"invoke\",1234,0,\"div\",[\"f64:0\",\"f64:4602678819172646912\"]],[\"invoke\",1239,0,\"div\",[\"f64:9223372036854775808\",\"f64:13842132293034192152\"]],[\"invoke\",1244,0,\"div\",[\"f64:9223372036854775808\",\"f64:9218868437227405311\"]],[\"invoke\",1249,0,\"div\",[\"f64:0\",\"f64:18442240474082181120\"]],[\"invoke\",1257,0,\"div\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",1263,0,\"div\",[\"f64:9223372036854775809\",\"f64:9223372036854775809\"]],[\"invoke\",1269,0,\"div\",[\"f64:1\",\"f64:9227875636482146304\"]],[\"invoke\",1274,0,\"div\",[\"f64:1\",\"f64:4602678819172646912\"]],[\"invoke\",1279,0,\"div\",[\"f64:9223372036854775809\",\"f64:13842132293034192152\"]],[\"invoke\",1284,0,\"div\",[\"f64:9223372036854775809\",\"f64:9218868437227405311\"]],[\"invoke\",1289,0,\"div\",[\"f64:1\",\"f64:18442240474082181120\"]],[\"invoke\",1297,0,\"div\",[\"f64:1\",\"f64:9221120237041090560\"]],[\"invoke\",1303,0,\"div\",[\"f64:9227875636482146304\",\"f64:9223372036854775809\"]],[\"invoke\",1308,0,\"div\",[\"f64:9227875636482146304\",\"f64:4503599627370496\"]],[\"invoke\",1313,0,\"div\",[\"f64:4503599627370496\",\"f64:13826050856027422720\"]],[\"invoke\",1318,0,\"div\",[\"f64:4503599627370496\",\"f64:4607182418800017408\"]],[\"invoke\",1323,0,\"div\",[\"f64:9227875636482146304\",\"f64:18442240474082181119\"]],[\"invoke\",1328,0,\"div\",[\"f64:9227875636482146304\",\"f64:9218868437227405312\"]],[\"invoke\",1337,0,\"div\",[\"f64:4503599627370496\",\"f64:9221120237041090560\"]],[\"invoke\",1343,0,\"div\",[\"f64:13826050856027422720\",\"f64:9223372036854775809\"]],[\"invoke\",1348,0,\"div\",[\"f64:13826050856027422720\",\"f64:4503599627370496\"]],[\"invoke\",1353,0,\"div\",[\"f64:4602678819172646912\",\"f64:13826050856027422720\"]],[\"invoke\",1358,0,\"div\",[\"f64:4602678819172646912\",\"f64:4607182418800017408\"]],[\"invoke\",1363,0,\"div\",[\"f64:13826050856027422720\",\"f64:18442240474082181119\"]],[\"invoke\",1368,0,\"div\",[\"f64:13826050856027422720\",\"f64:9218868437227405312\"]],[\"invoke\",1375,0,\"div\",[\"f64:4602678819172646912\",\"f64:18444492273895866368\"]],[\"invoke\",1382,0,\"div\",[\"f64:4607182418800017408\",\"f64:0\"]],[\"invoke\",1387,0,\"div\",[\"f64:13830554455654793216\",\"f64:9227875636482146304\"]],[\"invoke\",1392,0,\"div\",[\"f64:13830554455654793216\",\"f64:4602678819172646912\"]],[\"invoke\",1397,0,\"div\",[\"f64:4607182418800017408\",\"f64:13830554455654793216\"]],[\"invoke\",1403,0,\"div\",[\"f64:13830554455654793216\",\"f64:18442240474082181119\"]],[\"invoke\",1408,0,\"div\",[\"f64:13830554455654793216\",\"f64:9218868437227405312\"]],[\"invoke\",1415,0,\"div\",[\"f64:4607182418800017408\",\"f64:18444492273895866368\"]],[\"invoke\",1422,0,\"div\",[\"f64:4618760256179416344\",\"f64:0\"]],[\"invoke\",1427,0,\"div\",[\"f64:13842132293034192152\",\"f64:9227875636482146304\"]],[\"invoke\",1432,0,\"div\",[\"f64:13842132293034192152\",\"f64:4602678819172646912\"]],[\"invoke\",1437,0,\"div\",[\"f64:4618760256179416344\",\"f64:13830554455654793216\"]],[\"invoke\",1442,0,\"div\",[\"f64:4618760256179416344\",\"f64:4618760256179416344\"]],[\"invoke\",1447,0,\"div\",[\"f64:13842132293034192152\",\"f64:18442240474082181120\"]],[\"invoke\",1453,0,\"div\",[\"f64:13842132293034192152\",\"f64:9221120237041090560\"]],[\"invoke\",1461,0,\"div\",[\"f64:9218868437227405311\",\"f64:9223372036854775808\"]],[\"invoke\",1466,0,\"div\",[\"f64:9218868437227405311\",\"f64:1\"]],[\"invoke\",1472,0,\"div\",[\"f64:18442240474082181119\",\"f64:4602678819172646912\"]],[\"invoke\",1477,0,\"div\",[\"f64:9218868437227405311\",\"f64:13830554455654793216\"]],[\"invoke\",1482,0,\"div\",[\"f64:9218868437227405311\",\"f64:4618760256179416344\"]],[\"invoke\",1487,0,\"div\",[\"f64:18442240474082181119\",\"f64:18442240474082181120\"]],[\"invoke\",1493,0,\"div\",[\"f64:18442240474082181119\",\"f64:9221120237041090560\"]],[\"invoke\",1501,0,\"div\",[\"f64:9218868437227405312\",\"f64:9223372036854775808\"]],[\"invoke\",1506,0,\"div\",[\"f64:9218868437227405312\",\"f64:1\"]],[\"invoke\",1511,0,\"div\",[\"f64:18442240474082181120\",\"f64:13826050856027422720\"]],[\"invoke\",1516,0,\"div\",[\"f64:18442240474082181120\",\"f64:4607182418800017408\"]],[\"invoke\",1521,0,\"div\",[\"f64:9218868437227405312\",\"f64:13842132293034192152\"]],[\"invoke\",1526,0,\"div\",[\"f64:9218868437227405312\",\"f64:9218868437227405311\"]],[\"invoke\",1531,0,\"div\",[\"f64:18442240474082181120\",\"f64:18444492273895866368\"]],[\"invoke\",1543,0,\"div\",[\"f64:9221120237041090560\",\"f64:9223372036854775808\"]],[\"invoke\",1553,0,\"div\",[\"f64:9221120237041090560\",\"f64:1\"]],[\"invoke\",1563,0,\"div\",[\"f64:18444492273895866368\",\"f64:13826050856027422720\"]],[\"invoke\",1573,0,\"div\",[\"f64:18444492273895866368\",\"f64:4607182418800017408\"]],[\"invoke\",1583,0,\"div\",[\"f64:9221120237041090560\",\"f64:13842132293034192152\"]],[\"invoke\",1593,0,\"div\",[\"f64:9221120237041090560\",\"f64:9218868437227405311\"]],[\"invoke\",1603,0,\"div\",[\"f64:18444492273895866368\",\"f64:18444492273895866368\"]],[\"invoke\",1620,0,\"min\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",1625,0,\"min\",[\"f64:0\",\"f64:9223372036854775809\"]],[\"invoke\",1630,0,\"min\",[\"f64:0\",\"f64:4503599627370496\"]],[\"invoke\",1635,0,\"min\",[\"f64:9223372036854775808\",\"f64:13830554455654793216\"]],[\"invoke\",1641,0,\"min\",[\"f64:0\",\"f64:13842132293034192152\"]],[\"invoke\",1646,0,\"min\",[\"f64:0\",\"f64:9218868437227405311\"]],[\"invoke\",1651,0,\"min\",[\"f64:9223372036854775808\",\"f64:18444492273895866368\"]],[\"invoke\",1660,0,\"min\",[\"f64:9223372036854775809\",\"f64:0\"]],[\"invoke\",1665,0,\"min\",[\"f64:1\",\"f64:9223372036854775809\"]],[\"invoke\",1670,0,\"min\",[\"f64:1\",\"f64:4503599627370496\"]],[\"invoke\",1675,0,\"min\",[\"f64:9223372036854775809\",\"f64:13830554455654793216\"]],[\"invoke\",1680,0,\"min\",[\"f64:9223372036854775809\",\"f64:4618760256179416344\"]],[\"invoke\",1685,0,\"min\",[\"f64:1\",\"f64:18442240474082181119\"]],[\"invoke\",1690,0,\"min\",[\"f64:1\",\"f64:9218868437227405312\"]],[\"invoke\",1699,0,\"min\",[\"f64:9227875636482146304\",\"f64:9223372036854775808\"]],[\"invoke\",1704,0,\"min\",[\"f64:9227875636482146304\",\"f64:1\"]],[\"invoke\",1710,0,\"min\",[\"f64:4503599627370496\",\"f64:4503599627370496\"]],[\"invoke\",1715,0,\"min\",[\"f64:9227875636482146304\",\"f64:13830554455654793216\"]],[\"invoke\",1720,0,\"min\",[\"f64:9227875636482146304\",\"f64:4618760256179416344\"]],[\"invoke\",1725,0,\"min\",[\"f64:4503599627370496\",\"f64:18442240474082181119\"]],[\"invoke\",1730,0,\"min\",[\"f64:4503599627370496\",\"f64:9218868437227405312\"]],[\"invoke\",1739,0,\"min\",[\"f64:13826050856027422720\",\"f64:9223372036854775808\"]],[\"invoke\",1744,0,\"min\",[\"f64:13826050856027422720\",\"f64:1\"]],[\"invoke\",1749,0,\"min\",[\"f64:4602678819172646912\",\"f64:9227875636482146304\"]],[\"invoke\",1754,0,\"min\",[\"f64:4602678819172646912\",\"f64:4602678819172646912\"]],[\"invoke\",1759,0,\"min\",[\"f64:13826050856027422720\",\"f64:13842132293034192152\"]],[\"invoke\",1764,0,\"min\",[\"f64:13826050856027422720\",\"f64:9218868437227405311\"]],[\"invoke\",1769,0,\"min\",[\"f64:4602678819172646912\",\"f64:18442240474082181120\"]],[\"invoke\",1779,0,\"min\",[\"f64:13830554455654793216\",\"f64:9223372036854775808\"]],[\"invoke\",1784,0,\"min\",[\"f64:13830554455654793216\",\"f64:1\"]],[\"invoke\",1789,0,\"min\",[\"f64:4607182418800017408\",\"f64:9227875636482146304\"]],[\"invoke\",1794,0,\"min\",[\"f64:4607182418800017408\",\"f64:4602678819172646912\"]],[\"invoke\",1799,0,\"min\",[\"f64:13830554455654793216\",\"f64:13842132293034192152\"]],[\"invoke\",1804,0,\"min\",[\"f64:13830554455654793216\",\"f64:9218868437227405311\"]],[\"invoke\",1809,0,\"min\",[\"f64:4607182418800017408\",\"f64:18442240474082181120\"]],[\"invoke\",1817,0,\"min\",[\"f64:4607182418800017408\",\"f64:9221120237041090560\"]],[\"invoke\",1823,0,\"min\",[\"f64:13842132293034192152\",\"f64:9223372036854775809\"]],[\"invoke\",1828,0,\"min\",[\"f64:13842132293034192152\",\"f64:4503599627370496\"]],[\"invoke\",1833,0,\"min\",[\"f64:4618760256179416344\",\"f64:13826050856027422720\"]],[\"invoke\",1838,0,\"min\",[\"f64:4618760256179416344\",\"f64:4607182418800017408\"]],[\"invoke\",1844,0,\"min\",[\"f64:13842132293034192152\",\"f64:9218868437227405311\"]],[\"invoke\",1849,0,\"min\",[\"f64:4618760256179416344\",\"f64:18442240474082181120\"]],[\"invoke\",1857,0,\"min\",[\"f64:4618760256179416344\",\"f64:9221120237041090560\"]],[\"invoke\",1863,0,\"min\",[\"f64:18442240474082181119\",\"f64:9223372036854775809\"]],[\"invoke\",1868,0,\"min\",[\"f64:18442240474082181119\",\"f64:4503599627370496\"]],[\"invoke\",1873,0,\"min\",[\"f64:9218868437227405311\",\"f64:13826050856027422720\"]],[\"invoke\",1878,0,\"min\",[\"f64:9218868437227405311\",\"f64:4607182418800017408\"]],[\"invoke\",1883,0,\"min\",[\"f64:18442240474082181119\",\"f64:18442240474082181119\"]],[\"invoke\",1888,0,\"min\",[\"f64:18442240474082181119\",\"f64:9218868437227405312\"]],[\"invoke\",1895,0,\"min\",[\"f64:9218868437227405311\",\"f64:18444492273895866368\"]],[\"invoke\",1902,0,\"min\",[\"f64:9218868437227405312\",\"f64:0\"]],[\"invoke\",1908,0,\"min\",[\"f64:18442240474082181120\",\"f64:4503599627370496\"]],[\"invoke\",1913,0,\"min\",[\"f64:9218868437227405312\",\"f64:13826050856027422720\"]],[\"invoke\",1918,0,\"min\",[\"f64:9218868437227405312\",\"f64:4607182418800017408\"]],[\"invoke\",1923,0,\"min\",[\"f64:18442240474082181120\",\"f64:18442240474082181119\"]],[\"invoke\",1928,0,\"min\",[\"f64:18442240474082181120\",\"f64:9218868437227405312\"]],[\"invoke\",1935,0,\"min\",[\"f64:9218868437227405312\",\"f64:18444492273895866368\"]],[\"invoke\",1945,0,\"min\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",1955,0,\"min\",[\"f64:18444492273895866368\",\"f64:9227875636482146304\"]],[\"invoke\",1965,0,\"min\",[\"f64:18444492273895866368\",\"f64:4602678819172646912\"]],[\"invoke\",1975,0,\"min\",[\"f64:9221120237041090560\",\"f64:13830554455654793216\"]],[\"invoke\",1985,0,\"min\",[\"f64:9221120237041090560\",\"f64:4618760256179416344\"]],[\"invoke\",1995,0,\"min\",[\"f64:18444492273895866368\",\"f64:18442240474082181120\"]],[\"invoke\",2011,0,\"min\",[\"f64:9221120237041090560\",\"f64:18444492273895866368\"]],[\"invoke\",2022,0,\"max\",[\"f64:0\",\"f64:0\"]],[\"invoke\",2027,0,\"max\",[\"f64:9223372036854775808\",\"f64:9227875636482146304\"]],[\"invoke\",2032,0,\"max\",[\"f64:9223372036854775808\",\"f64:4602678819172646912\"]],[\"invoke\",2037,0,\"max\",[\"f64:0\",\"f64:13830554455654793216\"]],[\"invoke\",2042,0,\"max\",[\"f64:0\",\"f64:4618760256179416344\"]],[\"invoke\",2047,0,\"max\",[\"f64:9223372036854775808\",\"f64:18442240474082181120\"]],[\"invoke\",2053,0,\"max\",[\"f64:9223372036854775808\",\"f64:9221120237041090560\"]],[\"invoke\",2061,0,\"max\",[\"f64:1\",\"f64:9223372036854775808\"]],[\"invoke\",2066,0,\"max\",[\"f64:1\",\"f64:1\"]],[\"invoke\",2071,0,\"max\",[\"f64:9223372036854775809\",\"f64:13826050856027422720\"]],[\"invoke\",2076,0,\"max\",[\"f64:9223372036854775809\",\"f64:4607182418800017408\"]],[\"invoke\",2082,0,\"max\",[\"f64:1\",\"f64:4618760256179416344\"]],[\"invoke\",2087,0,\"max\",[\"f64:9223372036854775809\",\"f64:18442240474082181120\"]],[\"invoke\",2093,0,\"max\",[\"f64:9223372036854775809\",\"f64:9221120237041090560\"]],[\"invoke\",2101,0,\"max\",[\"f64:4503599627370496\",\"f64:9223372036854775808\"]],[\"invoke\",2106,0,\"max\",[\"f64:4503599627370496\",\"f64:1\"]],[\"invoke\",2111,0,\"max\",[\"f64:9227875636482146304\",\"f64:13826050856027422720\"]],[\"invoke\",2116,0,\"max\",[\"f64:9227875636482146304\",\"f64:4607182418800017408\"]],[\"invoke\",2121,0,\"max\",[\"f64:4503599627370496\",\"f64:13842132293034192152\"]],[\"invoke\",2126,0,\"max\",[\"f64:4503599627370496\",\"f64:9218868437227405311\"]],[\"invoke\",2131,0,\"max\",[\"f64:9227875636482146304\",\"f64:18444492273895866368\"]],[\"invoke\",2140,0,\"max\",[\"f64:13826050856027422720\",\"f64:0\"]],[\"invoke\",2145,0,\"max\",[\"f64:4602678819172646912\",\"f64:9223372036854775809\"]],[\"invoke\",2151,0,\"max\",[\"f64:13826050856027422720\",\"f64:13826050856027422720\"]],[\"invoke\",2156,0,\"max\",[\"f64:13826050856027422720\",\"f64:4607182418800017408\"]],[\"invoke\",2161,0,\"max\",[\"f64:4602678819172646912\",\"f64:13842132293034192152\"]],[\"invoke\",2166,0,\"max\",[\"f64:4602678819172646912\",\"f64:9218868437227405311\"]],[\"invoke\",2171,0,\"max\",[\"f64:13826050856027422720\",\"f64:18444492273895866368\"]],[\"invoke\",2180,0,\"max\",[\"f64:13830554455654793216\",\"f64:0\"]],[\"invoke\",2185,0,\"max\",[\"f64:4607182418800017408\",\"f64:9223372036854775809\"]],[\"invoke\",2190,0,\"max\",[\"f64:4607182418800017408\",\"f64:4503599627370496\"]],[\"invoke\",2195,0,\"max\",[\"f64:13830554455654793216\",\"f64:13830554455654793216\"]],[\"invoke\",2200,0,\"max\",[\"f64:13830554455654793216\",\"f64:4618760256179416344\"]],[\"invoke\",2205,0,\"max\",[\"f64:4607182418800017408\",\"f64:18442240474082181119\"]],[\"invoke\",2211,0,\"max\",[\"f64:13830554455654793216\",\"f64:18444492273895866368\"]],[\"invoke\",2220,0,\"max\",[\"f64:13842132293034192152\",\"f64:0\"]],[\"invoke\",2225,0,\"max\",[\"f64:4618760256179416344\",\"f64:9223372036854775809\"]],[\"invoke\",2230,0,\"max\",[\"f64:4618760256179416344\",\"f64:4503599627370496\"]],[\"invoke\",2235,0,\"max\",[\"f64:13842132293034192152\",\"f64:13830554455654793216\"]],[\"invoke\",2240,0,\"max\",[\"f64:13842132293034192152\",\"f64:4618760256179416344\"]],[\"invoke\",2245,0,\"max\",[\"f64:4618760256179416344\",\"f64:18442240474082181119\"]],[\"invoke\",2250,0,\"max\",[\"f64:4618760256179416344\",\"f64:9218868437227405312\"]],[\"invoke\",2259,0,\"max\",[\"f64:18442240474082181119\",\"f64:9223372036854775808\"]],[\"invoke\",2264,0,\"max\",[\"f64:18442240474082181119\",\"f64:1\"]],[\"invoke\",2269,0,\"max\",[\"f64:9218868437227405311\",\"f64:9227875636482146304\"]],[\"invoke\",2274,0,\"max\",[\"f64:9218868437227405311\",\"f64:4602678819172646912\"]],[\"invoke\",2280,0,\"max\",[\"f64:18442240474082181119\",\"f64:4618760256179416344\"]],[\"invoke\",2285,0,\"max\",[\"f64:9218868437227405311\",\"f64:18442240474082181119\"]],[\"invoke\",2290,0,\"max\",[\"f64:9218868437227405311\",\"f64:9218868437227405312\"]],[\"invoke\",2299,0,\"max\",[\"f64:18442240474082181120\",\"f64:9223372036854775808\"]],[\"invoke\",2304,0,\"max\",[\"f64:18442240474082181120\",\"f64:1\"]],[\"invoke\",2309,0,\"max\",[\"f64:9218868437227405312\",\"f64:9227875636482146304\"]],[\"invoke\",2314,0,\"max\",[\"f64:9218868437227405312\",\"f64:4602678819172646912\"]],[\"invoke\",2319,0,\"max\",[\"f64:18442240474082181120\",\"f64:13842132293034192152\"]],[\"invoke\",2324,0,\"max\",[\"f64:18442240474082181120\",\"f64:9218868437227405311\"]],[\"invoke\",2329,0,\"max\",[\"f64:9218868437227405312\",\"f64:18442240474082181120\"]],[\"invoke\",2337,0,\"max\",[\"f64:9218868437227405312\",\"f64:9221120237041090560\"]],[\"invoke\",2347,0,\"max\",[\"f64:18444492273895866368\",\"f64:9223372036854775809\"]],[\"invoke\",2359,0,\"max\",[\"f64:9221120237041090560\",\"f64:9227875636482146304\"]],[\"invoke\",2369,0,\"max\",[\"f64:9221120237041090560\",\"f64:4602678819172646912\"]],[\"invoke\",2379,0,\"max\",[\"f64:18444492273895866368\",\"f64:13842132293034192152\"]],[\"invoke\",2389,0,\"max\",[\"f64:18444492273895866368\",\"f64:9218868437227405311\"]],[\"invoke\",2399,0,\"max\",[\"f64:9221120237041090560\",\"f64:18442240474082181120\"]],[\"invoke\",2415,0,\"max\",[\"f64:9221120237041090560\",\"f64:9221120237041090560\"]],[\"invoke\",2423,0,\"sqrt\",[\"f64:9227875636482146304\"]],[\"invoke\",2428,0,\"sqrt\",[\"f64:4607182418800017408\"]],[\"invoke\",2433,0,\"sqrt\",[\"f64:18442240474082181120\"]],[\"invoke\",2440,0,\"floor\",[\"f64:0\"]],[\"invoke\",2445,0,\"floor\",[\"f64:13826050856027422720\"]],[\"invoke\",2450,0,\"floor\",[\"f64:4618760256179416344\"]],[\"invoke\",2457,0,\"floor\",[\"f64:9221120237041090560\"]],[\"invoke\",2463,0,\"ceil\",[\"f64:9227875636482146304\"]],[\"invoke\",2468,0,\"ceil\",[\"f64:4607182418800017408\"]],[\"invoke\",2473,0,\"ceil\",[\"f64:18442240474082181120\"]],[\"invoke\",2480,0,\"trunc\",[\"f64:0\"]],[\"invoke\",2485,0,\"trunc\",[\"f64:13826050856027422720\"]],[\"invoke\",2490,0,\"trunc\",[\"f64:4618760256179416344\"]],[\"invoke\",2495,0,\"trunc\",[\"f64:18444492273895866368\"]],[\"invoke\",2502,0,\"nearest\",[\"f64:1\"]],[\"invoke\",2507,0,\"nearest\",[\"f64:13830554455654793216\"]],[\"invoke\",2512,0,\"nearest\",[\"f64:9218868437227405311\"]],[\"file\",\"f32_cmp.wast\"],[\"module\",4,2],[\"invoke\",13,0,\"eq\",[\"f32:2147483648\",\"f32:2147483648\"]],[\"invoke\",18,0,\"eq\",[\"f32:2147483648\",\"f32:1\"]],[\"invoke\",23,0,\"eq\",[\"f32:0\",\"f32:2155872256\"]],[\"invoke\",28,0,\"eq\",[\"f32:0\",\"f32:1056964608\"]],[\"invoke\",33,0,\"eq\",[\"f32:2147483648\",\"f32:3234402267\"]],[\"invoke\",38,0,\"eq\",[\"f32:2147483648\",\"f32:2139095039\"]],[\"invoke\",43,0,\"eq\",[\"f32:0\",\"f32:4286578688\"]],[\"invoke\",51,0,\"eq\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",56,0,\"eq\",[\"f32:1\",\"f32:0\"]],[\"invoke\",61,0,\"eq\",[\"f32:2147483649\",\"f32:2155872256\"]],[\"invoke\",66,0,\"eq\",[\"f32:2147483649\",\"f32:1056964608\"]],[\"invoke\",71,0,\"eq\",[\"f32:1\",\"f32:3212836864\"]],[\"invoke\",76,0,\"eq\",[\"f32:1\",\"f32:1086918619\"]],[\"invoke\",81,0,\"eq\",[\"f32:2147483649\",\"f32:4286578688\"]],[\"invoke\",87,0,\"eq\",[\"f32:2147483649\",\"f32:2143289344\"]],[\"invoke\",94,0,\"eq\",[\"f32:2155872256\",\"f32:0\"]],[\"invoke\",99,0,\"eq\",[\"f32:8388608\",\"f32:2147483649\"]],[\"invoke\",104,0,\"eq\",[\"f32:8388608\",\"f32:8388608\"]],[\"invoke\",109,0,\"eq\",[\"f32:2155872256\",\"f32:3212836864\"]],[\"invoke\",114,0,\"eq\",[\"f32:2155872256\",\"f32:1086918619\"]],[\"invoke\",119,0,\"eq\",[\"f32:8388608\",\"f32:4286578687\"]],[\"invoke\",124,0,\"eq\",[\"f32:8388608\",\"f32:2139095040\"]],[\"invoke\",131,0,\"eq\",[\"f32:8388608\",\"f32:2143289344\"]],[\"invoke\",137,0,\"eq\",[\"f32:3204448256\",\"f32:2147483649\"]],[\"invoke\",142,0,\"eq\",[\"f32:3204448256\",\"f32:8388608\"]],[\"invoke\",147,0,\"eq\",[\"f32:1056964608\",\"f32:3204448256\"]],[\"invoke\",152,0,\"eq\",[\"f32:1056964608\",\"f32:1065353216\"]],[\"invoke\",157,0,\"eq\",[\"f32:3204448256\",\"f32:4286578687\"]],[\"invoke\",162,0,\"eq\",[\"f32:3204448256\",\"f32:2139095040\"]],[\"invoke\",167,0,\"eq\",[\"f32:3204448256\",\"f32:2143289344\"]],[\"invoke\",175,0,\"eq\",[\"f32:1065353216\",\"f32:2147483648\"]],[\"invoke\",180,0,\"eq\",[\"f32:1065353216\",\"f32:1\"]],[\"invoke\",185,0,\"eq\",[\"f32:3212836864\",\"f32:3204448256\"]],[\"invoke\",190,0,\"eq\",[\"f32:3212836864\",\"f32:1065353216\"]],[\"invoke\",195,0,\"eq\",[\"f32:1065353216\",\"f32:3234402267\"]],[\"invoke\",200,0,\"eq\",[\"f32:1065353216\",\"f32:2139095039\"]],[\"invoke\",204,0,\"eq\",[\"f32:1065353216\",\"f32:2139095040\"]],[\"invoke\",213,0,\"eq\",[\"f32:3234402267\",\"f32:2147483648\"]],[\"invoke\",218,0,\"eq\",[\"f32:3234402267\",\"f32:1\"]],[\"invoke\",223,0,\"eq\",[\"f32:1086918619\",\"f32:2155872256\"]],[\"invoke\",228,0,\"eq\",[\"f32:1086918619\",\"f32:1056964608\"]],[\"invoke\",233,0,\"eq\",[\"f32:3234402267\",\"f32:3234402267\"]],[\"invoke\",238,0,\"eq\",[\"f32:3234402267\",\"f32:2139095039\"]],[\"invoke\",242,0,\"eq\",[\"f32:3234402267\",\"f32:2139095040\"]],[\"invoke\",249,0,\"eq\",[\"f32:1086918619\",\"f32:4290772992\"]],[\"invoke\",256,0,\"eq\",[\"f32:2139095039\",\"f32:0\"]],[\"invoke\",261,0,\"eq\",[\"f32:4286578687\",\"f32:2155872256\"]],[\"invoke\",266,0,\"eq\",[\"f32:4286578687\",\"f32:1056964608\"]],[\"invoke\",271,0,\"eq\",[\"f32:2139095039\",\"f32:3212836864\"]],[\"invoke\",276,0,\"eq\",[\"f32:2139095039\",\"f32:1086918619\"]],[\"invoke\",281,0,\"eq\",[\"f32:4286578687\",\"f32:4286578688\"]],[\"invoke\",285,0,\"eq\",[\"f32:4286578687\",\"f32:4290772992\"]],[\"invoke\",294,0,\"eq\",[\"f32:4286578688\",\"f32:0\"]],[\"invoke\",299,0,\"eq\",[\"f32:2139095040\",\"f32:2147483649\"]],[\"invoke\",304,0,\"eq\",[\"f32:2139095040\",\"f32:8388608\"]],[\"invoke\",309,0,\"eq\",[\"f32:4286578688\",\"f32:3212836864\"]],[\"invoke\",314,0,\"eq\",[\"f32:4286578688\",\"f32:1086918619\"]],[\"invoke\",319,0,\"eq\",[\"f32:2139095040\",\"f32:4286578687\"]],[\"invoke\",323,0,\"eq\",[\"f32:2139095040\",\"f32:4286578688\"]],[\"invoke\",331,0,\"eq\",[\"f32:2139095040\",\"f32:2143289344\"]],[\"invoke\",341,0,\"eq\",[\"f32:4290772992\",\"f32:2147483649\"]],[\"invoke\",351,0,\"eq\",[\"f32:4290772992\",\"f32:8388608\"]],[\"invoke\",361,0,\"eq\",[\"f32:2143289344\",\"f32:3204448256\"]],[\"invoke\",371,0,\"eq\",[\"f32:2143289344\",\"f32:1065353216\"]],[\"invoke\",381,0,\"eq\",[\"f32:4290772992\",\"f32:4286578687\"]],[\"invoke\",389,0,\"eq\",[\"f32:4290772992\",\"f32:4286578688\"]],[\"invoke\",401,0,\"eq\",[\"f32:4290772992\",\"f32:2143289344\"]],[\"invoke\",415,0,\"ne\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",420,0,\"ne\",[\"f32:0\",\"f32:1\"]],[\"invoke\",425,0,\"ne\",[\"f32:2147483648\",\"f32:3204448256\"]],[\"invoke\",430,0,\"ne\",[\"f32:2147483648\",\"f32:1065353216\"]],[\"invoke\",435,0,\"ne\",[\"f32:0\",\"f32:3234402267\"]],[\"invoke\",439,0,\"ne\",[\"f32:0\",\"f32:4286578687\"]],[\"invoke\",444,0,\"ne\",[\"f32:0\",\"f32:2139095040\"]],[\"invoke\",453,0,\"ne\",[\"f32:2147483649\",\"f32:2147483648\"]],[\"invoke\",458,0,\"ne\",[\"f32:2147483649\",\"f32:1\"]],[\"invoke\",463,0,\"ne\",[\"f32:1\",\"f32:2155872256\"]],[\"invoke\",468,0,\"ne\",[\"f32:1\",\"f32:1056964608\"]],[\"invoke\",473,0,\"ne\",[\"f32:2147483649\",\"f32:3234402267\"]],[\"invoke\",477,0,\"ne\",[\"f32:2147483649\",\"f32:4286578687\"]],[\"invoke\",482,0,\"ne\",[\"f32:2147483649\",\"f32:2139095040\"]],[\"invoke\",489,0,\"ne\",[\"f32:1\",\"f32:4290772992\"]],[\"invoke\",496,0,\"ne\",[\"f32:8388608\",\"f32:0\"]],[\"invoke\",501,0,\"ne\",[\"f32:2155872256\",\"f32:2155872256\"]],[\"invoke\",506,0,\"ne\",[\"f32:2155872256\",\"f32:1056964608\"]],[\"invoke\",511,0,\"ne\",[\"f32:8388608\",\"f32:3212836864\"]],[\"invoke\",515,0,\"ne\",[\"f32:8388608\",\"f32:3234402267\"]],[\"invoke\",520,0,\"ne\",[\"f32:8388608\",\"f32:2139095039\"]],[\"invoke\",525,0,\"ne\",[\"f32:2155872256\",\"f32:4290772992\"]],[\"invoke\",534,0,\"ne\",[\"f32:3204448256\",\"f32:0\"]],[\"invoke\",539,0,\"ne\",[\"f32:1056964608\",\"f32:2147483649\"]],[\"invoke\",544,0,\"ne\",[\"f32:1056964608\",\"f32:8388608\"]],[\"invoke\",549,0,\"ne\",[\"f32:3204448256\",\"f32:3212836864\"]],[\"invoke\",553,0,\"ne\",[\"f32:3204448256\",\"f32:3234402267\"]],[\"invoke\",558,0,\"ne\",[\"f32:3204448256\",\"f32:2139095039\"]],[\"invoke\",563,0,\"ne\",[\"f32:1056964608\",\"f32:4286578688\"]],[\"invoke\",571,0,\"ne\",[\"f32:1056964608\",\"f32:2143289344\"]],[\"invoke\",577,0,\"ne\",[\"f32:3212836864\",\"f32:2147483649\"]],[\"invoke\",582,0,\"ne\",[\"f32:3212836864\",\"f32:8388608\"]],[\"invoke\",587,0,\"ne\",[\"f32:1065353216\",\"f32:3204448256\"]],[\"invoke\",592,0,\"ne\",[\"f32:1065353216\",\"f32:1065353216\"]],[\"invoke\",596,0,\"ne\",[\"f32:1065353216\",\"f32:1086918619\"]],[\"invoke\",601,0,\"ne\",[\"f32:3212836864\",\"f32:4286578688\"]],[\"invoke\",607,0,\"ne\",[\"f32:3212836864\",\"f32:2143289344\"]],[\"invoke\",615,0,\"ne\",[\"f32:1086918619\",\"f32:2147483648\"]],[\"invoke\",620,0,\"ne\",[\"f32:1086918619\",\"f32:1\"]],[\"invoke\",625,0,\"ne\",[\"f32:3234402267\",\"f32:3204448256\"]],[\"invoke\",630,0,\"ne\",[\"f32:3234402267\",\"f32:1065353216\"]],[\"invoke\",634,0,\"ne\",[\"f32:3234402267\",\"f32:1086918619\"]],[\"invoke\",639,0,\"ne\",[\"f32:1086918619\",\"f32:4286578687\"]],[\"invoke\",644,0,\"ne\",[\"f32:1086918619\",\"f32:2139095040\"]],[\"invoke\",653,0,\"ne\",[\"f32:4286578687\",\"f32:2147483648\"]],[\"invoke\",658,0,\"ne\",[\"f32:4286578687\",\"f32:1\"]],[\"invoke\",663,0,\"ne\",[\"f32:2139095039\",\"f32:2155872256\"]],[\"invoke\",668,0,\"ne\",[\"f32:2139095039\",\"f32:1056964608\"]],[\"invoke\",672,0,\"ne\",[\"f32:2139095039\",\"f32:1065353216\"]],[\"invoke\",677,0,\"ne\",[\"f32:4286578687\",\"f32:4286578687\"]],[\"invoke\",682,0,\"ne\",[\"f32:4286578687\",\"f32:2139095040\"]],[\"invoke\",689,0,\"ne\",[\"f32:2139095039\",\"f32:4290772992\"]],[\"invoke\",696,0,\"ne\",[\"f32:2139095040\",\"f32:0\"]],[\"invoke\",701,0,\"ne\",[\"f32:4286578688\",\"f32:2155872256\"]],[\"invoke\",706,0,\"ne\",[\"f32:4286578688\",\"f32:1056964608\"]],[\"invoke\",710,0,\"ne\",[\"f32:4286578688\",\"f32:1065353216\"]],[\"invoke\",715,0,\"ne\",[\"f32:2139095040\",\"f32:3234402267\"]],[\"invoke\",720,0,\"ne\",[\"f32:2139095040\",\"f32:2139095039\"]],[\"invoke\",725,0,\"ne\",[\"f32:4286578688\",\"f32:4290772992\"]],[\"invoke\",735,0,\"ne\",[\"f32:4290772992\",\"f32:0\"]],[\"invoke\",745,0,\"ne\",[\"f32:2143289344\",\"f32:2147483649\"]],[\"invoke\",755,0,\"ne\",[\"f32:2143289344\",\"f32:8388608\"]],[\"invoke\",763,0,\"ne\",[\"f32:2143289344\",\"f32:1056964608\"]],[\"invoke\",773,0,\"ne\",[\"f32:4290772992\",\"f32:3234402267\"]],[\"invoke\",783,0,\"ne\",[\"f32:4290772992\",\"f32:2139095039\"]],[\"invoke\",793,0,\"ne\",[\"f32:2143289344\",\"f32:4286578688\"]],[\"invoke\",809,0,\"ne\",[\"f32:2143289344\",\"f32:2143289344\"]],[\"invoke\",817,0,\"lt\",[\"f32:2147483648\",\"f32:2147483649\"]],[\"invoke\",822,0,\"lt\",[\"f32:2147483648\",\"f32:8388608\"]],[\"invoke\",826,0,\"lt\",[\"f32:2147483648\",\"f32:1056964608\"]],[\"invoke\",831,0,\"lt\",[\"f32:0\",\"f32:3212836864\"]],[\"invoke\",836,0,\"lt\",[\"f32:0\",\"f32:1086918619\"]],[\"invoke\",841,0,\"lt\",[\"f32:2147483648\",\"f32:4286578688\"]],[\"invoke\",847,0,\"lt\",[\"f32:2147483648\",\"f32:2143289344\"]],[\"invoke\",855,0,\"lt\",[\"f32:1\",\"f32:2147483648\"]],[\"invoke\",860,0,\"lt\",[\"f32:1\",\"f32:1\"]],[\"invoke\",864,0,\"lt\",[\"f32:1\",\"f32:8388608\"]],[\"invoke\",869,0,\"lt\",[\"f32:2147483649\",\"f32:3212836864\"]],[\"invoke\",874,0,\"lt\",[\"f32:2147483649\",\"f32:1086918619\"]],[\"invoke\",879,0,\"lt\",[\"f32:1\",\"f32:4286578687\"]],[\"invoke\",884,0,\"lt\",[\"f32:1\",\"f32:2139095040\"]],[\"invoke\",893,0,\"lt\",[\"f32:2155872256\",\"f32:2147483648\"]],[\"invoke\",898,0,\"lt\",[\"f32:2155872256\",\"f32:1\"]],[\"invoke\",903,0,\"lt\",[\"f32:8388608\",\"f32:2155872256\"]],[\"invoke\",907,0,\"lt\",[\"f32:8388608\",\"f32:3204448256\"]],[\"invoke\",912,0,\"lt\",[\"f32:8388608\",\"f32:1065353216\"]],[\"invoke\",917,0,\"lt\",[\"f32:2155872256\",\"f32:4286578687\"]],[\"invoke\",922,0,\"lt\",[\"f32:2155872256\",\"f32:2139095040\"]],[\"invoke\",929,0,\"lt\",[\"f32:8388608\",\"f32:4290772992\"]],[\"invoke\",936,0,\"lt\",[\"f32:1056964608\",\"f32:0\"]],[\"invoke\",941,0,\"lt\",[\"f32:3204448256\",\"f32:2155872256\"]],[\"invoke\",945,0,\"lt\",[\"f32:3204448256\",\"f32:3204448256\"]],[\"invoke\",950,0,\"lt\",[\"f32:3204448256\",\"f32:1065353216\"]],[\"invoke\",955,0,\"lt\",[\"f32:1056964608\",\"f32:3234402267\"]],[\"invoke\",960,0,\"lt\",[\"f32:1056964608\",\"f32:2139095039\"]],[\"invoke\",965,0,\"lt\",[\"f32:3204448256\",\"f32:4290772992\"]],[\"invoke\",974,0,\"lt\",[\"f32:3212836864\",\"f32:0\"]],[\"invoke\",979,0,\"lt\",[\"f32:1065353216\",\"f32:2147483649\"]],[\"invoke\",983,0,\"lt\",[\"f32:1065353216\",\"f32:2155872256\"]],[\"invoke\",988,0,\"lt\",[\"f32:1065353216\",\"f32:1056964608\"]],[\"invoke\",993,0,\"lt\",[\"f32:3212836864\",\"f32:3234402267\"]],[\"invoke\",998,0,\"lt\",[\"f32:3212836864\",\"f32:2139095039\"]],[\"invoke\",1003,0,\"lt\",[\"f32:1065353216\",\"f32:4286578688\"]],[\"invoke\",1011,0,\"lt\",[\"f32:1065353216\",\"f32:2143289344\"]],[\"invoke\",1017,0,\"lt\",[\"f32:3234402267\",\"f32:2147483649\"]],[\"invoke\",1021,0,\"lt\",[\"f32:3234402267\",\"f32:2155872256\"]],[\"invoke\",1026,0,\"lt\",[\"f32:3234402267\",\"f32:1056964608\"]],[\"invoke\",1031,0,\"lt\",[\"f32:1086918619\",\"f32:3212836864\"]],[\"invoke\",1036,0,\"lt\",[\"f32:1086918619\",\"f32:1086918619\"]],[\"invoke\",1041,0,\"lt\",[\"f32:3234402267\",\"f32:4286578688\"]],[\"invoke\",1047,0,\"lt\",[\"f32:3234402267\",\"f32:2143289344\"]],[\"invoke\",1055,0,\"lt\",[\"f32:2139095039\",\"f32:2147483648\"]],[\"invoke\",1059,0,\"lt\",[\"f32:2139095039\",\"f32:2147483649\"]],[\"invoke\",1064,0,\"lt\",[\"f32:2139095039\",\"f32:8388608\"]],[\"invoke\",1069,0,\"lt\",[\"f32:4286578687\",\"f32:3212836864\"]],[\"invoke\",1074,0,\"lt\",[\"f32:4286578687\",\"f32:1086918619\"]],[\"invoke\",1079,0,\"lt\",[\"f32:2139095039\",\"f32:4286578687\"]],[\"invoke\",1084,0,\"lt\",[\"f32:2139095039\",\"f32:2139095040\"]],[\"invoke\",1093,0,\"lt\",[\"f32:4286578688\",\"f32:2147483648\"]],[\"invoke\",1097,0,\"lt\",[\"f32:4286578688\",\"f32:2147483649\"]],[\"invoke\",1102,0,\"lt\",[\"f32:4286578688\",\"f32:8388608\"]],[\"invoke\",1107,0,\"lt\",[\"f32:2139095040\",\"f32:3204448256\"]],[\"invoke\",1112,0,\"lt\",[\"f32:2139095040\",\"f32:1065353216\"]],[\"invoke\",1117,0,\"lt\",[\"f32:4286578688\",\"f32:4286578687\"]],[\"invoke\",1122,0,\"lt\",[\"f32:4286578688\",\"f32:2139095040\"]],[\"invoke\",1129,0,\"lt\",[\"f32:2139095040\",\"f32:4290772992\"]],[\"invoke\",1137,0,\"lt\",[\"f32:2143289344\",\"f32:2147483648\"]],[\"invoke\",1147,0,\"lt\",[\"f32:2143289344\",\"f32:1\"]],[\"invoke\",1157,0,\"lt\",[\"f32:4290772992\",\"f32:3204448256\"]],[\"invoke\",1167,0,\"lt\",[\"f32:4290772992\",\"f32:1065353216\"]],[\"invoke\",1177,0,\"lt\",[\"f32:2143289344\",\"f32:3234402267\"]],[\"invoke\",1187,0,\"lt\",[\"f32:2143289344\",\"f32:2139095039\"]],[\"invoke\",1197,0,\"lt\",[\"f32:4290772992\",\"f32:4290772992\"]],[\"invoke\",1214,0,\"le\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",1218,0,\"le\",[\"f32:2147483648\",\"f32:1\"]],[\"invoke\",1223,0,\"le\",[\"f32:0\",\"f32:2155872256\"]],[\"invoke\",1228,0,\"le\",[\"f32:0\",\"f32:1056964608\"]],[\"invoke\",1233,0,\"le\",[\"f32:2147483648\",\"f32:3234402267\"]],[\"invoke\",1238,0,\"le\",[\"f32:2147483648\",\"f32:2139095039\"]],[\"invoke\",1243,0,\"le\",[\"f32:0\",\"f32:4286578688\"]],[\"invoke\",1251,0,\"le\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1256,0,\"le\",[\"f32:1\",\"f32:0\"]],[\"invoke\",1261,0,\"le\",[\"f32:2147483649\",\"f32:2155872256\"]],[\"invoke\",1266,0,\"le\",[\"f32:2147483649\",\"f32:1056964608\"]],[\"invoke\",1271,0,\"le\",[\"f32:1\",\"f32:3212836864\"]],[\"invoke\",1276,0,\"le\",[\"f32:1\",\"f32:1086918619\"]],[\"invoke\",1281,0,\"le\",[\"f32:2147483649\",\"f32:4286578688\"]],[\"invoke\",1287,0,\"le\",[\"f32:2147483649\",\"f32:2143289344\"]],[\"invoke\",1294,0,\"le\",[\"f32:2155872256\",\"f32:0\"]],[\"invoke\",1299,0,\"le\",[\"f32:8388608\",\"f32:2147483649\"]],[\"invoke\",1304,0,\"le\",[\"f32:8388608\",\"f32:8388608\"]],[\"invoke\",1309,0,\"le\",[\"f32:2155872256\",\"f32:3212836864\"]],[\"invoke\",1314,0,\"le\",[\"f32:2155872256\",\"f32:1086918619\"]],[\"invoke\",1319,0,\"le\",[\"f32:8388608\",\"f32:4286578687\"]],[\"invoke\",1324,0,\"le\",[\"f32:8388608\",\"f32:2139095040\"]],[\"invoke\",1331,0,\"le\",[\"f32:8388608\",\"f32:2143289344\"]],[\"invoke\",1337,0,\"le\",[\"f32:3204448256\",\"f32:2147483649\"]],[\"invoke\",1342,0,\"le\",[\"f32:3204448256\",\"f32:8388608\"]],[\"invoke\",1347,0,\"le\",[\"f32:1056964608\",\"f32:3204448256\"]],[\"invoke\",1352,0,\"le\",[\"f32:1056964608\",\"f32:1065353216\"]],[\"invoke\",1357,0,\"le\",[\"f32:3204448256\",\"f32:4286578687\"]],[\"invoke\",1362,0,\"le\",[\"f32:3204448256\",\"f32:2139095040\"]],[\"invoke\",1367,0,\"le\",[\"f32:3204448256\",\"f32:2143289344\"]],[\"invoke\",1375,0,\"le\",[\"f32:1065353216\",\"f32:2147483648\"]],[\"invoke\",1380,0,\"le\",[\"f32:1065353216\",\"f32:1\"]],[\"invoke\",1385,0,\"le\",[\"f32:3212836864\",\"f32:3204448256\"]],[\"invoke\",1390,0,\"le\",[\"f32:3212836864\",\"f32:1065353216\"]],[\"invoke\",1395,0,\"le\",[\"f32:1065353216\",\"f32:3234402267\"]],[\"invoke\",1400,0,\"le\",[\"f32:1065353216\",\"f32:2139095039\"]],[\"invoke\",1404,0,\"le\",[\"f32:1065353216\",\"f32:2139095040\"]],[\"invoke\",1413,0,\"le\",[\"f32:3234402267\",\"f32:2147483648\"]],[\"invoke\",1418,0,\"le\",[\"f32:3234402267\",\"f32:1\"]],[\"invoke\",1423,0,\"le\",[\"f32:1086918619\",\"f32:2155872256\"]],[\"invoke\",1428,0,\"le\",[\"f32:1086918619\",\"f32:1056964608\"]],[\"invoke\",1433,0,\"le\",[\"f32:3234402267\",\"f32:3234402267\"]],[\"invoke\",1438,0,\"le\",[\"f32:3234402267\",\"f32:2139095039\"]],[\"invoke\",1442,0,\"le\",[\"f32:3234402267\",\"f32:2139095040\"]],[\"invoke\",1449,0,\"le\",[\"f32:1086918619\",\"f32:4290772992\"]],[\"invoke\",1456,0,\"le\",[\"f32:2139095039\",\"f32:0\"]],[\"invoke\",1461,0,\"le\",[\"f32:4286578687\",\"f32:2155872256\"]],[\"invoke\",1466,0,\"le\",[\"f32:4286578687\",\"f32:1056964608\"]],[\"invoke\",1471,0,\"le\",[\"f32:2139095039\",\"f32:3212836864\"]],[\"invoke\",1476,0,\"le\",[\"f32:2139095039\",\"f32:1086918619\"]],[\"invoke\",1480,0,\"le\",[\"f32:2139095039\",\"f32:2139095039\"]],[\"invoke\",1485,0,\"le\",[\"f32:4286578687\",\"f32:4290772992\"]],[\"invoke\",1494,0,\"le\",[\"f32:4286578688\",\"f32:0\"]],[\"invoke\",1499,0,\"le\",[\"f32:2139095040\",\"f32:2147483649\"]],[\"invoke\",1504,0,\"le\",[\"f32:2139095040\",\"f32:8388608\"]],[\"invoke\",1509,0,\"le\",[\"f32:4286578688\",\"f32:3212836864\"]],[\"invoke\",1514,0,\"le\",[\"f32:4286578688\",\"f32:1086918619\"]],[\"invoke\",1519,0,\"le\",[\"f32:2139095040\",\"f32:4286578687\"]],[\"invoke\",1523,0,\"le\",[\"f32:2139095040\",\"f32:4286578688\"]],[\"invoke\",1531,0,\"le\",[\"f32:2139095040\",\"f32:2143289344\"]],[\"invoke\",1541,0,\"le\",[\"f32:4290772992\",\"f32:2147483649\"]],[\"invoke\",1551,0,\"le\",[\"f32:4290772992\",\"f32:8388608\"]],[\"invoke\",1561,0,\"le\",[\"f32:2143289344\",\"f32:3204448256\"]],[\"invoke\",1571,0,\"le\",[\"f32:2143289344\",\"f32:1065353216\"]],[\"invoke\",1581,0,\"le\",[\"f32:4290772992\",\"f32:4286578687\"]],[\"invoke\",1589,0,\"le\",[\"f32:4290772992\",\"f32:4286578688\"]],[\"invoke\",1601,0,\"le\",[\"f32:4290772992\",\"f32:2143289344\"]],[\"invoke\",1615,0,\"gt\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1620,0,\"gt\",[\"f32:0\",\"f32:1\"]],[\"invoke\",1625,0,\"gt\",[\"f32:2147483648\",\"f32:3204448256\"]],[\"invoke\",1630,0,\"gt\",[\"f32:2147483648\",\"f32:1065353216\"]],[\"invoke\",1635,0,\"gt\",[\"f32:0\",\"f32:3234402267\"]],[\"invoke\",1639,0,\"gt\",[\"f32:0\",\"f32:4286578687\"]],[\"invoke\",1644,0,\"gt\",[\"f32:0\",\"f32:2139095040\"]],[\"invoke\",1653,0,\"gt\",[\"f32:2147483649\",\"f32:2147483648\"]],[\"invoke\",1658,0,\"gt\",[\"f32:2147483649\",\"f32:1\"]],[\"invoke\",1663,0,\"gt\",[\"f32:1\",\"f32:2155872256\"]],[\"invoke\",1668,0,\"gt\",[\"f32:1\",\"f32:1056964608\"]],[\"invoke\",1673,0,\"gt\",[\"f32:2147483649\",\"f32:3234402267\"]],[\"invoke\",1677,0,\"gt\",[\"f32:2147483649\",\"f32:4286578687\"]],[\"invoke\",1682,0,\"gt\",[\"f32:2147483649\",\"f32:2139095040\"]],[\"invoke\",1689,0,\"gt\",[\"f32:1\",\"f32:4290772992\"]],[\"invoke\",1696,0,\"gt\",[\"f32:8388608\",\"f32:0\"]],[\"invoke\",1701,0,\"gt\",[\"f32:2155872256\",\"f32:2155872256\"]],[\"invoke\",1706,0,\"gt\",[\"f32:2155872256\",\"f32:1056964608\"]],[\"invoke\",1711,0,\"gt\",[\"f32:8388608\",\"f32:3212836864\"]],[\"invoke\",1715,0,\"gt\",[\"f32:8388608\",\"f32:3234402267\"]],[\"invoke\",1720,0,\"gt\",[\"f32:8388608\",\"f32:2139095039\"]],[\"invoke\",1725,0,\"gt\",[\"f32:2155872256\",\"f32:4290772992\"]],[\"invoke\",1734,0,\"gt\",[\"f32:3204448256\",\"f32:0\"]],[\"invoke\",1739,0,\"gt\",[\"f32:1056964608\",\"f32:2147483649\"]],[\"invoke\",1744,0,\"gt\",[\"f32:1056964608\",\"f32:8388608\"]],[\"invoke\",1749,0,\"gt\",[\"f32:3204448256\",\"f32:3212836864\"]],[\"invoke\",1753,0,\"gt\",[\"f32:3204448256\",\"f32:3234402267\"]],[\"invoke\",1758,0,\"gt\",[\"f32:3204448256\",\"f32:2139095039\"]],[\"invoke\",1763,0,\"gt\",[\"f32:1056964608\",\"f32:4286578688\"]],[\"invoke\",1771,0,\"gt\",[\"f32:1056964608\",\"f32:2143289344\"]],[\"invoke\",1777,0,\"gt\",[\"f32:3212836864\",\"f32:2147483649\"]],[\"invoke\",1782,0,\"gt\",[\"f32:3212836864\",\"f32:8388608\"]],[\"invoke\",1787,0,\"gt\",[\"f32:1065353216\",\"f32:3204448256\"]],[\"invoke\",1791,0,\"gt\",[\"f32:1065353216\",\"f32:3212836864\"]],[\"invoke\",1796,0,\"gt\",[\"f32:1065353216\",\"f32:1086918619\"]],[\"invoke\",1801,0,\"gt\",[\"f32:3212836864\",\"f32:4286578688\"]],[\"invoke\",1807,0,\"gt\",[\"f32:3212836864\",\"f32:2143289344\"]],[\"invoke\",1815,0,\"gt\",[\"f32:1086918619\",\"f32:2147483648\"]],[\"invoke\",1820,0,\"gt\",[\"f32:1086918619\",\"f32:1\"]],[\"invoke\",1825,0,\"gt\",[\"f32:3234402267\",\"f32:3204448256\"]],[\"invoke\",1830,0,\"gt\",[\"f32:3234402267\",\"f32:1065353216\"]],[\"invoke\",1834,0,\"gt\",[\"f32:3234402267\",\"f32:1086918619\"]],[\"invoke\",1839,0,\"gt\",[\"f32:1086918619\",\"f32:4286578687\"]],[\"invoke\",1844,0,\"gt\",[\"f32:1086918619\",\"f32:2139095040\"]],[\"invoke\",1853,0,\"gt\",[\"f32:4286578687\",\"f32:2147483648\"]],[\"invoke\",1858,0,\"gt\",[\"f32:4286578687\",\"f32:1\"]],[\"invoke\",1863,0,\"gt\",[\"f32:2139095039\",\"f32:2155872256\"]],[\"invoke\",1868,0,\"gt\",[\"f32:2139095039\",\"f32:1056964608\"]],[\"invoke\",1872,0,\"gt\",[\"f32:2139095039\",\"f32:1065353216\"]],[\"invoke\",1877,0,\"gt\",[\"f32:4286578687\",\"f32:4286578687\"]],[\"invoke\",1882,0,\"gt\",[\"f32:4286578687\",\"f32:2139095040\"]],[\"invoke\",1889,0,\"gt\",[\"f32:2139095039\",\"f32:4290772992\"]],[\"invoke\",1896,0,\"gt\",[\"f32:2139095040\",\"f32:0\"]],[\"invoke\",1901,0,\"gt\",[\"f32:4286578688\",\"f32:2155872256\"]],[\"invoke\",1906,0,\"gt\",[\"f32:4286578688\",\"f32:1056964608\"]],[\"invoke\",1910,0,\"gt\",[\"f32:4286578688\",\"f32:1065353216\"]],[\"invoke\",1915,0,\"gt\",[\"f32:2139095040\",\"f32:3234402267\"]],[\"invoke\",1920,0,\"gt\",[\"f32:2139095040\",\"f32:2139095039\"]],[\"invoke\",1925,0,\"gt\",[\"f32:4286578688\",\"f32:4290772992\"]],[\"invoke\",1935,0,\"gt\",[\"f32:4290772992\",\"f32:0\"]],[\"invoke\",1945,0,\"gt\",[\"f32:2143289344\",\"f32:2147483649\"]],[\"invoke\",1955,0,\"gt\",[\"f32:2143289344\",\"f32:8388608\"]],[\"invoke\",1963,0,\"gt\",[\"f32:2143289344\",\"f32:1056964608\"]],[\"invoke\",1973,0,\"gt\",[\"f32:4290772992\",\"f32:3234402267\"]],[\"invoke\",1983,0,\"gt\",[\"f32:4290772992\",\"f32:2139095039\"]],[\"invoke\",1993,0,\"gt\",[\"f32:2143289344\",\"f32:4286578688\"]],[\"invoke\",2009,0,\"gt\",[\"f32:2143289344\",\"f32:2143289344\"]],[\"invoke\",2017,0,\"ge\",[\"f32:2147483648\",\"f32:2147483649\"]],[\"invoke\",2022,0,\"ge\",[\"f32:2147483648\",\"f32:8388608\"]],[\"invoke\",2026,0,\"ge\",[\"f32:2147483648\",\"f32:1056964608\"]],[\"invoke\",2031,0,\"ge\",[\"f32:0\",\"f32:3212836864\"]],[\"invoke\",2036,0,\"ge\",[\"f32:0\",\"f32:1086918619\"]],[\"invoke\",2041,0,\"ge\",[\"f32:2147483648\",\"f32:4286578688\"]],[\"invoke\",2047,0,\"ge\",[\"f32:2147483648\",\"f32:2143289344\"]],[\"invoke\",2055,0,\"ge\",[\"f32:1\",\"f32:2147483648\"]],[\"invoke\",2060,0,\"ge\",[\"f32:1\",\"f32:1\"]],[\"invoke\",2064,0,\"ge\",[\"f32:1\",\"f32:8388608\"]],[\"invoke\",2069,0,\"ge\",[\"f32:2147483649\",\"f32:3212836864\"]],[\"invoke\",2074,0,\"ge\",[\"f32:2147483649\",\"f32:1086918619\"]],[\"invoke\",2079,0,\"ge\",[\"f32:1\",\"f32:4286578687\"]],[\"invoke\",2084,0,\"ge\",[\"f32:1\",\"f32:2139095040\"]],[\"invoke\",2093,0,\"ge\",[\"f32:2155872256\",\"f32:2147483648\"]],[\"invoke\",2098,0,\"ge\",[\"f32:2155872256\",\"f32:1\"]],[\"invoke\",2102,0,\"ge\",[\"f32:2155872256\",\"f32:8388608\"]],[\"invoke\",2107,0,\"ge\",[\"f32:8388608\",\"f32:3204448256\"]],[\"invoke\",2112,0,\"ge\",[\"f32:8388608\",\"f32:1065353216\"]],[\"invoke\",2117,0,\"ge\",[\"f32:2155872256\",\"f32:4286578687\"]],[\"invoke\",2122,0,\"ge\",[\"f32:2155872256\",\"f32:2139095040\"]],[\"invoke\",2129,0,\"ge\",[\"f32:8388608\",\"f32:4290772992\"]],[\"invoke\",2136,0,\"ge\",[\"f32:1056964608\",\"f32:0\"]],[\"invoke\",2141,0,\"ge\",[\"f32:3204448256\",\"f32:2155872256\"]],[\"invoke\",2145,0,\"ge\",[\"f32:3204448256\",\"f32:3204448256\"]],[\"invoke\",2150,0,\"ge\",[\"f32:3204448256\",\"f32:1065353216\"]],[\"invoke\",2155,0,\"ge\",[\"f32:1056964608\",\"f32:3234402267\"]],[\"invoke\",2160,0,\"ge\",[\"f32:1056964608\",\"f32:2139095039\"]],[\"invoke\",2165,0,\"ge\",[\"f32:3204448256\",\"f32:4290772992\"]],[\"invoke\",2174,0,\"ge\",[\"f32:3212836864\",\"f32:0\"]],[\"invoke\",2179,0,\"ge\",[\"f32:1065353216\",\"f32:2147483649\"]],[\"invoke\",2183,0,\"ge\",[\"f32:1065353216\",\"f32:2155872256\"]],[\"invoke\",2188,0,\"ge\",[\"f32:1065353216\",\"f32:1056964608\"]],[\"invoke\",2193,0,\"ge\",[\"f32:3212836864\",\"f32:3234402267\"]],[\"invoke\",2198,0,\"ge\",[\"f32:3212836864\",\"f32:2139095039\"]],[\"invoke\",2203,0,\"ge\",[\"f32:1065353216\",\"f32:4286578688\"]],[\"invoke\",2211,0,\"ge\",[\"f32:1065353216\",\"f32:2143289344\"]],[\"invoke\",2217,0,\"ge\",[\"f32:3234402267\",\"f32:2147483649\"]],[\"invoke\",2221,0,\"ge\",[\"f32:3234402267\",\"f32:2155872256\"]],[\"invoke\",2226,0,\"ge\",[\"f32:3234402267\",\"f32:1056964608\"]],[\"invoke\",2231,0,\"ge\",[\"f32:1086918619\",\"f32:3212836864\"]],[\"invoke\",2236,0,\"ge\",[\"f32:1086918619\",\"f32:1086918619\"]],[\"invoke\",2241,0,\"ge\",[\"f32:3234402267\",\"f32:4286578688\"]],[\"invoke\",2247,0,\"ge\",[\"f32:3234402267\",\"f32:2143289344\"]],[\"invoke\",2255,0,\"ge\",[\"f32:2139095039\",\"f32:2147483648\"]],[\"invoke\",2259,0,\"ge\",[\"f32:2139095039\",\"f32:2147483649\"]],[\"invoke\",2264,0,\"ge\",[\"f32:2139095039\",\"f32:8388608\"]],[\"invoke\",2269,0,\"ge\",[\"f32:4286578687\",\"f32:3212836864\"]],[\"invoke\",2274,0,\"ge\",[\"f32:4286578687\",\"f32:1086918619\"]],[\"invoke\",2279,0,\"ge\",[\"f32:2139095039\",\"f32:4286578687\"]],[\"invoke\",2284,0,\"ge\",[\"f32:2139095039\",\"f32:2139095040\"]],[\"invoke\",2293,0,\"ge\",[\"f32:4286578688\",\"f32:2147483648\"]],[\"invoke\",2297,0,\"ge\",[\"f32:4286578688\",\"f32:2147483649\"]],[\"invoke\",2302,0,\"ge\",[\"f32:4286578688\",\"f32:8388608\"]],[\"invoke\",2307,0,\"ge\",[\"f32:2139095040\",\"f32:3204448256\"]],[\"invoke\",2312,0,\"ge\",[\"f32:2139095040\",\"f32:1065353216\"]],[\"invoke\",2317,0,\"ge\",[\"f32:4286578688\",\"f32:4286578687\"]],[\"invoke\",2322,0,\"ge\",[\"f32:4286578688\",\"f32:2139095040\"]],[\"invoke\",2329,0,\"ge\",[\"f32:2139095040\",\"f32:4290772992\"]],[\"invoke\",2337,0,\"ge\",[\"f32:2143289344\",\"f32:2147483648\"]],[\"invoke\",2347,0,\"ge\",[\"f32:2143289344\",\"f32:1\"]],[\"invoke\",2357,0,\"ge\",[\"f32:4290772992\",\"f32:3204448256\"]],[\"invoke\",2367,0,\"ge\",[\"f32:4290772992\",\"f32:1065353216\"]],[\"invoke\",2377,0,\"ge\",[\"f32:2143289344\",\"f32:3234402267\"]],[\"invoke\",2387,0,\"ge\",[\"f32:2143289344\",\"f32:2139095039\"]],[\"invoke\",2397,0,\"ge\",[\"f32:4290772992\",\"f32:4290772992\"]],[\"file\",\"f64_cmp.wast\"],[\"module\",4,3],[\"invoke\",13,0,\"eq\",[\"f64:9223372036854775808\",\"f64:9223372036854775808\"]],[\"invoke\",18,0,\"eq\",[\"f64:9223372036854775808\",\"f64:1\"]],[\"invoke\",23,0,\"eq\",[\"f64:0\",\"f64:9227875636482146304\"]],[\"invoke\",28,0,\"eq\",[\"f64:0\",\"f64:4602678819172646912\"]],[\"invoke\",33,0,\"eq\",[\"f64:9223372036854775808\",\"f64:13842132293034192152\"]],[\"invoke\",38,0,\"eq\",[\"f64:9223372036854775808\",\"f64:9218868437227405311\"]],[\"invoke\",43,0,\"eq\",[\"f64:0\",\"f64:18442240474082181120\"]],[\"invoke\",51,0,\"eq\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",56,0,\"eq\",[\"f64:1\",\"f64:0\"]],[\"invoke\",61,0,\"eq\",[\"f64:9223372036854775809\",\"f64:9227875636482146304\"]],[\"invoke\",66,0,\"eq\",[\"f64:9223372036854775809\",\"f64:4602678819172646912\"]],[\"invoke\",71,0,\"eq\",[\"f64:1\",\"f64:13830554455654793216\"]],[\"invoke\",76,0,\"eq\",[\"f64:1\",\"f64:4618760256179416344\"]],[\"invoke\",81,0,\"eq\",[\"f64:9223372036854775809\",\"f64:18442240474082181120\"]],[\"invoke\",87,0,\"eq\",[\"f64:9223372036854775809\",\"f64:9221120237041090560\"]],[\"invoke\",94,0,\"eq\",[\"f64:9227875636482146304\",\"f64:0\"]],[\"invoke\",99,0,\"eq\",[\"f64:4503599627370496\",\"f64:9223372036854775809\"]],[\"invoke\",104,0,\"eq\",[\"f64:4503599627370496\",\"f64:4503599627370496\"]],[\"invoke\",109,0,\"eq\",[\"f64:9227875636482146304\",\"f64:13830554455654793216\"]],[\"invoke\",114,0,\"eq\",[\"f64:9227875636482146304\",\"f64:4618760256179416344\"]],[\"invoke\",119,0,\"eq\",[\"f64:4503599627370496\",\"f64:18442240474082181119\"]],[\"invoke\",124,0,\"eq\",[\"f64:4503599627370496\",\"f64:9218868437227405312\"]],[\"invoke\",131,0,\"eq\",[\"f64:4503599627370496\",\"f64:9221120237041090560\"]],[\"invoke\",137,0,\"eq\",[\"f64:13826050856027422720\",\"f64:9223372036854775809\"]],[\"invoke\",142,0,\"eq\",[\"f64:13826050856027422720\",\"f64:4503599627370496\"]],[\"invoke\",147,0,\"eq\",[\"f64:4602678819172646912\",\"f64:13826050856027422720\"]],[\"invoke\",152,0,\"eq\",[\"f64:4602678819172646912\",\"f64:4607182418800017408\"]],[\"invoke\",157,0,\"eq\",[\"f64:13826050856027422720\",\"f64:18442240474082181119\"]],[\"invoke\",162,0,\"eq\",[\"f64:13826050856027422720\",\"f64:9218868437227405312\"]],[\"invoke\",167,0,\"eq\",[\"f64:13826050856027422720\",\"f64:9221120237041090560\"]],[\"invoke\",175,0,\"eq\",[\"f64:4607182418800017408\",\"f64:9223372036854775808\"]],[\"invoke\",180,0,\"eq\",[\"f64:4607182418800017408\",\"f64:1\"]],[\"invoke\",185,0,\"eq\",[\"f64:13830554455654793216\",\"f64:13826050856027422720\"]],[\"invoke\",190,0,\"eq\",[\"f64:13830554455654793216\",\"f64:4607182418800017408\"]],[\"invoke\",195,0,\"eq\",[\"f64:4607182418800017408\",\"f64:13842132293034192152\"]],[\"invoke\",200,0,\"eq\",[\"f64:4607182418800017408\",\"f64:9218868437227405311\"]],[\"invoke\",204,0,\"eq\",[\"f64:4607182418800017408\",\"f64:9218868437227405312\"]],[\"invoke\",213,0,\"eq\",[\"f64:13842132293034192152\",\"f64:9223372036854775808\"]],[\"invoke\",218,0,\"eq\",[\"f64:13842132293034192152\",\"f64:1\"]],[\"invoke\",223,0,\"eq\",[\"f64:4618760256179416344\",\"f64:9227875636482146304\"]],[\"invoke\",228,0,\"eq\",[\"f64:4618760256179416344\",\"f64:4602678819172646912\"]],[\"invoke\",233,0,\"eq\",[\"f64:13842132293034192152\",\"f64:13842132293034192152\"]],[\"invoke\",238,0,\"eq\",[\"f64:13842132293034192152\",\"f64:9218868437227405311\"]],[\"invoke\",242,0,\"eq\",[\"f64:13842132293034192152\",\"f64:9218868437227405312\"]],[\"invoke\",249,0,\"eq\",[\"f64:4618760256179416344\",\"f64:18444492273895866368\"]],[\"invoke\",256,0,\"eq\",[\"f64:9218868437227405311\",\"f64:0\"]],[\"invoke\",261,0,\"eq\",[\"f64:18442240474082181119\",\"f64:9227875636482146304\"]],[\"invoke\",266,0,\"eq\",[\"f64:18442240474082181119\",\"f64:4602678819172646912\"]],[\"invoke\",271,0,\"eq\",[\"f64:9218868437227405311\",\"f64:13830554455654793216\"]],[\"invoke\",276,0,\"eq\",[\"f64:9218868437227405311\",\"f64:4618760256179416344\"]],[\"invoke\",281,0,\"eq\",[\"f64:18442240474082181119\",\"f64:18442240474082181120\"]],[\"invoke\",285,0,\"eq\",[\"f64:18442240474082181119\",\"f64:18444492273895866368\"]],[\"invoke\",294,0,\"eq\",[\"f64:18442240474082181120\",\"f64:0\"]],[\"invoke\",299,0,\"eq\",[\"f64:9218868437227405312\",\"f64:9223372036854775809\"]],[\"invoke\",304,0,\"eq\",[\"f64:9218868437227405312\",\"f64:4503599627370496\"]],[\"invoke\",309,0,\"eq\",[\"f64:18442240474082181120\",\"f64:13830554455654793216\"]],[\"invoke\",314,0,\"eq\",[\"f64:18442240474082181120\",\"f64:4618760256179416344\"]],[\"invoke\",319,0,\"eq\",[\"f64:9218868437227405312\",\"f64:18442240474082181119\"]],[\"invoke\",323,0,\"eq\",[\"f64:9218868437227405312\",\"f64:18442240474082181120\"]],[\"invoke\",331,0,\"eq\",[\"f64:9218868437227405312\",\"f64:9221120237041090560\"]],[\"invoke\",341,0,\"eq\",[\"f64:18444492273895866368\",\"f64:9223372036854775809\"]],[\"invoke\",351,0,\"eq\",[\"f64:18444492273895866368\",\"f64:4503599627370496\"]],[\"invoke\",361,0,\"eq\",[\"f64:9221120237041090560\",\"f64:13826050856027422720\"]],[\"invoke\",371,0,\"eq\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\"]],[\"invoke\",381,0,\"eq\",[\"f64:18444492273895866368\",\"f64:18442240474082181119\"]],[\"invoke\",389,0,\"eq\",[\"f64:18444492273895866368\",\"f64:18442240474082181120\"]],[\"invoke\",401,0,\"eq\",[\"f64:18444492273895866368\",\"f64:9221120237041090560\"]],[\"invoke\",415,0,\"ne\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",420,0,\"ne\",[\"f64:0\",\"f64:1\"]],[\"invoke\",425,0,\"ne\",[\"f64:9223372036854775808\",\"f64:13826050856027422720\"]],[\"invoke\",430,0,\"ne\",[\"f64:9223372036854775808\",\"f64:4607182418800017408\"]],[\"invoke\",435,0,\"ne\",[\"f64:0\",\"f64:13842132293034192152\"]],[\"invoke\",439,0,\"ne\",[\"f64:0\",\"f64:18442240474082181119\"]],[\"invoke\",444,0,\"ne\",[\"f64:0\",\"f64:9218868437227405312\"]],[\"invoke\",453,0,\"ne\",[\"f64:9223372036854775809\",\"f64:9223372036854775808\"]],[\"invoke\",458,0,\"ne\",[\"f64:9223372036854775809\",\"f64:1\"]],[\"invoke\",463,0,\"ne\",[\"f64:1\",\"f64:9227875636482146304\"]],[\"invoke\",468,0,\"ne\",[\"f64:1\",\"f64:4602678819172646912\"]],[\"invoke\",473,0,\"ne\",[\"f64:9223372036854775809\",\"f64:13842132293034192152\"]],[\"invoke\",477,0,\"ne\",[\"f64:9223372036854775809\",\"f64:18442240474082181119\"]],[\"invoke\",482,0,\"ne\",[\"f64:9223372036854775809\",\"f64:9218868437227405312\"]],[\"invoke\",489,0,\"ne\",[\"f64:1\",\"f64:18444492273895866368\"]],[\"invoke\",496,0,\"ne\",[\"f64:4503599627370496\",\"f64:0\"]],[\"invoke\",501,0,\"ne\",[\"f64:9227875636482146304\",\"f64:9227875636482146304\"]],[\"invoke\",506,0,\"ne\",[\"f64:9227875636482146304\",\"f64:4602678819172646912\"]],[\"invoke\",511,0,\"ne\",[\"f64:4503599627370496\",\"f64:13830554455654793216\"]],[\"invoke\",515,0,\"ne\",[\"f64:4503599627370496\",\"f64:13842132293034192152\"]],[\"invoke\",520,0,\"ne\",[\"f64:4503599627370496\",\"f64:9218868437227405311\"]],[\"invoke\",525,0,\"ne\",[\"f64:9227875636482146304\",\"f64:18444492273895866368\"]],[\"invoke\",534,0,\"ne\",[\"f64:13826050856027422720\",\"f64:0\"]],[\"invoke\",539,0,\"ne\",[\"f64:4602678819172646912\",\"f64:9223372036854775809\"]],[\"invoke\",544,0,\"ne\",[\"f64:4602678819172646912\",\"f64:4503599627370496\"]],[\"invoke\",549,0,\"ne\",[\"f64:13826050856027422720\",\"f64:13830554455654793216\"]],[\"invoke\",553,0,\"ne\",[\"f64:13826050856027422720\",\"f64:13842132293034192152\"]],[\"invoke\",558,0,\"ne\",[\"f64:13826050856027422720\",\"f64:9218868437227405311\"]],[\"invoke\",563,0,\"ne\",[\"f64:4602678819172646912\",\"f64:18442240474082181120\"]],[\"invoke\",571,0,\"ne\",[\"f64:4602678819172646912\",\"f64:9221120237041090560\"]],[\"invoke\",577,0,\"ne\",[\"f64:13830554455654793216\",\"f64:9223372036854775809\"]],[\"invoke\",582,0,\"ne\",[\"f64:13830554455654793216\",\"f64:4503599627370496\"]],[\"invoke\",587,0,\"ne\",[\"f64:4607182418800017408\",\"f64:13826050856027422720\"]],[\"invoke\",592,0,\"ne\",[\"f64:4607182418800017408\",\"f64:4607182418800017408\"]],[\"invoke\",596,0,\"ne\",[\"f64:4607182418800017408\",\"f64:4618760256179416344\"]],[\"invoke\",601,0,\"ne\",[\"f64:13830554455654793216\",\"f64:18442240474082181120\"]],[\"invoke\",607,0,\"ne\",[\"f64:13830554455654793216\",\"f64:9221120237041090560\"]],[\"invoke\",615,0,\"ne\",[\"f64:4618760256179416344\",\"f64:9223372036854775808\"]],[\"invoke\",620,0,\"ne\",[\"f64:4618760256179416344\",\"f64:1\"]],[\"invoke\",625,0,\"ne\",[\"f64:13842132293034192152\",\"f64:13826050856027422720\"]],[\"invoke\",630,0,\"ne\",[\"f64:13842132293034192152\",\"f64:4607182418800017408\"]],[\"invoke\",634,0,\"ne\",[\"f64:13842132293034192152\",\"f64:4618760256179416344\"]],[\"invoke\",639,0,\"ne\",[\"f64:4618760256179416344\",\"f64:18442240474082181119\"]],[\"invoke\",644,0,\"ne\",[\"f64:4618760256179416344\",\"f64:9218868437227405312\"]],[\"invoke\",653,0,\"ne\",[\"f64:18442240474082181119\",\"f64:9223372036854775808\"]],[\"invoke\",658,0,\"ne\",[\"f64:18442240474082181119\",\"f64:1\"]],[\"invoke\",663,0,\"ne\",[\"f64:9218868437227405311\",\"f64:9227875636482146304\"]],[\"invoke\",668,0,\"ne\",[\"f64:9218868437227405311\",\"f64:4602678819172646912\"]],[\"invoke\",672,0,\"ne\",[\"f64:9218868437227405311\",\"f64:4607182418800017408\"]],[\"invoke\",677,0,\"ne\",[\"f64:18442240474082181119\",\"f64:18442240474082181119\"]],[\"invoke\",682,0,\"ne\",[\"f64:18442240474082181119\",\"f64:9218868437227405312\"]],[\"invoke\",689,0,\"ne\",[\"f64:9218868437227405311\",\"f64:18444492273895866368\"]],[\"invoke\",696,0,\"ne\",[\"f64:9218868437227405312\",\"f64:0\"]],[\"invoke\",701,0,\"ne\",[\"f64:18442240474082181120\",\"f64:9227875636482146304\"]],[\"invoke\",706,0,\"ne\",[\"f64:18442240474082181120\",\"f64:4602678819172646912\"]],[\"invoke\",710,0,\"ne\",[\"f64:18442240474082181120\",\"f64:4607182418800017408\"]],[\"invoke\",715,0,\"ne\",[\"f64:9218868437227405312\",\"f64:13842132293034192152\"]],[\"invoke\",720,0,\"ne\",[\"f64:9218868437227405312\",\"f64:9218868437227405311\"]],[\"invoke\",725,0,\"ne\",[\"f64:18442240474082181120\",\"f64:18444492273895866368\"]],[\"invoke\",735,0,\"ne\",[\"f64:18444492273895866368\",\"f64:0\"]],[\"invoke\",745,0,\"ne\",[\"f64:9221120237041090560\",\"f64:9223372036854775809\"]],[\"invoke\",755,0,\"ne\",[\"f64:9221120237041090560\",\"f64:4503599627370496\"]],[\"invoke\",763,0,\"ne\",[\"f64:9221120237041090560\",\"f64:4602678819172646912\"]],[\"invoke\",773,0,\"ne\",[\"f64:18444492273895866368\",\"f64:13842132293034192152\"]],[\"invoke\",783,0,\"ne\",[\"f64:18444492273895866368\",\"f64:9218868437227405311\"]],[\"invoke\",793,0,\"ne\",[\"f64:9221120237041090560\",\"f64:18442240474082181120\"]],[\"invoke\",809,0,\"ne\",[\"f64:9221120237041090560\",\"f64:9221120237041090560\"]],[\"invoke\",817,0,\"lt\",[\"f64:9223372036854775808\",\"f64:9223372036854775809\"]],[\"invoke\",822,0,\"lt\",[\"f64:9223372036854775808\",\"f64:4503599627370496\"]],[\"invoke\",826,0,\"lt\",[\"f64:9223372036854775808\",\"f64:4602678819172646912\"]],[\"invoke\",831,0,\"lt\",[\"f64:0\",\"f64:13830554455654793216\"]],[\"invoke\",836,0,\"lt\",[\"f64:0\",\"f64:4618760256179416344\"]],[\"invoke\",841,0,\"lt\",[\"f64:9223372036854775808\",\"f64:18442240474082181120\"]],[\"invoke\",847,0,\"lt\",[\"f64:9223372036854775808\",\"f64:9221120237041090560\"]],[\"invoke\",855,0,\"lt\",[\"f64:1\",\"f64:9223372036854775808\"]],[\"invoke\",860,0,\"lt\",[\"f64:1\",\"f64:1\"]],[\"invoke\",864,0,\"lt\",[\"f64:1\",\"f64:4503599627370496\"]],[\"invoke\",869,0,\"lt\",[\"f64:9223372036854775809\",\"f64:13830554455654793216\"]],[\"invoke\",874,0,\"lt\",[\"f64:9223372036854775809\",\"f64:4618760256179416344\"]],[\"invoke\",879,0,\"lt\",[\"f64:1\",\"f64:18442240474082181119\"]],[\"invoke\",884,0,\"lt\",[\"f64:1\",\"f64:9218868437227405312\"]],[\"invoke\",893,0,\"lt\",[\"f64:9227875636482146304\",\"f64:9223372036854775808\"]],[\"invoke\",898,0,\"lt\",[\"f64:9227875636482146304\",\"f64:1\"]],[\"invoke\",903,0,\"lt\",[\"f64:4503599627370496\",\"f64:9227875636482146304\"]],[\"invoke\",907,0,\"lt\",[\"f64:4503599627370496\",\"f64:13826050856027422720\"]],[\"invoke\",912,0,\"lt\",[\"f64:4503599627370496\",\"f64:4607182418800017408\"]],[\"invoke\",917,0,\"lt\",[\"f64:9227875636482146304\",\"f64:18442240474082181119\"]],[\"invoke\",922,0,\"lt\",[\"f64:9227875636482146304\",\"f64:9218868437227405312\"]],[\"invoke\",929,0,\"lt\",[\"f64:4503599627370496\",\"f64:18444492273895866368\"]],[\"invoke\",936,0,\"lt\",[\"f64:4602678819172646912\",\"f64:0\"]],[\"invoke\",941,0,\"lt\",[\"f64:13826050856027422720\",\"f64:9227875636482146304\"]],[\"invoke\",945,0,\"lt\",[\"f64:13826050856027422720\",\"f64:13826050856027422720\"]],[\"invoke\",950,0,\"lt\",[\"f64:13826050856027422720\",\"f64:4607182418800017408\"]],[\"invoke\",955,0,\"lt\",[\"f64:4602678819172646912\",\"f64:13842132293034192152\"]],[\"invoke\",960,0,\"lt\",[\"f64:4602678819172646912\",\"f64:9218868437227405311\"]],[\"invoke\",965,0,\"lt\",[\"f64:13826050856027422720\",\"f64:18444492273895866368\"]],[\"invoke\",974,0,\"lt\",[\"f64:13830554455654793216\",\"f64:0\"]],[\"invoke\",979,0,\"lt\",[\"f64:4607182418800017408\",\"f64:9223372036854775809\"]],[\"invoke\",983,0,\"lt\",[\"f64:4607182418800017408\",\"f64:9227875636482146304\"]],[\"invoke\",988,0,\"lt\",[\"f64:4607182418800017408\",\"f64:4602678819172646912\"]],[\"invoke\",993,0,\"lt\",[\"f64:13830554455654793216\",\"f64:13842132293034192152\"]],[\"invoke\",998,0,\"lt\",[\"f64:13830554455654793216\",\"f64:9218868437227405311\"]],[\"invoke\",1003,0,\"lt\",[\"f64:4607182418800017408\",\"f64:18442240474082181120\"]],[\"invoke\",1011,0,\"lt\",[\"f64:4607182418800017408\",\"f64:9221120237041090560\"]],[\"invoke\",1017,0,\"lt\",[\"f64:13842132293034192152\",\"f64:9223372036854775809\"]],[\"invoke\",1021,0,\"lt\",[\"f64:13842132293034192152\",\"f64:9227875636482146304\"]],[\"invoke\",1026,0,\"lt\",[\"f64:13842132293034192152\",\"f64:4602678819172646912\"]],[\"invoke\",1031,0,\"lt\",[\"f64:4618760256179416344\",\"f64:13830554455654793216\"]],[\"invoke\",1036,0,\"lt\",[\"f64:4618760256179416344\",\"f64:4618760256179416344\"]],[\"invoke\",1041,0,\"lt\",[\"f64:13842132293034192152\",\"f64:18442240474082181120\"]],[\"invoke\",1047,0,\"lt\",[\"f64:13842132293034192152\",\"f64:9221120237041090560\"]],[\"invoke\",1055,0,\"lt\",[\"f64:9218868437227405311\",\"f64:9223372036854775808\"]],[\"invoke\",1059,0,\"lt\",[\"f64:9218868437227405311\",\"f64:9223372036854775809\"]],[\"invoke\",1064,0,\"lt\",[\"f64:9218868437227405311\",\"f64:4503599627370496\"]],[\"invoke\",1069,0,\"lt\",[\"f64:18442240474082181119\",\"f64:13830554455654793216\"]],[\"invoke\",1074,0,\"lt\",[\"f64:18442240474082181119\",\"f64:4618760256179416344\"]],[\"invoke\",1079,0,\"lt\",[\"f64:9218868437227405311\",\"f64:18442240474082181119\"]],[\"invoke\",1084,0,\"lt\",[\"f64:9218868437227405311\",\"f64:9218868437227405312\"]],[\"invoke\",1093,0,\"lt\",[\"f64:18442240474082181120\",\"f64:9223372036854775808\"]],[\"invoke\",1097,0,\"lt\",[\"f64:18442240474082181120\",\"f64:9223372036854775809\"]],[\"invoke\",1102,0,\"lt\",[\"f64:18442240474082181120\",\"f64:4503599627370496\"]],[\"invoke\",1107,0,\"lt\",[\"f64:9218868437227405312\",\"f64:13826050856027422720\"]],[\"invoke\",1112,0,\"lt\",[\"f64:9218868437227405312\",\"f64:4607182418800017408\"]],[\"invoke\",1117,0,\"lt\",[\"f64:18442240474082181120\",\"f64:18442240474082181119\"]],[\"invoke\",1122,0,\"lt\",[\"f64:18442240474082181120\",\"f64:9218868437227405312\"]],[\"invoke\",1129,0,\"lt\",[\"f64:9218868437227405312\",\"f64:18444492273895866368\"]],[\"invoke\",1137,0,\"lt\",[\"f64:9221120237041090560\",\"f64:9223372036854775808\"]],[\"invoke\",1147,0,\"lt\",[\"f64:9221120237041090560\",\"f64:1\"]],[\"invoke\",1157,0,\"lt\",[\"f64:18444492273895866368\",\"f64:13826050856027422720\"]],[\"invoke\",1167,0,\"lt\",[\"f64:18444492273895866368\",\"f64:4607182418800017408\"]],[\"invoke\",1177,0,\"lt\",[\"f64:9221120237041090560\",\"f64:13842132293034192152\"]],[\"invoke\",1187,0,\"lt\",[\"f64:9221120237041090560\",\"f64:9218868437227405311\"]],[\"invoke\",1197,0,\"lt\",[\"f64:18444492273895866368\",\"f64:18444492273895866368\"]],[\"invoke\",1214,0,\"le\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",1218,0,\"le\",[\"f64:9223372036854775808\",\"f64:1\"]],[\"invoke\",1223,0,\"le\",[\"f64:0\",\"f64:9227875636482146304\"]],[\"invoke\",1228,0,\"le\",[\"f64:0\",\"f64:4602678819172646912\"]],[\"invoke\",1233,0,\"le\",[\"f64:9223372036854775808\",\"f64:13842132293034192152\"]],[\"invoke\",1238,0,\"le\",[\"f64:9223372036854775808\",\"f64:9218868437227405311\"]],[\"invoke\",1243,0,\"le\",[\"f64:0\",\"f64:18442240474082181120\"]],[\"invoke\",1251,0,\"le\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",1256,0,\"le\",[\"f64:1\",\"f64:0\"]],[\"invoke\",1261,0,\"le\",[\"f64:9223372036854775809\",\"f64:9227875636482146304\"]],[\"invoke\",1266,0,\"le\",[\"f64:9223372036854775809\",\"f64:4602678819172646912\"]],[\"invoke\",1271,0,\"le\",[\"f64:1\",\"f64:13830554455654793216\"]],[\"invoke\",1276,0,\"le\",[\"f64:1\",\"f64:4618760256179416344\"]],[\"invoke\",1281,0,\"le\",[\"f64:9223372036854775809\",\"f64:18442240474082181120\"]],[\"invoke\",1287,0,\"le\",[\"f64:9223372036854775809\",\"f64:9221120237041090560\"]],[\"invoke\",1294,0,\"le\",[\"f64:9227875636482146304\",\"f64:0\"]],[\"invoke\",1299,0,\"le\",[\"f64:4503599627370496\",\"f64:9223372036854775809\"]],[\"invoke\",1304,0,\"le\",[\"f64:4503599627370496\",\"f64:4503599627370496\"]],[\"invoke\",1309,0,\"le\",[\"f64:9227875636482146304\",\"f64:13830554455654793216\"]],[\"invoke\",1314,0,\"le\",[\"f64:9227875636482146304\",\"f64:4618760256179416344\"]],[\"invoke\",1319,0,\"le\",[\"f64:4503599627370496\",\"f64:18442240474082181119\"]],[\"invoke\",1324,0,\"le\",[\"f64:4503599627370496\",\"f64:9218868437227405312\"]],[\"invoke\",1331,0,\"le\",[\"f64:4503599627370496\",\"f64:9221120237041090560\"]],[\"invoke\",1337,0,\"le\",[\"f64:13826050856027422720\",\"f64:9223372036854775809\"]],[\"invoke\",1342,0,\"le\",[\"f64:13826050856027422720\",\"f64:4503599627370496\"]],[\"invoke\",1347,0,\"le\",[\"f64:4602678819172646912\",\"f64:13826050856027422720\"]],[\"invoke\",1352,0,\"le\",[\"f64:4602678819172646912\",\"f64:4607182418800017408\"]],[\"invoke\",1357,0,\"le\",[\"f64:13826050856027422720\",\"f64:18442240474082181119\"]],[\"invoke\",1362,0,\"le\",[\"f64:13826050856027422720\",\"f64:9218868437227405312\"]],[\"invoke\",1367,0,\"le\",[\"f64:13826050856027422720\",\"f64:9221120237041090560\"]],[\"invoke\",1375,0,\"le\",[\"f64:4607182418800017408\",\"f64:9223372036854775808\"]],[\"invoke\",1380,0,\"le\",[\"f64:4607182418800017408\",\"f64:1\"]],[\"invoke\",1385,0,\"le\",[\"f64:13830554455654793216\",\"f64:13826050856027422720\"]],[\"invoke\",1390,0,\"le\",[\"f64:13830554455654793216\",\"f64:4607182418800017408\"]],[\"invoke\",1395,0,\"le\",[\"f64:4607182418800017408\",\"f64:13842132293034192152\"]],[\"invoke\",1400,0,\"le\",[\"f64:4607182418800017408\",\"f64:9218868437227405311\"]],[\"invoke\",1404,0,\"le\",[\"f64:4607182418800017408\",\"f64:9218868437227405312\"]],[\"invoke\",1413,0,\"le\",[\"f64:13842132293034192152\",\"f64:9223372036854775808\"]],[\"invoke\",1418,0,\"le\",[\"f64:13842132293034192152\",\"f64:1\"]],[\"invoke\",1423,0,\"le\",[\"f64:4618760256179416344\",\"f64:9227875636482146304\"]],[\"invoke\",1428,0,\"le\",[\"f64:4618760256179416344\",\"f64:4602678819172646912\"]],[\"invoke\",1433,0,\"le\",[\"f64:13842132293034192152\",\"f64:13842132293034192152\"]],[\"invoke\",1438,0,\"le\",[\"f64:13842132293034192152\",\"f64:9218868437227405311\"]],[\"invoke\",1442,0,\"le\",[\"f64:13842132293034192152\",\"f64:9218868437227405312\"]],[\"invoke\",1449,0,\"le\",[\"f64:4618760256179416344\",\"f64:18444492273895866368\"]],[\"invoke\",1456,0,\"le\",[\"f64:9218868437227405311\",\"f64:0\"]],[\"invoke\",1461,0,\"le\",[\"f64:18442240474082181119\",\"f64:9227875636482146304\"]],[\"invoke\",1466,0,\"le\",[\"f64:18442240474082181119\",\"f64:4602678819172646912\"]],[\"invoke\",1471,0,\"le\",[\"f64:9218868437227405311\",\"f64:13830554455654793216\"]],[\"invoke\",1476,0,\"le\",[\"f64:9218868437227405311\",\"f64:4618760256179416344\"]],[\"invoke\",1480,0,\"le\",[\"f64:9218868437227405311\",\"f64:9218868437227405311\"]],[\"invoke\",1485,0,\"le\",[\"f64:18442240474082181119\",\"f64:18444492273895866368\"]],[\"invoke\",1494,0,\"le\",[\"f64:18442240474082181120\",\"f64:0\"]],[\"invoke\",1499,0,\"le\",[\"f64:9218868437227405312\",\"f64:9223372036854775809\"]],[\"invoke\",1504,0,\"le\",[\"f64:9218868437227405312\",\"f64:4503599627370496\"]],[\"invoke\",1509,0,\"le\",[\"f64:18442240474082181120\",\"f64:13830554455654793216\"]],[\"invoke\",1514,0,\"le\",[\"f64:18442240474082181120\",\"f64:4618760256179416344\"]],[\"invoke\",1519,0,\"le\",[\"f64:9218868437227405312\",\"f64:18442240474082181119\"]],[\"invoke\",1523,0,\"le\",[\"f64:9218868437227405312\",\"f64:18442240474082181120\"]],[\"invoke\",1531,0,\"le\",[\"f64:9218868437227405312\",\"f64:9221120237041090560\"]],[\"invoke\",1541,0,\"le\",[\"f64:18444492273895866368\",\"f64:9223372036854775809\"]],[\"invoke\",1551,0,\"le\",[\"f64:18444492273895866368\",\"f64:4503599627370496\"]],[\"invoke\",1561,0,\"le\",[\"f64:9221120237041090560\",\"f64:13826050856027422720\"]],[\"invoke\",1571,0,\"le\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\"]],[\"invoke\",1581,0,\"le\",[\"f64:18444492273895866368\",\"f64:18442240474082181119\"]],[\"invoke\",1589,0,\"le\",[\"f64:18444492273895866368\",\"f64:18442240474082181120\"]],[\"invoke\",1601,0,\"le\",[\"f64:18444492273895866368\",\"f64:9221120237041090560\"]],[\"invoke\",1615,0,\"gt\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",1620,0,\"gt\",[\"f64:0\",\"f64:1\"]],[\"invoke\",1625,0,\"gt\",[\"f64:9223372036854775808\",\"f64:13826050856027422720\"]],[\"invoke\",1630,0,\"gt\",[\"f64:9223372036854775808\",\"f64:4607182418800017408\"]],[\"invoke\",1635,0,\"gt\",[\"f64:0\",\"f64:13842132293034192152\"]],[\"invoke\",1639,0,\"gt\",[\"f64:0\",\"f64:18442240474082181119\"]],[\"invoke\",1644,0,\"gt\",[\"f64:0\",\"f64:9218868437227405312\"]],[\"invoke\",1653,0,\"gt\",[\"f64:9223372036854775809\",\"f64:9223372036854775808\"]],[\"invoke\",1658,0,\"gt\",[\"f64:9223372036854775809\",\"f64:1\"]],[\"invoke\",1663,0,\"gt\",[\"f64:1\",\"f64:9227875636482146304\"]],[\"invoke\",1668,0,\"gt\",[\"f64:1\",\"f64:4602678819172646912\"]],[\"invoke\",1673,0,\"gt\",[\"f64:9223372036854775809\",\"f64:13842132293034192152\"]],[\"invoke\",1677,0,\"gt\",[\"f64:9223372036854775809\",\"f64:18442240474082181119\"]],[\"invoke\",1682,0,\"gt\",[\"f64:9223372036854775809\",\"f64:9218868437227405312\"]],[\"invoke\",1689,0,\"gt\",[\"f64:1\",\"f64:18444492273895866368\"]],[\"invoke\",1696,0,\"gt\",[\"f64:4503599627370496\",\"f64:0\"]],[\"invoke\",1701,0,\"gt\",[\"f64:9227875636482146304\",\"f64:9227875636482146304\"]],[\"invoke\",1706,0,\"gt\",[\"f64:9227875636482146304\",\"f64:4602678819172646912\"]],[\"invoke\",1711,0,\"gt\",[\"f64:4503599627370496\",\"f64:13830554455654793216\"]],[\"invoke\",1715,0,\"gt\",[\"f64:4503599627370496\",\"f64:13842132293034192152\"]],[\"invoke\",1720,0,\"gt\",[\"f64:4503599627370496\",\"f64:9218868437227405311\"]],[\"invoke\",1725,0,\"gt\",[\"f64:9227875636482146304\",\"f64:18444492273895866368\"]],[\"invoke\",1734,0,\"gt\",[\"f64:13826050856027422720\",\"f64:0\"]],[\"invoke\",1739,0,\"gt\",[\"f64:4602678819172646912\",\"f64:9223372036854775809\"]],[\"invoke\",1744,0,\"gt\",[\"f64:4602678819172646912\",\"f64:4503599627370496\"]],[\"invoke\",1749,0,\"gt\",[\"f64:13826050856027422720\",\"f64:13830554455654793216\"]],[\"invoke\",1753,0,\"gt\",[\"f64:13826050856027422720\",\"f64:13842132293034192152\"]],[\"invoke\",1758,0,\"gt\",[\"f64:13826050856027422720\",\"f64:9218868437227405311\"]],[\"invoke\",1763,0,\"gt\",[\"f64:4602678819172646912\",\"f64:18442240474082181120\"]],[\"invoke\",1771,0,\"gt\",[\"f64:4602678819172646912\",\"f64:9221120237041090560\"]],[\"invoke\",1777,0,\"gt\",[\"f64:13830554455654793216\",\"f64:9223372036854775809\"]],[\"invoke\",1782,0,\"gt\",[\"f64:13830554455654793216\",\"f64:4503599627370496\"]],[\"invoke\",1787,0,\"gt\",[\"f64:4607182418800017408\",\"f64:13826050856027422720\"]],[\"invoke\",1791,0,\"gt\",[\"f64:4607182418800017408\",\"f64:13830554455654793216\"]],[\"invoke\",1796,0,\"gt\",[\"f64:4607182418800017408\",\"f64:4618760256179416344\"]],[\"invoke\",1801,0,\"gt\",[\"f64:13830554455654793216\",\"f64:18442240474082181120\"]],[\"invoke\",1807,0,\"gt\",[\"f64:13830554455654793216\",\"f64:9221120237041090560\"]],[\"invoke\",1815,0,\"gt\",[\"f64:4618760256179416344\",\"f64:9223372036854775808\"]],[\"invoke\",1820,0,\"gt\",[\"f64:4618760256179416344\",\"f64:1\"]],[\"invoke\",1825,0,\"gt\",[\"f64:13842132293034192152\",\"f64:13826050856027422720\"]],[\"invoke\",1830,0,\"gt\",[\"f64:13842132293034192152\",\"f64:4607182418800017408\"]],[\"invoke\",1834,0,\"gt\",[\"f64:13842132293034192152\",\"f64:4618760256179416344\"]],[\"invoke\",1839,0,\"gt\",[\"f64:4618760256179416344\",\"f64:18442240474082181119\"]],[\"invoke\",1844,0,\"gt\",[\"f64:4618760256179416344\",\"f64:9218868437227405312\"]],[\"invoke\",1853,0,\"gt\",[\"f64:18442240474082181119\",\"f64:9223372036854775808\"]],[\"invoke\",1858,0,\"gt\",[\"f64:18442240474082181119\",\"f64:1\"]],[\"invoke\",1863,0,\"gt\",[\"f64:9218868437227405311\",\"f64:9227875636482146304\"]],[\"invoke\",1868,0,\"gt\",[\"f64:9218868437227405311\",\"f64:4602678819172646912\"]],[\"invoke\",1872,0,\"gt\",[\"f64:9218868437227405311\",\"f64:4607182418800017408\"]],[\"invoke\",1877,0,\"gt\",[\"f64:18442240474082181119\",\"f64:18442240474082181119\"]],[\"invoke\",1882,0,\"gt\",[\"f64:18442240474082181119\",\"f64:9218868437227405312\"]],[\"invoke\",1889,0,\"gt\",[\"f64:9218868437227405311\",\"f64:18444492273895866368\"]],[\"invoke\",1896,0,\"gt\",[\"f64:9218868437227405312\",\"f64:0\"]],[\"invoke\",1901,0,\"gt\",[\"f64:18442240474082181120\",\"f64:9227875636482146304\"]],[\"invoke\",1906,0,\"gt\",[\"f64:18442240474082181120\",\"f64:4602678819172646912\"]],[\"invoke\",1910,0,\"gt\",[\"f64:18442240474082181120\",\"f64:4607182418800017408\"]],[\"invoke\",1915,0,\"gt\",[\"f64:9218868437227405312\",\"f64:13842132293034192152\"]],[\"invoke\",1920,0,\"gt\",[\"f64:9218868437227405312\",\"f64:9218868437227405311\"]],[\"invoke\",1925,0,\"gt\",[\"f64:18442240474082181120\",\"f64:18444492273895866368\"]],[\"invoke\",1935,0,\"gt\",[\"f64:18444492273895866368\",\"f64:0\"]],[\"invoke\",1945,0,\"gt\",[\"f64:9221120237041090560\",\"f64:9223372036854775809\"]],[\"invoke\",1955,0,\"gt\",[\"f64:9221120237041090560\",\"f64:4503599627370496\"]],[\"invoke\",1963,0,\"gt\",[\"f64:9221120237041090560\",\"f64:4602678819172646912\"]],[\"invoke\",1973,0,\"gt\",[\"f64:18444492273895866368\",\"f64:13842132293034192152\"]],[\"invoke\",1983,0,\"gt\",[\"f64:18444492273895866368\",\"f64:9218868437227405311\"]],[\"invoke\",1993,0,\"gt\",[\"f64:9221120237041090560\",\"f64:18442240474082181120\"]],[\"invoke\",2009,0,\"gt\",[\"f64:9221120237041090560\",\"f64:9221120237041090560\"]],[\"invoke\",2017,0,\"ge\",[\"f64:9223372036854775808\",\"f64:9223372036854775809\"]],[\"invoke\",2022,0,\"ge\",[\"f64:9223372036854775808\",\"f64:4503599627370496\"]],[\"invoke\",2026,0,\"ge\",[\"f64:9223372036854775808\",\"f64:4602678819172646912\"]],[\"invoke\",2031,0,\"ge\",[\"f64:0\",\"f64:13830554455654793216\"]],[\"invoke\",2036,0,\"ge\",[\"f64:0\",\"f64:4618760256179416344\"]],[\"invoke\",2041,0,\"ge\",[\"f64:9223372036854775808\",\"f64:18442240474082181120\"]],[\"invoke\",2047,0,\"ge\",[\"f64:9223372036854775808\",\"f64:9221120237041090560\"]],[\"invoke\",2055,0,\"ge\",[\"f64:1\",\"f64:9223372036854775808\"]],[\"invoke\",2060,0,\"ge\",[\"f64:1\",\"f64:1\"]],[\"invoke\",2064,0,\"ge\",[\"f64:1\",\"f64:4503599627370496\"]],[\"invoke\",2069,0,\"ge\",[\"f64:9223372036854775809\",\"f64:13830554455654793216\"]],[\"invoke\",2074,0,\"ge\",[\"f64:9223372036854775809\",\"f64:4618760256179416344\"]],[\"invoke\",2079,0,\"ge\",[\"f64:1\",\"f64:18442240474082181119\"]],[\"invoke\",2084,0,\"ge\",[\"f64:1\",\"f64:9218868437227405312\"]],[\"invoke\",2093,0,\"ge\",[\"f64:9227875636482146304\",\"f64:9223372036854775808\"]],[\"invoke\",2098,0,\"ge\",[\"f64:9227875636482146304\",\"f64:1\"]],[\"invoke\",2102,0,\"ge\",[\"f64:9227875636482146304\",\"f64:4503599627370496\"]],[\"invoke\",2107,0,\"ge\",[\"f64:4503599627370496\",\"f64:13826050856027422720\"]],[\"invoke\",2112,0,\"ge\",[\"f64:4503599627370496\",\"f64:4607182418800017408\"]],[\"invoke\",2117,0,\"ge\",[\"f64:9227875636482146304\",\"f64:18442240474082181119\"]],[\"invoke\",2122,0,\"ge\",[\"f64:9227875636482146304\",\"f64:9218868437227405312\"]],[\"invoke\",2129,0,\"ge\",[\"f64:4503599627370496\",\"f64:18444492273895866368\"]],[\"invoke\",2136,0,\"ge\",[\"f64:4602678819172646912\",\"f64:0\"]],[\"invoke\",2141,0,\"ge\",[\"f64:13826050856027422720\",\"f64:9227875636482146304\"]],[\"invoke\",2145,0,\"ge\",[\"f64:13826050856027422720\",\"f64:13826050856027422720\"]],[\"invoke\",2150,0,\"ge\",[\"f64:13826050856027422720\",\"f64:4607182418800017408\"]],[\"invoke\",2155,0,\"ge\",[\"f64:4602678819172646912\",\"f64:13842132293034192152\"]],[\"invoke\",2160,0,\"ge\",[\"f64:4602678819172646912\",\"f64:9218868437227405311\"]],[\"invoke\",2165,0,\"ge\",[\"f64:13826050856027422720\",\"f64:18444492273895866368\"]],[\"invoke\",2174,0,\"ge\",[\"f64:13830554455654793216\",\"f64:0\"]],[\"invoke\",2179,0,\"ge\",[\"f64:4607182418800017408\",\"f64:9223372036854775809\"]],[\"invoke\",2183,0,\"ge\",[\"f64:4607182418800017408\",\"f64:9227875636482146304\"]],[\"invoke\",2188,0,\"ge\",[\"f64:4607182418800017408\",\"f64:4602678819172646912\"]],[\"invoke\",2193,0,\"ge\",[\"f64:13830554455654793216\",\"f64:13842132293034192152\"]],[\"invoke\",2198,0,\"ge\",[\"f64:13830554455654793216\",\"f64:9218868437227405311\"]],[\"invoke\",2203,0,\"ge\",[\"f64:4607182418800017408\",\"f64:18442240474082181120\"]],[\"invoke\",2211,0,\"ge\",[\"f64:4607182418800017408\",\"f64:9221120237041090560\"]],[\"invoke\",2217,0,\"ge\",[\"f64:13842132293034192152\",\"f64:9223372036854775809\"]],[\"invoke\",2221,0,\"ge\",[\"f64:13842132293034192152\",\"f64:9227875636482146304\"]],[\"invoke\",2226,0,\"ge\",[\"f64:13842132293034192152\",\"f64:4602678819172646912\"]],[\"invoke\",2231,0,\"ge\",[\"f64:4618760256179416344\",\"f64:13830554455654793216\"]],[\"invoke\",2236,0,\"ge\",[\"f64:4618760256179416344\",\"f64:4618760256179416344\"]],[\"invoke\",2241,0,\"ge\",[\"f64:13842132293034192152\",\"f64:18442240474082181120\"]],[\"invoke\",2247,0,\"ge\",[\"f64:13842132293034192152\",\"f64:9221120237041090560\"]],[\"invoke\",2255,0,\"ge\",[\"f64:9218868437227405311\",\"f64:9223372036854775808\"]],[\"invoke\",2259,0,\"ge\",[\"f64:9218868437227405311\",\"f64:9223372036854775809\"]],[\"invoke\",2264,0,\"ge\",[\"f64:9218868437227405311\",\"f64:4503599627370496\"]],[\"invoke\",2269,0,\"ge\",[\"f64:18442240474082181119\",\"f64:13830554455654793216\"]],[\"invoke\",2274,0,\"ge\",[\"f64:18442240474082181119\",\"f64:4618760256179416344\"]],[\"invoke\",2279,0,\"ge\",[\"f64:9218868437227405311\",\"f64:18442240474082181119\"]],[\"invoke\",2284,0,\"ge\",[\"f64:9218868437227405311\",\"f64:9218868437227405312\"]],[\"invoke\",2293,0,\"ge\",[\"f64:18442240474082181120\",\"f64:9223372036854775808\"]],[\"invoke\",2297,0,\"ge\",[\"f64:18442240474082181120\",\"f64:9223372036854775809\"]],[\"invoke\",2302,0,\"ge\",[\"f64:18442240474082181120\",\"f64:4503599627370496\"]],[\"invoke\",2307,0,\"ge\",[\"f64:9218868437227405312\",\"f64:13826050856027422720\"]],[\"invoke\",2312,0,\"ge\",[\"f64:9218868437227405312\",\"f64:4607182418800017408\"]],[\"invoke\",2317,0,\"ge\",[\"f64:18442240474082181120\",\"f64:18442240474082181119\"]],[\"invoke\",2322,0,\"ge\",[\"f64:18442240474082181120\",\"f64:9218868437227405312\"]],[\"invoke\",2329,0,\"ge\",[\"f64:9218868437227405312\",\"f64:18444492273895866368\"]],[\"invoke\",2337,0,\"ge\",[\"f64:9221120237041090560\",\"f64:9223372036854775808\"]],[\"invoke\",2347,0,\"ge\",[\"f64:9221120237041090560\",\"f64:1\"]],[\"invoke\",2357,0,\"ge\",[\"f64:18444492273895866368\",\"f64:13826050856027422720\"]],[\"invoke\",2367,0,\"ge\",[\"f64:18444492273895866368\",\"f64:4607182418800017408\"]],[\"invoke\",2377,0,\"ge\",[\"f64:9221120237041090560\",\"f64:13842132293034192152\"]],[\"invoke\",2387,0,\"ge\",[\"f64:9221120237041090560\",\"f64:9218868437227405311\"]],[\"invoke\",2397,0,\"ge\",[\"f64:18444492273895866368\",\"f64:18444492273895866368\"]],[\"file\",\"f32_bitwise.wast\"],[\"module\",4,4],[\"invoke\",10,0,\"copysign\",[\"f32:2147483648\",\"f32:2147483648\"]],[\"invoke\",11,0,\"copysign\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",12,0,\"copysign\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",13,0,\"copysign\",[\"f32:0\",\"f32:0\"]],[\"invoke\",14,0,\"copysign\",[\"f32:2147483648\",\"f32:2147483649\"]],[\"invoke\",15,0,\"copysign\",[\"f32:2147483648\",\"f32:1\"]],[\"invoke\",16,0,\"copysign\",[\"f32:0\",\"f32:2147483649\"]],[\"invoke\",17,0,\"copysign\",[\"f32:0\",\"f32:1\"]],[\"invoke\",18,0,\"copysign\",[\"f32:2147483648\",\"f32:2155872256\"]],[\"invoke\",19,0,\"copysign\",[\"f32:2147483648\",\"f32:8388608\"]],[\"invoke\",20,0,\"copysign\",[\"f32:0\",\"f32:2155872256\"]],[\"invoke\",21,0,\"copysign\",[\"f32:0\",\"f32:8388608\"]],[\"invoke\",22,0,\"copysign\",[\"f32:2147483648\",\"f32:3204448256\"]],[\"invoke\",23,0,\"copysign\",[\"f32:2147483648\",\"f32:1056964608\"]],[\"invoke\",24,0,\"copysign\",[\"f32:0\",\"f32:3204448256\"]],[\"invoke\",25,0,\"copysign\",[\"f32:0\",\"f32:1056964608\"]],[\"invoke\",26,0,\"copysign\",[\"f32:2147483648\",\"f32:3212836864\"]],[\"invoke\",27,0,\"copysign\",[\"f32:2147483648\",\"f32:1065353216\"]],[\"invoke\",28,0,\"copysign\",[\"f32:0\",\"f32:3212836864\"]],[\"invoke\",29,0,\"copysign\",[\"f32:0\",\"f32:1065353216\"]],[\"invoke\",30,0,\"copysign\",[\"f32:2147483648\",\"f32:3234402267\"]],[\"invoke\",31,0,\"copysign\",[\"f32:2147483648\",\"f32:1086918619\"]],[\"invoke\",32,0,\"copysign\",[\"f32:0\",\"f32:3234402267\"]],[\"invoke\",33,0,\"copysign\",[\"f32:0\",\"f32:1086918619\"]],[\"invoke\",34,0,\"copysign\",[\"f32:2147483648\",\"f32:4286578687\"]],[\"invoke\",35,0,\"copysign\",[\"f32:2147483648\",\"f32:2139095039\"]],[\"invoke\",36,0,\"copysign\",[\"f32:0\",\"f32:4286578687\"]],[\"invoke\",37,0,\"copysign\",[\"f32:0\",\"f32:2139095039\"]],[\"invoke\",38,0,\"copysign\",[\"f32:2147483648\",\"f32:4286578688\"]],[\"invoke\",39,0,\"copysign\",[\"f32:2147483648\",\"f32:2139095040\"]],[\"invoke\",40,0,\"copysign\",[\"f32:0\",\"f32:4286578688\"]],[\"invoke\",41,0,\"copysign\",[\"f32:0\",\"f32:2139095040\"]],[\"invoke\",42,0,\"copysign\",[\"f32:2147483648\",\"f32:4290772992\"]],[\"invoke\",43,0,\"copysign\",[\"f32:2147483648\",\"f32:2143289344\"]],[\"invoke\",44,0,\"copysign\",[\"f32:0\",\"f32:4290772992\"]],[\"invoke\",45,0,\"copysign\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",46,0,\"copysign\",[\"f32:2147483649\",\"f32:2147483648\"]],[\"invoke\",47,0,\"copysign\",[\"f32:2147483649\",\"f32:0\"]],[\"invoke\",48,0,\"copysign\",[\"f32:1\",\"f32:2147483648\"]],[\"invoke\",49,0,\"copysign\",[\"f32:1\",\"f32:0\"]],[\"invoke\",50,0,\"copysign\",[\"f32:2147483649\",\"f32:2147483649\"]],[\"invoke\",51,0,\"copysign\",[\"f32:2147483649\",\"f32:1\"]],[\"invoke\",52,0,\"copysign\",[\"f32:1\",\"f32:2147483649\"]],[\"invoke\",53,0,\"copysign\",[\"f32:1\",\"f32:1\"]],[\"invoke\",54,0,\"copysign\",[\"f32:2147483649\",\"f32:2155872256\"]],[\"invoke\",55,0,\"copysign\",[\"f32:2147483649\",\"f32:8388608\"]],[\"invoke\",56,0,\"copysign\",[\"f32:1\",\"f32:2155872256\"]],[\"invoke\",57,0,\"copysign\",[\"f32:1\",\"f32:8388608\"]],[\"invoke\",58,0,\"copysign\",[\"f32:2147483649\",\"f32:3204448256\"]],[\"invoke\",59,0,\"copysign\",[\"f32:2147483649\",\"f32:1056964608\"]],[\"invoke\",60,0,\"copysign\",[\"f32:1\",\"f32:3204448256\"]],[\"invoke\",61,0,\"copysign\",[\"f32:1\",\"f32:1056964608\"]],[\"invoke\",62,0,\"copysign\",[\"f32:2147483649\",\"f32:3212836864\"]],[\"invoke\",63,0,\"copysign\",[\"f32:2147483649\",\"f32:1065353216\"]],[\"invoke\",64,0,\"copysign\",[\"f32:1\",\"f32:3212836864\"]],[\"invoke\",65,0,\"copysign\",[\"f32:1\",\"f32:1065353216\"]],[\"invoke\",66,0,\"copysign\",[\"f32:2147483649\",\"f32:3234402267\"]],[\"invoke\",67,0,\"copysign\",[\"f32:2147483649\",\"f32:1086918619\"]],[\"invoke\",68,0,\"copysign\",[\"f32:1\",\"f32:3234402267\"]],[\"invoke\",69,0,\"copysign\",[\"f32:1\",\"f32:1086918619\"]],[\"invoke\",70,0,\"copysign\",[\"f32:2147483649\",\"f32:4286578687\"]],[\"invoke\",71,0,\"copysign\",[\"f32:2147483649\",\"f32:2139095039\"]],[\"invoke\",72,0,\"copysign\",[\"f32:1\",\"f32:4286578687\"]],[\"invoke\",73,0,\"copysign\",[\"f32:1\",\"f32:2139095039\"]],[\"invoke\",74,0,\"copysign\",[\"f32:2147483649\",\"f32:4286578688\"]],[\"invoke\",75,0,\"copysign\",[\"f32:2147483649\",\"f32:2139095040\"]],[\"invoke\",76,0,\"copysign\",[\"f32:1\",\"f32:4286578688\"]],[\"invoke\",77,0,\"copysign\",[\"f32:1\",\"f32:2139095040\"]],[\"invoke\",78,0,\"copysign\",[\"f32:2147483649\",\"f32:4290772992\"]],[\"invoke\",79,0,\"copysign\",[\"f32:2147483649\",\"f32:2143289344\"]],[\"invoke\",80,0,\"copysign\",[\"f32:1\",\"f32:4290772992\"]],[\"invoke\",81,0,\"copysign\",[\"f32:1\",\"f32:2143289344\"]],[\"invoke\",82,0,\"copysign\",[\"f32:2155872256\",\"f32:2147483648\"]],[\"invoke\",83,0,\"copysign\",[\"f32:2155872256\",\"f32:0\"]],[\"invoke\",84,0,\"copysign\",[\"f32:8388608\",\"f32:2147483648\"]],[\"invoke\",85,0,\"copysign\",[\"f32:8388608\",\"f32:0\"]],[\"invoke\",86,0,\"copysign\",[\"f32:2155872256\",\"f32:2147483649\"]],[\"invoke\",87,0,\"copysign\",[\"f32:2155872256\",\"f32:1\"]],[\"invoke\",88,0,\"copysign\",[\"f32:8388608\",\"f32:2147483649\"]],[\"invoke\",89,0,\"copysign\",[\"f32:8388608\",\"f32:1\"]],[\"invoke\",90,0,\"copysign\",[\"f32:2155872256\",\"f32:2155872256\"]],[\"invoke\",91,0,\"copysign\",[\"f32:2155872256\",\"f32:8388608\"]],[\"invoke\",92,0,\"copysign\",[\"f32:8388608\",\"f32:2155872256\"]],[\"invoke\",93,0,\"copysign\",[\"f32:8388608\",\"f32:8388608\"]],[\"invoke\",94,0,\"copysign\",[\"f32:2155872256\",\"f32:3204448256\"]],[\"invoke\",95,0,\"copysign\",[\"f32:2155872256\",\"f32:1056964608\"]],[\"invoke\",96,0,\"copysign\",[\"f32:8388608\",\"f32:3204448256\"]],[\"invoke\",97,0,\"copysign\",[\"f32:8388608\",\"f32:1056964608\"]],[\"invoke\",98,0,\"copysign\",[\"f32:2155872256\",\"f32:3212836864\"]],[\"invoke\",99,0,\"copysign\",[\"f32:2155872256\",\"f32:1065353216\"]],[\"invoke\",100,0,\"copysign\",[\"f32:8388608\",\"f32:3212836864\"]],[\"invoke\",101,0,\"copysign\",[\"f32:8388608\",\"f32:1065353216\"]],[\"invoke\",102,0,\"copysign\",[\"f32:2155872256\",\"f32:3234402267\"]],[\"invoke\",103,0,\"copysign\",[\"f32:2155872256\",\"f32:1086918619\"]],[\"invoke\",104,0,\"copysign\",[\"f32:8388608\",\"f32:3234402267\"]],[\"invoke\",105,0,\"copysign\",[\"f32:8388608\",\"f32:1086918619\"]],[\"invoke\",106,0,\"copysign\",[\"f32:2155872256\",\"f32:4286578687\"]],[\"invoke\",107,0,\"copysign\",[\"f32:2155872256\",\"f32:2139095039\"]],[\"invoke\",108,0,\"copysign\",[\"f32:8388608\",\"f32:4286578687\"]],[\"invoke\",109,0,\"copysign\",[\"f32:8388608\",\"f32:2139095039\"]],[\"invoke\",110,0,\"copysign\",[\"f32:2155872256\",\"f32:4286578688\"]],[\"invoke\",111,0,\"copysign\",[\"f32:2155872256\",\"f32:2139095040\"]],[\"invoke\",112,0,\"copysign\",[\"f32:8388608\",\"f32:4286578688\"]],[\"invoke\",113,0,\"copysign\",[\"f32:8388608\",\"f32:2139095040\"]],[\"invoke\",114,0,\"copysign\",[\"f32:2155872256\",\"f32:4290772992\"]],[\"invoke\",115,0,\"copysign\",[\"f32:2155872256\",\"f32:2143289344\"]],[\"invoke\",116,0,\"copysign\",[\"f32:8388608\",\"f32:4290772992\"]],[\"invoke\",117,0,\"copysign\",[\"f32:8388608\",\"f32:2143289344\"]],[\"invoke\",118,0,\"copysign\",[\"f32:3204448256\",\"f32:2147483648\"]],[\"invoke\",119,0,\"copysign\",[\"f32:3204448256\",\"f32:0\"]],[\"invoke\",120,0,\"copysign\",[\"f32:1056964608\",\"f32:2147483648\"]],[\"invoke\",121,0,\"copysign\",[\"f32:1056964608\",\"f32:0\"]],[\"invoke\",122,0,\"copysign\",[\"f32:3204448256\",\"f32:2147483649\"]],[\"invoke\",123,0,\"copysign\",[\"f32:3204448256\",\"f32:1\"]],[\"invoke\",124,0,\"copysign\",[\"f32:1056964608\",\"f32:2147483649\"]],[\"invoke\",125,0,\"copysign\",[\"f32:1056964608\",\"f32:1\"]],[\"invoke\",126,0,\"copysign\",[\"f32:3204448256\",\"f32:2155872256\"]],[\"invoke\",127,0,\"copysign\",[\"f32:3204448256\",\"f32:8388608\"]],[\"invoke\",128,0,\"copysign\",[\"f32:1056964608\",\"f32:2155872256\"]],[\"invoke\",129,0,\"copysign\",[\"f32:1056964608\",\"f32:8388608\"]],[\"invoke\",130,0,\"copysign\",[\"f32:3204448256\",\"f32:3204448256\"]],[\"invoke\",131,0,\"copysign\",[\"f32:3204448256\",\"f32:1056964608\"]],[\"invoke\",132,0,\"copysign\",[\"f32:1056964608\",\"f32:3204448256\"]],[\"invoke\",133,0,\"copysign\",[\"f32:1056964608\",\"f32:1056964608\"]],[\"invoke\",134,0,\"copysign\",[\"f32:3204448256\",\"f32:3212836864\"]],[\"invoke\",135,0,\"copysign\",[\"f32:3204448256\",\"f32:1065353216\"]],[\"invoke\",136,0,\"copysign\",[\"f32:1056964608\",\"f32:3212836864\"]],[\"invoke\",137,0,\"copysign\",[\"f32:1056964608\",\"f32:1065353216\"]],[\"invoke\",138,0,\"copysign\",[\"f32:3204448256\",\"f32:3234402267\"]],[\"invoke\",139,0,\"copysign\",[\"f32:3204448256\",\"f32:1086918619\"]],[\"invoke\",140,0,\"copysign\",[\"f32:1056964608\",\"f32:3234402267\"]],[\"invoke\",141,0,\"copysign\",[\"f32:1056964608\",\"f32:1086918619\"]],[\"invoke\",142,0,\"copysign\",[\"f32:3204448256\",\"f32:4286578687\"]],[\"invoke\",143,0,\"copysign\",[\"f32:3204448256\",\"f32:2139095039\"]],[\"invoke\",144,0,\"copysign\",[\"f32:1056964608\",\"f32:4286578687\"]],[\"invoke\",145,0,\"copysign\",[\"f32:1056964608\",\"f32:2139095039\"]],[\"invoke\",146,0,\"copysign\",[\"f32:3204448256\",\"f32:4286578688\"]],[\"invoke\",147,0,\"copysign\",[\"f32:3204448256\",\"f32:2139095040\"]],[\"invoke\",148,0,\"copysign\",[\"f32:1056964608\",\"f32:4286578688\"]],[\"invoke\",149,0,\"copysign\",[\"f32:1056964608\",\"f32:2139095040\"]],[\"invoke\",150,0,\"copysign\",[\"f32:3204448256\",\"f32:4290772992\"]],[\"invoke\",151,0,\"copysign\",[\"f32:3204448256\",\"f32:2143289344\"]],[\"invoke\",152,0,\"copysign\",[\"f32:1056964608\",\"f32:4290772992\"]],[\"invoke\",153,0,\"copysign\",[\"f32:1056964608\",\"f32:2143289344\"]],[\"invoke\",154,0,\"copysign\",[\"f32:3212836864\",\"f32:2147483648\"]],[\"invoke\",155,0,\"copysign\",[\"f32:3212836864\",\"f32:0\"]],[\"invoke\",156,0,\"copysign\",[\"f32:1065353216\",\"f32:2147483648\"]],[\"invoke\",157,0,\"copysign\",[\"f32:1065353216\",\"f32:0\"]],[\"invoke\",158,0,\"copysign\",[\"f32:3212836864\",\"f32:2147483649\"]],[\"invoke\",159,0,\"copysign\",[\"f32:3212836864\",\"f32:1\"]],[\"invoke\",160,0,\"copysign\",[\"f32:1065353216\",\"f32:2147483649\"]],[\"invoke\",161,0,\"copysign\",[\"f32:1065353216\",\"f32:1\"]],[\"invoke\",162,0,\"copysign\",[\"f32:3212836864\",\"f32:2155872256\"]],[\"invoke\",163,0,\"copysign\",[\"f32:3212836864\",\"f32:8388608\"]],[\"invoke\",164,0,\"copysign\",[\"f32:1065353216\",\"f32:2155872256\"]],[\"invoke\",165,0,\"copysign\",[\"f32:1065353216\",\"f32:8388608\"]],[\"invoke\",166,0,\"copysign\",[\"f32:3212836864\",\"f32:3204448256\"]],[\"invoke\",167,0,\"copysign\",[\"f32:3212836864\",\"f32:1056964608\"]],[\"invoke\",168,0,\"copysign\",[\"f32:1065353216\",\"f32:3204448256\"]],[\"invoke\",169,0,\"copysign\",[\"f32:1065353216\",\"f32:1056964608\"]],[\"invoke\",170,0,\"copysign\",[\"f32:3212836864\",\"f32:3212836864\"]],[\"invoke\",171,0,\"copysign\",[\"f32:3212836864\",\"f32:1065353216\"]],[\"invoke\",172,0,\"copysign\",[\"f32:1065353216\",\"f32:3212836864\"]],[\"invoke\",173,0,\"copysign\",[\"f32:1065353216\",\"f32:1065353216\"]],[\"invoke\",174,0,\"copysign\",[\"f32:3212836864\",\"f32:3234402267\"]],[\"invoke\",175,0,\"copysign\",[\"f32:3212836864\",\"f32:1086918619\"]],[\"invoke\",176,0,\"copysign\",[\"f32:1065353216\",\"f32:3234402267\"]],[\"invoke\",177,0,\"copysign\",[\"f32:1065353216\",\"f32:1086918619\"]],[\"invoke\",178,0,\"copysign\",[\"f32:3212836864\",\"f32:4286578687\"]],[\"invoke\",179,0,\"copysign\",[\"f32:3212836864\",\"f32:2139095039\"]],[\"invoke\",180,0,\"copysign\",[\"f32:1065353216\",\"f32:4286578687\"]],[\"invoke\",181,0,\"copysign\",[\"f32:1065353216\",\"f32:2139095039\"]],[\"invoke\",182,0,\"copysign\",[\"f32:3212836864\",\"f32:4286578688\"]],[\"invoke\",183,0,\"copysign\",[\"f32:3212836864\",\"f32:2139095040\"]],[\"invoke\",184,0,\"copysign\",[\"f32:1065353216\",\"f32:4286578688\"]],[\"invoke\",185,0,\"copysign\",[\"f32:1065353216\",\"f32:2139095040\"]],[\"invoke\",186,0,\"copysign\",[\"f32:3212836864\",\"f32:4290772992\"]],[\"invoke\",187,0,\"copysign\",[\"f32:3212836864\",\"f32:2143289344\"]],[\"invoke\",188,0,\"copysign\",[\"f32:1065353216\",\"f32:4290772992\"]],[\"invoke\",189,0,\"copysign\",[\"f32:1065353216\",\"f32:2143289344\"]],[\"invoke\",190,0,\"copysign\",[\"f32:3234402267\",\"f32:2147483648\"]],[\"invoke\",191,0,\"copysign\",[\"f32:3234402267\",\"f32:0\"]],[\"invoke\",192,0,\"copysign\",[\"f32:1086918619\",\"f32:2147483648\"]],[\"invoke\",193,0,\"copysign\",[\"f32:1086918619\",\"f32:0\"]],[\"invoke\",194,0,\"copysign\",[\"f32:3234402267\",\"f32:2147483649\"]],[\"invoke\",195,0,\"copysign\",[\"f32:3234402267\",\"f32:1\"]],[\"invoke\",196,0,\"copysign\",[\"f32:1086918619\",\"f32:2147483649\"]],[\"invoke\",197,0,\"copysign\",[\"f32:1086918619\",\"f32:1\"]],[\"invoke\",198,0,\"copysign\",[\"f32:3234402267\",\"f32:2155872256\"]],[\"invoke\",199,0,\"copysign\",[\"f32:3234402267\",\"f32:8388608\"]],[\"invoke\",200,0,\"copysign\",[\"f32:1086918619\",\"f32:2155872256\"]],[\"invoke\",201,0,\"copysign\",[\"f32:1086918619\",\"f32:8388608\"]],[\"invoke\",202,0,\"copysign\",[\"f32:3234402267\",\"f32:3204448256\"]],[\"invoke\",203,0,\"copysign\",[\"f32:3234402267\",\"f32:1056964608\"]],[\"invoke\",204,0,\"copysign\",[\"f32:1086918619\",\"f32:3204448256\"]],[\"invoke\",205,0,\"copysign\",[\"f32:1086918619\",\"f32:1056964608\"]],[\"invoke\",206,0,\"copysign\",[\"f32:3234402267\",\"f32:3212836864\"]],[\"invoke\",207,0,\"copysign\",[\"f32:3234402267\",\"f32:1065353216\"]],[\"invoke\",208,0,\"copysign\",[\"f32:1086918619\",\"f32:3212836864\"]],[\"invoke\",209,0,\"copysign\",[\"f32:1086918619\",\"f32:1065353216\"]],[\"invoke\",210,0,\"copysign\",[\"f32:3234402267\",\"f32:3234402267\"]],[\"invoke\",211,0,\"copysign\",[\"f32:3234402267\",\"f32:1086918619\"]],[\"invoke\",212,0,\"copysign\",[\"f32:1086918619\",\"f32:3234402267\"]],[\"invoke\",213,0,\"copysign\",[\"f32:1086918619\",\"f32:1086918619\"]],[\"invoke\",214,0,\"copysign\",[\"f32:3234402267\",\"f32:4286578687\"]],[\"invoke\",215,0,\"copysign\",[\"f32:3234402267\",\"f32:2139095039\"]],[\"invoke\",216,0,\"copysign\",[\"f32:1086918619\",\"f32:4286578687\"]],[\"invoke\",217,0,\"copysign\",[\"f32:1086918619\",\"f32:2139095039\"]],[\"invoke\",218,0,\"copysign\",[\"f32:3234402267\",\"f32:4286578688\"]],[\"invoke\",219,0,\"copysign\",[\"f32:3234402267\",\"f32:2139095040\"]],[\"invoke\",220,0,\"copysign\",[\"f32:1086918619\",\"f32:4286578688\"]],[\"invoke\",221,0,\"copysign\",[\"f32:1086918619\",\"f32:2139095040\"]],[\"invoke\",222,0,\"copysign\",[\"f32:3234402267\",\"f32:4290772992\"]],[\"invoke\",223,0,\"copysign\",[\"f32:3234402267\",\"f32:2143289344\"]],[\"invoke\",224,0,\"copysign\",[\"f32:1086918619\",\"f32:4290772992\"]],[\"invoke\",225,0,\"copysign\",[\"f32:1086918619\",\"f32:2143289344\"]],[\"invoke\",226,0,\"copysign\",[\"f32:4286578687\",\"f32:2147483648\"]],[\"invoke\",227,0,\"copysign\",[\"f32:4286578687\",\"f32:0\"]],[\"invoke\",228,0,\"copysign\",[\"f32:2139095039\",\"f32:2147483648\"]],[\"invoke\",229,0,\"copysign\",[\"f32:2139095039\",\"f32:0\"]],[\"invoke\",230,0,\"copysign\",[\"f32:4286578687\",\"f32:2147483649\"]],[\"invoke\",231,0,\"copysign\",[\"f32:4286578687\",\"f32:1\"]],[\"invoke\",232,0,\"copysign\",[\"f32:2139095039\",\"f32:2147483649\"]],[\"invoke\",233,0,\"copysign\",[\"f32:2139095039\",\"f32:1\"]],[\"invoke\",234,0,\"copysign\",[\"f32:4286578687\",\"f32:2155872256\"]],[\"invoke\",235,0,\"copysign\",[\"f32:4286578687\",\"f32:8388608\"]],[\"invoke\",236,0,\"copysign\",[\"f32:2139095039\",\"f32:2155872256\"]],[\"invoke\",237,0,\"copysign\",[\"f32:2139095039\",\"f32:8388608\"]],[\"invoke\",238,0,\"copysign\",[\"f32:4286578687\",\"f32:3204448256\"]],[\"invoke\",239,0,\"copysign\",[\"f32:4286578687\",\"f32:1056964608\"]],[\"invoke\",240,0,\"copysign\",[\"f32:2139095039\",\"f32:3204448256\"]],[\"invoke\",241,0,\"copysign\",[\"f32:2139095039\",\"f32:1056964608\"]],[\"invoke\",242,0,\"copysign\",[\"f32:4286578687\",\"f32:3212836864\"]],[\"invoke\",243,0,\"copysign\",[\"f32:4286578687\",\"f32:1065353216\"]],[\"invoke\",244,0,\"copysign\",[\"f32:2139095039\",\"f32:3212836864\"]],[\"invoke\",245,0,\"copysign\",[\"f32:2139095039\",\"f32:1065353216\"]],[\"invoke\",246,0,\"copysign\",[\"f32:4286578687\",\"f32:3234402267\"]],[\"invoke\",247,0,\"copysign\",[\"f32:4286578687\",\"f32:1086918619\"]],[\"invoke\",248,0,\"copysign\",[\"f32:2139095039\",\"f32:3234402267\"]],[\"invoke\",249,0,\"copysign\",[\"f32:2139095039\",\"f32:1086918619\"]],[\"invoke\",250,0,\"copysign\",[\"f32:4286578687\",\"f32:4286578687\"]],[\"invoke\",251,0,\"copysign\",[\"f32:4286578687\",\"f32:2139095039\"]],[\"invoke\",252,0,\"copysign\",[\"f32:2139095039\",\"f32:4286578687\"]],[\"invoke\",253,0,\"copysign\",[\"f32:2139095039\",\"f32:2139095039\"]],[\"invoke\",254,0,\"copysign\",[\"f32:4286578687\",\"f32:4286578688\"]],[\"invoke\",255,0,\"copysign\",[\"f32:4286578687\",\"f32:2139095040\"]],[\"invoke\",256,0,\"copysign\",[\"f32:2139095039\",\"f32:4286578688\"]],[\"invoke\",257,0,\"copysign\",[\"f32:2139095039\",\"f32:2139095040\"]],[\"invoke\",258,0,\"copysign\",[\"f32:4286578687\",\"f32:4290772992\"]],[\"invoke\",259,0,\"copysign\",[\"f32:4286578687\",\"f32:2143289344\"]],[\"invoke\",260,0,\"copysign\",[\"f32:2139095039\",\"f32:4290772992\"]],[\"invoke\",261,0,\"copysign\",[\"f32:2139095039\",\"f32:2143289344\"]],[\"invoke\",262,0,\"copysign\",[\"f32:4286578688\",\"f32:2147483648\"]],[\"invoke\",263,0,\"copysign\",[\"f32:4286578688\",\"f32:0\"]],[\"invoke\",264,0,\"copysign\",[\"f32:2139095040\",\"f32:2147483648\"]],[\"invoke\",265,0,\"copysign\",[\"f32:2139095040\",\"f32:0\"]],[\"invoke\",266,0,\"copysign\",[\"f32:4286578688\",\"f32:2147483649\"]],[\"invoke\",267,0,\"copysign\",[\"f32:4286578688\",\"f32:1\"]],[\"invoke\",268,0,\"copysign\",[\"f32:2139095040\",\"f32:2147483649\"]],[\"invoke\",269,0,\"copysign\",[\"f32:2139095040\",\"f32:1\"]],[\"invoke\",270,0,\"copysign\",[\"f32:4286578688\",\"f32:2155872256\"]],[\"invoke\",271,0,\"copysign\",[\"f32:4286578688\",\"f32:8388608\"]],[\"invoke\",272,0,\"copysign\",[\"f32:2139095040\",\"f32:2155872256\"]],[\"invoke\",273,0,\"copysign\",[\"f32:2139095040\",\"f32:8388608\"]],[\"invoke\",274,0,\"copysign\",[\"f32:4286578688\",\"f32:3204448256\"]],[\"invoke\",275,0,\"copysign\",[\"f32:4286578688\",\"f32:1056964608\"]],[\"invoke\",276,0,\"copysign\",[\"f32:2139095040\",\"f32:3204448256\"]],[\"invoke\",277,0,\"copysign\",[\"f32:2139095040\",\"f32:1056964608\"]],[\"invoke\",278,0,\"copysign\",[\"f32:4286578688\",\"f32:3212836864\"]],[\"invoke\",279,0,\"copysign\",[\"f32:4286578688\",\"f32:1065353216\"]],[\"invoke\",280,0,\"copysign\",[\"f32:2139095040\",\"f32:3212836864\"]],[\"invoke\",281,0,\"copysign\",[\"f32:2139095040\",\"f32:1065353216\"]],[\"invoke\",282,0,\"copysign\",[\"f32:4286578688\",\"f32:3234402267\"]],[\"invoke\",283,0,\"copysign\",[\"f32:4286578688\",\"f32:1086918619\"]],[\"invoke\",284,0,\"copysign\",[\"f32:2139095040\",\"f32:3234402267\"]],[\"invoke\",285,0,\"copysign\",[\"f32:2139095040\",\"f32:1086918619\"]],[\"invoke\",286,0,\"copysign\",[\"f32:4286578688\",\"f32:4286578687\"]],[\"invoke\",287,0,\"copysign\",[\"f32:4286578688\",\"f32:2139095039\"]],[\"invoke\",288,0,\"copysign\",[\"f32:2139095040\",\"f32:4286578687\"]],[\"invoke\",289,0,\"copysign\",[\"f32:2139095040\",\"f32:2139095039\"]],[\"invoke\",290,0,\"copysign\",[\"f32:4286578688\",\"f32:4286578688\"]],[\"invoke\",291,0,\"copysign\",[\"f32:4286578688\",\"f32:2139095040\"]],[\"invoke\",292,0,\"copysign\",[\"f32:2139095040\",\"f32:4286578688\"]],[\"invoke\",293,0,\"copysign\",[\"f32:2139095040\",\"f32:2139095040\"]],[\"invoke\",294,0,\"copysign\",[\"f32:4286578688\",\"f32:4290772992\"]],[\"invoke\",295,0,\"copysign\",[\"f32:4286578688\",\"f32:2143289344\"]],[\"invoke\",296,0,\"copysign\",[\"f32:2139095040\",\"f32:4290772992\"]],[\"invoke\",297,0,\"copysign\",[\"f32:2139095040\",\"f32:2143289344\"]],[\"invoke\",298,0,\"copysign\",[\"f32:4290772992\",\"f32:2147483648\"]],[\"invoke\",299,0,\"copysign\",[\"f32:4290772992\",\"f32:0\"]],[\"invoke\",300,0,\"copysign\",[\"f32:2143289344\",\"f32:2147483648\"]],[\"invoke\",301,0,\"copysign\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",302,0,\"copysign\",[\"f32:4290772992\",\"f32:2147483649\"]],[\"invoke\",303,0,\"copysign\",[\"f32:4290772992\",\"f32:1\"]],[\"invoke\",304,0,\"copysign\",[\"f32:2143289344\",\"f32:2147483649\"]],[\"invoke\",305,0,\"copysign\",[\"f32:2143289344\",\"f32:1\"]],[\"invoke\",306,0,\"copysign\",[\"f32:4290772992\",\"f32:2155872256\"]],[\"invoke\",307,0,\"copysign\",[\"f32:4290772992\",\"f32:8388608\"]],[\"invoke\",308,0,\"copysign\",[\"f32:2143289344\",\"f32:2155872256\"]],[\"invoke\",309,0,\"copysign\",[\"f32:2143289344\",\"f32:8388608\"]],[\"invoke\",310,0,\"copysign\",[\"f32:4290772992\",\"f32:3204448256\"]],[\"invoke\",311,0,\"copysign\",[\"f32:4290772992\",\"f32:1056964608\"]],[\"invoke\",312,0,\"copysign\",[\"f32:2143289344\",\"f32:3204448256\"]],[\"invoke\",313,0,\"copysign\",[\"f32:2143289344\",\"f32:1056964608\"]],[\"invoke\",314,0,\"copysign\",[\"f32:4290772992\",\"f32:3212836864\"]],[\"invoke\",315,0,\"copysign\",[\"f32:4290772992\",\"f32:1065353216\"]],[\"invoke\",316,0,\"copysign\",[\"f32:2143289344\",\"f32:3212836864\"]],[\"invoke\",317,0,\"copysign\",[\"f32:2143289344\",\"f32:1065353216\"]],[\"invoke\",318,0,\"copysign\",[\"f32:4290772992\",\"f32:3234402267\"]],[\"invoke\",319,0,\"copysign\",[\"f32:4290772992\",\"f32:1086918619\"]],[\"invoke\",320,0,\"copysign\",[\"f32:2143289344\",\"f32:3234402267\"]],[\"invoke\",321,0,\"copysign\",[\"f32:2143289344\",\"f32:1086918619\"]],[\"invoke\",322,0,\"copysign\",[\"f32:4290772992\",\"f32:4286578687\"]],[\"invoke\",323,0,\"copysign\",[\"f32:4290772992\",\"f32:2139095039\"]],[\"invoke\",324,0,\"copysign\",[\"f32:2143289344\",\"f32:4286578687\"]],[\"invoke\",325,0,\"copysign\",[\"f32:2143289344\",\"f32:2139095039\"]],[\"invoke\",326,0,\"copysign\",[\"f32:4290772992\",\"f32:4286578688\"]],[\"invoke\",327,0,\"copysign\",[\"f32:4290772992\",\"f32:2139095040\"]],[\"invoke\",328,0,\"copysign\",[\"f32:2143289344\",\"f32:4286578688\"]],[\"invoke\",329,0,\"copysign\",[\"f32:2143289344\",\"f32:2139095040\"]],[\"invoke\",330,0,\"copysign\",[\"f32:4290772992\",\"f32:4290772992\"]],[\"invoke\",331,0,\"copysign\",[\"f32:4290772992\",\"f32:2143289344\"]],[\"invoke\",332,0,\"copysign\",[\"f32:2143289344\",\"f32:4290772992\"]],[\"invoke\",333,0,\"copysign\",[\"f32:2143289344\",\"f32:2143289344\"]],[\"invoke\",334,0,\"abs\",[\"f32:2147483648\"]],[\"invoke\",335,0,\"abs\",[\"f32:0\"]],[\"invoke\",336,0,\"abs\",[\"f32:2147483649\"]],[\"invoke\",337,0,\"abs\",[\"f32:1\"]],[\"invoke\",338,0,\"abs\",[\"f32:2155872256\"]],[\"invoke\",339,0,\"abs\",[\"f32:8388608\"]],[\"invoke\",340,0,\"abs\",[\"f32:3204448256\"]],[\"invoke\",341,0,\"abs\",[\"f32:1056964608\"]],[\"invoke\",342,0,\"abs\",[\"f32:3212836864\"]],[\"invoke\",343,0,\"abs\",[\"f32:1065353216\"]],[\"invoke\",344,0,\"abs\",[\"f32:3234402267\"]],[\"invoke\",345,0,\"abs\",[\"f32:1086918619\"]],[\"invoke\",346,0,\"abs\",[\"f32:4286578687\"]],[\"invoke\",347,0,\"abs\",[\"f32:2139095039\"]],[\"invoke\",348,0,\"abs\",[\"f32:4286578688\"]],[\"invoke\",349,0,\"abs\",[\"f32:2139095040\"]],[\"invoke\",350,0,\"abs\",[\"f32:4290772992\"]],[\"invoke\",351,0,\"abs\",[\"f32:2143289344\"]],[\"invoke\",352,0,\"neg\",[\"f32:2147483648\"]],[\"invoke\",353,0,\"neg\",[\"f32:0\"]],[\"invoke\",354,0,\"neg\",[\"f32:2147483649\"]],[\"invoke\",355,0,\"neg\",[\"f32:1\"]],[\"invoke\",356,0,\"neg\",[\"f32:2155872256\"]],[\"invoke\",357,0,\"neg\",[\"f32:8388608\"]],[\"invoke\",358,0,\"neg\",[\"f32:3204448256\"]],[\"invoke\",359,0,\"neg\",[\"f32:1056964608\"]],[\"invoke\",360,0,\"neg\",[\"f32:3212836864\"]],[\"invoke\",361,0,\"neg\",[\"f32:1065353216\"]],[\"invoke\",362,0,\"neg\",[\"f32:3234402267\"]],[\"invoke\",363,0,\"neg\",[\"f32:1086918619\"]],[\"invoke\",364,0,\"neg\",[\"f32:4286578687\"]],[\"invoke\",365,0,\"neg\",[\"f32:2139095039\"]],[\"invoke\",366,0,\"neg\",[\"f32:4286578688\"]],[\"invoke\",367,0,\"neg\",[\"f32:2139095040\"]],[\"invoke\",368,0,\"neg\",[\"f32:4290772992\"]],[\"invoke\",369,0,\"neg\",[\"f32:2143289344\"]],[\"file\",\"f64_bitwise.wast\"],[\"module\",4,5],[\"invoke\",10,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9223372036854775808\"]],[\"invoke\",11,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",12,0,\"copysign\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",13,0,\"copysign\",[\"f64:0\",\"f64:0\"]],[\"invoke\",14,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9223372036854775809\"]],[\"invoke\",15,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:1\"]],[\"invoke\",16,0,\"copysign\",[\"f64:0\",\"f64:9223372036854775809\"]],[\"invoke\",17,0,\"copysign\",[\"f64:0\",\"f64:1\"]],[\"invoke\",18,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9227875636482146304\"]],[\"invoke\",19,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:4503599627370496\"]],[\"invoke\",20,0,\"copysign\",[\"f64:0\",\"f64:9227875636482146304\"]],[\"invoke\",21,0,\"copysign\",[\"f64:0\",\"f64:4503599627370496\"]],[\"invoke\",22,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:13826050856027422720\"]],[\"invoke\",23,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:4602678819172646912\"]],[\"invoke\",24,0,\"copysign\",[\"f64:0\",\"f64:13826050856027422720\"]],[\"invoke\",25,0,\"copysign\",[\"f64:0\",\"f64:4602678819172646912\"]],[\"invoke\",26,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:13830554455654793216\"]],[\"invoke\",27,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:4607182418800017408\"]],[\"invoke\",28,0,\"copysign\",[\"f64:0\",\"f64:13830554455654793216\"]],[\"invoke\",29,0,\"copysign\",[\"f64:0\",\"f64:4607182418800017408\"]],[\"invoke\",30,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:13842132293034192152\"]],[\"invoke\",31,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:4618760256179416344\"]],[\"invoke\",32,0,\"copysign\",[\"f64:0\",\"f64:13842132293034192152\"]],[\"invoke\",33,0,\"copysign\",[\"f64:0\",\"f64:4618760256179416344\"]],[\"invoke\",34,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:18442240474082181119\"]],[\"invoke\",35,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9218868437227405311\"]],[\"invoke\",36,0,\"copysign\",[\"f64:0\",\"f64:18442240474082181119\"]],[\"invoke\",37,0,\"copysign\",[\"f64:0\",\"f64:9218868437227405311\"]],[\"invoke\",38,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:18442240474082181120\"]],[\"invoke\",39,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9218868437227405312\"]],[\"invoke\",40,0,\"copysign\",[\"f64:0\",\"f64:18442240474082181120\"]],[\"invoke\",41,0,\"copysign\",[\"f64:0\",\"f64:9218868437227405312\"]],[\"invoke\",42,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:18444492273895866368\"]],[\"invoke\",43,0,\"copysign\",[\"f64:9223372036854775808\",\"f64:9221120237041090560\"]],[\"invoke\",44,0,\"copysign\",[\"f64:0\",\"f64:18444492273895866368\"]],[\"invoke\",45,0,\"copysign\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",46,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9223372036854775808\"]],[\"invoke\",47,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:0\"]],[\"invoke\",48,0,\"copysign\",[\"f64:1\",\"f64:9223372036854775808\"]],[\"invoke\",49,0,\"copysign\",[\"f64:1\",\"f64:0\"]],[\"invoke\",50,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9223372036854775809\"]],[\"invoke\",51,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:1\"]],[\"invoke\",52,0,\"copysign\",[\"f64:1\",\"f64:9223372036854775809\"]],[\"invoke\",53,0,\"copysign\",[\"f64:1\",\"f64:1\"]],[\"invoke\",54,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9227875636482146304\"]],[\"invoke\",55,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:4503599627370496\"]],[\"invoke\",56,0,\"copysign\",[\"f64:1\",\"f64:9227875636482146304\"]],[\"invoke\",57,0,\"copysign\",[\"f64:1\",\"f64:4503599627370496\"]],[\"invoke\",58,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:13826050856027422720\"]],[\"invoke\",59,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:4602678819172646912\"]],[\"invoke\",60,0,\"copysign\",[\"f64:1\",\"f64:13826050856027422720\"]],[\"invoke\",61,0,\"copysign\",[\"f64:1\",\"f64:4602678819172646912\"]],[\"invoke\",62,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:13830554455654793216\"]],[\"invoke\",63,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:4607182418800017408\"]],[\"invoke\",64,0,\"copysign\",[\"f64:1\",\"f64:13830554455654793216\"]],[\"invoke\",65,0,\"copysign\",[\"f64:1\",\"f64:4607182418800017408\"]],[\"invoke\",66,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:13842132293034192152\"]],[\"invoke\",67,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:4618760256179416344\"]],[\"invoke\",68,0,\"copysign\",[\"f64:1\",\"f64:13842132293034192152\"]],[\"invoke\",69,0,\"copysign\",[\"f64:1\",\"f64:4618760256179416344\"]],[\"invoke\",70,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:18442240474082181119\"]],[\"invoke\",71,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9218868437227405311\"]],[\"invoke\",72,0,\"copysign\",[\"f64:1\",\"f64:18442240474082181119\"]],[\"invoke\",73,0,\"copysign\",[\"f64:1\",\"f64:9218868437227405311\"]],[\"invoke\",74,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:18442240474082181120\"]],[\"invoke\",75,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9218868437227405312\"]],[\"invoke\",76,0,\"copysign\",[\"f64:1\",\"f64:18442240474082181120\"]],[\"invoke\",77,0,\"copysign\",[\"f64:1\",\"f64:9218868437227405312\"]],[\"invoke\",78,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:18444492273895866368\"]],[\"invoke\",79,0,\"copysign\",[\"f64:9223372036854775809\",\"f64:9221120237041090560\"]],[\"invoke\",80,0,\"copysign\",[\"f64:1\",\"f64:18444492273895866368\"]],[\"invoke\",81,0,\"copysign\",[\"f64:1\",\"f64:9221120237041090560\"]],[\"invoke\",82,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9223372036854775808\"]],[\"invoke\",83,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:0\"]],[\"invoke\",84,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9223372036854775808\"]],[\"invoke\",85,0,\"copysign\",[\"f64:4503599627370496\",\"f64:0\"]],[\"invoke\",86,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9223372036854775809\"]],[\"invoke\",87,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:1\"]],[\"invoke\",88,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9223372036854775809\"]],[\"invoke\",89,0,\"copysign\",[\"f64:4503599627370496\",\"f64:1\"]],[\"invoke\",90,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9227875636482146304\"]],[\"invoke\",91,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:4503599627370496\"]],[\"invoke\",92,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9227875636482146304\"]],[\"invoke\",93,0,\"copysign\",[\"f64:4503599627370496\",\"f64:4503599627370496\"]],[\"invoke\",94,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:13826050856027422720\"]],[\"invoke\",95,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:4602678819172646912\"]],[\"invoke\",96,0,\"copysign\",[\"f64:4503599627370496\",\"f64:13826050856027422720\"]],[\"invoke\",97,0,\"copysign\",[\"f64:4503599627370496\",\"f64:4602678819172646912\"]],[\"invoke\",98,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:13830554455654793216\"]],[\"invoke\",99,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:4607182418800017408\"]],[\"invoke\",100,0,\"copysign\",[\"f64:4503599627370496\",\"f64:13830554455654793216\"]],[\"invoke\",101,0,\"copysign\",[\"f64:4503599627370496\",\"f64:4607182418800017408\"]],[\"invoke\",102,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:13842132293034192152\"]],[\"invoke\",103,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:4618760256179416344\"]],[\"invoke\",104,0,\"copysign\",[\"f64:4503599627370496\",\"f64:13842132293034192152\"]],[\"invoke\",105,0,\"copysign\",[\"f64:4503599627370496\",\"f64:4618760256179416344\"]],[\"invoke\",106,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:18442240474082181119\"]],[\"invoke\",107,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9218868437227405311\"]],[\"invoke\",108,0,\"copysign\",[\"f64:4503599627370496\",\"f64:18442240474082181119\"]],[\"invoke\",109,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9218868437227405311\"]],[\"invoke\",110,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:18442240474082181120\"]],[\"invoke\",111,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9218868437227405312\"]],[\"invoke\",112,0,\"copysign\",[\"f64:4503599627370496\",\"f64:18442240474082181120\"]],[\"invoke\",113,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9218868437227405312\"]],[\"invoke\",114,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:18444492273895866368\"]],[\"invoke\",115,0,\"copysign\",[\"f64:9227875636482146304\",\"f64:9221120237041090560\"]],[\"invoke\",116,0,\"copysign\",[\"f64:4503599627370496\",\"f64:18444492273895866368\"]],[\"invoke\",117,0,\"copysign\",[\"f64:4503599627370496\",\"f64:9221120237041090560\"]],[\"invoke\",118,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9223372036854775808\"]],[\"invoke\",119,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:0\"]],[\"invoke\",120,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9223372036854775808\"]],[\"invoke\",121,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:0\"]],[\"invoke\",122,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9223372036854775809\"]],[\"invoke\",123,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:1\"]],[\"invoke\",124,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9223372036854775809\"]],[\"invoke\",125,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:1\"]],[\"invoke\",126,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9227875636482146304\"]],[\"invoke\",127,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:4503599627370496\"]],[\"invoke\",128,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9227875636482146304\"]],[\"invoke\",129,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:4503599627370496\"]],[\"invoke\",130,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:13826050856027422720\"]],[\"invoke\",131,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:4602678819172646912\"]],[\"invoke\",132,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:13826050856027422720\"]],[\"invoke\",133,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:4602678819172646912\"]],[\"invoke\",134,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:13830554455654793216\"]],[\"invoke\",135,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:4607182418800017408\"]],[\"invoke\",136,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:13830554455654793216\"]],[\"invoke\",137,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:4607182418800017408\"]],[\"invoke\",138,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:13842132293034192152\"]],[\"invoke\",139,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:4618760256179416344\"]],[\"invoke\",140,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:13842132293034192152\"]],[\"invoke\",141,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:4618760256179416344\"]],[\"invoke\",142,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:18442240474082181119\"]],[\"invoke\",143,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9218868437227405311\"]],[\"invoke\",144,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:18442240474082181119\"]],[\"invoke\",145,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9218868437227405311\"]],[\"invoke\",146,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:18442240474082181120\"]],[\"invoke\",147,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9218868437227405312\"]],[\"invoke\",148,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:18442240474082181120\"]],[\"invoke\",149,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9218868437227405312\"]],[\"invoke\",150,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:18444492273895866368\"]],[\"invoke\",151,0,\"copysign\",[\"f64:13826050856027422720\",\"f64:9221120237041090560\"]],[\"invoke\",152,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:18444492273895866368\"]],[\"invoke\",153,0,\"copysign\",[\"f64:4602678819172646912\",\"f64:9221120237041090560\"]],[\"invoke\",154,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9223372036854775808\"]],[\"invoke\",155,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:0\"]],[\"invoke\",156,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9223372036854775808\"]],[\"invoke\",157,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:0\"]],[\"invoke\",158,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9223372036854775809\"]],[\"invoke\",159,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:1\"]],[\"invoke\",160,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9223372036854775809\"]],[\"invoke\",161,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:1\"]],[\"invoke\",162,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9227875636482146304\"]],[\"invoke\",163,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:4503599627370496\"]],[\"invoke\",164,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9227875636482146304\"]],[\"invoke\",165,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:4503599627370496\"]],[\"invoke\",166,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:13826050856027422720\"]],[\"invoke\",167,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:4602678819172646912\"]],[\"invoke\",168,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:13826050856027422720\"]],[\"invoke\",169,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:4602678819172646912\"]],[\"invoke\",170,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:13830554455654793216\"]],[\"invoke\",171,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:4607182418800017408\"]],[\"invoke\",172,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:13830554455654793216\"]],[\"invoke\",173,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:4607182418800017408\"]],[\"invoke\",174,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:13842132293034192152\"]],[\"invoke\",175,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:4618760256179416344\"]],[\"invoke\",176,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:13842132293034192152\"]],[\"invoke\",177,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:4618760256179416344\"]],[\"invoke\",178,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:18442240474082181119\"]],[\"invoke\",179,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9218868437227405311\"]],[\"invoke\",180,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:18442240474082181119\"]],[\"invoke\",181,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9218868437227405311\"]],[\"invoke\",182,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:18442240474082181120\"]],[\"invoke\",183,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9218868437227405312\"]],[\"invoke\",184,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:18442240474082181120\"]],[\"invoke\",185,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9218868437227405312\"]],[\"invoke\",186,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:18444492273895866368\"]],[\"invoke\",187,0,\"copysign\",[\"f64:13830554455654793216\",\"f64:9221120237041090560\"]],[\"invoke\",188,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:18444492273895866368\"]],[\"invoke\",189,0,\"copysign\",[\"f64:4607182418800017408\",\"f64:9221120237041090560\"]],[\"invoke\",190,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9223372036854775808\"]],[\"invoke\",191,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:0\"]],[\"invoke\",192,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9223372036854775808\"]],[\"invoke\",193,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:0\"]],[\"invoke\",194,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9223372036854775809\"]],[\"invoke\",195,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:1\"]],[\"invoke\",196,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9223372036854775809\"]],[\"invoke\",197,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:1\"]],[\"invoke\",198,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9227875636482146304\"]],[\"invoke\",199,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:4503599627370496\"]],[\"invoke\",200,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9227875636482146304\"]],[\"invoke\",201,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:4503599627370496\"]],[\"invoke\",202,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:13826050856027422720\"]],[\"invoke\",203,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:4602678819172646912\"]],[\"invoke\",204,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:13826050856027422720\"]],[\"invoke\",205,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:4602678819172646912\"]],[\"invoke\",206,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:13830554455654793216\"]],[\"invoke\",207,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:4607182418800017408\"]],[\"invoke\",208,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:13830554455654793216\"]],[\"invoke\",209,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:4607182418800017408\"]],[\"invoke\",210,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:13842132293034192152\"]],[\"invoke\",211,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:4618760256179416344\"]],[\"invoke\",212,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:13842132293034192152\"]],[\"invoke\",213,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:4618760256179416344\"]],[\"invoke\",214,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:18442240474082181119\"]],[\"invoke\",215,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9218868437227405311\"]],[\"invoke\",216,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:18442240474082181119\"]],[\"invoke\",217,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9218868437227405311\"]],[\"invoke\",218,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:18442240474082181120\"]],[\"invoke\",219,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9218868437227405312\"]],[\"invoke\",220,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:18442240474082181120\"]],[\"invoke\",221,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9218868437227405312\"]],[\"invoke\",222,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:18444492273895866368\"]],[\"invoke\",223,0,\"copysign\",[\"f64:13842132293034192152\",\"f64:9221120237041090560\"]],[\"invoke\",224,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:18444492273895866368\"]],[\"invoke\",225,0,\"copysign\",[\"f64:4618760256179416344\",\"f64:9221120237041090560\"]],[\"invoke\",226,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9223372036854775808\"]],[\"invoke\",227,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:0\"]],[\"invoke\",228,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9223372036854775808\"]],[\"invoke\",229,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:0\"]],[\"invoke\",230,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9223372036854775809\"]],[\"invoke\",231,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:1\"]],[\"invoke\",232,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9223372036854775809\"]],[\"invoke\",233,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:1\"]],[\"invoke\",234,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9227875636482146304\"]],[\"invoke\",235,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:4503599627370496\"]],[\"invoke\",236,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9227875636482146304\"]],[\"invoke\",237,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:4503599627370496\"]],[\"invoke\",238,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:13826050856027422720\"]],[\"invoke\",239,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:4602678819172646912\"]],[\"invoke\",240,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:13826050856027422720\"]],[\"invoke\",241,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:4602678819172646912\"]],[\"invoke\",242,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:13830554455654793216\"]],[\"invoke\",243,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:4607182418800017408\"]],[\"invoke\",244,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:13830554455654793216\"]],[\"invoke\",245,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:4607182418800017408\"]],[\"invoke\",246,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:13842132293034192152\"]],[\"invoke\",247,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:4618760256179416344\"]],[\"invoke\",248,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:13842132293034192152\"]],[\"invoke\",249,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:4618760256179416344\"]],[\"invoke\",250,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:18442240474082181119\"]],[\"invoke\",251,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9218868437227405311\"]],[\"invoke\",252,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:18442240474082181119\"]],[\"invoke\",253,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9218868437227405311\"]],[\"invoke\",254,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:18442240474082181120\"]],[\"invoke\",255,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9218868437227405312\"]],[\"invoke\",256,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:18442240474082181120\"]],[\"invoke\",257,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9218868437227405312\"]],[\"invoke\",258,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:18444492273895866368\"]],[\"invoke\",259,0,\"copysign\",[\"f64:18442240474082181119\",\"f64:9221120237041090560\"]],[\"invoke\",260,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:18444492273895866368\"]],[\"invoke\",261,0,\"copysign\",[\"f64:9218868437227405311\",\"f64:9221120237041090560\"]],[\"invoke\",262,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9223372036854775808\"]],[\"invoke\",263,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:0\"]],[\"invoke\",264,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9223372036854775808\"]],[\"invoke\",265,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:0\"]],[\"invoke\",266,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9223372036854775809\"]],[\"invoke\",267,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:1\"]],[\"invoke\",268,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9223372036854775809\"]],[\"invoke\",269,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:1\"]],[\"invoke\",270,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9227875636482146304\"]],[\"invoke\",271,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:4503599627370496\"]],[\"invoke\",272,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9227875636482146304\"]],[\"invoke\",273,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:4503599627370496\"]],[\"invoke\",274,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:13826050856027422720\"]],[\"invoke\",275,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:4602678819172646912\"]],[\"invoke\",276,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:13826050856027422720\"]],[\"invoke\",277,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:4602678819172646912\"]],[\"invoke\",278,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:13830554455654793216\"]],[\"invoke\",279,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:4607182418800017408\"]],[\"invoke\",280,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:13830554455654793216\"]],[\"invoke\",281,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:4607182418800017408\"]],[\"invoke\",282,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:13842132293034192152\"]],[\"invoke\",283,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:4618760256179416344\"]],[\"invoke\",284,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:13842132293034192152\"]],[\"invoke\",285,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:4618760256179416344\"]],[\"invoke\",286,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:18442240474082181119\"]],[\"invoke\",287,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9218868437227405311\"]],[\"invoke\",288,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:18442240474082181119\"]],[\"invoke\",289,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9218868437227405311\"]],[\"invoke\",290,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:18442240474082181120\"]],[\"invoke\",291,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9218868437227405312\"]],[\"invoke\",292,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:18442240474082181120\"]],[\"invoke\",293,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9218868437227405312\"]],[\"invoke\",294,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:18444492273895866368\"]],[\"invoke\",295,0,\"copysign\",[\"f64:18442240474082181120\",\"f64:9221120237041090560\"]],[\"invoke\",296,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:18444492273895866368\"]],[\"invoke\",297,0,\"copysign\",[\"f64:9218868437227405312\",\"f64:9221120237041090560\"]],[\"invoke\",298,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9223372036854775808\"]],[\"invoke\",299,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:0\"]],[\"invoke\",300,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9223372036854775808\"]],[\"invoke\",301,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",302,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9223372036854775809\"]],[\"invoke\",303,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:1\"]],[\"invoke\",304,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9223372036854775809\"]],[\"invoke\",305,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:1\"]],[\"invoke\",306,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9227875636482146304\"]],[\"invoke\",307,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:4503599627370496\"]],[\"invoke\",308,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9227875636482146304\"]],[\"invoke\",309,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:4503599627370496\"]],[\"invoke\",310,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:13826050856027422720\"]],[\"invoke\",311,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:4602678819172646912\"]],[\"invoke\",312,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:13826050856027422720\"]],[\"invoke\",313,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:4602678819172646912\"]],[\"invoke\",314,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:13830554455654793216\"]],[\"invoke\",315,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:4607182418800017408\"]],[\"invoke\",316,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:13830554455654793216\"]],[\"invoke\",317,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:4607182418800017408\"]],[\"invoke\",318,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:13842132293034192152\"]],[\"invoke\",319,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:4618760256179416344\"]],[\"invoke\",320,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:13842132293034192152\"]],[\"invoke\",321,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:4618760256179416344\"]],[\"invoke\",322,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:18442240474082181119\"]],[\"invoke\",323,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9218868437227405311\"]],[\"invoke\",324,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:18442240474082181119\"]],[\"invoke\",325,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9218868437227405311\"]],[\"invoke\",326,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:18442240474082181120\"]],[\"invoke\",327,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9218868437227405312\"]],[\"invoke\",328,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:18442240474082181120\"]],[\"invoke\",329,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9218868437227405312\"]],[\"invoke\",330,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:18444492273895866368\"]],[\"invoke\",331,0,\"copysign\",[\"f64:18444492273895866368\",\"f64:9221120237041090560\"]],[\"invoke\",332,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:18444492273895866368\"]],[\"invoke\",333,0,\"copysign\",[\"f64:9221120237041090560\",\"f64:9221120237041090560\"]],[\"invoke\",334,0,\"abs\",[\"f64:9223372036854775808\"]],[\"invoke\",335,0,\"abs\",[\"f64:0\"]],[\"invoke\",336,0,\"abs\",[\"f64:9223372036854775809\"]],[\"invoke\",337,0,\"abs\",[\"f64:1\"]],[\"invoke\",338,0,\"abs\",[\"f64:9227875636482146304\"]],[\"invoke\",339,0,\"abs\",[\"f64:4503599627370496\"]],[\"invoke\",340,0,\"abs\",[\"f64:13826050856027422720\"]],[\"invoke\",341,0,\"abs\",[\"f64:4602678819172646912\"]],[\"invoke\",342,0,\"abs\",[\"f64:13830554455654793216\"]],[\"invoke\",343,0,\"abs\",[\"f64:4607182418800017408\"]],[\"invoke\",344,0,\"abs\",[\"f64:13842132293034192152\"]],[\"invoke\",345,0,\"abs\",[\"f64:4618760256179416344\"]],[\"invoke\",346,0,\"abs\",[\"f64:18442240474082181119\"]],[\"invoke\",347,0,\"abs\",[\"f64:9218868437227405311\"]],[\"invoke\",348,0,\"abs\",[\"f64:18442240474082181120\"]],[\"invoke\",349,0,\"abs\",[\"f64:9218868437227405312\"]],[\"invoke\",350,0,\"abs\",[\"f64:18444492273895866368\"]],[\"invoke\",351,0,\"abs\",[\"f64:9221120237041090560\"]],[\"invoke\",352,0,\"neg\",[\"f64:9223372036854775808\"]],[\"invoke\",353,0,\"neg\",[\"f64:0\"]],[\"invoke\",354,0,\"neg\",[\"f64:9223372036854775809\"]],[\"invoke\",355,0,\"neg\",[\"f64:1\"]],[\"invoke\",356,0,\"neg\",[\"f64:9227875636482146304\"]],[\"invoke\",357,0,\"neg\",[\"f64:4503599627370496\"]],[\"invoke\",358,0,\"neg\",[\"f64:13826050856027422720\"]],[\"invoke\",359,0,\"neg\",[\"f64:4602678819172646912\"]],[\"invoke\",360,0,\"neg\",[\"f64:13830554455654793216\"]],[\"invoke\",361,0,\"neg\",[\"f64:4607182418800017408\"]],[\"invoke\",362,0,\"neg\",[\"f64:13842132293034192152\"]],[\"invoke\",363,0,\"neg\",[\"f64:4618760256179416344\"]],[\"invoke\",364,0,\"neg\",[\"f64:18442240474082181119\"]],[\"invoke\",365,0,\"neg\",[\"f64:9218868437227405311\"]],[\"invoke\",366,0,\"neg\",[\"f64:18442240474082181120\"]],[\"invoke\",367,0,\"neg\",[\"f64:9218868437227405312\"]],[\"invoke\",368,0,\"neg\",[\"f64:18444492273895866368\"]],[\"invoke\",369,0,\"neg\",[\"f64:9221120237041090560\"]],[\"file\",\"float_exprs.wast\"],[\"module\",6,6],[\"invoke\",11,0,\"f64.no_contraction\",[\"f64:13369472591878845359\",\"f64:7598224971858294334\",\"f64:7009968021366006149\"]],[\"invoke\",13,0,\"f64.no_contraction\",[\"f64:11159707324127586240\",\"f64:7011538096610110295\",\"f64:4140382893275160737\"]],[\"invoke\",15,0,\"f64.no_contraction\",[\"f64:9554523352352050493\",\"f64:18042841594766434431\",\"f64:4368037109959396445\"]],[\"module\",19,7],[\"invoke\",27,0,\"f32.no_fma\",[\"f32:838240978\",\"f32:2796592697\",\"f32:329493464\"]],[\"invoke\",29,0,\"f32.no_fma\",[\"f32:999635965\",\"f32:3403528619\",\"f32:3222888213\"]],[\"invoke\",31,0,\"f64.no_fma\",[\"f64:7118716943724900052\",\"f64:6546073043412611735\",\"f64:18275705786238687882\"]],[\"invoke\",33,0,\"f64.no_fma\",[\"f64:1362668175782178275\",\"f64:18385570095786966502\",\"f64:5677031731722859914\"]],[\"invoke\",35,0,\"f64.no_fma\",[\"f64:4843589256781277081\",\"f64:7695653093478086834\",\"f64:16938438850771988744\"]],[\"module\",40,8],[\"invoke\",48,0,\"f64.no_fold_add_zero\",[\"f64:9223372036854775808\"]],[\"module\",54,9],[\"invoke\",62,0,\"f64.no_fold_zero_sub\",[\"f64:0\"]],[\"module\",68,10],[\"module\",80,11],[\"invoke\",88,0,\"f32.no_fold_mul_zero\",[\"f32:3212836864\"]],[\"invoke\",91,0,\"f64.no_fold_mul_zero\",[\"f64:9223372036854775808\"]],[\"invoke\",93,0,\"f64.no_fold_mul_zero\",[\"f64:13835058055282163712\"]],[\"module\",99,12],[\"module\",111,13],[\"invoke\",118,0,\"f32.no_fold_zero_div\",[\"f32:0\"]],[\"invoke\",120,0,\"f32.no_fold_zero_div\",[\"f32:2143289344\"]],[\"invoke\",123,0,\"f64.no_fold_zero_div\",[\"f64:9223372036854775808\"]],[\"module\",129,14],[\"module\",141,15],[\"module\",153,16],[\"module\",165,17],[\"module\",177,18],[\"invoke\",184,0,\"f32.no_fold_eq_self\",[\"f32:2143289344\"]],[\"module\",189,19],[\"invoke\",196,0,\"f32.no_fold_ne_self\",[\"f32:2143289344\"]],[\"module\",201,20],[\"invoke\",208,0,\"f32.no_fold_sub_self\",[\"f32:2139095040\"]],[\"invoke\",210,0,\"f64.no_fold_sub_self\",[\"f64:9218868437227405312\"]],[\"module\",215,21],[\"invoke\",222,0,\"f32.no_fold_div_self\",[\"f32:2139095040\"]],[\"invoke\",224,0,\"f32.no_fold_div_self\",[\"f32:0\"]],[\"invoke\",226,0,\"f64.no_fold_div_self\",[\"f64:9218868437227405312\"]],[\"invoke\",228,0,\"f64.no_fold_div_self\",[\"f64:0\"]],[\"module\",233,22],[\"invoke\",240,0,\"f32.no_fold_div_3\",[\"f32:3634023955\"]],[\"invoke\",242,0,\"f32.no_fold_div_3\",[\"f32:2517965963\"]],[\"invoke\",243,0,\"f32.no_fold_div_3\",[\"f32:2173683100\"]],[\"invoke\",245,0,\"f64.no_fold_div_3\",[\"f64:16679796490173820099\"]],[\"invoke\",247,0,\"f64.no_fold_div_3\",[\"f64:674365394458900388\"]],[\"invoke\",249,0,\"f64.no_fold_div_3\",[\"f64:6476267216527259981\"]],[\"module\",253,23],[\"invoke\",261,0,\"f32.no_factor\",[\"f32:3168433147\",\"f32:1028017286\",\"f32:3141035521\"]],[\"invoke\",263,0,\"f32.no_factor\",[\"f32:2684117842\",\"f32:369386499\",\"f32:2061166438\"]],[\"invoke\",265,0,\"f64.no_factor\",[\"f64:2698691837980592503\",\"f64:2529920934327896545\",\"f64:12819783413251458936\"]],[\"invoke\",267,0,\"f64.no_factor\",[\"f64:12326480769054961745\",\"f64:12563546453737163926\",\"f64:15990519985875741037\"]],[\"invoke\",269,0,\"f64.no_factor\",[\"f64:1871759566187673434\",\"f64:2002968319587025494\",\"f64:16033202089880281080\"]],[\"module\",273,24],[\"invoke\",281,0,\"f32.no_distribute\",[\"f32:3168433147\",\"f32:1028017286\",\"f32:3141035521\"]],[\"invoke\",283,0,\"f32.no_distribute\",[\"f32:2684117842\",\"f32:369386499\",\"f32:2061166438\"]],[\"invoke\",285,0,\"f64.no_distribute\",[\"f64:2698691837980592503\",\"f64:2529920934327896545\",\"f64:12819783413251458936\"]],[\"invoke\",287,0,\"f64.no_distribute\",[\"f64:12326480769054961745\",\"f64:12563546453737163926\",\"f64:15990519985875741037\"]],[\"invoke\",288,0,\"f64.no_distribute\",[\"f64:12532477544855171977\",\"f64:3439526350000314825\",\"f64:12694541248380731909\"]],[\"module\",293,25],[\"invoke\",300,0,\"f32.no_regroup_div_mul\",[\"f32:2249624147\",\"f32:2678828342\",\"f32:95319815\"]],[\"invoke\",302,0,\"f32.no_regroup_div_mul\",[\"f32:3350590135\",\"f32:3042588643\",\"f32:2186448635\"]],[\"invoke\",304,0,\"f32.no_regroup_div_mul\",[\"f32:2011387707\",\"f32:1274956446\",\"f32:3811596788\"]],[\"invoke\",306,0,\"f64.no_regroup_div_mul\",[\"f64:6126139291059848917\",\"f64:2596039250849921421\",\"f64:17423258659719899654\"]],[\"invoke\",308,0,\"f64.no_regroup_div_mul\",[\"f64:15994259208199847538\",\"f64:16584156163346075677\",\"f64:17596923907238870430\"]],[\"module\",313,26],[\"invoke\",320,0,\"f32.no_regroup_mul_div\",[\"f32:2249624147\",\"f32:2678828342\",\"f32:95319815\"]],[\"invoke\",322,0,\"f32.no_regroup_mul_div\",[\"f32:3350590135\",\"f32:3042588643\",\"f32:2186448635\"]],[\"invoke\",324,0,\"f32.no_regroup_mul_div\",[\"f32:2011387707\",\"f32:1274956446\",\"f32:3811596788\"]],[\"invoke\",326,0,\"f64.no_regroup_mul_div\",[\"f64:6126139291059848917\",\"f64:2596039250849921421\",\"f64:17423258659719899654\"]],[\"invoke\",328,0,\"f64.no_regroup_mul_div\",[\"f64:15994259208199847538\",\"f64:16584156163346075677\",\"f64:17596923907238870430\"]],[\"module\",333,27],[\"invoke\",340,0,\"f32.no_reassociate_add\",[\"f32:3585064686\",\"f32:1354934024\",\"f32:3612934982\",\"f32:3557837641\"]],[\"invoke\",342,0,\"f32.no_reassociate_add\",[\"f32:3506363549\",\"f32:3562765939\",\"f32:1440782572\",\"f32:1388583643\"]],[\"invoke\",343,0,\"f32.no_reassociate_add\",[\"f32:1460378878\",\"f32:1481791683\",\"f32:3506843934\",\"f32:1493913729\"]],[\"invoke\",345,0,\"f64.no_reassociate_add\",[\"f64:17619937326421449126\",\"f64:8424880666975634327\",\"f64:8461713040394112626\",\"f64:17692076622886930107\"]],[\"invoke\",347,0,\"f64.no_reassociate_add\",[\"f64:15816220208145029204\",\"f64:6443786499090728432\",\"f64:15798639273395365185\",\"f64:6395820899158300605\"]],[\"invoke\",349,0,\"f64.no_reassociate_add\",[\"f64:16720963389015391005\",\"f64:16597092572968550980\",\"f64:7518944085377596897\",\"f64:16733407756820198530\"]],[\"module\",353,28],[\"invoke\",361,0,\"f32.no_reassociate_mul\",[\"f32:598526039\",\"f32:4072603010\",\"f32:2166864805\",\"f32:3802968051\"]],[\"invoke\",363,0,\"f32.no_reassociate_mul\",[\"f32:191948150\",\"f32:1717012201\",\"f32:3682645872\",\"f32:3713382507\"]],[\"invoke\",365,0,\"f64.no_reassociate_mul\",[\"f64:10830726381612138752\",\"f64:18293529276079591087\",\"f64:12137662286027993114\",\"f64:16821646709291069775\"]],[\"invoke\",367,0,\"f64.no_reassociate_mul\",[\"f64:2352911459797566465\",\"f64:17379873157362463143\",\"f64:1179129869275935356\",\"f64:14228398113747850351\"]],[\"invoke\",369,0,\"f64.no_reassociate_mul\",[\"f64:3553622953022765407\",\"f64:1044040287824900408\",\"f64:17112762794520509437\",\"f64:11134095486440145773\"]],[\"module\",373,29],[\"invoke\",381,0,\"f32.no_fold_div_0\",[\"f32:3212836864\"]],[\"invoke\",383,0,\"f32.no_fold_div_0\",[\"f32:4286578688\"]],[\"invoke\",385,0,\"f32.no_fold_div_0\",[\"f32:2147483648\"]],[\"invoke\",388,0,\"f64.no_fold_div_0\",[\"f64:4607182418800017408\"]],[\"invoke\",389,0,\"f64.no_fold_div_0\",[\"f64:13830554455654793216\"]],[\"invoke\",391,0,\"f64.no_fold_div_0\",[\"f64:18442240474082181120\"]],[\"invoke\",393,0,\"f64.no_fold_div_0\",[\"f64:9223372036854775808\"]],[\"module\",399,30],[\"invoke\",406,0,\"f32.no_fold_div_neg0\",[\"f32:1065353216\"]],[\"invoke\",408,0,\"f32.no_fold_div_neg0\",[\"f32:2139095040\"]],[\"invoke\",410,0,\"f32.no_fold_div_neg0\",[\"f32:0\"]],[\"invoke\",413,0,\"f32.no_fold_div_neg0\",[\"f32:2143289344\"]],[\"invoke\",415,0,\"f64.no_fold_div_neg0\",[\"f64:13830554455654793216\"]],[\"invoke\",417,0,\"f64.no_fold_div_neg0\",[\"f64:18442240474082181120\"]],[\"invoke\",419,0,\"f64.no_fold_div_neg0\",[\"f64:9223372036854775808\"]],[\"module\",425,31],[\"invoke\",434,0,\"f32.no_fold_to_hypot\",[\"f32:392264092\",\"f32:497028527\"]],[\"invoke\",436,0,\"f32.no_fold_to_hypot\",[\"f32:2261577829\",\"f32:2641790518\"]],[\"invoke\",438,0,\"f32.no_fold_to_hypot\",[\"f32:432505039\",\"f32:2618036612\"]],[\"invoke\",439,0,\"f64.no_fold_to_hypot\",[\"f64:1743351192697472785\",\"f64:2202602366606243153\"]],[\"invoke\",441,0,\"f64.no_fold_to_hypot\",[\"f64:2195337108264055819\",\"f64:10384237061545402288\"]],[\"invoke\",443,0,\"f64.no_fold_to_hypot\",[\"f64:1591440107418864392\",\"f64:11515806374387309036\"]],[\"module\",447,32],[\"invoke\",453,0,\"f32.no_approximate_reciprocal\",[\"f32:2138280080\"]],[\"invoke\",455,0,\"f32.no_approximate_reciprocal\",[\"f32:1705936409\"]],[\"module\",460,33],[\"invoke\",467,0,\"f32.no_approximate_reciprocal_sqrt\",[\"f32:708147349\"]],[\"invoke\",469,0,\"f32.no_approximate_reciprocal_sqrt\",[\"f32:517799246\"]],[\"invoke\",471,0,\"f32.no_approximate_reciprocal_sqrt\",[\"f32:347001813\"]],[\"invoke\",474,0,\"f64.no_fuse_reciprocal_sqrt\",[\"f64:6008428610859539631\"]],[\"invoke\",476,0,\"f64.no_fuse_reciprocal_sqrt\",[\"f64:7616219057857077123\"]],[\"module\",481,34],[\"invoke\",486,0,\"f32.no_approximate_sqrt_reciprocal\",[\"f32:1574069443\"]],[\"invoke\",488,0,\"f32.no_approximate_sqrt_reciprocal\",[\"f32:1644769121\"]],[\"invoke\",490,0,\"f32.no_approximate_sqrt_reciprocal\",[\"f32:1940205041\"]],[\"module\",494,35],[\"invoke\",505,0,\"i32.no_fold_f32_s\",[\"i32:16777216\"]],[\"invoke\",507,0,\"i32.no_fold_f32_s\",[\"i32:4026531856\"]],[\"invoke\",510,0,\"i32.no_fold_f32_u\",[\"i32:16777217\"]],[\"invoke\",513,0,\"i64.no_fold_f64_s\",[\"i64:9007199254740992\"]],[\"invoke\",515,0,\"i64.no_fold_f64_s\",[\"i64:17293822569102705664\"]],[\"invoke\",518,0,\"i64.no_fold_f64_u\",[\"i64:9007199254740993\"]],[\"module\",523,36],[\"invoke\",530,0,\"f32.no_fold_add_sub\",[\"f32:677030386\",\"f32:2998136214\"]],[\"invoke\",532,0,\"f32.no_fold_add_sub\",[\"f32:3908960888\",\"f32:4063404061\"]],[\"invoke\",534,0,\"f32.no_fold_add_sub\",[\"f32:2307650739\",\"f32:2511328013\"]],[\"invoke\",537,0,\"f64.no_fold_add_sub\",[\"f64:2152218683357821298\",\"f64:2238360073507307376\"]],[\"invoke\",539,0,\"f64.no_fold_add_sub\",[\"f64:12298280617237492384\",\"f64:3233965342858558382\"]],[\"module\",544,37],[\"invoke\",551,0,\"f32.no_fold_sub_add\",[\"f32:3291029084\",\"f32:1137280182\"]],[\"invoke\",553,0,\"f32.no_fold_sub_add\",[\"f32:1285466516\",\"f32:1361849144\"]],[\"invoke\",554,0,\"f32.no_fold_sub_add\",[\"f32:740009747\",\"f32:2989707904\"]],[\"invoke\",557,0,\"f64.no_fold_sub_add\",[\"f64:5758126085282503565\",\"f64:14997141603873875659\"]],[\"invoke\",559,0,\"f64.no_fold_sub_add\",[\"f64:5738179408840599949\",\"f64:15186085143903012996\"]],[\"invoke\",561,0,\"f64.no_fold_sub_add\",[\"f64:2955729038738127538\",\"f64:12208627806665035010\"]],[\"module\",565,38],[\"invoke\",573,0,\"f32.no_fold_mul_div\",[\"f32:2995104604\",\"f32:178524966\"]],[\"invoke\",575,0,\"f32.no_fold_mul_div\",[\"f32:1507152519\",\"f32:3723483599\"]],[\"invoke\",578,0,\"f64.no_fold_mul_div\",[\"f64:10062123074470382106\",\"f64:12910565991996555404\"]],[\"invoke\",580,0,\"f64.no_fold_mul_div\",[\"f64:14905228263410157971\",\"f64:11346251643264732732\"]],[\"invoke\",582,0,\"f64.no_fold_mul_div\",[\"f64:16807035693954817236\",\"f64:12360222454864961326\"]],[\"module\",586,39],[\"invoke\",594,0,\"f32.no_fold_div_mul\",[\"f32:2777664539\",\"f32:3062588018\"]],[\"invoke\",596,0,\"f32.no_fold_div_mul\",[\"f32:2593594703\",\"f32:3709508810\"]],[\"invoke\",599,0,\"f64.no_fold_div_mul\",[\"f64:665690489208775809\",\"f64:14660005164454413124\"]],[\"invoke\",601,0,\"f64.no_fold_div_mul\",[\"f64:13179336828827425934\",\"f64:6536345148565138764\"]],[\"invoke\",602,0,\"f64.no_fold_div_mul\",[\"f64:12582623625647949669\",\"f64:15106746174896642041\"]],[\"module\",607,40],[\"invoke\",614,0,\"f32.no_fold_div2_mul2\",[\"f32:16777215\"]],[\"module\",619,41],[\"invoke\",624,0,\"no_fold_demote_promote\",[\"f64:13235495337234861917\"]],[\"invoke\",626,0,\"no_fold_demote_promote\",[\"f64:5090364081358261697\"]],[\"invoke\",628,0,\"no_fold_demote_promote\",[\"f64:5076240020598306430\"]],[\"module\",633,42],[\"invoke\",640,0,\"no_fold_promote_demote\",[\"f32:2147483648\"]],[\"invoke\",642,0,\"no_fold_promote_demote\",[\"f32:2147483649\"]],[\"invoke\",644,0,\"no_fold_promote_demote\",[\"f32:2155872255\"]],[\"invoke\",646,0,\"no_fold_promote_demote\",[\"f32:2155872256\"]],[\"invoke\",648,0,\"no_fold_promote_demote\",[\"f32:4286578687\"]],[\"invoke\",650,0,\"no_fold_promote_demote\",[\"f32:4286578688\"]],[\"module\",655,43],[\"invoke\",663,0,\"no_demote_mixed_add\",[\"f64:4773927428111915216\",\"f32:1387972204\"]],[\"invoke\",665,0,\"no_demote_mixed_add\",[\"f64:13740716732336801211\",\"f32:822392741\"]],[\"invoke\",666,0,\"no_demote_mixed_add\",[\"f64:13742514716462174325\",\"f32:2870112826\"]],[\"invoke\",669,0,\"no_demote_mixed_add_commuted\",[\"f32:1387972204\",\"f64:4773927428111915216\"]],[\"invoke\",671,0,\"no_demote_mixed_add_commuted\",[\"f32:822392741\",\"f64:13740716732336801211\"]],[\"module\",677,44],[\"invoke\",684,0,\"no_demote_mixed_sub\",[\"f64:4979303437048015281\",\"f32:1583535740\"]],[\"invoke\",686,0,\"no_demote_mixed_sub\",[\"f64:13860263758943608426\",\"f32:969848030\"]],[\"invoke\",688,0,\"no_demote_mixed_sub\",[\"f64:4673175763235896759\",\"f32:1198952676\"]],[\"invoke\",691,0,\"no_demote_mixed_sub_commuted\",[\"f32:1214924370\",\"f64:13967600632962086462\"]],[\"invoke\",693,0,\"no_demote_mixed_sub_commuted\",[\"f32:472962692\",\"f64:4364064588997139903\"]],[\"module\",699,45],[\"invoke\",706,0,\"no_demote_mixed_mul\",[\"f64:3700298049681794165\",\"f32:2017642079\"]],[\"invoke\",708,0,\"no_demote_mixed_mul\",[\"f64:5404042108537284972\",\"f32:592745128\"]],[\"invoke\",710,0,\"no_demote_mixed_mul\",[\"f64:3845043516226476604\",\"f32:1468885281\"]],[\"invoke\",713,0,\"no_demote_mixed_mul_commuted\",[\"f32:169311251\",\"f64:5240203039857786645\"]],[\"invoke\",714,0,\"no_demote_mixed_mul_commuted\",[\"f32:592745128\",\"f64:5404042108537284972\"]],[\"invoke\",716,0,\"no_demote_mixed_mul_commuted\",[\"f32:1468885281\",\"f64:3845043516226476604\"]],[\"module\",721,46],[\"invoke\",729,0,\"no_demote_mixed_div\",[\"f64:3919260277508722072\",\"f32:379509872\"]],[\"invoke\",731,0,\"no_demote_mixed_div\",[\"f64:3987118416164120709\",\"f32:327692725\"]],[\"invoke\",734,0,\"no_demote_mixed_div_commuted\",[\"f32:451659502\",\"f64:4418811329667688930\"]],[\"invoke\",736,0,\"no_demote_mixed_div_commuted\",[\"f32:737399826\",\"f64:3994494799108309244\"]],[\"invoke\",738,0,\"no_demote_mixed_div_commuted\",[\"f32:456887038\",\"f64:3717438582804640027\"]],[\"module\",742,47],[\"invoke\",778,0,\"f32.i32.no_fold_trunc_s_convert_s\",[\"f32:3217031168\"]],[\"invoke\",780,0,\"f32.i32.no_fold_trunc_u_convert_s\",[\"f32:3204448256\"]],[\"invoke\",782,0,\"f32.i32.no_fold_trunc_s_convert_u\",[\"f32:3217031168\"]],[\"invoke\",784,0,\"f32.i32.no_fold_trunc_u_convert_u\",[\"f32:3204448256\"]],[\"invoke\",787,0,\"f64.i32.no_fold_trunc_s_convert_s\",[\"f64:13832806255468478464\"]],[\"invoke\",789,0,\"f64.i32.no_fold_trunc_u_convert_s\",[\"f64:13826050856027422720\"]],[\"invoke\",790,0,\"f64.i32.no_fold_trunc_s_convert_u\",[\"f64:4609434218613702656\"]],[\"invoke\",792,0,\"f64.i32.no_fold_trunc_u_convert_u\",[\"f64:4609434218613702656\"]],[\"invoke\",795,0,\"f32.i64.no_fold_trunc_s_convert_s\",[\"f32:1069547520\"]],[\"invoke\",797,0,\"f32.i64.no_fold_trunc_u_convert_s\",[\"f32:1069547520\"]],[\"invoke\",799,0,\"f32.i64.no_fold_trunc_s_convert_u\",[\"f32:1069547520\"]],[\"invoke\",801,0,\"f32.i64.no_fold_trunc_u_convert_u\",[\"f32:1069547520\"]],[\"invoke\",804,0,\"f64.i64.no_fold_trunc_s_convert_s\",[\"f64:4609434218613702656\"]],[\"invoke\",806,0,\"f64.i64.no_fold_trunc_u_convert_s\",[\"f64:4609434218613702656\"]],[\"invoke\",808,0,\"f64.i64.no_fold_trunc_s_convert_u\",[\"f64:4609434218613702656\"]],[\"invoke\",810,0,\"f64.i64.no_fold_trunc_u_convert_u\",[\"f64:4609434218613702656\"]],[\"module\",817,48],[\"invoke\",838,0,\"init\",[\"i32:0\",\"f32:1097963930\"]],[\"invoke\",840,0,\"init\",[\"i32:8\",\"f32:1098173645\"]],[\"invoke\",842,0,\"check\",[\"i32:0\"]],[\"invoke\",843,0,\"check\",[\"i32:4\"]],[\"invoke\",845,0,\"check\",[\"i32:12\"]],[\"invoke\",847,0,\"check\",[\"i32:0\"]],[\"invoke\",849,0,\"check\",[\"i32:8\"]],[\"module\",852,49],[\"invoke\",873,0,\"init\",[\"i32:0\",\"f64:4624690162351420211\"]],[\"invoke\",875,0,\"init\",[\"i32:16\",\"f64:4624802752342104474\"]],[\"invoke\",877,0,\"check\",[\"i32:0\"]],[\"invoke\",879,0,\"check\",[\"i32:16\"]],[\"invoke\",881,0,\"run\",[\"i32:32\",\"f64:4613937818241073152\"]],[\"invoke\",883,0,\"check\",[\"i32:8\"]],[\"invoke\",885,0,\"check\",[\"i32:24\"]],[\"module\",889,50],[\"invoke\",902,0,\"f32.ult\",[\"f32:1073741824\",\"f32:1073741824\"]],[\"invoke\",904,0,\"f32.ult\",[\"f32:1073741824\",\"f32:2143289344\"]],[\"invoke\",905,0,\"f32.ule\",[\"f32:1077936128\",\"f32:1073741824\"]],[\"invoke\",907,0,\"f32.ule\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",909,0,\"f32.ugt\",[\"f32:1077936128\",\"f32:1073741824\"]],[\"invoke\",911,0,\"f32.ugt\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",913,0,\"f32.uge\",[\"f32:1077936128\",\"f32:1073741824\"]],[\"invoke\",915,0,\"f32.uge\",[\"f32:1073741824\",\"f32:1077936128\"]],[\"invoke\",917,0,\"f64.ult\",[\"f64:4613937818241073152\",\"f64:4611686018427387904\"]],[\"invoke\",919,0,\"f64.ult\",[\"f64:4611686018427387904\",\"f64:4613937818241073152\"]],[\"invoke\",921,0,\"f64.ule\",[\"f64:4613937818241073152\",\"f64:4611686018427387904\"]],[\"invoke\",923,0,\"f64.ule\",[\"f64:4611686018427387904\",\"f64:4613937818241073152\"]],[\"invoke\",925,0,\"f64.ugt\",[\"f64:4613937818241073152\",\"f64:4611686018427387904\"]],[\"invoke\",927,0,\"f64.ugt\",[\"f64:4611686018427387904\",\"f64:4613937818241073152\"]],[\"invoke\",929,0,\"f64.uge\",[\"f64:4613937818241073152\",\"f64:4611686018427387904\"]],[\"invoke\",930,0,\"f64.uge\",[\"f64:4611686018427387904\",\"f64:4611686018427387904\"]],[\"invoke\",932,0,\"f64.uge\",[\"f64:4611686018427387904\",\"f64:9221120237041090560\"]],[\"module\",936,51],[\"invoke\",949,0,\"f32.no_fold_lt_select\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",951,0,\"f32.no_fold_lt_select\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",953,0,\"f32.no_fold_le_select\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",955,0,\"f32.no_fold_le_select\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",957,0,\"f32.no_fold_gt_select\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",959,0,\"f32.no_fold_gt_select\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",961,0,\"f32.no_fold_ge_select\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",963,0,\"f32.no_fold_ge_select\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",965,0,\"f64.no_fold_lt_select\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",967,0,\"f64.no_fold_lt_select\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",969,0,\"f64.no_fold_le_select\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",970,0,\"f64.no_fold_le_select\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",972,0,\"f64.no_fold_gt_select\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",974,0,\"f64.no_fold_gt_select\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",976,0,\"f64.no_fold_ge_select\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",978,0,\"f64.no_fold_ge_select\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"module\",983,52],[\"invoke\",1027,0,\"f32.no_fold_lt_if\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1029,0,\"f32.no_fold_lt_if\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1031,0,\"f32.no_fold_le_if\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1033,0,\"f32.no_fold_le_if\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1035,0,\"f32.no_fold_gt_if\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1037,0,\"f32.no_fold_gt_if\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1039,0,\"f32.no_fold_ge_if\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",1041,0,\"f32.no_fold_ge_if\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1042,0,\"f32.no_fold_ge_if\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",1044,0,\"f64.no_fold_lt_if\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",1046,0,\"f64.no_fold_lt_if\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",1048,0,\"f64.no_fold_le_if\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",1050,0,\"f64.no_fold_le_if\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",1052,0,\"f64.no_fold_gt_if\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",1054,0,\"f64.no_fold_gt_if\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"invoke\",1056,0,\"f64.no_fold_ge_if\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",1058,0,\"f64.no_fold_ge_if\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"module\",1062,53],[\"invoke\",1076,0,\"f32.no_fold_lt_select_to_abs\",[\"f32:0\"]],[\"invoke\",1079,0,\"f32.no_fold_le_select_to_abs\",[\"f32:4290772992\"]],[\"invoke\",1081,0,\"f32.no_fold_le_select_to_abs\",[\"f32:2147483648\"]],[\"invoke\",1084,0,\"f32.no_fold_gt_select_to_abs\",[\"f32:0\"]],[\"invoke\",1085,0,\"f32.no_fold_gt_select_to_abs\",[\"f32:2147483648\"]],[\"invoke\",1088,0,\"f32.no_fold_ge_select_to_abs\",[\"f32:0\"]],[\"invoke\",1091,0,\"f64.no_fold_lt_select_to_abs\",[\"f64:18444492273895866368\"]],[\"invoke\",1093,0,\"f64.no_fold_lt_select_to_abs\",[\"f64:9223372036854775808\"]],[\"invoke\",1096,0,\"f64.no_fold_le_select_to_abs\",[\"f64:0\"]],[\"invoke\",1099,0,\"f64.no_fold_gt_select_to_abs\",[\"f64:18444492273895866368\"]],[\"invoke\",1101,0,\"f64.no_fold_gt_select_to_abs\",[\"f64:9223372036854775808\"]],[\"invoke\",1104,0,\"f64.no_fold_ge_select_to_abs\",[\"f64:0\"]],[\"module\",1109,54],[\"invoke\",1154,0,\"f32.no_fold_lt_if_to_abs\",[\"f32:4290772992\"]],[\"invoke\",1156,0,\"f32.no_fold_lt_if_to_abs\",[\"f32:2147483648\"]],[\"invoke\",1159,0,\"f32.no_fold_le_if_to_abs\",[\"f32:0\"]],[\"invoke\",1162,0,\"f32.no_fold_gt_if_to_abs\",[\"f32:4290772992\"]],[\"invoke\",1164,0,\"f32.no_fold_gt_if_to_abs\",[\"f32:2147483648\"]],[\"invoke\",1166,0,\"f32.no_fold_ge_if_to_abs\",[\"f32:4290772992\"]],[\"invoke\",1168,0,\"f32.no_fold_ge_if_to_abs\",[\"f32:2147483648\"]],[\"invoke\",1171,0,\"f64.no_fold_lt_if_to_abs\",[\"f64:0\"]],[\"invoke\",1174,0,\"f64.no_fold_le_if_to_abs\",[\"f64:18444492273895866368\"]],[\"invoke\",1176,0,\"f64.no_fold_le_if_to_abs\",[\"f64:9223372036854775808\"]],[\"invoke\",1179,0,\"f64.no_fold_gt_if_to_abs\",[\"f64:0\"]],[\"invoke\",1182,0,\"f64.no_fold_ge_if_to_abs\",[\"f64:18444492273895866368\"]],[\"invoke\",1184,0,\"f64.no_fold_ge_if_to_abs\",[\"f64:9223372036854775808\"]],[\"module\",1189,55],[\"invoke\",1199,0,\"f64.incorrect_correction\",[]],[\"module\",1204,56],[\"module\",1223,57],[\"invoke\",1240,0,\"calculate\",[]],[\"module\",1245,58],[\"module\",1256,59],[\"invoke\",1262,0,\"llvm_pr27153\",[\"i32:33554434\"]],[\"module\",1267,60],[\"module\",1284,61],[\"invoke\",1298,0,\"thepast0\",[\"f64:9007199254740992\",\"f64:4607182418800017407\",\"f64:4611686018427387904\",\"f64:4602678819172646912\"]],[\"invoke\",1300,0,\"thepast2\",[\"f32:16777216\",\"f32:1056964608\",\"f32:1065353216\"]],[\"module\",1305,62],[\"invoke\",1311,0,\"inverse\",[\"f32:1119879168\"]],[\"module\",1316,63],[\"invoke\",1327,0,\"f64_sqrt_minus_2\",[\"f64:4616189618054758400\"]],[\"module\",1331,64],[\"invoke\",1340,0,\"f32.no_fold_recip_recip\",[\"f32:426844452\"]],[\"invoke\",1342,0,\"f32.no_fold_recip_recip\",[\"f32:3253941441\"]],[\"invoke\",1345,0,\"f32.no_fold_recip_recip\",[\"f32:2147483648\"]],[\"invoke\",1347,0,\"f32.no_fold_recip_recip\",[\"f32:4286578688\"]],[\"invoke\",1350,0,\"f64.no_fold_recip_recip\",[\"f64:14500888369201570768\"]],[\"invoke\",1352,0,\"f64.no_fold_recip_recip\",[\"f64:5359183527603521526\"]],[\"invoke\",1354,0,\"f64.no_fold_recip_recip\",[\"f64:8671785631545870379\"]],[\"invoke\",1357,0,\"f64.no_fold_recip_recip\",[\"f64:0\"]],[\"invoke\",1359,0,\"f64.no_fold_recip_recip\",[\"f64:9218868437227405312\"]],[\"module\",1363,65],[\"invoke\",1374,0,\"f32.no_algebraic_factoring\",[\"f32:3415653214\",\"f32:1274676302\"]],[\"invoke\",1375,0,\"f32.no_algebraic_factoring\",[\"f32:1446924633\",\"f32:3607373982\"]],[\"invoke\",1377,0,\"f32.no_algebraic_factoring\",[\"f32:3278732464\",\"f32:3379389272\"]],[\"invoke\",1380,0,\"f64.no_algebraic_factoring\",[\"f64:2911983657790464931\",\"f64:2814431682419759911\"]],[\"invoke\",1382,0,\"f64.no_algebraic_factoring\",[\"f64:14639789466354372633\",\"f64:5456963169336729236\"]],[\"module\",1387,66],[\"invoke\",1397,0,\"f32.no_algebraic_factoring\",[\"f32:684135946\",\"f32:744319693\"]],[\"invoke\",1399,0,\"f32.no_algebraic_factoring\",[\"f32:968841772\",\"f32:3106497100\"]],[\"invoke\",1401,0,\"f32.no_algebraic_factoring\",[\"f32:1498230729\",\"f32:3650453580\"]],[\"invoke\",1404,0,\"f64.no_algebraic_factoring\",[\"f64:15222970140370015722\",\"f64:15325207139996136125\"]],[\"invoke\",1406,0,\"f64.no_algebraic_factoring\",[\"f64:14653559129294038194\",\"f64:14581996260169223461\"]],[\"module\",1412,67],[\"invoke\",1445,0,\"f32.simple_x4_sum\",[\"i32:0\",\"i32:16\",\"i32:32\"]],[\"invoke\",1447,0,\"f32.load\",[\"i32:36\"]],[\"invoke\",1449,0,\"f32.load\",[\"i32:44\"]],[\"module\",1451,68],[\"invoke\",1485,0,\"f64.load\",[\"i32:64\"]],[\"invoke\",1486,0,\"f64.load\",[\"i32:72\"]],[\"invoke\",1488,0,\"f64.load\",[\"i32:88\"]],[\"module\",1493,69],[\"invoke\",1585,0,\"f32.plain_sum\",[\"i32:0\",\"i32:256\"]],[\"module\",1587,70],[\"invoke\",1636,0,\"f64.plain_sum\",[\"i32:0\",\"i32:256\"]],[\"module\",1640,71],[\"invoke\",1649,0,\"f32.no_fold_neg_sub\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1651,0,\"f32.no_fold_neg_sub\",[\"f32:0\",\"f32:0\"]],[\"invoke\",1654,0,\"f64.no_fold_neg_sub\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",1656,0,\"f64.no_fold_neg_sub\",[\"f64:0\",\"f64:0\"]],[\"module\",1660,72],[\"invoke\",1669,0,\"f32.no_fold_neg_add\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1671,0,\"f32.no_fold_neg_add\",[\"f32:0\",\"f32:0\"]],[\"invoke\",1674,0,\"f64.no_fold_neg_add\",[\"f64:0\",\"f64:9223372036854775808\"]],[\"invoke\",1676,0,\"f64.no_fold_neg_add\",[\"f64:0\",\"f64:0\"]],[\"module\",1680,73],[\"invoke\",1689,0,\"f32.no_fold_add_neg_neg\",[\"f32:0\",\"f32:2147483648\"]],[\"invoke\",1690,0,\"f32.no_fold_add_neg_neg\",[\"f32:2147483648\",\"f32:0\"]],[\"invoke\",1693,0,\"f64.no_fold_add_neg_neg\",[\"f64:9223372036854775808\",\"f64:9223372036854775808\"]],[\"invoke\",1695,0,\"f64.no_fold_add_neg_neg\",[\"f64:9223372036854775808\",\"f64:0\"]],[\"module\",1700,74],[\"invoke\",1708,0,\"f32.no_fold_add_neg\",[\"f32:0\"]],[\"invoke\",1710,0,\"f32.no_fold_add_neg\",[\"f32:2139095040\"]],[\"invoke\",1713,0,\"f64.no_fold_add_neg\",[\"f64:0\"]],[\"invoke\",1715,0,\"f64.no_fold_add_neg\",[\"f64:9218868437227405312\"]],[\"module\",1720,75],[\"invoke\",1734,0,\"f32.no_fold_6x_via_add\",[\"f32:4046243078\"]],[\"invoke\",1736,0,\"f32.no_fold_6x_via_add\",[\"f32:419462401\"]],[\"invoke\",1738,0,\"f32.no_fold_6x_via_add\",[\"f32:3883931973\"]],[\"invoke\",1741,0,\"f64.no_fold_6x_via_add\",[\"f64:11424134044545165748\"]],[\"invoke\",1743,0,\"f64.no_fold_6x_via_add\",[\"f64:7991451501228919438\"]],[\"module\",1749,76],[\"invoke\",1757,0,\"f32.no_fold_div_div\",[\"f32:3875242260\",\"f32:3086869257\",\"f32:3301317576\"]],[\"invoke\",1758,0,\"f32.no_fold_div_div\",[\"f32:485052055\",\"f32:1996083391\",\"f32:2276616712\"]],[\"invoke\",1760,0,\"f32.no_fold_div_div\",[\"f32:3101818893\",\"f32:4258133430\",\"f32:2855958950\"]],[\"invoke\",1763,0,\"f64.no_fold_div_div\",[\"f64:6128077243319875447\",\"f64:7240092044185667120\",\"f64:10312472494987686942\"]],[\"invoke\",1765,0,\"f64.no_fold_div_div\",[\"f64:13843263185226986279\",\"f64:17796742619038211051\",\"f64:5375701731263473827\"]],[\"invoke\",1767,0,\"f64.no_fold_div_div\",[\"f64:9835707468114203513\",\"f64:1924400690116523912\",\"f64:13208934041167870811\"]],[\"module\",1773,77],[\"invoke\",1782,0,\"f32.no_fold_mul_divs\",[\"f32:4068974897\",\"f32:1276265036\",\"f32:930821438\",\"f32:1044692964\"]],[\"invoke\",1784,0,\"f32.no_fold_mul_divs\",[\"f32:4135236702\",\"f32:787270424\",\"f32:932959293\",\"f32:1724950821\"]],[\"invoke\",1787,0,\"f64.no_fold_mul_divs\",[\"f64:10143060558527560466\",\"f64:11745059379675007839\",\"f64:16295837305232663584\",\"f64:5444961058358534642\"]],[\"invoke\",1789,0,\"f64.no_fold_mul_divs\",[\"f64:15220380342429201729\",\"f64:14697937818549468616\",\"f64:13203624158275174657\",\"f64:17131104131485469546\"]],[\"invoke\",1791,0,\"f64.no_fold_mul_divs\",[\"f64:4529089342618677929\",\"f64:3361245300043094097\",\"f64:1815899012046749567\",\"f64:15418396504351552390\"]],[\"module\",1795,78],[\"invoke\",1804,0,\"f32.no_fold_add_divs\",[\"f32:2690073844\",\"f32:2809448479\",\"f32:3608905030\"]],[\"invoke\",1806,0,\"f32.no_fold_add_divs\",[\"f32:2365787800\",\"f32:245111369\",\"f32:3952003433\"]],[\"invoke\",1809,0,\"f64.no_fold_add_divs\",[\"f64:15770585325769044278\",\"f64:6564157675451289455\",\"f64:8712254759989822359\"]],[\"invoke\",1810,0,\"f64.no_fold_add_divs\",[\"f64:14069844870254671283\",\"f64:4634122757084803708\",\"f64:9524897388132352235\"]],[\"invoke\",1812,0,\"f64.no_fold_add_divs\",[\"f64:6019502660029506228\",\"f64:15316513033818836241\",\"f64:4039967192182502935\"]],[\"module\",1817,79],[\"invoke\",1825,0,\"f32.no_fold_sqrt_square\",[\"f32:2662226315\"]],[\"invoke\",1827,0,\"f32.no_fold_sqrt_square\",[\"f32:2624528574\"]],[\"invoke\",1829,0,\"f32.no_fold_sqrt_square\",[\"f32:1978715378\"]],[\"invoke\",1832,0,\"f64.no_fold_sqrt_square\",[\"f64:11517048459773840771\"]],[\"invoke\",1834,0,\"f64.no_fold_sqrt_square\",[\"f64:11056484744549647728\"]],[\"module\",1839,80],[\"invoke\",1847,0,\"f32.no_fold_mul_sqrts\",[\"f32:24047316\",\"f32:2517821717\"]],[\"invoke\",1849,0,\"f32.no_fold_mul_sqrts\",[\"f32:329708528\",\"f32:1120042892\"]],[\"invoke\",1851,0,\"f32.no_fold_mul_sqrts\",[\"f32:598482176\",\"f32:990534933\"]],[\"invoke\",1854,0,\"f64.no_fold_mul_sqrts\",[\"f64:1712959863583927241\",\"f64:2792003944717853898\"]],[\"invoke\",1856,0,\"f64.no_fold_mul_sqrts\",[\"f64:2976792199849816182\",\"f64:2030444188042608984\"]],[\"module\",1861,81],[\"invoke\",1869,0,\"f32.no_fold_div_sqrts\",[\"f32:3428799709\",\"f32:2733489079\"]],[\"invoke\",1870,0,\"f32.no_fold_div_sqrts\",[\"f32:1339867611\",\"f32:1296568207\"]],[\"invoke\",1872,0,\"f32.no_fold_div_sqrts\",[\"f32:1566143010\",\"f32:816694667\"]],[\"invoke\",1875,0,\"f64.no_fold_div_sqrts\",[\"f64:10629913473787695463\",\"f64:12991130264919696663\"]],[\"invoke\",1877,0,\"f64.no_fold_div_sqrts\",[\"f64:6965599900716272009\",\"f64:4118781927977980600\"]],[\"invoke\",1879,0,\"f64.no_fold_div_sqrts\",[\"f64:1056821405580891413\",\"f64:8865548665903786673\"]],[\"module\",1883,82],[\"invoke\",1892,0,\"f32.no_fold_mul_sqrt_div\",[\"f32:2210946958\",\"f32:256302916\"]],[\"invoke\",1894,0,\"f32.no_fold_mul_sqrt_div\",[\"f32:3576537897\",\"f32:2010442638\"]],[\"invoke\",1897,0,\"f64.no_fold_mul_sqrt_div\",[\"f64:7751219282814906463\",\"f64:8023732701704228537\"]],[\"invoke\",1899,0,\"f64.no_fold_mul_sqrt_div\",[\"f64:2695209648295623224\",\"f64:7133480874314061811\"]],[\"invoke\",1901,0,\"f64.no_fold_mul_sqrt_div\",[\"f64:5076901024782455083\",\"f64:8399438310541178654\"]],[\"module\",1906,83],[\"invoke\",1915,0,\"f64.no_flush_intermediate_subnormal\",[\"f64:4503599627370496\",\"f64:4372995238176751616\",\"f64:4841369599423283200\"]],[\"module\",1920,84],[\"invoke\",1944,0,\"f32.recoding_le\",[\"f32:4286578688\",\"f32:1077936128\"]],[\"invoke\",1947,0,\"f32.recoding_eq\",[\"f32:0\",\"f32:1065353216\"]],[\"invoke\",1948,0,\"f32.recoding_le\",[\"f32:0\",\"f32:1065353216\"]],[\"invoke\",1951,0,\"f64.recoding_eq\",[\"f64:18442240474082181120\",\"f64:4613937818241073152\"]],[\"invoke\",1953,0,\"f64.recoding_lt\",[\"f64:18442240474082181120\",\"f64:4613937818241073152\"]],[\"invoke\",1956,0,\"f64.recoding_le\",[\"f64:0\",\"f64:4607182418800017408\"]],[\"invoke\",1959,0,\"recoding_demote\",[\"f64:4014054135371399168\",\"f32:1150853120\"]],[\"module\",1964,85],[\"invoke\",1973,0,\"f64.no_extended_precision_div\",[\"f64:4613937818241073152\",\"f64:4619567317775286272\",\"f64:4601392076421969627\"]],[\"module\",1980,86],[\"invoke\",1989,0,\"f64.no_distribute_exact\",[\"f64:9223372036854775808\"]],[\"module\",1994,87],[\"invoke\",2027,0,\"f32.xkcd_sqrt_2\",[\"f32:1077936128\",\"f32:1084227584\",\"f32:1078530011\",\"f32:1088421888\"]],[\"invoke\",2029,0,\"f32.xkcd_sqrt_3\",[\"f32:1073741824\",\"f32:1076754516\",\"f32:1078530011\"]],[\"invoke\",2031,0,\"f32.xkcd_sqrt_5\",[\"f32:1073741824\",\"f32:1076754516\",\"f32:1077936128\"]],[\"invoke\",2034,0,\"f64.sqrt\",[\"f64:4611686018427387904\"]],[\"invoke\",2036,0,\"f64.sqrt\",[\"f64:4613937818241073152\"]],[\"invoke\",2038,0,\"f64.sqrt\",[\"f64:4617315517961601024\"]],[\"invoke\",2039,0,\"f64.xkcd_sqrt_5\",[\"f64:4611686018427387904\",\"f64:4613303445314885481\",\"f64:4613937818241073152\"]],[\"module\",2045,88],[\"invoke\",2123,0,\"f32.compute_radix\",[\"f32:1065353216\",\"f32:1065353216\"]],[\"module\",2129,89],[\"invoke\",2137,0,\"f32.no_fold_sub1_mul_add\",[\"f32:796917760\",\"f32:1065353216\"]],[\"module\",2143,90],[\"invoke\",2157,0,\"f32.no_fold_add_le_monotonicity\",[\"f32:0\",\"f32:0\",\"f32:2143289344\"]],[\"invoke\",2159,0,\"f64.no_fold_add_le_monotonicity\",[\"f64:0\",\"f64:0\",\"f64:9221120237041090560\"]],[\"module\",2164,91],[\"invoke\",2190,0,\"f32.not_lt\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",2192,0,\"f32.not_gt\",[\"f32:2143289344\",\"f32:0\"]],[\"invoke\",2194,0,\"f64.not_lt\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"invoke\",2196,0,\"f64.not_gt\",[\"f64:9221120237041090560\",\"f64:0\"]],[\"module\",2203,92],[\"invoke\",2211,0,\"f32.epsilon\",[]],[\"module\",2218,93],[\"invoke\",2266,0,\"f32.epsilon\",[]],[\"module\",2272,94],[\"invoke\",2292,0,\"f32.no_trichotomy_lt\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",2294,0,\"f32.no_trichotomy_gt\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",2295,0,\"f32.no_trichotomy_ge\",[\"f32:0\",\"f32:2143289344\"]],[\"invoke\",2297,0,\"f64.no_trichotomy_le\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"invoke\",2299,0,\"f64.no_trichotomy_ge\",[\"f64:0\",\"f64:9221120237041090560\"]],[\"module\",2304,95],[\"invoke\",2385,0,\"f32.canonical_nan_bitpattern\",[\"i32:2143289344\",\"i32:2143289344\"]],[\"invoke\",2387,0,\"f32.canonical_nan_bitpattern\",[\"i32:2143289344\",\"i32:4290772992\"]],[\"invoke\",2389,0,\"f32.nonarithmetic_nan_bitpattern\",[\"i32:2143302160\"]],[\"invoke\",2394,0,\"f64.canonical_nan_bitpattern\",[\"i64:0\",\"i64:0\"]],[\"invoke\",2396,0,\"f64.canonical_nan_bitpattern\",[\"i64:18444492273895866368\",\"i64:9221120237041090560\"]],[\"invoke\",2398,0,\"f64.canonical_nan_bitpattern\",[\"i64:18444492273895866368\",\"i64:18444492273895866368\"]],[\"invoke\",2400,0,\"f64.nonarithmetic_nan_bitpattern\",[\"i64:18444492273895879184\"]],[\"module\",2420,96],[\"invoke\",2447,0,\"with_binary_sum_collapse\",[\"f64:4719355144821538816\",\"f64:4607182418800017408\",\"f64:13830554455654793216\",\"f64:4725141118604279808\",\"f64:4720637518976909312\",\"f64:4607182418800017408\",\"f64:13830554455654793216\",\"f64:13938223582048944128\"]],[\"module\",2454,97],[\"invoke\",2466,0,\"f32.contract2fma\",[\"f32:1066192077\",\"f32:1066192077\"]],[\"invoke\",2468,0,\"f64.contract2fma\",[\"f64:4607182418800017408\",\"f64:4607182418800017408\"]],[\"invoke\",2469,0,\"f64.contract2fma\",[\"f64:4607632778762754458\",\"f64:4607632778762754458\"]],[\"module\",2475,98],[\"invoke\",2484,0,\"f32.division_by_small_number\",[\"f32:1289068416\",\"f32:1203982336\",\"f32:980151802\"]],[\"module\",2490,99],[\"invoke\",2497,0,\"f32.golden_ratio\",[\"f32:1056964608\",\"f32:1065353216\",\"f32:1084227584\"]],[\"module\",2503,100],[\"invoke\",2516,0,\"f32.silver_means\",[\"f32:0\"]],[\"invoke\",2518,0,\"f32.silver_means\",[\"f32:1073741824\"]],[\"invoke\",2520,0,\"f32.silver_means\",[\"f32:1082130432\"]],[\"invoke\",2522,0,\"f64.silver_means\",[\"f64:0\"]],[\"invoke\",2524,0,\"f64.silver_means\",[\"f64:4611686018427387904\"]],[\"invoke\",2526,0,\"f64.silver_means\",[\"f64:4616189618054758400\"]],[\"module\",2532,101],[\"invoke\",2537,0,\"point_four\",[\"f64:4616189618054758400\",\"f64:4621819117588971520\"]],[\"module\",2542,102],[\"invoke\",2608,0,\"tau\",[\"i32:11\"]],[\"module\",2612,103],[\"invoke\",2624,0,\"f64.no_fold_conditional_inc\",[\"f64:9223372036854775808\",\"f64:13830554455654793216\"]],[\"file\",\"float_literals.wast\"],[\"module\",3,104],[\"invoke\",121,0,\"f32.nan\",[]],[\"invoke\",122,0,\"f32.positive_nan\",[]],[\"invoke\",123,0,\"f32.negative_nan\",[]],[\"invoke\",124,0,\"f32.plain_nan\",[]],[\"invoke\",125,0,\"f32.informally_known_as_plain_snan\",[]],[\"invoke\",126,0,\"f32.all_ones_nan\",[]],[\"invoke\",127,0,\"f32.misc_nan\",[]],[\"invoke\",128,0,\"f32.misc_positive_nan\",[]],[\"invoke\",129,0,\"f32.misc_negative_nan\",[]],[\"invoke\",130,0,\"f32.infinity\",[]],[\"invoke\",131,0,\"f32.positive_infinity\",[]],[\"invoke\",132,0,\"f32.negative_infinity\",[]],[\"invoke\",133,0,\"f32.zero\",[]],[\"invoke\",134,0,\"f32.positive_zero\",[]],[\"invoke\",135,0,\"f32.negative_zero\",[]],[\"invoke\",136,0,\"f32.misc\",[]],[\"invoke\",137,0,\"f32.min_positive\",[]],[\"invoke\",138,0,\"f32.min_normal\",[]],[\"invoke\",139,0,\"f32.max_subnormal\",[]],[\"invoke\",140,0,\"f32.max_finite\",[]],[\"invoke\",141,0,\"f32.trailing_dot\",[]],[\"invoke\",142,0,\"f32.misc_int\",[]],[\"invoke\",143,0,\"f32.large_int\",[]],[\"invoke\",144,0,\"f32.min_int32\",[]],[\"invoke\",145,0,\"f32.min_int64\",[]],[\"invoke\",146,0,\"f32_dec.zero\",[]],[\"invoke\",147,0,\"f32_dec.positive_zero\",[]],[\"invoke\",148,0,\"f32_dec.negative_zero\",[]],[\"invoke\",149,0,\"f32_dec.misc\",[]],[\"invoke\",150,0,\"f32_dec.min_positive\",[]],[\"invoke\",151,0,\"f32_dec.min_normal\",[]],[\"invoke\",152,0,\"f32_dec.max_subnormal\",[]],[\"invoke\",153,0,\"f32_dec.max_finite\",[]],[\"invoke\",154,0,\"f32_dec.trailing_dot\",[]],[\"invoke\",155,0,\"f32_dec.root_beer_float\",[]],[\"invoke\",156,0,\"f32_dec.misc_int\",[]],[\"invoke\",157,0,\"f32_dec.large_int\",[]],[\"invoke\",158,0,\"f32_dec.min_int32\",[]],[\"invoke\",159,0,\"f32_dec.min_int64\",[]],[\"invoke\",161,0,\"f64.nan\",[]],[\"invoke\",162,0,\"f64.positive_nan\",[]],[\"invoke\",163,0,\"f64.negative_nan\",[]],[\"invoke\",164,0,\"f64.plain_nan\",[]],[\"invoke\",165,0,\"f64.informally_known_as_plain_snan\",[]],[\"invoke\",166,0,\"f64.all_ones_nan\",[]],[\"invoke\",167,0,\"f64.misc_nan\",[]],[\"invoke\",168,0,\"f64.misc_positive_nan\",[]],[\"invoke\",169,0,\"f64.misc_negative_nan\",[]],[\"invoke\",170,0,\"f64.infinity\",[]],[\"invoke\",171,0,\"f64.positive_infinity\",[]],[\"invoke\",172,0,\"f64.negative_infinity\",[]],[\"invoke\",173,0,\"f64.zero\",[]],[\"invoke\",174,0,\"f64.positive_zero\",[]],[\"invoke\",175,0,\"f64.negative_zero\",[]],[\"invoke\",176,0,\"f64.misc\",[]],[\"invoke\",177,0,\"f64.min_positive\",[]],[\"invoke\",178,0,\"f64.min_normal\",[]],[\"invoke\",179,0,\"f64.max_subnormal\",[]],[\"invoke\",180,0,\"f64.max_finite\",[]],[\"invoke\",181,0,\"f64.trailing_dot\",[]],[\"invoke\",182,0,\"f64.misc_int\",[]],[\"invoke\",183,0,\"f64.large_int\",[]],[\"invoke\",184,0,\"f64.min_int32\",[]],[\"invoke\",185,0,\"f64.min_int64\",[]],[\"invoke\",186,0,\"f64_dec.zero\",[]],[\"invoke\",187,0,\"f64_dec.positive_zero\",[]],[\"invoke\",188,0,\"f64_dec.negative_zero\",[]],[\"invoke\",189,0,\"f64_dec.misc\",[]],[\"invoke\",190,0,\"f64_dec.min_positive\",[]],[\"invoke\",191,0,\"f64_dec.min_normal\",[]],[\"invoke\",192,0,\"f64_dec.max_subnormal\",[]],[\"invoke\",193,0,\"f64_dec.max_finite\",[]],[\"invoke\",194,0,\"f64_dec.trailing_dot\",[]],[\"invoke\",195,0,\"f64_dec.root_beer_float\",[]],[\"invoke\",196,0,\"f64_dec.misc_int\",[]],[\"invoke\",197,0,\"f64_dec.large_int\",[]],[\"invoke\",198,0,\"f64_dec.min_int32\",[]],[\"invoke\",199,0,\"f64_dec.min_int64\",[]],[\"invoke\",201,0,\"f32-dec-sep1\",[]],[\"invoke\",202,0,\"f32-dec-sep2\",[]],[\"invoke\",203,0,\"f32-dec-sep3\",[]],[\"invoke\",204,0,\"f32-dec-sep4\",[]],[\"invoke\",205,0,\"f32-dec-sep5\",[]],[\"invoke\",206,0,\"f32-hex-sep1\",[]],[\"invoke\",207,0,\"f32-hex-sep2\",[]],[\"invoke\",208,0,\"f32-hex-sep3\",[]],[\"invoke\",209,0,\"f32-hex-sep4\",[]],[\"invoke\",210,0,\"f32-hex-sep5\",[]],[\"invoke\",212,0,\"f64-dec-sep1\",[]],[\"invoke\",213,0,\"f64-dec-sep2\",[]],[\"invoke\",214,0,\"f64-dec-sep3\",[]],[\"invoke\",215,0,\"f64-dec-sep4\",[]],[\"invoke\",216,0,\"f64-dec-sep5\",[]],[\"invoke\",217,0,\"f64-hex-sep1\",[]],[\"invoke\",218,0,\"f64-hex-sep2\",[]],[\"invoke\",219,0,\"f64-hex-sep3\",[]],[\"invoke\",220,0,\"f64-hex-sep4\",[]],[\"invoke\",221,0,\"f64-hex-sep5\",[]],[\"module\",224,105],[\"invoke\",233,0,\"4294967249\",[]],[\"file\",\"float_misc.wast\"],[\"module\",17,106],[\"invoke\",50,0,\"f32.add\",[\"f32:1066388847\",\"f32:789036054\"]],[\"invoke\",55,0,\"f32.add\",[\"f32:1065353216\",\"f32:864026624\"]],[\"invoke\",56,0,\"f32.add\",[\"f32:1065353216\",\"f32:864026625\"]],[\"invoke\",57,0,\"f64.add\",[\"f64:4607182418800017408\",\"f64:4368491638549381120\"]],[\"invoke\",58,0,\"f64.add\",[\"f64:4607182418800017408\",\"f64:4368491638549381121\"]],[\"invoke\",61,0,\"f32.add\",[\"f32:1\",\"f32:8388607\"]],[\"invoke\",62,0,\"f64.add\",[\"f64:1\",\"f64:4503599627370495\"]],[\"invoke\",67,0,\"f32.add\",[\"f32:1325400064\",\"f32:1149241344\"]],[\"invoke\",72,0,\"f64.add\",[\"f64:9290926031265333248\",\"f64:5910\"]],[\"invoke\",75,0,\"f64.add\",[\"f64:4845873199050653696\",\"f64:4607182463836013682\"]],[\"invoke\",78,0,\"f64.add\",[\"f64:4845873199050653697\",\"f64:4607182281361063936\"]],[\"invoke\",81,0,\"f32.add\",[\"f32:1258291200\",\"f32:1056964608\"]],[\"invoke\",82,0,\"f32.add\",[\"f32:1258291201\",\"f32:1056964608\"]],[\"invoke\",83,0,\"f64.add\",[\"f64:4841369599423283200\",\"f64:4602678819172646912\"]],[\"invoke\",84,0,\"f64.add\",[\"f64:4841369599423283201\",\"f64:4602678819172646912\"]],[\"invoke\",88,0,\"f32.add\",[\"f32:1630930834\",\"f32:3650472296\"]],[\"invoke\",89,0,\"f32.add\",[\"f32:376639884\",\"f32:24880479\"]],[\"invoke\",90,0,\"f32.add\",[\"f32:1393899754\",\"f32:3680827526\"]],[\"invoke\",91,0,\"f32.add\",[\"f32:947682203\",\"f32:1958603311\"]],[\"invoke\",92,0,\"f64.add\",[\"f64:2751474943031650218\",\"f64:14953834855654151696\"]],[\"invoke\",93,0,\"f64.add\",[\"f64:14174076479053295281\",\"f64:3779173703388472492\"]],[\"invoke\",94,0,\"f64.add\",[\"f64:3940735352412940081\",\"f64:13776826739676942972\"]],[\"invoke\",95,0,\"f64.add\",[\"f64:6845567588107709194\",\"f64:4904758653169279867\"]],[\"invoke\",99,0,\"f32.add\",[\"f32:1670249659\",\"f32:3384781876\"]],[\"invoke\",100,0,\"f32.add\",[\"f32:692047414\",\"f32:2564611463\"]],[\"invoke\",101,0,\"f32.add\",[\"f32:2862180574\",\"f32:2122049802\"]],[\"invoke\",102,0,\"f32.add\",[\"f32:2848402951\",\"f32:2325576998\"]],[\"invoke\",103,0,\"f32.add\",[\"f32:982116028\",\"f32:2317187467\"]],[\"invoke\",104,0,\"f64.add\",[\"f64:5417704807092288842\",\"f64:11458115339210975423\"]],[\"invoke\",105,0,\"f64.add\",[\"f64:5306888566943064716\",\"f64:13560253914302152139\"]],[\"invoke\",107,0,\"f64.add\",[\"f64:14493512931660601393\",\"f64:14459238760182946131\"]],[\"invoke\",108,0,\"f64.add\",[\"f64:13847269089137787654\",\"f64:5913400236268010570\"]],[\"invoke\",111,0,\"f32.add\",[\"f32:2231979500\",\"f32:711174153\"]],[\"invoke\",112,0,\"f32.add\",[\"f32:3084976721\",\"f32:843077785\"]],[\"invoke\",113,0,\"f32.add\",[\"f32:3522127374\",\"f32:157500525\"]],[\"invoke\",114,0,\"f32.add\",[\"f32:78702389\",\"f32:3468399689\"]],[\"invoke\",115,0,\"f32.add\",[\"f32:2208228371\",\"f32:1870536627\"]],[\"invoke\",116,0,\"f64.add\",[\"f64:1111252809067936271\",\"f64:18353849863141451174\"]],[\"invoke\",118,0,\"f64.add\",[\"f64:9478779231447112314\",\"f64:3336259491488022866\"]],[\"invoke\",119,0,\"f64.add\",[\"f64:11541137186853127278\",\"f64:735421354967021004\"]],[\"invoke\",120,0,\"f64.add\",[\"f64:18181384676953296798\",\"f64:8211214354507491487\"]],[\"invoke\",123,0,\"f64.add\",[\"f64:17455847474217352892\",\"f64:8328504330151758329\"]],[\"invoke\",124,0,\"f64.add\",[\"f64:8138029755241725240\",\"f64:7967841770626914860\"]],[\"invoke\",125,0,\"f64.add\",[\"f64:16644741111433920314\",\"f64:7647005019700459394\"]],[\"invoke\",126,0,\"f64.add\",[\"f64:6696851869641768443\",\"f64:6935821972358342665\"]],[\"invoke\",130,0,\"f64.add\",[\"f64:17221080860858566255\",\"f64:18119355194379769652\"]],[\"invoke\",131,0,\"f64.add\",[\"f64:5479469458864399218\",\"f64:15063363222154738502\"]],[\"invoke\",132,0,\"f64.add\",[\"f64:15191393426281101490\",\"f64:2705322087145917275\"]],[\"invoke\",133,0,\"f64.add\",[\"f64:12404517211283155052\",\"f64:15933096090325362723\"]],[\"invoke\",134,0,\"f64.add\",[\"f64:12941874353187635000\",\"f64:149235811938438489\"]],[\"invoke\",137,0,\"f32.add\",[\"f32:2039859408\",\"f32:2137384617\"]],[\"invoke\",138,0,\"f32.add\",[\"f32:2135652809\",\"f32:4113932278\"]],[\"invoke\",140,0,\"f32.add\",[\"f32:4220448050\",\"f32:4286022000\"]],[\"invoke\",141,0,\"f32.add\",[\"f32:4280642669\",\"f32:4269109313\"]],[\"invoke\",142,0,\"f64.add\",[\"f64:9214390167692528523\",\"f64:9025765862177526868\"]],[\"invoke\",143,0,\"f64.add\",[\"f64:9218174330906182895\",\"f64:9066655639269665468\"]],[\"invoke\",144,0,\"f64.add\",[\"f64:18440065048487386960\",\"f64:9166530475417861020\"]],[\"invoke\",145,0,\"f64.add\",[\"f64:18341378616977760125\",\"f64:9218376305633483958\"]],[\"invoke\",146,0,\"f64.add\",[\"f64:9214484525044672441\",\"f64:18297568705700624757\"]],[\"invoke\",149,0,\"f32.add\",[\"f32:5932680\",\"f32:623\"]],[\"invoke\",151,0,\"f32.add\",[\"f32:2147483656\",\"f32:3701056\"]],[\"invoke\",152,0,\"f32.add\",[\"f32:2147483668\",\"f32:44113961\"]],[\"invoke\",153,0,\"f32.add\",[\"f32:453\",\"f32:2147507390\"]],[\"invoke\",154,0,\"f64.add\",[\"f64:5760669582171681\",\"f64:9233067416817195210\"]],[\"invoke\",155,0,\"f64.add\",[\"f64:9301019945277718\",\"f64:9236877899492518055\"]],[\"invoke\",156,0,\"f64.add\",[\"f64:9225260466475370890\",\"f64:9229416573822848190\"]],[\"invoke\",157,0,\"f64.add\",[\"f64:16303139584665809\",\"f64:9240639734747285230\"]],[\"invoke\",162,0,\"f32.add\",[\"f32:2139095038\",\"f32:1937768448\"]],[\"invoke\",163,0,\"f64.add\",[\"f64:9218868437227405310\",\"f64:8980177656976769024\"]],[\"invoke\",166,0,\"f32.add\",[\"f32:1073741824\",\"f32:1073741824\"]],[\"invoke\",167,0,\"f64.add\",[\"f64:4611686018427387904\",\"f64:4611686018427387904\"]],[\"invoke\",170,0,\"f32.add\",[\"f32:2139095039\",\"f32:1929379839\"]],[\"invoke\",171,0,\"f32.add\",[\"f32:2139095039\",\"f32:1929379840\"]],[\"invoke\",172,0,\"f64.add\",[\"f64:9218868437227405311\",\"f64:8975674057349398527\"]],[\"invoke\",173,0,\"f64.add\",[\"f64:9218868437227405311\",\"f64:8975674057349398528\"]],[\"invoke\",178,0,\"f64.sub\",[\"f64:4679240012837945344\",\"f64:4440549232587309056\"]],[\"invoke\",182,0,\"f32.sub\",[\"f32:1065353216\",\"f32:855638016\"]],[\"invoke\",183,0,\"f32.sub\",[\"f32:1065353216\",\"f32:855638017\"]],[\"invoke\",184,0,\"f64.sub\",[\"f64:4607182418800017408\",\"f64:4363988038922010624\"]],[\"invoke\",185,0,\"f64.sub\",[\"f64:4607182418800017408\",\"f64:4363988038922010625\"]],[\"invoke\",188,0,\"f32.sub\",[\"f32:183964211\",\"f32:4211807167\"]],[\"invoke\",189,0,\"f32.sub\",[\"f32:4213323727\",\"f32:3575761746\"]],[\"invoke\",191,0,\"f32.sub\",[\"f32:88711906\",\"f32:431212897\"]],[\"invoke\",192,0,\"f32.sub\",[\"f32:919562194\",\"f32:2319656354\"]],[\"invoke\",193,0,\"f64.sub\",[\"f64:12332465020357998661\",\"f64:9766989582560416510\"]],[\"invoke\",194,0,\"f64.sub\",[\"f64:16318450733361321773\",\"f64:13120762196173477233\"]],[\"invoke\",195,0,\"f64.sub\",[\"f64:2534186520144737456\",\"f64:10065159679028096147\"]],[\"invoke\",196,0,\"f64.sub\",[\"f64:81253721542311597\",\"f64:14524181566355681001\"]],[\"invoke\",197,0,\"f64.sub\",[\"f64:13189545483472981053\",\"f64:11407195172005604952\"]],[\"invoke\",201,0,\"f32.sub\",[\"f32:4130431355\",\"f32:1119299749\"]],[\"invoke\",202,0,\"f32.sub\",[\"f32:2517909066\",\"f32:864524238\"]],[\"invoke\",203,0,\"f32.sub\",[\"f32:2573484334\",\"f32:3114628459\"]],[\"invoke\",204,0,\"f32.sub\",[\"f32:4044667730\",\"f32:576942556\"]],[\"invoke\",205,0,\"f64.sub\",[\"f64:14742371419310964805\",\"f64:17888404506408184249\"]],[\"invoke\",206,0,\"f64.sub\",[\"f64:2953146626865245854\",\"f64:2577681730975527916\"]],[\"invoke\",207,0,\"f64.sub\",[\"f64:12932364735331397407\",\"f64:2320782934320318207\"]],[\"invoke\",208,0,\"f64.sub\",[\"f64:9365060414983047910\",\"f64:12353777816259046974\"]],[\"invoke\",212,0,\"f32.sub\",[\"f32:1869943590\",\"f32:943887556\"]],[\"invoke\",213,0,\"f32.sub\",[\"f32:3372906046\",\"f32:2919590399\"]],[\"invoke\",214,0,\"f32.sub\",[\"f32:2912495853\",\"f32:2745492671\"]],[\"invoke\",215,0,\"f32.sub\",[\"f32:3096029999\",\"f32:957859028\"]],[\"invoke\",216,0,\"f32.sub\",[\"f32:2939165019\",\"f32:2346559691\"]],[\"invoke\",217,0,\"f64.sub\",[\"f64:13126685627069188368\",\"f64:17084005755352353256\"]],[\"invoke\",218,0,\"f64.sub\",[\"f64:17250804263238954355\",\"f64:17897322818375888829\"]],[\"invoke\",220,0,\"f64.sub\",[\"f64:11250563508203208480\",\"f64:2160870138446053709\"]],[\"invoke\",221,0,\"f64.sub\",[\"f64:11315355526970152728\",\"f64:13767999508795332779\"]],[\"invoke\",224,0,\"f64.sub\",[\"f64:4259315722107263852\",\"f64:4089445689175118070\"]],[\"invoke\",225,0,\"f64.sub\",[\"f64:188121565440651108\",\"f64:62416789530785743\"]],[\"invoke\",226,0,\"f64.sub\",[\"f64:3467770562990504390\",\"f64:3710644584044210353\"]],[\"invoke\",227,0,\"f64.sub\",[\"f64:13655868372788825570\",\"f64:13522732182992332383\"]],[\"invoke\",228,0,\"f64.sub\",[\"f64:4496158230847685281\",\"f64:4595312328816348364\"]],[\"invoke\",231,0,\"f64.sub\",[\"f64:10165048318361601487\",\"f64:10384658282813060399\"]],[\"invoke\",233,0,\"f64.sub\",[\"f64:5124509539958121241\",\"f64:1953255029772502995\"]],[\"invoke\",234,0,\"f64.sub\",[\"f64:2408125051325635052\",\"f64:10707017964771367822\"]],[\"invoke\",235,0,\"f64.sub\",[\"f64:4352135458168599028\",\"f64:1826599214642193119\"]],[\"invoke\",239,0,\"f32.sub\",[\"f32:1102651427\",\"f32:1078530011\"]],[\"invoke\",240,0,\"f64.sub\",[\"f64:4627206743602008890\",\"f64:4614256656552045848\"]],[\"invoke\",243,0,\"f32.sub\",[\"f32:1245125372\",\"f32:1245125368\"]],[\"invoke\",244,0,\"f32.sub\",[\"f32:1240736760\",\"f32:1240736728\"]],[\"invoke\",246,0,\"f32.sub\",[\"f32:1220759616\",\"f32:1220759584\"]],[\"invoke\",247,0,\"f32.sub\",[\"f32:1220759616\",\"f32:1220759552\"]],[\"invoke\",248,0,\"f64.sub\",[\"f64:4838362400168542206\",\"f64:4838362400168542204\"]],[\"invoke\",249,0,\"f64.sub\",[\"f64:4835858800541171708\",\"f64:4835858800541171692\"]],[\"invoke\",250,0,\"f64.sub\",[\"f64:4835858800541171708\",\"f64:4835858800541171684\"]],[\"invoke\",251,0,\"f64.sub\",[\"f64:4825251601286430752\",\"f64:4825251601286430736\"]],[\"invoke\",252,0,\"f64.sub\",[\"f64:4825251601286430752\",\"f64:4825251601286430720\"]],[\"invoke\",256,0,\"f64.sub\",[\"f64:4503599627370496\",\"f64:4503599627370495\"]],[\"invoke\",259,0,\"f32.sub\",[\"f32:1065353217\",\"f32:1065353215\"]],[\"invoke\",260,0,\"f32.sub\",[\"f32:1065353217\",\"f32:1065353216\"]],[\"invoke\",261,0,\"f32.sub\",[\"f32:1065353216\",\"f32:1065353215\"]],[\"invoke\",262,0,\"f64.sub\",[\"f64:4607182418800017409\",\"f64:4607182418800017407\"]],[\"invoke\",263,0,\"f64.sub\",[\"f64:4607182418800017409\",\"f64:4607182418800017408\"]],[\"invoke\",264,0,\"f64.sub\",[\"f64:4607182418800017408\",\"f64:4607182418800017407\"]],[\"invoke\",268,0,\"f32.sub\",[\"f32:2139095039\",\"f32:1929379839\"]],[\"invoke\",270,0,\"f64.sub\",[\"f64:9218868437227405311\",\"f64:8975674057349398527\"]],[\"invoke\",271,0,\"f64.sub\",[\"f64:9218868437227405311\",\"f64:8975674057349398528\"]],[\"invoke\",274,0,\"f32.mul\",[\"f32:1482907561\",\"f32:1482907561\"]],[\"invoke\",275,0,\"f32.mul\",[\"f32:1621981420\",\"f32:1621981420\"]],[\"invoke\",276,0,\"f32.mul\",[\"f32:1761892689\",\"f32:1761892689\"]],[\"invoke\",277,0,\"f64.mul\",[\"f64:4831355200913801216\",\"f64:4831355200913801216\"]],[\"invoke\",278,0,\"f64.mul\",[\"f64:4906019910204099648\",\"f64:4906019910204099648\"]],[\"invoke\",284,0,\"f32.mul\",[\"f32:1323067183\",\"f32:1351920719\"]],[\"invoke\",285,0,\"f64.mul\",[\"f64:4745541551160033280\",\"f64:4761032175258435584\"]],[\"invoke\",289,0,\"f32.mul\",[\"f32:1117401907\",\"f32:1146388480\"]],[\"invoke\",290,0,\"f64.mul\",[\"f64:4635125847112967782\",\"f64:4650687894887858176\"]],[\"invoke\",293,0,\"f32.mul\",[\"f32:3725225879\",\"f32:767181884\"]],[\"invoke\",294,0,\"f32.mul\",[\"f32:4071298289\",\"f32:2363594761\"]],[\"invoke\",295,0,\"f32.mul\",[\"f32:3990403914\",\"f32:2406636213\"]],[\"invoke\",296,0,\"f32.mul\",[\"f32:3876262739\",\"f32:2590162616\"]],[\"invoke\",298,0,\"f64.mul\",[\"f64:15745248579468343268\",\"f64:8867411559652116184\"]],[\"invoke\",299,0,\"f64.mul\",[\"f64:9393595877903301723\",\"f64:12847704090045979814\"]],[\"invoke\",300,0,\"f64.mul\",[\"f64:7339743909496900438\",\"f64:14312273837817528234\"]],[\"invoke\",301,0,\"f64.mul\",[\"f64:12422633289194844785\",\"f64:7233496047441461849\"]],[\"invoke\",302,0,\"f64.mul\",[\"f64:8188526721198436258\",\"f64:745378815681991665\"]],[\"invoke\",305,0,\"f32.mul\",[\"f32:2468326353\",\"f32:3984723636\"]],[\"invoke\",306,0,\"f32.mul\",[\"f32:1680245441\",\"f32:1228341789\"]],[\"invoke\",308,0,\"f32.mul\",[\"f32:1631446143\",\"f32:3340593865\"]],[\"invoke\",309,0,\"f32.mul\",[\"f32:1321841569\",\"f32:3771977928\"]],[\"invoke\",310,0,\"f64.mul\",[\"f64:10956034376207055635\",\"f64:3195464683520095288\"]],[\"invoke\",311,0,\"f64.mul\",[\"f64:3366372084365197849\",\"f64:10971437597834234015\"]],[\"invoke\",312,0,\"f64.mul\",[\"f64:15316253934569525376\",\"f64:17593766689751523793\"]],[\"invoke\",313,0,\"f64.mul\",[\"f64:8873430008942894499\",\"f64:2630310872370005737\"]],[\"invoke\",314,0,\"f64.mul\",[\"f64:6138390736122864607\",\"f64:14591737303103877464\"]],[\"invoke\",318,0,\"f32.mul\",[\"f32:3192278970\",\"f32:242309673\"]],[\"invoke\",319,0,\"f32.mul\",[\"f32:3060150317\",\"f32:1953896717\"]],[\"invoke\",320,0,\"f32.mul\",[\"f32:3685735869\",\"f32:265571119\"]],[\"invoke\",321,0,\"f32.mul\",[\"f32:3355295625\",\"f32:69023757\"]],[\"invoke\",322,0,\"f64.mul\",[\"f64:11598370094301102699\",\"f64:15783697741936198553\"]],[\"invoke\",323,0,\"f64.mul\",[\"f64:6760137556672200005\",\"f64:10390971429121674926\"]],[\"invoke\",324,0,\"f64.mul\",[\"f64:14608361260346079328\",\"f64:6227029768418337647\"]],[\"invoke\",325,0,\"f64.mul\",[\"f64:8069908676175581646\",\"f64:15517844864458283108\"]],[\"invoke\",329,0,\"f64.mul\",[\"f64:3075846375446710711\",\"f64:2019524319895558702\"]],[\"invoke\",330,0,\"f64.mul\",[\"f64:13792389967993824121\",\"f64:7865224186729676301\"]],[\"invoke\",331,0,\"f64.mul\",[\"f64:15483491341737357200\",\"f64:10898188329492193507\"]],[\"invoke\",332,0,\"f64.mul\",[\"f64:8100886621587996114\",\"f64:4881220253517731398\"]],[\"invoke\",333,0,\"f64.mul\",[\"f64:12589892576446671178\",\"f64:8646729507413822745\"]],[\"invoke\",336,0,\"f64.mul\",[\"f64:1913383041739811140\",\"f64:2696786534754768330\"]],[\"invoke\",337,0,\"f64.mul\",[\"f64:13576886274997223712\",\"f64:9480836654241272360\"]],[\"invoke\",339,0,\"f64.mul\",[\"f64:10357270161024523488\",\"f64:3460198093814186274\"]],[\"invoke\",340,0,\"f64.mul\",[\"f64:11506848031881565957\",\"f64:11547514064126512393\"]],[\"invoke\",343,0,\"f64.mul\",[\"f64:8446730755803745435\",\"f64:640105622936255012\"]],[\"invoke\",344,0,\"f64.mul\",[\"f64:4578331547514318947\",\"f64:3937894457345907544\"]],[\"invoke\",345,0,\"f64.mul\",[\"f64:13839181621982597923\",\"f64:4426983905639375259\"]],[\"invoke\",346,0,\"f64.mul\",[\"f64:2931365221683549507\",\"f64:3687257801017498184\"]],[\"invoke\",347,0,\"f64.mul\",[\"f64:14180592859625794472\",\"f64:3043918530412552819\"]],[\"invoke\",350,0,\"f32.mul\",[\"f32:436207616\",\"f32:436207616\"]],[\"invoke\",352,0,\"f64.mul\",[\"f64:2186111271319845836\",\"f64:2186111271319845836\"]],[\"invoke\",353,0,\"f64.mul\",[\"f64:2186111271319845837\",\"f64:2186111271319845837\"]],[\"invoke\",356,0,\"f32.mul\",[\"f32:1602224127\",\"f32:1602224127\"]],[\"invoke\",357,0,\"f32.mul\",[\"f32:1602224128\",\"f32:1602224128\"]],[\"invoke\",358,0,\"f64.mul\",[\"f64:6913025428013711359\",\"f64:6913025428013711359\"]],[\"invoke\",359,0,\"f64.mul\",[\"f64:6913025428013711360\",\"f64:6913025428013711360\"]],[\"invoke\",362,0,\"f32.mul\",[\"f32:1065353217\",\"f32:1065353217\"]],[\"invoke\",364,0,\"f64.mul\",[\"f64:4607182418800017409\",\"f64:4607182418800017409\"]],[\"invoke\",365,0,\"f64.mul\",[\"f64:4607182418800017407\",\"f64:4607182418800017407\"]],[\"invoke\",368,0,\"f32.mul\",[\"f32:1065353217\",\"f32:1065353215\"]],[\"invoke\",369,0,\"f32.mul\",[\"f32:1065353218\",\"f32:1065353214\"]],[\"invoke\",370,0,\"f64.mul\",[\"f64:4607182418800017409\",\"f64:4607182418800017407\"]],[\"invoke\",371,0,\"f64.mul\",[\"f64:4607182418800017410\",\"f64:4607182418800017406\"]],[\"invoke\",375,0,\"f32.mul\",[\"f32:8388608\",\"f32:872415232\"]],[\"invoke\",376,0,\"f64.mul\",[\"f64:4503599627370496\",\"f64:4372995238176751616\"]],[\"invoke\",382,0,\"f32.div\",[\"f32:1066388847\",\"f32:1120403456\"]],[\"invoke\",383,0,\"f32.div\",[\"f32:1258294259\",\"f32:1262485497\"]],[\"invoke\",384,0,\"f32.div\",[\"f32:1199570944\",\"f32:754974720\"]],[\"invoke\",385,0,\"f32.div\",[\"f32:1072586677\",\"f32:2139095039\"]],[\"invoke\",386,0,\"f32.div\",[\"f32:1082130432\",\"f32:1077936128\"]],[\"invoke\",387,0,\"f64.div\",[\"f64:4607738418748954166\",\"f64:4636737291354636288\"]],[\"invoke\",388,0,\"f64.div\",[\"f64:4710766852517658624\",\"f64:4713017006285127680\"]],[\"invoke\",390,0,\"f64.div\",[\"f64:4611065853604003840\",\"f64:9218868437227405311\"]],[\"invoke\",391,0,\"f64.div\",[\"f64:4616189618054758400\",\"f64:4613937818241073152\"]],[\"invoke\",395,0,\"f32.div\",[\"f32:1249905654\",\"f32:1245708284\"]],[\"invoke\",396,0,\"f64.div\",[\"f64:4706263254500900864\",\"f64:4704009808640999424\"]],[\"invoke\",399,0,\"f32.div\",[\"f32:666187309\",\"f32:2138899896\"]],[\"invoke\",400,0,\"f32.div\",[\"f32:338737113\",\"f32:1637454009\"]],[\"invoke\",401,0,\"f32.div\",[\"f32:3351999420\",\"f32:401966635\"]],[\"invoke\",403,0,\"f32.div\",[\"f32:3564182439\",\"f32:397999726\"]],[\"invoke\",404,0,\"f64.div\",[\"f64:5269602717919885505\",\"f64:5615431061534361830\"]],[\"invoke\",405,0,\"f64.div\",[\"f64:1791703022234099881\",\"f64:230587289790163684\"]],[\"invoke\",406,0,\"f64.div\",[\"f64:15176390632865983384\",\"f64:7489729865403831125\"]],[\"invoke\",407,0,\"f64.div\",[\"f64:16945752639368638170\",\"f64:5718505335991307775\"]],[\"invoke\",408,0,\"f64.div\",[\"f64:16263708435887736913\",\"f64:6648866667391375614\"]],[\"invoke\",411,0,\"f32.div\",[\"f32:3798033061\",\"f32:2491443361\"]],[\"invoke\",412,0,\"f32.div\",[\"f32:686927199\",\"f32:1440960248\"]],[\"invoke\",414,0,\"f32.div\",[\"f32:642177221\",\"f32:2685135\"]],[\"invoke\",415,0,\"f32.div\",[\"f32:1824271560\",\"f32:1797890210\"]],[\"invoke\",416,0,\"f64.div\",[\"f64:4278321332874065\",\"f64:15464375907975098426\"]],[\"invoke\",417,0,\"f64.div\",[\"f64:9385779280320516508\",\"f64:2195352144435258723\"]],[\"invoke\",418,0,\"f64.div\",[\"f64:12019785500442997560\",\"f64:14033717547286793792\"]],[\"invoke\",419,0,\"f64.div\",[\"f64:14192622858179995755\",\"f64:1048270709368415171\"]],[\"invoke\",420,0,\"f64.div\",[\"f64:14895971708944847415\",\"f64:14082502105592202184\"]],[\"invoke\",424,0,\"f32.div\",[\"f32:3861505243\",\"f32:1298875600\"]],[\"invoke\",425,0,\"f32.div\",[\"f32:1387472197\",\"f32:4021087697\"]],[\"invoke\",426,0,\"f32.div\",[\"f32:4149014653\",\"f32:3294714580\"]],[\"invoke\",427,0,\"f32.div\",[\"f32:3987554477\",\"f32:3327836421\"]],[\"invoke\",428,0,\"f64.div\",[\"f64:10882983485852580843\",\"f64:1499380901194126188\"]],[\"invoke\",429,0,\"f64.div\",[\"f64:17353632673902705731\",\"f64:11343375610449883809\"]],[\"invoke\",430,0,\"f64.div\",[\"f64:10471640091267549911\",\"f64:4317563730789156718\"]],[\"invoke\",431,0,\"f64.div\",[\"f64:15262578458239868670\",\"f64:11184694400998603321\"]],[\"invoke\",435,0,\"f64.div\",[\"f64:16467910284400317286\",\"f64:14710955777971283471\"]],[\"invoke\",436,0,\"f64.div\",[\"f64:16290965053652735591\",\"f64:15317706837775392625\"]],[\"invoke\",437,0,\"f64.div\",[\"f64:5440366292977110369\",\"f64:18177315027663270891\"]],[\"invoke\",438,0,\"f64.div\",[\"f64:5586144947709395659\",\"f64:6532436425888624877\"]],[\"invoke\",439,0,\"f64.div\",[\"f64:17550005606375580620\",\"f64:6180045224129992598\"]],[\"invoke\",442,0,\"f64.div\",[\"f64:4611065853588275309\",\"f64:9218868437227405311\"]],[\"invoke\",443,0,\"f64.div\",[\"f64:58005932411648970\",\"f64:4662638783615926141\"]],[\"invoke\",445,0,\"f64.div\",[\"f64:12062544014359965409\",\"f64:16674780236028867992\"]],[\"invoke\",446,0,\"f64.div\",[\"f64:752499975442349235\",\"f64:5356690663768240614\"]],[\"invoke\",447,0,\"f64.div\",[\"f64:83041154348962762\",\"f64:13934889252531101931\"]],[\"invoke\",450,0,\"f32.div\",[\"f32:1817629909\",\"f32:1421132838\"]],[\"invoke\",451,0,\"f32.div\",[\"f32:1824604388\",\"f32:4105258014\"]],[\"invoke\",452,0,\"f32.div\",[\"f32:1747858929\",\"f32:1063784191\"]],[\"invoke\",453,0,\"f32.div\",[\"f32:3378374953\",\"f32:3497907368\"]],[\"invoke\",455,0,\"f64.div\",[\"f64:4885037015672297625\",\"f64:9954263091431620051\"]],[\"invoke\",456,0,\"f64.div\",[\"f64:4022347395424227722\",\"f64:11486191764643320419\"]],[\"invoke\",457,0,\"f64.div\",[\"f64:7623973190248181230\",\"f64:7481900282945497881\"]],[\"invoke\",458,0,\"f64.div\",[\"f64:14650287530633645126\",\"f64:8091500841285620267\"]],[\"invoke\",459,0,\"f64.div\",[\"f64:9910334119372230161\",\"f64:10921408834055405722\"]],[\"invoke\",462,0,\"f64.div\",[\"f64:4352764235752579571\",\"f64:4610853254537913145\"]],[\"invoke\",463,0,\"f64.div\",[\"f64:4148344307949876337\",\"f64:13642564096968604240\"]],[\"invoke\",464,0,\"f64.div\",[\"f64:4425554483259831683\",\"f64:4103199251532205583\"]],[\"invoke\",466,0,\"f64.div\",[\"f64:4558988817252519457\",\"f64:14066629987516208597\"]],[\"invoke\",469,0,\"f32.div\",[\"f32:8388608\",\"f32:8388607\"]],[\"invoke\",470,0,\"f32.div\",[\"f32:8388607\",\"f32:8388608\"]],[\"invoke\",471,0,\"f64.div\",[\"f64:4503599627370496\",\"f64:4503599627370495\"]],[\"invoke\",472,0,\"f64.div\",[\"f64:4503599627370495\",\"f64:4503599627370496\"]],[\"invoke\",475,0,\"f32.div\",[\"f32:880803839\",\"f32:2139095039\"]],[\"invoke\",476,0,\"f32.div\",[\"f32:880803840\",\"f32:2139095039\"]],[\"invoke\",478,0,\"f64.div\",[\"f64:4377498837804122112\",\"f64:9218868437227405311\"]],[\"invoke\",481,0,\"f32.div\",[\"f32:1065353216\",\"f32:2097152\"]],[\"invoke\",482,0,\"f32.div\",[\"f32:1065353216\",\"f32:2097153\"]],[\"invoke\",483,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:1125899906842624\"]],[\"invoke\",484,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:1125899906842625\"]],[\"invoke\",487,0,\"f32.div\",[\"f32:1065353216\",\"f32:2122317825\"]],[\"invoke\",488,0,\"f32.div\",[\"f32:1065353216\",\"f32:2122317824\"]],[\"invoke\",489,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:9209861237972664321\"]],[\"invoke\",500,0,\"f32.div\",[\"f32:1065353216\",\"f32:1077936128\"]],[\"invoke\",501,0,\"f32.div\",[\"f32:1077936128\",\"f32:1091567616\"]],[\"invoke\",502,0,\"f32.div\",[\"f32:1091567616\",\"f32:1104674816\"]],[\"invoke\",503,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:4613937818241073152\"]],[\"invoke\",504,0,\"f64.div\",[\"f64:4613937818241073152\",\"f64:4621256167635550208\"]],[\"invoke\",505,0,\"f64.div\",[\"f64:4621256167635550208\",\"f64:4628293042053316608\"]],[\"invoke\",508,0,\"f32.div\",[\"f32:1065353217\",\"f32:1065353215\"]],[\"invoke\",510,0,\"f32.div\",[\"f32:1065353216\",\"f32:1065353215\"]],[\"invoke\",511,0,\"f32.div\",[\"f32:1065353216\",\"f32:1065353217\"]],[\"invoke\",512,0,\"f64.div\",[\"f64:4607182418800017409\",\"f64:4607182418800017407\"]],[\"invoke\",513,0,\"f64.div\",[\"f64:4607182418800017407\",\"f64:4607182418800017409\"]],[\"invoke\",514,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:4607182418800017407\"]],[\"invoke\",515,0,\"f64.div\",[\"f64:4607182418800017408\",\"f64:4607182418800017409\"]],[\"invoke\",519,0,\"f32.sqrt\",[\"f32:1126891520\"]],[\"invoke\",521,0,\"f64.sqrt\",[\"f64:4640220544191430656\"]],[\"invoke\",522,0,\"f64.sqrt\",[\"f64:4505170691092029701\"]],[\"invoke\",525,0,\"f64.sqrt\",[\"f64:3868634135368364633\"]],[\"invoke\",526,0,\"f64.sqrt\",[\"f64:6130334638238385213\"]],[\"invoke\",527,0,\"f64.sqrt\",[\"f64:6420749722515481850\"]],[\"invoke\",528,0,\"f64.sqrt\",[\"f64:4441983858611369811\"]],[\"invoke\",529,0,\"f64.sqrt\",[\"f64:2943222801950574478\"]],[\"invoke\",533,0,\"f64.sqrt\",[\"f64:4607182418800017407\"]],[\"invoke\",537,0,\"f32.sqrt\",[\"f32:1911349112\"]],[\"invoke\",538,0,\"f32.sqrt\",[\"f32:1033984731\"]],[\"invoke\",539,0,\"f32.sqrt\",[\"f32:471548520\"]],[\"invoke\",540,0,\"f32.sqrt\",[\"f32:980180519\"]],[\"invoke\",541,0,\"f64.sqrt\",[\"f64:447478826231748356\"]],[\"invoke\",542,0,\"f64.sqrt\",[\"f64:7882765141420635228\"]],[\"invoke\",543,0,\"f64.sqrt\",[\"f64:6345006020483303032\"]],[\"invoke\",545,0,\"f64.sqrt\",[\"f64:9108179429173493573\"]],[\"invoke\",548,0,\"f32.sqrt\",[\"f32:1293112087\"]],[\"invoke\",549,0,\"f32.sqrt\",[\"f32:118173697\"]],[\"invoke\",550,0,\"f32.sqrt\",[\"f32:941555112\"]],[\"invoke\",551,0,\"f32.sqrt\",[\"f32:60323222\"]],[\"invoke\",552,0,\"f32.sqrt\",[\"f32:40220718\"]],[\"invoke\",553,0,\"f64.sqrt\",[\"f64:7741365502393472048\"]],[\"invoke\",554,0,\"f64.sqrt\",[\"f64:1175297548666390979\"]],[\"invoke\",556,0,\"f64.sqrt\",[\"f64:3521792205891300764\"]],[\"invoke\",557,0,\"f64.sqrt\",[\"f64:8798159938601760820\"]],[\"invoke\",560,0,\"f32.sqrt\",[\"f32:2058533950\"]],[\"invoke\",561,0,\"f32.sqrt\",[\"f32:1194962978\"]],[\"invoke\",562,0,\"f32.sqrt\",[\"f32:1062209384\"]],[\"invoke\",563,0,\"f32.sqrt\",[\"f32:339551808\"]],[\"invoke\",564,0,\"f32.sqrt\",[\"f32:279876202\"]],[\"invoke\",566,0,\"f64.sqrt\",[\"f64:2893298197477532149\"]],[\"invoke\",567,0,\"f64.sqrt\",[\"f64:8954101765007123282\"]],[\"invoke\",568,0,\"f64.sqrt\",[\"f64:4405641787023763989\"]],[\"invoke\",569,0,\"f64.sqrt\",[\"f64:2394824404681191749\"]],[\"invoke\",572,0,\"f64.sqrt\",[\"f64:9494538992465685200\"]],[\"invoke\",573,0,\"f64.sqrt\",[\"f64:5074882158241187075\"]],[\"invoke\",574,0,\"f64.sqrt\",[\"f64:1187437724299488295\"]],[\"invoke\",576,0,\"f64.sqrt\",[\"f64:7161993531047854177\"]],[\"invoke\",579,0,\"f32.sqrt\",[\"f32:1065353217\"]],[\"invoke\",580,0,\"f32.sqrt\",[\"f32:1065353218\"]],[\"invoke\",581,0,\"f64.sqrt\",[\"f64:4607182418800017409\"]],[\"invoke\",582,0,\"f64.sqrt\",[\"f64:4607182418800017410\"]],[\"invoke\",585,0,\"f32.sqrt\",[\"f32:1065353214\"]],[\"invoke\",586,0,\"f32.sqrt\",[\"f32:1065353213\"]],[\"invoke\",587,0,\"f64.sqrt\",[\"f64:4607182418800017406\"]],[\"invoke\",591,0,\"f32.sqrt\",[\"f32:1048575999\"]],[\"invoke\",592,0,\"f32.sqrt\",[\"f32:1048576000\"]],[\"invoke\",593,0,\"f32.sqrt\",[\"f32:1048576001\"]],[\"invoke\",594,0,\"f32.sqrt\",[\"f32:1048576002\"]],[\"invoke\",595,0,\"f64.sqrt\",[\"f64:4598175219545276415\"]],[\"invoke\",596,0,\"f64.sqrt\",[\"f64:4598175219545276416\"]],[\"invoke\",597,0,\"f64.sqrt\",[\"f64:4598175219545276417\"]],[\"invoke\",602,0,\"f32.sqrt\",[\"f32:1383964906\"]],[\"invoke\",603,0,\"f64.sqrt\",[\"f64:4778235767454362395\"]],[\"invoke\",607,0,\"f32.sqrt\",[\"f32:1344155865\"]],[\"invoke\",608,0,\"f32.sqrt\",[\"f32:1496014503\"]],[\"invoke\",609,0,\"f32.sqrt\",[\"f32:1437792278\"]],[\"invoke\",610,0,\"f32.sqrt\",[\"f32:1318267910\"]],[\"invoke\",611,0,\"f64.sqrt\",[\"f64:4756863450987102208\"]],[\"invoke\",612,0,\"f64.sqrt\",[\"f64:4838391936821527880\"]],[\"invoke\",614,0,\"f64.sqrt\",[\"f64:4742964961037254656\"]],[\"invoke\",618,0,\"f32.sqrt\",[\"f32:1057229822\"]],[\"invoke\",619,0,\"f32.sqrt\",[\"f32:1057013196\"]],[\"invoke\",620,0,\"f64.sqrt\",[\"f64:4602821204854702080\"]],[\"invoke\",621,0,\"f64.sqrt\",[\"f64:4602704904656519168\"]],[\"invoke\",625,0,\"f32.sqrt\",[\"f32:1091567616\"]],[\"invoke\",626,0,\"f32.sqrt\",[\"f32:1124663296\"]],[\"invoke\",628,0,\"f32.sqrt\",[\"f32:1148846080\"]],[\"invoke\",629,0,\"f64.sqrt\",[\"f64:4621256167635550208\"]],[\"invoke\",630,0,\"f64.sqrt\",[\"f64:4639024275540410368\"]],[\"invoke\",631,0,\"f64.sqrt\",[\"f64:4610667174614947795\"]],[\"invoke\",632,0,\"f64.sqrt\",[\"f64:4652007308841189376\"]],[\"invoke\",656,0,\"f32.ceil\",[\"f32:1065353215\"]],[\"invoke\",657,0,\"f32.ceil\",[\"f32:1065353217\"]],[\"invoke\",659,0,\"f64.ceil\",[\"f64:4607182418800017409\"]],[\"invoke\",662,0,\"f32.ceil\",[\"f32:1258291199\"]],[\"invoke\",663,0,\"f32.ceil\",[\"f32:3405774847\"]],[\"invoke\",664,0,\"f64.ceil\",[\"f64:4841369599423283199\"]],[\"invoke\",665,0,\"f64.ceil\",[\"f64:14064741636278059007\"]],[\"invoke\",669,0,\"f32.ceil\",[\"f32:1266679807\"]],[\"invoke\",670,0,\"f32.ceil\",[\"f32:3414163455\"]],[\"invoke\",671,0,\"f64.ceil\",[\"f64:4845873199050653695\"]],[\"invoke\",675,0,\"f32.floor\",[\"f32:3212836863\"]],[\"invoke\",676,0,\"f32.floor\",[\"f32:3212836865\"]],[\"invoke\",677,0,\"f64.floor\",[\"f64:13830554455654793215\"]],[\"invoke\",678,0,\"f64.floor\",[\"f64:13830554455654793217\"]],[\"invoke\",681,0,\"f32.floor\",[\"f32:3405774847\"]],[\"invoke\",682,0,\"f32.floor\",[\"f32:1258291199\"]],[\"invoke\",683,0,\"f64.floor\",[\"f64:14064741636278059007\"]],[\"invoke\",688,0,\"f32.floor\",[\"f32:1202524032\"]],[\"invoke\",689,0,\"f64.floor\",[\"f64:4680825439885721600\"]],[\"invoke\",692,0,\"f32.trunc\",[\"f32:3405774847\"]],[\"invoke\",693,0,\"f32.trunc\",[\"f32:1258291199\"]],[\"invoke\",694,0,\"f64.trunc\",[\"f64:14064741636278059007\"]],[\"invoke\",695,0,\"f64.trunc\",[\"f64:4841369599423283199\"]],[\"invoke\",700,0,\"f32.nearest\",[\"f32:1258291201\"]],[\"invoke\",701,0,\"f32.nearest\",[\"f32:1258291202\"]],[\"invoke\",703,0,\"f32.nearest\",[\"f32:1468006399\"]],[\"invoke\",704,0,\"f64.nearest\",[\"f64:4841369599423283201\"]],[\"invoke\",705,0,\"f64.nearest\",[\"f64:4841369599423283202\"]],[\"invoke\",706,0,\"f64.nearest\",[\"f64:4602678819172646911\"]],[\"invoke\",707,0,\"f64.nearest\",[\"f64:5084563979301289983\"]],[\"invoke\",711,0,\"f32.nearest\",[\"f32:1083179008\"]],[\"invoke\",712,0,\"f32.nearest\",[\"f32:3230662656\"]],[\"invoke\",714,0,\"f64.nearest\",[\"f64:4616752568008179712\"]],[\"invoke\",715,0,\"f64.nearest\",[\"f64:13840124604862955520\"]],[\"invoke\",716,0,\"f64.nearest\",[\"f64:13838435755002691584\"]],[\"invoke\",719,0,\"f32.nearest\",[\"f32:3405774847\"]],[\"invoke\",720,0,\"f32.nearest\",[\"f32:1258291199\"]],[\"invoke\",721,0,\"f64.nearest\",[\"f64:14064741636278059007\"]],[\"invoke\",722,0,\"f64.nearest\",[\"f64:4841369599423283199\"]]]"; diff --git a/tests/corpus/webassembly-spec-float/main.mjs b/tests/corpus/webassembly-spec-float/main.mjs new file mode 100644 index 000000000..289dad212 --- /dev/null +++ b/tests/corpus/webassembly-spec-float/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (9 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-spec-imports/data.mjs b/tests/corpus/webassembly-spec-imports/data.mjs new file mode 100644 index 000000000..5ecccab26 --- /dev/null +++ b/tests/corpus/webassembly-spec-imports/data.mjs @@ -0,0 +1,137 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * imports.wast, table.wast, names.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABHgdgAABgAX8AYAF9AGAAAX9gAAF9YAF/AX9gAX4BfgMIBwABAgMEBQYECAJwAApwAQoUBQMBAAIGFAN/AEE3C30AQwAAMEILfgFCwgALB60BDQRmdW5jAAAIZnVuYy1pMzIAAQhmdW5jLWYzMgACCWZ1bmMtPmkzMgADCWZ1bmMtPmYzMgAEDWZ1bmMtaTMyLT5pMzIABQ1mdW5jLWk2NC0+aTY0AAYKZ2xvYmFsLWkzMgMACmdsb2JhbC1mMzIDAQ5nbG9iYWwtbXV0LWk2NAMCDHRhYmxlLTEwLWluZgEAC3RhYmxlLTEwLTIwAQEMbWVtb3J5LTItaW5mAgAKIQcCAAsCAAsCAAsEAEEWCwcAQwAAMEELBAAgAAsEACAACw==", + "AGFzbQEAAAABJAhgAX8AYAF+AGABfQBgAXwAYAF/AGACf30AYAJ8fABgAX4BfgKDAxIIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTY0AAEIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTY0AAEIc3BlY3Rlc3QJcHJpbnRfZjMyAAIIc3BlY3Rlc3QJcHJpbnRfZjY0AAMIc3BlY3Rlc3QNcHJpbnRfaTMyX2YzMgAFCHNwZWN0ZXN0DXByaW50X2Y2NF9mNjQABghzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9mNjQAAwR0ZXN0DWZ1bmMtaTY0LT5pNjQABwhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIABAhzcGVjdGVzdAlwcmludF9pMzIABAMDAgABBAUBcAECAgczCAJwMQALAnAyAAwCcDMADQJwNAANAnA1AA4CcDYADwdwcmludDMyABIHcHJpbnQ2NAATCQgBAEEACwICBQpoAiwBAX0gALIhASAAEAAgAEEBakMAAChCEAYgABACIAAQCCABEAQgAEEAEQAACzkBAXwgABAKuSEBIAAQASABRAAAAAAAAPA/oEQAAAAAAIBKQBAHIAAQAyABEAUgARAJIAFBAREDAAs=", + "AGFzbQEAAAABBQFgAX8AAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAAcNAQlwcmludF9pMzIAAQoIAQYAIAAQAAs=", + "AGFzbQEAAAABCwJgAX8AYAJ/fwF/AhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQcNAQlwcmludF9pMzIAAQoJAQcAIAAgAWoL", + "AGFzbQEAAAABBAFgAAACDQEEdGVzdARmdW5jAAA=", + "AGFzbQEAAAABBQFgAX8AAhEBBHRlc3QIZnVuYy1pMzIAAA==", + "AGFzbQEAAAABBQFgAX0AAhEBBHRlc3QIZnVuYy1mMzIAAA==", + "AGFzbQEAAAABBQFgAAF/AhIBBHRlc3QJZnVuYy0+aTMyAAA=", + "AGFzbQEAAAABBQFgAAF9AhIBBHRlc3QJZnVuYy0+ZjMyAAA=", + "AGFzbQEAAAABBgFgAX8BfwIWAQR0ZXN0DWZ1bmMtaTMyLT5pMzIAAA==", + "AGFzbQEAAAABBgFgAX4BfgIWAQR0ZXN0DWZ1bmMtaTY0LT5pNjQAAA==", + "AGFzbQEAAAABBAFgAAACEAEEdGVzdAd1bmtub3duAAA=", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QHdW5rbm93bgAA", + "AGFzbQEAAAABBQFgAX8AAg0BBHRlc3QEZnVuYwAA", + "AGFzbQEAAAABBQFgAAF/Ag0BBHRlc3QEZnVuYwAA", + "AGFzbQEAAAABBgFgAX8BfwINAQR0ZXN0BGZ1bmMAAA==", + "AGFzbQEAAAABBAFgAAACEQEEdGVzdAhmdW5jLWkzMgAA", + "AGFzbQEAAAABBQFgAAF/AhEBBHRlc3QIZnVuYy1pMzIAAA==", + "AGFzbQEAAAABBQFgAX0AAhEBBHRlc3QIZnVuYy1pMzIAAA==", + "AGFzbQEAAAABBQFgAX4AAhEBBHRlc3QIZnVuYy1pMzIAAA==", + "AGFzbQEAAAABBgFgAX8BfwIRAQR0ZXN0CGZ1bmMtaTMyAAA=", + "AGFzbQEAAAABBAFgAAACEgEEdGVzdAlmdW5jLT5pMzIAAA==", + "AGFzbQEAAAABBQFgAX8AAhIBBHRlc3QJZnVuYy0+aTMyAAA=", + "AGFzbQEAAAABBQFgAAF9AhIBBHRlc3QJZnVuYy0+aTMyAAA=", + "AGFzbQEAAAABBQFgAAF+AhIBBHRlc3QJZnVuYy0+aTMyAAA=", + "AGFzbQEAAAABBgFgAX8BfwISAQR0ZXN0CWZ1bmMtPmkzMgAA", + "AGFzbQEAAAABBAFgAAACFgEEdGVzdA1mdW5jLWkzMi0+aTMyAAA=", + "AGFzbQEAAAABBQFgAX8AAhYBBHRlc3QNZnVuYy1pMzItPmkzMgAA", + "AGFzbQEAAAABBQFgAAF/AhYBBHRlc3QNZnVuYy1pMzItPmkzMgAA", + "AGFzbQEAAAABBQFgAAF/AhMBBHRlc3QKZ2xvYmFsLWkzMgAA", + "AGFzbQEAAAABBAFgAAACFQEEdGVzdAx0YWJsZS0xMC1pbmYAAA==", + "AGFzbQEAAAABBAFgAAACFQEEdGVzdAxtZW1vcnktMi1pbmYAAA==", + "AGFzbQEAAAABBAFgAAACFwEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgAA", + "AGFzbQEAAAABBAFgAAACEgEIc3BlY3Rlc3QFdGFibGUAAA==", + "AGFzbQEAAAABBAFgAAACEwEIc3BlY3Rlc3QGbWVtb3J5AAA=", + "AGFzbQEAAAABEQRgAAF/YAABfmAAAX1gAAF8AqIBBwhzcGVjdGVzdApnbG9iYWxfaTMyA38ACHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwAIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdApnbG9iYWxfaTMyA38ACHNwZWN0ZXN0Cmdsb2JhbF9pNjQDfgAIc3BlY3Rlc3QKZ2xvYmFsX2YzMgN9AAhzcGVjdGVzdApnbG9iYWxfZjY0A3wAAwgHAAAAAAECAwc5BwVnZXQtMAAABWdldC0xAAEFZ2V0LXgAAgVnZXQteQADBWdldC00AAQFZ2V0LTUABQVnZXQtNgAGCiQHBAAjAAsEACMBCwQAIwILBAAjAwsEACMECwQAIwULBAAjBgs=", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38A", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA30A", + "AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN+AQ==", + "AGFzbQEAAAACEQEEdGVzdAd1bmtub3duA38A", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QHdW5rbm93bgN/AA==", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA34A", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA30A", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA3wA", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38B", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA38A", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA34A", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA3wA", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA30B", + "AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN/AQ==", + "AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN9AQ==", + "AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN8AQ==", + "AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN+AA==", + "AGFzbQEAAAACDgEEdGVzdARmdW5jA38A", + "AGFzbQEAAAACFgEEdGVzdAx0YWJsZS0xMC1pbmYDfwA=", + "AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYDfwA=", + "AGFzbQEAAAACFwEIc3BlY3Rlc3QJcHJpbnRfaTMyA38A", + "AGFzbQEAAAACEwEIc3BlY3Rlc3QFdGFibGUDfwA=", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5A38A", + "AGFzbQEAAAABCgJgAAF/YAF/AX8CFQEIc3BlY3Rlc3QFdGFibGUBcAEKFAMEAwEAAAcIAQRjYWxsAAAJCAEAQQELAgECChMDBwAgABEAAAsEAEELCwQAQRYL", + "AGFzbQEAAAACJwIIc3BlY3Rlc3QFdGFibGUBcAAACHNwZWN0ZXN0BXRhYmxlAXAAAAQHAnAACnAACg==", + "AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAK", + "AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAF", + "AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAA", + "AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAo=", + "AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAU=", + "AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAA=", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoU", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQUU", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQAU", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoZ", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQUZ", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQAZ", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAK", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAF", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAA", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKFA==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEFFA==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAFA==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKGQ==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEFGQ==", + "AGFzbQEAAAACEgEEdGVzdAd1bmtub3duAXAACg==", + "AGFzbQEAAAACFgEIc3BlY3Rlc3QHdW5rbm93bgFwAAo=", + "AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAM", + "AGFzbQEAAAACGAEEdGVzdAx0YWJsZS0xMC1pbmYBcAEKFA==", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQwU", + "AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoS", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAM", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKDw==", + "AGFzbQEAAAACDwEEdGVzdARmdW5jAXAACg==", + "AGFzbQEAAAACFQEEdGVzdApnbG9iYWwtaTMyAXAACg==", + "AGFzbQEAAAACFwEEdGVzdAxtZW1vcnktMi1pbmYBcAAK", + "AGFzbQEAAAACGAEIc3BlY3Rlc3QJcHJpbnRfaTMyAXAACg==", + "AGFzbQEAAAABBgFgAX8BfwIVAQhzcGVjdGVzdAZtZW1vcnkCAQECAwIBAAcIAQRsb2FkAAAKCQEHACAAKAIACwsHAQBBCgsBEA==", + "AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAI=", + "AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAE=", + "AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAA=", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAB", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAA", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAg==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAg==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAw==", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAw==", + "AGFzbQEAAAACEQEEdGVzdAd1bmtub3duAgAB", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QHdW5rbm93bgIAAQ==", + "AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAM=", + "AGFzbQEAAAACFwEEdGVzdAxtZW1vcnktMi1pbmYCAQID", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAC", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAQ==", + "AGFzbQEAAAACEgEEdGVzdAhmdW5jLWkzMgIAAQ==", + "AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyAgAB", + "AGFzbQEAAAACFgEEdGVzdAx0YWJsZS0xMC1pbmYCAAE=", + "AGFzbQEAAAACFwEIc3BlY3Rlc3QJcHJpbnRfaTMyAgAB", + "AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgIAAQ==", + "AGFzbQEAAAACEwEIc3BlY3Rlc3QFdGFibGUCAAE=", + "AGFzbQEAAAABBgFgAX8BfwIVAQhzcGVjdGVzdAZtZW1vcnkCAQADAwIBAAcIAQRncm93AAAKCAEGACAAQAAL", + "AGFzbQEAAAA=", + "AGFzbQEAAAABKQpgAABgAX8AYAJ/fwBgAX4AYAF9AGABfABgAAF/YAABfmAAAX1gAAF8AugCEAhub3Qgd2FzbQpvdmVybG9hZGVkAAAIbm90IHdhc20Kb3ZlcmxvYWRlZAABCG5vdCB3YXNtCm92ZXJsb2FkZWQAAghub3Qgd2FzbQpvdmVybG9hZGVkAAMIbm90IHdhc20Kb3ZlcmxvYWRlZAAECG5vdCB3YXNtCm92ZXJsb2FkZWQABQhub3Qgd2FzbQpvdmVybG9hZGVkAAYIbm90IHdhc20Kb3ZlcmxvYWRlZAAHCG5vdCB3YXNtCm92ZXJsb2FkZWQACAhub3Qgd2FzbQpvdmVybG9hZGVkAAkIbm90IHdhc20Kb3ZlcmxvYWRlZAN/AAhub3Qgd2FzbQpvdmVybG9hZGVkA34ACG5vdCB3YXNtCm92ZXJsb2FkZWQDfQAIbm90IHdhc20Kb3ZlcmxvYWRlZAN8AAhub3Qgd2FzbQpvdmVybG9hZGVkAXAAAAhub3Qgd2FzbQpvdmVybG9hZGVkAgAA", + "AGFzbQEAAAAEBAFwAAA=", + "AGFzbQEAAAAEBAFwAAE=", + "AGFzbQEAAAAEBQFwAQAA", + "AGFzbQEAAAAEBQFwAQAB", + "AGFzbQEAAAAEBgFwAQGAAg==", + "AGFzbQEAAAAEBwFwAQCAgAQ=", + "AGFzbQEAAAAECQFwAQD/////Dw==", + "AGFzbQEAAAAEBwJwAABwAAA=", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAABAQBcAAA", + "AGFzbQEAAAABBQFgAAF/AwIBAAcHAQNmb28AAAoGAQQAQQAL", + "AGFzbQEAAAABBQFgAAF/AwIBAAcHAQNmb28AAAoGAQQAQQEL", + "AGFzbQEAAAABBQFgAAF/A+ED3wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAerId8DAAAAATAAAQItMAACAV8AAwEkAAQBQAAFIX4hQCMkJV4mKigpXytgLT17fXxbXVw6IjsnPD4/LC4vIAAGA05hTgAHCEluZmluaXR5AAgCaWYACQZtYWxsb2MACgdfbWFsbG9jAAsIX19tYWxsb2MADAFhAA0BQQAOA++7vwAPAsOFABADQcyKABED4oSrABID76yDABMEZu+sgQAUA2ZmaQAVEAABAgMEBQYHCAkKCwwNDg8AFhAQERITFBUWFxgZGhscHR4fABcCIH8AGCDCgMKBwoLCg8KEwoXChsKHwojCicKKwovCjMKNwo7CjwAZIMKQwpHCksKTwpTClcKWwpfCmMKZwprCm8Kcwp3CnsKfABoY77+w77+x77+y77+z77+077+177+277+3ABsY77+477+577+677+777+877+977++77+/ABww4pCA4pCB4pCC4pCD4pCE4pCF4pCG4pCH4pCI4pCJ4pCK4pCL4pCM4pCN4pCO4pCPAB0w4pCQ4pCR4pCS4pCT4pCU4pCV4pCW4pCX4pCY4pCZ4pCa4pCb4pCc4pCd4pCe4pCfAB4G4pCg4pChAB8q77+w77+x77+y77+z77+077+177+277+377+477+577+677+777+877+9ACAD4oCNACED4oCMACICzY8AIwPigaAAJAPitb8AJQTwkYG/ACYD4aCOACcW77+v4oCLwqDCreKBoOGagOKAruKArQAoJ+KAjuKAj+KAkeKAqOKAqeKAquKAq+KArOKAr+KBpuKBp+KBqOKBqQApEuKBquKBq+KBrOKBreKBruKBrwAqDOKBoeKBouKBo+KBpAArDPCQgIDzn7+/9I+/vwAsgQJazI/NhsyGzZvNjMy0zZjNns2HzKvMpcyqzZPNiM2UzY7Ml8yezLrMr8yxzJ7MmcyxzJzMlsygYc2XzajMjsyEzIbNl8y/zaHNn82AzLbNgcylzLDMs8ytzZnMssyxzLnMnc2OzLxszYTNisyazZfNps2EzavMh82BzLbMt82JzKnMucyrzJ3Nls2FzJnMssy8zYfNms2NzK7NjsylzYXMnmfNg8yQzIXNrsyUzJDMjsyCzI/Mvs2KzI3Ni82KzafMgcyGzabNnsy2zZXNlM2azKlvzYvMlM2QzarNqcyhzY/MosynzYHMq8yZzKTMrs2WzZnNk8y6zJzMqcy8zJjMoAAtDOGFn+GFoOOFpO++oAAuA++4gAAvA++4hAAwBPOghIAAMQTzoIevADICzIgAMwEKADQD4pCkADUD4oCoADYBDQA3Ag0KADgCCg0AOQEeADoBCwA7AQwAPALChQA9A+KAqQA+A+KApgA/A+KPjgBAAsKLAEECwowAQgLCjQBDA+KGtQBEA+KGqQBFA+KMpABGA+KktgBHA+KGsgBIA+KuqABJA+KusABKA++/vQBLA++3kABMA++3kQBNA++3kgBOA++3kwBPA++3lABQA++3lQBRA++3lgBSA++3lwBTA++3mABUA++3mQBVA++3mgBWA++3mwBXA++3nABYA++3nQBZA++3ngBaA++3nwBbA++3oABcA++3oQBdA++3ogBeA++3owBfA++3pABgA++3pQBhA++3pgBiA++3pwBjA++3qABkA++3qQBlA++3qgBmA++3qwBnA++3rABoA++3rQBpA++3rgBqA++3rwBrA++/vgBsA++/vwBtBPCfv74AbgTwn7+/AG8E8K+/vgBwBPCvv78AcQTwv7++AHIE8L+/vwBzBPGPv74AdATxj7+/AHUE8Z+/vgB2BPGfv78AdwTxr7++AHgE8a+/vwB5BPG/v74AegTxv7+/AHsE8o+/vgB8BPKPv78AfQTyn7++AH4E8p+/vwB/BPKvv74AgAEE8q+/vwCBAQTyv7++AIIBBPK/v78AgwEE84+/vgCEAQTzj7+/AIUBBPOfv74AhgEE85+/vwCHAQTzr7++AIgBBPOvv78AiQEE87+/vgCKAQTzv7+/AIsBBPSPv74AjAEE9I+/vwCNAQnMiOKAvcyIzIkAjgEDYWJjAI8BBuKArWFiYwCQAQbigK5jYmEAkQEJ4oCtYWJj4oCuAJIBCeKArmNiYeKArQCTAQTwnZGoAJQBBPCdkLQAlQEE8J2YiACWAQTwnZi8AJcBBPCdkIAAmAEE8J2TkACZAQTwnZWsAJoBBPCdl5QAmwEE8J2SnACcAQTwnZSEAJ0BBPCdlLgAngEE8J2WoACfAQTwnZmwAKABA+G0gAChAQPhtKwAogED4pK2AKMBA++8oQCkAQTwn4SQAKUBBPCfhLAApgEE86CBgQCnAQZVKzAwNDEAqAEEQeKAiwCpAQLQkACqAQPqmZYAqwED4re8AKwBA+K3tgCtAQPisa8ArgEE8J+FkACvAQTwn4WwALABA+KwrQCxAQTwkJCCALIBBPCQkIgAswEE8JCSsAC0AQLDgAC1AQLDgQC2AQLDggC3AQLDgwC4AQLDhAC5AQLEgAC6AQLEggC7AQLEhAC8AQLHjQC9AQLHngC+AQLHoAC/AQLHugDAAQLIgADBAQLIggDCAQLIpgDDAQLIugDEAQLTkADFAQLTkgDGAQLfigDHAQPgoKEAyAED4KCiAMkBA+CgowDKAQPgoKQAywED4KClAMwBA+CkhADNAQPgpIUAzgED4KWyAM8BA+CmhQDQAQPgqIUA0QED4KqFANIBA+CshQDTAQPgroUA1AED4LCFANUBA+CyhQDWAQPgtIUA1wED4LiwANgBA+C6sADZAQPgvIEA2gED4L2oANsBA+C+uADcAQPhgKEA3QED4YCiAN4BA+GCnADfAQPhhaEA4AED4YqgAOEBA+GLkADiAQPhjqAA4wED4ZCKAOQBA+GWswDlAQPhmqgA5gED4ZqqAOcBA+GbhgDoAQPhnIAA6QED4ZygAOoBA+GdgADrAQPhnaAA7AED4aCgAO0BA+GihwDuAQPhpKAA7wED4aWjAPABA+GolQDxAQPhqYsA8gED4amhAPMBA+GugwD0AQPhr4AA9QED4a+BAPYBA+GwowD3AQPhuIAA+AED4bqgAPkBA+G6ogD6AQPhuqQA+wED4bqmAPwBA+G6qAD9AQPhuqoA/gED4bqsAP8BA+G6rgCAAgPhurAAgQID4bqyAIICA+G6tACDAgPhurYAhAID44GCAIUCA+OCogCGAgPjhJoAhwID44WPAIgCA+OIjgCJAgPjiI8AigID44iQAIsCA+OIkQCMAgPjiJIAjQID44iTAI4CA+OIlACPAgPjiJUAkAID44iWAJECA+OIlwCSAgPjiJgAkwID44iZAJQCA+OImgCVAgPjiJsAlgID44muAJcCA+OJrwCYAgPjibAAmQID44mxAJoCA+OJsgCbAgPjibMAnAID44m0AJ0CA+OJtQCeAgPjibYAnwID44m3AKACA+OJuAChAgPjibkAogID44m6AKMCA+OJuwCkAgPji5AApQID6oCKAKYCA+qTrgCnAgPqlYkAqAID6pqgAKkCA+qggACqAgPqoKMAqwID6qGdAKwCA+qiggCtAgPqo6oArgID6qSiAK8CA+qlhgCwAgPqpoQAsQID6qiAALICA++9sQCzAgPvv4IAtAIE8JCAgAC1AgTwkIqAALYCBPCQiqAAtwIE8JCMgAC4AgTwkI6gALkCBPCQkpYAugIE8JCUgAC7AgTwkJ2AALwCBPCQoIAAvQIE8JCkoAC+AgTwkKaAAL8CBPCQpqAAwAIE8JCogADBAgTwkKyAAMICBPCQsIAAwwIE8JCwgQDEAgTwkLKAAMUCBPCRgIUAxgIE8JGCgwDHAgTwkYSnAMgCBPCRhZAAyQIE8JGGgwDKAgTwkYiAAMsCBPCRioAAzAIE8JGKsADNAgTwkYyFAM4CBPCRjbAAzwIE8JGQgADQAgTwkZKBANECBPCRloAA0gIE8JGYgADTAgTwkZqAANQCBPCRnJIA1QIE8JGcoADWAgTwkaKhANcCBPCRq5UA2AIE8JGwgADZAgTwkbKPANoCBPCRsq8A2wIE8JKAgADcAgTwlqeVAN0CBPCWqYYA3gIE8JarpwDfAgTwlr2UAOACBPCbsYEA4QIE8JuxpADiAgTwnqCjAOMCBPCfh6YA5AID4rGtAOUCAs6bAOYCA+KxsADnAgLCqgDoAgPiiIAA6QID4oKzAOoCBPCQpIAA6wID4rKAAOwCBPCQjLAA7QICzoYA7gICzpEA7wID4byIAPACA+G8iQDxAgPhvIoA8gID4byLAPMCA+G8jAD0AgPhvI0A9QID4byOAPYCA+G8jwD3AgPhvogA+AID4b6JAPkCA+G+igD6AgPhvosA+wID4b6MAPwCA+G+jQD9AgPhvo4A/gID4b6PAP8CA+G+uACAAwPhvrkAgQMD4b66AIIDA+G+uwCDAwPhvrwAhAME8J2aqACFAwTwnZuiAIYDBPCdnJwAhwME8J2dlgCIAwTwnZ6QAIkDA+KNtgCKAwPijboAiwMD4qmcAIwDA+GXhQCNAwPhjqoAjgOcASnLusu88JSXj/CdhbTwnYW28J2FuPCdhbrigb7igo7inaninavin6/vtL/vuLbvuZrvvInvvaDzoICp4p2z4p214p+n4p+p4p+r4p+t4qaI4qaK4qaW4rij4ril77iY77i477i677i877i+77mA77mC77mE77mI77mc77me77y9772d772j86CBnfOggb3Cu+KAmeKAneKAuuKdrwCPA5wBKMu5y7vwlJeO8J2Fs/CdhbXwnYW38J2FueKBveKCjeKdqOKdquKfru+0vu+4te+5me+8iO+9n/OggKjinbLinbTin6bin6jin6rin6zipofiponippXiuKLiuKTvuJfvuLfvuLnvuLvvuL3vuL/vuYHvuYPvuYfvuZvvuZ3vvLvvvZvvvaLzoIGb86CBu8Kr4oCY4oCc4oC54p2uAJADCPCdqovwnaqkAJEDBPCdqosAkgMCwr0AkwMFMeKBhDIAlAMDMS8yAJUDA+CtswCWAwPgtbQAlwMD4rO9AJgDA+qgsQCZAwTwkIWBAJoDBPCQhbUAmwME8JCFtgCcAwTwkKa9AJ0DBPCQubsAngMD77yCAJ8DAX8AoAMBCAChAwPijKsAogMD4oymAKMDA+KQiACkAwPikKEApQMD4be7AKYDAQ8ApwMD4oaQAKgDA+KMpwCpAwPijZIAqgMD4o2UAKsDA+KNogCsAwPijasArQMBGgCuAwPikKYArwMD4pCaALADA++/vACxAwE/ALIDAsK/ALMDA+GlhQC0AwLNvgC1AwLVngC2AwLYnwC3AwPhjacAuAMD4oGHALkDA+KNsAC6AwPinZMAuwMD4p2UALwDA+KzugC9AwPis7sAvgMD4riuAL8DA+OJhADAAwPqmI8AwQMD6pu3AMIDA++4lgDDAwPvuZYAxAMD77yfAMUDBPCRhYMAxgME8J6lnwDHAwTzoIC/AMgDBPCWoYQAyQMD4q+RAMoDAsK2AMsDA+KBiwDMAwLcgADNAwPhg7sAzgMD4Y2oAM8DA+OAtwDQAwPinaEA0QMD4riPANIDA+K4kADTAwPiuJEA1AMD4riOANUDARQA1gMD4piZANcDA+K4vwDYAwPjgIcA2QMD4LmbANoDA+qZrgDbAwLPkwDcAwLPlADdAwPhupsA3gMK/BXfAwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBABBEAsEAEERCwQAQRILBABBEwsEAEEUCwQAQRULBABBFgsEAEEXCwQAQRgLBABBGQsEAEEaCwQAQRsLBABBHAsEAEEdCwQAQR4LBABBHwsEAEEgCwQAQSELBABBIgsEAEEjCwQAQSQLBABBJQsEAEEmCwQAQScLBABBKAsEAEEpCwQAQSoLBABBKwsEAEEsCwQAQS0LBABBLgsEAEEvCwQAQTALBABBMQsEAEEyCwQAQTMLBABBNAsEAEE1CwQAQTYLBABBNwsEAEE4CwQAQTkLBABBOgsEAEE7CwQAQTwLBABBPQsEAEE+CwQAQT8LBQBBwAALBQBBwQALBQBBwgALBQBBwwALBQBBxAALBQBBxQALBQBBxgALBQBBxwALBQBByAALBQBByQALBQBBygALBQBBywALBQBBzAALBQBBzQALBQBBzgALBQBBzwALBQBB0AALBQBB0QALBQBB0gALBQBB0wALBQBB1AALBQBB1QALBQBB1gALBQBB1wALBQBB2AALBQBB2QALBQBB2gALBQBB2wALBQBB3AALBQBB3QALBQBB3gALBQBB3wALBQBB4AALBQBB4QALBQBB4gALBQBB4wALBQBB5AALBQBB5QALBQBB5gALBQBB5wALBQBB6AALBQBB6QALBQBB6gALBQBB6wALBQBB7AALBQBB7QALBQBB7gALBQBB7wALBQBB8AALBQBB8QALBQBB8gALBQBB8wALBQBB9AALBQBB9QALBQBB9gALBQBB9wALBQBB+AALBQBB+QALBQBB+gALBQBB+wALBQBB/AALBQBB/QALBQBB/gALBQBB/wALBQBBgAELBQBBgQELBQBBggELBQBBgwELBQBBhAELBQBBhQELBQBBhgELBQBBhwELBQBBiAELBQBBiQELBQBBigELBQBBiwELBQBBjAELBQBBjQELBQBBjgELBQBBjwELBQBBkAELBQBBkQELBQBBkgELBQBBkwELBQBBlAELBQBBlQELBQBBlgELBQBBlwELBQBBmAELBQBBmQELBQBBmgELBQBBmwELBQBBnAELBQBBnQELBQBBngELBQBBnwELBQBBoAELBQBBoQELBQBBogELBQBBowELBQBBpAELBQBBpQELBQBBpgELBQBBpwELBQBBqAELBQBBqQELBQBBqgELBQBBqwELBQBBrAELBQBBrQELBQBBrgELBQBBrwELBQBBsAELBQBBsQELBQBBsgELBQBBswELBQBBtAELBQBBtQELBQBBtgELBQBBtwELBQBBuAELBQBBuQELBQBBugELBQBBuwELBQBBvAELBQBBvQELBQBBvgELBQBBvwELBQBBwAELBQBBwQELBQBBwgELBQBBwwELBQBBxAELBQBBxQELBQBBxgELBQBBxwELBQBByAELBQBByQELBQBBygELBQBBywELBQBBzAELBQBBzQELBQBBzgELBQBBzwELBQBB0AELBQBB0QELBQBB0gELBQBB0wELBQBB1AELBQBB1QELBQBB1gELBQBB1wELBQBB2AELBQBB2QELBQBB2gELBQBB2wELBQBB3AELBQBB3QELBQBB3gELBQBB3wELBQBB4AELBQBB4QELBQBB4gELBQBB4wELBQBB5AELBQBB5QELBQBB5gELBQBB5wELBQBB6AELBQBB6QELBQBB6gELBQBB6wELBQBB7AELBQBB7QELBQBB7gELBQBB7wELBQBB8AELBQBB8QELBQBB8gELBQBB8wELBQBB9AELBQBB9QELBQBB9gELBQBB9wELBQBB+AELBQBB+QELBQBB+gELBQBB+wELBQBB/AELBQBB/QELBQBB/gELBQBB/wELBQBBgAILBQBBgQILBQBBggILBQBBgwILBQBBhAILBQBBhQILBQBBhgILBQBBhwILBQBBiAILBQBBiQILBQBBigILBQBBiwILBQBBjAILBQBBjQILBQBBjgILBQBBjwILBQBBkAILBQBBkQILBQBBkgILBQBBkwILBQBBlAILBQBBlQILBQBBlgILBQBBlwILBQBBmAILBQBBmQILBQBBmgILBQBBmwILBQBBnAILBQBBnQILBQBBngILBQBBnwILBQBBoAILBQBBoQILBQBBogILBQBBowILBQBBpAILBQBBpQILBQBBpgILBQBBpwILBQBBqAILBQBBqQILBQBBqgILBQBBqwILBQBBrAILBQBBrQILBQBBrgILBQBBrwILBQBBsAILBQBBsQILBQBBsgILBQBBswILBQBBtAILBQBBtQILBQBBtgILBQBBtwILBQBBuAILBQBBuQILBQBBugILBQBBuwILBQBBvAILBQBBvQILBQBBvgILBQBBvwILBQBBwAILBQBBwQILBQBBwgILBQBBwwILBQBBxAILBQBBxQILBQBBxgILBQBBxwILBQBByAILBQBByQILBQBBygILBQBBywILBQBBzAILBQBBzQILBQBBzgILBQBBzwILBQBB0AILBQBB0QILBQBB0gILBQBB0wILBQBB1AILBQBB1QILBQBB1gILBQBB1wILBQBB2AILBQBB2QILBQBB2gILBQBB2wILBQBB3AILBQBB3QILBQBB3gILBQBB3wILBQBB4AILBQBB4QILBQBB4gILBQBB4wILBQBB5AILBQBB5QILBQBB5gILBQBB5wILBQBB6AILBQBB6QILBQBB6gILBQBB6wILBQBB7AILBQBB7QILBQBB7gILBQBB7wILBQBB8AILBQBB8QILBQBB8gILBQBB8wILBQBB9AILBQBB9QILBQBB9gILBQBB9wILBQBB+AILBQBB+QILBQBB+gILBQBB+wILBQBB/AILBQBB/QILBQBB/gILBQBB/wILBQBBgAMLBQBBgQMLBQBBggMLBQBBgwMLBQBBhAMLBQBBhQMLBQBBhgMLBQBBhwMLBQBBiAMLBQBBiQMLBQBBigMLBQBBiwMLBQBBjAMLBQBBjQMLBQBBjgMLBQBBjwMLBQBBkAMLBQBBkQMLBQBBkgMLBQBBkwMLBQBBlAMLBQBBlQMLBQBBlgMLBQBBlwMLBQBBmAMLBQBBmQMLBQBBmgMLBQBBmwMLBQBBnAMLBQBBnQMLBQBBngMLBQBBnwMLBQBBoAMLBQBBoQMLBQBBogMLBQBBowMLBQBBpAMLBQBBpQMLBQBBpgMLBQBBpwMLBQBBqAMLBQBBqQMLBQBBqgMLBQBBqwMLBQBBrAMLBQBBrQMLBQBBrgMLBQBBrwMLBQBBsAMLBQBBsQMLBQBBsgMLBQBBswMLBQBBtAMLBQBBtQMLBQBBtgMLBQBBtwMLBQBBuAMLBQBBuQMLBQBBugMLBQBBuwMLBQBBvAMLBQBBvQMLBQBBvgMLBQBBvwMLBQBBwAMLBQBBwQMLBQBBwgMLBQBBwwMLBQBBxAMLBQBBxQMLBQBBxgMLBQBBxwMLBQBByAMLBQBByQMLBQBBygMLBQBBywMLBQBBzAMLBQBBzQMLBQBBzgMLBQBBzwMLBQBB0AMLBQBB0QMLBQBB0gMLBQBB0wMLBQBB1AMLBQBB1QMLBQBB1gMLBQBB1wMLBQBB2AMLBQBB2QMLBQBB2gMLBQBB2wMLBQBB3AMLBQBB3QMLBQBB3gML", + "AGFzbQEAAAABCgJgAX8AYAJ/fwACKwIIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTMyAAADAgEBBwsBB3ByaW50MzIAAgoMAQoAIAAQACABEAEL", +]; +export const script = "[[\"file\",\"imports.wast\"],[\"module\",3,0],[\"register\",\"test\"],[\"module\",26,1],[\"invoke\",85,0,\"print32\",[\"i32:13\"]],[\"invoke\",86,0,\"print64\",[\"i64:24\"]],[\"module\",97,2],[\"invoke\",104,0,\"print_i32\",[\"i32:13\"]],[\"module\",107,3],[\"invoke\",114,0,\"print_i32\",[\"i32:5\",\"i32:11\"]],[\"module\",116,4],[\"module\",117,5],[\"module\",118,6],[\"module\",119,7],[\"module\",120,8],[\"module\",121,9],[\"module\",122,10],[\"instantiate\",125,11],[\"instantiate\",129,12],[\"instantiate\",134,13],[\"instantiate\",138,14],[\"instantiate\",142,15],[\"instantiate\",146,16],[\"instantiate\",150,17],[\"instantiate\",154,18],[\"instantiate\",158,19],[\"instantiate\",162,20],[\"instantiate\",166,21],[\"instantiate\",170,22],[\"instantiate\",174,23],[\"instantiate\",178,24],[\"instantiate\",182,25],[\"instantiate\",186,26],[\"instantiate\",190,27],[\"instantiate\",194,28],[\"instantiate\",199,29],[\"instantiate\",203,30],[\"instantiate\",207,31],[\"instantiate\",211,32],[\"instantiate\",215,33],[\"instantiate\",219,34],[\"module\",226,35],[\"invoke\",246,0,\"get-0\",[]],[\"invoke\",247,0,\"get-1\",[]],[\"invoke\",248,0,\"get-x\",[]],[\"invoke\",249,0,\"get-y\",[]],[\"invoke\",250,0,\"get-4\",[]],[\"invoke\",251,0,\"get-5\",[]],[\"invoke\",252,0,\"get-6\",[]],[\"module\",254,36],[\"module\",255,37],[\"module\",256,38],[\"instantiate\",259,39],[\"instantiate\",263,40],[\"instantiate\",268,41],[\"instantiate\",272,42],[\"instantiate\",276,43],[\"instantiate\",280,44],[\"instantiate\",284,45],[\"instantiate\",288,46],[\"instantiate\",292,47],[\"instantiate\",296,48],[\"instantiate\",300,49],[\"instantiate\",304,50],[\"instantiate\",308,51],[\"instantiate\",312,52],[\"instantiate\",317,53],[\"instantiate\",321,54],[\"instantiate\",325,55],[\"instantiate\",329,56],[\"instantiate\",333,57],[\"instantiate\",337,58],[\"module\",344,59],[\"invoke\",356,0,\"call\",[\"i32:0\"]],[\"invoke\",357,0,\"call\",[\"i32:1\"]],[\"invoke\",358,0,\"call\",[\"i32:2\"]],[\"invoke\",359,0,\"call\",[\"i32:3\"]],[\"invoke\",360,0,\"call\",[\"i32:100\"]],[\"module\",363,59],[\"invoke\",375,0,\"call\",[\"i32:0\"]],[\"invoke\",376,0,\"call\",[\"i32:1\"]],[\"invoke\",377,0,\"call\",[\"i32:2\"]],[\"invoke\",378,0,\"call\",[\"i32:3\"]],[\"invoke\",379,0,\"call\",[\"i32:100\"]],[\"module\",381,60],[\"module\",388,61],[\"module\",389,62],[\"module\",390,63],[\"module\",391,64],[\"module\",392,65],[\"module\",393,66],[\"module\",394,67],[\"module\",395,68],[\"module\",396,69],[\"module\",397,70],[\"module\",398,71],[\"module\",399,72],[\"module\",400,73],[\"module\",401,74],[\"module\",402,75],[\"module\",403,76],[\"module\",404,77],[\"module\",405,78],[\"module\",406,79],[\"module\",407,80],[\"instantiate\",410,81],[\"instantiate\",414,82],[\"instantiate\",419,83],[\"instantiate\",423,84],[\"instantiate\",427,85],[\"instantiate\",431,86],[\"instantiate\",435,87],[\"instantiate\",439,88],[\"instantiate\",444,89],[\"instantiate\",448,90],[\"instantiate\",452,91],[\"instantiate\",456,92],[\"module\",464,93],[\"invoke\",471,0,\"load\",[\"i32:0\"]],[\"invoke\",472,0,\"load\",[\"i32:10\"]],[\"invoke\",473,0,\"load\",[\"i32:8\"]],[\"invoke\",474,0,\"load\",[\"i32:1000000\"]],[\"module\",476,93],[\"invoke\",482,0,\"load\",[\"i32:0\"]],[\"invoke\",483,0,\"load\",[\"i32:10\"]],[\"invoke\",484,0,\"load\",[\"i32:8\"]],[\"invoke\",485,0,\"load\",[\"i32:1000000\"]],[\"module\",500,94],[\"module\",501,95],[\"module\",502,96],[\"module\",503,97],[\"module\",504,98],[\"module\",505,99],[\"module\",506,100],[\"module\",507,101],[\"module\",508,102],[\"instantiate\",511,103],[\"instantiate\",515,104],[\"instantiate\",520,105],[\"instantiate\",524,106],[\"instantiate\",528,107],[\"instantiate\",532,108],[\"instantiate\",537,109],[\"instantiate\",541,110],[\"instantiate\",545,111],[\"instantiate\",549,112],[\"instantiate\",553,113],[\"instantiate\",557,114],[\"instantiate\",562,107],[\"instantiate\",566,108],[\"module\",570,115],[\"invoke\",574,0,\"grow\",[\"i32:0\"]],[\"invoke\",575,0,\"grow\",[\"i32:1\"]],[\"invoke\",576,0,\"grow\",[\"i32:0\"]],[\"invoke\",577,0,\"grow\",[\"i32:1\"]],[\"invoke\",578,0,\"grow\",[\"i32:0\"]],[\"module\",654,116],[\"register\",\"not wasm\"],[\"instantiate\",657,117],[\"file\",\"table.wast\"],[\"module\",3,118],[\"module\",4,119],[\"module\",5,120],[\"module\",6,121],[\"module\",7,122],[\"module\",8,123],[\"module\",9,124],[\"module\",11,125],[\"module\",12,126],[\"file\",\"names.wast\"],[\"module\",4,127],[\"invoke\",8,0,\"foo\",[]],[\"module\",12,128],[\"module\",19,129],[\"invoke\",615,0,\"\",[]],[\"invoke\",616,0,\"0\",[]],[\"invoke\",617,0,\"-0\",[]],[\"invoke\",618,0,\"_\",[]],[\"invoke\",620,0,\"@\",[]],[\"invoke\",621,0,\"~!@#$%^&*()_+`-={}|[]\\\\:\\\";'<>?,./ \",[]],[\"invoke\",622,0,\"NaN\",[]],[\"invoke\",623,0,\"Infinity\",[]],[\"invoke\",624,0,\"if\",[]],[\"invoke\",626,0,\"_malloc\",[]],[\"invoke\",627,0,\"__malloc\",[]],[\"invoke\",628,0,\"a\",[]],[\"invoke\",629,0,\"A\",[]],[\"invoke\",630,0,\"\u{feff}\",[]],[\"invoke\",632,0,\"Å\",[]],[\"invoke\",633,0,\"Å\",[]],[\"invoke\",634,0,\"ffi\",[]],[\"invoke\",635,0,\"ffi\",[]],[\"invoke\",636,0,\"ffi\",[]],[\"invoke\",638,0,\"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\",[]],[\"invoke\",639,0,\" \u{7f}\",[]],[\"invoke\",640,0,\"\u{80}\u{81}\u{82}\u{83}\u{84}\u{85}\u{86}\u{87}\u{88}\u{89}\u{8a}\u{8b}\u{8c}\u{8d}\u{8e}\u{8f}\",[]],[\"invoke\",641,0,\"\u{90}\u{91}\u{92}\u{93}\u{94}\u{95}\u{96}\u{97}\u{98}\u{99}\u{9a}\u{9b}\u{9c}\u{9d}\u{9e}\u{9f}\",[]],[\"invoke\",642,0,\"￰￱￲￳￴￵￶￷\",[]],[\"invoke\",644,0,\"␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏\",[]],[\"invoke\",645,0,\"␐␑␒␓␔␕␖␗␘␙␚␛␜␝␞␟\",[]],[\"invoke\",646,0,\"␠␡\",[]],[\"invoke\",647,0,\"￰￱￲￳￴￵￶￷￸\u{fff9}\u{fffa}\u{fffb}�\",[]],[\"invoke\",648,0,\"\u{200d}\",[]],[\"invoke\",650,0,\"͏\",[]],[\"invoke\",651,0,\"\u{2060}\",[]],[\"invoke\",652,0,\"⵿\",[]],[\"invoke\",653,0,\"𑁿\",[]],[\"invoke\",654,0,\"\u{180e}\",[]],[\"invoke\",656,0,\"\u{200e}\u{200f}‑\u{2028}\u{2029}\u{202a}\u{202b}\u{202c} \u{2066}\u{2067}\u{2068}\u{2069}\",[]],[\"invoke\",657,0,\"\u{206a}\u{206b}\u{206c}\u{206d}\u{206e}\u{206f}\",[]],[\"invoke\",658,0,\"\u{2061}\u{2062}\u{2063}\u{2064}\",[]],[\"invoke\",659,0,\"𐀀󟿿􏿿\",[]],[\"invoke\",660,0,\"Z̴͇̫̥̪͓͈͔͎̗̞̺̯̱̞̙̱̜̖̠̏͆̆͛͌͘͞ḁ̶̰̳̭͙̲̱̹̝͎̼͗ͨ̎̄̆͗̿̀́͟͡l̶̷͉̩̹̫̝͖̙̲̼͇͚͍̮͎̥̞̈́͊͗ͦ̈́ͫ̇́̚ͅͅg̶͕͔͚̩̓̐̅ͮ̔̐̎̂̏̾͊̍͋͊ͧ́̆ͦ͞o̡͋̔͐ͪͩ͏̢̧̫̙̤̮͖͙͓̺̜̩̼̘̠́\",[]],[\"invoke\",662,0,\"︀\",[]],[\"invoke\",663,0,\"︄\",[]],[\"invoke\",664,0,\"󠄀\",[]],[\"invoke\",665,0,\"󠇯\",[]],[\"invoke\",667,0,\"\\n\",[]],[\"invoke\",668,0,\"␤\",[]],[\"invoke\",669,0,\"\u{2028}\",[]],[\"invoke\",670,0,\"\\r\",[]],[\"invoke\",671,0,\"\\r\\n\",[]],[\"invoke\",673,0,\"\\u001e\",[]],[\"invoke\",674,0,\"\\u000b\",[]],[\"invoke\",675,0,\"\\f\",[]],[\"invoke\",676,0,\"\u{85}\",[]],[\"invoke\",677,0,\"\u{2029}\",[]],[\"invoke\",679,0,\"⏎\",[]],[\"invoke\",680,0,\"\u{8b}\",[]],[\"invoke\",681,0,\"\u{8c}\",[]],[\"invoke\",682,0,\"\u{8d}\",[]],[\"invoke\",683,0,\"↵\",[]],[\"invoke\",685,0,\"⌤\",[]],[\"invoke\",686,0,\"⤶\",[]],[\"invoke\",687,0,\"↲\",[]],[\"invoke\",688,0,\"⮨\",[]],[\"invoke\",689,0,\"⮰\",[]],[\"invoke\",691,0,\"﷐\",[]],[\"invoke\",692,0,\"﷑\",[]],[\"invoke\",693,0,\"﷒\",[]],[\"invoke\",694,0,\"﷓\",[]],[\"invoke\",695,0,\"﷔\",[]],[\"invoke\",697,0,\"﷖\",[]],[\"invoke\",698,0,\"﷗\",[]],[\"invoke\",699,0,\"﷘\",[]],[\"invoke\",700,0,\"﷙\",[]],[\"invoke\",701,0,\"﷚\",[]],[\"invoke\",703,0,\"﷜\",[]],[\"invoke\",704,0,\"﷝\",[]],[\"invoke\",705,0,\"﷞\",[]],[\"invoke\",706,0,\"﷟\",[]],[\"invoke\",707,0,\"﷠\",[]],[\"invoke\",709,0,\"﷢\",[]],[\"invoke\",710,0,\"﷣\",[]],[\"invoke\",711,0,\"﷤\",[]],[\"invoke\",712,0,\"﷥\",[]],[\"invoke\",714,0,\"﷧\",[]],[\"invoke\",715,0,\"﷨\",[]],[\"invoke\",716,0,\"﷩\",[]],[\"invoke\",717,0,\"﷪\",[]],[\"invoke\",718,0,\"﷫\",[]],[\"invoke\",720,0,\"﷭\",[]],[\"invoke\",721,0,\"﷮\",[]],[\"invoke\",722,0,\"﷯\",[]],[\"invoke\",723,0,\"￾\",[]],[\"invoke\",724,0,\"￿\",[]],[\"invoke\",726,0,\"🿿\",[]],[\"invoke\",727,0,\"𯿾\",[]],[\"invoke\",728,0,\"𯿿\",[]],[\"invoke\",729,0,\"𿿾\",[]],[\"invoke\",730,0,\"𿿿\",[]],[\"invoke\",732,0,\"񏿿\",[]],[\"invoke\",733,0,\"񟿾\",[]],[\"invoke\",734,0,\"񟿿\",[]],[\"invoke\",735,0,\"񯿾\",[]],[\"invoke\",736,0,\"񯿿\",[]],[\"invoke\",738,0,\"񿿿\",[]],[\"invoke\",739,0,\"򏿾\",[]],[\"invoke\",740,0,\"򏿿\",[]],[\"invoke\",741,0,\"򟿾\",[]],[\"invoke\",742,0,\"򟿿\",[]],[\"invoke\",744,0,\"򯿿\",[]],[\"invoke\",745,0,\"򿿾\",[]],[\"invoke\",746,0,\"򿿿\",[]],[\"invoke\",747,0,\"󏿾\",[]],[\"invoke\",748,0,\"󏿿\",[]],[\"invoke\",750,0,\"󟿿\",[]],[\"invoke\",751,0,\"󯿾\",[]],[\"invoke\",752,0,\"󯿿\",[]],[\"invoke\",753,0,\"󿿾\",[]],[\"invoke\",754,0,\"󿿿\",[]],[\"invoke\",756,0,\"􏿿\",[]],[\"invoke\",757,0,\"̈‽̈̉\",[]],[\"invoke\",758,0,\"abc\",[]],[\"invoke\",759,0,\"\u{202d}abc\",[]],[\"invoke\",761,0,\"\u{202d}abc\u{202e}\",[]],[\"invoke\",762,0,\"\u{202e}cba\u{202d}\",[]],[\"invoke\",763,0,\"𝑨\",[]],[\"invoke\",764,0,\"𝐴\",[]],[\"invoke\",765,0,\"𝘈\",[]],[\"invoke\",767,0,\"𝐀\",[]],[\"invoke\",768,0,\"𝓐\",[]],[\"invoke\",769,0,\"𝕬\",[]],[\"invoke\",770,0,\"𝗔\",[]],[\"invoke\",771,0,\"𝒜\",[]],[\"invoke\",773,0,\"𝔸\",[]],[\"invoke\",774,0,\"𝖠\",[]],[\"invoke\",775,0,\"𝙰\",[]],[\"invoke\",776,0,\"ᴀ\",[]],[\"invoke\",777,0,\"ᴬ\",[]],[\"invoke\",779,0,\"A\",[]],[\"invoke\",780,0,\"🄐\",[]],[\"invoke\",781,0,\"🄰\",[]],[\"invoke\",782,0,\"\u{e0041}\",[]],[\"invoke\",783,0,\"U+0041\",[]],[\"invoke\",785,0,\"А\",[]],[\"invoke\",786,0,\"Ꙗ\",[]],[\"invoke\",787,0,\"ⷼ\",[]],[\"invoke\",788,0,\"ⷶ\",[]],[\"invoke\",789,0,\"Ɐ\",[]],[\"invoke\",791,0,\"🅰\",[]],[\"invoke\",792,0,\"Ⱝ\",[]],[\"invoke\",793,0,\"𐐂\",[]],[\"invoke\",794,0,\"𐐈\",[]],[\"invoke\",795,0,\"𐒰\",[]],[\"invoke\",797,0,\"Á\",[]],[\"invoke\",798,0,\"Â\",[]],[\"invoke\",799,0,\"Ã\",[]],[\"invoke\",800,0,\"Ä\",[]],[\"invoke\",801,0,\"Ā\",[]],[\"invoke\",803,0,\"Ą\",[]],[\"invoke\",804,0,\"Ǎ\",[]],[\"invoke\",805,0,\"Ǟ\",[]],[\"invoke\",806,0,\"Ǡ\",[]],[\"invoke\",808,0,\"Ȁ\",[]],[\"invoke\",809,0,\"Ȃ\",[]],[\"invoke\",810,0,\"Ȧ\",[]],[\"invoke\",811,0,\"Ⱥ\",[]],[\"invoke\",812,0,\"Ӑ\",[]],[\"invoke\",814,0,\"ߊ\",[]],[\"invoke\",815,0,\"ࠡ\",[]],[\"invoke\",816,0,\"ࠢ\",[]],[\"invoke\",817,0,\"ࠣ\",[]],[\"invoke\",818,0,\"ࠤ\",[]],[\"invoke\",820,0,\"ऄ\",[]],[\"invoke\",821,0,\"अ\",[]],[\"invoke\",822,0,\"ॲ\",[]],[\"invoke\",823,0,\"অ\",[]],[\"invoke\",824,0,\"ਅ\",[]],[\"invoke\",826,0,\"ଅ\",[]],[\"invoke\",827,0,\"அ\",[]],[\"invoke\",828,0,\"అ\",[]],[\"invoke\",829,0,\"ಅ\",[]],[\"invoke\",830,0,\"അ\",[]],[\"invoke\",832,0,\"ະ\",[]],[\"invoke\",833,0,\"༁\",[]],[\"invoke\",834,0,\"ཨ\",[]],[\"invoke\",835,0,\"ྸ\",[]],[\"invoke\",836,0,\"အ\",[]],[\"invoke\",838,0,\"ႜ\",[]],[\"invoke\",839,0,\"ᅡ\",[]],[\"invoke\",840,0,\"አ\",[]],[\"invoke\",841,0,\"ዐ\",[]],[\"invoke\",842,0,\"Ꭰ\",[]],[\"invoke\",844,0,\"ᖳ\",[]],[\"invoke\",845,0,\"ᚨ\",[]],[\"invoke\",846,0,\"ᚪ\",[]],[\"invoke\",847,0,\"ᛆ\",[]],[\"invoke\",848,0,\"ᜀ\",[]],[\"invoke\",850,0,\"ᝀ\",[]],[\"invoke\",851,0,\"ᝠ\",[]],[\"invoke\",852,0,\"ᠠ\",[]],[\"invoke\",853,0,\"ᢇ\",[]],[\"invoke\",855,0,\"ᥣ\",[]],[\"invoke\",856,0,\"ᨕ\",[]],[\"invoke\",857,0,\"ᩋ\",[]],[\"invoke\",858,0,\"ᩡ\",[]],[\"invoke\",859,0,\"ᮃ\",[]],[\"invoke\",861,0,\"ᯁ\",[]],[\"invoke\",862,0,\"ᰣ\",[]],[\"invoke\",863,0,\"Ḁ\",[]],[\"invoke\",864,0,\"Ạ\",[]],[\"invoke\",865,0,\"Ả\",[]],[\"invoke\",867,0,\"Ầ\",[]],[\"invoke\",868,0,\"Ẩ\",[]],[\"invoke\",869,0,\"Ẫ\",[]],[\"invoke\",870,0,\"Ậ\",[]],[\"invoke\",871,0,\"Ắ\",[]],[\"invoke\",873,0,\"Ẳ\",[]],[\"invoke\",874,0,\"Ẵ\",[]],[\"invoke\",875,0,\"Ặ\",[]],[\"invoke\",876,0,\"あ\",[]],[\"invoke\",877,0,\"ア\",[]],[\"invoke\",879,0,\"ㅏ\",[]],[\"invoke\",880,0,\"㈎\",[]],[\"invoke\",881,0,\"㈏\",[]],[\"invoke\",882,0,\"㈐\",[]],[\"invoke\",883,0,\"㈑\",[]],[\"invoke\",885,0,\"㈓\",[]],[\"invoke\",886,0,\"㈔\",[]],[\"invoke\",887,0,\"㈕\",[]],[\"invoke\",888,0,\"㈖\",[]],[\"invoke\",889,0,\"㈗\",[]],[\"invoke\",891,0,\"㈙\",[]],[\"invoke\",892,0,\"㈚\",[]],[\"invoke\",893,0,\"㈛\",[]],[\"invoke\",894,0,\"㉮\",[]],[\"invoke\",895,0,\"㉯\",[]],[\"invoke\",897,0,\"㉱\",[]],[\"invoke\",898,0,\"㉲\",[]],[\"invoke\",899,0,\"㉳\",[]],[\"invoke\",900,0,\"㉴\",[]],[\"invoke\",901,0,\"㉵\",[]],[\"invoke\",903,0,\"㉷\",[]],[\"invoke\",904,0,\"㉸\",[]],[\"invoke\",905,0,\"㉹\",[]],[\"invoke\",906,0,\"㉺\",[]],[\"invoke\",908,0,\"㋐\",[]],[\"invoke\",909,0,\"ꀊ\",[]],[\"invoke\",910,0,\"ꓮ\",[]],[\"invoke\",911,0,\"ꕉ\",[]],[\"invoke\",912,0,\"ꚠ\",[]],[\"invoke\",914,0,\"ꠣ\",[]],[\"invoke\",915,0,\"ꡝ\",[]],[\"invoke\",916,0,\"ꢂ\",[]],[\"invoke\",917,0,\"꣪\",[]],[\"invoke\",918,0,\"ꤢ\",[]],[\"invoke\",920,0,\"ꦄ\",[]],[\"invoke\",921,0,\"ꨀ\",[]],[\"invoke\",922,0,\"ア\",[]],[\"invoke\",923,0,\"ᅡ\",[]],[\"invoke\",924,0,\"𐀀\",[]],[\"invoke\",926,0,\"𐊠\",[]],[\"invoke\",927,0,\"𐌀\",[]],[\"invoke\",928,0,\"𐎠\",[]],[\"invoke\",929,0,\"𐒖\",[]],[\"invoke\",930,0,\"𐔀\",[]],[\"invoke\",932,0,\"𐠀\",[]],[\"invoke\",933,0,\"𐤠\",[]],[\"invoke\",934,0,\"𐦀\",[]],[\"invoke\",935,0,\"𐦠\",[]],[\"invoke\",936,0,\"𐨀\",[]],[\"invoke\",938,0,\"𐰀\",[]],[\"invoke\",939,0,\"𐰁\",[]],[\"invoke\",940,0,\"𐲀\",[]],[\"invoke\",941,0,\"𑀅\",[]],[\"invoke\",942,0,\"𑂃\",[]],[\"invoke\",944,0,\"𑅐\",[]],[\"invoke\",945,0,\"𑆃\",[]],[\"invoke\",946,0,\"𑈀\",[]],[\"invoke\",947,0,\"𑊀\",[]],[\"invoke\",948,0,\"𑊰\",[]],[\"invoke\",950,0,\"𑍰\",[]],[\"invoke\",951,0,\"𑐀\",[]],[\"invoke\",952,0,\"𑒁\",[]],[\"invoke\",953,0,\"𑖀\",[]],[\"invoke\",955,0,\"𑚀\",[]],[\"invoke\",956,0,\"𑜒\",[]],[\"invoke\",957,0,\"𑜠\",[]],[\"invoke\",958,0,\"𑢡\",[]],[\"invoke\",959,0,\"𑫕\",[]],[\"invoke\",961,0,\"𑲏\",[]],[\"invoke\",962,0,\"𑲯\",[]],[\"invoke\",963,0,\"𒀀\",[]],[\"invoke\",964,0,\"𖧕\",[]],[\"invoke\",965,0,\"𖩆\",[]],[\"invoke\",967,0,\"𖽔\",[]],[\"invoke\",968,0,\"𛱁\",[]],[\"invoke\",969,0,\"𛱤\",[]],[\"invoke\",970,0,\"𞠣\",[]],[\"invoke\",971,0,\"🇦\",[]],[\"invoke\",973,0,\"Λ\",[]],[\"invoke\",974,0,\"Ɒ\",[]],[\"invoke\",975,0,\"ª\",[]],[\"invoke\",976,0,\"∀\",[]],[\"invoke\",977,0,\"₳\",[]],[\"invoke\",979,0,\"Ⲁ\",[]],[\"invoke\",980,0,\"𐌰\",[]],[\"invoke\",981,0,\"Ά\",[]],[\"invoke\",982,0,\"Α\",[]],[\"invoke\",983,0,\"Ἀ\",[]],[\"invoke\",985,0,\"Ἂ\",[]],[\"invoke\",986,0,\"Ἃ\",[]],[\"invoke\",987,0,\"Ἄ\",[]],[\"invoke\",988,0,\"Ἅ\",[]],[\"invoke\",989,0,\"Ἆ\",[]],[\"invoke\",991,0,\"ᾈ\",[]],[\"invoke\",992,0,\"ᾉ\",[]],[\"invoke\",993,0,\"ᾊ\",[]],[\"invoke\",994,0,\"ᾋ\",[]],[\"invoke\",995,0,\"ᾌ\",[]],[\"invoke\",997,0,\"ᾎ\",[]],[\"invoke\",998,0,\"ᾏ\",[]],[\"invoke\",999,0,\"Ᾰ\",[]],[\"invoke\",1000,0,\"Ᾱ\",[]],[\"invoke\",1002,0,\"Ά\",[]],[\"invoke\",1003,0,\"ᾼ\",[]],[\"invoke\",1004,0,\"𝚨\",[]],[\"invoke\",1005,0,\"𝛢\",[]],[\"invoke\",1006,0,\"𝜜\",[]],[\"invoke\",1008,0,\"𝞐\",[]],[\"invoke\",1009,0,\"⍶\",[]],[\"invoke\",1010,0,\"⍺\",[]],[\"invoke\",1011,0,\"⩜\",[]],[\"invoke\",1012,0,\"ᗅ\",[]],[\"invoke\",1014,0,\")˺˼𔗏\u{1d174}\u{1d176}\u{1d178}\u{1d17a}⁾₎❩❫⟯﴿︶﹚)⦆\u{e0029}❳❵⟧⟩⟫⟭⦈⦊⦖⸣⸥︘︸︺︼︾﹀﹂﹄﹈﹜﹞]}」\u{e005d}\u{e007d}»’”›❯\",[]],[\"invoke\",1015,0,\"(˹˻𔗎\u{1d173}\u{1d175}\u{1d177}\u{1d179}⁽₍❨❪⟮﴾︵﹙(⦅\u{e0028}❲❴⟦⟨⟪⟬⦇⦉⦕⸢⸤︗︷︹︻︽︿﹁﹃﹇﹛﹝[{「\u{e005b}\u{e007b}«‘“‹❮\",[]],[\"invoke\",1016,0,\"𝪋𝪤\",[]],[\"invoke\",1017,0,\"𝪋\",[]],[\"invoke\",1018,0,\"½\",[]],[\"invoke\",1020,0,\"1/2\",[]],[\"invoke\",1021,0,\"୳\",[]],[\"invoke\",1022,0,\"൴\",[]],[\"invoke\",1023,0,\"⳽\",[]],[\"invoke\",1024,0,\"꠱\",[]],[\"invoke\",1026,0,\"𐅵\",[]],[\"invoke\",1027,0,\"𐅶\",[]],[\"invoke\",1028,0,\"𐦽\",[]],[\"invoke\",1029,0,\"𐹻\",[]],[\"invoke\",1030,0,\""\",[]],[\"invoke\",1032,0,\"\\b\",[]],[\"invoke\",1033,0,\"⌫\",[]],[\"invoke\",1034,0,\"⌦\",[]],[\"invoke\",1035,0,\"␈\",[]],[\"invoke\",1036,0,\"␡\",[]],[\"invoke\",1038,0,\"\\u000f\",[]],[\"invoke\",1039,0,\"←\",[]],[\"invoke\",1040,0,\"⌧\",[]],[\"invoke\",1041,0,\"⍒\",[]],[\"invoke\",1042,0,\"⍔\",[]],[\"invoke\",1044,0,\"⍫\",[]],[\"invoke\",1045,0,\"\\u001a\",[]],[\"invoke\",1046,0,\"␦\",[]],[\"invoke\",1047,0,\"␚\",[]],[\"invoke\",1049,0,\"?\",[]],[\"invoke\",1050,0,\"¿\",[]],[\"invoke\",1051,0,\"᥅\",[]],[\"invoke\",1052,0,\";\",[]],[\"invoke\",1053,0,\"՞\",[]],[\"invoke\",1055,0,\"፧\",[]],[\"invoke\",1056,0,\"⁇\",[]],[\"invoke\",1057,0,\"⍰\",[]],[\"invoke\",1058,0,\"❓\",[]],[\"invoke\",1059,0,\"❔\",[]],[\"invoke\",1061,0,\"⳻\",[]],[\"invoke\",1062,0,\"⸮\",[]],[\"invoke\",1063,0,\"㉄\",[]],[\"invoke\",1064,0,\"꘏\",[]],[\"invoke\",1065,0,\"꛷\",[]],[\"invoke\",1067,0,\"﹖\",[]],[\"invoke\",1068,0,\"?\",[]],[\"invoke\",1069,0,\"𑅃\",[]],[\"invoke\",1070,0,\"𞥟\",[]],[\"invoke\",1071,0,\"\u{e003f}\",[]],[\"invoke\",1073,0,\"⯑\",[]],[\"invoke\",1074,0,\"¶\",[]],[\"invoke\",1075,0,\"⁋\",[]],[\"invoke\",1076,0,\"܀\",[]],[\"invoke\",1077,0,\"჻\",[]],[\"invoke\",1079,0,\"〷\",[]],[\"invoke\",1080,0,\"❡\",[]],[\"invoke\",1081,0,\"⸏\",[]],[\"invoke\",1082,0,\"⸐\",[]],[\"invoke\",1083,0,\"⸑\",[]],[\"invoke\",1085,0,\"\\u0014\",[]],[\"invoke\",1086,0,\"☙\",[]],[\"invoke\",1087,0,\"⸿\",[]],[\"invoke\",1088,0,\"〇\",[]],[\"invoke\",1089,0,\"๛\",[]],[\"invoke\",1091,0,\"ϓ\",[]],[\"invoke\",1092,0,\"ϔ\",[]],[\"invoke\",1093,0,\"ẛ\",[]],[\"module\",1095,130],[\"invoke\",1107,0,\"print32\",[\"i32:42\",\"i32:123\"]]]"; diff --git a/tests/corpus/webassembly-spec-imports/main.mjs b/tests/corpus/webassembly-spec-imports/main.mjs new file mode 100644 index 000000000..681908d64 --- /dev/null +++ b/tests/corpus/webassembly-spec-imports/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (3 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-spec-int/data.mjs b/tests/corpus/webassembly-spec-int/data.mjs new file mode 100644 index 000000000..08a72be2f --- /dev/null +++ b/tests/corpus/webassembly-spec-int/data.mjs @@ -0,0 +1,33 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * i32.wast, i64.wast, int_exprs.wast, int_literals.wast, conversions.wast, traps.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABDAJgAn9/AX9gAX8BfwMgHwAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAH3gEfA2FkZAAAA3N1YgABA211bAACBWRpdl9zAAMFZGl2X3UABAVyZW1fcwAFBXJlbV91AAYDYW5kAAcCb3IACAN4b3IACQNzaGwACgVzaHJfcwALBXNocl91AAwEcm90bAANBHJvdHIADgNjbHoADwNjdHoAEAZwb3BjbnQAEQlleHRlbmQ4X3MAEgpleHRlbmQxNl9zABMDZXF6ABQCZXEAFQJuZQAWBGx0X3MAFwRsdF91ABgEbGVfcwAZBGxlX3UAGgRndF9zABsEZ3RfdQAcBGdlX3MAHQRnZV91AB4K7QEfBwAgACABagsHACAAIAFrCwcAIAAgAWwLBwAgACABbQsHACAAIAFuCwcAIAAgAW8LBwAgACABcAsHACAAIAFxCwcAIAAgAXILBwAgACABcwsHACAAIAF0CwcAIAAgAXULBwAgACABdgsHACAAIAF3CwcAIAAgAXgLBQAgAGcLBQAgAGgLBQAgAGkLBQAgAMALBQAgAMELBQAgAEULBwAgACABRgsHACAAIAFHCwcAIAAgAUgLBwAgACABSQsHACAAIAFMCwcAIAAgAU0LBwAgACABSgsHACAAIAFLCwcAIAAgAU4LBwAgACABTws=", + "AGFzbQEAAAABFwRgAn5+AX5gAX4BfmABfgF/YAJ+fgF/AyEgAAAAAAAAAAAAAAAAAAAAAQEBAQEBAgMDAwMDAwMDAwMH6wEgA2FkZAAAA3N1YgABA211bAACBWRpdl9zAAMFZGl2X3UABAVyZW1fcwAFBXJlbV91AAYDYW5kAAcCb3IACAN4b3IACQNzaGwACgVzaHJfcwALBXNocl91AAwEcm90bAANBHJvdHIADgNjbHoADwNjdHoAEAZwb3BjbnQAEQlleHRlbmQ4X3MAEgpleHRlbmQxNl9zABMKZXh0ZW5kMzJfcwAUA2VxegAVAmVxABYCbmUAFwRsdF9zABgEbHRfdQAZBGxlX3MAGgRsZV91ABsEZ3RfcwAcBGd0X3UAHQRnZV9zAB4EZ2VfdQAfCvMBIAcAIAAgAXwLBwAgACABfQsHACAAIAF+CwcAIAAgAX8LBwAgACABgAsHACAAIAGBCwcAIAAgAYILBwAgACABgwsHACAAIAGECwcAIAAgAYULBwAgACABhgsHACAAIAGHCwcAIAAgAYgLBwAgACABiQsHACAAIAGKCwUAIAB5CwUAIAB6CwUAIAB7CwUAIADCCwUAIADDCwUAIADECwUAIABQCwcAIAAgAVELBwAgACABUgsHACAAIAFTCwcAIAAgAVQLBwAgACABVwsHACAAIAFYCwcAIAAgAVULBwAgACABVgsHACAAIAFZCwcAIAAgAVoL", + "AGFzbQEAAAABDQJgAn9/AX9gAn5+AX8DBQQAAAEBB20EGGkzMi5ub19mb2xkX2NtcF9zX29mZnNldAAAGGkzMi5ub19mb2xkX2NtcF91X29mZnNldAABGGk2NC5ub19mb2xkX2NtcF9zX29mZnNldAACGGk2NC5ub19mb2xkX2NtcF91X29mZnNldAADCjkEDQAgAEEBaiABQQFqSAsNACAAQQFqIAFBAWpJCw0AIABCAXwgAUIBfFMLDQAgAEIBfCABQgF8VAs=", + "AGFzbQEAAAABBgFgAX4BfgMCAQAHHQEZaTY0Lm5vX2ZvbGRfd3JhcF9leHRlbmRfcwAACggBBgAgAKesCw==", + "AGFzbQEAAAABBgFgAX4BfgMCAQAHHQEZaTY0Lm5vX2ZvbGRfd3JhcF9leHRlbmRfdQAACggBBgAgAKetCw==", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9zaGxfc2hyX3MAABVpMzIubm9fZm9sZF9zaGxfc2hyX3UAARVpNjQubm9fZm9sZF9zaGxfc2hyX3MAAhVpNjQubm9fZm9sZF9zaGxfc2hyX3UAAwotBAoAIABBAXRBAXULCgAgAEEBdEEBdgsKACAAQgGGQgGHCwoAIABCAYZCAYgL", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9zaHJfc19zaGwAABVpMzIubm9fZm9sZF9zaHJfdV9zaGwAARVpNjQubm9fZm9sZF9zaHJfc19zaGwAAhVpNjQubm9fZm9sZF9zaHJfdV9zaGwAAwotBAoAIABBAXVBAXQLCgAgAEEBdkEBdAsKACAAQgGHQgGGCwoAIABCAYhCAYYL", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9kaXZfc19tdWwAABVpMzIubm9fZm9sZF9kaXZfdV9tdWwAARVpNjQubm9fZm9sZF9kaXZfc19tdWwAAhVpNjQubm9fZm9sZF9kaXZfdV9tdWwAAwotBAoAIABBBm1BBmwLCgAgAEEGbkEGbAsKACAAQgZ/QgZ+CwoAIABCBoBCBn4L", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdlBBZpMzIubm9fZm9sZF9kaXZfc19zZWxmAAAWaTMyLm5vX2ZvbGRfZGl2X3Vfc2VsZgABFmk2NC5ub19mb2xkX2Rpdl9zX3NlbGYAAhZpNjQubm9fZm9sZF9kaXZfdV9zZWxmAAMKIQQHACAAIABtCwcAIAAgAG4LBwAgACAAfwsHACAAIACACw==", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdlBBZpMzIubm9fZm9sZF9yZW1fc19zZWxmAAAWaTMyLm5vX2ZvbGRfcmVtX3Vfc2VsZgABFmk2NC5ub19mb2xkX3JlbV9zX3NlbGYAAhZpNjQubm9fZm9sZF9yZW1fdV9zZWxmAAMKIQQHACAAIABvCwcAIAAgAHALBwAgACAAgQsHACAAIACCCw==", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9tdWxfZGl2X3MAABVpMzIubm9fZm9sZF9tdWxfZGl2X3UAARVpNjQubm9fZm9sZF9tdWxfZGl2X3MAAhVpNjQubm9fZm9sZF9tdWxfZGl2X3UAAwotBAoAIABBBmxBBm0LCgAgAEEGbEEGbgsKACAAQgZ+QgZ/CwoAIABCBn5CBoAL", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLQITaTMyLm5vX2ZvbGRfZGl2X3NfMgAAE2k2NC5ub19mb2xkX2Rpdl9zXzIAAQoRAgcAIABBAm0LBwAgAEICfws=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLQITaTMyLm5vX2ZvbGRfcmVtX3NfMgAAE2k2NC5ub19mb2xkX3JlbV9zXzIAAQoRAgcAIABBAm8LBwAgAEICgQs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfMAAAC2kzMi5kaXZfdV8wAAELaTY0LmRpdl9zXzAAAgtpNjQuZGl2X3VfMAADCiEEBwAgAEEAbQsHACAAQQBuCwcAIABCAH8LBwAgAEIAgAs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfMwAAC2kzMi5kaXZfdV8zAAELaTY0LmRpdl9zXzMAAgtpNjQuZGl2X3VfMwADCiEEBwAgAEEDbQsHACAAQQNuCwcAIABCA38LBwAgAEIDgAs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfNQAAC2kzMi5kaXZfdV81AAELaTY0LmRpdl9zXzUAAgtpNjQuZGl2X3VfNQADCiEEBwAgAEEFbQsHACAAQQVuCwcAIABCBX8LBwAgAEIFgAs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfNwAAC2kzMi5kaXZfdV83AAELaTY0LmRpdl9zXzcAAgtpNjQuZGl2X3VfNwADCiEEBwAgAEEHbQsHACAAQQduCwcAIABCB38LBwAgAEIHgAs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfMwAAC2kzMi5yZW1fdV8zAAELaTY0LnJlbV9zXzMAAgtpNjQucmVtX3VfMwADCiEEBwAgAEEDbwsHACAAQQNwCwcAIABCA4ELBwAgAEIDggs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfNQAAC2kzMi5yZW1fdV81AAELaTY0LnJlbV9zXzUAAgtpNjQucmVtX3VfNQADCiEEBwAgAEEFbwsHACAAQQVwCwcAIABCBYELBwAgAEIFggs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfNwAAC2kzMi5yZW1fdV83AAELaTY0LnJlbV9zXzcAAgtpNjQucmVtX3VfNwADCiEEBwAgAEEHbwsHACAAQQdwCwcAIABCB4ELBwAgAEIHggs=", + "AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLwIUaTMyLm5vX2ZvbGRfZGl2X25lZzEAABRpNjQubm9fZm9sZF9kaXZfbmVnMQABChECBwAgAEF/bQsHACAAQn9/Cw==", + "AGFzbQEAAAABCQJgAAF/YAABfgMfHgAAAAAAAAAAAAAAAQEBAQEBAQEBAQEAAAAAAQEBAQe3Ax4IaTMyLnRlc3QAAAhpMzIudW1heAABCGkzMi5zbWF4AAIMaTMyLm5lZ19zbWF4AAMIaTMyLnNtaW4ABAxpMzIuYWx0X3NtaW4ABQxpMzIuaW5jX3NtaW4ABgxpMzIubmVnX3plcm8ABw1pMzIubm90X29jdGFsAAgUaTMyLnVuc2lnbmVkX2RlY2ltYWwACQ1pMzIucGx1c19zaWduAAoIaTY0LnRlc3QACwhpNjQudW1heAAMCGk2NC5zbWF4AA0MaTY0Lm5lZ19zbWF4AA4IaTY0LnNtaW4ADwxpNjQuYWx0X3NtaW4AEAxpNjQuaW5jX3NtaW4AEQxpNjQubmVnX3plcm8AEg1pNjQubm90X29jdGFsABMUaTY0LnVuc2lnbmVkX2RlY2ltYWwAFA1pNjQucGx1c19zaWduABUMaTMyLWRlYy1zZXAxABYMaTMyLWRlYy1zZXAyABcMaTMyLWhleC1zZXAxABgMaTMyLWhleC1zZXAyABkMaTY0LWRlYy1zZXAxABoMaTY0LWRlYy1zZXAyABsMaTY0LWhleC1zZXAxABwMaTY0LWhleC1zZXAyAB0KlQIeCQBBjaC33QAPCwUAQX8PCwkAQf////8HDwsJAEGBgICAeA8LCQBBgICAgHgPCwkAQYCAgIB4DwsMAEGAgICAeEEBag8LBQBBAA8LBQBBCg8LBQBBfw8LBQBBKg8LDQBC7tSZ3eDN7tUMDwsFAEJ/DwsOAEL///////////8ADwsOAEKBgICAgICAgIB/DwsOAEKAgICAgICAgIB/DwsOAEKAgICAgICAgIB/DwsRAEKAgICAgICAgIB/QgF8DwsFAEIADwsFAEIKDwsFAEJ/DwsFAEIqDwsGAEHAhD0LBQBB6AcLCABBmYG80AALBgBBj9QGCwYAQsCEPQsFAELoBwsLAEKZs4KA8IG8BQsGAEKP1AYL", + "AGFzbQEAAAABPQxgAX8BfmABfgF/YAF9AX9gAXwBf2ABfQF+YAF8AX5gAX8BfWABfgF9YAF/AXxgAX4BfGABfQF8YAF8AX0DIiEAAAECAgMDBAQFBQICAwMEBAUFBgcICQYHCAkKCwYJAgUHkQUhEGk2NC5leHRlbmRfaTMyX3MAABBpNjQuZXh0ZW5kX2kzMl91AAEMaTMyLndyYXBfaTY0AAIPaTMyLnRydW5jX2YzMl9zAAMPaTMyLnRydW5jX2YzMl91AAQPaTMyLnRydW5jX2Y2NF9zAAUPaTMyLnRydW5jX2Y2NF91AAYPaTY0LnRydW5jX2YzMl9zAAcPaTY0LnRydW5jX2YzMl91AAgPaTY0LnRydW5jX2Y2NF9zAAkPaTY0LnRydW5jX2Y2NF91AAoTaTMyLnRydW5jX3NhdF9mMzJfcwALE2kzMi50cnVuY19zYXRfZjMyX3UADBNpMzIudHJ1bmNfc2F0X2Y2NF9zAA0TaTMyLnRydW5jX3NhdF9mNjRfdQAOE2k2NC50cnVuY19zYXRfZjMyX3MADxNpNjQudHJ1bmNfc2F0X2YzMl91ABATaTY0LnRydW5jX3NhdF9mNjRfcwARE2k2NC50cnVuY19zYXRfZjY0X3UAEhFmMzIuY29udmVydF9pMzJfcwATEWYzMi5jb252ZXJ0X2k2NF9zABQRZjY0LmNvbnZlcnRfaTMyX3MAFRFmNjQuY29udmVydF9pNjRfcwAWEWYzMi5jb252ZXJ0X2kzMl91ABcRZjMyLmNvbnZlcnRfaTY0X3UAGBFmNjQuY29udmVydF9pMzJfdQAZEWY2NC5jb252ZXJ0X2k2NF91ABoPZjY0LnByb21vdGVfZjMyABsOZjMyLmRlbW90ZV9mNjQAHBNmMzIucmVpbnRlcnByZXRfaTMyAB0TZjY0LnJlaW50ZXJwcmV0X2k2NAAeE2kzMi5yZWludGVycHJldF9mMzIAHxNpNjQucmVpbnRlcnByZXRfZjY0ACAKzwEhBQAgAKwLBQAgAK0LBQAgAKcLBQAgAKgLBQAgAKkLBQAgAKoLBQAgAKsLBQAgAK4LBQAgAK8LBQAgALALBQAgALELBgAgAPwACwYAIAD8AQsGACAA/AILBgAgAPwDCwYAIAD8BAsGACAA/AULBgAgAPwGCwYAIAD8BwsFACAAsgsFACAAtAsFACAAtwsFACAAuQsFACAAswsFACAAtQsFACAAuAsFACAAugsFACAAuwsFACAAtgsFACAAvgsFACAAvwsFACAAvAsFACAAvQs=", + "AGFzbQEAAAABCwJgAn9/AGACfn4AAwUEAAABAQdNBBBub19kY2UuaTMyLmRpdl9zAAAQbm9fZGNlLmkzMi5kaXZfdQABEG5vX2RjZS5pNjQuZGl2X3MAAhBub19kY2UuaTY0LmRpdl91AAMKJQQIACAAIAFtGgsIACAAIAFuGgsIACAAIAF/GgsIACAAIAGAGgs=", + "AGFzbQEAAAABCwJgAn9/AGACfn4AAwUEAAABAQdNBBBub19kY2UuaTMyLnJlbV9zAAAQbm9fZGNlLmkzMi5yZW1fdQABEG5vX2RjZS5pNjQucmVtX3MAAhBub19kY2UuaTY0LnJlbV91AAMKJQQIACAAIAFvGgsIACAAIAFwGgsIACAAIAGBGgsIACAAIAGCGgs=", + "AGFzbQEAAAABCQJgAX0AYAF8AAMJCAAAAQEAAAEBB8kBCBZub19kY2UuaTMyLnRydW5jX2YzMl9zAAAWbm9fZGNlLmkzMi50cnVuY19mMzJfdQABFm5vX2RjZS5pMzIudHJ1bmNfZjY0X3MAAhZub19kY2UuaTMyLnRydW5jX2Y2NF91AAMWbm9fZGNlLmk2NC50cnVuY19mMzJfcwAEFm5vX2RjZS5pNjQudHJ1bmNfZjMyX3UABRZub19kY2UuaTY0LnRydW5jX2Y2NF9zAAYWbm9fZGNlLmk2NC50cnVuY19mNjRfdQAHCjkIBgAgAKgaCwYAIACpGgsGACAAqhoLBgAgAKsaCwYAIACuGgsGACAArxoLBgAgALAaCwYAIACxGgs=", + "AGFzbQEAAAABBQFgAX8AAw8OAAAAAAAAAAAAAAAAAAAFAwEAAQehAg4Pbm9fZGNlLmkzMi5sb2FkAAATbm9fZGNlLmkzMi5sb2FkMTZfcwABE25vX2RjZS5pMzIubG9hZDE2X3UAAhJub19kY2UuaTMyLmxvYWQ4X3MAAxJub19kY2UuaTMyLmxvYWQ4X3UABA9ub19kY2UuaTY0LmxvYWQABRNub19kY2UuaTY0LmxvYWQzMl9zAAYTbm9fZGNlLmk2NC5sb2FkMzJfdQAHE25vX2RjZS5pNjQubG9hZDE2X3MACBNub19kY2UuaTY0LmxvYWQxNl91AAkSbm9fZGNlLmk2NC5sb2FkOF9zAAoSbm9fZGNlLmk2NC5sb2FkOF91AAsPbm9fZGNlLmYzMi5sb2FkAAwPbm9fZGNlLmY2NC5sb2FkAA0Kfw4IACAAKAIAGgsIACAALgEAGgsIACAALwEAGgsIACAALAAAGgsIACAALQAAGgsIACAAKQMAGgsIACAANAIAGgsIACAANQIAGgsIACAAMgEAGgsIACAAMwEAGgsIACAAMAAAGgsIACAAMQAAGgsIACAAKgIAGgsIACAAKwMAGgs=", +]; +export const script = "[[\"file\",\"i32.wast\"],[\"module\",3,0],[\"invoke\",37,0,\"add\",[\"i32:1\",\"i32:1\"]],[\"invoke\",38,0,\"add\",[\"i32:1\",\"i32:0\"]],[\"invoke\",39,0,\"add\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",40,0,\"add\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",41,0,\"add\",[\"i32:2147483647\",\"i32:1\"]],[\"invoke\",42,0,\"add\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",43,0,\"add\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",44,0,\"add\",[\"i32:1073741823\",\"i32:1\"]],[\"invoke\",46,0,\"sub\",[\"i32:1\",\"i32:1\"]],[\"invoke\",47,0,\"sub\",[\"i32:1\",\"i32:0\"]],[\"invoke\",48,0,\"sub\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",49,0,\"sub\",[\"i32:2147483647\",\"i32:4294967295\"]],[\"invoke\",50,0,\"sub\",[\"i32:2147483648\",\"i32:1\"]],[\"invoke\",51,0,\"sub\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",52,0,\"sub\",[\"i32:1073741823\",\"i32:4294967295\"]],[\"invoke\",54,0,\"mul\",[\"i32:1\",\"i32:1\"]],[\"invoke\",55,0,\"mul\",[\"i32:1\",\"i32:0\"]],[\"invoke\",56,0,\"mul\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",57,0,\"mul\",[\"i32:268435456\",\"i32:4096\"]],[\"invoke\",58,0,\"mul\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",59,0,\"mul\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",60,0,\"mul\",[\"i32:2147483647\",\"i32:4294967295\"]],[\"invoke\",61,0,\"mul\",[\"i32:19088743\",\"i32:1985229328\"]],[\"invoke\",62,0,\"mul\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",64,0,\"div_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",65,0,\"div_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",66,0,\"div_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",67,0,\"div_s\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",68,0,\"div_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",69,0,\"div_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",70,0,\"div_s\",[\"i32:0\",\"i32:4294967295\"]],[\"invoke\",71,0,\"div_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",72,0,\"div_s\",[\"i32:2147483648\",\"i32:2\"]],[\"invoke\",73,0,\"div_s\",[\"i32:2147483649\",\"i32:1000\"]],[\"invoke\",74,0,\"div_s\",[\"i32:5\",\"i32:2\"]],[\"invoke\",75,0,\"div_s\",[\"i32:4294967291\",\"i32:2\"]],[\"invoke\",76,0,\"div_s\",[\"i32:5\",\"i32:4294967294\"]],[\"invoke\",77,0,\"div_s\",[\"i32:4294967291\",\"i32:4294967294\"]],[\"invoke\",78,0,\"div_s\",[\"i32:7\",\"i32:3\"]],[\"invoke\",79,0,\"div_s\",[\"i32:4294967289\",\"i32:3\"]],[\"invoke\",80,0,\"div_s\",[\"i32:7\",\"i32:4294967293\"]],[\"invoke\",81,0,\"div_s\",[\"i32:4294967289\",\"i32:4294967293\"]],[\"invoke\",82,0,\"div_s\",[\"i32:11\",\"i32:5\"]],[\"invoke\",83,0,\"div_s\",[\"i32:17\",\"i32:7\"]],[\"invoke\",85,0,\"div_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",86,0,\"div_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",87,0,\"div_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",88,0,\"div_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",89,0,\"div_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",90,0,\"div_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",91,0,\"div_u\",[\"i32:2147483648\",\"i32:2\"]],[\"invoke\",92,0,\"div_u\",[\"i32:2414874608\",\"i32:65537\"]],[\"invoke\",93,0,\"div_u\",[\"i32:2147483649\",\"i32:1000\"]],[\"invoke\",94,0,\"div_u\",[\"i32:5\",\"i32:2\"]],[\"invoke\",95,0,\"div_u\",[\"i32:4294967291\",\"i32:2\"]],[\"invoke\",96,0,\"div_u\",[\"i32:5\",\"i32:4294967294\"]],[\"invoke\",97,0,\"div_u\",[\"i32:4294967291\",\"i32:4294967294\"]],[\"invoke\",98,0,\"div_u\",[\"i32:7\",\"i32:3\"]],[\"invoke\",99,0,\"div_u\",[\"i32:11\",\"i32:5\"]],[\"invoke\",100,0,\"div_u\",[\"i32:17\",\"i32:7\"]],[\"invoke\",102,0,\"rem_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",103,0,\"rem_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",104,0,\"rem_s\",[\"i32:2147483647\",\"i32:4294967295\"]],[\"invoke\",105,0,\"rem_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",106,0,\"rem_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",107,0,\"rem_s\",[\"i32:0\",\"i32:4294967295\"]],[\"invoke\",108,0,\"rem_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",109,0,\"rem_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",110,0,\"rem_s\",[\"i32:2147483648\",\"i32:2\"]],[\"invoke\",111,0,\"rem_s\",[\"i32:2147483649\",\"i32:1000\"]],[\"invoke\",112,0,\"rem_s\",[\"i32:5\",\"i32:2\"]],[\"invoke\",113,0,\"rem_s\",[\"i32:4294967291\",\"i32:2\"]],[\"invoke\",114,0,\"rem_s\",[\"i32:5\",\"i32:4294967294\"]],[\"invoke\",115,0,\"rem_s\",[\"i32:4294967291\",\"i32:4294967294\"]],[\"invoke\",116,0,\"rem_s\",[\"i32:7\",\"i32:3\"]],[\"invoke\",117,0,\"rem_s\",[\"i32:4294967289\",\"i32:3\"]],[\"invoke\",118,0,\"rem_s\",[\"i32:7\",\"i32:4294967293\"]],[\"invoke\",119,0,\"rem_s\",[\"i32:4294967289\",\"i32:4294967293\"]],[\"invoke\",120,0,\"rem_s\",[\"i32:11\",\"i32:5\"]],[\"invoke\",121,0,\"rem_s\",[\"i32:17\",\"i32:7\"]],[\"invoke\",123,0,\"rem_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",124,0,\"rem_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",125,0,\"rem_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",126,0,\"rem_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",127,0,\"rem_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",128,0,\"rem_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",129,0,\"rem_u\",[\"i32:2147483648\",\"i32:2\"]],[\"invoke\",130,0,\"rem_u\",[\"i32:2414874608\",\"i32:65537\"]],[\"invoke\",131,0,\"rem_u\",[\"i32:2147483649\",\"i32:1000\"]],[\"invoke\",132,0,\"rem_u\",[\"i32:5\",\"i32:2\"]],[\"invoke\",133,0,\"rem_u\",[\"i32:4294967291\",\"i32:2\"]],[\"invoke\",134,0,\"rem_u\",[\"i32:5\",\"i32:4294967294\"]],[\"invoke\",135,0,\"rem_u\",[\"i32:4294967291\",\"i32:4294967294\"]],[\"invoke\",136,0,\"rem_u\",[\"i32:7\",\"i32:3\"]],[\"invoke\",137,0,\"rem_u\",[\"i32:11\",\"i32:5\"]],[\"invoke\",138,0,\"rem_u\",[\"i32:17\",\"i32:7\"]],[\"invoke\",140,0,\"and\",[\"i32:1\",\"i32:0\"]],[\"invoke\",141,0,\"and\",[\"i32:0\",\"i32:1\"]],[\"invoke\",142,0,\"and\",[\"i32:1\",\"i32:1\"]],[\"invoke\",143,0,\"and\",[\"i32:0\",\"i32:0\"]],[\"invoke\",144,0,\"and\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",145,0,\"and\",[\"i32:2147483647\",\"i32:4294967295\"]],[\"invoke\",146,0,\"and\",[\"i32:4042326015\",\"i32:4294963440\"]],[\"invoke\",147,0,\"and\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",149,0,\"or\",[\"i32:1\",\"i32:0\"]],[\"invoke\",150,0,\"or\",[\"i32:0\",\"i32:1\"]],[\"invoke\",151,0,\"or\",[\"i32:1\",\"i32:1\"]],[\"invoke\",152,0,\"or\",[\"i32:0\",\"i32:0\"]],[\"invoke\",153,0,\"or\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",154,0,\"or\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",155,0,\"or\",[\"i32:4042326015\",\"i32:4294963440\"]],[\"invoke\",156,0,\"or\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",158,0,\"xor\",[\"i32:1\",\"i32:0\"]],[\"invoke\",159,0,\"xor\",[\"i32:0\",\"i32:1\"]],[\"invoke\",160,0,\"xor\",[\"i32:1\",\"i32:1\"]],[\"invoke\",161,0,\"xor\",[\"i32:0\",\"i32:0\"]],[\"invoke\",162,0,\"xor\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",163,0,\"xor\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",164,0,\"xor\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",165,0,\"xor\",[\"i32:4294967295\",\"i32:2147483647\"]],[\"invoke\",166,0,\"xor\",[\"i32:4042326015\",\"i32:4294963440\"]],[\"invoke\",167,0,\"xor\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",169,0,\"shl\",[\"i32:1\",\"i32:1\"]],[\"invoke\",170,0,\"shl\",[\"i32:1\",\"i32:0\"]],[\"invoke\",171,0,\"shl\",[\"i32:2147483647\",\"i32:1\"]],[\"invoke\",172,0,\"shl\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",173,0,\"shl\",[\"i32:2147483648\",\"i32:1\"]],[\"invoke\",174,0,\"shl\",[\"i32:1073741824\",\"i32:1\"]],[\"invoke\",175,0,\"shl\",[\"i32:1\",\"i32:31\"]],[\"invoke\",176,0,\"shl\",[\"i32:1\",\"i32:32\"]],[\"invoke\",177,0,\"shl\",[\"i32:1\",\"i32:33\"]],[\"invoke\",178,0,\"shl\",[\"i32:1\",\"i32:4294967295\"]],[\"invoke\",179,0,\"shl\",[\"i32:1\",\"i32:2147483647\"]],[\"invoke\",181,0,\"shr_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",182,0,\"shr_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",183,0,\"shr_s\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",184,0,\"shr_s\",[\"i32:2147483647\",\"i32:1\"]],[\"invoke\",185,0,\"shr_s\",[\"i32:2147483648\",\"i32:1\"]],[\"invoke\",186,0,\"shr_s\",[\"i32:1073741824\",\"i32:1\"]],[\"invoke\",187,0,\"shr_s\",[\"i32:1\",\"i32:32\"]],[\"invoke\",188,0,\"shr_s\",[\"i32:1\",\"i32:33\"]],[\"invoke\",189,0,\"shr_s\",[\"i32:1\",\"i32:4294967295\"]],[\"invoke\",190,0,\"shr_s\",[\"i32:1\",\"i32:2147483647\"]],[\"invoke\",191,0,\"shr_s\",[\"i32:1\",\"i32:2147483648\"]],[\"invoke\",192,0,\"shr_s\",[\"i32:2147483648\",\"i32:31\"]],[\"invoke\",193,0,\"shr_s\",[\"i32:4294967295\",\"i32:32\"]],[\"invoke\",194,0,\"shr_s\",[\"i32:4294967295\",\"i32:33\"]],[\"invoke\",195,0,\"shr_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",196,0,\"shr_s\",[\"i32:4294967295\",\"i32:2147483647\"]],[\"invoke\",197,0,\"shr_s\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",199,0,\"shr_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",200,0,\"shr_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",201,0,\"shr_u\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",202,0,\"shr_u\",[\"i32:2147483647\",\"i32:1\"]],[\"invoke\",203,0,\"shr_u\",[\"i32:2147483648\",\"i32:1\"]],[\"invoke\",204,0,\"shr_u\",[\"i32:1073741824\",\"i32:1\"]],[\"invoke\",205,0,\"shr_u\",[\"i32:1\",\"i32:32\"]],[\"invoke\",206,0,\"shr_u\",[\"i32:1\",\"i32:33\"]],[\"invoke\",207,0,\"shr_u\",[\"i32:1\",\"i32:4294967295\"]],[\"invoke\",208,0,\"shr_u\",[\"i32:1\",\"i32:2147483647\"]],[\"invoke\",209,0,\"shr_u\",[\"i32:1\",\"i32:2147483648\"]],[\"invoke\",210,0,\"shr_u\",[\"i32:2147483648\",\"i32:31\"]],[\"invoke\",211,0,\"shr_u\",[\"i32:4294967295\",\"i32:32\"]],[\"invoke\",212,0,\"shr_u\",[\"i32:4294967295\",\"i32:33\"]],[\"invoke\",213,0,\"shr_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",214,0,\"shr_u\",[\"i32:4294967295\",\"i32:2147483647\"]],[\"invoke\",215,0,\"shr_u\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",217,0,\"rotl\",[\"i32:1\",\"i32:1\"]],[\"invoke\",218,0,\"rotl\",[\"i32:1\",\"i32:0\"]],[\"invoke\",219,0,\"rotl\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",220,0,\"rotl\",[\"i32:1\",\"i32:32\"]],[\"invoke\",221,0,\"rotl\",[\"i32:2882377846\",\"i32:1\"]],[\"invoke\",222,0,\"rotl\",[\"i32:4261469184\",\"i32:4\"]],[\"invoke\",223,0,\"rotl\",[\"i32:2965492451\",\"i32:5\"]],[\"invoke\",224,0,\"rotl\",[\"i32:32768\",\"i32:37\"]],[\"invoke\",225,0,\"rotl\",[\"i32:2965492451\",\"i32:65285\"]],[\"invoke\",226,0,\"rotl\",[\"i32:1989852383\",\"i32:4294967277\"]],[\"invoke\",227,0,\"rotl\",[\"i32:1989852383\",\"i32:2147483661\"]],[\"invoke\",228,0,\"rotl\",[\"i32:1\",\"i32:31\"]],[\"invoke\",229,0,\"rotl\",[\"i32:2147483648\",\"i32:1\"]],[\"invoke\",231,0,\"rotr\",[\"i32:1\",\"i32:1\"]],[\"invoke\",232,0,\"rotr\",[\"i32:1\",\"i32:0\"]],[\"invoke\",233,0,\"rotr\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",234,0,\"rotr\",[\"i32:1\",\"i32:32\"]],[\"invoke\",235,0,\"rotr\",[\"i32:4278242304\",\"i32:1\"]],[\"invoke\",236,0,\"rotr\",[\"i32:524288\",\"i32:4\"]],[\"invoke\",237,0,\"rotr\",[\"i32:2965492451\",\"i32:5\"]],[\"invoke\",238,0,\"rotr\",[\"i32:32768\",\"i32:37\"]],[\"invoke\",239,0,\"rotr\",[\"i32:2965492451\",\"i32:65285\"]],[\"invoke\",240,0,\"rotr\",[\"i32:1989852383\",\"i32:4294967277\"]],[\"invoke\",241,0,\"rotr\",[\"i32:1989852383\",\"i32:2147483661\"]],[\"invoke\",242,0,\"rotr\",[\"i32:1\",\"i32:31\"]],[\"invoke\",243,0,\"rotr\",[\"i32:2147483648\",\"i32:31\"]],[\"invoke\",245,0,\"clz\",[\"i32:4294967295\"]],[\"invoke\",246,0,\"clz\",[\"i32:0\"]],[\"invoke\",247,0,\"clz\",[\"i32:32768\"]],[\"invoke\",248,0,\"clz\",[\"i32:255\"]],[\"invoke\",249,0,\"clz\",[\"i32:2147483648\"]],[\"invoke\",250,0,\"clz\",[\"i32:1\"]],[\"invoke\",251,0,\"clz\",[\"i32:2\"]],[\"invoke\",252,0,\"clz\",[\"i32:2147483647\"]],[\"invoke\",254,0,\"ctz\",[\"i32:4294967295\"]],[\"invoke\",255,0,\"ctz\",[\"i32:0\"]],[\"invoke\",256,0,\"ctz\",[\"i32:32768\"]],[\"invoke\",257,0,\"ctz\",[\"i32:65536\"]],[\"invoke\",258,0,\"ctz\",[\"i32:2147483648\"]],[\"invoke\",259,0,\"ctz\",[\"i32:2147483647\"]],[\"invoke\",261,0,\"popcnt\",[\"i32:4294967295\"]],[\"invoke\",262,0,\"popcnt\",[\"i32:0\"]],[\"invoke\",263,0,\"popcnt\",[\"i32:32768\"]],[\"invoke\",264,0,\"popcnt\",[\"i32:2147516416\"]],[\"invoke\",265,0,\"popcnt\",[\"i32:2147483647\"]],[\"invoke\",266,0,\"popcnt\",[\"i32:2863311530\"]],[\"invoke\",267,0,\"popcnt\",[\"i32:1431655765\"]],[\"invoke\",268,0,\"popcnt\",[\"i32:3735928559\"]],[\"invoke\",270,0,\"extend8_s\",[\"i32:0\"]],[\"invoke\",271,0,\"extend8_s\",[\"i32:127\"]],[\"invoke\",272,0,\"extend8_s\",[\"i32:128\"]],[\"invoke\",273,0,\"extend8_s\",[\"i32:255\"]],[\"invoke\",274,0,\"extend8_s\",[\"i32:19088640\"]],[\"invoke\",275,0,\"extend8_s\",[\"i32:4275878528\"]],[\"invoke\",276,0,\"extend8_s\",[\"i32:4294967295\"]],[\"invoke\",278,0,\"extend16_s\",[\"i32:0\"]],[\"invoke\",279,0,\"extend16_s\",[\"i32:32767\"]],[\"invoke\",280,0,\"extend16_s\",[\"i32:32768\"]],[\"invoke\",281,0,\"extend16_s\",[\"i32:65535\"]],[\"invoke\",282,0,\"extend16_s\",[\"i32:19070976\"]],[\"invoke\",283,0,\"extend16_s\",[\"i32:4275863552\"]],[\"invoke\",284,0,\"extend16_s\",[\"i32:4294967295\"]],[\"invoke\",286,0,\"eqz\",[\"i32:0\"]],[\"invoke\",287,0,\"eqz\",[\"i32:1\"]],[\"invoke\",288,0,\"eqz\",[\"i32:2147483648\"]],[\"invoke\",289,0,\"eqz\",[\"i32:2147483647\"]],[\"invoke\",290,0,\"eqz\",[\"i32:4294967295\"]],[\"invoke\",292,0,\"eq\",[\"i32:0\",\"i32:0\"]],[\"invoke\",293,0,\"eq\",[\"i32:1\",\"i32:1\"]],[\"invoke\",294,0,\"eq\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",295,0,\"eq\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",296,0,\"eq\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",297,0,\"eq\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",298,0,\"eq\",[\"i32:1\",\"i32:0\"]],[\"invoke\",299,0,\"eq\",[\"i32:0\",\"i32:1\"]],[\"invoke\",300,0,\"eq\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",301,0,\"eq\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",302,0,\"eq\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",303,0,\"eq\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",304,0,\"eq\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",305,0,\"eq\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",307,0,\"ne\",[\"i32:0\",\"i32:0\"]],[\"invoke\",308,0,\"ne\",[\"i32:1\",\"i32:1\"]],[\"invoke\",309,0,\"ne\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",310,0,\"ne\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",311,0,\"ne\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",312,0,\"ne\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",313,0,\"ne\",[\"i32:1\",\"i32:0\"]],[\"invoke\",314,0,\"ne\",[\"i32:0\",\"i32:1\"]],[\"invoke\",315,0,\"ne\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",316,0,\"ne\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",317,0,\"ne\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",318,0,\"ne\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",319,0,\"ne\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",320,0,\"ne\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",322,0,\"lt_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",323,0,\"lt_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",324,0,\"lt_s\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",325,0,\"lt_s\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",326,0,\"lt_s\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",327,0,\"lt_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",328,0,\"lt_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",329,0,\"lt_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",330,0,\"lt_s\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",331,0,\"lt_s\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",332,0,\"lt_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",333,0,\"lt_s\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",334,0,\"lt_s\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",335,0,\"lt_s\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",337,0,\"lt_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",338,0,\"lt_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",339,0,\"lt_u\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",340,0,\"lt_u\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",341,0,\"lt_u\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",342,0,\"lt_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",343,0,\"lt_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",344,0,\"lt_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",345,0,\"lt_u\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",346,0,\"lt_u\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",347,0,\"lt_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",348,0,\"lt_u\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",349,0,\"lt_u\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",350,0,\"lt_u\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",352,0,\"le_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",353,0,\"le_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",354,0,\"le_s\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",355,0,\"le_s\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",356,0,\"le_s\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",357,0,\"le_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",358,0,\"le_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",359,0,\"le_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",360,0,\"le_s\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",361,0,\"le_s\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",362,0,\"le_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",363,0,\"le_s\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",364,0,\"le_s\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",365,0,\"le_s\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",367,0,\"le_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",368,0,\"le_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",369,0,\"le_u\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",370,0,\"le_u\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",371,0,\"le_u\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",372,0,\"le_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",373,0,\"le_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",374,0,\"le_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",375,0,\"le_u\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",376,0,\"le_u\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",377,0,\"le_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",378,0,\"le_u\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",379,0,\"le_u\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",380,0,\"le_u\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",382,0,\"gt_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",383,0,\"gt_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",384,0,\"gt_s\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",385,0,\"gt_s\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",386,0,\"gt_s\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",387,0,\"gt_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",388,0,\"gt_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",389,0,\"gt_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",390,0,\"gt_s\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",391,0,\"gt_s\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",392,0,\"gt_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",393,0,\"gt_s\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",394,0,\"gt_s\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",395,0,\"gt_s\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",397,0,\"gt_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",398,0,\"gt_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",399,0,\"gt_u\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",400,0,\"gt_u\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",401,0,\"gt_u\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",402,0,\"gt_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",403,0,\"gt_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",404,0,\"gt_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",405,0,\"gt_u\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",406,0,\"gt_u\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",407,0,\"gt_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",408,0,\"gt_u\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",409,0,\"gt_u\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",410,0,\"gt_u\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",412,0,\"ge_s\",[\"i32:0\",\"i32:0\"]],[\"invoke\",413,0,\"ge_s\",[\"i32:1\",\"i32:1\"]],[\"invoke\",414,0,\"ge_s\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",415,0,\"ge_s\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",416,0,\"ge_s\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",417,0,\"ge_s\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",418,0,\"ge_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",419,0,\"ge_s\",[\"i32:0\",\"i32:1\"]],[\"invoke\",420,0,\"ge_s\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",421,0,\"ge_s\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",422,0,\"ge_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",423,0,\"ge_s\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",424,0,\"ge_s\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",425,0,\"ge_s\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"invoke\",427,0,\"ge_u\",[\"i32:0\",\"i32:0\"]],[\"invoke\",428,0,\"ge_u\",[\"i32:1\",\"i32:1\"]],[\"invoke\",429,0,\"ge_u\",[\"i32:4294967295\",\"i32:1\"]],[\"invoke\",430,0,\"ge_u\",[\"i32:2147483648\",\"i32:2147483648\"]],[\"invoke\",431,0,\"ge_u\",[\"i32:2147483647\",\"i32:2147483647\"]],[\"invoke\",432,0,\"ge_u\",[\"i32:4294967295\",\"i32:4294967295\"]],[\"invoke\",433,0,\"ge_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",434,0,\"ge_u\",[\"i32:0\",\"i32:1\"]],[\"invoke\",435,0,\"ge_u\",[\"i32:2147483648\",\"i32:0\"]],[\"invoke\",436,0,\"ge_u\",[\"i32:0\",\"i32:2147483648\"]],[\"invoke\",437,0,\"ge_u\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",438,0,\"ge_u\",[\"i32:4294967295\",\"i32:2147483648\"]],[\"invoke\",439,0,\"ge_u\",[\"i32:2147483648\",\"i32:2147483647\"]],[\"invoke\",440,0,\"ge_u\",[\"i32:2147483647\",\"i32:2147483648\"]],[\"file\",\"i64.wast\"],[\"module\",3,1],[\"invoke\",38,0,\"add\",[\"i64:1\",\"i64:1\"]],[\"invoke\",39,0,\"add\",[\"i64:1\",\"i64:0\"]],[\"invoke\",40,0,\"add\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",41,0,\"add\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",42,0,\"add\",[\"i64:9223372036854775807\",\"i64:1\"]],[\"invoke\",43,0,\"add\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",44,0,\"add\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",45,0,\"add\",[\"i64:1073741823\",\"i64:1\"]],[\"invoke\",47,0,\"sub\",[\"i64:1\",\"i64:1\"]],[\"invoke\",48,0,\"sub\",[\"i64:1\",\"i64:0\"]],[\"invoke\",49,0,\"sub\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",50,0,\"sub\",[\"i64:9223372036854775807\",\"i64:18446744073709551615\"]],[\"invoke\",51,0,\"sub\",[\"i64:9223372036854775808\",\"i64:1\"]],[\"invoke\",52,0,\"sub\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",53,0,\"sub\",[\"i64:1073741823\",\"i64:18446744073709551615\"]],[\"invoke\",55,0,\"mul\",[\"i64:1\",\"i64:1\"]],[\"invoke\",56,0,\"mul\",[\"i64:1\",\"i64:0\"]],[\"invoke\",57,0,\"mul\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",58,0,\"mul\",[\"i64:1152921504606846976\",\"i64:4096\"]],[\"invoke\",59,0,\"mul\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",60,0,\"mul\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",61,0,\"mul\",[\"i64:9223372036854775807\",\"i64:18446744073709551615\"]],[\"invoke\",62,0,\"mul\",[\"i64:81985529216486895\",\"i64:18364758544493064720\"]],[\"invoke\",63,0,\"mul\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",65,0,\"div_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",66,0,\"div_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",67,0,\"div_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",68,0,\"div_s\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",69,0,\"div_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",70,0,\"div_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",71,0,\"div_s\",[\"i64:0\",\"i64:18446744073709551615\"]],[\"invoke\",72,0,\"div_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",73,0,\"div_s\",[\"i64:9223372036854775808\",\"i64:2\"]],[\"invoke\",74,0,\"div_s\",[\"i64:9223372036854775809\",\"i64:1000\"]],[\"invoke\",75,0,\"div_s\",[\"i64:5\",\"i64:2\"]],[\"invoke\",76,0,\"div_s\",[\"i64:18446744073709551611\",\"i64:2\"]],[\"invoke\",77,0,\"div_s\",[\"i64:5\",\"i64:18446744073709551614\"]],[\"invoke\",78,0,\"div_s\",[\"i64:18446744073709551611\",\"i64:18446744073709551614\"]],[\"invoke\",79,0,\"div_s\",[\"i64:7\",\"i64:3\"]],[\"invoke\",80,0,\"div_s\",[\"i64:18446744073709551609\",\"i64:3\"]],[\"invoke\",81,0,\"div_s\",[\"i64:7\",\"i64:18446744073709551613\"]],[\"invoke\",82,0,\"div_s\",[\"i64:18446744073709551609\",\"i64:18446744073709551613\"]],[\"invoke\",83,0,\"div_s\",[\"i64:11\",\"i64:5\"]],[\"invoke\",84,0,\"div_s\",[\"i64:17\",\"i64:7\"]],[\"invoke\",86,0,\"div_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",87,0,\"div_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",88,0,\"div_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",89,0,\"div_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",90,0,\"div_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",91,0,\"div_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",92,0,\"div_u\",[\"i64:9223372036854775808\",\"i64:2\"]],[\"invoke\",93,0,\"div_u\",[\"i64:10371807465568210928\",\"i64:4294967297\"]],[\"invoke\",94,0,\"div_u\",[\"i64:9223372036854775809\",\"i64:1000\"]],[\"invoke\",95,0,\"div_u\",[\"i64:5\",\"i64:2\"]],[\"invoke\",96,0,\"div_u\",[\"i64:18446744073709551611\",\"i64:2\"]],[\"invoke\",97,0,\"div_u\",[\"i64:5\",\"i64:18446744073709551614\"]],[\"invoke\",98,0,\"div_u\",[\"i64:18446744073709551611\",\"i64:18446744073709551614\"]],[\"invoke\",99,0,\"div_u\",[\"i64:7\",\"i64:3\"]],[\"invoke\",100,0,\"div_u\",[\"i64:11\",\"i64:5\"]],[\"invoke\",101,0,\"div_u\",[\"i64:17\",\"i64:7\"]],[\"invoke\",103,0,\"rem_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",104,0,\"rem_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",105,0,\"rem_s\",[\"i64:9223372036854775807\",\"i64:18446744073709551615\"]],[\"invoke\",106,0,\"rem_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",107,0,\"rem_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",108,0,\"rem_s\",[\"i64:0\",\"i64:18446744073709551615\"]],[\"invoke\",109,0,\"rem_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",110,0,\"rem_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",111,0,\"rem_s\",[\"i64:9223372036854775808\",\"i64:2\"]],[\"invoke\",112,0,\"rem_s\",[\"i64:9223372036854775809\",\"i64:1000\"]],[\"invoke\",113,0,\"rem_s\",[\"i64:5\",\"i64:2\"]],[\"invoke\",114,0,\"rem_s\",[\"i64:18446744073709551611\",\"i64:2\"]],[\"invoke\",115,0,\"rem_s\",[\"i64:5\",\"i64:18446744073709551614\"]],[\"invoke\",116,0,\"rem_s\",[\"i64:18446744073709551611\",\"i64:18446744073709551614\"]],[\"invoke\",117,0,\"rem_s\",[\"i64:7\",\"i64:3\"]],[\"invoke\",118,0,\"rem_s\",[\"i64:18446744073709551609\",\"i64:3\"]],[\"invoke\",119,0,\"rem_s\",[\"i64:7\",\"i64:18446744073709551613\"]],[\"invoke\",120,0,\"rem_s\",[\"i64:18446744073709551609\",\"i64:18446744073709551613\"]],[\"invoke\",121,0,\"rem_s\",[\"i64:11\",\"i64:5\"]],[\"invoke\",122,0,\"rem_s\",[\"i64:17\",\"i64:7\"]],[\"invoke\",124,0,\"rem_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",125,0,\"rem_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",126,0,\"rem_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",127,0,\"rem_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",128,0,\"rem_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",129,0,\"rem_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",130,0,\"rem_u\",[\"i64:9223372036854775808\",\"i64:2\"]],[\"invoke\",131,0,\"rem_u\",[\"i64:10371807465568210928\",\"i64:4294967297\"]],[\"invoke\",132,0,\"rem_u\",[\"i64:9223372036854775809\",\"i64:1000\"]],[\"invoke\",133,0,\"rem_u\",[\"i64:5\",\"i64:2\"]],[\"invoke\",134,0,\"rem_u\",[\"i64:18446744073709551611\",\"i64:2\"]],[\"invoke\",135,0,\"rem_u\",[\"i64:5\",\"i64:18446744073709551614\"]],[\"invoke\",136,0,\"rem_u\",[\"i64:18446744073709551611\",\"i64:18446744073709551614\"]],[\"invoke\",137,0,\"rem_u\",[\"i64:7\",\"i64:3\"]],[\"invoke\",138,0,\"rem_u\",[\"i64:11\",\"i64:5\"]],[\"invoke\",139,0,\"rem_u\",[\"i64:17\",\"i64:7\"]],[\"invoke\",141,0,\"and\",[\"i64:1\",\"i64:0\"]],[\"invoke\",142,0,\"and\",[\"i64:0\",\"i64:1\"]],[\"invoke\",143,0,\"and\",[\"i64:1\",\"i64:1\"]],[\"invoke\",144,0,\"and\",[\"i64:0\",\"i64:0\"]],[\"invoke\",145,0,\"and\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",146,0,\"and\",[\"i64:9223372036854775807\",\"i64:18446744073709551615\"]],[\"invoke\",147,0,\"and\",[\"i64:4042326015\",\"i64:4294963440\"]],[\"invoke\",148,0,\"and\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",150,0,\"or\",[\"i64:1\",\"i64:0\"]],[\"invoke\",151,0,\"or\",[\"i64:0\",\"i64:1\"]],[\"invoke\",152,0,\"or\",[\"i64:1\",\"i64:1\"]],[\"invoke\",153,0,\"or\",[\"i64:0\",\"i64:0\"]],[\"invoke\",154,0,\"or\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",155,0,\"or\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",156,0,\"or\",[\"i64:4042326015\",\"i64:4294963440\"]],[\"invoke\",157,0,\"or\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",159,0,\"xor\",[\"i64:1\",\"i64:0\"]],[\"invoke\",160,0,\"xor\",[\"i64:0\",\"i64:1\"]],[\"invoke\",161,0,\"xor\",[\"i64:1\",\"i64:1\"]],[\"invoke\",162,0,\"xor\",[\"i64:0\",\"i64:0\"]],[\"invoke\",163,0,\"xor\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",164,0,\"xor\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",165,0,\"xor\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",166,0,\"xor\",[\"i64:18446744073709551615\",\"i64:9223372036854775807\"]],[\"invoke\",167,0,\"xor\",[\"i64:4042326015\",\"i64:4294963440\"]],[\"invoke\",168,0,\"xor\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",170,0,\"shl\",[\"i64:1\",\"i64:1\"]],[\"invoke\",171,0,\"shl\",[\"i64:1\",\"i64:0\"]],[\"invoke\",172,0,\"shl\",[\"i64:9223372036854775807\",\"i64:1\"]],[\"invoke\",173,0,\"shl\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",174,0,\"shl\",[\"i64:9223372036854775808\",\"i64:1\"]],[\"invoke\",175,0,\"shl\",[\"i64:4611686018427387904\",\"i64:1\"]],[\"invoke\",176,0,\"shl\",[\"i64:1\",\"i64:63\"]],[\"invoke\",177,0,\"shl\",[\"i64:1\",\"i64:64\"]],[\"invoke\",178,0,\"shl\",[\"i64:1\",\"i64:65\"]],[\"invoke\",179,0,\"shl\",[\"i64:1\",\"i64:18446744073709551615\"]],[\"invoke\",180,0,\"shl\",[\"i64:1\",\"i64:9223372036854775807\"]],[\"invoke\",182,0,\"shr_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",183,0,\"shr_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",184,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",185,0,\"shr_s\",[\"i64:9223372036854775807\",\"i64:1\"]],[\"invoke\",186,0,\"shr_s\",[\"i64:9223372036854775808\",\"i64:1\"]],[\"invoke\",187,0,\"shr_s\",[\"i64:4611686018427387904\",\"i64:1\"]],[\"invoke\",188,0,\"shr_s\",[\"i64:1\",\"i64:64\"]],[\"invoke\",189,0,\"shr_s\",[\"i64:1\",\"i64:65\"]],[\"invoke\",190,0,\"shr_s\",[\"i64:1\",\"i64:18446744073709551615\"]],[\"invoke\",191,0,\"shr_s\",[\"i64:1\",\"i64:9223372036854775807\"]],[\"invoke\",192,0,\"shr_s\",[\"i64:1\",\"i64:9223372036854775808\"]],[\"invoke\",193,0,\"shr_s\",[\"i64:9223372036854775808\",\"i64:63\"]],[\"invoke\",194,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:64\"]],[\"invoke\",195,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:65\"]],[\"invoke\",196,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",197,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775807\"]],[\"invoke\",198,0,\"shr_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",200,0,\"shr_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",201,0,\"shr_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",202,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",203,0,\"shr_u\",[\"i64:9223372036854775807\",\"i64:1\"]],[\"invoke\",204,0,\"shr_u\",[\"i64:9223372036854775808\",\"i64:1\"]],[\"invoke\",205,0,\"shr_u\",[\"i64:4611686018427387904\",\"i64:1\"]],[\"invoke\",206,0,\"shr_u\",[\"i64:1\",\"i64:64\"]],[\"invoke\",207,0,\"shr_u\",[\"i64:1\",\"i64:65\"]],[\"invoke\",208,0,\"shr_u\",[\"i64:1\",\"i64:18446744073709551615\"]],[\"invoke\",209,0,\"shr_u\",[\"i64:1\",\"i64:9223372036854775807\"]],[\"invoke\",210,0,\"shr_u\",[\"i64:1\",\"i64:9223372036854775808\"]],[\"invoke\",211,0,\"shr_u\",[\"i64:9223372036854775808\",\"i64:63\"]],[\"invoke\",212,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:64\"]],[\"invoke\",213,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:65\"]],[\"invoke\",214,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",215,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775807\"]],[\"invoke\",216,0,\"shr_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",218,0,\"rotl\",[\"i64:1\",\"i64:1\"]],[\"invoke\",219,0,\"rotl\",[\"i64:1\",\"i64:0\"]],[\"invoke\",220,0,\"rotl\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",221,0,\"rotl\",[\"i64:1\",\"i64:64\"]],[\"invoke\",222,0,\"rotl\",[\"i64:12379718583323101902\",\"i64:1\"]],[\"invoke\",223,0,\"rotl\",[\"i64:18302628889324683264\",\"i64:4\"]],[\"invoke\",224,0,\"rotl\",[\"i64:12379570969274382345\",\"i64:53\"]],[\"invoke\",225,0,\"rotl\",[\"i64:12380715672649826460\",\"i64:63\"]],[\"invoke\",226,0,\"rotl\",[\"i64:12379570969274382345\",\"i64:245\"]],[\"invoke\",227,0,\"rotl\",[\"i64:12379676934707509257\",\"i64:18446744073709551597\"]],[\"invoke\",228,0,\"rotl\",[\"i64:12380715672649826460\",\"i64:9223372036854775871\"]],[\"invoke\",229,0,\"rotl\",[\"i64:1\",\"i64:63\"]],[\"invoke\",230,0,\"rotl\",[\"i64:9223372036854775808\",\"i64:1\"]],[\"invoke\",232,0,\"rotr\",[\"i64:1\",\"i64:1\"]],[\"invoke\",233,0,\"rotr\",[\"i64:1\",\"i64:0\"]],[\"invoke\",234,0,\"rotr\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",235,0,\"rotr\",[\"i64:1\",\"i64:64\"]],[\"invoke\",236,0,\"rotr\",[\"i64:12379718583323101902\",\"i64:1\"]],[\"invoke\",237,0,\"rotr\",[\"i64:18302628889324683264\",\"i64:4\"]],[\"invoke\",238,0,\"rotr\",[\"i64:12379570969274382345\",\"i64:53\"]],[\"invoke\",239,0,\"rotr\",[\"i64:12380715672649826460\",\"i64:63\"]],[\"invoke\",240,0,\"rotr\",[\"i64:12379570969274382345\",\"i64:245\"]],[\"invoke\",241,0,\"rotr\",[\"i64:12379676934707509257\",\"i64:18446744073709551597\"]],[\"invoke\",242,0,\"rotr\",[\"i64:12380715672649826460\",\"i64:9223372036854775871\"]],[\"invoke\",243,0,\"rotr\",[\"i64:1\",\"i64:63\"]],[\"invoke\",244,0,\"rotr\",[\"i64:9223372036854775808\",\"i64:63\"]],[\"invoke\",246,0,\"clz\",[\"i64:18446744073709551615\"]],[\"invoke\",247,0,\"clz\",[\"i64:0\"]],[\"invoke\",248,0,\"clz\",[\"i64:32768\"]],[\"invoke\",249,0,\"clz\",[\"i64:255\"]],[\"invoke\",250,0,\"clz\",[\"i64:9223372036854775808\"]],[\"invoke\",251,0,\"clz\",[\"i64:1\"]],[\"invoke\",252,0,\"clz\",[\"i64:2\"]],[\"invoke\",253,0,\"clz\",[\"i64:9223372036854775807\"]],[\"invoke\",255,0,\"ctz\",[\"i64:18446744073709551615\"]],[\"invoke\",256,0,\"ctz\",[\"i64:0\"]],[\"invoke\",257,0,\"ctz\",[\"i64:32768\"]],[\"invoke\",258,0,\"ctz\",[\"i64:65536\"]],[\"invoke\",259,0,\"ctz\",[\"i64:9223372036854775808\"]],[\"invoke\",260,0,\"ctz\",[\"i64:9223372036854775807\"]],[\"invoke\",262,0,\"popcnt\",[\"i64:18446744073709551615\"]],[\"invoke\",263,0,\"popcnt\",[\"i64:0\"]],[\"invoke\",264,0,\"popcnt\",[\"i64:32768\"]],[\"invoke\",265,0,\"popcnt\",[\"i64:9223512776490647552\"]],[\"invoke\",266,0,\"popcnt\",[\"i64:9223372036854775807\"]],[\"invoke\",267,0,\"popcnt\",[\"i64:12297829381041378645\"]],[\"invoke\",268,0,\"popcnt\",[\"i64:11068046444512062122\"]],[\"invoke\",269,0,\"popcnt\",[\"i64:16045690984833335023\"]],[\"invoke\",271,0,\"extend8_s\",[\"i64:0\"]],[\"invoke\",272,0,\"extend8_s\",[\"i64:127\"]],[\"invoke\",273,0,\"extend8_s\",[\"i64:128\"]],[\"invoke\",274,0,\"extend8_s\",[\"i64:255\"]],[\"invoke\",275,0,\"extend8_s\",[\"i64:81985529216486656\"]],[\"invoke\",276,0,\"extend8_s\",[\"i64:18364758544493064832\"]],[\"invoke\",277,0,\"extend8_s\",[\"i64:18446744073709551615\"]],[\"invoke\",279,0,\"extend16_s\",[\"i64:0\"]],[\"invoke\",280,0,\"extend16_s\",[\"i64:32767\"]],[\"invoke\",281,0,\"extend16_s\",[\"i64:32768\"]],[\"invoke\",282,0,\"extend16_s\",[\"i64:65535\"]],[\"invoke\",283,0,\"extend16_s\",[\"i64:1311768467463733248\"]],[\"invoke\",284,0,\"extend16_s\",[\"i64:18364758544493084672\"]],[\"invoke\",285,0,\"extend16_s\",[\"i64:18446744073709551615\"]],[\"invoke\",287,0,\"extend32_s\",[\"i64:0\"]],[\"invoke\",288,0,\"extend32_s\",[\"i64:32767\"]],[\"invoke\",289,0,\"extend32_s\",[\"i64:32768\"]],[\"invoke\",290,0,\"extend32_s\",[\"i64:65535\"]],[\"invoke\",291,0,\"extend32_s\",[\"i64:2147483647\"]],[\"invoke\",292,0,\"extend32_s\",[\"i64:2147483648\"]],[\"invoke\",293,0,\"extend32_s\",[\"i64:4294967295\"]],[\"invoke\",294,0,\"extend32_s\",[\"i64:81985526906748928\"]],[\"invoke\",295,0,\"extend32_s\",[\"i64:18364758544655319040\"]],[\"invoke\",296,0,\"extend32_s\",[\"i64:18446744073709551615\"]],[\"invoke\",298,0,\"eqz\",[\"i64:0\"]],[\"invoke\",299,0,\"eqz\",[\"i64:1\"]],[\"invoke\",300,0,\"eqz\",[\"i64:9223372036854775808\"]],[\"invoke\",301,0,\"eqz\",[\"i64:9223372036854775807\"]],[\"invoke\",302,0,\"eqz\",[\"i64:18446744073709551615\"]],[\"invoke\",304,0,\"eq\",[\"i64:0\",\"i64:0\"]],[\"invoke\",305,0,\"eq\",[\"i64:1\",\"i64:1\"]],[\"invoke\",306,0,\"eq\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",307,0,\"eq\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",308,0,\"eq\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",309,0,\"eq\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",310,0,\"eq\",[\"i64:1\",\"i64:0\"]],[\"invoke\",311,0,\"eq\",[\"i64:0\",\"i64:1\"]],[\"invoke\",312,0,\"eq\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",313,0,\"eq\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",314,0,\"eq\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",315,0,\"eq\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",316,0,\"eq\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",317,0,\"eq\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",319,0,\"ne\",[\"i64:0\",\"i64:0\"]],[\"invoke\",320,0,\"ne\",[\"i64:1\",\"i64:1\"]],[\"invoke\",321,0,\"ne\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",322,0,\"ne\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",323,0,\"ne\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",324,0,\"ne\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",325,0,\"ne\",[\"i64:1\",\"i64:0\"]],[\"invoke\",326,0,\"ne\",[\"i64:0\",\"i64:1\"]],[\"invoke\",327,0,\"ne\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",328,0,\"ne\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",329,0,\"ne\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",330,0,\"ne\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",331,0,\"ne\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",332,0,\"ne\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",334,0,\"lt_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",335,0,\"lt_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",336,0,\"lt_s\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",337,0,\"lt_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",338,0,\"lt_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",339,0,\"lt_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",340,0,\"lt_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",341,0,\"lt_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",342,0,\"lt_s\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",343,0,\"lt_s\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",344,0,\"lt_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",345,0,\"lt_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",346,0,\"lt_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",347,0,\"lt_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",349,0,\"lt_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",350,0,\"lt_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",351,0,\"lt_u\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",352,0,\"lt_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",353,0,\"lt_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",354,0,\"lt_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",355,0,\"lt_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",356,0,\"lt_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",357,0,\"lt_u\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",358,0,\"lt_u\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",359,0,\"lt_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",360,0,\"lt_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",361,0,\"lt_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",362,0,\"lt_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",364,0,\"le_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",365,0,\"le_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",366,0,\"le_s\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",367,0,\"le_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",368,0,\"le_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",369,0,\"le_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",370,0,\"le_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",371,0,\"le_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",372,0,\"le_s\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",373,0,\"le_s\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",374,0,\"le_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",375,0,\"le_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",376,0,\"le_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",377,0,\"le_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",379,0,\"le_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",380,0,\"le_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",381,0,\"le_u\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",382,0,\"le_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",383,0,\"le_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",384,0,\"le_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",385,0,\"le_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",386,0,\"le_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",387,0,\"le_u\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",388,0,\"le_u\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",389,0,\"le_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",390,0,\"le_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",391,0,\"le_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",392,0,\"le_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",394,0,\"gt_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",395,0,\"gt_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",396,0,\"gt_s\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",397,0,\"gt_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",398,0,\"gt_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",399,0,\"gt_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",400,0,\"gt_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",401,0,\"gt_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",402,0,\"gt_s\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",403,0,\"gt_s\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",404,0,\"gt_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",405,0,\"gt_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",406,0,\"gt_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",407,0,\"gt_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",409,0,\"gt_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",410,0,\"gt_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",411,0,\"gt_u\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",412,0,\"gt_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",413,0,\"gt_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",414,0,\"gt_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",415,0,\"gt_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",416,0,\"gt_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",417,0,\"gt_u\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",418,0,\"gt_u\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",419,0,\"gt_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",420,0,\"gt_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",421,0,\"gt_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",422,0,\"gt_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",424,0,\"ge_s\",[\"i64:0\",\"i64:0\"]],[\"invoke\",425,0,\"ge_s\",[\"i64:1\",\"i64:1\"]],[\"invoke\",426,0,\"ge_s\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",427,0,\"ge_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",428,0,\"ge_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",429,0,\"ge_s\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",430,0,\"ge_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",431,0,\"ge_s\",[\"i64:0\",\"i64:1\"]],[\"invoke\",432,0,\"ge_s\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",433,0,\"ge_s\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",434,0,\"ge_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",435,0,\"ge_s\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",436,0,\"ge_s\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",437,0,\"ge_s\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"invoke\",439,0,\"ge_u\",[\"i64:0\",\"i64:0\"]],[\"invoke\",440,0,\"ge_u\",[\"i64:1\",\"i64:1\"]],[\"invoke\",441,0,\"ge_u\",[\"i64:18446744073709551615\",\"i64:1\"]],[\"invoke\",442,0,\"ge_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775808\"]],[\"invoke\",443,0,\"ge_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775807\"]],[\"invoke\",444,0,\"ge_u\",[\"i64:18446744073709551615\",\"i64:18446744073709551615\"]],[\"invoke\",445,0,\"ge_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",446,0,\"ge_u\",[\"i64:0\",\"i64:1\"]],[\"invoke\",447,0,\"ge_u\",[\"i64:9223372036854775808\",\"i64:0\"]],[\"invoke\",448,0,\"ge_u\",[\"i64:0\",\"i64:9223372036854775808\"]],[\"invoke\",449,0,\"ge_u\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"invoke\",450,0,\"ge_u\",[\"i64:18446744073709551615\",\"i64:9223372036854775808\"]],[\"invoke\",451,0,\"ge_u\",[\"i64:9223372036854775808\",\"i64:9223372036854775807\"]],[\"invoke\",452,0,\"ge_u\",[\"i64:9223372036854775807\",\"i64:9223372036854775808\"]],[\"file\",\"int_exprs.wast\"],[\"module\",6,2],[\"invoke\",18,0,\"i32.no_fold_cmp_s_offset\",[\"i32:2147483647\",\"i32:0\"]],[\"invoke\",19,0,\"i32.no_fold_cmp_u_offset\",[\"i32:4294967295\",\"i32:0\"]],[\"invoke\",20,0,\"i64.no_fold_cmp_s_offset\",[\"i64:9223372036854775807\",\"i64:0\"]],[\"invoke\",21,0,\"i64.no_fold_cmp_u_offset\",[\"i64:18446744073709551615\",\"i64:0\"]],[\"module\",25,3],[\"invoke\",30,0,\"i64.no_fold_wrap_extend_s\",[\"i64:4538991236898928\"]],[\"invoke\",31,0,\"i64.no_fold_wrap_extend_s\",[\"i64:45230338458316960\"]],[\"module\",35,4],[\"invoke\",40,0,\"i64.no_fold_wrap_extend_u\",[\"i64:4538991236898928\"]],[\"module\",44,5],[\"invoke\",56,0,\"i32.no_fold_shl_shr_s\",[\"i32:2147483648\"]],[\"invoke\",57,0,\"i32.no_fold_shl_shr_u\",[\"i32:2147483648\"]],[\"invoke\",58,0,\"i64.no_fold_shl_shr_s\",[\"i64:9223372036854775808\"]],[\"invoke\",59,0,\"i64.no_fold_shl_shr_u\",[\"i64:9223372036854775808\"]],[\"module\",63,6],[\"invoke\",75,0,\"i32.no_fold_shr_s_shl\",[\"i32:1\"]],[\"invoke\",76,0,\"i32.no_fold_shr_u_shl\",[\"i32:1\"]],[\"invoke\",77,0,\"i64.no_fold_shr_s_shl\",[\"i64:1\"]],[\"invoke\",78,0,\"i64.no_fold_shr_u_shl\",[\"i64:1\"]],[\"module\",82,7],[\"invoke\",94,0,\"i32.no_fold_div_s_mul\",[\"i32:1\"]],[\"invoke\",95,0,\"i32.no_fold_div_u_mul\",[\"i32:1\"]],[\"invoke\",96,0,\"i64.no_fold_div_s_mul\",[\"i64:1\"]],[\"invoke\",97,0,\"i64.no_fold_div_u_mul\",[\"i64:1\"]],[\"module\",101,8],[\"invoke\",113,0,\"i32.no_fold_div_s_self\",[\"i32:0\"]],[\"invoke\",114,0,\"i32.no_fold_div_u_self\",[\"i32:0\"]],[\"invoke\",115,0,\"i64.no_fold_div_s_self\",[\"i64:0\"]],[\"invoke\",116,0,\"i64.no_fold_div_u_self\",[\"i64:0\"]],[\"module\",120,9],[\"invoke\",132,0,\"i32.no_fold_rem_s_self\",[\"i32:0\"]],[\"invoke\",133,0,\"i32.no_fold_rem_u_self\",[\"i32:0\"]],[\"invoke\",134,0,\"i64.no_fold_rem_s_self\",[\"i64:0\"]],[\"invoke\",135,0,\"i64.no_fold_rem_u_self\",[\"i64:0\"]],[\"module\",139,10],[\"invoke\",151,0,\"i32.no_fold_mul_div_s\",[\"i32:2147483648\"]],[\"invoke\",152,0,\"i32.no_fold_mul_div_u\",[\"i32:2147483648\"]],[\"invoke\",153,0,\"i64.no_fold_mul_div_s\",[\"i64:9223372036854775808\"]],[\"invoke\",154,0,\"i64.no_fold_mul_div_u\",[\"i64:9223372036854775808\"]],[\"module\",158,11],[\"invoke\",166,0,\"i32.no_fold_div_s_2\",[\"i32:4294967285\"]],[\"invoke\",167,0,\"i64.no_fold_div_s_2\",[\"i64:18446744073709551605\"]],[\"module\",171,12],[\"invoke\",179,0,\"i32.no_fold_rem_s_2\",[\"i32:4294967285\"]],[\"invoke\",180,0,\"i64.no_fold_rem_s_2\",[\"i64:18446744073709551605\"]],[\"module\",184,13],[\"invoke\",196,0,\"i32.div_s_0\",[\"i32:71\"]],[\"invoke\",197,0,\"i32.div_u_0\",[\"i32:71\"]],[\"invoke\",198,0,\"i64.div_s_0\",[\"i64:71\"]],[\"invoke\",199,0,\"i64.div_u_0\",[\"i64:71\"]],[\"module\",203,14],[\"invoke\",215,0,\"i32.div_s_3\",[\"i32:71\"]],[\"invoke\",216,0,\"i32.div_s_3\",[\"i32:1610612736\"]],[\"invoke\",217,0,\"i32.div_u_3\",[\"i32:71\"]],[\"invoke\",218,0,\"i32.div_u_3\",[\"i32:3221225472\"]],[\"invoke\",219,0,\"i64.div_s_3\",[\"i64:71\"]],[\"invoke\",220,0,\"i64.div_s_3\",[\"i64:3458764513820540928\"]],[\"invoke\",221,0,\"i64.div_u_3\",[\"i64:71\"]],[\"invoke\",222,0,\"i64.div_u_3\",[\"i64:13835058055282163712\"]],[\"module\",226,15],[\"invoke\",238,0,\"i32.div_s_5\",[\"i32:71\"]],[\"invoke\",239,0,\"i32.div_s_5\",[\"i32:1342177280\"]],[\"invoke\",240,0,\"i32.div_u_5\",[\"i32:71\"]],[\"invoke\",241,0,\"i32.div_u_5\",[\"i32:2684354560\"]],[\"invoke\",242,0,\"i64.div_s_5\",[\"i64:71\"]],[\"invoke\",243,0,\"i64.div_s_5\",[\"i64:5764607523034234880\"]],[\"invoke\",244,0,\"i64.div_u_5\",[\"i64:71\"]],[\"invoke\",245,0,\"i64.div_u_5\",[\"i64:11529215046068469760\"]],[\"module\",249,16],[\"invoke\",261,0,\"i32.div_s_7\",[\"i32:71\"]],[\"invoke\",262,0,\"i32.div_s_7\",[\"i32:1879048192\"]],[\"invoke\",263,0,\"i32.div_u_7\",[\"i32:71\"]],[\"invoke\",264,0,\"i32.div_u_7\",[\"i32:3758096384\"]],[\"invoke\",265,0,\"i64.div_s_7\",[\"i64:71\"]],[\"invoke\",266,0,\"i64.div_s_7\",[\"i64:8070450532247928832\"]],[\"invoke\",267,0,\"i64.div_u_7\",[\"i64:71\"]],[\"invoke\",268,0,\"i64.div_u_7\",[\"i64:16140901064495857664\"]],[\"module\",272,17],[\"invoke\",284,0,\"i32.rem_s_3\",[\"i32:71\"]],[\"invoke\",285,0,\"i32.rem_s_3\",[\"i32:1610612736\"]],[\"invoke\",286,0,\"i32.rem_u_3\",[\"i32:71\"]],[\"invoke\",287,0,\"i32.rem_u_3\",[\"i32:3221225472\"]],[\"invoke\",288,0,\"i64.rem_s_3\",[\"i64:71\"]],[\"invoke\",289,0,\"i64.rem_s_3\",[\"i64:3458764513820540928\"]],[\"invoke\",290,0,\"i64.rem_u_3\",[\"i64:71\"]],[\"invoke\",291,0,\"i64.rem_u_3\",[\"i64:13835058055282163712\"]],[\"module\",295,18],[\"invoke\",307,0,\"i32.rem_s_5\",[\"i32:71\"]],[\"invoke\",308,0,\"i32.rem_s_5\",[\"i32:1342177280\"]],[\"invoke\",309,0,\"i32.rem_u_5\",[\"i32:71\"]],[\"invoke\",310,0,\"i32.rem_u_5\",[\"i32:2684354560\"]],[\"invoke\",311,0,\"i64.rem_s_5\",[\"i64:71\"]],[\"invoke\",312,0,\"i64.rem_s_5\",[\"i64:5764607523034234880\"]],[\"invoke\",313,0,\"i64.rem_u_5\",[\"i64:71\"]],[\"invoke\",314,0,\"i64.rem_u_5\",[\"i64:11529215046068469760\"]],[\"module\",318,19],[\"invoke\",330,0,\"i32.rem_s_7\",[\"i32:71\"]],[\"invoke\",331,0,\"i32.rem_s_7\",[\"i32:1879048192\"]],[\"invoke\",332,0,\"i32.rem_u_7\",[\"i32:71\"]],[\"invoke\",333,0,\"i32.rem_u_7\",[\"i32:3758096384\"]],[\"invoke\",334,0,\"i64.rem_s_7\",[\"i64:71\"]],[\"invoke\",335,0,\"i64.rem_s_7\",[\"i64:8070450532247928832\"]],[\"invoke\",336,0,\"i64.rem_u_7\",[\"i64:71\"]],[\"invoke\",337,0,\"i64.rem_u_7\",[\"i64:16140901064495857664\"]],[\"module\",341,20],[\"invoke\",349,0,\"i32.no_fold_div_neg1\",[\"i32:2147483648\"]],[\"invoke\",350,0,\"i64.no_fold_div_neg1\",[\"i64:9223372036854775808\"]],[\"file\",\"int_literals.wast\"],[\"module\",1,21],[\"invoke\",37,0,\"i32.test\",[]],[\"invoke\",38,0,\"i32.umax\",[]],[\"invoke\",39,0,\"i32.smax\",[]],[\"invoke\",40,0,\"i32.neg_smax\",[]],[\"invoke\",41,0,\"i32.smin\",[]],[\"invoke\",42,0,\"i32.alt_smin\",[]],[\"invoke\",43,0,\"i32.inc_smin\",[]],[\"invoke\",44,0,\"i32.neg_zero\",[]],[\"invoke\",45,0,\"i32.not_octal\",[]],[\"invoke\",46,0,\"i32.unsigned_decimal\",[]],[\"invoke\",47,0,\"i32.plus_sign\",[]],[\"invoke\",49,0,\"i64.test\",[]],[\"invoke\",50,0,\"i64.umax\",[]],[\"invoke\",51,0,\"i64.smax\",[]],[\"invoke\",52,0,\"i64.neg_smax\",[]],[\"invoke\",53,0,\"i64.smin\",[]],[\"invoke\",54,0,\"i64.alt_smin\",[]],[\"invoke\",55,0,\"i64.inc_smin\",[]],[\"invoke\",56,0,\"i64.neg_zero\",[]],[\"invoke\",57,0,\"i64.not_octal\",[]],[\"invoke\",58,0,\"i64.unsigned_decimal\",[]],[\"invoke\",59,0,\"i64.plus_sign\",[]],[\"invoke\",61,0,\"i32-dec-sep1\",[]],[\"invoke\",62,0,\"i32-dec-sep2\",[]],[\"invoke\",63,0,\"i32-hex-sep1\",[]],[\"invoke\",64,0,\"i32-hex-sep2\",[]],[\"invoke\",66,0,\"i64-dec-sep1\",[]],[\"invoke\",67,0,\"i64-dec-sep2\",[]],[\"invoke\",68,0,\"i64-hex-sep1\",[]],[\"invoke\",69,0,\"i64-hex-sep2\",[]],[\"file\",\"conversions.wast\"],[\"module\",1,22],[\"invoke\",37,0,\"i64.extend_i32_s\",[\"i32:0\"]],[\"invoke\",39,0,\"i64.extend_i32_s\",[\"i32:4294957296\"]],[\"invoke\",40,0,\"i64.extend_i32_s\",[\"i32:4294967295\"]],[\"invoke\",42,0,\"i64.extend_i32_s\",[\"i32:2147483648\"]],[\"invoke\",44,0,\"i64.extend_i32_u\",[\"i32:0\"]],[\"invoke\",45,0,\"i64.extend_i32_u\",[\"i32:10000\"]],[\"invoke\",47,0,\"i64.extend_i32_u\",[\"i32:4294967295\"]],[\"invoke\",48,0,\"i64.extend_i32_u\",[\"i32:2147483647\"]],[\"invoke\",51,0,\"i32.wrap_i64\",[\"i64:18446744073709551615\"]],[\"invoke\",52,0,\"i32.wrap_i64\",[\"i64:18446744073709451616\"]],[\"invoke\",53,0,\"i32.wrap_i64\",[\"i64:2147483648\"]],[\"invoke\",55,0,\"i32.wrap_i64\",[\"i64:18446744069414584320\"]],[\"invoke\",56,0,\"i32.wrap_i64\",[\"i64:18446744069414584319\"]],[\"invoke\",57,0,\"i32.wrap_i64\",[\"i64:18446744069414584321\"]],[\"invoke\",59,0,\"i32.wrap_i64\",[\"i64:1311768467463790320\"]],[\"invoke\",60,0,\"i32.wrap_i64\",[\"i64:4294967295\"]],[\"invoke\",62,0,\"i32.wrap_i64\",[\"i64:4294967297\"]],[\"invoke\",64,0,\"i32.trunc_f32_s\",[\"f32:0\"]],[\"invoke\",65,0,\"i32.trunc_f32_s\",[\"f32:2147483648\"]],[\"invoke\",67,0,\"i32.trunc_f32_s\",[\"f32:2147483649\"]],[\"invoke\",68,0,\"i32.trunc_f32_s\",[\"f32:1065353216\"]],[\"invoke\",69,0,\"i32.trunc_f32_s\",[\"f32:1066192077\"]],[\"invoke\",71,0,\"i32.trunc_f32_s\",[\"f32:3212836864\"]],[\"invoke\",72,0,\"i32.trunc_f32_s\",[\"f32:3213675725\"]],[\"invoke\",74,0,\"i32.trunc_f32_s\",[\"f32:3220386611\"]],[\"invoke\",75,0,\"i32.trunc_f32_s\",[\"f32:3221225472\"]],[\"invoke\",76,0,\"i32.trunc_f32_s\",[\"f32:1325400063\"]],[\"invoke\",78,0,\"i32.trunc_f32_s\",[\"f32:1325400064\"]],[\"invoke\",79,0,\"i32.trunc_f32_s\",[\"f32:3472883713\"]],[\"invoke\",80,0,\"i32.trunc_f32_s\",[\"f32:2139095040\"]],[\"invoke\",82,0,\"i32.trunc_f32_s\",[\"f32:2143289344\"]],[\"invoke\",84,0,\"i32.trunc_f32_s\",[\"f32:4290772992\"]],[\"invoke\",88,0,\"i32.trunc_f32_u\",[\"f32:2147483648\"]],[\"invoke\",89,0,\"i32.trunc_f32_u\",[\"f32:1\"]],[\"invoke\",90,0,\"i32.trunc_f32_u\",[\"f32:2147483649\"]],[\"invoke\",92,0,\"i32.trunc_f32_u\",[\"f32:1066192077\"]],[\"invoke\",93,0,\"i32.trunc_f32_u\",[\"f32:1069547520\"]],[\"invoke\",94,0,\"i32.trunc_f32_u\",[\"f32:1072902963\"]],[\"invoke\",96,0,\"i32.trunc_f32_u\",[\"f32:1325400064\"]],[\"invoke\",97,0,\"i32.trunc_f32_u\",[\"f32:1333788671\"]],[\"invoke\",99,0,\"i32.trunc_f32_u\",[\"f32:3212836863\"]],[\"invoke\",100,0,\"i32.trunc_f32_u\",[\"f32:1333788672\"]],[\"invoke\",101,0,\"i32.trunc_f32_u\",[\"f32:3212836864\"]],[\"invoke\",103,0,\"i32.trunc_f32_u\",[\"f32:4286578688\"]],[\"invoke\",104,0,\"i32.trunc_f32_u\",[\"f32:2143289344\"]],[\"invoke\",106,0,\"i32.trunc_f32_u\",[\"f32:4290772992\"]],[\"invoke\",110,0,\"i32.trunc_f64_s\",[\"f64:9223372036854775808\"]],[\"invoke\",111,0,\"i32.trunc_f64_s\",[\"f64:1\"]],[\"invoke\",113,0,\"i32.trunc_f64_s\",[\"f64:4607182418800017408\"]],[\"invoke\",114,0,\"i32.trunc_f64_s\",[\"f64:4607632778762754458\"]],[\"invoke\",115,0,\"i32.trunc_f64_s\",[\"f64:4609434218613702656\"]],[\"invoke\",117,0,\"i32.trunc_f64_s\",[\"f64:13831004815617530266\"]],[\"invoke\",118,0,\"i32.trunc_f64_s\",[\"f64:13832806255468478464\"]],[\"invoke\",120,0,\"i32.trunc_f64_s\",[\"f64:13835058055282163712\"]],[\"invoke\",121,0,\"i32.trunc_f64_s\",[\"f64:4746794007244308480\"]],[\"invoke\",122,0,\"i32.trunc_f64_s\",[\"f64:13970166044103278592\"]],[\"invoke\",124,0,\"i32.trunc_f64_s\",[\"f64:4746794007248083354\"]],[\"invoke\",125,0,\"i32.trunc_f64_s\",[\"f64:4746794007248502784\"]],[\"invoke\",126,0,\"i32.trunc_f64_s\",[\"f64:13970166044105375744\"]],[\"invoke\",128,0,\"i32.trunc_f64_s\",[\"f64:18442240474082181120\"]],[\"invoke\",129,0,\"i32.trunc_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",134,0,\"i32.trunc_f64_u\",[\"f64:0\"]],[\"invoke\",135,0,\"i32.trunc_f64_u\",[\"f64:9223372036854775808\"]],[\"invoke\",136,0,\"i32.trunc_f64_u\",[\"f64:1\"]],[\"invoke\",138,0,\"i32.trunc_f64_u\",[\"f64:4607182418800017408\"]],[\"invoke\",139,0,\"i32.trunc_f64_u\",[\"f64:4607632778762754458\"]],[\"invoke\",140,0,\"i32.trunc_f64_u\",[\"f64:4609434218613702656\"]],[\"invoke\",142,0,\"i32.trunc_f64_u\",[\"f64:4611686018427387904\"]],[\"invoke\",143,0,\"i32.trunc_f64_u\",[\"f64:4746794007248502784\"]],[\"invoke\",145,0,\"i32.trunc_f64_u\",[\"f64:13829653735729319117\"]],[\"invoke\",146,0,\"i32.trunc_f64_u\",[\"f64:13830554455654793215\"]],[\"invoke\",147,0,\"i32.trunc_f64_u\",[\"f64:4726483295884279808\"]],[\"invoke\",149,0,\"i32.trunc_f64_u\",[\"f64:4751297606875663565\"]],[\"invoke\",150,0,\"i32.trunc_f64_u\",[\"f64:4751297606875873280\"]],[\"invoke\",151,0,\"i32.trunc_f64_u\",[\"f64:13830554455654793216\"]],[\"invoke\",153,0,\"i32.trunc_f64_u\",[\"f64:5055640609639927018\"]],[\"invoke\",154,0,\"i32.trunc_f64_u\",[\"f64:4890909195324358656\"]],[\"invoke\",156,0,\"i32.trunc_f64_u\",[\"f64:18442240474082181120\"]],[\"invoke\",157,0,\"i32.trunc_f64_u\",[\"f64:9221120237041090560\"]],[\"invoke\",159,0,\"i32.trunc_f64_u\",[\"f64:18444492273895866368\"]],[\"invoke\",163,0,\"i64.trunc_f32_s\",[\"f32:2147483648\"]],[\"invoke\",164,0,\"i64.trunc_f32_s\",[\"f32:1\"]],[\"invoke\",165,0,\"i64.trunc_f32_s\",[\"f32:2147483649\"]],[\"invoke\",167,0,\"i64.trunc_f32_s\",[\"f32:1066192077\"]],[\"invoke\",168,0,\"i64.trunc_f32_s\",[\"f32:1069547520\"]],[\"invoke\",170,0,\"i64.trunc_f32_s\",[\"f32:3213675725\"]],[\"invoke\",171,0,\"i64.trunc_f32_s\",[\"f32:3217031168\"]],[\"invoke\",172,0,\"i64.trunc_f32_s\",[\"f32:3220386611\"]],[\"invoke\",174,0,\"i64.trunc_f32_s\",[\"f32:1333788672\"]],[\"invoke\",175,0,\"i64.trunc_f32_s\",[\"f32:3481272320\"]],[\"invoke\",176,0,\"i64.trunc_f32_s\",[\"f32:1593835519\"]],[\"invoke\",178,0,\"i64.trunc_f32_s\",[\"f32:1593835520\"]],[\"invoke\",179,0,\"i64.trunc_f32_s\",[\"f32:3741319169\"]],[\"invoke\",181,0,\"i64.trunc_f32_s\",[\"f32:4286578688\"]],[\"invoke\",182,0,\"i64.trunc_f32_s\",[\"f32:2143289344\"]],[\"invoke\",184,0,\"i64.trunc_f32_s\",[\"f32:4290772992\"]],[\"invoke\",188,0,\"i64.trunc_f32_u\",[\"f32:2147483648\"]],[\"invoke\",189,0,\"i64.trunc_f32_u\",[\"f32:1\"]],[\"invoke\",190,0,\"i64.trunc_f32_u\",[\"f32:2147483649\"]],[\"invoke\",192,0,\"i64.trunc_f32_u\",[\"f32:1066192077\"]],[\"invoke\",193,0,\"i64.trunc_f32_u\",[\"f32:1069547520\"]],[\"invoke\",195,0,\"i64.trunc_f32_u\",[\"f32:1602224127\"]],[\"invoke\",196,0,\"i64.trunc_f32_u\",[\"f32:3211159142\"]],[\"invoke\",197,0,\"i64.trunc_f32_u\",[\"f32:3212836863\"]],[\"invoke\",199,0,\"i64.trunc_f32_u\",[\"f32:3212836864\"]],[\"invoke\",200,0,\"i64.trunc_f32_u\",[\"f32:2139095040\"]],[\"invoke\",202,0,\"i64.trunc_f32_u\",[\"f32:2143289344\"]],[\"invoke\",204,0,\"i64.trunc_f32_u\",[\"f32:4290772992\"]],[\"invoke\",207,0,\"i64.trunc_f64_s\",[\"f64:0\"]],[\"invoke\",209,0,\"i64.trunc_f64_s\",[\"f64:1\"]],[\"invoke\",210,0,\"i64.trunc_f64_s\",[\"f64:9223372036854775809\"]],[\"invoke\",211,0,\"i64.trunc_f64_s\",[\"f64:4607182418800017408\"]],[\"invoke\",213,0,\"i64.trunc_f64_s\",[\"f64:4609434218613702656\"]],[\"invoke\",214,0,\"i64.trunc_f64_s\",[\"f64:13830554455654793216\"]],[\"invoke\",216,0,\"i64.trunc_f64_s\",[\"f64:13832806255468478464\"]],[\"invoke\",217,0,\"i64.trunc_f64_s\",[\"f64:13834607695319426662\"]],[\"invoke\",218,0,\"i64.trunc_f64_s\",[\"f64:13835058055282163712\"]],[\"invoke\",220,0,\"i64.trunc_f64_s\",[\"f64:13974669643730649088\"]],[\"invoke\",221,0,\"i64.trunc_f64_s\",[\"f64:4890909195324358655\"]],[\"invoke\",222,0,\"i64.trunc_f64_s\",[\"f64:14114281232179134464\"]],[\"invoke\",224,0,\"i64.trunc_f64_s\",[\"f64:14114281232179134465\"]],[\"invoke\",225,0,\"i64.trunc_f64_s\",[\"f64:9218868437227405312\"]],[\"invoke\",227,0,\"i64.trunc_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",229,0,\"i64.trunc_f64_s\",[\"f64:18444492273895866368\"]],[\"invoke\",232,0,\"i64.trunc_f64_u\",[\"f64:0\"]],[\"invoke\",234,0,\"i64.trunc_f64_u\",[\"f64:1\"]],[\"invoke\",235,0,\"i64.trunc_f64_u\",[\"f64:9223372036854775809\"]],[\"invoke\",236,0,\"i64.trunc_f64_u\",[\"f64:4607182418800017408\"]],[\"invoke\",238,0,\"i64.trunc_f64_u\",[\"f64:4609434218613702656\"]],[\"invoke\",239,0,\"i64.trunc_f64_u\",[\"f64:4751297606873776128\"]],[\"invoke\",241,0,\"i64.trunc_f64_u\",[\"f64:4895412794951729151\"]],[\"invoke\",242,0,\"i64.trunc_f64_u\",[\"f64:13829653735729319117\"]],[\"invoke\",243,0,\"i64.trunc_f64_u\",[\"f64:13830554455654793215\"]],[\"invoke\",245,0,\"i64.trunc_f64_u\",[\"f64:4846369599423283200\"]],[\"invoke\",246,0,\"i64.trunc_f64_u\",[\"f64:4890909195324358656\"]],[\"invoke\",247,0,\"i64.trunc_f64_u\",[\"f64:4895412794951729152\"]],[\"invoke\",249,0,\"i64.trunc_f64_u\",[\"f64:9218868437227405312\"]],[\"invoke\",250,0,\"i64.trunc_f64_u\",[\"f64:18442240474082181120\"]],[\"invoke\",253,0,\"i64.trunc_f64_u\",[\"f64:18444492273895866368\"]],[\"invoke\",256,0,\"f32.convert_i32_s\",[\"i32:1\"]],[\"invoke\",257,0,\"f32.convert_i32_s\",[\"i32:4294967295\"]],[\"invoke\",259,0,\"f32.convert_i32_s\",[\"i32:2147483647\"]],[\"invoke\",260,0,\"f32.convert_i32_s\",[\"i32:2147483648\"]],[\"invoke\",261,0,\"f32.convert_i32_s\",[\"i32:1234567890\"]],[\"invoke\",266,0,\"i32.trunc_sat_f32_s\",[\"f32:2147483648\"]],[\"invoke\",267,0,\"i32.trunc_sat_f32_s\",[\"f32:1\"]],[\"invoke\",269,0,\"i32.trunc_sat_f32_s\",[\"f32:1065353216\"]],[\"invoke\",270,0,\"i32.trunc_sat_f32_s\",[\"f32:1066192077\"]],[\"invoke\",271,0,\"i32.trunc_sat_f32_s\",[\"f32:1069547520\"]],[\"invoke\",273,0,\"i32.trunc_sat_f32_s\",[\"f32:3213675725\"]],[\"invoke\",274,0,\"i32.trunc_sat_f32_s\",[\"f32:3217031168\"]],[\"invoke\",276,0,\"i32.trunc_sat_f32_s\",[\"f32:3221225472\"]],[\"invoke\",277,0,\"i32.trunc_sat_f32_s\",[\"f32:1325400063\"]],[\"invoke\",278,0,\"i32.trunc_sat_f32_s\",[\"f32:3472883712\"]],[\"invoke\",280,0,\"i32.trunc_sat_f32_s\",[\"f32:3472883713\"]],[\"invoke\",281,0,\"i32.trunc_sat_f32_s\",[\"f32:2139095040\"]],[\"invoke\",282,0,\"i32.trunc_sat_f32_s\",[\"f32:4286578688\"]],[\"invoke\",285,0,\"i32.trunc_sat_f32_s\",[\"f32:4290772992\"]],[\"invoke\",288,0,\"i32.trunc_sat_f32_u\",[\"f32:0\"]],[\"invoke\",290,0,\"i32.trunc_sat_f32_u\",[\"f32:1\"]],[\"invoke\",291,0,\"i32.trunc_sat_f32_u\",[\"f32:2147483649\"]],[\"invoke\",292,0,\"i32.trunc_sat_f32_u\",[\"f32:1065353216\"]],[\"invoke\",294,0,\"i32.trunc_sat_f32_u\",[\"f32:1069547520\"]],[\"invoke\",295,0,\"i32.trunc_sat_f32_u\",[\"f32:1072902963\"]],[\"invoke\",296,0,\"i32.trunc_sat_f32_u\",[\"f32:1073741824\"]],[\"invoke\",298,0,\"i32.trunc_sat_f32_u\",[\"f32:1333788671\"]],[\"invoke\",299,0,\"i32.trunc_sat_f32_u\",[\"f32:3211159142\"]],[\"invoke\",301,0,\"i32.trunc_sat_f32_u\",[\"f32:1333788672\"]],[\"invoke\",302,0,\"i32.trunc_sat_f32_u\",[\"f32:3212836864\"]],[\"invoke\",303,0,\"i32.trunc_sat_f32_u\",[\"f32:2139095040\"]],[\"invoke\",305,0,\"i32.trunc_sat_f32_u\",[\"f32:2143289344\"]],[\"invoke\",307,0,\"i32.trunc_sat_f32_u\",[\"f32:4290772992\"]],[\"invoke\",310,0,\"i32.trunc_sat_f64_s\",[\"f64:0\"]],[\"invoke\",312,0,\"i32.trunc_sat_f64_s\",[\"f64:1\"]],[\"invoke\",313,0,\"i32.trunc_sat_f64_s\",[\"f64:9223372036854775809\"]],[\"invoke\",315,0,\"i32.trunc_sat_f64_s\",[\"f64:4607632778762754458\"]],[\"invoke\",316,0,\"i32.trunc_sat_f64_s\",[\"f64:4609434218613702656\"]],[\"invoke\",317,0,\"i32.trunc_sat_f64_s\",[\"f64:13830554455654793216\"]],[\"invoke\",319,0,\"i32.trunc_sat_f64_s\",[\"f64:13832806255468478464\"]],[\"invoke\",320,0,\"i32.trunc_sat_f64_s\",[\"f64:13834607695319426662\"]],[\"invoke\",321,0,\"i32.trunc_sat_f64_s\",[\"f64:13835058055282163712\"]],[\"invoke\",323,0,\"i32.trunc_sat_f64_s\",[\"f64:13970166044103278592\"]],[\"invoke\",324,0,\"i32.trunc_sat_f64_s\",[\"f64:4746794007248502784\"]],[\"invoke\",326,0,\"i32.trunc_sat_f64_s\",[\"f64:9218868437227405312\"]],[\"invoke\",327,0,\"i32.trunc_sat_f64_s\",[\"f64:18442240474082181120\"]],[\"invoke\",328,0,\"i32.trunc_sat_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",333,0,\"i32.trunc_sat_f64_u\",[\"f64:0\"]],[\"invoke\",334,0,\"i32.trunc_sat_f64_u\",[\"f64:9223372036854775808\"]],[\"invoke\",335,0,\"i32.trunc_sat_f64_u\",[\"f64:1\"]],[\"invoke\",337,0,\"i32.trunc_sat_f64_u\",[\"f64:4607182418800017408\"]],[\"invoke\",338,0,\"i32.trunc_sat_f64_u\",[\"f64:4607632778762754458\"]],[\"invoke\",340,0,\"i32.trunc_sat_f64_u\",[\"f64:4611235658464650854\"]],[\"invoke\",341,0,\"i32.trunc_sat_f64_u\",[\"f64:4611686018427387904\"]],[\"invoke\",342,0,\"i32.trunc_sat_f64_u\",[\"f64:4746794007248502784\"]],[\"invoke\",344,0,\"i32.trunc_sat_f64_u\",[\"f64:13829653735729319117\"]],[\"invoke\",345,0,\"i32.trunc_sat_f64_u\",[\"f64:13830554455654793215\"]],[\"invoke\",346,0,\"i32.trunc_sat_f64_u\",[\"f64:4726483295884279808\"]],[\"invoke\",348,0,\"i32.trunc_sat_f64_u\",[\"f64:13830554455654793216\"]],[\"invoke\",349,0,\"i32.trunc_sat_f64_u\",[\"f64:4846369599423283200\"]],[\"invoke\",351,0,\"i32.trunc_sat_f64_u\",[\"f64:4890909195324358656\"]],[\"invoke\",352,0,\"i32.trunc_sat_f64_u\",[\"f64:9218868437227405312\"]],[\"invoke\",353,0,\"i32.trunc_sat_f64_u\",[\"f64:18442240474082181120\"]],[\"invoke\",356,0,\"i32.trunc_sat_f64_u\",[\"f64:18444492273895866368\"]],[\"invoke\",359,0,\"i64.trunc_sat_f32_s\",[\"f32:0\"]],[\"invoke\",361,0,\"i64.trunc_sat_f32_s\",[\"f32:1\"]],[\"invoke\",362,0,\"i64.trunc_sat_f32_s\",[\"f32:2147483649\"]],[\"invoke\",363,0,\"i64.trunc_sat_f32_s\",[\"f32:1065353216\"]],[\"invoke\",365,0,\"i64.trunc_sat_f32_s\",[\"f32:1069547520\"]],[\"invoke\",366,0,\"i64.trunc_sat_f32_s\",[\"f32:3212836864\"]],[\"invoke\",367,0,\"i64.trunc_sat_f32_s\",[\"f32:3213675725\"]],[\"invoke\",369,0,\"i64.trunc_sat_f32_s\",[\"f32:3220386611\"]],[\"invoke\",370,0,\"i64.trunc_sat_f32_s\",[\"f32:3221225472\"]],[\"invoke\",372,0,\"i64.trunc_sat_f32_s\",[\"f32:3481272320\"]],[\"invoke\",373,0,\"i64.trunc_sat_f32_s\",[\"f32:1593835519\"]],[\"invoke\",374,0,\"i64.trunc_sat_f32_s\",[\"f32:3741319168\"]],[\"invoke\",376,0,\"i64.trunc_sat_f32_s\",[\"f32:3741319169\"]],[\"invoke\",377,0,\"i64.trunc_sat_f32_s\",[\"f32:2139095040\"]],[\"invoke\",378,0,\"i64.trunc_sat_f32_s\",[\"f32:4286578688\"]],[\"invoke\",381,0,\"i64.trunc_sat_f32_s\",[\"f32:4290772992\"]],[\"invoke\",384,0,\"i64.trunc_sat_f32_u\",[\"f32:0\"]],[\"invoke\",386,0,\"i64.trunc_sat_f32_u\",[\"f32:1\"]],[\"invoke\",387,0,\"i64.trunc_sat_f32_u\",[\"f32:2147483649\"]],[\"invoke\",388,0,\"i64.trunc_sat_f32_u\",[\"f32:1065353216\"]],[\"invoke\",390,0,\"i64.trunc_sat_f32_u\",[\"f32:1069547520\"]],[\"invoke\",391,0,\"i64.trunc_sat_f32_u\",[\"f32:1333788672\"]],[\"invoke\",392,0,\"i64.trunc_sat_f32_u\",[\"f32:1602224127\"]],[\"invoke\",394,0,\"i64.trunc_sat_f32_u\",[\"f32:3212836863\"]],[\"invoke\",395,0,\"i64.trunc_sat_f32_u\",[\"f32:1602224128\"]],[\"invoke\",397,0,\"i64.trunc_sat_f32_u\",[\"f32:2139095040\"]],[\"invoke\",398,0,\"i64.trunc_sat_f32_u\",[\"f32:4286578688\"]],[\"invoke\",399,0,\"i64.trunc_sat_f32_u\",[\"f32:2143289344\"]],[\"invoke\",404,0,\"i64.trunc_sat_f64_s\",[\"f64:0\"]],[\"invoke\",405,0,\"i64.trunc_sat_f64_s\",[\"f64:9223372036854775808\"]],[\"invoke\",406,0,\"i64.trunc_sat_f64_s\",[\"f64:1\"]],[\"invoke\",408,0,\"i64.trunc_sat_f64_s\",[\"f64:4607182418800017408\"]],[\"invoke\",409,0,\"i64.trunc_sat_f64_s\",[\"f64:4607632778762754458\"]],[\"invoke\",411,0,\"i64.trunc_sat_f64_s\",[\"f64:13830554455654793216\"]],[\"invoke\",412,0,\"i64.trunc_sat_f64_s\",[\"f64:13831004815617530266\"]],[\"invoke\",413,0,\"i64.trunc_sat_f64_s\",[\"f64:13832806255468478464\"]],[\"invoke\",415,0,\"i64.trunc_sat_f64_s\",[\"f64:13835058055282163712\"]],[\"invoke\",416,0,\"i64.trunc_sat_f64_s\",[\"f64:4751297606875873280\"]],[\"invoke\",417,0,\"i64.trunc_sat_f64_s\",[\"f64:13974669643730649088\"]],[\"invoke\",419,0,\"i64.trunc_sat_f64_s\",[\"f64:14114281232179134464\"]],[\"invoke\",420,0,\"i64.trunc_sat_f64_s\",[\"f64:4890909195324358656\"]],[\"invoke\",422,0,\"i64.trunc_sat_f64_s\",[\"f64:9218868437227405312\"]],[\"invoke\",423,0,\"i64.trunc_sat_f64_s\",[\"f64:18442240474082181120\"]],[\"invoke\",424,0,\"i64.trunc_sat_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",429,0,\"i64.trunc_sat_f64_u\",[\"f64:0\"]],[\"invoke\",430,0,\"i64.trunc_sat_f64_u\",[\"f64:9223372036854775808\"]],[\"invoke\",431,0,\"i64.trunc_sat_f64_u\",[\"f64:1\"]],[\"invoke\",433,0,\"i64.trunc_sat_f64_u\",[\"f64:4607182418800017408\"]],[\"invoke\",434,0,\"i64.trunc_sat_f64_u\",[\"f64:4607632778762754458\"]],[\"invoke\",436,0,\"i64.trunc_sat_f64_u\",[\"f64:4751297606873776128\"]],[\"invoke\",437,0,\"i64.trunc_sat_f64_u\",[\"f64:4751297606875873280\"]],[\"invoke\",438,0,\"i64.trunc_sat_f64_u\",[\"f64:4895412794951729151\"]],[\"invoke\",440,0,\"i64.trunc_sat_f64_u\",[\"f64:13830554455654793215\"]],[\"invoke\",441,0,\"i64.trunc_sat_f64_u\",[\"f64:4726483295884279808\"]],[\"invoke\",443,0,\"i64.trunc_sat_f64_u\",[\"f64:4890909195324358656\"]],[\"invoke\",444,0,\"i64.trunc_sat_f64_u\",[\"f64:4895412794951729152\"]],[\"invoke\",445,0,\"i64.trunc_sat_f64_u\",[\"f64:13830554455654793216\"]],[\"invoke\",447,0,\"i64.trunc_sat_f64_u\",[\"f64:18442240474082181120\"]],[\"invoke\",448,0,\"i64.trunc_sat_f64_u\",[\"f64:9221120237041090560\"]],[\"invoke\",450,0,\"i64.trunc_sat_f64_u\",[\"f64:18444492273895866368\"]],[\"invoke\",455,0,\"f32.convert_i32_s\",[\"i32:4278190079\"]],[\"invoke\",456,0,\"f32.convert_i32_s\",[\"i32:16777219\"]],[\"invoke\",459,0,\"f32.convert_i64_s\",[\"i64:1\"]],[\"invoke\",460,0,\"f32.convert_i64_s\",[\"i64:18446744073709551615\"]],[\"invoke\",461,0,\"f32.convert_i64_s\",[\"i64:0\"]],[\"invoke\",463,0,\"f32.convert_i64_s\",[\"i64:9223372036854775808\"]],[\"invoke\",464,0,\"f32.convert_i64_s\",[\"i64:314159265358979\"]],[\"invoke\",466,0,\"f32.convert_i64_s\",[\"i64:16777217\"]],[\"invoke\",468,0,\"f32.convert_i64_s\",[\"i64:16777219\"]],[\"invoke\",469,0,\"f32.convert_i64_s\",[\"i64:18446744073692774397\"]],[\"invoke\",472,0,\"f32.convert_i64_s\",[\"i64:9223372311732682753\"]],[\"invoke\",473,0,\"f32.convert_i64_s\",[\"i64:9007199791611905\"]],[\"invoke\",474,0,\"f32.convert_i64_s\",[\"i64:18437736873917939711\"]],[\"invoke\",477,0,\"f64.convert_i32_s\",[\"i32:4294967295\"]],[\"invoke\",478,0,\"f64.convert_i32_s\",[\"i32:0\"]],[\"invoke\",479,0,\"f64.convert_i32_s\",[\"i32:2147483647\"]],[\"invoke\",481,0,\"f64.convert_i32_s\",[\"i32:987654321\"]],[\"invoke\",483,0,\"f64.convert_i64_s\",[\"i64:1\"]],[\"invoke\",485,0,\"f64.convert_i64_s\",[\"i64:0\"]],[\"invoke\",486,0,\"f64.convert_i64_s\",[\"i64:9223372036854775807\"]],[\"invoke\",487,0,\"f64.convert_i64_s\",[\"i64:9223372036854775808\"]],[\"invoke\",490,0,\"f64.convert_i64_s\",[\"i64:9007199254740993\"]],[\"invoke\",491,0,\"f64.convert_i64_s\",[\"i64:18437736874454810623\"]],[\"invoke\",492,0,\"f64.convert_i64_s\",[\"i64:9007199254740995\"]],[\"invoke\",495,0,\"f32.convert_i32_u\",[\"i32:1\"]],[\"invoke\",496,0,\"f32.convert_i32_u\",[\"i32:0\"]],[\"invoke\",498,0,\"f32.convert_i32_u\",[\"i32:2147483648\"]],[\"invoke\",499,0,\"f32.convert_i32_u\",[\"i32:305419896\"]],[\"invoke\",500,0,\"f32.convert_i32_u\",[\"i32:4294967295\"]],[\"invoke\",502,0,\"f32.convert_i32_u\",[\"i32:2147483777\"]],[\"invoke\",503,0,\"f32.convert_i32_u\",[\"i32:2147483778\"]],[\"invoke\",504,0,\"f32.convert_i32_u\",[\"i32:4294966912\"]],[\"invoke\",506,0,\"f32.convert_i32_u\",[\"i32:4294966914\"]],[\"invoke\",508,0,\"f32.convert_i32_u\",[\"i32:16777217\"]],[\"invoke\",511,0,\"f32.convert_i64_u\",[\"i64:1\"]],[\"invoke\",512,0,\"f32.convert_i64_u\",[\"i64:0\"]],[\"invoke\",513,0,\"f32.convert_i64_u\",[\"i64:9223372036854775807\"]],[\"invoke\",515,0,\"f32.convert_i64_u\",[\"i64:18446744073709551615\"]],[\"invoke\",517,0,\"f32.convert_i64_u\",[\"i64:16777217\"]],[\"invoke\",520,0,\"f32.convert_i64_u\",[\"i64:9007199791611905\"]],[\"invoke\",521,0,\"f32.convert_i64_u\",[\"i64:9223371761976868863\"]],[\"invoke\",522,0,\"f32.convert_i64_u\",[\"i64:9223372586610589697\"]],[\"invoke\",525,0,\"f64.convert_i32_u\",[\"i32:1\"]],[\"invoke\",526,0,\"f64.convert_i32_u\",[\"i32:0\"]],[\"invoke\",527,0,\"f64.convert_i32_u\",[\"i32:2147483647\"]],[\"invoke\",529,0,\"f64.convert_i32_u\",[\"i32:4294967295\"]],[\"invoke\",531,0,\"f64.convert_i64_u\",[\"i64:1\"]],[\"invoke\",533,0,\"f64.convert_i64_u\",[\"i64:9223372036854775807\"]],[\"invoke\",534,0,\"f64.convert_i64_u\",[\"i64:9223372036854775808\"]],[\"invoke\",535,0,\"f64.convert_i64_u\",[\"i64:18446744073709551615\"]],[\"invoke\",537,0,\"f64.convert_i64_u\",[\"i64:9223372036854776833\"]],[\"invoke\",538,0,\"f64.convert_i64_u\",[\"i64:9223372036854776834\"]],[\"invoke\",539,0,\"f64.convert_i64_u\",[\"i64:18446744073709548544\"]],[\"invoke\",541,0,\"f64.convert_i64_u\",[\"i64:18446744073709548546\"]],[\"invoke\",543,0,\"f64.convert_i64_u\",[\"i64:9007199254740993\"]],[\"invoke\",546,0,\"f64.promote_f32\",[\"f32:0\"]],[\"invoke\",547,0,\"f64.promote_f32\",[\"f32:2147483648\"]],[\"invoke\",548,0,\"f64.promote_f32\",[\"f32:1\"]],[\"invoke\",550,0,\"f64.promote_f32\",[\"f32:1065353216\"]],[\"invoke\",551,0,\"f64.promote_f32\",[\"f32:3212836864\"]],[\"invoke\",552,0,\"f64.promote_f32\",[\"f32:4286578687\"]],[\"invoke\",555,0,\"f64.promote_f32\",[\"f32:67108864\"]],[\"invoke\",557,0,\"f64.promote_f32\",[\"f32:2118632255\"]],[\"invoke\",559,0,\"f64.promote_f32\",[\"f32:4286578688\"]],[\"invoke\",560,0,\"f64.promote_f32\",[\"f32:2143289344\"]],[\"invoke\",562,0,\"f64.promote_f32\",[\"f32:4290772992\"]],[\"invoke\",566,0,\"f32.demote_f64\",[\"f64:9223372036854775808\"]],[\"invoke\",567,0,\"f32.demote_f64\",[\"f64:1\"]],[\"invoke\",568,0,\"f32.demote_f64\",[\"f64:9223372036854775809\"]],[\"invoke\",570,0,\"f32.demote_f64\",[\"f64:13830554455654793216\"]],[\"invoke\",571,0,\"f32.demote_f64\",[\"f64:4039728865214464000\"]],[\"invoke\",573,0,\"f32.demote_f64\",[\"f64:4039728865214463999\"]],[\"invoke\",574,0,\"f32.demote_f64\",[\"f64:13263100902069239807\"]],[\"invoke\",575,0,\"f32.demote_f64\",[\"f64:3936146074321813504\"]],[\"invoke\",577,0,\"f32.demote_f64\",[\"f64:5183643170298134528\"]],[\"invoke\",578,0,\"f32.demote_f64\",[\"f64:14407015207152910336\"]],[\"invoke\",579,0,\"f32.demote_f64\",[\"f64:5183643170298134529\"]],[\"invoke\",581,0,\"f32.demote_f64\",[\"f64:5183643170566569984\"]],[\"invoke\",582,0,\"f32.demote_f64\",[\"f64:14407015207421345792\"]],[\"invoke\",584,0,\"f32.demote_f64\",[\"f64:14407015207689781247\"]],[\"invoke\",585,0,\"f32.demote_f64\",[\"f64:5183643170835005440\"]],[\"invoke\",586,0,\"f32.demote_f64\",[\"f64:14407015207689781248\"]],[\"invoke\",588,0,\"f32.demote_f64\",[\"f64:5172657297058430976\"]],[\"invoke\",589,0,\"f32.demote_f64\",[\"f64:9218868437227405312\"]],[\"invoke\",590,0,\"f32.demote_f64\",[\"f64:18442240474082181120\"]],[\"invoke\",592,0,\"f32.demote_f64\",[\"f64:4607182418800017407\"]],[\"invoke\",593,0,\"f32.demote_f64\",[\"f64:4607182419068452864\"]],[\"invoke\",595,0,\"f32.demote_f64\",[\"f64:4607182419605323775\"]],[\"invoke\",596,0,\"f32.demote_f64\",[\"f64:4607182419605323776\"]],[\"invoke\",597,0,\"f32.demote_f64\",[\"f64:4607182420142194688\"]],[\"invoke\",599,0,\"f32.demote_f64\",[\"f64:4715268810125344769\"]],[\"invoke\",600,0,\"f32.demote_f64\",[\"f64:4715268810662215679\"]],[\"invoke\",602,0,\"f32.demote_f64\",[\"f64:5094955347580439664\"]],[\"invoke\",603,0,\"f32.demote_f64\",[\"f64:4101111194527827589\"]],[\"invoke\",604,0,\"f32.demote_f64\",[\"f64:4038806939559600639\"]],[\"invoke\",606,0,\"f32.demote_f64\",[\"f64:14338315240173327556\"]],[\"invoke\",607,0,\"f32.demote_f64\",[\"f64:9221120237041090560\"]],[\"invoke\",609,0,\"f32.demote_f64\",[\"f64:18444492273895866368\"]],[\"invoke\",612,0,\"f32.demote_f64\",[\"f64:9227875636482146304\"]],[\"invoke\",613,0,\"f32.demote_f64\",[\"f64:3931642474694443008\"]],[\"invoke\",615,0,\"f32.demote_f64\",[\"f64:3931642474694443009\"]],[\"invoke\",616,0,\"f32.demote_f64\",[\"f64:13155014511549218817\"]],[\"invoke\",618,0,\"f32.reinterpret_i32\",[\"i32:0\"]],[\"invoke\",620,0,\"f32.reinterpret_i32\",[\"i32:1\"]],[\"invoke\",621,0,\"f32.reinterpret_i32\",[\"i32:4294967295\"]],[\"invoke\",622,0,\"f32.reinterpret_i32\",[\"i32:123456789\"]],[\"invoke\",624,0,\"f32.reinterpret_i32\",[\"i32:2139095040\"]],[\"invoke\",625,0,\"f32.reinterpret_i32\",[\"i32:4286578688\"]],[\"invoke\",627,0,\"f32.reinterpret_i32\",[\"i32:4290772992\"]],[\"invoke\",628,0,\"f32.reinterpret_i32\",[\"i32:2141192192\"]],[\"invoke\",629,0,\"f32.reinterpret_i32\",[\"i32:4288675840\"]],[\"invoke\",632,0,\"f64.reinterpret_i64\",[\"i64:1\"]],[\"invoke\",633,0,\"f64.reinterpret_i64\",[\"i64:18446744073709551615\"]],[\"invoke\",634,0,\"f64.reinterpret_i64\",[\"i64:9223372036854775808\"]],[\"invoke\",636,0,\"f64.reinterpret_i64\",[\"i64:9223372036854775809\"]],[\"invoke\",637,0,\"f64.reinterpret_i64\",[\"i64:9218868437227405312\"]],[\"invoke\",639,0,\"f64.reinterpret_i64\",[\"i64:9221120237041090560\"]],[\"invoke\",640,0,\"f64.reinterpret_i64\",[\"i64:18444492273895866368\"]],[\"invoke\",641,0,\"f64.reinterpret_i64\",[\"i64:9219994337134247936\"]],[\"invoke\",644,0,\"i32.reinterpret_f32\",[\"f32:0\"]],[\"invoke\",645,0,\"i32.reinterpret_f32\",[\"f32:2147483648\"]],[\"invoke\",646,0,\"i32.reinterpret_f32\",[\"f32:1\"]],[\"invoke\",649,0,\"i32.reinterpret_f32\",[\"f32:1065353216\"]],[\"invoke\",650,0,\"i32.reinterpret_f32\",[\"f32:1078530010\"]],[\"invoke\",652,0,\"i32.reinterpret_f32\",[\"f32:4286578687\"]],[\"invoke\",653,0,\"i32.reinterpret_f32\",[\"f32:2139095040\"]],[\"invoke\",654,0,\"i32.reinterpret_f32\",[\"f32:4286578688\"]],[\"invoke\",656,0,\"i32.reinterpret_f32\",[\"f32:4290772992\"]],[\"invoke\",660,0,\"i64.reinterpret_f64\",[\"f64:0\"]],[\"invoke\",661,0,\"i64.reinterpret_f64\",[\"f64:9223372036854775808\"]],[\"invoke\",664,0,\"i64.reinterpret_f64\",[\"f64:9223372036854775809\"]],[\"invoke\",665,0,\"i64.reinterpret_f64\",[\"f64:4607182418800017408\"]],[\"invoke\",667,0,\"i64.reinterpret_f64\",[\"f64:9218868437227405311\"]],[\"invoke\",668,0,\"i64.reinterpret_f64\",[\"f64:18442240474082181119\"]],[\"invoke\",669,0,\"i64.reinterpret_f64\",[\"f64:9218868437227405312\"]],[\"invoke\",671,0,\"i64.reinterpret_f64\",[\"f64:9221120237041090560\"]],[\"invoke\",672,0,\"i64.reinterpret_f64\",[\"f64:18444492273895866368\"]],[\"file\",\"traps.wast\"],[\"module\",5,23],[\"invoke\",16,0,\"no_dce.i32.div_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",17,0,\"no_dce.i32.div_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",18,0,\"no_dce.i64.div_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",19,0,\"no_dce.i64.div_u\",[\"i64:1\",\"i64:0\"]],[\"invoke\",20,0,\"no_dce.i32.div_s\",[\"i32:2147483648\",\"i32:4294967295\"]],[\"invoke\",21,0,\"no_dce.i64.div_s\",[\"i64:9223372036854775808\",\"i64:18446744073709551615\"]],[\"module\",23,24],[\"invoke\",34,0,\"no_dce.i32.rem_s\",[\"i32:1\",\"i32:0\"]],[\"invoke\",35,0,\"no_dce.i32.rem_u\",[\"i32:1\",\"i32:0\"]],[\"invoke\",36,0,\"no_dce.i64.rem_s\",[\"i64:1\",\"i64:0\"]],[\"invoke\",37,0,\"no_dce.i64.rem_u\",[\"i64:1\",\"i64:0\"]],[\"module\",39,25],[\"invoke\",50,0,\"no_dce.i32.trunc_f32_s\",[\"f32:2143289344\"]],[\"invoke\",51,0,\"no_dce.i32.trunc_f32_u\",[\"f32:2143289344\"]],[\"invoke\",52,0,\"no_dce.i32.trunc_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",53,0,\"no_dce.i32.trunc_f64_u\",[\"f64:9221120237041090560\"]],[\"invoke\",54,0,\"no_dce.i64.trunc_f32_s\",[\"f32:2143289344\"]],[\"invoke\",55,0,\"no_dce.i64.trunc_f32_u\",[\"f32:2143289344\"]],[\"invoke\",56,0,\"no_dce.i64.trunc_f64_s\",[\"f64:9221120237041090560\"]],[\"invoke\",57,0,\"no_dce.i64.trunc_f64_u\",[\"f64:9221120237041090560\"]],[\"module\",59,26],[\"invoke\",78,0,\"no_dce.i32.load\",[\"i32:65536\"]],[\"invoke\",79,0,\"no_dce.i32.load16_s\",[\"i32:65536\"]],[\"invoke\",80,0,\"no_dce.i32.load16_u\",[\"i32:65536\"]],[\"invoke\",81,0,\"no_dce.i32.load8_s\",[\"i32:65536\"]],[\"invoke\",82,0,\"no_dce.i32.load8_u\",[\"i32:65536\"]],[\"invoke\",83,0,\"no_dce.i64.load\",[\"i32:65536\"]],[\"invoke\",84,0,\"no_dce.i64.load32_s\",[\"i32:65536\"]],[\"invoke\",85,0,\"no_dce.i64.load32_u\",[\"i32:65536\"]],[\"invoke\",86,0,\"no_dce.i64.load16_s\",[\"i32:65536\"]],[\"invoke\",87,0,\"no_dce.i64.load16_u\",[\"i32:65536\"]],[\"invoke\",88,0,\"no_dce.i64.load8_s\",[\"i32:65536\"]],[\"invoke\",89,0,\"no_dce.i64.load8_u\",[\"i32:65536\"]],[\"invoke\",90,0,\"no_dce.f32.load\",[\"i32:65536\"]],[\"invoke\",91,0,\"no_dce.f64.load\",[\"i32:65536\"]]]"; diff --git a/tests/corpus/webassembly-spec-int/main.mjs b/tests/corpus/webassembly-spec-int/main.mjs new file mode 100644 index 000000000..3f5bef066 --- /dev/null +++ b/tests/corpus/webassembly-spec-int/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (6 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-spec-memory/data.mjs b/tests/corpus/webassembly-spec-memory/data.mjs new file mode 100644 index 000000000..d62a7e491 --- /dev/null +++ b/tests/corpus/webassembly-spec-memory/data.mjs @@ -0,0 +1,175 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * address.wast, align.wast, endianness.wast, float_memory.wast, load.wast, store.wast, memory.wast, memory_grow.wast, memory_redundancy.wast, memory_size.wast, memory_trap.wast, bulk.wast, memory_copy.wast, memory_fill.wast, memory_init.wast, data.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABCgJgAX8Bf2ABfwADHx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEFAwEAAQfNAh4IOHVfZ29vZDEAAAg4dV9nb29kMgABCDh1X2dvb2QzAAIIOHVfZ29vZDQAAwg4dV9nb29kNQAECDhzX2dvb2QxAAUIOHNfZ29vZDIABgg4c19nb29kMwAHCDhzX2dvb2Q0AAgIOHNfZ29vZDUACQkxNnVfZ29vZDEACgkxNnVfZ29vZDIACwkxNnVfZ29vZDMADAkxNnVfZ29vZDQADQkxNnVfZ29vZDUADgkxNnNfZ29vZDEADwkxNnNfZ29vZDIAEAkxNnNfZ29vZDMAEQkxNnNfZ29vZDQAEgkxNnNfZ29vZDUAEwgzMl9nb29kMQAUCDMyX2dvb2QyABUIMzJfZ29vZDMAFggzMl9nb29kNAAXCDMyX2dvb2Q1ABgGOHVfYmFkABkGOHNfYmFkABoHMTZ1X2JhZAAbBzE2c19iYWQAHAYzMl9iYWQAHQqKAh4HACAALQAACwcAIAAtAAALBwAgAC0AAQsHACAALQACCwcAIAAtABkLBwAgACwAAAsHACAALAAACwcAIAAsAAELBwAgACwAAgsHACAALAAZCwcAIAAvAQALBwAgAC8AAAsHACAALwABCwcAIAAvAQILBwAgAC8BGQsHACAALgEACwcAIAAuAAALBwAgAC4AAQsHACAALgECCwcAIAAuARkLBwAgACgCAAsHACAAKAAACwcAIAAoAAELBwAgACgBAgsHACAAKAIZCwwAIAAtAP////8PGgsMACAALAD/////DxoLDAAgAC8B/////w8aCwwAIAAuAf////8PGgsMACAAKAL/////DxoLCyABAEEACxphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eg==", + "AGFzbQEAAAABCgJgAX8BfmABfwADKyoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEFAwEAAQfZAyoIOHVfZ29vZDEAAAg4dV9nb29kMgABCDh1X2dvb2QzAAIIOHVfZ29vZDQAAwg4dV9nb29kNQAECDhzX2dvb2QxAAUIOHNfZ29vZDIABgg4c19nb29kMwAHCDhzX2dvb2Q0AAgIOHNfZ29vZDUACQkxNnVfZ29vZDEACgkxNnVfZ29vZDIACwkxNnVfZ29vZDMADAkxNnVfZ29vZDQADQkxNnVfZ29vZDUADgkxNnNfZ29vZDEADwkxNnNfZ29vZDIAEAkxNnNfZ29vZDMAEQkxNnNfZ29vZDQAEgkxNnNfZ29vZDUAEwkzMnVfZ29vZDEAFAkzMnVfZ29vZDIAFQkzMnVfZ29vZDMAFgkzMnVfZ29vZDQAFwkzMnVfZ29vZDUAGAkzMnNfZ29vZDEAGQkzMnNfZ29vZDIAGgkzMnNfZ29vZDMAGwkzMnNfZ29vZDQAHAkzMnNfZ29vZDUAHQg2NF9nb29kMQAeCDY0X2dvb2QyAB8INjRfZ29vZDMAIAg2NF9nb29kNAAhCDY0X2dvb2Q1ACIGOHVfYmFkACMGOHNfYmFkACQHMTZ1X2JhZAAlBzE2c19iYWQAJgczMnVfYmFkACcHMzJzX2JhZAAoBjY0X2JhZAApCvQCKgcAIAAxAAALBwAgADEAAAsHACAAMQABCwcAIAAxAAILBwAgADEAGQsHACAAMAAACwcAIAAwAAALBwAgADAAAQsHACAAMAACCwcAIAAwABkLBwAgADMBAAsHACAAMwAACwcAIAAzAAELBwAgADMBAgsHACAAMwEZCwcAIAAyAQALBwAgADIAAAsHACAAMgABCwcAIAAyAQILBwAgADIBGQsHACAANQIACwcAIAA1AAALBwAgADUAAQsHACAANQECCwcAIAA1AhkLBwAgADQCAAsHACAANAAACwcAIAA0AAELBwAgADQBAgsHACAANAIZCwcAIAApAwALBwAgACkAAAsHACAAKQABCwcAIAApAQILBwAgACkDGQsMACAAMQD/////DxoLDAAgADAA/////w8aCwwAIAAzAf////8PGgsMACAAMgH/////DxoLDAAgADUC/////w8aCwwAIAA0Av////8PGgsMACAAKQP/////DxoLCyABAEEACxphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eg==", + "AGFzbQEAAAABCgJgAX8BfWABfwADBwYAAAAAAAEFAwEAAQdBBggzMl9nb29kMQAACDMyX2dvb2QyAAEIMzJfZ29vZDMAAggzMl9nb29kNAADCDMyX2dvb2Q1AAQGMzJfYmFkAAUKNgYHACAAKgIACwcAIAAqAAALBwAgACoAAQsHACAAKgECCwcAIAAqAggLDAAgACoC/////w8aCwsSAQBBAAsMAAAAAAAAoH8BANB/", + "AGFzbQEAAAABCgJgAX8BfGABfwADBwYAAAAAAAEFAwEAAQdBBgg2NF9nb29kMQAACDY0X2dvb2QyAAEINjRfZ29vZDMAAgg2NF9nb29kNAADCDY0X2dvb2Q1AAQGNjRfYmFkAAUKNgYHACAAKwMACwcAIAArAAALBwAgACsAAQsHACAAKwECCwcAIAArAxILDAAgACsD/////w8aCwsgAQBBAAsaAAAAAAAAAAAAAAAAAAAAAPR/AQAAAAAA/H8=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALAAAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALQAAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALgEAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALwEAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKAIAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMAAAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMQAAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMgEAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMwEAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANAIAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANQIAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKQMAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKgIAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKwMAGgs=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE6AAAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE7AQAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE2AgAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE8AAAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE9AQAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE+AgAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE3AwAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDgEMAEEAQwAAgD84AgAL", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEgEQAEEARAAAAAAAAPA/OQMACw==", + "AGFzbQEAAAABFwRgAX8BfWABfwF8YAJ/fwF/YAJ/fwF+AwUEAAECAwUDAQABB00EEGYzMl9hbGlnbl9zd2l0Y2gAABBmNjRfYWxpZ25fc3dpdGNoAAEQaTMyX2FsaWduX3N3aXRjaAACEGk2NF9hbGlnbl9zd2l0Y2gAAwr7CARjAQJ9QwAAIEEhAQJAAkACQAJAAkAgAA4EAAECAwQLQQAgATgCAEEAKgIAIQIMAwtBACABOAAAQQAqAAAhAgwCC0EAIAE4AQBBACoBACECDAELQQAgATgCAEEAKgIAIQILIAILewECfEQAAAAAAAAkQCEBAkACQAJAAkACQAJAIAAOBQABAgMEBQtBACABOQMAQQArAwAhAgwEC0EAIAE5AABBACsAACECDAMLQQAgATkBAEEAKwEAIQIMAgtBACABOQIAQQArAgAhAgwBC0EAIAE5AwBBACsDACECCyACC+ICAQJ/QQohAgJAAkACQAJAAkACQCAADgUAAQIDBAULIAFBAEYEQEEAIAI6AABBACwAACEDCyABQQFGBEBBACACOgAAQQAsAAAhAwsMBAsgAUEARgRAQQAgAjoAAEEALQAAIQMLIAFBAUYEQEEAIAI6AABBAC0AACEDCwwDCyABQQBGBEBBACACOwEAQQAuAQAhAwsgAUEBRgRAQQAgAjsAAEEALgAAIQMLIAFBAkYEQEEAIAI7AQBBAC4BACEDCwwCCyABQQBGBEBBACACOwEAQQAvAQAhAwsgAUEBRgRAQQAgAjsAAEEALwAAIQMLIAFBAkYEQEEAIAI7AQBBAC8BACEDCwwBCyABQQBGBEBBACACNgIAQQAoAgAhAwsgAUEBRgRAQQAgAjYAAEEAKAAAIQMLIAFBAkYEQEEAIAI2AQBBACgBACEDCyABQQRGBEBBACACNgIAQQAoAgAhAwsLIAMLtAQBAn5CCiECAkACQAJAAkACQAJAAkACQCAADgcAAQIDBAUGBwsgAUEARgRAQQAgAjwAAEEAMAAAIQMLIAFBAUYEQEEAIAI8AABBADAAACEDCwwGCyABQQBGBEBBACACPAAAQQAxAAAhAwsgAUEBRgRAQQAgAjwAAEEAMQAAIQMLDAULIAFBAEYEQEEAIAI9AQBBADIBACEDCyABQQFGBEBBACACPQAAQQAyAAAhAwsgAUECRgRAQQAgAj0BAEEAMgEAIQMLDAQLIAFBAEYEQEEAIAI9AQBBADMBACEDCyABQQFGBEBBACACPQAAQQAzAAAhAwsgAUECRgRAQQAgAj0BAEEAMwEAIQMLDAMLIAFBAEYEQEEAIAI+AgBBADQCACEDCyABQQFGBEBBACACPgAAQQA0AAAhAwsgAUECRgRAQQAgAj4BAEEANAEAIQMLIAFBBEYEQEEAIAI+AgBBADQCACEDCwwCCyABQQBGBEBBACACPgIAQQA1AgAhAwsgAUEBRgRAQQAgAj4AAEEANQAAIQMLIAFBAkYEQEEAIAI+AQBBADUBACEDCyABQQRGBEBBACACPgIAQQA1AgAhAwsMAQsgAUEARgRAQQAgAjcDAEEAKQMAIQMLIAFBAUYEQEEAIAI3AABBACkAACEDCyABQQJGBEBBACACNwEAQQApAQAhAwsgAUEERgRAQQAgAjcCAEEAKQIAIQMLIAFBCEYEQEEAIAI3AwBBACkDACEDCwsgAws=", + "AGFzbQEAAAABCwJgAn9+AGABfwF/AwMCAAEFAwEAAQcQAgVzdG9yZQAABGxvYWQAAQoTAgkAIAAgATcCAAsHACAAKAIACw==", + "AGFzbQEAAAABJAdgAn9/AGACf34AYAF/AX9gAX8BfmABfgF+YAF9AX1gAXwBfAMYFwAAAQICAwICAgQEBAQEBQYCAgQEBAUGBQMBAAEH4QERDGkzMl9sb2FkMTZfcwAGDGkzMl9sb2FkMTZfdQAHCGkzMl9sb2FkAAgMaTY0X2xvYWQxNl9zAAkMaTY0X2xvYWQxNl91AAoMaTY0X2xvYWQzMl9zAAsMaTY0X2xvYWQzMl91AAwIaTY0X2xvYWQADQhmMzJfbG9hZAAOCGY2NF9sb2FkAA8LaTMyX3N0b3JlMTYAEAlpMzJfc3RvcmUAEQtpNjRfc3RvcmUxNgASC2k2NF9zdG9yZTMyABMJaTY0X3N0b3JlABQJZjMyX3N0b3JlABUJZjY0X3N0b3JlABYK9gIXFgAgACABOgAAIABBAWogAUEIdjoAAAsUACAAIAEQACAAQQJqIAFBEHYQAAsWACAAIAGnEAEgAEEEaiABQiCIpxABCxMAIAAtAAAgAEEBai0AAEEIdHILEQAgABADIABBAmoQA0EQdHILEwAgABAErSAAQQRqEAStQiCGhAsNAEEAIAAQAEEALgEACw0AQQAgABAAQQAvAQALDQBBACAAEAFBACgCAAsOAEEAIACnEABBADIBAAsOAEEAIACnEABBADMBAAsOAEEAIACnEAFBADQCAAsOAEEAIACnEAFBADUCAAsNAEEAIAAQAkEAKQMACw4AQQAgALwQAUEAKgIACw4AQQAgAL0QAkEAKwMACw0AQQAgADsBAEEAEAMLDQBBACAANgIAQQAQBAsOAEEAIAA9AQBBABADrQsOAEEAIAA+AgBBABAErQsNAEEAIAA3AwBBABAFCw4AQQAgADgCAEEAEAS+Cw4AQQAgADkDAEEAEAW/Cw==", + "AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBACoCAAsHAEEAKAIACwwAQQBDAACgfzgCAAsNAEEAQYCAgP0HNgIACwkAQQBBADYCAAsLCgEAQQALBAAAoH8=", + "AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBACsDAAsHAEEAKQMACxAAQQBEAAAAAAAA9H85AwALEgBBAEKAgICAgICA+v8ANwMACwkAQQBCADcDAAsLDgEAQQALCAAAAAAAAPR/", + "AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBASoCAAsHAEEBKAIACwwAQQFDAACgfzgCAAsNAEEBQYCAgP0HNgIACwkAQQFBADYCAAsLCwEAQQALBQAAAKB/", + "AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBASsDAAsHAEEBKQMACxAAQQFEAAAAAAAA9H85AwALEgBBAUKAgICAgICA+v8ANwMACwkAQQFCADcDAAsLDwEAQQALCQAAAAAAAAD0fw==", + "AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBACoCAAsHAEEAKAIACwwAQQBDAQDQfzgCAAsNAEEAQYGAwP4HNgIACwkAQQBBADYCAAsLCgEAQQALBAEA0H8=", + "AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBACsDAAsHAEEAKQMACxAAQQBEAQAAAAAA/H85AwALEgBBAEKBgICAgICA/v8ANwMACwkAQQBCADcDAAsLDgEAQQALCAEAAAAAAPx/", + "AGFzbQEAAAABFQRgA39/fwF/YAABf2AAAGACf38BfwMnJgECAQECAQEBAQEBAwMBAAEBAQEBAQECAQIBAQICAgIBAQEBAQEBBAUBcAEBAQUDAQABBgYBfwFBAAsHtwUlC2FzLWJyLXZhbHVlAAANYXMtYnJfaWYtY29uZAABDmFzLWJyX2lmLXZhbHVlAAITYXMtYnJfaWYtdmFsdWUtY29uZAADEWFzLWJyX3RhYmxlLWluZGV4AAQRYXMtYnJfdGFibGUtdmFsdWUABRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAGD2FzLXJldHVybi12YWx1ZQAHCmFzLWlmLWNvbmQACAphcy1pZi10aGVuAAkKYXMtaWYtZWxzZQAKD2FzLXNlbGVjdC1maXJzdAALEGFzLXNlbGVjdC1zZWNvbmQADA5hcy1zZWxlY3QtY29uZAANDWFzLWNhbGwtZmlyc3QADwthcy1jYWxsLW1pZAAQDGFzLWNhbGwtbGFzdAARFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAEhRhcy1jYWxsX2luZGlyZWN0LW1pZAATFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAUFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAFRJhcy1sb2NhbC5zZXQtdmFsdWUAFhJhcy1sb2NhbC50ZWUtdmFsdWUAFxNhcy1nbG9iYWwuc2V0LXZhbHVlABgPYXMtbG9hZC1hZGRyZXNzABkQYXMtbG9hZE4tYWRkcmVzcwAaEGFzLXN0b3JlLWFkZHJlc3MAGw5hcy1zdG9yZS12YWx1ZQAcEWFzLXN0b3JlTi1hZGRyZXNzAB0PYXMtc3RvcmVOLXZhbHVlAB4QYXMtdW5hcnktb3BlcmFuZAAfDmFzLWJpbmFyeS1sZWZ0ACAPYXMtYmluYXJ5LXJpZ2h0ACEPYXMtdGVzdC1vcGVyYW5kACIPYXMtY29tcGFyZS1sZWZ0ACMQYXMtY29tcGFyZS1yaWdodAAkE2FzLW1lbW9yeS5ncm93LXNpemUAJQkHAQBBAAsBDgqGBCYMAAJ/QQAoAgAMAAsLDAACQEEAKAIADQALCxEAAn9BACgCAEEBDQAaQQcLCxEAAn9BBkEAKAIADQAaQQcLCw8AAkBBACgCAA4CAAAACwsTAAJ/QQAoAgBBAQ4CAAAAQQcLCxIAAn9BBkEAKAIADgEAAEEHCwsIAEEAKAIADwsPAEEAKAIABH9BAAVBAQsLDwBBAQR/QQAoAgAFQQALCw8AQQAEf0EABUEAKAIACwsMAEEAKAIAIAAgARsLDAAgAEEAKAIAIAEbCwwAQQBBAUEAKAIAGwsEAEF/Cw0AQQAoAgBBAkEDEA4LDQBBAUEAKAIAQQMQDgsNAEEBQQJBACgCABAOCxAAQQAoAgBBAkEDQQARAAALEABBAUEAKAIAQQNBABEAAAsQAEEBQQJBACgCAEEAEQAACxAAQQFBAkEDQQAoAgARAAALCwEBf0EAKAIAIQALCwEBf0EAKAIAIgALCwEBf0EAKAIAJAALCgBBACgCACgCAAsKAEEAKAIALAAACwwAQQAoAgBBBzYCAAsMAEECQQAoAgA2AgALDABBACwAAEEHOgAACwwAQQJBACgCADsBAAsJAEHkACgCAGcLCwBB5AAoAgBBCmoLCwBBCkHkACgCAGsLCQBB5AAoAgBFCwsAQeQAKAIAQQpMCwsAQQpB5AAoAgBHCwoAQeQAKAIAQAAL", + "AGFzbQEAAAABBAFgAAADCgkAAAAAAAAAAAAFAwEAAQeXAQkOYXMtYmxvY2stdmFsdWUAAA1hcy1sb29wLXZhbHVlAAELYXMtYnItdmFsdWUAAg5hcy1icl9pZi12YWx1ZQADE2FzLWJyX2lmLXZhbHVlLWNvbmQABBFhcy1icl90YWJsZS12YWx1ZQAFD2FzLXJldHVybi12YWx1ZQAGCmFzLWlmLXRoZW4ABwphcy1pZi1lbHNlAAgKiAEJDAACQEEAQQE2AgALCwwAA0BBAEEBNgIACwsOAAJAQQBBATYCAAwACwsQAAJAQQBBATYCAEEBDQALCxAAAkBBBkEAQQE2AgANAAsLEQACQEEAQQE2AgBBAQ4AAAsLCgBBAEEBNgIADwsOAEEBBEBBAEEBNgIACwsPAEEABEAFQQBBATYCAAsL", + "AGFzbQEAAAAFAwEAAA==", + "AGFzbQEAAAAFAwEAAQ==", + "AGFzbQEAAAAFBAEBAAA=", + "AGFzbQEAAAAFBAEBAAE=", + "AGFzbQEAAAAFBQEBAYAC", + "AGFzbQEAAAAFBgEBAICABA==", + "AGFzbQEAAAABBQFgAAF/AwIBAAUEAQEAAAcLAQdtZW1zaXplAAAKBgEEAD8ACwsGAQBBAAsA", + "AGFzbQEAAAABBQFgAAF/AwIBAAUEAQEBAQcLAQdtZW1zaXplAAAKBgEEAD8ACwsHAQBBAAsBeA==", + "AGFzbQEAAAABEwRgAAF/YAABfGABfwF/YAF+AX4DDQwAAQICAgIDAwMDAwMFAwEAAQehAQwEZGF0YQAABGNhc3QAAQtpMzJfbG9hZDhfcwACC2kzMl9sb2FkOF91AAMMaTMyX2xvYWQxNl9zAAQMaTMyX2xvYWQxNl91AAULaTY0X2xvYWQ4X3MABgtpNjRfbG9hZDhfdQAHDGk2NF9sb2FkMTZfcwAIDGk2NF9sb2FkMTZfdQAJDGk2NF9sb2FkMzJfcwAKDGk2NF9sb2FkMzJfdQALCp8CDE4AQQAtAABBwQBGQQMtAABBpwFGcUEGLQAAQQBGQRMtAABBAEZxcUEULQAAQdcARkEXLQAAQc0ARnFBGC0AAEEARkH/By0AAEEARnFxcQs4AEEIQseffzcDAEEIKwMAQseff79hBEBEAAAAAAAAAAAPC0EJQgA3AABBD0HFgAE7AABBCSsAAAsOAEEIIAA6AABBCCwAAAsOAEEIIAA6AABBCC0AAAsOAEEIIAA7AQBBCC4BAAsOAEEIIAA7AQBBCC8BAAsOAEEIIAA8AABBCDAAAAsOAEEIIAA8AABBCDEAAAsOAEEIIAA9AQBBCDIBAAsOAEEIIAA9AQBBCDMBAAsOAEEIIAA+AgBBCDQCAAsOAEEIIAA+AgBBCDUCAAsLFAIAQQALBUFCQ6dEAEEUCwRXQVNN", + "AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAQEGFgN/AEGQzgALfwBBkM4AC38AQZDOAAsHOgUGbWVtb3J5AgAKX19kYXRhX2VuZAMAC19fc3RhY2tfdG9wAwELX19oZWFwX2Jhc2UDAgRsb2FkAAAKCQEHACAALQAACw==", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8DBwYAAQABAgAFAwEAAAdXBgxsb2FkX2F0X3plcm8AAA1zdG9yZV9hdF96ZXJvAAERbG9hZF9hdF9wYWdlX3NpemUAAhJzdG9yZV9hdF9wYWdlX3NpemUAAwRncm93AAQEc2l6ZQAFCjUGBwBBACgCAAsJAEEAQQI2AgALCQBBgIAEKAIACwsAQYCABEEDNgIACwYAIABAAAsEAD8ACw==", + "AGFzbQEAAAABBgFgAX8BfwMCAQAFAwEAAAcIAQRncm93AAAKCAEGACAAQAAL", + "AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAAoHCAEEZ3JvdwAACggBBgAgAEAACw==", + "AGFzbQEAAAABDAJgAX8Bf2ACf38BfwMDAgABBQMBAAEHHAIEZ3JvdwAAEWNoZWNrLW1lbW9yeS16ZXJvAAEKPAIGACAAQAALMwEBf0EBIQICQANAIAAtAAAhAiACQQBHDQEgACABTw0BIABBAWohACAAIAFNDQALCyACCw==", + "AGFzbQEAAAABFQRgA39/fwF/YAABf2AAAGACf38BfwMnJgECAQECAQEBAQEBAwMBAAEBAQEBAQECAQIBAQICAgIBAQEBAQEBBAUBcAEBAQUDAQABBgYBfwFBAAsHtwUlC2FzLWJyLXZhbHVlAAANYXMtYnJfaWYtY29uZAABDmFzLWJyX2lmLXZhbHVlAAITYXMtYnJfaWYtdmFsdWUtY29uZAADEWFzLWJyX3RhYmxlLWluZGV4AAQRYXMtYnJfdGFibGUtdmFsdWUABRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAGD2FzLXJldHVybi12YWx1ZQAHCmFzLWlmLWNvbmQACAphcy1pZi10aGVuAAkKYXMtaWYtZWxzZQAKD2FzLXNlbGVjdC1maXJzdAALEGFzLXNlbGVjdC1zZWNvbmQADA5hcy1zZWxlY3QtY29uZAANDWFzLWNhbGwtZmlyc3QADwthcy1jYWxsLW1pZAAQDGFzLWNhbGwtbGFzdAARFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAEhRhcy1jYWxsX2luZGlyZWN0LW1pZAATFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAUFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAFRJhcy1sb2NhbC5zZXQtdmFsdWUAFhJhcy1sb2NhbC50ZWUtdmFsdWUAFxNhcy1nbG9iYWwuc2V0LXZhbHVlABgPYXMtbG9hZC1hZGRyZXNzABkQYXMtbG9hZE4tYWRkcmVzcwAaEGFzLXN0b3JlLWFkZHJlc3MAGw5hcy1zdG9yZS12YWx1ZQAcEWFzLXN0b3JlTi1hZGRyZXNzAB0PYXMtc3RvcmVOLXZhbHVlAB4QYXMtdW5hcnktb3BlcmFuZAAfDmFzLWJpbmFyeS1sZWZ0ACAPYXMtYmluYXJ5LXJpZ2h0ACEPYXMtdGVzdC1vcGVyYW5kACIPYXMtY29tcGFyZS1sZWZ0ACMQYXMtY29tcGFyZS1yaWdodAAkE2FzLW1lbW9yeS5ncm93LXNpemUAJQkHAQBBAAsBDgraAyYLAAJ/QQBAAAwACwsLAAJAQQBAAA0ACwsQAAJ/QQBAAEEBDQAaQQcLCxAAAn9BBkEAQAANABpBBwsLDgACQEEAQAAOAgAAAAsLEgACf0EAQABBAQ4CAAAAQQcLCxEAAn9BBkEAQAAOAQAAQQcLCwcAQQBAAA8LDgBBAEAABH9BAAVBAQsLDgBBAQR/QQBAAAVBAAsLDgBBAAR/QQAFQQBAAAsLCwBBAEAAIAAgARsLCwAgAEEAQAAgARsLCwBBAEEBQQBAABsLBABBfwsMAEEAQABBAkEDEA4LDABBAUEAQABBAxAOCwwAQQFBAkEAQAAQDgsPAEEAQABBAkEDQQARAAALDwBBAUEAQABBA0EAEQAACw8AQQFBAkEAQABBABEAAAsPAEEBQQJBA0EAQAARAAALCgEBf0EAQAAhAAsKAQF/QQBAACIACwoBAX9BAEAAJAALCQBBAEAAKAIACwkAQQBAACwAAAsLAEEAQABBBzYCAAsLAEECQQBAADYCAAsLAEEAQABBBzoAAAsLAEECQQBAADsBAAsHAEEAQABnCwkAQQBAAEEKagsJAEEKQQBAAGsLBwBBAEAARQsJAEEAQABBCkwLCQBBCkEAQABHCwgAQQBAAEAACw==", + "AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABBxECBm1lbW9yeQIABGdyb3cAAAoIAQYAQQFAAAs=", + "AGFzbQEAAAABBQFgAAF/AhgBDGdyb3duLW1lbW9yeQZtZW1vcnkCAAIDAgEABxECBm1lbW9yeQIABGdyb3cAAAoIAQYAQQFAAAs=", + "AGFzbQEAAAABBQFgAAF/AiEBFWdyb3duLWltcG9ydGVkLW1lbW9yeQZtZW1vcnkCAAMDAgEABwgBBHNpemUAAAoGAQQAPwAL", + "AGFzbQEAAAABEQRgAABgAAF/YAABfWABfwF/AwcGAAEBAgMBBQQBAQEBB2sGD3plcm9fZXZlcnl0aGluZwAAEnRlc3Rfc3RvcmVfdG9fbG9hZAABE3Rlc3RfcmVkdW5kYW50X2xvYWQAAg90ZXN0X2RlYWRfc3RvcmUAAwZtYWxsb2MABA9tYWxsb2NfYWxpYXNpbmcABQqlAQYeAEEAQQA2AgBBBEEANgIAQQhBADYCAEEMQQA2AgALGABBCEEANgIAQQVDAAAAgDgCAEEIKAIACyIBAn9BCCgCACEAQQVBgICAgHg2AgBBCCgCACEBIAAgAWoLHwEBfUEIQaPGjJkCNgIAQQsqAgAhAEEIQQA2AgAgAAsEAEEQCyMBAn9BBBAEIQBBBBAEIQEgAEEqNgIAIAFBKzYCACAAKAIACw==", + "AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQMBAAAHDwIEc2l6ZQAABGdyb3cAAQoOAgQAPwALBwAgAEAAGgs=", + "AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQMBAAEHDwIEc2l6ZQAABGdyb3cAAQoOAgQAPwALBwAgAEAAGgs=", + "AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQQBAQACBw8CBHNpemUAAARncm93AAEKDgIEAD8ACwcAIABAABoL", + "AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQQBAQMIBw8CBHNpemUAAARncm93AAEKDgIEAD8ACwcAIABAABoL", + "AGFzbQEAAAABDwNgAAF/YAJ/fwBgAX8BfwMFBAABAgIFAwEAAQceAwVzdG9yZQABBGxvYWQAAgttZW1vcnkuZ3JvdwADCioECQA/AEGAgARsCwwAEAAgAGogATYCAAsKABAAIABqKAIACwYAIABAAAs=", + "AGFzbQEAAAABKQhgAX8Bf2ABfwF+YAF/AX1gAX8BfGACf38AYAJ/fgBgAn99AGACf3wAAxgXAAECAwAAAAABAQEBAQEEBQYHBAQFBQUFAwEAAQezAhcIaTMyLmxvYWQAAAhpNjQubG9hZAABCGYzMi5sb2FkAAIIZjY0LmxvYWQAAwtpMzIubG9hZDhfcwAEC2kzMi5sb2FkOF91AAUMaTMyLmxvYWQxNl9zAAYMaTMyLmxvYWQxNl91AAcLaTY0LmxvYWQ4X3MACAtpNjQubG9hZDhfdQAJDGk2NC5sb2FkMTZfcwAKDGk2NC5sb2FkMTZfdQALDGk2NC5sb2FkMzJfcwAMDGk2NC5sb2FkMzJfdQANCWkzMi5zdG9yZQAOCWk2NC5zdG9yZQAPCWYzMi5zdG9yZQAQCWY2NC5zdG9yZQARCmkzMi5zdG9yZTgAEgtpMzIuc3RvcmUxNgATCmk2NC5zdG9yZTgAFAtpNjQuc3RvcmUxNgAVC2k2NC5zdG9yZTMyABYKywEXBwAgACgCAAsHACAAKQMACwcAIAAqAgALBwAgACsDAAsHACAALAAACwcAIAAtAAALBwAgAC4BAAsHACAALwEACwcAIAAwAAALBwAgADEAAAsHACAAMgEACwcAIAAzAQALBwAgADQCAAsHACAANQIACwkAIAAgATYCAAsJACAAIAE3AwALCQAgACABOAIACwkAIAAgATkDAAsJACAAIAE6AAALCQAgACABOwEACwkAIAAgATwAAAsJACAAIAE9AQALCQAgACABPgIACwsdAgBBAAsIYWJjZGVmZ2gAQfj/AwsIYWJjZGVmZ2g=", + "AGFzbQEAAAAFAwEAAQsGAQEDZm9v", + "AGFzbQEAAAABBAFgAAADAwIAAAQEAXAAAwkNAQVwA9IAC9BwC9IBCwoHAgIACwIACw==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHEgIEZmlsbAAAB2xvYWQ4X3UAAQoVAgsAIAAgASAC/AsACwcAIAAtAAAL", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxICBGNvcHkAAAdsb2FkOF91AAEKFgIMACAAIAEgAvwKAAALBwAgAC0AAAsLCgEAQQALBKq7zN0=", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHEgIEaW5pdAAAB2xvYWQ4X3UAAQwBAQoWAgwAIAAgASAC/AgAAAsHACAALQAACwsHAQEEqrvM3Q==", + "AGFzbQEAAAABCAJgAABgAX8AAwUEAAEAAQUDAQABBzsEDGRyb3BfcGFzc2l2ZQAADGluaXRfcGFzc2l2ZQABC2Ryb3BfYWN0aXZlAAILaW5pdF9hY3RpdmUAAwwBAgonBAUA/AkACwwAQQBBACAA/AgAAAsFAPwJAQsMAEEAQQAgAPwIAQALCwoCAQF4AEEACwF4", + "AGFzbQEAAAABBAFgAAADAgEADAFBCgcBBQD8CUALC4MBQQEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQA=", + "AGFzbQEAAAABBAFgAAADAgEADAEBCgcBBQD8CQALCwoBAQdnb29kYnll", + "AGFzbQEAAAABEANgAAF/YAN/f38AYAF/AX8DBQQAAAECBAQBcAADBw8CBGluaXQAAgRjYWxsAAMJCAEBAAQAAQABCiAEBABBAAsEAEEBCwwAIAAgASAC/AwAAAsHACAAEQAACw==", + "AGFzbQEAAAABCAJgAABgAX8AAwYFAAABAAEEBAFwAAEHOwQMZHJvcF9wYXNzaXZlAAEMaW5pdF9wYXNzaXZlAAILZHJvcF9hY3RpdmUAAwtpbml0X2FjdGl2ZQAECQsCAQABAABBAAsBAAoqBQIACwUA/A0ACwwAQQBBACAA/AwAAAsFAPwNAQsMAEEAQQAgAPwMAQAL", + "AGFzbQEAAAABBAFgAAADAgEACcQBQQEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAoHAQUA/A1ACw==", + "AGFzbQEAAAABBAFgAAADAgEACQUBAQABAAoHAQUA/A0ACw==", + "AGFzbQEAAAABEANgAAF/YAN/f38AYAF/AX8DBgUAAAABAgQEAXAACgcPAgRjb3B5AAMEY2FsbAAECQkBAEEACwMAAQIKJQUEAEEACwQAQQELBABBAgsMACAAIAEgAvwOAAALBwAgABEAAAs=", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABCg0CAwABCwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDUECQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBGUEPQQL8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDUEZQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBFEEWQQT8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBGUEBQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBCkEMQQf8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDEEKQQf8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsaAQBBAAsUAAECAwQFBgcICQoLDA0ODxAREhM=", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsbAQBBAAsVAAECAwQFBgcICQoLDA0ODxAREhMU", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBB7P8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsdAQBB6/8DCxUAAQIDBAUGBwgJCgsMDQ4PEBESExQ=", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBBzv8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBB4v8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw==", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHFwMDbWVtAgADcnVuAAAHbG9hZDhfdQABChYCDAAgACABIAL8CgAACwcAIAAtAAALCxwBAEHs/wMLFAABAgMEBQYHCAkKCwwNDg8QERIT", + "AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBBgOADCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw==", + "AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpAAhYAQQpB1QBBCvwLAEEJQQpBBfwKAAALJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCw==", + "AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpAAhYAQQpB1QBBCvwLAEEQQQ9BBfwKAAALJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCw==", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoTAREAQYD+A0GAgAJBgQL8CgAACw==", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYB+QYCAAUGBAvwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoTAREAQYCAAkGA/gNBgQL8CgAACw==", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCAAUGAfkGBAvwKAAAL", + "AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpUAioAQQBB1QBBgIAC/AsAQYCAAkGqAUGAgAL8CwBBgKACQYDgAUEA/AoAAAsnAANAIAAgAUYEQEF/DwsgAC0AACACRgRAIABBAWohAAwBCwsgAA8L", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCABEGA4AFBAPwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCACEGA4AFBAPwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCgAkGAgARBAPwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCgAkGAgAhBAPwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCABEGAgARBAPwKAAAL", + "AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCACEGAgAhBAPwKAAAL", + "AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQq3FQKMFQBB54oBQQFBwAr8CwBB6bACQQJBnwj8CwBB0bgDQQNB3Af8CwBByqgCQQRBwgL8CwBBqT5BBUHKD/wLAEG6sQFBBkHcF/wLAEHygwFBB0HEEvwLAEHj0wJBCEHDBvwLAEH8AEEJQfEK/AsAQdQQQQpBxhX8CwBBm8YAQQtBmhj8CwBB55sDQQxB5QX8CwBB9h5BDUGHFvwLAEGzhANBDkGACvwLAEHJiQNBD0G6C/wLAEGNoAFBEEHWGPwLAEGx9AJBEUGgBPwLAEGj4QBBEkHtFPwLAEGlwgFBE0HbFPwLAEGF4gJBFEGiDPwLAEHY0AJBFUGbDfwLAEHeiAJBFkGGBfwLAEGr+wJBF0HCDvwLAEHNoQNBGEHhFPwLAEGb7QFBGUHVB/wLAEHUyABBGkGPDvwLAEGOiANBG0HnA/wLAEGh6gNBHEGSBPwLAEHcmwJBHUGvB/wLAEHwNEEeQf0C/AsAQb6QA0EfQZEY/AsAQcGEA0EgQZIF/AsAQfzbAkEhQaYN/AsAQb6EAkEiQcQI/AsAQf6MA0EjQYIL/AsAQerzAkEkQZwR/AsAQeumA0ElQdoS/AsAQY+vA0EmQfoB/AsAQdywAUEnQbEQ/AsAQeyFAUEoQcAZ/AsAQbuoA0EpQeMZ/AsAQbK0AkEqQewV/AsAQbyaAkErQZYQ/AsAQeyTAkEsQcsV/AsAQdv/AUEtQbgC/AsAQYLyA0EuQcAB/AsAQf7xAUEvQdQE/AsAQfuBAUEwQfUD/AsAQaq9A0ExQa4F/AsAQfuLAkEyQYED/AsAQdHbA0EzQYcH/AsAQYXgA0E0QdYS/AsAQfzuAkE1QaEL/AsAQfXKAUE2QdoY/AsAQb4rQTdB1xD8CwBBiZkCQThBhwT8CwBB3N4CQTlB0Bn8CwBBqO0CQTpBjg38CwBBj+wCQTtB4Bj8CwBBsa8BQTxBoQv8CwBB8ckDQT1BlwX8CwBBhfwBQT5Bhw38CwBB9xdBP0HRBfwLAEHpiQJBwABB1AD8CwBBuoQCQcEAQe0P/AsAQcqfAkHCAEEd/AsAQcuVAUHDAEHaF/wLAEHI4gBBxABBkwj8CwBB5I4BQcUAQfwZ/AsAQZ8kQcYAQcMI/AsAQZ7+AEHHAEHND/wLAEGcjgFByABB0xH8CwBB5IoDQckAQfUY/AsAQZTWAEHKAEGwD/wLAEHa/ABBywBBrwv8CwBB3uICQcwAQZkJ/AsAQfmmA0HNAEGgDPwLAEG7ggJBzgBB6gz8CwBB5NwDQc8AQdQZ/AsAQZGUA0HQAEHfAfwLAEGJIkHRAEH7EPwLAEGqwQNB0gBBqgr8CwBBrLMDQdMAQdgU/AsAQZu8AUHUAEGVCPwLAEGv0QJB1QBBmRj8CwBBs/wBQdYAQewV/AsAQeMdQdcAQdoP/AsAQcisA0HYAEEA/AsAQZWGA0HZAEGVEPwLAEG7nwFB2gBB0Bb8CwBBoogCQdsAQcAB/AsAQbrJAEHcAEGTEfwLAEH94ABB3QBBGPwLAEGL7gBB3gBBwQT8CwBBmtgCQd8AQakQ/AsAQf+eAkHgAEHsGvwLAEH4tQFB4QBBzRX8CwBB+DFB4gBBvgb8CwBBm4QCQeMAQZIP/AsAQbWrAUHkAEG+FfwLAEHOzgNB6KcDQbIQ/AoAAEGy7ANBuLICQeYB/AoAAEH5lANBzbgBQfwR/AoAAEG0NEG8uwFB/wT8CgAAQc42QfeEAkHJCPwKAABBy5cBQezQAEH9GPwKAABBrNUBQYapA0HkAPwKAABB1dQBQaLVAkG1DfwKAABB8NgDQbXDAEH3APwKAABBuy5BhBJBkgX8CgAAQbMlQa+TA0HdEfwKAABByeIAQf2VAUHBBvwKAABBztwAQanrAkHkGfwKAABB8NgAQdTfAkHpEfwKAABBiosCQak0QYwU/AoAAEHIJkGaDUGwCvwKAABBvO0DQdU7QYYN/AoAAEGY3AJBqI8BQSH8CgAAQY7XAkHMrgFBkwv8CgAAQa3sAkGbhQNBmgv8CgAAQcTxA0GzxABBwgb8CgAAQc2FAkGjnQFB9Rn8CgAAQf+8AkGtqANBgRn8CgAAQdTJAUH2zgNBlBP8CgAAQd6ZAUGyvANB2gL8CgAAQez7AEHKmAJB/hL8CgAAQbDcAEH2lQJBrAL8CgAAQaPQA0GF7QBB0Rj8CgAAQfuLAkGy2QNBgQr8CgAAQYTGAEH03wBBrwf8CgAAQYsWQbnRAEHfDvwKAABButECQYbXAkHiBfwKAABBvuwDQYWUAUH6APwKAABB7LsBQdndAkHbDfwKAABB0LABQaPzAEG+BfwKAABBlNgAQdPPAUGmDvwKAABBtLQBQfefAUGoCPwKAABBoL8DQfKrA0HHFPwKAABBlMcBQYEIQakY/AoAAEG0gwNBvNkCQc8H/AoAAEH43AFB+sUCQaAS/AoAAEHp3gNB5gFBuBb8CgAAQdCvAUGamgNBlRH8CgAAQem8AkHqygBBpg/8CgAAQcziAUH+ogFBihH8CgAAQaWeA0Gz1wJBjQj8CgAAQYTHAUHTlgJB8gz8CgAAQZTJA0H75QJBwg/8CgAAQZmrAkGQLUGjD/wKAABB194BQcSwA0HAEvwKAABBm+kDQbyNAUHMCvwKAABB5YcDQaXsAEH+AvwKAABBiIQBQfWbAkHsDvwKAABB4vcCQd7YAEH3FfwKAABB4N4BQaq7AkHDAvwKAABBspUCQdDZAUGGDfwKAABB+usDQdSgA0G9CvwKAABBte4AQejpAkGEBfwKAABB5uIBQYKVAUHwA/wKAABBmN8CQdnzAkHgFfwKAABBh7UCQfXcAkHGCvwKAABB8NAAQdrkAUHDC/wKAABBv+4CQeLoAkG7C/wKAABBqSZBxOABQecO/AoAAEH8qAJBpb8DQdcN/AoAAEHOzgFB19QBQecI/AoAAEHTywNB0cABQacI/AoAAEGs3wNBhq8CQf4F/AoAAEGA2QJB7BFB8Av8CgAAQeT/AUGF8QJBxhf8CgAAQYzXAEGMpgFB8wf8CgAAQfE7Qfz2AUHaF/wKAABB/IwBQbvlAEH4GfwKAABB2r8DQeG0A0G0AvwKAABB48ABQa+DAUGDCfwKAABBvJsBQYPPAEHSBfwKAABB6RZBry5BwhL8CgAAQf/7AUGvhwNB7hb8CgAAQZb2AEGThwFBrxT8CgAAQYfkAkGf3gFB/Q/8CgAAQe2uA0GRmgJBpBT8CgAAQa3eAUGNpwNBkAn8CgAAQc/2AkGJoQNBwRj8CgAAQbbvAUHj4AJB2RT8CgAAQcEnQcchQTT8CgAAQaQ0QYO9AUG5A/wKAABB2IECQe3TAUH1GvwKAABBkv4BQezPA0HhFfwKAABBuYwCQYLGAEHmEvwKAABB5YsBQYqqA0G1GvwKAABBnbEBQffYAkGIAfwKAABB0c0DQaU3QZUI/AoAAEHBzwJB9K0DQdUS/AoAAEGV3QJBqp0BQe0G/AoAAEHKnwJB7MQBQfca/AoAAEGu5QJBkPkBQdYG/AoAAEGsvQFB+vgBQeEK/AoAAEHyhwJBtAVBugz8CgAAQcrZA0GZkQFBqxf8CgAAQcKJA0G3wgJB/gr8CgAACycAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADws=", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo5AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsPAEGA/gNB1QBBgAL8CwAL", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo5AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsPAEGA/gNB1QBBgQL8CwAL", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAfkHVAEGBAvwLAAs=", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo2AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsMAEESQdUAQQD8CwAL", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAgARB1QBBAPwLAAs=", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAgAhB1QBBAPwLAAs=", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEEBQaoBQf7/A/wLAAs=", + "AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQpAAicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsWAEESQdUAQQr8CwBBFUGqAUEE/AsACw==", + "AGFzbQEAAAABDgJgA39/fwF/YAN/f38AAwMCAAEFBAEBAQEHFAIKY2hlY2tSYW5nZQAAA3J1bgABCjUCJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCwsAIAAgASAC/AsACw==", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABCg0CAwABCwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY=", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEChYCDABBB0EAQQT8CAEACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY=", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEChYCDABBD0EBQQP8CAMACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY=", + "AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEClgCTgBBB0EAQQT8CAEA/AkBQQ9BAUED/AgDAPwJA0EUQQ9BBfwKAABBFUEdQQH8CgAAQRhBCkEB/AoAAEENQQtBBPwKAABBE0EUQQX8CgAACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCgoBCAD8CQD8CQALCwQBAQE3", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChIBEAD8CQBB0glBAUEB/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAUEB/AgAAAsLBwEAQQALATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBBAUEAQQH8CAAAQQFBAEEB/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAEEF/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAkED/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBB/v8DQQFBA/wIAAALCwQBAQE3", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBBEEA/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAUEA/AgAAAsLBAEBATc=", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgYAEQQBBAPwIAAALCwQBAQE3", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgIAEQQBBAPwIAAALCwQBAQE3", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgIAEQQFBAPwIAAALCwQBAQE3", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgYAEQQRBAPwIAAALCwQBAQE3", + "AGFzbQEAAAABDQJgA39/fwF/YAJ/fwADAwIAAQUEAQEBAQcUAgpjaGVja1JhbmdlAAADcnVuAAEMAQEKNgInAANAIAAgAUYEQEF/DwsgAC0AACACRgRAIABBAWohAAwBCwsgAA8LDAAgAEEAIAH8CAAACwsTAQEQQkJCQkJCQkJCQkJCQkJCQg==", + "AGFzbQEAAAABDQJgA39/fwF/YAJ/fwADAwIAAQUDAQABBxQCCmNoZWNrUmFuZ2UAAANydW4AAQwBAQo2AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsMACAAQQAgAfwIAAALCxMBARBCQkJCQkJCQkJCQkJCQkJC", + "AGFzbQEAAAABBAFgAAADAgEABQMBAAEMAUEKDgEMAEEAQQBBAPwIQAALC4MBQQEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQA=", + "AGFzbQEAAAAFAwEAAQuzARwAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMBAAEEYWJjZABBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwBBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwBBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwEAAQRhYmNk", + "AGFzbQEAAAAFAwEAAQsHAQBBAAsBYQ==", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwcBAEEACwFh", + "AGFzbQEAAAAFAwEAAQsiBQBBAAsBYQBBAwsBYgBB5AALA2NkZQBBBQsBeABBAwsBYw==", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCycGAEEACwFhAEEBCwFiAEECCwNjZGUAQQMLAWYAQQILAWcAQQELAWg=", + "AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAUDAQABCwcBACMACwFh", + "AGFzbQEAAAACKwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAAELBwEAIwALAWE=", + "AGFzbQEAAAAFAwEAAQsPAgBBAAsBYQBB//8DCwFi", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCw8CAEEACwFhAEH//wMLAWI=", + "AGFzbQEAAAAFAwEAAgsJAQBB//8HCwFh", + "AGFzbQEAAAAFAwEAAAsGAQBBAAsA", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwYBAEEACwA=", + "AGFzbQEAAAAFBAEBAAALBgEAQQALAA==", + "AGFzbQEAAAAFAwEAAQsIAQBBgIAECwA=", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwcBAEEACwFh", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAwsHAQBBAAsBYQ==", + "AGFzbQEAAAACKwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAAALBwEAIwALAWE=", + "AGFzbQEAAAACLAIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAQADCwcBACMACwFh", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwcBAEEBCwFh", + "AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAwsHAQBBAQsBYQ==", + "AGFzbQEAAAAFAwEAAAsHAQBBAAsBYQ==", + "AGFzbQEAAAAFBAEBAAALBwEAQQALAWE=", + "AGFzbQEAAAAFBAEBAAELBwEAQQALAWE=", + "AGFzbQEAAAAFAwEAAAsGAQBBAQsA", + "AGFzbQEAAAAFBAEBAAELBgEAQQELAA==", + "AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAUDAQAACwcBACMACwFh", + "AGFzbQEAAAAFBAEBAQILCQEAQYCABAsBYQ==", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwkBAEGAgAQLAWE=", + "AGFzbQEAAAAFAwEAAgsJAQBBgIAICwFh", + "AGFzbQEAAAAFBAEBAgMLCQEAQYCACAsBYQ==", + "AGFzbQEAAAAFAwEAAQsHAQBBfwsBYQ==", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwcBAEF/CwFh", + "AGFzbQEAAAAFAwEAAgsIAQBBnH8LAWE=", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwgBAEGcfwsBYQ==", +]; +export const script = "[[\"file\",\"address.wast\"],[\"module\",3,0],[\"invoke\",104,0,\"8u_good1\",[\"i32:0\"]],[\"invoke\",105,0,\"8u_good2\",[\"i32:0\"]],[\"invoke\",106,0,\"8u_good3\",[\"i32:0\"]],[\"invoke\",107,0,\"8u_good4\",[\"i32:0\"]],[\"invoke\",108,0,\"8u_good5\",[\"i32:0\"]],[\"invoke\",110,0,\"8s_good1\",[\"i32:0\"]],[\"invoke\",111,0,\"8s_good2\",[\"i32:0\"]],[\"invoke\",112,0,\"8s_good3\",[\"i32:0\"]],[\"invoke\",113,0,\"8s_good4\",[\"i32:0\"]],[\"invoke\",114,0,\"8s_good5\",[\"i32:0\"]],[\"invoke\",116,0,\"16u_good1\",[\"i32:0\"]],[\"invoke\",117,0,\"16u_good2\",[\"i32:0\"]],[\"invoke\",118,0,\"16u_good3\",[\"i32:0\"]],[\"invoke\",119,0,\"16u_good4\",[\"i32:0\"]],[\"invoke\",120,0,\"16u_good5\",[\"i32:0\"]],[\"invoke\",122,0,\"16s_good1\",[\"i32:0\"]],[\"invoke\",123,0,\"16s_good2\",[\"i32:0\"]],[\"invoke\",124,0,\"16s_good3\",[\"i32:0\"]],[\"invoke\",125,0,\"16s_good4\",[\"i32:0\"]],[\"invoke\",126,0,\"16s_good5\",[\"i32:0\"]],[\"invoke\",128,0,\"32_good1\",[\"i32:0\"]],[\"invoke\",129,0,\"32_good2\",[\"i32:0\"]],[\"invoke\",130,0,\"32_good3\",[\"i32:0\"]],[\"invoke\",131,0,\"32_good4\",[\"i32:0\"]],[\"invoke\",132,0,\"32_good5\",[\"i32:0\"]],[\"invoke\",134,0,\"8u_good1\",[\"i32:65507\"]],[\"invoke\",135,0,\"8u_good2\",[\"i32:65507\"]],[\"invoke\",136,0,\"8u_good3\",[\"i32:65507\"]],[\"invoke\",137,0,\"8u_good4\",[\"i32:65507\"]],[\"invoke\",138,0,\"8u_good5\",[\"i32:65507\"]],[\"invoke\",140,0,\"8s_good1\",[\"i32:65507\"]],[\"invoke\",141,0,\"8s_good2\",[\"i32:65507\"]],[\"invoke\",142,0,\"8s_good3\",[\"i32:65507\"]],[\"invoke\",143,0,\"8s_good4\",[\"i32:65507\"]],[\"invoke\",144,0,\"8s_good5\",[\"i32:65507\"]],[\"invoke\",146,0,\"16u_good1\",[\"i32:65507\"]],[\"invoke\",147,0,\"16u_good2\",[\"i32:65507\"]],[\"invoke\",148,0,\"16u_good3\",[\"i32:65507\"]],[\"invoke\",149,0,\"16u_good4\",[\"i32:65507\"]],[\"invoke\",150,0,\"16u_good5\",[\"i32:65507\"]],[\"invoke\",152,0,\"16s_good1\",[\"i32:65507\"]],[\"invoke\",153,0,\"16s_good2\",[\"i32:65507\"]],[\"invoke\",154,0,\"16s_good3\",[\"i32:65507\"]],[\"invoke\",155,0,\"16s_good4\",[\"i32:65507\"]],[\"invoke\",156,0,\"16s_good5\",[\"i32:65507\"]],[\"invoke\",158,0,\"32_good1\",[\"i32:65507\"]],[\"invoke\",159,0,\"32_good2\",[\"i32:65507\"]],[\"invoke\",160,0,\"32_good3\",[\"i32:65507\"]],[\"invoke\",161,0,\"32_good4\",[\"i32:65507\"]],[\"invoke\",162,0,\"32_good5\",[\"i32:65507\"]],[\"invoke\",164,0,\"8u_good1\",[\"i32:65508\"]],[\"invoke\",165,0,\"8u_good2\",[\"i32:65508\"]],[\"invoke\",166,0,\"8u_good3\",[\"i32:65508\"]],[\"invoke\",167,0,\"8u_good4\",[\"i32:65508\"]],[\"invoke\",168,0,\"8u_good5\",[\"i32:65508\"]],[\"invoke\",170,0,\"8s_good1\",[\"i32:65508\"]],[\"invoke\",171,0,\"8s_good2\",[\"i32:65508\"]],[\"invoke\",172,0,\"8s_good3\",[\"i32:65508\"]],[\"invoke\",173,0,\"8s_good4\",[\"i32:65508\"]],[\"invoke\",174,0,\"8s_good5\",[\"i32:65508\"]],[\"invoke\",176,0,\"16u_good1\",[\"i32:65508\"]],[\"invoke\",177,0,\"16u_good2\",[\"i32:65508\"]],[\"invoke\",178,0,\"16u_good3\",[\"i32:65508\"]],[\"invoke\",179,0,\"16u_good4\",[\"i32:65508\"]],[\"invoke\",180,0,\"16u_good5\",[\"i32:65508\"]],[\"invoke\",182,0,\"16s_good1\",[\"i32:65508\"]],[\"invoke\",183,0,\"16s_good2\",[\"i32:65508\"]],[\"invoke\",184,0,\"16s_good3\",[\"i32:65508\"]],[\"invoke\",185,0,\"16s_good4\",[\"i32:65508\"]],[\"invoke\",186,0,\"16s_good5\",[\"i32:65508\"]],[\"invoke\",188,0,\"32_good1\",[\"i32:65508\"]],[\"invoke\",189,0,\"32_good2\",[\"i32:65508\"]],[\"invoke\",190,0,\"32_good3\",[\"i32:65508\"]],[\"invoke\",191,0,\"32_good4\",[\"i32:65508\"]],[\"invoke\",192,0,\"32_good5\",[\"i32:65508\"]],[\"invoke\",194,0,\"8u_good3\",[\"i32:4294967295\"]],[\"invoke\",195,0,\"8s_good3\",[\"i32:4294967295\"]],[\"invoke\",196,0,\"16u_good3\",[\"i32:4294967295\"]],[\"invoke\",197,0,\"16s_good3\",[\"i32:4294967295\"]],[\"invoke\",198,0,\"32_good3\",[\"i32:4294967295\"]],[\"invoke\",199,0,\"32_good3\",[\"i32:4294967295\"]],[\"invoke\",201,0,\"8u_bad\",[\"i32:0\"]],[\"invoke\",202,0,\"8s_bad\",[\"i32:0\"]],[\"invoke\",203,0,\"16u_bad\",[\"i32:0\"]],[\"invoke\",204,0,\"16s_bad\",[\"i32:0\"]],[\"invoke\",205,0,\"32_bad\",[\"i32:0\"]],[\"invoke\",207,0,\"8u_bad\",[\"i32:1\"]],[\"invoke\",208,0,\"8s_bad\",[\"i32:1\"]],[\"invoke\",209,0,\"16u_bad\",[\"i32:1\"]],[\"invoke\",210,0,\"16s_bad\",[\"i32:1\"]],[\"invoke\",211,0,\"32_bad\",[\"i32:1\"]],[\"module\",223,1],[\"invoke\",362,0,\"8u_good1\",[\"i32:0\"]],[\"invoke\",363,0,\"8u_good2\",[\"i32:0\"]],[\"invoke\",364,0,\"8u_good3\",[\"i32:0\"]],[\"invoke\",365,0,\"8u_good4\",[\"i32:0\"]],[\"invoke\",366,0,\"8u_good5\",[\"i32:0\"]],[\"invoke\",368,0,\"8s_good1\",[\"i32:0\"]],[\"invoke\",369,0,\"8s_good2\",[\"i32:0\"]],[\"invoke\",370,0,\"8s_good3\",[\"i32:0\"]],[\"invoke\",371,0,\"8s_good4\",[\"i32:0\"]],[\"invoke\",372,0,\"8s_good5\",[\"i32:0\"]],[\"invoke\",374,0,\"16u_good1\",[\"i32:0\"]],[\"invoke\",375,0,\"16u_good2\",[\"i32:0\"]],[\"invoke\",376,0,\"16u_good3\",[\"i32:0\"]],[\"invoke\",377,0,\"16u_good4\",[\"i32:0\"]],[\"invoke\",378,0,\"16u_good5\",[\"i32:0\"]],[\"invoke\",380,0,\"16s_good1\",[\"i32:0\"]],[\"invoke\",381,0,\"16s_good2\",[\"i32:0\"]],[\"invoke\",382,0,\"16s_good3\",[\"i32:0\"]],[\"invoke\",383,0,\"16s_good4\",[\"i32:0\"]],[\"invoke\",384,0,\"16s_good5\",[\"i32:0\"]],[\"invoke\",386,0,\"32u_good1\",[\"i32:0\"]],[\"invoke\",387,0,\"32u_good2\",[\"i32:0\"]],[\"invoke\",388,0,\"32u_good3\",[\"i32:0\"]],[\"invoke\",389,0,\"32u_good4\",[\"i32:0\"]],[\"invoke\",390,0,\"32u_good5\",[\"i32:0\"]],[\"invoke\",392,0,\"32s_good1\",[\"i32:0\"]],[\"invoke\",393,0,\"32s_good2\",[\"i32:0\"]],[\"invoke\",394,0,\"32s_good3\",[\"i32:0\"]],[\"invoke\",395,0,\"32s_good4\",[\"i32:0\"]],[\"invoke\",396,0,\"32s_good5\",[\"i32:0\"]],[\"invoke\",398,0,\"64_good1\",[\"i32:0\"]],[\"invoke\",399,0,\"64_good2\",[\"i32:0\"]],[\"invoke\",400,0,\"64_good3\",[\"i32:0\"]],[\"invoke\",401,0,\"64_good4\",[\"i32:0\"]],[\"invoke\",402,0,\"64_good5\",[\"i32:0\"]],[\"invoke\",404,0,\"8u_good1\",[\"i32:65503\"]],[\"invoke\",405,0,\"8u_good2\",[\"i32:65503\"]],[\"invoke\",406,0,\"8u_good3\",[\"i32:65503\"]],[\"invoke\",407,0,\"8u_good4\",[\"i32:65503\"]],[\"invoke\",408,0,\"8u_good5\",[\"i32:65503\"]],[\"invoke\",410,0,\"8s_good1\",[\"i32:65503\"]],[\"invoke\",411,0,\"8s_good2\",[\"i32:65503\"]],[\"invoke\",412,0,\"8s_good3\",[\"i32:65503\"]],[\"invoke\",413,0,\"8s_good4\",[\"i32:65503\"]],[\"invoke\",414,0,\"8s_good5\",[\"i32:65503\"]],[\"invoke\",416,0,\"16u_good1\",[\"i32:65503\"]],[\"invoke\",417,0,\"16u_good2\",[\"i32:65503\"]],[\"invoke\",418,0,\"16u_good3\",[\"i32:65503\"]],[\"invoke\",419,0,\"16u_good4\",[\"i32:65503\"]],[\"invoke\",420,0,\"16u_good5\",[\"i32:65503\"]],[\"invoke\",422,0,\"16s_good1\",[\"i32:65503\"]],[\"invoke\",423,0,\"16s_good2\",[\"i32:65503\"]],[\"invoke\",424,0,\"16s_good3\",[\"i32:65503\"]],[\"invoke\",425,0,\"16s_good4\",[\"i32:65503\"]],[\"invoke\",426,0,\"16s_good5\",[\"i32:65503\"]],[\"invoke\",428,0,\"32u_good1\",[\"i32:65503\"]],[\"invoke\",429,0,\"32u_good2\",[\"i32:65503\"]],[\"invoke\",430,0,\"32u_good3\",[\"i32:65503\"]],[\"invoke\",431,0,\"32u_good4\",[\"i32:65503\"]],[\"invoke\",432,0,\"32u_good5\",[\"i32:65503\"]],[\"invoke\",434,0,\"32s_good1\",[\"i32:65503\"]],[\"invoke\",435,0,\"32s_good2\",[\"i32:65503\"]],[\"invoke\",436,0,\"32s_good3\",[\"i32:65503\"]],[\"invoke\",437,0,\"32s_good4\",[\"i32:65503\"]],[\"invoke\",438,0,\"32s_good5\",[\"i32:65503\"]],[\"invoke\",440,0,\"64_good1\",[\"i32:65503\"]],[\"invoke\",441,0,\"64_good2\",[\"i32:65503\"]],[\"invoke\",442,0,\"64_good3\",[\"i32:65503\"]],[\"invoke\",443,0,\"64_good4\",[\"i32:65503\"]],[\"invoke\",444,0,\"64_good5\",[\"i32:65503\"]],[\"invoke\",446,0,\"8u_good1\",[\"i32:65504\"]],[\"invoke\",447,0,\"8u_good2\",[\"i32:65504\"]],[\"invoke\",448,0,\"8u_good3\",[\"i32:65504\"]],[\"invoke\",449,0,\"8u_good4\",[\"i32:65504\"]],[\"invoke\",450,0,\"8u_good5\",[\"i32:65504\"]],[\"invoke\",452,0,\"8s_good1\",[\"i32:65504\"]],[\"invoke\",453,0,\"8s_good2\",[\"i32:65504\"]],[\"invoke\",454,0,\"8s_good3\",[\"i32:65504\"]],[\"invoke\",455,0,\"8s_good4\",[\"i32:65504\"]],[\"invoke\",456,0,\"8s_good5\",[\"i32:65504\"]],[\"invoke\",458,0,\"16u_good1\",[\"i32:65504\"]],[\"invoke\",459,0,\"16u_good2\",[\"i32:65504\"]],[\"invoke\",460,0,\"16u_good3\",[\"i32:65504\"]],[\"invoke\",461,0,\"16u_good4\",[\"i32:65504\"]],[\"invoke\",462,0,\"16u_good5\",[\"i32:65504\"]],[\"invoke\",464,0,\"16s_good1\",[\"i32:65504\"]],[\"invoke\",465,0,\"16s_good2\",[\"i32:65504\"]],[\"invoke\",466,0,\"16s_good3\",[\"i32:65504\"]],[\"invoke\",467,0,\"16s_good4\",[\"i32:65504\"]],[\"invoke\",468,0,\"16s_good5\",[\"i32:65504\"]],[\"invoke\",470,0,\"32u_good1\",[\"i32:65504\"]],[\"invoke\",471,0,\"32u_good2\",[\"i32:65504\"]],[\"invoke\",472,0,\"32u_good3\",[\"i32:65504\"]],[\"invoke\",473,0,\"32u_good4\",[\"i32:65504\"]],[\"invoke\",474,0,\"32u_good5\",[\"i32:65504\"]],[\"invoke\",476,0,\"32s_good1\",[\"i32:65504\"]],[\"invoke\",477,0,\"32s_good2\",[\"i32:65504\"]],[\"invoke\",478,0,\"32s_good3\",[\"i32:65504\"]],[\"invoke\",479,0,\"32s_good4\",[\"i32:65504\"]],[\"invoke\",480,0,\"32s_good5\",[\"i32:65504\"]],[\"invoke\",482,0,\"64_good1\",[\"i32:65504\"]],[\"invoke\",483,0,\"64_good2\",[\"i32:65504\"]],[\"invoke\",484,0,\"64_good3\",[\"i32:65504\"]],[\"invoke\",485,0,\"64_good4\",[\"i32:65504\"]],[\"invoke\",486,0,\"64_good5\",[\"i32:65504\"]],[\"invoke\",488,0,\"8u_good3\",[\"i32:4294967295\"]],[\"invoke\",489,0,\"8s_good3\",[\"i32:4294967295\"]],[\"invoke\",490,0,\"16u_good3\",[\"i32:4294967295\"]],[\"invoke\",491,0,\"16s_good3\",[\"i32:4294967295\"]],[\"invoke\",492,0,\"32u_good3\",[\"i32:4294967295\"]],[\"invoke\",493,0,\"32s_good3\",[\"i32:4294967295\"]],[\"invoke\",494,0,\"64_good3\",[\"i32:4294967295\"]],[\"invoke\",496,0,\"8u_bad\",[\"i32:0\"]],[\"invoke\",497,0,\"8s_bad\",[\"i32:0\"]],[\"invoke\",498,0,\"16u_bad\",[\"i32:0\"]],[\"invoke\",499,0,\"16s_bad\",[\"i32:0\"]],[\"invoke\",500,0,\"32u_bad\",[\"i32:0\"]],[\"invoke\",501,0,\"32s_bad\",[\"i32:0\"]],[\"invoke\",502,0,\"64_bad\",[\"i32:0\"]],[\"invoke\",504,0,\"8u_bad\",[\"i32:1\"]],[\"invoke\",505,0,\"8s_bad\",[\"i32:1\"]],[\"invoke\",506,0,\"16u_bad\",[\"i32:1\"]],[\"invoke\",507,0,\"16s_bad\",[\"i32:1\"]],[\"invoke\",508,0,\"32u_bad\",[\"i32:0\"]],[\"invoke\",509,0,\"32s_bad\",[\"i32:0\"]],[\"invoke\",510,0,\"64_bad\",[\"i32:1\"]],[\"module\",514,2],[\"invoke\",538,0,\"32_good1\",[\"i32:0\"]],[\"invoke\",539,0,\"32_good2\",[\"i32:0\"]],[\"invoke\",540,0,\"32_good3\",[\"i32:0\"]],[\"invoke\",541,0,\"32_good4\",[\"i32:0\"]],[\"invoke\",542,0,\"32_good5\",[\"i32:0\"]],[\"invoke\",544,0,\"32_good1\",[\"i32:65524\"]],[\"invoke\",545,0,\"32_good2\",[\"i32:65524\"]],[\"invoke\",546,0,\"32_good3\",[\"i32:65524\"]],[\"invoke\",547,0,\"32_good4\",[\"i32:65524\"]],[\"invoke\",548,0,\"32_good5\",[\"i32:65524\"]],[\"invoke\",550,0,\"32_good1\",[\"i32:65525\"]],[\"invoke\",551,0,\"32_good2\",[\"i32:65525\"]],[\"invoke\",552,0,\"32_good3\",[\"i32:65525\"]],[\"invoke\",553,0,\"32_good4\",[\"i32:65525\"]],[\"invoke\",554,0,\"32_good5\",[\"i32:65525\"]],[\"invoke\",556,0,\"32_good3\",[\"i32:4294967295\"]],[\"invoke\",557,0,\"32_good3\",[\"i32:4294967295\"]],[\"invoke\",559,0,\"32_bad\",[\"i32:0\"]],[\"invoke\",560,0,\"32_bad\",[\"i32:1\"]],[\"module\",564,3],[\"invoke\",588,0,\"64_good1\",[\"i32:0\"]],[\"invoke\",589,0,\"64_good2\",[\"i32:0\"]],[\"invoke\",590,0,\"64_good3\",[\"i32:0\"]],[\"invoke\",591,0,\"64_good4\",[\"i32:0\"]],[\"invoke\",592,0,\"64_good5\",[\"i32:0\"]],[\"invoke\",594,0,\"64_good1\",[\"i32:65510\"]],[\"invoke\",595,0,\"64_good2\",[\"i32:65510\"]],[\"invoke\",596,0,\"64_good3\",[\"i32:65510\"]],[\"invoke\",597,0,\"64_good4\",[\"i32:65510\"]],[\"invoke\",598,0,\"64_good5\",[\"i32:65510\"]],[\"invoke\",600,0,\"64_good1\",[\"i32:65511\"]],[\"invoke\",601,0,\"64_good2\",[\"i32:65511\"]],[\"invoke\",602,0,\"64_good3\",[\"i32:65511\"]],[\"invoke\",603,0,\"64_good4\",[\"i32:65511\"]],[\"invoke\",604,0,\"64_good5\",[\"i32:65511\"]],[\"invoke\",606,0,\"64_good3\",[\"i32:4294967295\"]],[\"invoke\",607,0,\"64_good3\",[\"i32:4294967295\"]],[\"invoke\",609,0,\"64_bad\",[\"i32:0\"]],[\"invoke\",610,0,\"64_bad\",[\"i32:1\"]],[\"file\",\"align.wast\"],[\"module\",3,4],[\"module\",4,5],[\"module\",5,6],[\"module\",6,7],[\"module\",7,8],[\"module\",8,9],[\"module\",9,10],[\"module\",10,11],[\"module\",11,12],[\"module\",12,13],[\"module\",13,14],[\"module\",14,15],[\"module\",15,16],[\"module\",16,17],[\"module\",17,18],[\"module\",18,19],[\"module\",19,20],[\"module\",20,21],[\"module\",21,22],[\"module\",22,23],[\"module\",23,24],[\"module\",24,25],[\"module\",25,26],[\"module\",458,27],[\"invoke\",802,0,\"f32_align_switch\",[\"i32:0\"]],[\"invoke\",803,0,\"f32_align_switch\",[\"i32:1\"]],[\"invoke\",804,0,\"f32_align_switch\",[\"i32:2\"]],[\"invoke\",805,0,\"f32_align_switch\",[\"i32:3\"]],[\"invoke\",807,0,\"f64_align_switch\",[\"i32:0\"]],[\"invoke\",808,0,\"f64_align_switch\",[\"i32:1\"]],[\"invoke\",809,0,\"f64_align_switch\",[\"i32:2\"]],[\"invoke\",810,0,\"f64_align_switch\",[\"i32:3\"]],[\"invoke\",811,0,\"f64_align_switch\",[\"i32:4\"]],[\"invoke\",813,0,\"i32_align_switch\",[\"i32:0\",\"i32:0\"]],[\"invoke\",814,0,\"i32_align_switch\",[\"i32:0\",\"i32:1\"]],[\"invoke\",815,0,\"i32_align_switch\",[\"i32:1\",\"i32:0\"]],[\"invoke\",816,0,\"i32_align_switch\",[\"i32:1\",\"i32:1\"]],[\"invoke\",817,0,\"i32_align_switch\",[\"i32:2\",\"i32:0\"]],[\"invoke\",818,0,\"i32_align_switch\",[\"i32:2\",\"i32:1\"]],[\"invoke\",819,0,\"i32_align_switch\",[\"i32:2\",\"i32:2\"]],[\"invoke\",820,0,\"i32_align_switch\",[\"i32:3\",\"i32:0\"]],[\"invoke\",821,0,\"i32_align_switch\",[\"i32:3\",\"i32:1\"]],[\"invoke\",822,0,\"i32_align_switch\",[\"i32:3\",\"i32:2\"]],[\"invoke\",823,0,\"i32_align_switch\",[\"i32:4\",\"i32:0\"]],[\"invoke\",824,0,\"i32_align_switch\",[\"i32:4\",\"i32:1\"]],[\"invoke\",825,0,\"i32_align_switch\",[\"i32:4\",\"i32:2\"]],[\"invoke\",826,0,\"i32_align_switch\",[\"i32:4\",\"i32:4\"]],[\"invoke\",828,0,\"i64_align_switch\",[\"i32:0\",\"i32:0\"]],[\"invoke\",829,0,\"i64_align_switch\",[\"i32:0\",\"i32:1\"]],[\"invoke\",830,0,\"i64_align_switch\",[\"i32:1\",\"i32:0\"]],[\"invoke\",831,0,\"i64_align_switch\",[\"i32:1\",\"i32:1\"]],[\"invoke\",832,0,\"i64_align_switch\",[\"i32:2\",\"i32:0\"]],[\"invoke\",833,0,\"i64_align_switch\",[\"i32:2\",\"i32:1\"]],[\"invoke\",834,0,\"i64_align_switch\",[\"i32:2\",\"i32:2\"]],[\"invoke\",835,0,\"i64_align_switch\",[\"i32:3\",\"i32:0\"]],[\"invoke\",836,0,\"i64_align_switch\",[\"i32:3\",\"i32:1\"]],[\"invoke\",837,0,\"i64_align_switch\",[\"i32:3\",\"i32:2\"]],[\"invoke\",838,0,\"i64_align_switch\",[\"i32:4\",\"i32:0\"]],[\"invoke\",839,0,\"i64_align_switch\",[\"i32:4\",\"i32:1\"]],[\"invoke\",840,0,\"i64_align_switch\",[\"i32:4\",\"i32:2\"]],[\"invoke\",841,0,\"i64_align_switch\",[\"i32:4\",\"i32:4\"]],[\"invoke\",842,0,\"i64_align_switch\",[\"i32:5\",\"i32:0\"]],[\"invoke\",843,0,\"i64_align_switch\",[\"i32:5\",\"i32:1\"]],[\"invoke\",844,0,\"i64_align_switch\",[\"i32:5\",\"i32:2\"]],[\"invoke\",845,0,\"i64_align_switch\",[\"i32:5\",\"i32:4\"]],[\"invoke\",846,0,\"i64_align_switch\",[\"i32:6\",\"i32:0\"]],[\"invoke\",847,0,\"i64_align_switch\",[\"i32:6\",\"i32:1\"]],[\"invoke\",848,0,\"i64_align_switch\",[\"i32:6\",\"i32:2\"]],[\"invoke\",849,0,\"i64_align_switch\",[\"i32:6\",\"i32:4\"]],[\"invoke\",850,0,\"i64_align_switch\",[\"i32:6\",\"i32:8\"]],[\"module\",854,28],[\"invoke\",864,0,\"store\",[\"i32:65532\",\"i64:18446744073709551615\"]],[\"invoke\",866,0,\"load\",[\"i32:65532\"]],[\"file\",\"endianness.wast\"],[\"module\",1,29],[\"invoke\",133,0,\"i32_load16_s\",[\"i32:4294967295\"]],[\"invoke\",134,0,\"i32_load16_s\",[\"i32:4294963054\"]],[\"invoke\",135,0,\"i32_load16_s\",[\"i32:42\"]],[\"invoke\",136,0,\"i32_load16_s\",[\"i32:12816\"]],[\"invoke\",138,0,\"i32_load16_u\",[\"i32:4294967295\"]],[\"invoke\",139,0,\"i32_load16_u\",[\"i32:4294963054\"]],[\"invoke\",140,0,\"i32_load16_u\",[\"i32:42\"]],[\"invoke\",141,0,\"i32_load16_u\",[\"i32:51966\"]],[\"invoke\",143,0,\"i32_load\",[\"i32:4294967295\"]],[\"invoke\",144,0,\"i32_load\",[\"i32:4252543054\"]],[\"invoke\",145,0,\"i32_load\",[\"i32:42424242\"]],[\"invoke\",146,0,\"i32_load\",[\"i32:2880249322\"]],[\"invoke\",148,0,\"i64_load16_s\",[\"i64:18446744073709551615\"]],[\"invoke\",149,0,\"i64_load16_s\",[\"i64:18446744073709547374\"]],[\"invoke\",150,0,\"i64_load16_s\",[\"i64:42\"]],[\"invoke\",151,0,\"i64_load16_s\",[\"i64:12816\"]],[\"invoke\",153,0,\"i64_load16_u\",[\"i64:18446744073709551615\"]],[\"invoke\",154,0,\"i64_load16_u\",[\"i64:18446744073709547374\"]],[\"invoke\",155,0,\"i64_load16_u\",[\"i64:42\"]],[\"invoke\",156,0,\"i64_load16_u\",[\"i64:51966\"]],[\"invoke\",158,0,\"i64_load32_s\",[\"i64:18446744073709551615\"]],[\"invoke\",159,0,\"i64_load32_s\",[\"i64:18446744073667127374\"]],[\"invoke\",160,0,\"i64_load32_s\",[\"i64:42424242\"]],[\"invoke\",161,0,\"i64_load32_s\",[\"i64:305419896\"]],[\"invoke\",163,0,\"i64_load32_u\",[\"i64:18446744073709551615\"]],[\"invoke\",164,0,\"i64_load32_u\",[\"i64:18446744073667127374\"]],[\"invoke\",165,0,\"i64_load32_u\",[\"i64:42424242\"]],[\"invoke\",166,0,\"i64_load32_u\",[\"i64:2880249322\"]],[\"invoke\",168,0,\"i64_load\",[\"i64:18446744073709551615\"]],[\"invoke\",169,0,\"i64_load\",[\"i64:18446744073667127374\"]],[\"invoke\",170,0,\"i64_load\",[\"i64:2880249322\"]],[\"invoke\",171,0,\"i64_load\",[\"i64:12370766947463011818\"]],[\"invoke\",173,0,\"f32_load\",[\"f32:3212836864\"]],[\"invoke\",174,0,\"f32_load\",[\"f32:1011494326\"]],[\"invoke\",175,0,\"f32_load\",[\"f32:1166316389\"]],[\"invoke\",176,0,\"f32_load\",[\"f32:2139095039\"]],[\"invoke\",178,0,\"f64_load\",[\"f64:13830554455654793216\"]],[\"invoke\",179,0,\"f64_load\",[\"f64:4653144502447687399\"]],[\"invoke\",180,0,\"f64_load\",[\"f64:4691032041816096430\"]],[\"invoke\",181,0,\"f64_load\",[\"f64:9218868437227405311\"]],[\"invoke\",184,0,\"i32_store16\",[\"i32:4294967295\"]],[\"invoke\",185,0,\"i32_store16\",[\"i32:4294963054\"]],[\"invoke\",186,0,\"i32_store16\",[\"i32:42\"]],[\"invoke\",187,0,\"i32_store16\",[\"i32:51966\"]],[\"invoke\",189,0,\"i32_store\",[\"i32:4294967295\"]],[\"invoke\",190,0,\"i32_store\",[\"i32:4294963054\"]],[\"invoke\",191,0,\"i32_store\",[\"i32:42424242\"]],[\"invoke\",192,0,\"i32_store\",[\"i32:3735931646\"]],[\"invoke\",194,0,\"i64_store16\",[\"i64:18446744073709551615\"]],[\"invoke\",195,0,\"i64_store16\",[\"i64:18446744073709547374\"]],[\"invoke\",196,0,\"i64_store16\",[\"i64:42\"]],[\"invoke\",197,0,\"i64_store16\",[\"i64:51966\"]],[\"invoke\",199,0,\"i64_store32\",[\"i64:18446744073709551615\"]],[\"invoke\",200,0,\"i64_store32\",[\"i64:18446744073709547374\"]],[\"invoke\",201,0,\"i64_store32\",[\"i64:42424242\"]],[\"invoke\",202,0,\"i64_store32\",[\"i64:3735931646\"]],[\"invoke\",204,0,\"i64_store\",[\"i64:18446744073709551615\"]],[\"invoke\",205,0,\"i64_store\",[\"i64:18446744073667127374\"]],[\"invoke\",206,0,\"i64_store\",[\"i64:2880249322\"]],[\"invoke\",207,0,\"i64_store\",[\"i64:12370766947463011818\"]],[\"invoke\",209,0,\"f32_store\",[\"f32:3212836864\"]],[\"invoke\",210,0,\"f32_store\",[\"f32:1011494326\"]],[\"invoke\",211,0,\"f32_store\",[\"f32:1166316389\"]],[\"invoke\",212,0,\"f32_store\",[\"f32:2139095039\"]],[\"invoke\",214,0,\"f64_store\",[\"f64:13830554455654793216\"]],[\"invoke\",215,0,\"f64_store\",[\"f64:4653144502447687399\"]],[\"invoke\",216,0,\"f64_store\",[\"f64:4691032041816096430\"]],[\"invoke\",217,0,\"f64_store\",[\"f64:9218868437227405311\"]],[\"file\",\"float_memory.wast\"],[\"module\",5,30],[\"invoke\",15,0,\"i32.load\",[]],[\"invoke\",16,0,\"f32.load\",[]],[\"invoke\",17,0,\"reset\",[]],[\"invoke\",18,0,\"i32.load\",[]],[\"invoke\",19,0,\"f32.load\",[]],[\"invoke\",20,0,\"f32.store\",[]],[\"invoke\",21,0,\"i32.load\",[]],[\"invoke\",22,0,\"f32.load\",[]],[\"invoke\",23,0,\"reset\",[]],[\"invoke\",24,0,\"i32.load\",[]],[\"invoke\",25,0,\"f32.load\",[]],[\"invoke\",26,0,\"i32.store\",[]],[\"invoke\",27,0,\"i32.load\",[]],[\"invoke\",28,0,\"f32.load\",[]],[\"module\",30,31],[\"invoke\",40,0,\"i64.load\",[]],[\"invoke\",41,0,\"f64.load\",[]],[\"invoke\",42,0,\"reset\",[]],[\"invoke\",43,0,\"i64.load\",[]],[\"invoke\",44,0,\"f64.load\",[]],[\"invoke\",45,0,\"f64.store\",[]],[\"invoke\",46,0,\"i64.load\",[]],[\"invoke\",47,0,\"f64.load\",[]],[\"invoke\",48,0,\"reset\",[]],[\"invoke\",49,0,\"i64.load\",[]],[\"invoke\",50,0,\"f64.load\",[]],[\"invoke\",51,0,\"i64.store\",[]],[\"invoke\",52,0,\"i64.load\",[]],[\"invoke\",53,0,\"f64.load\",[]],[\"module\",57,32],[\"invoke\",67,0,\"i32.load\",[]],[\"invoke\",68,0,\"f32.load\",[]],[\"invoke\",69,0,\"reset\",[]],[\"invoke\",70,0,\"i32.load\",[]],[\"invoke\",71,0,\"f32.load\",[]],[\"invoke\",72,0,\"f32.store\",[]],[\"invoke\",73,0,\"i32.load\",[]],[\"invoke\",74,0,\"f32.load\",[]],[\"invoke\",75,0,\"reset\",[]],[\"invoke\",76,0,\"i32.load\",[]],[\"invoke\",77,0,\"f32.load\",[]],[\"invoke\",78,0,\"i32.store\",[]],[\"invoke\",79,0,\"i32.load\",[]],[\"invoke\",80,0,\"f32.load\",[]],[\"module\",82,33],[\"invoke\",92,0,\"i64.load\",[]],[\"invoke\",93,0,\"f64.load\",[]],[\"invoke\",94,0,\"reset\",[]],[\"invoke\",95,0,\"i64.load\",[]],[\"invoke\",96,0,\"f64.load\",[]],[\"invoke\",97,0,\"f64.store\",[]],[\"invoke\",98,0,\"i64.load\",[]],[\"invoke\",99,0,\"f64.load\",[]],[\"invoke\",100,0,\"reset\",[]],[\"invoke\",101,0,\"i64.load\",[]],[\"invoke\",102,0,\"f64.load\",[]],[\"invoke\",103,0,\"i64.store\",[]],[\"invoke\",104,0,\"i64.load\",[]],[\"invoke\",105,0,\"f64.load\",[]],[\"module\",109,34],[\"invoke\",119,0,\"i32.load\",[]],[\"invoke\",120,0,\"f32.load\",[]],[\"invoke\",121,0,\"reset\",[]],[\"invoke\",122,0,\"i32.load\",[]],[\"invoke\",123,0,\"f32.load\",[]],[\"invoke\",124,0,\"f32.store\",[]],[\"invoke\",125,0,\"i32.load\",[]],[\"invoke\",126,0,\"f32.load\",[]],[\"invoke\",127,0,\"reset\",[]],[\"invoke\",128,0,\"i32.load\",[]],[\"invoke\",129,0,\"f32.load\",[]],[\"invoke\",130,0,\"i32.store\",[]],[\"invoke\",131,0,\"i32.load\",[]],[\"invoke\",132,0,\"f32.load\",[]],[\"module\",134,35],[\"invoke\",144,0,\"i64.load\",[]],[\"invoke\",145,0,\"f64.load\",[]],[\"invoke\",146,0,\"reset\",[]],[\"invoke\",147,0,\"i64.load\",[]],[\"invoke\",148,0,\"f64.load\",[]],[\"invoke\",149,0,\"f64.store\",[]],[\"invoke\",150,0,\"i64.load\",[]],[\"invoke\",151,0,\"f64.load\",[]],[\"invoke\",152,0,\"reset\",[]],[\"invoke\",153,0,\"i64.load\",[]],[\"invoke\",154,0,\"f64.load\",[]],[\"invoke\",155,0,\"i64.store\",[]],[\"invoke\",156,0,\"i64.load\",[]],[\"invoke\",157,0,\"f64.load\",[]],[\"file\",\"load.wast\"],[\"module\",3,36],[\"invoke\",161,0,\"as-br-value\",[]],[\"invoke\",163,0,\"as-br_if-cond\",[]],[\"invoke\",164,0,\"as-br_if-value\",[]],[\"invoke\",165,0,\"as-br_if-value-cond\",[]],[\"invoke\",167,0,\"as-br_table-index\",[]],[\"invoke\",168,0,\"as-br_table-value\",[]],[\"invoke\",169,0,\"as-br_table-value-index\",[]],[\"invoke\",171,0,\"as-return-value\",[]],[\"invoke\",173,0,\"as-if-cond\",[]],[\"invoke\",174,0,\"as-if-then\",[]],[\"invoke\",175,0,\"as-if-else\",[]],[\"invoke\",177,0,\"as-select-first\",[\"i32:0\",\"i32:1\"]],[\"invoke\",178,0,\"as-select-second\",[\"i32:0\",\"i32:0\"]],[\"invoke\",179,0,\"as-select-cond\",[]],[\"invoke\",181,0,\"as-call-first\",[]],[\"invoke\",182,0,\"as-call-mid\",[]],[\"invoke\",183,0,\"as-call-last\",[]],[\"invoke\",185,0,\"as-call_indirect-first\",[]],[\"invoke\",186,0,\"as-call_indirect-mid\",[]],[\"invoke\",187,0,\"as-call_indirect-last\",[]],[\"invoke\",188,0,\"as-call_indirect-index\",[]],[\"invoke\",190,0,\"as-local.set-value\",[]],[\"invoke\",191,0,\"as-local.tee-value\",[]],[\"invoke\",192,0,\"as-global.set-value\",[]],[\"invoke\",194,0,\"as-load-address\",[]],[\"invoke\",195,0,\"as-loadN-address\",[]],[\"invoke\",196,0,\"as-store-address\",[]],[\"invoke\",197,0,\"as-store-value\",[]],[\"invoke\",198,0,\"as-storeN-address\",[]],[\"invoke\",199,0,\"as-storeN-value\",[]],[\"invoke\",201,0,\"as-unary-operand\",[]],[\"invoke\",203,0,\"as-binary-left\",[]],[\"invoke\",204,0,\"as-binary-right\",[]],[\"invoke\",206,0,\"as-test-operand\",[]],[\"invoke\",208,0,\"as-compare-left\",[]],[\"invoke\",209,0,\"as-compare-right\",[]],[\"invoke\",211,0,\"as-memory.grow-size\",[]],[\"file\",\"store.wast\"],[\"module\",3,37],[\"invoke\",44,0,\"as-block-value\",[]],[\"invoke\",45,0,\"as-loop-value\",[]],[\"invoke\",47,0,\"as-br-value\",[]],[\"invoke\",48,0,\"as-br_if-value\",[]],[\"invoke\",49,0,\"as-br_if-value-cond\",[]],[\"invoke\",50,0,\"as-br_table-value\",[]],[\"invoke\",52,0,\"as-return-value\",[]],[\"invoke\",54,0,\"as-if-then\",[]],[\"invoke\",55,0,\"as-if-else\",[]],[\"file\",\"memory.wast\"],[\"module\",3,38],[\"module\",4,39],[\"module\",5,40],[\"module\",6,41],[\"module\",7,42],[\"module\",8,43],[\"module\",13,44],[\"invoke\",14,0,\"memsize\",[]],[\"module\",15,44],[\"invoke\",16,0,\"memsize\",[]],[\"module\",17,45],[\"invoke\",18,0,\"memsize\",[]],[\"module\",92,46],[\"invoke\",180,0,\"data\",[]],[\"invoke\",181,0,\"cast\",[]],[\"invoke\",183,0,\"i32_load8_s\",[\"i32:4294967295\"]],[\"invoke\",184,0,\"i32_load8_u\",[\"i32:4294967295\"]],[\"invoke\",185,0,\"i32_load16_s\",[\"i32:4294967295\"]],[\"invoke\",186,0,\"i32_load16_u\",[\"i32:4294967295\"]],[\"invoke\",188,0,\"i32_load8_s\",[\"i32:100\"]],[\"invoke\",189,0,\"i32_load8_u\",[\"i32:200\"]],[\"invoke\",190,0,\"i32_load16_s\",[\"i32:20000\"]],[\"invoke\",191,0,\"i32_load16_u\",[\"i32:40000\"]],[\"invoke\",193,0,\"i32_load8_s\",[\"i32:4275856707\"]],[\"invoke\",194,0,\"i32_load8_s\",[\"i32:878104047\"]],[\"invoke\",195,0,\"i32_load8_u\",[\"i32:4275856707\"]],[\"invoke\",196,0,\"i32_load8_u\",[\"i32:878104047\"]],[\"invoke\",197,0,\"i32_load16_s\",[\"i32:4275856707\"]],[\"invoke\",198,0,\"i32_load16_s\",[\"i32:878104047\"]],[\"invoke\",199,0,\"i32_load16_u\",[\"i32:4275856707\"]],[\"invoke\",200,0,\"i32_load16_u\",[\"i32:878104047\"]],[\"invoke\",202,0,\"i64_load8_s\",[\"i64:18446744073709551615\"]],[\"invoke\",203,0,\"i64_load8_u\",[\"i64:18446744073709551615\"]],[\"invoke\",204,0,\"i64_load16_s\",[\"i64:18446744073709551615\"]],[\"invoke\",205,0,\"i64_load16_u\",[\"i64:18446744073709551615\"]],[\"invoke\",206,0,\"i64_load32_s\",[\"i64:18446744073709551615\"]],[\"invoke\",207,0,\"i64_load32_u\",[\"i64:18446744073709551615\"]],[\"invoke\",209,0,\"i64_load8_s\",[\"i64:100\"]],[\"invoke\",210,0,\"i64_load8_u\",[\"i64:200\"]],[\"invoke\",211,0,\"i64_load16_s\",[\"i64:20000\"]],[\"invoke\",212,0,\"i64_load16_u\",[\"i64:40000\"]],[\"invoke\",213,0,\"i64_load32_s\",[\"i64:20000\"]],[\"invoke\",214,0,\"i64_load32_u\",[\"i64:40000\"]],[\"invoke\",216,0,\"i64_load8_s\",[\"i64:18364758543954109763\"]],[\"invoke\",217,0,\"i64_load8_s\",[\"i64:3771275841602506223\"]],[\"invoke\",218,0,\"i64_load8_u\",[\"i64:18364758543954109763\"]],[\"invoke\",219,0,\"i64_load8_u\",[\"i64:3771275841602506223\"]],[\"invoke\",220,0,\"i64_load16_s\",[\"i64:18364758543954109763\"]],[\"invoke\",221,0,\"i64_load16_s\",[\"i64:3771275841602506223\"]],[\"invoke\",222,0,\"i64_load16_u\",[\"i64:18364758543954109763\"]],[\"invoke\",223,0,\"i64_load16_u\",[\"i64:3771275841602506223\"]],[\"invoke\",224,0,\"i64_load32_s\",[\"i64:18364758543954109763\"]],[\"invoke\",225,0,\"i64_load32_s\",[\"i64:3771275841602506223\"]],[\"invoke\",226,0,\"i64_load32_u\",[\"i64:18364758543954109763\"]],[\"invoke\",227,0,\"i64_load32_u\",[\"i64:3771275841602506223\"]],[\"module\",246,47],[\"invoke\",260,0,\"load\",[\"i32:0\"]],[\"invoke\",261,0,\"load\",[\"i32:10000\"]],[\"invoke\",262,0,\"load\",[\"i32:20000\"]],[\"invoke\",263,0,\"load\",[\"i32:30000\"]],[\"invoke\",264,0,\"load\",[\"i32:40000\"]],[\"invoke\",265,0,\"load\",[\"i32:50000\"]],[\"invoke\",266,0,\"load\",[\"i32:60000\"]],[\"invoke\",267,0,\"load\",[\"i32:65535\"]],[\"file\",\"memory_grow.wast\"],[\"module\",1,48],[\"invoke\",14,0,\"size\",[]],[\"invoke\",15,0,\"store_at_zero\",[]],[\"invoke\",16,0,\"load_at_zero\",[]],[\"invoke\",17,0,\"store_at_page_size\",[]],[\"invoke\",18,0,\"load_at_page_size\",[]],[\"invoke\",19,0,\"grow\",[\"i32:1\"]],[\"invoke\",20,0,\"size\",[]],[\"invoke\",21,0,\"load_at_zero\",[]],[\"invoke\",22,0,\"store_at_zero\",[]],[\"invoke\",23,0,\"load_at_zero\",[]],[\"invoke\",24,0,\"store_at_page_size\",[]],[\"invoke\",25,0,\"load_at_page_size\",[]],[\"invoke\",26,0,\"grow\",[\"i32:4\"]],[\"invoke\",27,0,\"size\",[]],[\"invoke\",28,0,\"load_at_zero\",[]],[\"invoke\",29,0,\"store_at_zero\",[]],[\"invoke\",30,0,\"load_at_zero\",[]],[\"invoke\",31,0,\"load_at_page_size\",[]],[\"invoke\",32,0,\"store_at_page_size\",[]],[\"invoke\",33,0,\"load_at_page_size\",[]],[\"module\",36,49],[\"invoke\",41,0,\"grow\",[\"i32:0\"]],[\"invoke\",42,0,\"grow\",[\"i32:1\"]],[\"invoke\",43,0,\"grow\",[\"i32:0\"]],[\"invoke\",44,0,\"grow\",[\"i32:2\"]],[\"invoke\",45,0,\"grow\",[\"i32:800\"]],[\"invoke\",46,0,\"grow\",[\"i32:65536\"]],[\"invoke\",47,0,\"grow\",[\"i32:64736\"]],[\"invoke\",48,0,\"grow\",[\"i32:1\"]],[\"module\",50,50],[\"invoke\",55,0,\"grow\",[\"i32:0\"]],[\"invoke\",56,0,\"grow\",[\"i32:1\"]],[\"invoke\",57,0,\"grow\",[\"i32:1\"]],[\"invoke\",58,0,\"grow\",[\"i32:2\"]],[\"invoke\",59,0,\"grow\",[\"i32:6\"]],[\"invoke\",60,0,\"grow\",[\"i32:0\"]],[\"invoke\",61,0,\"grow\",[\"i32:1\"]],[\"invoke\",62,0,\"grow\",[\"i32:65536\"]],[\"module\",66,51],[\"invoke\",87,0,\"check-memory-zero\",[\"i32:0\",\"i32:65535\"]],[\"invoke\",88,0,\"grow\",[\"i32:1\"]],[\"invoke\",89,0,\"check-memory-zero\",[\"i32:65536\",\"i32:131071\"]],[\"invoke\",90,0,\"grow\",[\"i32:1\"]],[\"invoke\",91,0,\"check-memory-zero\",[\"i32:131072\",\"i32:196607\"]],[\"invoke\",92,0,\"grow\",[\"i32:1\"]],[\"invoke\",93,0,\"check-memory-zero\",[\"i32:196608\",\"i32:262143\"]],[\"invoke\",94,0,\"grow\",[\"i32:1\"]],[\"invoke\",95,0,\"check-memory-zero\",[\"i32:262144\",\"i32:327679\"]],[\"invoke\",96,0,\"grow\",[\"i32:1\"]],[\"invoke\",97,0,\"check-memory-zero\",[\"i32:327680\",\"i32:393215\"]],[\"module\",101,52],[\"invoke\",259,0,\"as-br-value\",[]],[\"invoke\",261,0,\"as-br_if-cond\",[]],[\"invoke\",262,0,\"as-br_if-value\",[]],[\"invoke\",263,0,\"as-br_if-value-cond\",[]],[\"invoke\",265,0,\"as-br_table-index\",[]],[\"invoke\",266,0,\"as-br_table-value\",[]],[\"invoke\",267,0,\"as-br_table-value-index\",[]],[\"invoke\",269,0,\"as-return-value\",[]],[\"invoke\",271,0,\"as-if-cond\",[]],[\"invoke\",272,0,\"as-if-then\",[]],[\"invoke\",273,0,\"as-if-else\",[]],[\"invoke\",275,0,\"as-select-first\",[\"i32:0\",\"i32:1\"]],[\"invoke\",276,0,\"as-select-second\",[\"i32:0\",\"i32:0\"]],[\"invoke\",277,0,\"as-select-cond\",[]],[\"invoke\",279,0,\"as-call-first\",[]],[\"invoke\",280,0,\"as-call-mid\",[]],[\"invoke\",281,0,\"as-call-last\",[]],[\"invoke\",283,0,\"as-call_indirect-first\",[]],[\"invoke\",284,0,\"as-call_indirect-mid\",[]],[\"invoke\",285,0,\"as-call_indirect-last\",[]],[\"invoke\",286,0,\"as-call_indirect-index\",[]],[\"invoke\",288,0,\"as-local.set-value\",[]],[\"invoke\",289,0,\"as-local.tee-value\",[]],[\"invoke\",290,0,\"as-global.set-value\",[]],[\"invoke\",292,0,\"as-load-address\",[]],[\"invoke\",293,0,\"as-loadN-address\",[]],[\"invoke\",294,0,\"as-store-address\",[]],[\"invoke\",295,0,\"as-store-value\",[]],[\"invoke\",296,0,\"as-storeN-address\",[]],[\"invoke\",297,0,\"as-storeN-value\",[]],[\"invoke\",299,0,\"as-unary-operand\",[]],[\"invoke\",301,0,\"as-binary-left\",[]],[\"invoke\",302,0,\"as-binary-right\",[]],[\"invoke\",304,0,\"as-test-operand\",[]],[\"invoke\",306,0,\"as-compare-left\",[]],[\"invoke\",307,0,\"as-compare-right\",[]],[\"invoke\",309,0,\"as-memory.grow-size\",[]],[\"module\",312,53,\"$Mgm\"],[\"register\",\"grown-memory\",\"$Mgm\"],[\"invoke\",317,\"$Mgm\",\"grow\",[]],[\"module\",318,54,\"$Mgim1\"],[\"register\",\"grown-imported-memory\",\"$Mgim1\"],[\"invoke\",324,\"$Mgim1\",\"grow\",[]],[\"module\",325,55,\"$Mgim2\"],[\"invoke\",330,\"$Mgim2\",\"size\",[]],[\"file\",\"memory_redundancy.wast\"],[\"module\",5,56],[\"invoke\",59,0,\"test_store_to_load\",[]],[\"invoke\",60,0,\"zero_everything\",[]],[\"invoke\",61,0,\"test_redundant_load\",[]],[\"invoke\",62,0,\"zero_everything\",[]],[\"invoke\",63,0,\"test_dead_store\",[]],[\"invoke\",64,0,\"zero_everything\",[]],[\"invoke\",65,0,\"malloc_aliasing\",[]],[\"file\",\"memory_size.wast\"],[\"module\",1,57],[\"invoke\",7,0,\"size\",[]],[\"invoke\",8,0,\"grow\",[\"i32:1\"]],[\"invoke\",9,0,\"size\",[]],[\"invoke\",10,0,\"grow\",[\"i32:4\"]],[\"invoke\",11,0,\"size\",[]],[\"invoke\",12,0,\"grow\",[\"i32:0\"]],[\"invoke\",13,0,\"size\",[]],[\"module\",15,58],[\"invoke\",21,0,\"size\",[]],[\"invoke\",22,0,\"grow\",[\"i32:1\"]],[\"invoke\",23,0,\"size\",[]],[\"invoke\",24,0,\"grow\",[\"i32:4\"]],[\"invoke\",25,0,\"size\",[]],[\"invoke\",26,0,\"grow\",[\"i32:0\"]],[\"invoke\",27,0,\"size\",[]],[\"module\",29,59],[\"invoke\",35,0,\"size\",[]],[\"invoke\",36,0,\"grow\",[\"i32:3\"]],[\"invoke\",37,0,\"size\",[]],[\"invoke\",38,0,\"grow\",[\"i32:1\"]],[\"invoke\",39,0,\"size\",[]],[\"invoke\",40,0,\"grow\",[\"i32:0\"]],[\"invoke\",41,0,\"size\",[]],[\"invoke\",42,0,\"grow\",[\"i32:4\"]],[\"invoke\",43,0,\"size\",[]],[\"invoke\",44,0,\"grow\",[\"i32:1\"]],[\"invoke\",45,0,\"size\",[]],[\"module\",47,60],[\"invoke\",53,0,\"size\",[]],[\"invoke\",54,0,\"grow\",[\"i32:1\"]],[\"invoke\",55,0,\"size\",[]],[\"invoke\",56,0,\"grow\",[\"i32:3\"]],[\"invoke\",57,0,\"size\",[]],[\"invoke\",58,0,\"grow\",[\"i32:0\"]],[\"invoke\",59,0,\"size\",[]],[\"invoke\",60,0,\"grow\",[\"i32:2\"]],[\"invoke\",61,0,\"size\",[]],[\"invoke\",62,0,\"grow\",[\"i32:1\"]],[\"invoke\",63,0,\"size\",[]],[\"file\",\"memory_trap.wast\"],[\"module\",1,61],[\"invoke\",21,0,\"store\",[\"i32:4294967292\",\"i32:42\"]],[\"invoke\",22,0,\"load\",[\"i32:4294967292\"]],[\"invoke\",23,0,\"store\",[\"i32:4294967293\",\"i32:305419896\"]],[\"invoke\",24,0,\"load\",[\"i32:4294967293\"]],[\"invoke\",25,0,\"store\",[\"i32:4294967294\",\"i32:13\"]],[\"invoke\",26,0,\"load\",[\"i32:4294967294\"]],[\"invoke\",27,0,\"store\",[\"i32:4294967295\",\"i32:13\"]],[\"invoke\",28,0,\"load\",[\"i32:4294967295\"]],[\"invoke\",29,0,\"store\",[\"i32:0\",\"i32:13\"]],[\"invoke\",30,0,\"load\",[\"i32:0\"]],[\"invoke\",31,0,\"store\",[\"i32:2147483648\",\"i32:13\"]],[\"invoke\",32,0,\"load\",[\"i32:2147483648\"]],[\"invoke\",33,0,\"memory.grow\",[\"i32:65537\"]],[\"module\",35,62],[\"invoke\",111,0,\"i32.store\",[\"i32:65536\",\"i32:0\"]],[\"invoke\",112,0,\"i32.store\",[\"i32:65535\",\"i32:0\"]],[\"invoke\",113,0,\"i32.store\",[\"i32:65534\",\"i32:0\"]],[\"invoke\",114,0,\"i32.store\",[\"i32:65533\",\"i32:0\"]],[\"invoke\",115,0,\"i32.store\",[\"i32:4294967295\",\"i32:0\"]],[\"invoke\",116,0,\"i32.store\",[\"i32:4294967294\",\"i32:0\"]],[\"invoke\",117,0,\"i32.store\",[\"i32:4294967293\",\"i32:0\"]],[\"invoke\",118,0,\"i32.store\",[\"i32:4294967292\",\"i32:0\"]],[\"invoke\",119,0,\"i64.store\",[\"i32:65536\",\"i64:0\"]],[\"invoke\",120,0,\"i64.store\",[\"i32:65535\",\"i64:0\"]],[\"invoke\",121,0,\"i64.store\",[\"i32:65534\",\"i64:0\"]],[\"invoke\",122,0,\"i64.store\",[\"i32:65533\",\"i64:0\"]],[\"invoke\",123,0,\"i64.store\",[\"i32:65532\",\"i64:0\"]],[\"invoke\",124,0,\"i64.store\",[\"i32:65531\",\"i64:0\"]],[\"invoke\",125,0,\"i64.store\",[\"i32:65530\",\"i64:0\"]],[\"invoke\",126,0,\"i64.store\",[\"i32:65529\",\"i64:0\"]],[\"invoke\",127,0,\"i64.store\",[\"i32:4294967295\",\"i64:0\"]],[\"invoke\",128,0,\"i64.store\",[\"i32:4294967294\",\"i64:0\"]],[\"invoke\",129,0,\"i64.store\",[\"i32:4294967293\",\"i64:0\"]],[\"invoke\",130,0,\"i64.store\",[\"i32:4294967292\",\"i64:0\"]],[\"invoke\",131,0,\"i64.store\",[\"i32:4294967291\",\"i64:0\"]],[\"invoke\",132,0,\"i64.store\",[\"i32:4294967290\",\"i64:0\"]],[\"invoke\",133,0,\"i64.store\",[\"i32:4294967289\",\"i64:0\"]],[\"invoke\",134,0,\"i64.store\",[\"i32:4294967288\",\"i64:0\"]],[\"invoke\",135,0,\"f32.store\",[\"i32:65536\",\"f32:0\"]],[\"invoke\",136,0,\"f32.store\",[\"i32:65535\",\"f32:0\"]],[\"invoke\",137,0,\"f32.store\",[\"i32:65534\",\"f32:0\"]],[\"invoke\",138,0,\"f32.store\",[\"i32:65533\",\"f32:0\"]],[\"invoke\",139,0,\"f32.store\",[\"i32:4294967295\",\"f32:0\"]],[\"invoke\",140,0,\"f32.store\",[\"i32:4294967294\",\"f32:0\"]],[\"invoke\",141,0,\"f32.store\",[\"i32:4294967293\",\"f32:0\"]],[\"invoke\",142,0,\"f32.store\",[\"i32:4294967292\",\"f32:0\"]],[\"invoke\",143,0,\"f64.store\",[\"i32:65536\",\"f64:0\"]],[\"invoke\",144,0,\"f64.store\",[\"i32:65535\",\"f64:0\"]],[\"invoke\",145,0,\"f64.store\",[\"i32:65534\",\"f64:0\"]],[\"invoke\",146,0,\"f64.store\",[\"i32:65533\",\"f64:0\"]],[\"invoke\",147,0,\"f64.store\",[\"i32:65532\",\"f64:0\"]],[\"invoke\",148,0,\"f64.store\",[\"i32:65531\",\"f64:0\"]],[\"invoke\",149,0,\"f64.store\",[\"i32:65530\",\"f64:0\"]],[\"invoke\",150,0,\"f64.store\",[\"i32:65529\",\"f64:0\"]],[\"invoke\",151,0,\"f64.store\",[\"i32:4294967295\",\"f64:0\"]],[\"invoke\",152,0,\"f64.store\",[\"i32:4294967294\",\"f64:0\"]],[\"invoke\",153,0,\"f64.store\",[\"i32:4294967293\",\"f64:0\"]],[\"invoke\",154,0,\"f64.store\",[\"i32:4294967292\",\"f64:0\"]],[\"invoke\",155,0,\"f64.store\",[\"i32:4294967291\",\"f64:0\"]],[\"invoke\",156,0,\"f64.store\",[\"i32:4294967290\",\"f64:0\"]],[\"invoke\",157,0,\"f64.store\",[\"i32:4294967289\",\"f64:0\"]],[\"invoke\",158,0,\"f64.store\",[\"i32:4294967288\",\"f64:0\"]],[\"invoke\",159,0,\"i32.store8\",[\"i32:65536\",\"i32:0\"]],[\"invoke\",160,0,\"i32.store8\",[\"i32:4294967295\",\"i32:0\"]],[\"invoke\",161,0,\"i32.store16\",[\"i32:65536\",\"i32:0\"]],[\"invoke\",162,0,\"i32.store16\",[\"i32:65535\",\"i32:0\"]],[\"invoke\",163,0,\"i32.store16\",[\"i32:4294967295\",\"i32:0\"]],[\"invoke\",164,0,\"i32.store16\",[\"i32:4294967294\",\"i32:0\"]],[\"invoke\",165,0,\"i64.store8\",[\"i32:65536\",\"i64:0\"]],[\"invoke\",166,0,\"i64.store8\",[\"i32:4294967295\",\"i64:0\"]],[\"invoke\",167,0,\"i64.store16\",[\"i32:65536\",\"i64:0\"]],[\"invoke\",168,0,\"i64.store16\",[\"i32:65535\",\"i64:0\"]],[\"invoke\",169,0,\"i64.store16\",[\"i32:4294967295\",\"i64:0\"]],[\"invoke\",170,0,\"i64.store16\",[\"i32:4294967294\",\"i64:0\"]],[\"invoke\",171,0,\"i64.store32\",[\"i32:65536\",\"i64:0\"]],[\"invoke\",172,0,\"i64.store32\",[\"i32:65535\",\"i64:0\"]],[\"invoke\",173,0,\"i64.store32\",[\"i32:65534\",\"i64:0\"]],[\"invoke\",174,0,\"i64.store32\",[\"i32:65533\",\"i64:0\"]],[\"invoke\",175,0,\"i64.store32\",[\"i32:4294967295\",\"i64:0\"]],[\"invoke\",176,0,\"i64.store32\",[\"i32:4294967294\",\"i64:0\"]],[\"invoke\",177,0,\"i64.store32\",[\"i32:4294967293\",\"i64:0\"]],[\"invoke\",178,0,\"i64.store32\",[\"i32:4294967292\",\"i64:0\"]],[\"invoke\",179,0,\"i32.load\",[\"i32:65536\"]],[\"invoke\",180,0,\"i32.load\",[\"i32:65535\"]],[\"invoke\",181,0,\"i32.load\",[\"i32:65534\"]],[\"invoke\",182,0,\"i32.load\",[\"i32:65533\"]],[\"invoke\",183,0,\"i32.load\",[\"i32:4294967295\"]],[\"invoke\",184,0,\"i32.load\",[\"i32:4294967294\"]],[\"invoke\",185,0,\"i32.load\",[\"i32:4294967293\"]],[\"invoke\",186,0,\"i32.load\",[\"i32:4294967292\"]],[\"invoke\",187,0,\"i64.load\",[\"i32:65536\"]],[\"invoke\",188,0,\"i64.load\",[\"i32:65535\"]],[\"invoke\",189,0,\"i64.load\",[\"i32:65534\"]],[\"invoke\",190,0,\"i64.load\",[\"i32:65533\"]],[\"invoke\",191,0,\"i64.load\",[\"i32:65532\"]],[\"invoke\",192,0,\"i64.load\",[\"i32:65531\"]],[\"invoke\",193,0,\"i64.load\",[\"i32:65530\"]],[\"invoke\",194,0,\"i64.load\",[\"i32:65529\"]],[\"invoke\",195,0,\"i64.load\",[\"i32:4294967295\"]],[\"invoke\",196,0,\"i64.load\",[\"i32:4294967294\"]],[\"invoke\",197,0,\"i64.load\",[\"i32:4294967293\"]],[\"invoke\",198,0,\"i64.load\",[\"i32:4294967292\"]],[\"invoke\",199,0,\"i64.load\",[\"i32:4294967291\"]],[\"invoke\",200,0,\"i64.load\",[\"i32:4294967290\"]],[\"invoke\",201,0,\"i64.load\",[\"i32:4294967289\"]],[\"invoke\",202,0,\"i64.load\",[\"i32:4294967288\"]],[\"invoke\",203,0,\"f32.load\",[\"i32:65536\"]],[\"invoke\",204,0,\"f32.load\",[\"i32:65535\"]],[\"invoke\",205,0,\"f32.load\",[\"i32:65534\"]],[\"invoke\",206,0,\"f32.load\",[\"i32:65533\"]],[\"invoke\",207,0,\"f32.load\",[\"i32:4294967295\"]],[\"invoke\",208,0,\"f32.load\",[\"i32:4294967294\"]],[\"invoke\",209,0,\"f32.load\",[\"i32:4294967293\"]],[\"invoke\",210,0,\"f32.load\",[\"i32:4294967292\"]],[\"invoke\",211,0,\"f64.load\",[\"i32:65536\"]],[\"invoke\",212,0,\"f64.load\",[\"i32:65535\"]],[\"invoke\",213,0,\"f64.load\",[\"i32:65534\"]],[\"invoke\",214,0,\"f64.load\",[\"i32:65533\"]],[\"invoke\",215,0,\"f64.load\",[\"i32:65532\"]],[\"invoke\",216,0,\"f64.load\",[\"i32:65531\"]],[\"invoke\",217,0,\"f64.load\",[\"i32:65530\"]],[\"invoke\",218,0,\"f64.load\",[\"i32:65529\"]],[\"invoke\",219,0,\"f64.load\",[\"i32:4294967295\"]],[\"invoke\",220,0,\"f64.load\",[\"i32:4294967294\"]],[\"invoke\",221,0,\"f64.load\",[\"i32:4294967293\"]],[\"invoke\",222,0,\"f64.load\",[\"i32:4294967292\"]],[\"invoke\",223,0,\"f64.load\",[\"i32:4294967291\"]],[\"invoke\",224,0,\"f64.load\",[\"i32:4294967290\"]],[\"invoke\",225,0,\"f64.load\",[\"i32:4294967289\"]],[\"invoke\",226,0,\"f64.load\",[\"i32:4294967288\"]],[\"invoke\",227,0,\"i32.load8_s\",[\"i32:65536\"]],[\"invoke\",228,0,\"i32.load8_s\",[\"i32:4294967295\"]],[\"invoke\",229,0,\"i32.load8_u\",[\"i32:65536\"]],[\"invoke\",230,0,\"i32.load8_u\",[\"i32:4294967295\"]],[\"invoke\",231,0,\"i32.load16_s\",[\"i32:65536\"]],[\"invoke\",232,0,\"i32.load16_s\",[\"i32:65535\"]],[\"invoke\",233,0,\"i32.load16_s\",[\"i32:4294967295\"]],[\"invoke\",234,0,\"i32.load16_s\",[\"i32:4294967294\"]],[\"invoke\",235,0,\"i32.load16_u\",[\"i32:65536\"]],[\"invoke\",236,0,\"i32.load16_u\",[\"i32:65535\"]],[\"invoke\",237,0,\"i32.load16_u\",[\"i32:4294967295\"]],[\"invoke\",238,0,\"i32.load16_u\",[\"i32:4294967294\"]],[\"invoke\",239,0,\"i64.load8_s\",[\"i32:65536\"]],[\"invoke\",240,0,\"i64.load8_s\",[\"i32:4294967295\"]],[\"invoke\",241,0,\"i64.load8_u\",[\"i32:65536\"]],[\"invoke\",242,0,\"i64.load8_u\",[\"i32:4294967295\"]],[\"invoke\",243,0,\"i64.load16_s\",[\"i32:65536\"]],[\"invoke\",244,0,\"i64.load16_s\",[\"i32:65535\"]],[\"invoke\",245,0,\"i64.load16_s\",[\"i32:4294967295\"]],[\"invoke\",246,0,\"i64.load16_s\",[\"i32:4294967294\"]],[\"invoke\",247,0,\"i64.load16_u\",[\"i32:65536\"]],[\"invoke\",248,0,\"i64.load16_u\",[\"i32:65535\"]],[\"invoke\",249,0,\"i64.load16_u\",[\"i32:4294967295\"]],[\"invoke\",250,0,\"i64.load16_u\",[\"i32:4294967294\"]],[\"invoke\",251,0,\"i64.load32_s\",[\"i32:65536\"]],[\"invoke\",252,0,\"i64.load32_s\",[\"i32:65535\"]],[\"invoke\",253,0,\"i64.load32_s\",[\"i32:65534\"]],[\"invoke\",254,0,\"i64.load32_s\",[\"i32:65533\"]],[\"invoke\",255,0,\"i64.load32_s\",[\"i32:4294967295\"]],[\"invoke\",256,0,\"i64.load32_s\",[\"i32:4294967294\"]],[\"invoke\",257,0,\"i64.load32_s\",[\"i32:4294967293\"]],[\"invoke\",258,0,\"i64.load32_s\",[\"i32:4294967292\"]],[\"invoke\",259,0,\"i64.load32_u\",[\"i32:65536\"]],[\"invoke\",260,0,\"i64.load32_u\",[\"i32:65535\"]],[\"invoke\",261,0,\"i64.load32_u\",[\"i32:65534\"]],[\"invoke\",262,0,\"i64.load32_u\",[\"i32:65533\"]],[\"invoke\",263,0,\"i64.load32_u\",[\"i32:4294967295\"]],[\"invoke\",264,0,\"i64.load32_u\",[\"i32:4294967294\"]],[\"invoke\",265,0,\"i64.load32_u\",[\"i32:4294967293\"]],[\"invoke\",266,0,\"i64.load32_u\",[\"i32:4294967292\"]],[\"invoke\",269,0,\"i64.load\",[\"i32:65528\"]],[\"invoke\",270,0,\"i64.load\",[\"i32:0\"]],[\"invoke\",274,0,\"i64.store\",[\"i32:65528\",\"i64:0\"]],[\"invoke\",275,0,\"i32.store\",[\"i32:65533\",\"i32:305419896\"]],[\"invoke\",276,0,\"i32.load\",[\"i32:65532\"]],[\"invoke\",277,0,\"i64.store\",[\"i32:65529\",\"i64:1311768467294899695\"]],[\"invoke\",278,0,\"i64.load\",[\"i32:65528\"]],[\"invoke\",279,0,\"f32.store\",[\"i32:65533\",\"f32:1301390004\"]],[\"invoke\",280,0,\"f32.load\",[\"i32:65532\"]],[\"invoke\",281,0,\"f64.store\",[\"i32:65529\",\"f64:4878018892390247374\"]],[\"invoke\",282,0,\"f64.load\",[\"i32:65528\"]],[\"file\",\"bulk.wast\"],[\"module\",2,63],[\"module\",6,64],[\"module\",13,65],[\"invoke\",27,0,\"fill\",[\"i32:1\",\"i32:255\",\"i32:3\"]],[\"invoke\",28,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",29,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",30,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",31,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",32,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",35,0,\"fill\",[\"i32:0\",\"i32:48042\",\"i32:2\"]],[\"invoke\",36,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",37,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",40,0,\"fill\",[\"i32:0\",\"i32:0\",\"i32:65536\"]],[\"invoke\",43,0,\"fill\",[\"i32:65280\",\"i32:1\",\"i32:257\"]],[\"invoke\",45,0,\"load8_u\",[\"i32:65280\"]],[\"invoke\",46,0,\"load8_u\",[\"i32:65535\"]],[\"invoke\",49,0,\"fill\",[\"i32:65536\",\"i32:0\",\"i32:0\"]],[\"invoke\",52,0,\"fill\",[\"i32:65537\",\"i32:0\",\"i32:0\"]],[\"module\",57,66],[\"invoke\",71,0,\"copy\",[\"i32:10\",\"i32:0\",\"i32:4\"]],[\"invoke\",73,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",74,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",75,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",76,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",77,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",78,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",81,0,\"copy\",[\"i32:8\",\"i32:10\",\"i32:4\"]],[\"invoke\",82,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",83,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",84,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",85,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",86,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",87,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",90,0,\"copy\",[\"i32:10\",\"i32:7\",\"i32:6\"]],[\"invoke\",91,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",92,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",93,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",94,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",95,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",96,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",97,0,\"load8_u\",[\"i32:16\"]],[\"invoke\",100,0,\"copy\",[\"i32:65280\",\"i32:0\",\"i32:256\"]],[\"invoke\",101,0,\"copy\",[\"i32:65024\",\"i32:65280\",\"i32:256\"]],[\"invoke\",104,0,\"copy\",[\"i32:65536\",\"i32:0\",\"i32:0\"]],[\"invoke\",105,0,\"copy\",[\"i32:0\",\"i32:65536\",\"i32:0\"]],[\"invoke\",108,0,\"copy\",[\"i32:65537\",\"i32:0\",\"i32:0\"]],[\"invoke\",110,0,\"copy\",[\"i32:0\",\"i32:65537\",\"i32:0\"]],[\"module\",115,67],[\"invoke\",129,0,\"init\",[\"i32:0\",\"i32:1\",\"i32:2\"]],[\"invoke\",130,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",131,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",132,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",135,0,\"init\",[\"i32:65532\",\"i32:0\",\"i32:4\"]],[\"invoke\",138,0,\"init\",[\"i32:65534\",\"i32:0\",\"i32:3\"]],[\"invoke\",140,0,\"load8_u\",[\"i32:65534\"]],[\"invoke\",141,0,\"load8_u\",[\"i32:65535\"]],[\"invoke\",144,0,\"init\",[\"i32:65536\",\"i32:0\",\"i32:0\"]],[\"invoke\",145,0,\"init\",[\"i32:0\",\"i32:4\",\"i32:0\"]],[\"invoke\",148,0,\"init\",[\"i32:65537\",\"i32:0\",\"i32:0\"]],[\"invoke\",150,0,\"init\",[\"i32:0\",\"i32:5\",\"i32:0\"]],[\"module\",154,68],[\"invoke\",168,0,\"init_passive\",[\"i32:1\"]],[\"invoke\",169,0,\"drop_passive\",[]],[\"invoke\",170,0,\"drop_passive\",[]],[\"invoke\",171,0,\"init_passive\",[\"i32:0\"]],[\"invoke\",172,0,\"init_passive\",[\"i32:1\"]],[\"invoke\",173,0,\"init_passive\",[\"i32:0\"]],[\"invoke\",174,0,\"drop_active\",[]],[\"invoke\",175,0,\"init_active\",[\"i32:0\"]],[\"invoke\",176,0,\"init_active\",[\"i32:1\"]],[\"invoke\",177,0,\"init_active\",[\"i32:0\"]],[\"module\",181,69],[\"module\",196,70],[\"module\",199,71],[\"invoke\",219,0,\"init\",[\"i32:2\",\"i32:0\",\"i32:2\"]],[\"invoke\",221,0,\"call\",[\"i32:2\"]],[\"invoke\",224,0,\"init\",[\"i32:0\",\"i32:1\",\"i32:2\"]],[\"invoke\",225,0,\"call\",[\"i32:0\"]],[\"invoke\",226,0,\"call\",[\"i32:1\"]],[\"invoke\",227,0,\"call\",[\"i32:2\"]],[\"invoke\",230,0,\"init\",[\"i32:1\",\"i32:2\",\"i32:2\"]],[\"invoke\",233,0,\"init\",[\"i32:3\",\"i32:0\",\"i32:0\"]],[\"invoke\",234,0,\"init\",[\"i32:0\",\"i32:4\",\"i32:0\"]],[\"invoke\",237,0,\"init\",[\"i32:4\",\"i32:0\",\"i32:0\"]],[\"invoke\",239,0,\"init\",[\"i32:0\",\"i32:5\",\"i32:0\"]],[\"module\",244,72],[\"invoke\",261,0,\"init_passive\",[\"i32:1\"]],[\"invoke\",262,0,\"drop_passive\",[]],[\"invoke\",263,0,\"drop_passive\",[]],[\"invoke\",264,0,\"init_passive\",[\"i32:0\"]],[\"invoke\",265,0,\"init_passive\",[\"i32:1\"]],[\"invoke\",266,0,\"init_passive\",[\"i32:0\"]],[\"invoke\",267,0,\"drop_active\",[]],[\"invoke\",268,0,\"init_active\",[\"i32:0\"]],[\"invoke\",269,0,\"init_active\",[\"i32:1\"]],[\"invoke\",270,0,\"init_active\",[\"i32:0\"]],[\"module\",274,73],[\"module\",297,74],[\"module\",300,75],[\"invoke\",319,0,\"copy\",[\"i32:3\",\"i32:0\",\"i32:3\"]],[\"invoke\",321,0,\"call\",[\"i32:3\"]],[\"invoke\",322,0,\"call\",[\"i32:4\"]],[\"invoke\",323,0,\"call\",[\"i32:5\"]],[\"invoke\",326,0,\"copy\",[\"i32:0\",\"i32:1\",\"i32:3\"]],[\"invoke\",328,0,\"call\",[\"i32:0\"]],[\"invoke\",329,0,\"call\",[\"i32:1\"]],[\"invoke\",330,0,\"call\",[\"i32:2\"]],[\"invoke\",333,0,\"copy\",[\"i32:2\",\"i32:0\",\"i32:3\"]],[\"invoke\",335,0,\"call\",[\"i32:2\"]],[\"invoke\",336,0,\"call\",[\"i32:3\"]],[\"invoke\",337,0,\"call\",[\"i32:4\"]],[\"invoke\",340,0,\"copy\",[\"i32:6\",\"i32:8\",\"i32:2\"]],[\"invoke\",341,0,\"copy\",[\"i32:8\",\"i32:6\",\"i32:2\"]],[\"invoke\",344,0,\"copy\",[\"i32:10\",\"i32:0\",\"i32:0\"]],[\"invoke\",345,0,\"copy\",[\"i32:0\",\"i32:10\",\"i32:0\"]],[\"invoke\",348,0,\"copy\",[\"i32:11\",\"i32:0\",\"i32:0\"]],[\"invoke\",350,0,\"copy\",[\"i32:0\",\"i32:11\",\"i32:0\"]],[\"file\",\"memory_copy.wast\"],[\"module\",6,76],[\"invoke\",15,0,\"test\",[]],[\"invoke\",27,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",38,0,\"load8_u\",[\"i32:21\"]],[\"module\",48,77],[\"invoke\",60,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",71,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",82,0,\"load8_u\",[\"i32:23\"]],[\"module\",90,78],[\"invoke\",104,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",115,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",126,0,\"load8_u\",[\"i32:25\"]],[\"module\",132,79],[\"invoke\",147,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",158,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",169,0,\"load8_u\",[\"i32:26\"]],[\"module\",174,80],[\"invoke\",191,0,\"load8_u\",[\"i32:6\"]],[\"invoke\",202,0,\"load8_u\",[\"i32:17\"]],[\"invoke\",213,0,\"load8_u\",[\"i32:28\"]],[\"module\",216,81],[\"invoke\",235,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",246,0,\"load8_u\",[\"i32:19\"]],[\"module\",258,82],[\"invoke\",267,0,\"test\",[]],[\"invoke\",278,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",289,0,\"load8_u\",[\"i32:20\"]],[\"module\",300,83],[\"invoke\",311,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",322,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",333,0,\"load8_u\",[\"i32:22\"]],[\"module\",342,84],[\"invoke\",355,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",366,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",377,0,\"load8_u\",[\"i32:1014\"]],[\"invoke\",387,0,\"load8_u\",[\"i32:3004\"]],[\"invoke\",398,0,\"load8_u\",[\"i32:5193\"]],[\"invoke\",409,0,\"load8_u\",[\"i32:7382\"]],[\"invoke\",420,0,\"load8_u\",[\"i32:9571\"]],[\"invoke\",431,0,\"load8_u\",[\"i32:11760\"]],[\"invoke\",442,0,\"load8_u\",[\"i32:13949\"]],[\"invoke\",453,0,\"load8_u\",[\"i32:16138\"]],[\"invoke\",464,0,\"load8_u\",[\"i32:18327\"]],[\"invoke\",475,0,\"load8_u\",[\"i32:20516\"]],[\"invoke\",485,0,\"load8_u\",[\"i32:22506\"]],[\"invoke\",496,0,\"load8_u\",[\"i32:24695\"]],[\"invoke\",507,0,\"load8_u\",[\"i32:26884\"]],[\"invoke\",518,0,\"load8_u\",[\"i32:29073\"]],[\"invoke\",529,0,\"load8_u\",[\"i32:31262\"]],[\"invoke\",540,0,\"load8_u\",[\"i32:33451\"]],[\"invoke\",551,0,\"load8_u\",[\"i32:35640\"]],[\"invoke\",562,0,\"load8_u\",[\"i32:37829\"]],[\"invoke\",572,0,\"load8_u\",[\"i32:39819\"]],[\"invoke\",583,0,\"load8_u\",[\"i32:42008\"]],[\"invoke\",594,0,\"load8_u\",[\"i32:44197\"]],[\"invoke\",605,0,\"load8_u\",[\"i32:46386\"]],[\"invoke\",616,0,\"load8_u\",[\"i32:48575\"]],[\"invoke\",627,0,\"load8_u\",[\"i32:50764\"]],[\"invoke\",638,0,\"load8_u\",[\"i32:52953\"]],[\"invoke\",649,0,\"load8_u\",[\"i32:55142\"]],[\"invoke\",660,0,\"load8_u\",[\"i32:57331\"]],[\"invoke\",670,0,\"load8_u\",[\"i32:59321\"]],[\"invoke\",681,0,\"load8_u\",[\"i32:61510\"]],[\"invoke\",692,0,\"load8_u\",[\"i32:63699\"]],[\"module\",703,85],[\"invoke\",714,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",725,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",736,0,\"load8_u\",[\"i32:418\"]],[\"invoke\",747,0,\"load8_u\",[\"i32:2607\"]],[\"invoke\",758,0,\"load8_u\",[\"i32:4796\"]],[\"invoke\",768,0,\"load8_u\",[\"i32:6786\"]],[\"invoke\",779,0,\"load8_u\",[\"i32:8975\"]],[\"invoke\",790,0,\"load8_u\",[\"i32:11164\"]],[\"invoke\",801,0,\"load8_u\",[\"i32:13353\"]],[\"invoke\",812,0,\"load8_u\",[\"i32:15542\"]],[\"invoke\",823,0,\"load8_u\",[\"i32:17731\"]],[\"invoke\",834,0,\"load8_u\",[\"i32:19920\"]],[\"invoke\",845,0,\"load8_u\",[\"i32:22109\"]],[\"invoke\",856,0,\"load8_u\",[\"i32:24298\"]],[\"invoke\",866,0,\"load8_u\",[\"i32:26288\"]],[\"invoke\",877,0,\"load8_u\",[\"i32:28477\"]],[\"invoke\",888,0,\"load8_u\",[\"i32:30666\"]],[\"invoke\",899,0,\"load8_u\",[\"i32:32855\"]],[\"invoke\",910,0,\"load8_u\",[\"i32:35044\"]],[\"invoke\",921,0,\"load8_u\",[\"i32:37233\"]],[\"invoke\",932,0,\"load8_u\",[\"i32:39422\"]],[\"invoke\",943,0,\"load8_u\",[\"i32:41611\"]],[\"invoke\",953,0,\"load8_u\",[\"i32:43601\"]],[\"invoke\",964,0,\"load8_u\",[\"i32:45790\"]],[\"invoke\",975,0,\"load8_u\",[\"i32:47979\"]],[\"invoke\",986,0,\"load8_u\",[\"i32:50168\"]],[\"invoke\",997,0,\"load8_u\",[\"i32:52357\"]],[\"invoke\",1008,0,\"load8_u\",[\"i32:54546\"]],[\"invoke\",1019,0,\"load8_u\",[\"i32:56735\"]],[\"invoke\",1030,0,\"load8_u\",[\"i32:58924\"]],[\"invoke\",1041,0,\"load8_u\",[\"i32:61113\"]],[\"invoke\",1051,0,\"load8_u\",[\"i32:63103\"]],[\"invoke\",1062,0,\"load8_u\",[\"i32:65292\"]],[\"module\",1065,86],[\"invoke\",1084,0,\"load8_u\",[\"i32:1790\"]],[\"invoke\",1095,0,\"load8_u\",[\"i32:3979\"]],[\"invoke\",1106,0,\"load8_u\",[\"i32:6168\"]],[\"invoke\",1117,0,\"load8_u\",[\"i32:8357\"]],[\"invoke\",1128,0,\"load8_u\",[\"i32:10546\"]],[\"invoke\",1139,0,\"load8_u\",[\"i32:12735\"]],[\"invoke\",1149,0,\"load8_u\",[\"i32:14725\"]],[\"invoke\",1160,0,\"load8_u\",[\"i32:16914\"]],[\"invoke\",1171,0,\"load8_u\",[\"i32:19103\"]],[\"invoke\",1182,0,\"load8_u\",[\"i32:21292\"]],[\"invoke\",1193,0,\"load8_u\",[\"i32:23481\"]],[\"invoke\",1204,0,\"load8_u\",[\"i32:25670\"]],[\"invoke\",1215,0,\"load8_u\",[\"i32:27859\"]],[\"invoke\",1226,0,\"load8_u\",[\"i32:30048\"]],[\"invoke\",1237,0,\"load8_u\",[\"i32:32237\"]],[\"invoke\",1247,0,\"load8_u\",[\"i32:34227\"]],[\"invoke\",1258,0,\"load8_u\",[\"i32:36416\"]],[\"invoke\",1269,0,\"load8_u\",[\"i32:38605\"]],[\"invoke\",1280,0,\"load8_u\",[\"i32:40794\"]],[\"invoke\",1291,0,\"load8_u\",[\"i32:42983\"]],[\"invoke\",1302,0,\"load8_u\",[\"i32:45172\"]],[\"invoke\",1313,0,\"load8_u\",[\"i32:47361\"]],[\"invoke\",1324,0,\"load8_u\",[\"i32:49550\"]],[\"invoke\",1334,0,\"load8_u\",[\"i32:51540\"]],[\"invoke\",1345,0,\"load8_u\",[\"i32:53729\"]],[\"invoke\",1356,0,\"load8_u\",[\"i32:55918\"]],[\"invoke\",1367,0,\"load8_u\",[\"i32:58107\"]],[\"invoke\",1378,0,\"load8_u\",[\"i32:60296\"]],[\"invoke\",1389,0,\"load8_u\",[\"i32:62485\"]],[\"invoke\",1400,0,\"load8_u\",[\"i32:64674\"]],[\"invoke\",1411,0,\"load8_u\",[\"i32:65522\"]],[\"invoke\",1422,0,\"load8_u\",[\"i32:65533\"]],[\"module\",1426,87],[\"invoke\",1443,0,\"load8_u\",[\"i32:1392\"]],[\"invoke\",1454,0,\"load8_u\",[\"i32:3581\"]],[\"invoke\",1465,0,\"load8_u\",[\"i32:5770\"]],[\"invoke\",1476,0,\"load8_u\",[\"i32:7959\"]],[\"invoke\",1487,0,\"load8_u\",[\"i32:10148\"]],[\"invoke\",1498,0,\"load8_u\",[\"i32:12337\"]],[\"invoke\",1509,0,\"load8_u\",[\"i32:14526\"]],[\"invoke\",1520,0,\"load8_u\",[\"i32:16715\"]],[\"invoke\",1530,0,\"load8_u\",[\"i32:18705\"]],[\"invoke\",1541,0,\"load8_u\",[\"i32:20894\"]],[\"invoke\",1552,0,\"load8_u\",[\"i32:23083\"]],[\"invoke\",1563,0,\"load8_u\",[\"i32:25272\"]],[\"invoke\",1574,0,\"load8_u\",[\"i32:27461\"]],[\"invoke\",1585,0,\"load8_u\",[\"i32:29650\"]],[\"invoke\",1596,0,\"load8_u\",[\"i32:31839\"]],[\"invoke\",1607,0,\"load8_u\",[\"i32:34028\"]],[\"invoke\",1618,0,\"load8_u\",[\"i32:36217\"]],[\"invoke\",1628,0,\"load8_u\",[\"i32:38207\"]],[\"invoke\",1639,0,\"load8_u\",[\"i32:40396\"]],[\"invoke\",1650,0,\"load8_u\",[\"i32:42585\"]],[\"invoke\",1661,0,\"load8_u\",[\"i32:44774\"]],[\"invoke\",1672,0,\"load8_u\",[\"i32:46963\"]],[\"invoke\",1683,0,\"load8_u\",[\"i32:49152\"]],[\"invoke\",1694,0,\"load8_u\",[\"i32:51341\"]],[\"invoke\",1705,0,\"load8_u\",[\"i32:53530\"]],[\"invoke\",1715,0,\"load8_u\",[\"i32:55520\"]],[\"invoke\",1726,0,\"load8_u\",[\"i32:57709\"]],[\"invoke\",1737,0,\"load8_u\",[\"i32:59898\"]],[\"invoke\",1748,0,\"load8_u\",[\"i32:62087\"]],[\"invoke\",1759,0,\"load8_u\",[\"i32:64276\"]],[\"invoke\",1770,0,\"load8_u\",[\"i32:65519\"]],[\"invoke\",1781,0,\"load8_u\",[\"i32:65530\"]],[\"module\",1788,88],[\"invoke\",1803,0,\"load8_u\",[\"i32:994\"]],[\"invoke\",1814,0,\"load8_u\",[\"i32:3183\"]],[\"invoke\",1824,0,\"load8_u\",[\"i32:5173\"]],[\"invoke\",1835,0,\"load8_u\",[\"i32:7362\"]],[\"invoke\",1846,0,\"load8_u\",[\"i32:9551\"]],[\"invoke\",1857,0,\"load8_u\",[\"i32:11740\"]],[\"invoke\",1868,0,\"load8_u\",[\"i32:13929\"]],[\"invoke\",1879,0,\"load8_u\",[\"i32:16118\"]],[\"invoke\",1890,0,\"load8_u\",[\"i32:18307\"]],[\"invoke\",1901,0,\"load8_u\",[\"i32:20496\"]],[\"invoke\",1911,0,\"load8_u\",[\"i32:22486\"]],[\"invoke\",1922,0,\"load8_u\",[\"i32:24675\"]],[\"invoke\",1933,0,\"load8_u\",[\"i32:26864\"]],[\"invoke\",1944,0,\"load8_u\",[\"i32:29053\"]],[\"invoke\",1955,0,\"load8_u\",[\"i32:31242\"]],[\"invoke\",1966,0,\"load8_u\",[\"i32:33431\"]],[\"invoke\",1977,0,\"load8_u\",[\"i32:35620\"]],[\"invoke\",1988,0,\"load8_u\",[\"i32:37809\"]],[\"invoke\",1999,0,\"load8_u\",[\"i32:39998\"]],[\"invoke\",2009,0,\"load8_u\",[\"i32:41988\"]],[\"invoke\",2020,0,\"load8_u\",[\"i32:44177\"]],[\"invoke\",2031,0,\"load8_u\",[\"i32:46366\"]],[\"invoke\",2042,0,\"load8_u\",[\"i32:48555\"]],[\"invoke\",2053,0,\"load8_u\",[\"i32:50744\"]],[\"invoke\",2064,0,\"load8_u\",[\"i32:52933\"]],[\"invoke\",2075,0,\"load8_u\",[\"i32:55122\"]],[\"invoke\",2086,0,\"load8_u\",[\"i32:57311\"]],[\"invoke\",2096,0,\"load8_u\",[\"i32:59301\"]],[\"invoke\",2107,0,\"load8_u\",[\"i32:61490\"]],[\"invoke\",2118,0,\"load8_u\",[\"i32:63679\"]],[\"invoke\",2129,0,\"load8_u\",[\"i32:65487\"]],[\"invoke\",2140,0,\"load8_u\",[\"i32:65498\"]],[\"module\",2149,86],[\"invoke\",2162,0,\"load8_u\",[\"i32:596\"]],[\"invoke\",2173,0,\"load8_u\",[\"i32:2785\"]],[\"invoke\",2184,0,\"load8_u\",[\"i32:4974\"]],[\"invoke\",2195,0,\"load8_u\",[\"i32:7163\"]],[\"invoke\",2205,0,\"load8_u\",[\"i32:9153\"]],[\"invoke\",2216,0,\"load8_u\",[\"i32:11342\"]],[\"invoke\",2227,0,\"load8_u\",[\"i32:13531\"]],[\"invoke\",2238,0,\"load8_u\",[\"i32:15720\"]],[\"invoke\",2249,0,\"load8_u\",[\"i32:17909\"]],[\"invoke\",2260,0,\"load8_u\",[\"i32:20098\"]],[\"invoke\",2271,0,\"load8_u\",[\"i32:22287\"]],[\"invoke\",2282,0,\"load8_u\",[\"i32:24476\"]],[\"invoke\",2292,0,\"load8_u\",[\"i32:26466\"]],[\"invoke\",2303,0,\"load8_u\",[\"i32:28655\"]],[\"invoke\",2314,0,\"load8_u\",[\"i32:30844\"]],[\"invoke\",2325,0,\"load8_u\",[\"i32:33033\"]],[\"invoke\",2336,0,\"load8_u\",[\"i32:35222\"]],[\"invoke\",2347,0,\"load8_u\",[\"i32:37411\"]],[\"invoke\",2358,0,\"load8_u\",[\"i32:39600\"]],[\"invoke\",2369,0,\"load8_u\",[\"i32:41789\"]],[\"invoke\",2380,0,\"load8_u\",[\"i32:43978\"]],[\"invoke\",2390,0,\"load8_u\",[\"i32:45968\"]],[\"invoke\",2401,0,\"load8_u\",[\"i32:48157\"]],[\"invoke\",2412,0,\"load8_u\",[\"i32:50346\"]],[\"invoke\",2423,0,\"load8_u\",[\"i32:52535\"]],[\"invoke\",2434,0,\"load8_u\",[\"i32:54724\"]],[\"invoke\",2445,0,\"load8_u\",[\"i32:56913\"]],[\"invoke\",2456,0,\"load8_u\",[\"i32:59102\"]],[\"invoke\",2467,0,\"load8_u\",[\"i32:61291\"]],[\"invoke\",2477,0,\"load8_u\",[\"i32:63281\"]],[\"invoke\",2488,0,\"load8_u\",[\"i32:65470\"]],[\"invoke\",2499,0,\"load8_u\",[\"i32:65526\"]],[\"module\",2510,89],[\"invoke\",2521,0,\"load8_u\",[\"i32:198\"]],[\"invoke\",2532,0,\"load8_u\",[\"i32:2387\"]],[\"invoke\",2543,0,\"load8_u\",[\"i32:4576\"]],[\"invoke\",2554,0,\"load8_u\",[\"i32:6765\"]],[\"invoke\",2565,0,\"load8_u\",[\"i32:8954\"]],[\"invoke\",2576,0,\"load8_u\",[\"i32:11143\"]],[\"invoke\",2586,0,\"load8_u\",[\"i32:13133\"]],[\"invoke\",2597,0,\"load8_u\",[\"i32:15322\"]],[\"invoke\",2608,0,\"load8_u\",[\"i32:17511\"]],[\"invoke\",2619,0,\"load8_u\",[\"i32:19700\"]],[\"invoke\",2630,0,\"load8_u\",[\"i32:21889\"]],[\"invoke\",2641,0,\"load8_u\",[\"i32:24078\"]],[\"invoke\",2652,0,\"load8_u\",[\"i32:26267\"]],[\"invoke\",2663,0,\"load8_u\",[\"i32:28456\"]],[\"invoke\",2673,0,\"load8_u\",[\"i32:30446\"]],[\"invoke\",2684,0,\"load8_u\",[\"i32:32635\"]],[\"invoke\",2695,0,\"load8_u\",[\"i32:34824\"]],[\"invoke\",2706,0,\"load8_u\",[\"i32:37013\"]],[\"invoke\",2717,0,\"load8_u\",[\"i32:39202\"]],[\"invoke\",2728,0,\"load8_u\",[\"i32:41391\"]],[\"invoke\",2739,0,\"load8_u\",[\"i32:43580\"]],[\"invoke\",2750,0,\"load8_u\",[\"i32:45769\"]],[\"invoke\",2761,0,\"load8_u\",[\"i32:47958\"]],[\"invoke\",2771,0,\"load8_u\",[\"i32:49948\"]],[\"invoke\",2782,0,\"load8_u\",[\"i32:52137\"]],[\"invoke\",2793,0,\"load8_u\",[\"i32:54326\"]],[\"invoke\",2804,0,\"load8_u\",[\"i32:56515\"]],[\"invoke\",2815,0,\"load8_u\",[\"i32:58704\"]],[\"invoke\",2826,0,\"load8_u\",[\"i32:60893\"]],[\"invoke\",2837,0,\"load8_u\",[\"i32:63082\"]],[\"invoke\",2848,0,\"load8_u\",[\"i32:65271\"]],[\"invoke\",2858,0,\"load8_u\",[\"i32:65514\"]],[\"invoke\",2869,0,\"load8_u\",[\"i32:65525\"]],[\"module\",2871,86],[\"invoke\",2891,0,\"load8_u\",[\"i32:1989\"]],[\"invoke\",2902,0,\"load8_u\",[\"i32:4178\"]],[\"invoke\",2913,0,\"load8_u\",[\"i32:6367\"]],[\"invoke\",2924,0,\"load8_u\",[\"i32:8556\"]],[\"invoke\",2935,0,\"load8_u\",[\"i32:10745\"]],[\"invoke\",2946,0,\"load8_u\",[\"i32:12934\"]],[\"invoke\",2957,0,\"load8_u\",[\"i32:15123\"]],[\"invoke\",2967,0,\"load8_u\",[\"i32:17113\"]],[\"invoke\",2978,0,\"load8_u\",[\"i32:19302\"]],[\"invoke\",2989,0,\"load8_u\",[\"i32:21491\"]],[\"invoke\",3000,0,\"load8_u\",[\"i32:23680\"]],[\"invoke\",3011,0,\"load8_u\",[\"i32:25869\"]],[\"invoke\",3022,0,\"load8_u\",[\"i32:28058\"]],[\"invoke\",3033,0,\"load8_u\",[\"i32:30247\"]],[\"invoke\",3044,0,\"load8_u\",[\"i32:32436\"]],[\"invoke\",3054,0,\"load8_u\",[\"i32:34426\"]],[\"invoke\",3065,0,\"load8_u\",[\"i32:36615\"]],[\"invoke\",3076,0,\"load8_u\",[\"i32:38804\"]],[\"invoke\",3087,0,\"load8_u\",[\"i32:40993\"]],[\"invoke\",3098,0,\"load8_u\",[\"i32:43182\"]],[\"invoke\",3109,0,\"load8_u\",[\"i32:45371\"]],[\"invoke\",3120,0,\"load8_u\",[\"i32:47560\"]],[\"invoke\",3131,0,\"load8_u\",[\"i32:49749\"]],[\"invoke\",3142,0,\"load8_u\",[\"i32:51938\"]],[\"invoke\",3152,0,\"load8_u\",[\"i32:53928\"]],[\"invoke\",3163,0,\"load8_u\",[\"i32:56117\"]],[\"invoke\",3174,0,\"load8_u\",[\"i32:58306\"]],[\"invoke\",3185,0,\"load8_u\",[\"i32:60495\"]],[\"invoke\",3196,0,\"load8_u\",[\"i32:62684\"]],[\"invoke\",3207,0,\"load8_u\",[\"i32:64873\"]],[\"invoke\",3218,0,\"load8_u\",[\"i32:65523\"]],[\"invoke\",3229,0,\"load8_u\",[\"i32:65534\"]],[\"module\",3232,86],[\"invoke\",3250,0,\"load8_u\",[\"i32:1591\"]],[\"invoke\",3261,0,\"load8_u\",[\"i32:3780\"]],[\"invoke\",3272,0,\"load8_u\",[\"i32:5969\"]],[\"invoke\",3283,0,\"load8_u\",[\"i32:8158\"]],[\"invoke\",3294,0,\"load8_u\",[\"i32:10347\"]],[\"invoke\",3305,0,\"load8_u\",[\"i32:12536\"]],[\"invoke\",3316,0,\"load8_u\",[\"i32:14725\"]],[\"invoke\",3327,0,\"load8_u\",[\"i32:16914\"]],[\"invoke\",3338,0,\"load8_u\",[\"i32:19103\"]],[\"invoke\",3348,0,\"load8_u\",[\"i32:21093\"]],[\"invoke\",3359,0,\"load8_u\",[\"i32:23282\"]],[\"invoke\",3370,0,\"load8_u\",[\"i32:25471\"]],[\"invoke\",3381,0,\"load8_u\",[\"i32:27660\"]],[\"invoke\",3392,0,\"load8_u\",[\"i32:29849\"]],[\"invoke\",3403,0,\"load8_u\",[\"i32:32038\"]],[\"invoke\",3414,0,\"load8_u\",[\"i32:34227\"]],[\"invoke\",3425,0,\"load8_u\",[\"i32:36416\"]],[\"invoke\",3435,0,\"load8_u\",[\"i32:38406\"]],[\"invoke\",3446,0,\"load8_u\",[\"i32:40595\"]],[\"invoke\",3457,0,\"load8_u\",[\"i32:42784\"]],[\"invoke\",3468,0,\"load8_u\",[\"i32:44973\"]],[\"invoke\",3479,0,\"load8_u\",[\"i32:47162\"]],[\"invoke\",3490,0,\"load8_u\",[\"i32:49351\"]],[\"invoke\",3501,0,\"load8_u\",[\"i32:51540\"]],[\"invoke\",3512,0,\"load8_u\",[\"i32:53729\"]],[\"invoke\",3523,0,\"load8_u\",[\"i32:55918\"]],[\"invoke\",3533,0,\"load8_u\",[\"i32:57908\"]],[\"invoke\",3544,0,\"load8_u\",[\"i32:60097\"]],[\"invoke\",3555,0,\"load8_u\",[\"i32:62286\"]],[\"invoke\",3566,0,\"load8_u\",[\"i32:64475\"]],[\"invoke\",3577,0,\"load8_u\",[\"i32:65521\"]],[\"invoke\",3588,0,\"load8_u\",[\"i32:65532\"]],[\"module\",3593,90],[\"invoke\",3610,0,\"load8_u\",[\"i32:1392\"]],[\"invoke\",3621,0,\"load8_u\",[\"i32:3581\"]],[\"invoke\",3631,0,\"load8_u\",[\"i32:5571\"]],[\"invoke\",3642,0,\"load8_u\",[\"i32:7760\"]],[\"invoke\",3653,0,\"load8_u\",[\"i32:9949\"]],[\"invoke\",3664,0,\"load8_u\",[\"i32:12138\"]],[\"invoke\",3675,0,\"load8_u\",[\"i32:14327\"]],[\"invoke\",3686,0,\"load8_u\",[\"i32:16516\"]],[\"invoke\",3697,0,\"load8_u\",[\"i32:18705\"]],[\"invoke\",3708,0,\"load8_u\",[\"i32:20894\"]],[\"invoke\",3719,0,\"load8_u\",[\"i32:23083\"]],[\"invoke\",3729,0,\"load8_u\",[\"i32:25073\"]],[\"invoke\",3740,0,\"load8_u\",[\"i32:27262\"]],[\"invoke\",3751,0,\"load8_u\",[\"i32:29451\"]],[\"invoke\",3762,0,\"load8_u\",[\"i32:31640\"]],[\"invoke\",3773,0,\"load8_u\",[\"i32:33829\"]],[\"invoke\",3784,0,\"load8_u\",[\"i32:36018\"]],[\"invoke\",3795,0,\"load8_u\",[\"i32:38207\"]],[\"invoke\",3806,0,\"load8_u\",[\"i32:40396\"]],[\"invoke\",3816,0,\"load8_u\",[\"i32:42386\"]],[\"invoke\",3827,0,\"load8_u\",[\"i32:44575\"]],[\"invoke\",3838,0,\"load8_u\",[\"i32:46764\"]],[\"invoke\",3849,0,\"load8_u\",[\"i32:48953\"]],[\"invoke\",3860,0,\"load8_u\",[\"i32:51142\"]],[\"invoke\",3871,0,\"load8_u\",[\"i32:53331\"]],[\"invoke\",3882,0,\"load8_u\",[\"i32:55520\"]],[\"invoke\",3893,0,\"load8_u\",[\"i32:57709\"]],[\"invoke\",3904,0,\"load8_u\",[\"i32:59898\"]],[\"invoke\",3914,0,\"load8_u\",[\"i32:61888\"]],[\"invoke\",3925,0,\"load8_u\",[\"i32:64077\"]],[\"invoke\",3936,0,\"load8_u\",[\"i32:65519\"]],[\"invoke\",3947,0,\"load8_u\",[\"i32:65530\"]],[\"module\",3954,91],[\"invoke\",3969,0,\"load8_u\",[\"i32:994\"]],[\"invoke\",3980,0,\"load8_u\",[\"i32:3183\"]],[\"invoke\",3991,0,\"load8_u\",[\"i32:5372\"]],[\"invoke\",4002,0,\"load8_u\",[\"i32:7561\"]],[\"invoke\",4012,0,\"load8_u\",[\"i32:9551\"]],[\"invoke\",4023,0,\"load8_u\",[\"i32:11740\"]],[\"invoke\",4034,0,\"load8_u\",[\"i32:13929\"]],[\"invoke\",4045,0,\"load8_u\",[\"i32:16118\"]],[\"invoke\",4056,0,\"load8_u\",[\"i32:18307\"]],[\"invoke\",4067,0,\"load8_u\",[\"i32:20496\"]],[\"invoke\",4078,0,\"load8_u\",[\"i32:22685\"]],[\"invoke\",4089,0,\"load8_u\",[\"i32:24874\"]],[\"invoke\",4100,0,\"load8_u\",[\"i32:27063\"]],[\"invoke\",4110,0,\"load8_u\",[\"i32:29053\"]],[\"invoke\",4121,0,\"load8_u\",[\"i32:31242\"]],[\"invoke\",4132,0,\"load8_u\",[\"i32:33431\"]],[\"invoke\",4143,0,\"load8_u\",[\"i32:35620\"]],[\"invoke\",4154,0,\"load8_u\",[\"i32:37809\"]],[\"invoke\",4165,0,\"load8_u\",[\"i32:39998\"]],[\"invoke\",4176,0,\"load8_u\",[\"i32:42187\"]],[\"invoke\",4187,0,\"load8_u\",[\"i32:44376\"]],[\"invoke\",4197,0,\"load8_u\",[\"i32:46366\"]],[\"invoke\",4208,0,\"load8_u\",[\"i32:48555\"]],[\"invoke\",4219,0,\"load8_u\",[\"i32:50744\"]],[\"invoke\",4230,0,\"load8_u\",[\"i32:52933\"]],[\"invoke\",4241,0,\"load8_u\",[\"i32:55122\"]],[\"invoke\",4252,0,\"load8_u\",[\"i32:57311\"]],[\"invoke\",4263,0,\"load8_u\",[\"i32:59500\"]],[\"invoke\",4274,0,\"load8_u\",[\"i32:61441\"]],[\"invoke\",4285,0,\"load8_u\",[\"i32:61452\"]],[\"invoke\",4295,0,\"load8_u\",[\"i32:61908\"]],[\"invoke\",4306,0,\"load8_u\",[\"i32:64097\"]],[\"module\",4763,92],[\"invoke\",4786,0,\"checkRange\",[\"i32:20\",\"i32:65536\",\"i32:0\"]],[\"module\",4789,93],[\"module\",4815,94],[\"module\",4821,95],[\"module\",4827,96],[\"module\",4833,97],[\"module\",4839,98],[\"invoke\",4861,0,\"checkRange\",[\"i32:32768\",\"i32:65536\",\"i32:170\"]],[\"module\",4863,99],[\"module\",4869,100],[\"module\",4875,101],[\"module\",4881,102],[\"module\",4887,103],[\"module\",4893,104],[\"module\",4899,105],[\"invoke\",5123,0,\"checkRange\",[\"i32:2132\",\"i32:2827\",\"i32:10\"]],[\"invoke\",5145,0,\"checkRange\",[\"i32:5691\",\"i32:6552\",\"i32:83\"]],[\"invoke\",5167,0,\"checkRange\",[\"i32:10087\",\"i32:10206\",\"i32:5\"]],[\"invoke\",5189,0,\"checkRange\",[\"i32:13114\",\"i32:14133\",\"i32:59\"]],[\"invoke\",5209,0,\"checkRange\",[\"i32:15871\",\"i32:15998\",\"i32:95\"]],[\"invoke\",5231,0,\"checkRange\",[\"i32:18553\",\"i32:18744\",\"i32:42\"]],[\"invoke\",5253,0,\"checkRange\",[\"i32:21468\",\"i32:21492\",\"i32:93\"]],[\"invoke\",5275,0,\"checkRange\",[\"i32:24348\",\"i32:24515\",\"i32:92\"]],[\"invoke\",5297,0,\"checkRange\",[\"i32:27503\",\"i32:27573\",\"i32:77\"]],[\"invoke\",5319,0,\"checkRange\",[\"i32:31379\",\"i32:31403\",\"i32:57\"]],[\"invoke\",5341,0,\"checkRange\",[\"i32:33056\",\"i32:33660\",\"i32:89\"]],[\"invoke\",5363,0,\"checkRange\",[\"i32:35648\",\"i32:36547\",\"i32:83\"]],[\"invoke\",5385,0,\"checkRange\",[\"i32:39187\",\"i32:39859\",\"i32:92\"]],[\"invoke\",5405,0,\"checkRange\",[\"i32:42945\",\"i32:43115\",\"i32:77\"]],[\"invoke\",5427,0,\"checkRange\",[\"i32:45575\",\"i32:45640\",\"i32:77\"]],[\"invoke\",5449,0,\"checkRange\",[\"i32:47951\",\"i32:48632\",\"i32:100\"]],[\"invoke\",5471,0,\"checkRange\",[\"i32:50370\",\"i32:51358\",\"i32:92\"]],[\"invoke\",5493,0,\"checkRange\",[\"i32:55198\",\"i32:55389\",\"i32:42\"]],[\"invoke\",5515,0,\"checkRange\",[\"i32:58516\",\"i32:58835\",\"i32:95\"]],[\"invoke\",5537,0,\"checkRange\",[\"i32:60777\",\"i32:60834\",\"i32:76\"]],[\"invoke\",5559,0,\"checkRange\",[\"i32:63525\",\"i32:63605\",\"i32:74\"]],[\"file\",\"memory_fill.wast\"],[\"module\",6,106],[\"invoke\",22,0,\"test\",[]],[\"invoke\",24,0,\"checkRange\",[\"i32:0\",\"i32:65280\",\"i32:0\"]],[\"invoke\",26,0,\"checkRange\",[\"i32:65280\",\"i32:65536\",\"i32:85\"]],[\"module\",28,107],[\"invoke\",44,0,\"test\",[]],[\"module\",46,108],[\"invoke\",62,0,\"test\",[]],[\"module\",64,109],[\"invoke\",80,0,\"test\",[]],[\"invoke\",82,0,\"checkRange\",[\"i32:0\",\"i32:65536\",\"i32:0\"]],[\"module\",84,110],[\"invoke\",100,0,\"test\",[]],[\"module\",102,111],[\"invoke\",118,0,\"test\",[]],[\"module\",120,112],[\"invoke\",136,0,\"test\",[]],[\"invoke\",138,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"invoke\",140,0,\"checkRange\",[\"i32:1\",\"i32:65535\",\"i32:170\"]],[\"invoke\",142,0,\"checkRange\",[\"i32:65535\",\"i32:65536\",\"i32:0\"]],[\"module\",145,113],[\"invoke\",162,0,\"test\",[]],[\"invoke\",164,0,\"checkRange\",[\"i32:0\",\"i32:18\",\"i32:0\"]],[\"invoke\",166,0,\"checkRange\",[\"i32:18\",\"i32:21\",\"i32:85\"]],[\"invoke\",168,0,\"checkRange\",[\"i32:21\",\"i32:25\",\"i32:170\"]],[\"invoke\",170,0,\"checkRange\",[\"i32:25\",\"i32:28\",\"i32:85\"]],[\"invoke\",172,0,\"checkRange\",[\"i32:28\",\"i32:65536\",\"i32:0\"]],[\"module\",621,114],[\"invoke\",638,0,\"run\",[\"i32:65280\",\"i32:37\",\"i32:512\"]],[\"invoke\",641,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",643,114],[\"invoke\",660,0,\"run\",[\"i32:65279\",\"i32:37\",\"i32:514\"]],[\"invoke\",663,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",665,114],[\"invoke\",682,0,\"run\",[\"i32:65279\",\"i32:37\",\"i32:4294967295\"]],[\"invoke\",685,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"file\",\"memory_init.wast\"],[\"module\",6,115],[\"invoke\",17,0,\"test\",[]],[\"invoke\",19,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",20,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",21,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",22,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",23,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",24,0,\"load8_u\",[\"i32:5\"]],[\"invoke\",25,0,\"load8_u\",[\"i32:6\"]],[\"invoke\",26,0,\"load8_u\",[\"i32:7\"]],[\"invoke\",27,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",28,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",29,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",30,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",31,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",32,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",33,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",34,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",35,0,\"load8_u\",[\"i32:16\"]],[\"invoke\",36,0,\"load8_u\",[\"i32:17\"]],[\"invoke\",37,0,\"load8_u\",[\"i32:18\"]],[\"invoke\",38,0,\"load8_u\",[\"i32:19\"]],[\"invoke\",39,0,\"load8_u\",[\"i32:20\"]],[\"invoke\",40,0,\"load8_u\",[\"i32:21\"]],[\"invoke\",41,0,\"load8_u\",[\"i32:22\"]],[\"invoke\",42,0,\"load8_u\",[\"i32:23\"]],[\"invoke\",43,0,\"load8_u\",[\"i32:24\"]],[\"invoke\",44,0,\"load8_u\",[\"i32:25\"]],[\"invoke\",45,0,\"load8_u\",[\"i32:26\"]],[\"invoke\",46,0,\"load8_u\",[\"i32:27\"]],[\"invoke\",47,0,\"load8_u\",[\"i32:28\"]],[\"invoke\",48,0,\"load8_u\",[\"i32:29\"]],[\"module\",50,116],[\"invoke\",61,0,\"test\",[]],[\"invoke\",63,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",64,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",65,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",66,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",67,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",68,0,\"load8_u\",[\"i32:5\"]],[\"invoke\",69,0,\"load8_u\",[\"i32:6\"]],[\"invoke\",70,0,\"load8_u\",[\"i32:7\"]],[\"invoke\",71,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",72,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",73,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",74,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",75,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",76,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",77,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",78,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",79,0,\"load8_u\",[\"i32:16\"]],[\"invoke\",80,0,\"load8_u\",[\"i32:17\"]],[\"invoke\",81,0,\"load8_u\",[\"i32:18\"]],[\"invoke\",82,0,\"load8_u\",[\"i32:19\"]],[\"invoke\",83,0,\"load8_u\",[\"i32:20\"]],[\"invoke\",84,0,\"load8_u\",[\"i32:21\"]],[\"invoke\",85,0,\"load8_u\",[\"i32:22\"]],[\"invoke\",86,0,\"load8_u\",[\"i32:23\"]],[\"invoke\",87,0,\"load8_u\",[\"i32:24\"]],[\"invoke\",88,0,\"load8_u\",[\"i32:25\"]],[\"invoke\",89,0,\"load8_u\",[\"i32:26\"]],[\"invoke\",90,0,\"load8_u\",[\"i32:27\"]],[\"invoke\",91,0,\"load8_u\",[\"i32:28\"]],[\"invoke\",92,0,\"load8_u\",[\"i32:29\"]],[\"module\",94,117],[\"invoke\",105,0,\"test\",[]],[\"invoke\",107,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",108,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",109,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",110,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",111,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",112,0,\"load8_u\",[\"i32:5\"]],[\"invoke\",113,0,\"load8_u\",[\"i32:6\"]],[\"invoke\",114,0,\"load8_u\",[\"i32:7\"]],[\"invoke\",115,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",116,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",117,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",118,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",119,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",120,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",121,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",122,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",123,0,\"load8_u\",[\"i32:16\"]],[\"invoke\",124,0,\"load8_u\",[\"i32:17\"]],[\"invoke\",125,0,\"load8_u\",[\"i32:18\"]],[\"invoke\",126,0,\"load8_u\",[\"i32:19\"]],[\"invoke\",127,0,\"load8_u\",[\"i32:20\"]],[\"invoke\",128,0,\"load8_u\",[\"i32:21\"]],[\"invoke\",129,0,\"load8_u\",[\"i32:22\"]],[\"invoke\",130,0,\"load8_u\",[\"i32:23\"]],[\"invoke\",131,0,\"load8_u\",[\"i32:24\"]],[\"invoke\",132,0,\"load8_u\",[\"i32:25\"]],[\"invoke\",133,0,\"load8_u\",[\"i32:26\"]],[\"invoke\",134,0,\"load8_u\",[\"i32:27\"]],[\"invoke\",135,0,\"load8_u\",[\"i32:28\"]],[\"invoke\",136,0,\"load8_u\",[\"i32:29\"]],[\"module\",138,118],[\"invoke\",157,0,\"test\",[]],[\"invoke\",159,0,\"load8_u\",[\"i32:0\"]],[\"invoke\",160,0,\"load8_u\",[\"i32:1\"]],[\"invoke\",161,0,\"load8_u\",[\"i32:2\"]],[\"invoke\",162,0,\"load8_u\",[\"i32:3\"]],[\"invoke\",163,0,\"load8_u\",[\"i32:4\"]],[\"invoke\",164,0,\"load8_u\",[\"i32:5\"]],[\"invoke\",165,0,\"load8_u\",[\"i32:6\"]],[\"invoke\",166,0,\"load8_u\",[\"i32:7\"]],[\"invoke\",167,0,\"load8_u\",[\"i32:8\"]],[\"invoke\",168,0,\"load8_u\",[\"i32:9\"]],[\"invoke\",169,0,\"load8_u\",[\"i32:10\"]],[\"invoke\",170,0,\"load8_u\",[\"i32:11\"]],[\"invoke\",171,0,\"load8_u\",[\"i32:12\"]],[\"invoke\",172,0,\"load8_u\",[\"i32:13\"]],[\"invoke\",173,0,\"load8_u\",[\"i32:14\"]],[\"invoke\",174,0,\"load8_u\",[\"i32:15\"]],[\"invoke\",175,0,\"load8_u\",[\"i32:16\"]],[\"invoke\",176,0,\"load8_u\",[\"i32:17\"]],[\"invoke\",177,0,\"load8_u\",[\"i32:18\"]],[\"invoke\",178,0,\"load8_u\",[\"i32:19\"]],[\"invoke\",179,0,\"load8_u\",[\"i32:20\"]],[\"invoke\",180,0,\"load8_u\",[\"i32:21\"]],[\"invoke\",181,0,\"load8_u\",[\"i32:22\"]],[\"invoke\",182,0,\"load8_u\",[\"i32:23\"]],[\"invoke\",183,0,\"load8_u\",[\"i32:24\"]],[\"invoke\",184,0,\"load8_u\",[\"i32:25\"]],[\"invoke\",185,0,\"load8_u\",[\"i32:26\"]],[\"invoke\",186,0,\"load8_u\",[\"i32:27\"]],[\"invoke\",187,0,\"load8_u\",[\"i32:28\"]],[\"invoke\",188,0,\"load8_u\",[\"i32:29\"]],[\"module\",203,119],[\"invoke\",209,0,\"test\",[]],[\"module\",211,120],[\"invoke\",217,0,\"test\",[]],[\"module\",219,121],[\"invoke\",224,0,\"test\",[]],[\"module\",240,122],[\"invoke\",246,0,\"test\",[]],[\"module\",248,123],[\"invoke\",253,0,\"test\",[]],[\"module\",255,124],[\"invoke\",260,0,\"test\",[]],[\"module\",262,125],[\"invoke\",267,0,\"test\",[]],[\"module\",269,126],[\"invoke\",274,0,\"test\",[]],[\"module\",276,127],[\"invoke\",281,0,\"test\",[]],[\"module\",283,128],[\"invoke\",288,0,\"test\",[]],[\"module\",290,129],[\"invoke\",295,0,\"test\",[]],[\"module\",297,130],[\"invoke\",302,0,\"test\",[]],[\"module\",304,131],[\"invoke\",309,0,\"test\",[]],[\"module\",815,132],[\"invoke\",833,0,\"run\",[\"i32:65528\",\"i32:16\"]],[\"invoke\",836,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",838,132],[\"invoke\",856,0,\"run\",[\"i32:65527\",\"i32:16\"]],[\"invoke\",859,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",861,132],[\"invoke\",879,0,\"run\",[\"i32:65472\",\"i32:30\"]],[\"invoke\",882,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",884,132],[\"invoke\",902,0,\"run\",[\"i32:65473\",\"i32:31\"]],[\"invoke\",905,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",907,133],[\"invoke\",925,0,\"run\",[\"i32:65528\",\"i32:4294967040\"]],[\"invoke\",928,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",930,133],[\"invoke\",948,0,\"run\",[\"i32:0\",\"i32:4294967292\"]],[\"invoke\",951,0,\"checkRange\",[\"i32:0\",\"i32:1\",\"i32:0\"]],[\"module\",954,134],[\"file\",\"data.wast\"],[\"module\",5,135],[\"module\",39,136],[\"module\",43,137],[\"module\",48,138],[\"module\",56,139],[\"module\",66,140],[\"module\",71,141],[\"module\",77,140],[\"module\",82,141],[\"module\",100,142],[\"module\",105,143],[\"module\",111,144],[\"module\",116,145],[\"module\",120,146],[\"module\",125,147],[\"module\",130,148],[\"module\",135,145],[\"module\",139,146],[\"module\",144,147],[\"module\",149,149],[\"module\",154,150],[\"module\",159,151],[\"module\",165,152],[\"module\",171,153],[\"module\",176,154],[\"instantiate\",184,155],[\"instantiate\",192,156],[\"instantiate\",200,157],[\"instantiate\",207,158],[\"instantiate\",214,159],[\"instantiate\",231,160],[\"instantiate\",240,161],[\"instantiate\",247,162],[\"instantiate\",255,163],[\"instantiate\",263,164],[\"instantiate\",271,165],[\"instantiate\",278,166],[\"instantiate\",286,167],[\"instantiate\",293,168]]"; diff --git a/tests/corpus/webassembly-spec-memory/main.mjs b/tests/corpus/webassembly-spec-memory/main.mjs new file mode 100644 index 000000000..f45ccc584 --- /dev/null +++ b/tests/corpus/webassembly-spec-memory/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (16 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-spec-table/data.mjs b/tests/corpus/webassembly-spec-table/data.mjs new file mode 100644 index 000000000..d6334cb9e --- /dev/null +++ b/tests/corpus/webassembly-spec-table/data.mjs @@ -0,0 +1,205 @@ +/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * table_copy.wast, table_fill.wast, table_get.wast, table_grow.wast, table_init.wast, table_set.wast, table_size.wast, elem.wast, ref_func.wast, ref_is_null.wast, ref_null.wast, exports.wast, linking.wast. Do not edit. */ +export const modules = [ + "AGFzbQEAAAABBQFgAAF/AwYFAAAAAAAHHwUDZWYwAAADZWYxAAEDZWYyAAIDZWYzAAMDZWY0AAQKGgUEAEEACwQAQQELBABBAgsEAEEDCwQAQQQL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCi4IBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwMAAQsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BAkED/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBD0EC/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BGUED/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRRBFkEE/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBAUED/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBDEEH/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQxBCkEH/A4AAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBAEEU/A4BAAsHACAAEQAACwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCi4IBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwMAAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BAkED/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBD0EC/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BGUED/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRRBFkEE/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBAUED/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBDEEH/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQxBCkEH/A4BAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBAEEU/A4AAQsHACAAEQABCwcAIAARAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEF+QQFBAvwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBBvwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQX5BAvwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQ9BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQ9BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR5BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR9BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQR5BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQR9BAPwOAAAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEF+QQFBAvwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBBvwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQX5BAvwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQ9BAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQ9BAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR5BAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR9BAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQR5BAPwOAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQR9BAPwOAQAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEACwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ8BAEEACwkAAQIDBAUGBwgKZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw==", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEYCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ8BAEEXCwkAAQIDBAUGBwgKZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw==", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEELCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEVCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCREBAEEVCwsAAQIDBAUGBwgJCgpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBwFwAYABgAEHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFwEAQfAACxAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIAAgASAC/A4AAAs=", + "AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBwFwAYABgAEHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFgEAQQALEAABAgMEBQYHCAkKCwwNDg8KZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw==", + "AGFzbQEAAAABDAJgA39vfwBgAX8BbwMEAwAAAQQEAW8ACgccAwRmaWxsAAALZmlsbC1hYmJyZXYAAQNnZXQAAgogAwsAIAAgASAC/BEACwsAIAAgASAC/BEACwYAIAAlAAs=", + "AGFzbQEAAAABFwVgAABgAW8AYAF/AW9gAX8BcGABfwF/AwYFAAECAwQEBwJvAAJwAAMHOAQEaW5pdAABDWdldC1leHRlcm5yZWYAAgtnZXQtZnVuY3JlZgADD2lzX251bGwtZnVuY3JlZgAECQkBAgFBAQsAAQAKKwUCAAsQAEEBIAAmAEECQQElASYBCwYAIAAlAAsGACAAJQELBwAgABAD0Qs=", + "AGFzbQEAAAABFQRgAX8Bb2ACf28AYAJ/bwF/YAABfwMGBQABAgIDBAQBbwAABykFA2dldAAAA3NldAABBGdyb3cAAgtncm93LWFiYnJldgADBHNpemUABAorBQYAIAAlAAsIACAAIAEmAAsJACABIAD8DwALCQAgASAA/A8ACwUA/BAACw==", + "AGFzbQEAAAABBQFgAAF/AwIBAAQEAXAAEAcIAQRncm93AAAJBQEDAAEACgsBCQDSAEFw/A8ACw==", + "AGFzbQEAAAABBgFgAX8BfwMCAQAEBAFvAAAHCAEEZ3JvdwAACgsBCQDQbyAA/A8ACw==", + "AGFzbQEAAAABBgFgAX8BfwMCAQAEBQFvAQAKBwgBBGdyb3cAAAoLAQkA0G8gAPwPAAs=", + "AGFzbQEAAAABDAJgAX8Bf2ACf38BcAMDAgABBAQBcAAKBxsCBGdyb3cAABBjaGVjay10YWJsZS1udWxsAAEJBQEDAAEBCj0CCQDQcCAA/A8ACzEBAXDSASECAkADQCAAJQAhAiAC0UUNASAAIAFPDQEgAEEBaiEAIAAgAU0NAAsLIAIL", + "AGFzbQEAAAABBQFgAAF/AwIBAAQEAXAAAQcQAgV0YWJsZQEABGdyb3cAAAoLAQkA0HBBAfwPAAs=", + "AGFzbQEAAAABBQFgAAF/AhcBC2dyb3duLXRhYmxlBXRhYmxlAXAAAgMCAQAHEAIFdGFibGUBAARncm93AAAKCwEJANBwQQH8DwAL", + "AGFzbQEAAAABBQFgAAF/AiABFGdyb3duLWltcG9ydGVkLXRhYmxlBXRhYmxlAXAAAwMCAQAHCAEEc2l6ZQAACgcBBQD8EAAL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgovBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEHQQBBBPwMAQALBwAgABEAAAs=", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgovBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQQFBA/wMAwALBwAgABEAAAs=", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgpxBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQtOAEEHQQBBBPwMAQD8DQFBD0EBQQP8DAMA/A0DQRRBD0EF/A4AAEEVQR1BAfwOAABBGEEKQQH8DgAAQQ1BC0EE/A4AAEETQRRBBfwOAAALBwAgABEAAAs=", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKLwcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBB0EAQQT8DAEBCwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKLwcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBD0EBQQP8DAMBCwcAIAARAAEL", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKcQcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLTgBBB0EAQQT8DAEB/A0BQQ9BAUED/AwDAfwNA0EUQQ9BBfwOAQFBFUEdQQH8DgEBQRhBCkEB/A4BAUENQQtBBPwOAQFBE0EUQQX8DgEBCwcAIAARAAEL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCjkLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsFAPwNAgs=", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQFBAfwMAgAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkoLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsWAEEMQQFBAfwMAQBBFUEBQQH8DAEACw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCjwLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsIAPwNAfwNAQs=", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkMLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsPAPwNAUEMQQFBAfwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQBBBfwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQJBA/wMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQRBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQVBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQJBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQJBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQRBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQVBAPwMAQAL", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBGkEBQQP8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBDEEEQQD8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBDEEFQQD8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHEECQQD8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHUECQQD8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHEEEQQD8DAEBCw==", + "AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHUEFQQD8DAEBCw==", + "AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABIEAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBACAB/AwAAAs=", + "AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQHAXABoAHAAgdkEgJmMAAAAmYxAAECZjIAAgJmMwADAmY0AAQCZjUABQJmNgAGAmY3AAcCZjgACAJmOQAJA2YxMAAKA2YxMQALA2YxMgAMA2YxMwANA2YxNAAOA2YxNQAPBHRlc3QAEANydW4AEQkUAQEAEAABAgMEBQYHCAkKCwwNDg8KZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgAEEAIAH8DAAACw==", + "AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABQEAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBACAB/AwAAAs=", + "AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABEBAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBCCAB/AwAAAs=", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAABCcQBQQEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAoOAQwAQQBBAEEA/AxAAAs=", + "AGFzbQEAAAABIgdgAABgAX8Bb2ABfwFwYAJ/bwBgAn9wAGACf38AYAF/AX8DCAcAAQIDBAUGBAcCbwABcAACB2IGDWdldC1leHRlcm5yZWYAAQtnZXQtZnVuY3JlZgACDXNldC1leHRlcm5yZWYAAwtzZXQtZnVuY3JlZgAEEHNldC1mdW5jcmVmLWZyb20ABQ9pc19udWxsLWZ1bmNyZWYABgkJAQIBQQELAAEACjcHAgALBgAgACUACwYAIAAlAQsIACAAIAEmAAsIACAAIAEmAQsKACAAIAElASYBCwcAIAAQAtEL", + "AGFzbQEAAAABCQJgAAF/YAF/AAMJCAAAAAABAQEBBA8EbwAAbwABbwEAAm8BAwgHUQgHc2l6ZS10MAAAB3NpemUtdDEAAQdzaXplLXQyAAIHc2l6ZS10MwADB2dyb3ctdDAABAdncm93LXQxAAUHZ3Jvdy10MgAGB2dyb3ctdDMABwpFCAUA/BAACwUA/BABCwUA/BACCwUA/BADCwoA0G8gAPwPABoLCgDQbyAA/A8BGgsKANBvIAD8DwIaCwoA0G8gAPwPAxoL", + "AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgmkAz0BAAAFcATSAAvSAAvQcAvSAQsBAAABAAQAAAEBAQAABXAE0gAL0gAL0HAL0gELAQAAAQAEAAABAQBBAAsABEEACwLSAAvQcAsAQQALAABBAAsCAAEAQQALAABBAAsCAAEAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAEQQALAtIAC9BwCwBBAAsABEEACwLSAAvQcAsAQQALAABBAAsCAAEAQQALAABBAAsCAAEAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAADAAAHcATSAAvSAAvQcAvSAQsDAAADAAQAAAEBAwAAB3AE0gAL0gAL0HAL0gELAwAAAwAEAAABAQoHAgIACwIACw==", + "AGFzbQEAAAABBAFgAAADAwIAAAQFAXABAwMJDwEEQQALA9IAC9BwC9IBCwoHAgIACwIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEACwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBAAsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCR8FAEEACwEAAEEDCwEAAEEHCwEAAEEFCwEAAEEDCwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkfBQBBCQsBAABBAwsBAABBBwsBAABBAwsBAABBBQsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMCAQAEBQFwAOgHCQcBACMACwEACgQBAgAL", + "AGFzbQEAAAABBQFgAAF/AwUEAAAAAAQEAXAACgcTAgZjYWxsLTcAAgZjYWxsLTkAAwkNAgBBBwsBAABBCQsBAQodBAUAQcEACwUAQcIACwcAQQcRAAALBwBBCREAAAs=", + "AGFzbQEAAAABBQFgAAF/AwUEAAAAAAQEAXAACwcTAgZjYWxsLTcAAgZjYWxsLTkAAwkXAgRBBgsC0HAL0gALBEEJCwLSAQvQcAsKHQQFAEHBAAsFAEHCAAsHAEEHEQAACwcAQQkRAAAL", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEJCwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBCQsBAAoEAQIACw==", + "AGFzbQEAAAAEBAFwAAAJBgEAQQALAA==", + "AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAACQYBAEEACwA=", + "AGFzbQEAAAAEBQFwAQAACQYBAEEACwA=", + "AGFzbQEAAAAEBAFwABQJBgEAQRQLAA==", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAAAwIBAAkHAQBBAAsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAZAMCAQAJBwEAQQALAQAKBAECAAs=", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAAAwIBAAkHAQBBAQsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAHgMCAQAJBwEAQQELAQAKBAECAAs=", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAACQcBAEEACwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAADAgEABAUBcAEAAAkHAQBBAAsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAUBcAEAAQkHAQBBAAsBAAoEAQIACw==", + "AGFzbQEAAAAEBAFwAAAJBgEAQQELAA==", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEKCwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBCgsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAUBcAEKFAkHAQBBCgsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEF/CwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBfwsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEF2CwEACgQBAgAL", + "AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBdgsBAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQRpbml0AAEJBwEAQQALAQAKEQICAAsMAEEAQQBBAfwMAAAL", + "AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQRpbml0AAEJBQEDAAEAChECAgALDABBAEEAQQH8DAAACw==", + "AGFzbQEAAAABBQFgAAF/AwQDAAAABAQBcAAKBxQBEGNhbGwtb3ZlcndyaXR0ZW4AAgkNAgBBCQsBAABBCQsBAQoVAwUAQcEACwUAQcIACwcAQQkRAAAL", + "AGFzbQEAAAABBQFgAAF/AhQBCHNwZWN0ZXN0BXRhYmxlAXAACgMEAwAAAAccARhjYWxsLW92ZXJ3cml0dGVuLWVsZW1lbnQAAgkNAgBBCQsBAABBCQsBAQoVAwUAQcEACwUAQcIACwcAQQkRAAAL", + "AGFzbQEAAAABBQFgAAF/AwYFAAAAAAAEBAFwAAoHKwQMc2hhcmVkLXRhYmxlAQAGY2FsbC03AAIGY2FsbC04AAMGY2FsbC05AAQJDQIAQQgLAQAAQQkLAQEKJQUFAEHBAAsFAEHCAAsHAEEHEQAACwcAQQgRAAALBwBBCREAAAs=", + "AGFzbQEAAAABBQFgAAF/AhoBB21vZHVsZTEMc2hhcmVkLXRhYmxlAXAACgMDAgAACQ0CAEEHCwEAAEEICwEBCg0CBQBBwwALBQBBxAAL", + "AGFzbQEAAAABBQFgAAF/AhoBB21vZHVsZTEMc2hhcmVkLXRhYmxlAXAACgMDAgAACQ0CAEEICwEAAEEJCwEBCg0CBQBBxQALBQBBxgAL", + "AGFzbQEAAAABCwJgAX8Bb2ACf28AAwMCAAEEBAFvAAIHFQMFdGFibGUBAANnZXQAAANzZXQAAQoRAgYAIAAlAAsIACAAIAEmAAs=", + "AGFzbQEAAAACFAEIZXhwb3J0ZXIFdGFibGUBbwACCQsBBgBBAAtvAdBvCw==", + "AGFzbQEAAAABBQFgAAF/AwIBAAYGAXAA0gALBwUBAWYDAAoGAQQAQSoL", + "AGFzbQEAAAABBQFgAAF/Ag4BB21vZHVsZTQBZgNwAAMCAQAEBAFwAAoHFgESY2FsbF9pbXBvcnRlZF9lbGVtAAAJCQEEQQALASMACwoJAQcAQQARAAAL", + "AGFzbQEAAAABBgFgAX8BfwMCAQAHBQEBZgAACgYBBAAgAAs=", + "AGFzbQEAAAABDQNgAX8Bf2AAAGAAAX8CBwEBTQFmAAADDw4AAQEBAQECAgIBAQAAAAQEAXAAAQYaBXAA0gALcADSAQtwAdIAC3AA0gMLcADSBAsHUAgJaXNfbnVsbC1mAAcJaXNfbnVsbC1nAAgJaXNfbnVsbC12AAkFc2V0LWYACgVzZXQtZwALBmNhbGwtZgAMBmNhbGwtZwANBmNhbGwtdgAOCRADAwACAwUDAAIEBgMAAgABCm4OBwAgAEEBagsIANIFGtIGGgsCAAsCAAsCAAsCAAsFANIA0QsFANIB0QsFACMC0QsGANIAJAILBgDSASQCCw8AQQDSACYAIABBABEAAAsPAEEA0gEmACAAQQARAAALDwBBACMCJgAgAEEAEQAACw==", + "AGFzbQEAAAABBAFgAAADCAcAAAAAAAAABAQBcAABBgYBcADSAAsHBQEBZgABCRUEAEEACwECAEEACwEDAQABBAEAAQUKIwcCAAsCAAsCAAsCAAsCAAsCAAsPANIA0gHSAtID0gTSBQ8L", + "AGFzbQEAAAABFwVgAXABf2ABbwF/YAAAYAFvAGABfwF/AwgHAAECAwIEBAQHAnAAAm8AAgdHBgdmdW5jcmVmAAAJZXh0ZXJucmVmAAEEaW5pdAADBmRlaW5pdAAEDGZ1bmNyZWYtZWxlbQAFDmV4dGVybnJlZi1lbGVtAAYJBwEAQQELAQIKOgcFACAA0QsFACAA0QsCAAsIAEEBIAAmAQsOAEEB0HAmAEEB0G8mAQsIACAAJQAQAAsIACAAJQEQAQs=", + "AGFzbQEAAAABCQJgAAFvYAABcAMDAgABBgsCbwDQbwtwANBwCwcXAglleHRlcm5yZWYAAAdmdW5jcmVmAAEKCwIEANBvCwQA0HAL", + "AGFzbQEAAAABBAFgAAADAgEABwUBAWEAAAoEAQIACw==", + "AGFzbQEAAAABBAFgAAADAgEABwkCAWEAAAFiAAAKBAECAAs=", + "AGFzbQEAAAABBAFgAAADAwIAAAcJAgFhAAABYgABCgcCAgALAgAL", + "AGFzbQEAAAABBAFgAAADAgEABw0DAWEAAAFiAAABYwAACgQBAgAL", + "AGFzbQEAAAABBQFgAX8AAwIBAAcJAgFhAAABYgAACgQBAgAL", + "AGFzbQEAAAABBgFgAX8BfwMCAQAHBQEBZQAACgoBCAAgAEEBag8L", + "AGFzbQEAAAA=", + "AGFzbQEAAAABBQFgAAF/AwIBAAcNAwFhAAABYgAAAWMAAAoGAQQAQSoL", + "AGFzbQEAAAAGBgF/AEEACwcFAQFhAwA=", + "AGFzbQEAAAAGBgF/AEEACwcJAgFhAwABYgMA", + "AGFzbQEAAAAGCwJ/AEEAC38AQQALBwkCAWEDAAFiAwE=", + "AGFzbQEAAAAGBgF/AEEqCwcFAQFlAwA=", + "AGFzbQEAAAAEBAFwAAAHBQEBYQEA", + "AGFzbQEAAAAEBAFwAAAHCQIBYQEAAWIBAA==", + "AGFzbQEAAAAEBwJwAABwAAAHCQIBYQEAAWIBAQ==", + "AGFzbQEAAAAEBQFwAQABBwUBAWEBAA==", + "AGFzbQEAAAAFAwEAAAcFAQFhAgA=", + "AGFzbQEAAAAFAwEAAAcJAgFhAgABYgIA", + "AGFzbQEAAAAFBAEBAAEHBQEBYQIA", + "AGFzbQEAAAABBQFgAAF/AwMCAAAHCAEEY2FsbAAACgsCBAAQAQsEAEECCw==", + "AGFzbQEAAAABBQFgAAF/AgsBAk1mBGNhbGwAAAMEAwAAAAchAwdNZi5jYWxsAAAMY2FsbCBNZi5jYWxsAAEEY2FsbAACChADBAAQAAsEABADCwQAQQML", + "AGFzbQEAAAABBQFgAX8AAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAABwkBBXByaW50AAA=", + "AGFzbQEAAAABBQFgAX4AAhQBCnJlZXhwb3J0X2YFcHJpbnQAAA==", + "AGFzbQEAAAABBgFgAX8BfwIUAQpyZWV4cG9ydF9mBXByaW50AAA=", + "AGFzbQEAAAABCQJgAAF/YAF/AAMEAwAAAQYMAn8AQSoLfwFBjgELBy0FBGdsb2IDAANnZXQAAAhtdXRfZ2xvYgMBB2dldF9tdXQAAQdzZXRfbXV0AAIKEgMEACMACwQAIwELBgAgACQBCw==", + "AGFzbQEAAAABCQJgAAF/YAF/AAI+BQJNZwRnbG9iA38AAk1nCG11dF9nbG9iA38BAk1nA2dldAAAAk1nB2dldF9tdXQAAAJNZwdzZXRfbXV0AAEDAgEABgYBfwBBKwsHSQcHTWcuZ2xvYgMABk1nLmdldAAABGdsb2IDAgNnZXQAAwtNZy5tdXRfZ2xvYgMBCk1nLmdldF9tdXQAAQpNZy5zZXRfbXV0AAIKBgEEACMCCw==", + "AGFzbQEAAAACEAECTWcIbXV0X2dsb2IDfwA=", + "AGFzbQEAAAACDAECTWcEZ2xvYgN/AQ==", + "AGFzbQEAAAAGFQRwANBwC3AB0HALbwDQbwtvAdBvCwc9BAxnLWNvbnN0LWZ1bmMDAApnLXZhci1mdW5jAwEOZy1jb25zdC1leHRlcm4DAgxnLXZhci1leHRlcm4DAw==", + "AGFzbQEAAAACYQQHTXJlZl9leAxnLWNvbnN0LWZ1bmMDcAAHTXJlZl9leA5nLWNvbnN0LWV4dGVybgNvAAdNcmVmX2V4CmctdmFyLWZ1bmMDcAEHTXJlZl9leAxnLXZhci1leHRlcm4DbwE=", + "AGFzbQEAAAACGwEHTXJlZl9leA5nLWNvbnN0LWV4dGVybgNwAA==", + "AGFzbQEAAAACGQEHTXJlZl9leAxnLWNvbnN0LWZ1bmMDbwA=", + "AGFzbQEAAAACFwEHTXJlZl9leApnLXZhci1mdW5jA28B", + "AGFzbQEAAAACGQEHTXJlZl9leAxnLXZhci1leHRlcm4DcAE=", + "AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8DBAMAAAIEBAFwAAoHEgMDdGFiAQABaAABBGNhbGwAAgkKAQBBAgsEAAAAAAoTAwQAQQQLBABBfAsHACAAEQAACw==", + "AGFzbQEAAAABDQNgAABgAAF/YAF/AX8CEgICTXQEY2FsbAACAk10AWgAAQMEAwECAgQFAXABBQUHIQMHTXQuY2FsbAAADGNhbGwgTXQuY2FsbAADBGNhbGwABAkLAQBBAAsFAgICAQAKFQMEAEEFCwYAIAAQAAsHACAAEQEACw==", + "AGFzbQEAAAABCgJgAAF/YAF/AX8CEwICTXQBaAAAAk10A3RhYgFwAAUDAwIAAQcIAQRjYWxsAAIJCAEAQQELAgEACg4CBABBBgsHACAAEQAACw==", + "AGFzbQEAAAABBAFgAAACDAECTXQDdGFiAXAAAAMCAQAJBwEAQQkLAQAKBAECAAs=", + "AGFzbQEAAAAGBgF/AEEFCwcFAQFnAwA=", + "AGFzbQEAAAACCQECRzEBZwN/AAYGAX8AIwALBwUBAWcDAQ==", + "AGFzbQEAAAABBAFgAAACDAECTXQDdGFiAXAAAAMCAQAJBwEAQQoLAQAKBAECAAs=", + "AGFzbQEAAAABBQFgAAF/AhYCAk10A3RhYgFwAAoCTXQDbWVtAgABAwIBAAkNAgBBBwsBAABBCQsBAAoGAQQAQQAL", + "AGFzbQEAAAABBQFgAAF/AgwBAk10A3RhYgFwAAoDAgEACRECAEEHCwEAAEEICwUAAAAAAAoGAQQAQQAL", + "AGFzbQEAAAABBQFgAAF/AgwBAk10A3RhYgFwAAoDAgEABQMBAAEJBwEAQQcLAQAKBgEEAEEACwsJAQBBgIAECwFk", + "AGFzbQEAAAAEBwJwAAFvAAEHFQIGdC1mdW5jAQAIdC1leHRlcm4BAQ==", + "AGFzbQEAAAACLQIJTXRhYmxlX2V4BnQtZnVuYwFwAAEJTXRhYmxlX2V4CHQtZXh0ZXJuAW8AAQ==", + "AGFzbQEAAAACFgEJTXRhYmxlX2V4BnQtZnVuYwFvAAE=", + "AGFzbQEAAAACGAEJTXRhYmxlX2V4CHQtZXh0ZXJuAXAAAQ==", + "AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAQUHDgIDbWVtAgAEbG9hZAAACgkBBwAgAC0AAAsLEAEAQQoLCgABAgMEBQYHCAk=", + "AGFzbQEAAAABBgFgAX8BfwILAQJNbQRsb2FkAAADAgEABQMBAAEHEgIHTW0ubG9hZAAABGxvYWQAAQoJAQcAIAAtAAALCwwBAEEKCwbw8fLz9PU=", + "AGFzbQEAAAABBgFgAX8BfwILAQJNbQNtZW0CAAEDAgEABwgBBGxvYWQAAAoJAQcAIAAtAAALCw4BAEEFCwigoaKjpKWmpw==", + "AGFzbQEAAAACCwECTW0DbWVtAgAACwkBAEH//wMLAWE=", + "AGFzbQEAAAACCwECTW0DbWVtAgAACwkBAEGAgAQLAWE=", + "AGFzbQEAAAABBgFgAX8BfwIMAQJNbQNtZW0CAQEIAwIBAAcIAQRncm93AAAKCAEGACAAQAAL", + "AGFzbQEAAAABBAFgAAACJwMIc3BlY3Rlc3QFcHJpbnQAAAJNbQNtZW0CAAECTW0DdGFiAXAAAAsJAQBBAAsDYWJj", + "AGFzbQEAAAACCwECTW0DbWVtAgABCyICAEEACwNhYmMAQfb/EwsSenp6enp6enp6enp6enp6enp6", + "AGFzbQEAAAABBAFgAAACCwECTW0DbWVtAgABAwIBAAQEAXAAAAkHAQBBAAsBAAoEAQIACwsJAQBBAAsDYWJj", + "AGFzbQEAAAABBQFgAAF/AwMCAAAEBAFwAAEFAwEAAQcxBAZtZW1vcnkCAAV0YWJsZQEADWdldCBtZW1vcnlbMF0AAAxnZXQgdGFibGVbMF0AAQoRAgcAQQAtAAALBwBBABEAAAs=", + "AGFzbQEAAAABCAJgAAF/YAAAAhsCAk1zBm1lbW9yeQIAAQJNcwV0YWJsZQFwAAEDAwIAAQgBAQkHAQBBAAsBAAoMAgYAQa29AwsDAAALCwsBAEEACwVoZWxsbw==", +]; +export const script = "[[\"file\",\"table_copy.wast\"],[\"module\",6,0],[\"register\",\"a\"],[\"module\",15,1],[\"invoke\",45,0,\"test\",[]],[\"invoke\",50,0,\"check_t0\",[\"i32:4\"]],[\"invoke\",54,0,\"check_t0\",[\"i32:8\"]],[\"invoke\",58,0,\"check_t0\",[\"i32:12\"]],[\"invoke\",62,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",66,0,\"check_t0\",[\"i32:20\"]],[\"invoke\",71,0,\"check_t0\",[\"i32:25\"]],[\"invoke\",75,0,\"check_t0\",[\"i32:29\"]],[\"invoke\",79,0,\"check_t1\",[\"i32:3\"]],[\"invoke\",83,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",87,0,\"check_t1\",[\"i32:11\"]],[\"invoke\",92,0,\"check_t1\",[\"i32:16\"]],[\"invoke\",96,0,\"check_t1\",[\"i32:20\"]],[\"invoke\",100,0,\"check_t1\",[\"i32:24\"]],[\"invoke\",104,0,\"check_t1\",[\"i32:28\"]],[\"module\",107,2],[\"invoke\",139,0,\"check_t0\",[\"i32:1\"]],[\"invoke\",143,0,\"check_t0\",[\"i32:5\"]],[\"invoke\",148,0,\"check_t0\",[\"i32:10\"]],[\"invoke\",152,0,\"check_t0\",[\"i32:14\"]],[\"invoke\",156,0,\"check_t0\",[\"i32:18\"]],[\"invoke\",160,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",164,0,\"check_t0\",[\"i32:26\"]],[\"invoke\",169,0,\"check_t1\",[\"i32:1\"]],[\"invoke\",173,0,\"check_t1\",[\"i32:5\"]],[\"invoke\",177,0,\"check_t1\",[\"i32:9\"]],[\"invoke\",181,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",185,0,\"check_t1\",[\"i32:17\"]],[\"invoke\",190,0,\"check_t1\",[\"i32:22\"]],[\"invoke\",194,0,\"check_t1\",[\"i32:26\"]],[\"module\",199,3],[\"invoke\",229,0,\"test\",[]],[\"invoke\",233,0,\"check_t0\",[\"i32:3\"]],[\"invoke\",237,0,\"check_t0\",[\"i32:7\"]],[\"invoke\",241,0,\"check_t0\",[\"i32:11\"]],[\"invoke\",246,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",250,0,\"check_t0\",[\"i32:20\"]],[\"invoke\",254,0,\"check_t0\",[\"i32:24\"]],[\"invoke\",258,0,\"check_t0\",[\"i32:28\"]],[\"invoke\",262,0,\"check_t1\",[\"i32:2\"]],[\"invoke\",267,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",271,0,\"check_t1\",[\"i32:11\"]],[\"invoke\",275,0,\"check_t1\",[\"i32:15\"]],[\"invoke\",279,0,\"check_t1\",[\"i32:19\"]],[\"invoke\",283,0,\"check_t1\",[\"i32:23\"]],[\"invoke\",288,0,\"check_t1\",[\"i32:28\"]],[\"module\",291,4],[\"invoke\",323,0,\"check_t0\",[\"i32:1\"]],[\"invoke\",327,0,\"check_t0\",[\"i32:5\"]],[\"invoke\",331,0,\"check_t0\",[\"i32:9\"]],[\"invoke\",335,0,\"check_t0\",[\"i32:13\"]],[\"invoke\",339,0,\"check_t0\",[\"i32:17\"]],[\"invoke\",344,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",348,0,\"check_t0\",[\"i32:26\"]],[\"invoke\",352,0,\"check_t1\",[\"i32:0\"]],[\"invoke\",356,0,\"check_t1\",[\"i32:4\"]],[\"invoke\",360,0,\"check_t1\",[\"i32:8\"]],[\"invoke\",365,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",369,0,\"check_t1\",[\"i32:17\"]],[\"invoke\",373,0,\"check_t1\",[\"i32:21\"]],[\"invoke\",377,0,\"check_t1\",[\"i32:25\"]],[\"invoke\",381,0,\"check_t1\",[\"i32:29\"]],[\"module\",383,5],[\"invoke\",417,0,\"check_t0\",[\"i32:3\"]],[\"invoke\",421,0,\"check_t0\",[\"i32:7\"]],[\"invoke\",425,0,\"check_t0\",[\"i32:11\"]],[\"invoke\",429,0,\"check_t0\",[\"i32:15\"]],[\"invoke\",433,0,\"check_t0\",[\"i32:19\"]],[\"invoke\",437,0,\"check_t0\",[\"i32:23\"]],[\"invoke\",442,0,\"check_t0\",[\"i32:28\"]],[\"invoke\",446,0,\"check_t1\",[\"i32:2\"]],[\"invoke\",450,0,\"check_t1\",[\"i32:6\"]],[\"invoke\",454,0,\"check_t1\",[\"i32:10\"]],[\"invoke\",458,0,\"check_t1\",[\"i32:14\"]],[\"invoke\",463,0,\"check_t1\",[\"i32:19\"]],[\"invoke\",467,0,\"check_t1\",[\"i32:23\"]],[\"invoke\",471,0,\"check_t1\",[\"i32:27\"]],[\"module\",475,6],[\"invoke\",506,0,\"check_t0\",[\"i32:0\"]],[\"invoke\",510,0,\"check_t0\",[\"i32:4\"]],[\"invoke\",515,0,\"check_t0\",[\"i32:9\"]],[\"invoke\",519,0,\"check_t0\",[\"i32:13\"]],[\"invoke\",523,0,\"check_t0\",[\"i32:17\"]],[\"invoke\",527,0,\"check_t0\",[\"i32:21\"]],[\"invoke\",531,0,\"check_t0\",[\"i32:25\"]],[\"invoke\",535,0,\"check_t0\",[\"i32:29\"]],[\"invoke\",540,0,\"check_t1\",[\"i32:4\"]],[\"invoke\",544,0,\"check_t1\",[\"i32:8\"]],[\"invoke\",548,0,\"check_t1\",[\"i32:12\"]],[\"invoke\",552,0,\"check_t1\",[\"i32:16\"]],[\"invoke\",556,0,\"check_t1\",[\"i32:20\"]],[\"invoke\",561,0,\"check_t1\",[\"i32:25\"]],[\"invoke\",565,0,\"check_t1\",[\"i32:29\"]],[\"module\",567,7],[\"invoke\",600,0,\"check_t0\",[\"i32:2\"]],[\"invoke\",604,0,\"check_t0\",[\"i32:6\"]],[\"invoke\",608,0,\"check_t0\",[\"i32:10\"]],[\"invoke\",613,0,\"check_t0\",[\"i32:15\"]],[\"invoke\",617,0,\"check_t0\",[\"i32:19\"]],[\"invoke\",621,0,\"check_t0\",[\"i32:23\"]],[\"invoke\",625,0,\"check_t0\",[\"i32:27\"]],[\"invoke\",629,0,\"check_t1\",[\"i32:1\"]],[\"invoke\",633,0,\"check_t1\",[\"i32:5\"]],[\"invoke\",638,0,\"check_t1\",[\"i32:10\"]],[\"invoke\",642,0,\"check_t1\",[\"i32:14\"]],[\"invoke\",646,0,\"check_t1\",[\"i32:18\"]],[\"invoke\",650,0,\"check_t1\",[\"i32:22\"]],[\"invoke\",654,0,\"check_t1\",[\"i32:26\"]],[\"module\",659,8],[\"invoke\",690,0,\"check_t0\",[\"i32:0\"]],[\"invoke\",694,0,\"check_t0\",[\"i32:4\"]],[\"invoke\",698,0,\"check_t0\",[\"i32:8\"]],[\"invoke\",702,0,\"check_t0\",[\"i32:12\"]],[\"invoke\",706,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",711,0,\"check_t0\",[\"i32:21\"]],[\"invoke\",715,0,\"check_t0\",[\"i32:25\"]],[\"invoke\",719,0,\"check_t0\",[\"i32:29\"]],[\"invoke\",723,0,\"check_t1\",[\"i32:3\"]],[\"invoke\",727,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",731,0,\"check_t1\",[\"i32:11\"]],[\"invoke\",736,0,\"check_t1\",[\"i32:16\"]],[\"invoke\",740,0,\"check_t1\",[\"i32:20\"]],[\"invoke\",744,0,\"check_t1\",[\"i32:24\"]],[\"invoke\",748,0,\"check_t1\",[\"i32:28\"]],[\"module\",751,9],[\"invoke\",783,0,\"check_t0\",[\"i32:1\"]],[\"invoke\",788,0,\"check_t0\",[\"i32:6\"]],[\"invoke\",792,0,\"check_t0\",[\"i32:10\"]],[\"invoke\",796,0,\"check_t0\",[\"i32:14\"]],[\"invoke\",800,0,\"check_t0\",[\"i32:18\"]],[\"invoke\",804,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",809,0,\"check_t0\",[\"i32:27\"]],[\"invoke\",813,0,\"check_t1\",[\"i32:1\"]],[\"invoke\",817,0,\"check_t1\",[\"i32:5\"]],[\"invoke\",821,0,\"check_t1\",[\"i32:9\"]],[\"invoke\",825,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",829,0,\"check_t1\",[\"i32:17\"]],[\"invoke\",834,0,\"check_t1\",[\"i32:22\"]],[\"invoke\",838,0,\"check_t1\",[\"i32:26\"]],[\"module\",843,10],[\"invoke\",873,0,\"test\",[]],[\"invoke\",877,0,\"check_t0\",[\"i32:3\"]],[\"invoke\",881,0,\"check_t0\",[\"i32:7\"]],[\"invoke\",886,0,\"check_t0\",[\"i32:12\"]],[\"invoke\",890,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",894,0,\"check_t0\",[\"i32:20\"]],[\"invoke\",898,0,\"check_t0\",[\"i32:24\"]],[\"invoke\",902,0,\"check_t0\",[\"i32:28\"]],[\"invoke\",907,0,\"check_t1\",[\"i32:3\"]],[\"invoke\",911,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",915,0,\"check_t1\",[\"i32:11\"]],[\"invoke\",919,0,\"check_t1\",[\"i32:15\"]],[\"invoke\",923,0,\"check_t1\",[\"i32:19\"]],[\"invoke\",927,0,\"check_t1\",[\"i32:23\"]],[\"invoke\",932,0,\"check_t1\",[\"i32:28\"]],[\"module\",935,11],[\"invoke\",967,0,\"check_t0\",[\"i32:1\"]],[\"invoke\",971,0,\"check_t0\",[\"i32:5\"]],[\"invoke\",975,0,\"check_t0\",[\"i32:9\"]],[\"invoke\",979,0,\"check_t0\",[\"i32:13\"]],[\"invoke\",984,0,\"check_t0\",[\"i32:18\"]],[\"invoke\",988,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",992,0,\"check_t0\",[\"i32:26\"]],[\"invoke\",996,0,\"check_t1\",[\"i32:0\"]],[\"invoke\",1000,0,\"check_t1\",[\"i32:4\"]],[\"invoke\",1005,0,\"check_t1\",[\"i32:9\"]],[\"invoke\",1009,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",1013,0,\"check_t1\",[\"i32:17\"]],[\"invoke\",1017,0,\"check_t1\",[\"i32:21\"]],[\"invoke\",1021,0,\"check_t1\",[\"i32:25\"]],[\"invoke\",1025,0,\"check_t1\",[\"i32:29\"]],[\"module\",1027,12],[\"invoke\",1061,0,\"check_t0\",[\"i32:3\"]],[\"invoke\",1065,0,\"check_t0\",[\"i32:7\"]],[\"invoke\",1069,0,\"check_t0\",[\"i32:11\"]],[\"invoke\",1073,0,\"check_t0\",[\"i32:15\"]],[\"invoke\",1077,0,\"check_t0\",[\"i32:19\"]],[\"invoke\",1082,0,\"check_t0\",[\"i32:24\"]],[\"invoke\",1086,0,\"check_t0\",[\"i32:28\"]],[\"invoke\",1090,0,\"check_t1\",[\"i32:2\"]],[\"invoke\",1094,0,\"check_t1\",[\"i32:6\"]],[\"invoke\",1098,0,\"check_t1\",[\"i32:10\"]],[\"invoke\",1103,0,\"check_t1\",[\"i32:15\"]],[\"invoke\",1107,0,\"check_t1\",[\"i32:19\"]],[\"invoke\",1111,0,\"check_t1\",[\"i32:23\"]],[\"invoke\",1115,0,\"check_t1\",[\"i32:27\"]],[\"module\",1119,13],[\"invoke\",1150,0,\"check_t0\",[\"i32:0\"]],[\"invoke\",1154,0,\"check_t0\",[\"i32:4\"]],[\"invoke\",1159,0,\"check_t0\",[\"i32:9\"]],[\"invoke\",1163,0,\"check_t0\",[\"i32:13\"]],[\"invoke\",1167,0,\"check_t0\",[\"i32:17\"]],[\"invoke\",1171,0,\"check_t0\",[\"i32:21\"]],[\"invoke\",1175,0,\"check_t0\",[\"i32:25\"]],[\"invoke\",1180,0,\"check_t1\",[\"i32:0\"]],[\"invoke\",1184,0,\"check_t1\",[\"i32:4\"]],[\"invoke\",1188,0,\"check_t1\",[\"i32:8\"]],[\"invoke\",1192,0,\"check_t1\",[\"i32:12\"]],[\"invoke\",1196,0,\"check_t1\",[\"i32:16\"]],[\"invoke\",1201,0,\"check_t1\",[\"i32:21\"]],[\"invoke\",1205,0,\"check_t1\",[\"i32:25\"]],[\"invoke\",1209,0,\"check_t1\",[\"i32:29\"]],[\"module\",1211,14],[\"invoke\",1244,0,\"check_t0\",[\"i32:2\"]],[\"invoke\",1248,0,\"check_t0\",[\"i32:6\"]],[\"invoke\",1252,0,\"check_t0\",[\"i32:10\"]],[\"invoke\",1257,0,\"check_t0\",[\"i32:15\"]],[\"invoke\",1261,0,\"check_t0\",[\"i32:19\"]],[\"invoke\",1265,0,\"check_t0\",[\"i32:23\"]],[\"invoke\",1269,0,\"check_t0\",[\"i32:27\"]],[\"invoke\",1273,0,\"check_t1\",[\"i32:1\"]],[\"invoke\",1278,0,\"check_t1\",[\"i32:6\"]],[\"invoke\",1282,0,\"check_t1\",[\"i32:10\"]],[\"invoke\",1286,0,\"check_t1\",[\"i32:14\"]],[\"invoke\",1290,0,\"check_t1\",[\"i32:18\"]],[\"invoke\",1294,0,\"check_t1\",[\"i32:22\"]],[\"invoke\",1299,0,\"check_t1\",[\"i32:27\"]],[\"module\",1303,15],[\"invoke\",1334,0,\"check_t0\",[\"i32:0\"]],[\"invoke\",1338,0,\"check_t0\",[\"i32:4\"]],[\"invoke\",1342,0,\"check_t0\",[\"i32:8\"]],[\"invoke\",1346,0,\"check_t0\",[\"i32:12\"]],[\"invoke\",1350,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",1355,0,\"check_t0\",[\"i32:21\"]],[\"invoke\",1359,0,\"check_t0\",[\"i32:25\"]],[\"invoke\",1363,0,\"check_t0\",[\"i32:29\"]],[\"invoke\",1367,0,\"check_t1\",[\"i32:3\"]],[\"invoke\",1371,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",1376,0,\"check_t1\",[\"i32:12\"]],[\"invoke\",1380,0,\"check_t1\",[\"i32:16\"]],[\"invoke\",1384,0,\"check_t1\",[\"i32:20\"]],[\"invoke\",1388,0,\"check_t1\",[\"i32:24\"]],[\"invoke\",1392,0,\"check_t1\",[\"i32:28\"]],[\"module\",1395,16],[\"invoke\",1428,0,\"check_t0\",[\"i32:2\"]],[\"invoke\",1432,0,\"check_t0\",[\"i32:6\"]],[\"invoke\",1436,0,\"check_t0\",[\"i32:10\"]],[\"invoke\",1440,0,\"check_t0\",[\"i32:14\"]],[\"invoke\",1444,0,\"check_t0\",[\"i32:18\"]],[\"invoke\",1448,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",1453,0,\"check_t0\",[\"i32:27\"]],[\"invoke\",1457,0,\"check_t1\",[\"i32:1\"]],[\"invoke\",1461,0,\"check_t1\",[\"i32:5\"]],[\"invoke\",1465,0,\"check_t1\",[\"i32:9\"]],[\"invoke\",1469,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",1474,0,\"check_t1\",[\"i32:18\"]],[\"invoke\",1478,0,\"check_t1\",[\"i32:22\"]],[\"invoke\",1482,0,\"check_t1\",[\"i32:26\"]],[\"module\",1487,17],[\"invoke\",1517,0,\"test\",[]],[\"invoke\",1521,0,\"check_t0\",[\"i32:3\"]],[\"invoke\",1526,0,\"check_t0\",[\"i32:8\"]],[\"invoke\",1530,0,\"check_t0\",[\"i32:12\"]],[\"invoke\",1534,0,\"check_t0\",[\"i32:16\"]],[\"invoke\",1538,0,\"check_t0\",[\"i32:20\"]],[\"invoke\",1542,0,\"check_t0\",[\"i32:24\"]],[\"invoke\",1546,0,\"check_t0\",[\"i32:28\"]],[\"invoke\",1551,0,\"check_t1\",[\"i32:3\"]],[\"invoke\",1555,0,\"check_t1\",[\"i32:7\"]],[\"invoke\",1559,0,\"check_t1\",[\"i32:11\"]],[\"invoke\",1563,0,\"check_t1\",[\"i32:15\"]],[\"invoke\",1567,0,\"check_t1\",[\"i32:19\"]],[\"invoke\",1572,0,\"check_t1\",[\"i32:24\"]],[\"invoke\",1576,0,\"check_t1\",[\"i32:28\"]],[\"module\",1579,18],[\"invoke\",1611,0,\"check_t0\",[\"i32:1\"]],[\"invoke\",1615,0,\"check_t0\",[\"i32:5\"]],[\"invoke\",1619,0,\"check_t0\",[\"i32:9\"]],[\"invoke\",1624,0,\"check_t0\",[\"i32:14\"]],[\"invoke\",1628,0,\"check_t0\",[\"i32:18\"]],[\"invoke\",1632,0,\"check_t0\",[\"i32:22\"]],[\"invoke\",1636,0,\"check_t0\",[\"i32:26\"]],[\"invoke\",1640,0,\"check_t1\",[\"i32:0\"]],[\"invoke\",1644,0,\"check_t1\",[\"i32:4\"]],[\"invoke\",1649,0,\"check_t1\",[\"i32:9\"]],[\"invoke\",1653,0,\"check_t1\",[\"i32:13\"]],[\"invoke\",1657,0,\"check_t1\",[\"i32:17\"]],[\"invoke\",1661,0,\"check_t1\",[\"i32:21\"]],[\"invoke\",1665,0,\"check_t1\",[\"i32:25\"]],[\"module\",1671,19],[\"invoke\",1694,0,\"test\",[]],[\"module\",1696,20],[\"module\",1721,21],[\"module\",1746,22],[\"module\",1771,23],[\"invoke\",1794,0,\"test\",[]],[\"module\",1796,24],[\"module\",1821,25],[\"module\",1846,26],[\"module\",1871,27],[\"invoke\",1894,0,\"test\",[]],[\"module\",1896,28],[\"module\",1921,29],[\"module\",1946,30],[\"module\",1971,31],[\"invoke\",1994,0,\"test\",[]],[\"module\",1996,32],[\"module\",2021,33],[\"module\",2046,34],[\"module\",2071,35],[\"invoke\",2094,0,\"test\",[]],[\"module\",2096,36],[\"module\",2121,37],[\"module\",2146,38],[\"module\",2171,39],[\"module\",2196,40],[\"invoke\",2219,0,\"test\",[]],[\"module\",2221,41],[\"invoke\",2251,0,\"test\",[\"i32:2\"]],[\"invoke\",2255,0,\"test\",[\"i32:6\"]],[\"invoke\",2259,0,\"test\",[\"i32:10\"]],[\"invoke\",2263,0,\"test\",[\"i32:14\"]],[\"invoke\",2267,0,\"test\",[\"i32:18\"]],[\"invoke\",2272,0,\"test\",[\"i32:23\"]],[\"invoke\",2276,0,\"test\",[\"i32:27\"]],[\"invoke\",2280,0,\"test\",[\"i32:31\"]],[\"module\",2282,42],[\"invoke\",2312,0,\"test\",[\"i32:2\"]],[\"invoke\",2316,0,\"test\",[\"i32:6\"]],[\"invoke\",2321,0,\"test\",[\"i32:11\"]],[\"invoke\",2325,0,\"test\",[\"i32:15\"]],[\"invoke\",2329,0,\"test\",[\"i32:19\"]],[\"invoke\",2333,0,\"test\",[\"i32:23\"]],[\"invoke\",2337,0,\"test\",[\"i32:27\"]],[\"module\",2343,43],[\"invoke\",2369,0,\"run\",[\"i32:0\",\"i32:24\",\"i32:16\"]],[\"invoke\",2374,0,\"test\",[\"i32:3\"]],[\"invoke\",2378,0,\"test\",[\"i32:7\"]],[\"invoke\",2382,0,\"test\",[\"i32:11\"]],[\"invoke\",2386,0,\"test\",[\"i32:15\"]],[\"invoke\",2390,0,\"test\",[\"i32:19\"]],[\"invoke\",2395,0,\"test\",[\"i32:24\"]],[\"invoke\",2399,0,\"test\",[\"i32:28\"]],[\"module\",2404,44],[\"invoke\",2430,0,\"run\",[\"i32:0\",\"i32:23\",\"i32:15\"]],[\"invoke\",2435,0,\"test\",[\"i32:3\"]],[\"invoke\",2439,0,\"test\",[\"i32:7\"]],[\"invoke\",2444,0,\"test\",[\"i32:12\"]],[\"invoke\",2448,0,\"test\",[\"i32:16\"]],[\"invoke\",2452,0,\"test\",[\"i32:20\"]],[\"invoke\",2456,0,\"test\",[\"i32:24\"]],[\"invoke\",2460,0,\"test\",[\"i32:28\"]],[\"module\",2465,45],[\"invoke\",2493,0,\"test\",[\"i32:0\"]],[\"invoke\",2497,0,\"test\",[\"i32:4\"]],[\"invoke\",2501,0,\"test\",[\"i32:8\"]],[\"invoke\",2505,0,\"test\",[\"i32:12\"]],[\"invoke\",2509,0,\"test\",[\"i32:16\"]],[\"invoke\",2513,0,\"test\",[\"i32:20\"]],[\"invoke\",2518,0,\"test\",[\"i32:25\"]],[\"invoke\",2522,0,\"test\",[\"i32:29\"]],[\"module\",2526,43],[\"invoke\",2554,0,\"test\",[\"i32:0\"]],[\"invoke\",2558,0,\"test\",[\"i32:4\"]],[\"invoke\",2562,0,\"test\",[\"i32:8\"]],[\"invoke\",2567,0,\"test\",[\"i32:13\"]],[\"invoke\",2571,0,\"test\",[\"i32:17\"]],[\"invoke\",2575,0,\"test\",[\"i32:21\"]],[\"invoke\",2579,0,\"test\",[\"i32:25\"]],[\"invoke\",2583,0,\"test\",[\"i32:29\"]],[\"module\",2587,46],[\"invoke\",2616,0,\"test\",[\"i32:1\"]],[\"invoke\",2620,0,\"test\",[\"i32:5\"]],[\"invoke\",2624,0,\"test\",[\"i32:9\"]],[\"invoke\",2628,0,\"test\",[\"i32:13\"]],[\"invoke\",2632,0,\"test\",[\"i32:17\"]],[\"invoke\",2636,0,\"test\",[\"i32:21\"]],[\"invoke\",2641,0,\"test\",[\"i32:26\"]],[\"invoke\",2645,0,\"test\",[\"i32:30\"]],[\"module\",2648,43],[\"invoke\",2677,0,\"test\",[\"i32:1\"]],[\"invoke\",2681,0,\"test\",[\"i32:5\"]],[\"invoke\",2685,0,\"test\",[\"i32:9\"]],[\"invoke\",2690,0,\"test\",[\"i32:14\"]],[\"invoke\",2694,0,\"test\",[\"i32:18\"]],[\"invoke\",2698,0,\"test\",[\"i32:22\"]],[\"invoke\",2702,0,\"test\",[\"i32:26\"]],[\"invoke\",2706,0,\"test\",[\"i32:30\"]],[\"module\",2709,47],[\"invoke\",2739,0,\"test\",[\"i32:2\"]],[\"invoke\",2743,0,\"test\",[\"i32:6\"]],[\"invoke\",2747,0,\"test\",[\"i32:10\"]],[\"invoke\",2751,0,\"test\",[\"i32:14\"]],[\"invoke\",2755,0,\"test\",[\"i32:18\"]],[\"invoke\",2759,0,\"test\",[\"i32:22\"]],[\"invoke\",2764,0,\"test\",[\"i32:27\"]],[\"invoke\",2768,0,\"test\",[\"i32:31\"]],[\"module\",2770,48],[\"invoke\",2800,0,\"test\",[\"i32:2\"]],[\"invoke\",2804,0,\"test\",[\"i32:6\"]],[\"invoke\",2808,0,\"test\",[\"i32:10\"]],[\"invoke\",2813,0,\"test\",[\"i32:15\"]],[\"invoke\",2817,0,\"test\",[\"i32:19\"]],[\"invoke\",2821,0,\"test\",[\"i32:23\"]],[\"invoke\",2825,0,\"test\",[\"i32:27\"]],[\"invoke\",2829,0,\"test\",[\"i32:31\"]],[\"invoke\",2834,0,\"test\",[\"i32:36\"]],[\"invoke\",2838,0,\"test\",[\"i32:40\"]],[\"invoke\",2842,0,\"test\",[\"i32:44\"]],[\"invoke\",2846,0,\"test\",[\"i32:48\"]],[\"invoke\",2850,0,\"test\",[\"i32:52\"]],[\"invoke\",2854,0,\"test\",[\"i32:56\"]],[\"invoke\",2859,0,\"test\",[\"i32:61\"]],[\"invoke\",2863,0,\"test\",[\"i32:65\"]],[\"invoke\",2867,0,\"test\",[\"i32:69\"]],[\"invoke\",2871,0,\"test\",[\"i32:73\"]],[\"invoke\",2875,0,\"test\",[\"i32:77\"]],[\"invoke\",2880,0,\"test\",[\"i32:82\"]],[\"invoke\",2884,0,\"test\",[\"i32:86\"]],[\"invoke\",2888,0,\"test\",[\"i32:90\"]],[\"invoke\",2892,0,\"test\",[\"i32:94\"]],[\"invoke\",2896,0,\"test\",[\"i32:98\"]],[\"invoke\",2901,0,\"test\",[\"i32:103\"]],[\"invoke\",2905,0,\"test\",[\"i32:107\"]],[\"invoke\",2909,0,\"test\",[\"i32:111\"]],[\"invoke\",2913,0,\"test\",[\"i32:115\"]],[\"invoke\",2917,0,\"test\",[\"i32:119\"]],[\"invoke\",2921,0,\"test\",[\"i32:123\"]],[\"module\",2927,49],[\"invoke\",2953,0,\"run\",[\"i32:112\",\"i32:0\",\"i32:4294967264\"]],[\"invoke\",2958,0,\"test\",[\"i32:3\"]],[\"invoke\",2962,0,\"test\",[\"i32:7\"]],[\"invoke\",2966,0,\"test\",[\"i32:11\"]],[\"invoke\",2970,0,\"test\",[\"i32:15\"]],[\"invoke\",2975,0,\"test\",[\"i32:20\"]],[\"invoke\",2979,0,\"test\",[\"i32:24\"]],[\"invoke\",2983,0,\"test\",[\"i32:28\"]],[\"invoke\",2987,0,\"test\",[\"i32:32\"]],[\"invoke\",2991,0,\"test\",[\"i32:36\"]],[\"invoke\",2996,0,\"test\",[\"i32:41\"]],[\"invoke\",3000,0,\"test\",[\"i32:45\"]],[\"invoke\",3004,0,\"test\",[\"i32:49\"]],[\"invoke\",3008,0,\"test\",[\"i32:53\"]],[\"invoke\",3012,0,\"test\",[\"i32:57\"]],[\"invoke\",3016,0,\"test\",[\"i32:61\"]],[\"invoke\",3021,0,\"test\",[\"i32:66\"]],[\"invoke\",3025,0,\"test\",[\"i32:70\"]],[\"invoke\",3029,0,\"test\",[\"i32:74\"]],[\"invoke\",3033,0,\"test\",[\"i32:78\"]],[\"invoke\",3037,0,\"test\",[\"i32:82\"]],[\"invoke\",3042,0,\"test\",[\"i32:87\"]],[\"invoke\",3046,0,\"test\",[\"i32:91\"]],[\"invoke\",3050,0,\"test\",[\"i32:95\"]],[\"invoke\",3054,0,\"test\",[\"i32:99\"]],[\"invoke\",3058,0,\"test\",[\"i32:103\"]],[\"invoke\",3063,0,\"test\",[\"i32:108\"]],[\"invoke\",3067,0,\"test\",[\"i32:112\"]],[\"invoke\",3071,0,\"test\",[\"i32:116\"]],[\"invoke\",3075,0,\"test\",[\"i32:120\"]],[\"invoke\",3079,0,\"test\",[\"i32:124\"]],[\"file\",\"table_fill.wast\"],[\"module\",1,50],[\"invoke\",17,0,\"get\",[\"i32:1\"]],[\"invoke\",18,0,\"get\",[\"i32:2\"]],[\"invoke\",19,0,\"get\",[\"i32:3\"]],[\"invoke\",20,0,\"get\",[\"i32:4\"]],[\"invoke\",21,0,\"get\",[\"i32:5\"]],[\"invoke\",23,0,\"fill\",[\"i32:2\",\"externref:1\",\"i32:3\"]],[\"invoke\",24,0,\"get\",[\"i32:1\"]],[\"invoke\",25,0,\"get\",[\"i32:2\"]],[\"invoke\",26,0,\"get\",[\"i32:3\"]],[\"invoke\",27,0,\"get\",[\"i32:4\"]],[\"invoke\",28,0,\"get\",[\"i32:5\"]],[\"invoke\",30,0,\"fill\",[\"i32:4\",\"externref:2\",\"i32:2\"]],[\"invoke\",31,0,\"get\",[\"i32:3\"]],[\"invoke\",32,0,\"get\",[\"i32:4\"]],[\"invoke\",33,0,\"get\",[\"i32:5\"]],[\"invoke\",34,0,\"get\",[\"i32:6\"]],[\"invoke\",36,0,\"fill\",[\"i32:4\",\"externref:3\",\"i32:0\"]],[\"invoke\",37,0,\"get\",[\"i32:3\"]],[\"invoke\",38,0,\"get\",[\"i32:4\"]],[\"invoke\",39,0,\"get\",[\"i32:5\"]],[\"invoke\",41,0,\"fill\",[\"i32:8\",\"externref:4\",\"i32:2\"]],[\"invoke\",42,0,\"get\",[\"i32:7\"]],[\"invoke\",43,0,\"get\",[\"i32:8\"]],[\"invoke\",44,0,\"get\",[\"i32:9\"]],[\"invoke\",46,0,\"fill-abbrev\",[\"i32:9\",\"externref:null\",\"i32:1\"]],[\"invoke\",47,0,\"get\",[\"i32:8\"]],[\"invoke\",48,0,\"get\",[\"i32:9\"]],[\"invoke\",50,0,\"fill\",[\"i32:10\",\"externref:5\",\"i32:0\"]],[\"invoke\",51,0,\"get\",[\"i32:9\"]],[\"invoke\",54,0,\"fill\",[\"i32:8\",\"externref:6\",\"i32:3\"]],[\"invoke\",57,0,\"get\",[\"i32:7\"]],[\"invoke\",58,0,\"get\",[\"i32:8\"]],[\"invoke\",59,0,\"get\",[\"i32:9\"]],[\"invoke\",62,0,\"fill\",[\"i32:11\",\"externref:null\",\"i32:0\"]],[\"invoke\",67,0,\"fill\",[\"i32:11\",\"externref:null\",\"i32:10\"]],[\"file\",\"table_get.wast\"],[\"module\",1,51],[\"invoke\",24,0,\"init\",[\"externref:1\"]],[\"invoke\",26,0,\"get-externref\",[\"i32:0\"]],[\"invoke\",27,0,\"get-externref\",[\"i32:1\"]],[\"invoke\",29,0,\"get-funcref\",[\"i32:0\"]],[\"invoke\",30,0,\"is_null-funcref\",[\"i32:1\"]],[\"invoke\",31,0,\"is_null-funcref\",[\"i32:2\"]],[\"invoke\",33,0,\"get-externref\",[\"i32:2\"]],[\"invoke\",34,0,\"get-funcref\",[\"i32:3\"]],[\"invoke\",35,0,\"get-externref\",[\"i32:4294967295\"]],[\"invoke\",36,0,\"get-funcref\",[\"i32:4294967295\"]],[\"file\",\"table_grow.wast\"],[\"module\",1,52],[\"invoke\",16,0,\"size\",[]],[\"invoke\",17,0,\"set\",[\"i32:0\",\"externref:2\"]],[\"invoke\",18,0,\"get\",[\"i32:0\"]],[\"invoke\",20,0,\"grow\",[\"i32:1\",\"externref:null\"]],[\"invoke\",21,0,\"size\",[]],[\"invoke\",22,0,\"get\",[\"i32:0\"]],[\"invoke\",23,0,\"set\",[\"i32:0\",\"externref:2\"]],[\"invoke\",24,0,\"get\",[\"i32:0\"]],[\"invoke\",25,0,\"set\",[\"i32:1\",\"externref:2\"]],[\"invoke\",26,0,\"get\",[\"i32:1\"]],[\"invoke\",28,0,\"grow-abbrev\",[\"i32:4\",\"externref:3\"]],[\"invoke\",29,0,\"size\",[]],[\"invoke\",30,0,\"get\",[\"i32:0\"]],[\"invoke\",31,0,\"set\",[\"i32:0\",\"externref:2\"]],[\"invoke\",32,0,\"get\",[\"i32:0\"]],[\"invoke\",33,0,\"get\",[\"i32:1\"]],[\"invoke\",34,0,\"get\",[\"i32:4\"]],[\"invoke\",35,0,\"set\",[\"i32:4\",\"externref:4\"]],[\"invoke\",36,0,\"get\",[\"i32:4\"]],[\"invoke\",37,0,\"set\",[\"i32:5\",\"externref:2\"]],[\"invoke\",38,0,\"get\",[\"i32:5\"]],[\"module\",42,53],[\"invoke\",50,0,\"grow\",[]],[\"module\",53,54],[\"invoke\",60,0,\"grow\",[\"i32:0\"]],[\"invoke\",61,0,\"grow\",[\"i32:1\"]],[\"invoke\",62,0,\"grow\",[\"i32:0\"]],[\"invoke\",63,0,\"grow\",[\"i32:2\"]],[\"invoke\",64,0,\"grow\",[\"i32:800\"]],[\"module\",67,55],[\"invoke\",74,0,\"grow\",[\"i32:0\"]],[\"invoke\",75,0,\"grow\",[\"i32:1\"]],[\"invoke\",76,0,\"grow\",[\"i32:1\"]],[\"invoke\",77,0,\"grow\",[\"i32:2\"]],[\"invoke\",78,0,\"grow\",[\"i32:6\"]],[\"invoke\",79,0,\"grow\",[\"i32:0\"]],[\"invoke\",80,0,\"grow\",[\"i32:1\"]],[\"invoke\",81,0,\"grow\",[\"i32:65536\"]],[\"module\",84,56],[\"invoke\",106,0,\"check-table-null\",[\"i32:0\",\"i32:9\"]],[\"invoke\",107,0,\"grow\",[\"i32:10\"]],[\"invoke\",108,0,\"check-table-null\",[\"i32:0\",\"i32:19\"]],[\"module\",111,57,\"$Tgt\"],[\"register\",\"grown-table\",\"$Tgt\"],[\"invoke\",116,\"$Tgt\",\"grow\",[]],[\"module\",117,58,\"$Tgit1\"],[\"register\",\"grown-imported-table\",\"$Tgit1\"],[\"invoke\",123,\"$Tgit1\",\"grow\",[]],[\"module\",124,59,\"$Tgit2\"],[\"invoke\",129,\"$Tgit2\",\"size\",[]],[\"file\",\"table_init.wast\"],[\"module\",6,0],[\"register\",\"a\"],[\"module\",15,60],[\"invoke\",41,0,\"test\",[]],[\"invoke\",43,0,\"check\",[\"i32:1\"]],[\"invoke\",45,0,\"check\",[\"i32:3\"]],[\"invoke\",47,0,\"check\",[\"i32:5\"]],[\"invoke\",48,0,\"check\",[\"i32:6\"]],[\"invoke\",50,0,\"check\",[\"i32:8\"]],[\"invoke\",52,0,\"check\",[\"i32:10\"]],[\"invoke\",53,0,\"check\",[\"i32:11\"]],[\"invoke\",55,0,\"check\",[\"i32:13\"]],[\"invoke\",57,0,\"check\",[\"i32:15\"]],[\"invoke\",58,0,\"check\",[\"i32:16\"]],[\"invoke\",60,0,\"check\",[\"i32:18\"]],[\"invoke\",62,0,\"check\",[\"i32:20\"]],[\"invoke\",64,0,\"check\",[\"i32:22\"]],[\"invoke\",65,0,\"check\",[\"i32:23\"]],[\"invoke\",67,0,\"check\",[\"i32:25\"]],[\"invoke\",69,0,\"check\",[\"i32:27\"]],[\"invoke\",70,0,\"check\",[\"i32:28\"]],[\"module\",73,61],[\"invoke\",99,0,\"test\",[]],[\"invoke\",101,0,\"check\",[\"i32:1\"]],[\"invoke\",102,0,\"check\",[\"i32:2\"]],[\"invoke\",104,0,\"check\",[\"i32:4\"]],[\"invoke\",106,0,\"check\",[\"i32:6\"]],[\"invoke\",107,0,\"check\",[\"i32:7\"]],[\"invoke\",109,0,\"check\",[\"i32:9\"]],[\"invoke\",111,0,\"check\",[\"i32:11\"]],[\"invoke\",113,0,\"check\",[\"i32:13\"]],[\"invoke\",114,0,\"check\",[\"i32:14\"]],[\"invoke\",116,0,\"check\",[\"i32:16\"]],[\"invoke\",118,0,\"check\",[\"i32:18\"]],[\"invoke\",119,0,\"check\",[\"i32:19\"]],[\"invoke\",121,0,\"check\",[\"i32:21\"]],[\"invoke\",123,0,\"check\",[\"i32:23\"]],[\"invoke\",124,0,\"check\",[\"i32:24\"]],[\"invoke\",126,0,\"check\",[\"i32:26\"]],[\"invoke\",128,0,\"check\",[\"i32:28\"]],[\"invoke\",129,0,\"check\",[\"i32:29\"]],[\"module\",131,62],[\"invoke\",166,0,\"check\",[\"i32:0\"]],[\"invoke\",168,0,\"check\",[\"i32:2\"]],[\"invoke\",170,0,\"check\",[\"i32:4\"]],[\"invoke\",171,0,\"check\",[\"i32:5\"]],[\"invoke\",173,0,\"check\",[\"i32:7\"]],[\"invoke\",175,0,\"check\",[\"i32:9\"]],[\"invoke\",176,0,\"check\",[\"i32:10\"]],[\"invoke\",178,0,\"check\",[\"i32:12\"]],[\"invoke\",180,0,\"check\",[\"i32:14\"]],[\"invoke\",181,0,\"check\",[\"i32:15\"]],[\"invoke\",183,0,\"check\",[\"i32:17\"]],[\"invoke\",185,0,\"check\",[\"i32:19\"]],[\"invoke\",186,0,\"check\",[\"i32:20\"]],[\"invoke\",188,0,\"check\",[\"i32:22\"]],[\"invoke\",190,0,\"check\",[\"i32:24\"]],[\"invoke\",192,0,\"check\",[\"i32:26\"]],[\"invoke\",193,0,\"check\",[\"i32:27\"]],[\"invoke\",195,0,\"check\",[\"i32:29\"]],[\"module\",197,63],[\"invoke\",224,0,\"check\",[\"i32:0\"]],[\"invoke\",225,0,\"check\",[\"i32:1\"]],[\"invoke\",227,0,\"check\",[\"i32:3\"]],[\"invoke\",229,0,\"check\",[\"i32:5\"]],[\"invoke\",230,0,\"check\",[\"i32:6\"]],[\"invoke\",232,0,\"check\",[\"i32:8\"]],[\"invoke\",234,0,\"check\",[\"i32:10\"]],[\"invoke\",235,0,\"check\",[\"i32:11\"]],[\"invoke\",237,0,\"check\",[\"i32:13\"]],[\"invoke\",239,0,\"check\",[\"i32:15\"]],[\"invoke\",241,0,\"check\",[\"i32:17\"]],[\"invoke\",242,0,\"check\",[\"i32:18\"]],[\"invoke\",244,0,\"check\",[\"i32:20\"]],[\"invoke\",246,0,\"check\",[\"i32:22\"]],[\"invoke\",247,0,\"check\",[\"i32:23\"]],[\"invoke\",249,0,\"check\",[\"i32:25\"]],[\"invoke\",251,0,\"check\",[\"i32:27\"]],[\"invoke\",252,0,\"check\",[\"i32:28\"]],[\"module\",255,64],[\"invoke\",281,0,\"test\",[]],[\"invoke\",283,0,\"check\",[\"i32:1\"]],[\"invoke\",284,0,\"check\",[\"i32:2\"]],[\"invoke\",286,0,\"check\",[\"i32:4\"]],[\"invoke\",288,0,\"check\",[\"i32:6\"]],[\"invoke\",290,0,\"check\",[\"i32:8\"]],[\"invoke\",291,0,\"check\",[\"i32:9\"]],[\"invoke\",293,0,\"check\",[\"i32:11\"]],[\"invoke\",295,0,\"check\",[\"i32:13\"]],[\"invoke\",296,0,\"check\",[\"i32:14\"]],[\"invoke\",298,0,\"check\",[\"i32:16\"]],[\"invoke\",300,0,\"check\",[\"i32:18\"]],[\"invoke\",301,0,\"check\",[\"i32:19\"]],[\"invoke\",303,0,\"check\",[\"i32:21\"]],[\"invoke\",305,0,\"check\",[\"i32:23\"]],[\"invoke\",306,0,\"check\",[\"i32:24\"]],[\"invoke\",308,0,\"check\",[\"i32:26\"]],[\"invoke\",310,0,\"check\",[\"i32:28\"]],[\"module\",313,65],[\"invoke\",347,0,\"test\",[]],[\"invoke\",348,0,\"check\",[\"i32:0\"]],[\"invoke\",350,0,\"check\",[\"i32:2\"]],[\"invoke\",352,0,\"check\",[\"i32:4\"]],[\"invoke\",353,0,\"check\",[\"i32:5\"]],[\"invoke\",355,0,\"check\",[\"i32:7\"]],[\"invoke\",357,0,\"check\",[\"i32:9\"]],[\"invoke\",358,0,\"check\",[\"i32:10\"]],[\"invoke\",360,0,\"check\",[\"i32:12\"]],[\"invoke\",362,0,\"check\",[\"i32:14\"]],[\"invoke\",363,0,\"check\",[\"i32:15\"]],[\"invoke\",365,0,\"check\",[\"i32:17\"]],[\"invoke\",367,0,\"check\",[\"i32:19\"]],[\"invoke\",369,0,\"check\",[\"i32:21\"]],[\"invoke\",370,0,\"check\",[\"i32:22\"]],[\"invoke\",372,0,\"check\",[\"i32:24\"]],[\"invoke\",374,0,\"check\",[\"i32:26\"]],[\"invoke\",375,0,\"check\",[\"i32:27\"]],[\"invoke\",377,0,\"check\",[\"i32:29\"]],[\"module\",407,66],[\"module\",431,67],[\"invoke\",453,0,\"test\",[]],[\"module\",455,68],[\"invoke\",477,0,\"test\",[]],[\"module\",479,69],[\"module\",503,70],[\"invoke\",525,0,\"test\",[]],[\"module\",527,71],[\"module\",551,72],[\"invoke\",573,0,\"test\",[]],[\"module\",575,73],[\"invoke\",597,0,\"test\",[]],[\"module\",599,74],[\"module\",623,75],[\"invoke\",645,0,\"test\",[]],[\"module\",647,76],[\"module\",671,77],[\"invoke\",693,0,\"test\",[]],[\"module\",695,78],[\"module\",719,79],[\"invoke\",741,0,\"test\",[]],[\"module\",743,80],[\"invoke\",765,0,\"test\",[]],[\"module\",767,81],[\"module\",791,82],[\"invoke\",813,0,\"test\",[]],[\"module\",815,83],[\"module\",839,84],[\"invoke\",861,0,\"test\",[]],[\"module\",863,85],[\"invoke\",885,0,\"test\",[]],[\"module\",887,86],[\"module\",1478,87],[\"invoke\",1506,0,\"run\",[\"i32:24\",\"i32:16\"]],[\"invoke\",1508,0,\"test\",[\"i32:1\"]],[\"invoke\",1509,0,\"test\",[\"i32:2\"]],[\"invoke\",1511,0,\"test\",[\"i32:4\"]],[\"invoke\",1513,0,\"test\",[\"i32:6\"]],[\"invoke\",1514,0,\"test\",[\"i32:7\"]],[\"invoke\",1516,0,\"test\",[\"i32:9\"]],[\"invoke\",1518,0,\"test\",[\"i32:11\"]],[\"invoke\",1520,0,\"test\",[\"i32:13\"]],[\"invoke\",1521,0,\"test\",[\"i32:14\"]],[\"invoke\",1523,0,\"test\",[\"i32:16\"]],[\"invoke\",1525,0,\"test\",[\"i32:18\"]],[\"invoke\",1526,0,\"test\",[\"i32:19\"]],[\"invoke\",1528,0,\"test\",[\"i32:21\"]],[\"invoke\",1530,0,\"test\",[\"i32:23\"]],[\"invoke\",1531,0,\"test\",[\"i32:24\"]],[\"invoke\",1533,0,\"test\",[\"i32:26\"]],[\"invoke\",1535,0,\"test\",[\"i32:28\"]],[\"invoke\",1536,0,\"test\",[\"i32:29\"]],[\"invoke\",1538,0,\"test\",[\"i32:31\"]],[\"module\",1540,87],[\"invoke\",1569,0,\"test\",[\"i32:0\"]],[\"invoke\",1571,0,\"test\",[\"i32:2\"]],[\"invoke\",1572,0,\"test\",[\"i32:3\"]],[\"invoke\",1574,0,\"test\",[\"i32:5\"]],[\"invoke\",1576,0,\"test\",[\"i32:7\"]],[\"invoke\",1577,0,\"test\",[\"i32:8\"]],[\"invoke\",1579,0,\"test\",[\"i32:10\"]],[\"invoke\",1581,0,\"test\",[\"i32:12\"]],[\"invoke\",1582,0,\"test\",[\"i32:13\"]],[\"invoke\",1584,0,\"test\",[\"i32:15\"]],[\"invoke\",1586,0,\"test\",[\"i32:17\"]],[\"invoke\",1587,0,\"test\",[\"i32:18\"]],[\"invoke\",1589,0,\"test\",[\"i32:20\"]],[\"invoke\",1591,0,\"test\",[\"i32:22\"]],[\"invoke\",1593,0,\"test\",[\"i32:24\"]],[\"invoke\",1594,0,\"test\",[\"i32:25\"]],[\"invoke\",1596,0,\"test\",[\"i32:27\"]],[\"invoke\",1598,0,\"test\",[\"i32:29\"]],[\"invoke\",1599,0,\"test\",[\"i32:30\"]],[\"module\",1602,88],[\"invoke\",1630,0,\"run\",[\"i32:96\",\"i32:32\"]],[\"invoke\",1632,0,\"test\",[\"i32:1\"]],[\"invoke\",1633,0,\"test\",[\"i32:2\"]],[\"invoke\",1635,0,\"test\",[\"i32:4\"]],[\"invoke\",1637,0,\"test\",[\"i32:6\"]],[\"invoke\",1638,0,\"test\",[\"i32:7\"]],[\"invoke\",1640,0,\"test\",[\"i32:9\"]],[\"invoke\",1642,0,\"test\",[\"i32:11\"]],[\"invoke\",1644,0,\"test\",[\"i32:13\"]],[\"invoke\",1645,0,\"test\",[\"i32:14\"]],[\"invoke\",1647,0,\"test\",[\"i32:16\"]],[\"invoke\",1649,0,\"test\",[\"i32:18\"]],[\"invoke\",1650,0,\"test\",[\"i32:19\"]],[\"invoke\",1652,0,\"test\",[\"i32:21\"]],[\"invoke\",1654,0,\"test\",[\"i32:23\"]],[\"invoke\",1655,0,\"test\",[\"i32:24\"]],[\"invoke\",1657,0,\"test\",[\"i32:26\"]],[\"invoke\",1659,0,\"test\",[\"i32:28\"]],[\"invoke\",1660,0,\"test\",[\"i32:29\"]],[\"invoke\",1662,0,\"test\",[\"i32:31\"]],[\"invoke\",1664,0,\"test\",[\"i32:33\"]],[\"invoke\",1666,0,\"test\",[\"i32:35\"]],[\"invoke\",1667,0,\"test\",[\"i32:36\"]],[\"invoke\",1669,0,\"test\",[\"i32:38\"]],[\"invoke\",1671,0,\"test\",[\"i32:40\"]],[\"invoke\",1672,0,\"test\",[\"i32:41\"]],[\"invoke\",1674,0,\"test\",[\"i32:43\"]],[\"invoke\",1676,0,\"test\",[\"i32:45\"]],[\"invoke\",1677,0,\"test\",[\"i32:46\"]],[\"invoke\",1679,0,\"test\",[\"i32:48\"]],[\"invoke\",1681,0,\"test\",[\"i32:50\"]],[\"invoke\",1682,0,\"test\",[\"i32:51\"]],[\"invoke\",1684,0,\"test\",[\"i32:53\"]],[\"invoke\",1686,0,\"test\",[\"i32:55\"]],[\"invoke\",1688,0,\"test\",[\"i32:57\"]],[\"invoke\",1689,0,\"test\",[\"i32:58\"]],[\"invoke\",1691,0,\"test\",[\"i32:60\"]],[\"invoke\",1693,0,\"test\",[\"i32:62\"]],[\"invoke\",1694,0,\"test\",[\"i32:63\"]],[\"invoke\",1696,0,\"test\",[\"i32:65\"]],[\"invoke\",1698,0,\"test\",[\"i32:67\"]],[\"invoke\",1699,0,\"test\",[\"i32:68\"]],[\"invoke\",1701,0,\"test\",[\"i32:70\"]],[\"invoke\",1703,0,\"test\",[\"i32:72\"]],[\"invoke\",1704,0,\"test\",[\"i32:73\"]],[\"invoke\",1706,0,\"test\",[\"i32:75\"]],[\"invoke\",1708,0,\"test\",[\"i32:77\"]],[\"invoke\",1710,0,\"test\",[\"i32:79\"]],[\"invoke\",1711,0,\"test\",[\"i32:80\"]],[\"invoke\",1713,0,\"test\",[\"i32:82\"]],[\"invoke\",1715,0,\"test\",[\"i32:84\"]],[\"invoke\",1716,0,\"test\",[\"i32:85\"]],[\"invoke\",1718,0,\"test\",[\"i32:87\"]],[\"invoke\",1720,0,\"test\",[\"i32:89\"]],[\"invoke\",1721,0,\"test\",[\"i32:90\"]],[\"invoke\",1723,0,\"test\",[\"i32:92\"]],[\"invoke\",1725,0,\"test\",[\"i32:94\"]],[\"invoke\",1726,0,\"test\",[\"i32:95\"]],[\"invoke\",1728,0,\"test\",[\"i32:97\"]],[\"invoke\",1730,0,\"test\",[\"i32:99\"]],[\"invoke\",1732,0,\"test\",[\"i32:101\"]],[\"invoke\",1733,0,\"test\",[\"i32:102\"]],[\"invoke\",1735,0,\"test\",[\"i32:104\"]],[\"invoke\",1737,0,\"test\",[\"i32:106\"]],[\"invoke\",1738,0,\"test\",[\"i32:107\"]],[\"invoke\",1740,0,\"test\",[\"i32:109\"]],[\"invoke\",1742,0,\"test\",[\"i32:111\"]],[\"invoke\",1743,0,\"test\",[\"i32:112\"]],[\"invoke\",1745,0,\"test\",[\"i32:114\"]],[\"invoke\",1747,0,\"test\",[\"i32:116\"]],[\"invoke\",1748,0,\"test\",[\"i32:117\"]],[\"invoke\",1750,0,\"test\",[\"i32:119\"]],[\"invoke\",1752,0,\"test\",[\"i32:121\"]],[\"invoke\",1754,0,\"test\",[\"i32:123\"]],[\"invoke\",1755,0,\"test\",[\"i32:124\"]],[\"invoke\",1757,0,\"test\",[\"i32:126\"]],[\"invoke\",1759,0,\"test\",[\"i32:128\"]],[\"invoke\",1760,0,\"test\",[\"i32:129\"]],[\"invoke\",1762,0,\"test\",[\"i32:131\"]],[\"invoke\",1764,0,\"test\",[\"i32:133\"]],[\"invoke\",1765,0,\"test\",[\"i32:134\"]],[\"invoke\",1767,0,\"test\",[\"i32:136\"]],[\"invoke\",1769,0,\"test\",[\"i32:138\"]],[\"invoke\",1770,0,\"test\",[\"i32:139\"]],[\"invoke\",1772,0,\"test\",[\"i32:141\"]],[\"invoke\",1774,0,\"test\",[\"i32:143\"]],[\"invoke\",1776,0,\"test\",[\"i32:145\"]],[\"invoke\",1777,0,\"test\",[\"i32:146\"]],[\"invoke\",1779,0,\"test\",[\"i32:148\"]],[\"invoke\",1781,0,\"test\",[\"i32:150\"]],[\"invoke\",1782,0,\"test\",[\"i32:151\"]],[\"invoke\",1784,0,\"test\",[\"i32:153\"]],[\"invoke\",1786,0,\"test\",[\"i32:155\"]],[\"invoke\",1787,0,\"test\",[\"i32:156\"]],[\"invoke\",1789,0,\"test\",[\"i32:158\"]],[\"module\",1792,88],[\"invoke\",1820,0,\"run\",[\"i32:97\",\"i32:31\"]],[\"invoke\",1821,0,\"test\",[\"i32:0\"]],[\"invoke\",1823,0,\"test\",[\"i32:2\"]],[\"invoke\",1825,0,\"test\",[\"i32:4\"]],[\"invoke\",1827,0,\"test\",[\"i32:6\"]],[\"invoke\",1828,0,\"test\",[\"i32:7\"]],[\"invoke\",1830,0,\"test\",[\"i32:9\"]],[\"invoke\",1832,0,\"test\",[\"i32:11\"]],[\"invoke\",1833,0,\"test\",[\"i32:12\"]],[\"invoke\",1835,0,\"test\",[\"i32:14\"]],[\"invoke\",1837,0,\"test\",[\"i32:16\"]],[\"invoke\",1838,0,\"test\",[\"i32:17\"]],[\"invoke\",1840,0,\"test\",[\"i32:19\"]],[\"invoke\",1842,0,\"test\",[\"i32:21\"]],[\"invoke\",1843,0,\"test\",[\"i32:22\"]],[\"invoke\",1845,0,\"test\",[\"i32:24\"]],[\"invoke\",1847,0,\"test\",[\"i32:26\"]],[\"invoke\",1849,0,\"test\",[\"i32:28\"]],[\"invoke\",1850,0,\"test\",[\"i32:29\"]],[\"invoke\",1852,0,\"test\",[\"i32:31\"]],[\"invoke\",1854,0,\"test\",[\"i32:33\"]],[\"invoke\",1855,0,\"test\",[\"i32:34\"]],[\"invoke\",1857,0,\"test\",[\"i32:36\"]],[\"invoke\",1859,0,\"test\",[\"i32:38\"]],[\"invoke\",1860,0,\"test\",[\"i32:39\"]],[\"invoke\",1862,0,\"test\",[\"i32:41\"]],[\"invoke\",1864,0,\"test\",[\"i32:43\"]],[\"invoke\",1865,0,\"test\",[\"i32:44\"]],[\"invoke\",1867,0,\"test\",[\"i32:46\"]],[\"invoke\",1869,0,\"test\",[\"i32:48\"]],[\"invoke\",1871,0,\"test\",[\"i32:50\"]],[\"invoke\",1872,0,\"test\",[\"i32:51\"]],[\"invoke\",1874,0,\"test\",[\"i32:53\"]],[\"invoke\",1876,0,\"test\",[\"i32:55\"]],[\"invoke\",1877,0,\"test\",[\"i32:56\"]],[\"invoke\",1879,0,\"test\",[\"i32:58\"]],[\"invoke\",1881,0,\"test\",[\"i32:60\"]],[\"invoke\",1882,0,\"test\",[\"i32:61\"]],[\"invoke\",1884,0,\"test\",[\"i32:63\"]],[\"invoke\",1886,0,\"test\",[\"i32:65\"]],[\"invoke\",1887,0,\"test\",[\"i32:66\"]],[\"invoke\",1889,0,\"test\",[\"i32:68\"]],[\"invoke\",1891,0,\"test\",[\"i32:70\"]],[\"invoke\",1893,0,\"test\",[\"i32:72\"]],[\"invoke\",1894,0,\"test\",[\"i32:73\"]],[\"invoke\",1896,0,\"test\",[\"i32:75\"]],[\"invoke\",1898,0,\"test\",[\"i32:77\"]],[\"invoke\",1899,0,\"test\",[\"i32:78\"]],[\"invoke\",1901,0,\"test\",[\"i32:80\"]],[\"invoke\",1903,0,\"test\",[\"i32:82\"]],[\"invoke\",1904,0,\"test\",[\"i32:83\"]],[\"invoke\",1906,0,\"test\",[\"i32:85\"]],[\"invoke\",1908,0,\"test\",[\"i32:87\"]],[\"invoke\",1909,0,\"test\",[\"i32:88\"]],[\"invoke\",1911,0,\"test\",[\"i32:90\"]],[\"invoke\",1913,0,\"test\",[\"i32:92\"]],[\"invoke\",1915,0,\"test\",[\"i32:94\"]],[\"invoke\",1916,0,\"test\",[\"i32:95\"]],[\"invoke\",1918,0,\"test\",[\"i32:97\"]],[\"invoke\",1920,0,\"test\",[\"i32:99\"]],[\"invoke\",1921,0,\"test\",[\"i32:100\"]],[\"invoke\",1923,0,\"test\",[\"i32:102\"]],[\"invoke\",1925,0,\"test\",[\"i32:104\"]],[\"invoke\",1926,0,\"test\",[\"i32:105\"]],[\"invoke\",1928,0,\"test\",[\"i32:107\"]],[\"invoke\",1930,0,\"test\",[\"i32:109\"]],[\"invoke\",1931,0,\"test\",[\"i32:110\"]],[\"invoke\",1933,0,\"test\",[\"i32:112\"]],[\"invoke\",1935,0,\"test\",[\"i32:114\"]],[\"invoke\",1937,0,\"test\",[\"i32:116\"]],[\"invoke\",1938,0,\"test\",[\"i32:117\"]],[\"invoke\",1940,0,\"test\",[\"i32:119\"]],[\"invoke\",1942,0,\"test\",[\"i32:121\"]],[\"invoke\",1943,0,\"test\",[\"i32:122\"]],[\"invoke\",1945,0,\"test\",[\"i32:124\"]],[\"invoke\",1947,0,\"test\",[\"i32:126\"]],[\"invoke\",1948,0,\"test\",[\"i32:127\"]],[\"invoke\",1950,0,\"test\",[\"i32:129\"]],[\"invoke\",1952,0,\"test\",[\"i32:131\"]],[\"invoke\",1953,0,\"test\",[\"i32:132\"]],[\"invoke\",1955,0,\"test\",[\"i32:134\"]],[\"invoke\",1957,0,\"test\",[\"i32:136\"]],[\"invoke\",1959,0,\"test\",[\"i32:138\"]],[\"invoke\",1960,0,\"test\",[\"i32:139\"]],[\"invoke\",1962,0,\"test\",[\"i32:141\"]],[\"invoke\",1964,0,\"test\",[\"i32:143\"]],[\"invoke\",1965,0,\"test\",[\"i32:144\"]],[\"invoke\",1967,0,\"test\",[\"i32:146\"]],[\"invoke\",1969,0,\"test\",[\"i32:148\"]],[\"invoke\",1970,0,\"test\",[\"i32:149\"]],[\"invoke\",1972,0,\"test\",[\"i32:151\"]],[\"invoke\",1974,0,\"test\",[\"i32:153\"]],[\"invoke\",1975,0,\"test\",[\"i32:154\"]],[\"invoke\",1977,0,\"test\",[\"i32:156\"]],[\"invoke\",1979,0,\"test\",[\"i32:158\"]],[\"module\",1982,89],[\"invoke\",2010,0,\"run\",[\"i32:48\",\"i32:4294967280\"]],[\"invoke\",2011,0,\"test\",[\"i32:0\"]],[\"invoke\",2013,0,\"test\",[\"i32:2\"]],[\"invoke\",2015,0,\"test\",[\"i32:4\"]],[\"invoke\",2016,0,\"test\",[\"i32:5\"]],[\"invoke\",2018,0,\"test\",[\"i32:7\"]],[\"invoke\",2020,0,\"test\",[\"i32:9\"]],[\"invoke\",2021,0,\"test\",[\"i32:10\"]],[\"invoke\",2023,0,\"test\",[\"i32:12\"]],[\"invoke\",2025,0,\"test\",[\"i32:14\"]],[\"invoke\",2026,0,\"test\",[\"i32:15\"]],[\"invoke\",2028,0,\"test\",[\"i32:17\"]],[\"invoke\",2030,0,\"test\",[\"i32:19\"]],[\"invoke\",2032,0,\"test\",[\"i32:21\"]],[\"invoke\",2033,0,\"test\",[\"i32:22\"]],[\"invoke\",2035,0,\"test\",[\"i32:24\"]],[\"invoke\",2037,0,\"test\",[\"i32:26\"]],[\"invoke\",2038,0,\"test\",[\"i32:27\"]],[\"invoke\",2040,0,\"test\",[\"i32:29\"]],[\"invoke\",2042,0,\"test\",[\"i32:31\"]],[\"invoke\",2043,0,\"test\",[\"i32:32\"]],[\"invoke\",2045,0,\"test\",[\"i32:34\"]],[\"invoke\",2047,0,\"test\",[\"i32:36\"]],[\"invoke\",2048,0,\"test\",[\"i32:37\"]],[\"invoke\",2050,0,\"test\",[\"i32:39\"]],[\"invoke\",2052,0,\"test\",[\"i32:41\"]],[\"invoke\",2054,0,\"test\",[\"i32:43\"]],[\"invoke\",2055,0,\"test\",[\"i32:44\"]],[\"invoke\",2057,0,\"test\",[\"i32:46\"]],[\"invoke\",2059,0,\"test\",[\"i32:48\"]],[\"invoke\",2060,0,\"test\",[\"i32:49\"]],[\"invoke\",2062,0,\"test\",[\"i32:51\"]],[\"invoke\",2064,0,\"test\",[\"i32:53\"]],[\"invoke\",2065,0,\"test\",[\"i32:54\"]],[\"invoke\",2067,0,\"test\",[\"i32:56\"]],[\"invoke\",2069,0,\"test\",[\"i32:58\"]],[\"invoke\",2070,0,\"test\",[\"i32:59\"]],[\"invoke\",2072,0,\"test\",[\"i32:61\"]],[\"invoke\",2074,0,\"test\",[\"i32:63\"]],[\"module\",2076,90],[\"invoke\",2105,0,\"test\",[\"i32:0\"]],[\"invoke\",2106,0,\"test\",[\"i32:1\"]],[\"invoke\",2108,0,\"test\",[\"i32:3\"]],[\"invoke\",2110,0,\"test\",[\"i32:5\"]],[\"invoke\",2111,0,\"test\",[\"i32:6\"]],[\"invoke\",2113,0,\"test\",[\"i32:8\"]],[\"invoke\",2115,0,\"test\",[\"i32:10\"]],[\"invoke\",2116,0,\"test\",[\"i32:11\"]],[\"invoke\",2118,0,\"test\",[\"i32:13\"]],[\"invoke\",2120,0,\"test\",[\"i32:15\"]],[\"module\",2122,91],[\"file\",\"table_set.wast\"],[\"module\",1,92],[\"invoke\",29,0,\"get-externref\",[\"i32:0\"]],[\"invoke\",30,0,\"set-externref\",[\"i32:0\",\"externref:1\"]],[\"invoke\",31,0,\"get-externref\",[\"i32:0\"]],[\"invoke\",32,0,\"set-externref\",[\"i32:0\",\"externref:null\"]],[\"invoke\",33,0,\"get-externref\",[\"i32:0\"]],[\"invoke\",35,0,\"get-funcref\",[\"i32:0\"]],[\"invoke\",36,0,\"set-funcref-from\",[\"i32:0\",\"i32:1\"]],[\"invoke\",37,0,\"is_null-funcref\",[\"i32:0\"]],[\"invoke\",38,0,\"set-funcref\",[\"i32:0\",\"funcref:null\"]],[\"invoke\",39,0,\"get-funcref\",[\"i32:0\"]],[\"invoke\",41,0,\"set-externref\",[\"i32:2\",\"externref:null\"]],[\"invoke\",42,0,\"set-funcref\",[\"i32:3\",\"funcref:null\"]],[\"invoke\",43,0,\"set-externref\",[\"i32:4294967295\",\"externref:null\"]],[\"invoke\",44,0,\"set-funcref\",[\"i32:4294967295\",\"funcref:null\"]],[\"invoke\",46,0,\"set-externref\",[\"i32:2\",\"externref:0\"]],[\"invoke\",47,0,\"set-funcref-from\",[\"i32:3\",\"i32:1\"]],[\"invoke\",48,0,\"set-externref\",[\"i32:4294967295\",\"externref:0\"]],[\"invoke\",49,0,\"set-funcref-from\",[\"i32:4294967295\",\"i32:1\"]],[\"file\",\"table_size.wast\"],[\"module\",1,93],[\"invoke\",26,0,\"size-t0\",[]],[\"invoke\",27,0,\"grow-t0\",[\"i32:1\"]],[\"invoke\",28,0,\"size-t0\",[]],[\"invoke\",29,0,\"grow-t0\",[\"i32:4\"]],[\"invoke\",30,0,\"size-t0\",[]],[\"invoke\",31,0,\"grow-t0\",[\"i32:0\"]],[\"invoke\",32,0,\"size-t0\",[]],[\"invoke\",34,0,\"size-t1\",[]],[\"invoke\",35,0,\"grow-t1\",[\"i32:1\"]],[\"invoke\",36,0,\"size-t1\",[]],[\"invoke\",37,0,\"grow-t1\",[\"i32:4\"]],[\"invoke\",38,0,\"size-t1\",[]],[\"invoke\",39,0,\"grow-t1\",[\"i32:0\"]],[\"invoke\",40,0,\"size-t1\",[]],[\"invoke\",42,0,\"size-t2\",[]],[\"invoke\",43,0,\"grow-t2\",[\"i32:3\"]],[\"invoke\",44,0,\"size-t2\",[]],[\"invoke\",45,0,\"grow-t2\",[\"i32:1\"]],[\"invoke\",46,0,\"size-t2\",[]],[\"invoke\",47,0,\"grow-t2\",[\"i32:0\"]],[\"invoke\",48,0,\"size-t2\",[]],[\"invoke\",49,0,\"grow-t2\",[\"i32:4\"]],[\"invoke\",50,0,\"size-t2\",[]],[\"invoke\",51,0,\"grow-t2\",[\"i32:1\"]],[\"invoke\",52,0,\"size-t2\",[]],[\"invoke\",54,0,\"size-t3\",[]],[\"invoke\",55,0,\"grow-t3\",[\"i32:1\"]],[\"invoke\",56,0,\"size-t3\",[]],[\"invoke\",57,0,\"grow-t3\",[\"i32:3\"]],[\"invoke\",58,0,\"size-t3\",[]],[\"invoke\",59,0,\"grow-t3\",[\"i32:0\"]],[\"invoke\",60,0,\"size-t3\",[]],[\"invoke\",61,0,\"grow-t3\",[\"i32:2\"]],[\"invoke\",62,0,\"size-t3\",[]],[\"invoke\",63,0,\"grow-t3\",[\"i32:1\"]],[\"invoke\",64,0,\"size-t3\",[]],[\"file\",\"elem.wast\"],[\"module\",4,94],[\"module\",80,95],[\"module\",90,96],[\"module\",95,97],[\"module\",101,98],[\"module\",110,99],[\"module\",120,100],[\"module\",127,100],[\"module\",134,101],[\"invoke\",148,0,\"call-7\",[]],[\"invoke\",149,0,\"call-9\",[]],[\"module\",153,102],[\"invoke\",167,0,\"call-7\",[]],[\"invoke\",168,0,\"call-9\",[]],[\"module\",182,103],[\"module\",187,104],[\"module\",193,105],[\"module\",197,106],[\"module\",202,107],[\"module\",207,108],[\"module\",212,109],[\"module\",218,110],[\"module\",224,111],[\"module\",230,112],[\"instantiate\",239,113],[\"instantiate\",248,114],[\"instantiate\",257,115],[\"instantiate\",266,116],[\"instantiate\",273,117],[\"instantiate\",281,118],[\"instantiate\",290,119],[\"instantiate\",298,118],[\"instantiate\",307,120],[\"instantiate\",315,121],[\"instantiate\",324,122],[\"instantiate\",332,123],[\"module\",342,124],[\"invoke\",350,0,\"init\",[]],[\"module\",352,125],[\"invoke\",360,0,\"init\",[]],[\"module\",537,126],[\"invoke\",548,0,\"call-overwritten\",[]],[\"module\",550,127],[\"invoke\",561,0,\"call-overwritten-element\",[]],[\"module\",565,128,\"$module1\"],[\"register\",\"module1\",\"$module1\"],[\"invoke\",585,\"$module1\",\"call-7\",[]],[\"invoke\",586,\"$module1\",\"call-8\",[]],[\"invoke\",587,\"$module1\",\"call-9\",[]],[\"module\",589,129,\"$module2\"],[\"invoke\",598,\"$module1\",\"call-7\",[]],[\"invoke\",599,\"$module1\",\"call-8\",[]],[\"invoke\",600,\"$module1\",\"call-9\",[]],[\"module\",602,130,\"$module3\"],[\"invoke\",611,\"$module1\",\"call-7\",[]],[\"invoke\",612,\"$module1\",\"call-8\",[]],[\"invoke\",613,\"$module1\",\"call-9\",[]],[\"module\",646,131,\"$m\"],[\"register\",\"exporter\",\"$m\"],[\"invoke\",655,\"$m\",\"get\",[\"i32:0\"]],[\"invoke\",656,\"$m\",\"get\",[\"i32:1\"]],[\"invoke\",658,\"$m\",\"set\",[\"i32:0\",\"externref:42\"]],[\"invoke\",659,\"$m\",\"set\",[\"i32:1\",\"externref:137\"]],[\"invoke\",661,\"$m\",\"get\",[\"i32:0\"]],[\"invoke\",662,\"$m\",\"get\",[\"i32:1\"]],[\"module\",664,132],[\"invoke\",668,\"$m\",\"get\",[\"i32:0\"]],[\"invoke\",669,\"$m\",\"get\",[\"i32:1\"]],[\"module\",673,133,\"$module4\"],[\"register\",\"module4\",\"$module4\"],[\"module\",682,134],[\"invoke\",692,0,\"call_imported_elem\",[]],[\"file\",\"ref_func.wast\"],[\"module\",1,135],[\"register\",\"M\"],[\"module\",6,136],[\"invoke\",56,0,\"is_null-f\",[]],[\"invoke\",57,0,\"is_null-g\",[]],[\"invoke\",58,0,\"is_null-v\",[]],[\"invoke\",60,0,\"call-f\",[\"i32:4\"]],[\"invoke\",61,0,\"call-g\",[\"i32:4\"]],[\"invoke\",62,0,\"call-v\",[\"i32:4\"]],[\"invoke\",63,0,\"set-g\",[]],[\"invoke\",64,0,\"call-v\",[\"i32:4\"]],[\"invoke\",65,0,\"set-f\",[]],[\"invoke\",66,0,\"call-v\",[\"i32:4\"]],[\"module\",80,137],[\"file\",\"ref_is_null.wast\"],[\"module\",1,138],[\"invoke\",30,0,\"funcref\",[\"funcref:null\"]],[\"invoke\",31,0,\"externref\",[\"externref:null\"]],[\"invoke\",33,0,\"externref\",[\"externref:1\"]],[\"invoke\",35,0,\"init\",[\"externref:0\"]],[\"invoke\",37,0,\"funcref-elem\",[\"i32:0\"]],[\"invoke\",38,0,\"externref-elem\",[\"i32:0\"]],[\"invoke\",40,0,\"funcref-elem\",[\"i32:1\"]],[\"invoke\",41,0,\"externref-elem\",[\"i32:1\"]],[\"invoke\",43,0,\"deinit\",[]],[\"invoke\",45,0,\"funcref-elem\",[\"i32:0\"]],[\"invoke\",46,0,\"externref-elem\",[\"i32:0\"]],[\"invoke\",48,0,\"funcref-elem\",[\"i32:1\"]],[\"invoke\",49,0,\"externref-elem\",[\"i32:1\"]],[\"file\",\"ref_null.wast\"],[\"module\",1,139],[\"invoke\",9,0,\"externref\",[]],[\"invoke\",10,0,\"funcref\",[]],[\"file\",\"exports.wast\"],[\"module\",3,140],[\"module\",4,141],[\"module\",5,142],[\"module\",7,140],[\"module\",8,143],[\"module\",9,144],[\"module\",10,140],[\"module\",11,140],[\"module\",12,140],[\"module\",13,140],[\"module\",14,140],[\"module\",16,145,\"$Func\"],[\"invoke\",22,0,\"e\",[\"i32:42\"]],[\"invoke\",23,\"$Func\",\"e\",[\"i32:42\"]],[\"module\",24,146],[\"module\",25,146,\"$Other1\"],[\"invoke\",26,\"$Func\",\"e\",[\"i32:42\"]],[\"module\",28,147],[\"invoke\",34,0,\"a\",[]],[\"invoke\",35,0,\"b\",[]],[\"invoke\",36,0,\"c\",[]],[\"module\",74,148],[\"module\",75,149],[\"module\",76,150],[\"module\",78,148],[\"module\",79,148],[\"module\",80,148],[\"module\",81,148],[\"module\",82,148],[\"module\",83,148],[\"module\",85,151,\"$Global\"],[\"get\",89,0,\"e\",[]],[\"get\",90,\"$Global\",\"e\",[]],[\"module\",91,146],[\"module\",92,146,\"$Other2\"],[\"get\",93,\"$Global\",\"e\",[]],[\"module\",131,152],[\"module\",132,153],[\"module\",133,154],[\"module\",135,152],[\"module\",136,155],[\"module\",137,152],[\"module\",138,155],[\"module\",139,152],[\"module\",140,155],[\"module\",141,152],[\"module\",142,155],[\"module\",143,152],[\"module\",144,155],[\"module\",145,152],[\"module\",146,155],[\"module\",186,156],[\"module\",187,157],[\"module\",191,156],[\"module\",192,158],[\"module\",193,156],[\"module\",194,158],[\"module\",195,156],[\"module\",196,158],[\"module\",197,156],[\"module\",198,158],[\"module\",199,156],[\"module\",200,158],[\"module\",201,156],[\"module\",202,158],[\"file\",\"linking.wast\"],[\"module\",3,159,\"$Mf\"],[\"register\",\"Mf\",\"$Mf\"],[\"module\",9,160,\"$Nf\"],[\"invoke\",17,\"$Mf\",\"call\",[]],[\"invoke\",18,\"$Nf\",\"Mf.call\",[]],[\"invoke\",19,\"$Nf\",\"call\",[]],[\"invoke\",20,\"$Nf\",\"call Mf.call\",[]],[\"module\",22,161],[\"register\",\"reexport_f\"],[\"instantiate\",28,162],[\"instantiate\",32,163],[\"module\",39,164,\"$Mg\"],[\"register\",\"Mg\",\"$Mg\"],[\"module\",50,165,\"$Ng\"],[\"get\",67,\"$Mg\",\"glob\",[]],[\"get\",68,\"$Ng\",\"Mg.glob\",[]],[\"get\",69,\"$Ng\",\"glob\",[]],[\"invoke\",70,\"$Mg\",\"get\",[]],[\"invoke\",71,\"$Ng\",\"Mg.get\",[]],[\"invoke\",72,\"$Ng\",\"get\",[]],[\"get\",74,\"$Mg\",\"mut_glob\",[]],[\"get\",75,\"$Ng\",\"Mg.mut_glob\",[]],[\"invoke\",76,\"$Mg\",\"get_mut\",[]],[\"invoke\",77,\"$Ng\",\"Mg.get_mut\",[]],[\"invoke\",79,\"$Mg\",\"set_mut\",[\"i32:241\"]],[\"get\",80,\"$Mg\",\"mut_glob\",[]],[\"get\",81,\"$Ng\",\"Mg.mut_glob\",[]],[\"invoke\",82,\"$Mg\",\"get_mut\",[]],[\"invoke\",83,\"$Ng\",\"Mg.get_mut\",[]],[\"instantiate\",87,166],[\"instantiate\",91,167],[\"module\",96,168,\"$Mref_ex\"],[\"register\",\"Mref_ex\",\"$Mref_ex\"],[\"module\",104,169,\"$Mref_im\"],[\"instantiate\",113,170],[\"instantiate\",117,171],[\"instantiate\",123,172],[\"instantiate\",127,173],[\"module\",134,174,\"$Mt\"],[\"register\",\"Mt\",\"$Mt\"],[\"module\",149,175,\"$Nt\"],[\"invoke\",168,\"$Mt\",\"call\",[\"i32:2\"]],[\"invoke\",169,\"$Nt\",\"Mt.call\",[\"i32:2\"]],[\"invoke\",170,\"$Nt\",\"call\",[\"i32:2\"]],[\"invoke\",171,\"$Nt\",\"call Mt.call\",[\"i32:2\"]],[\"invoke\",173,\"$Mt\",\"call\",[\"i32:1\"]],[\"invoke\",174,\"$Nt\",\"Mt.call\",[\"i32:1\"]],[\"invoke\",175,\"$Nt\",\"call\",[\"i32:1\"]],[\"invoke\",176,\"$Nt\",\"call Mt.call\",[\"i32:1\"]],[\"invoke\",178,\"$Mt\",\"call\",[\"i32:0\"]],[\"invoke\",179,\"$Nt\",\"Mt.call\",[\"i32:0\"]],[\"invoke\",180,\"$Nt\",\"call\",[\"i32:0\"]],[\"invoke\",181,\"$Nt\",\"call Mt.call\",[\"i32:0\"]],[\"invoke\",183,\"$Mt\",\"call\",[\"i32:20\"]],[\"invoke\",184,\"$Nt\",\"Mt.call\",[\"i32:20\"]],[\"invoke\",185,\"$Nt\",\"call\",[\"i32:7\"]],[\"invoke\",186,\"$Nt\",\"call Mt.call\",[\"i32:20\"]],[\"invoke\",188,\"$Nt\",\"call\",[\"i32:3\"]],[\"invoke\",189,\"$Nt\",\"call\",[\"i32:4\"]],[\"module\",191,176,\"$Ot\"],[\"invoke\",204,\"$Mt\",\"call\",[\"i32:3\"]],[\"invoke\",205,\"$Nt\",\"Mt.call\",[\"i32:3\"]],[\"invoke\",206,\"$Nt\",\"call Mt.call\",[\"i32:3\"]],[\"invoke\",207,\"$Ot\",\"call\",[\"i32:3\"]],[\"invoke\",209,\"$Mt\",\"call\",[\"i32:2\"]],[\"invoke\",210,\"$Nt\",\"Mt.call\",[\"i32:2\"]],[\"invoke\",211,\"$Nt\",\"call\",[\"i32:2\"]],[\"invoke\",212,\"$Nt\",\"call Mt.call\",[\"i32:2\"]],[\"invoke\",213,\"$Ot\",\"call\",[\"i32:2\"]],[\"invoke\",215,\"$Mt\",\"call\",[\"i32:1\"]],[\"invoke\",216,\"$Nt\",\"Mt.call\",[\"i32:1\"]],[\"invoke\",217,\"$Nt\",\"call\",[\"i32:1\"]],[\"invoke\",218,\"$Nt\",\"call Mt.call\",[\"i32:1\"]],[\"invoke\",219,\"$Ot\",\"call\",[\"i32:1\"]],[\"invoke\",221,\"$Mt\",\"call\",[\"i32:0\"]],[\"invoke\",222,\"$Nt\",\"Mt.call\",[\"i32:0\"]],[\"invoke\",223,\"$Nt\",\"call\",[\"i32:0\"]],[\"invoke\",224,\"$Nt\",\"call Mt.call\",[\"i32:0\"]],[\"invoke\",225,\"$Ot\",\"call\",[\"i32:0\"]],[\"invoke\",227,\"$Ot\",\"call\",[\"i32:20\"]],[\"module\",229,177],[\"module\",235,178,\"$G1\"],[\"register\",\"G1\",\"$G1\"],[\"module\",237,179,\"$G2\"],[\"get\",241,\"$G2\",\"g\",[]],[\"instantiate\",244,180],[\"instantiate\",253,181],[\"invoke\",262,\"$Mt\",\"call\",[\"i32:7\"]],[\"instantiate\",267,182],[\"invoke\",275,\"$Mt\",\"call\",[\"i32:7\"]],[\"invoke\",276,\"$Mt\",\"call\",[\"i32:8\"]],[\"instantiate\",279,183],[\"invoke\",288,\"$Mt\",\"call\",[\"i32:7\"]],[\"module\",291,184,\"$Mtable_ex\"],[\"register\",\"Mtable_ex\",\"$Mtable_ex\"],[\"module\",297,185],[\"instantiate\",303,186],[\"instantiate\",307,187],[\"module\",314,188,\"$Mm\"],[\"register\",\"Mm\",\"$Mm\"],[\"module\",324,189,\"$Nm\"],[\"invoke\",336,\"$Mm\",\"load\",[\"i32:12\"]],[\"invoke\",337,\"$Nm\",\"Mm.load\",[\"i32:12\"]],[\"invoke\",338,\"$Nm\",\"load\",[\"i32:12\"]],[\"module\",340,190,\"$Om\"],[\"invoke\",349,\"$Mm\",\"load\",[\"i32:12\"]],[\"invoke\",350,\"$Nm\",\"Mm.load\",[\"i32:12\"]],[\"invoke\",351,\"$Nm\",\"load\",[\"i32:12\"]],[\"invoke\",352,\"$Om\",\"load\",[\"i32:12\"]],[\"module\",354,191],[\"instantiate\",360,192],[\"module\",367,193,\"$Pm\"],[\"invoke\",375,\"$Pm\",\"grow\",[\"i32:0\"]],[\"invoke\",376,\"$Pm\",\"grow\",[\"i32:2\"]],[\"invoke\",377,\"$Pm\",\"grow\",[\"i32:0\"]],[\"invoke\",378,\"$Pm\",\"grow\",[\"i32:1\"]],[\"invoke\",379,\"$Pm\",\"grow\",[\"i32:1\"]],[\"invoke\",380,\"$Pm\",\"grow\",[\"i32:0\"]],[\"invoke\",381,\"$Pm\",\"grow\",[\"i32:1\"]],[\"invoke\",382,\"$Pm\",\"grow\",[\"i32:0\"]],[\"instantiate\",385,194],[\"invoke\",393,\"$Mm\",\"load\",[\"i32:0\"]],[\"instantiate\",398,195],[\"invoke\",406,\"$Mm\",\"load\",[\"i32:0\"]],[\"invoke\",407,\"$Mm\",\"load\",[\"i32:327670\"]],[\"instantiate\",410,196],[\"invoke\",419,\"$Mm\",\"load\",[\"i32:0\"]],[\"module\",422,197,\"$Ms\"],[\"register\",\"Ms\",\"$Ms\"],[\"instantiate\",436,198],[\"invoke\",452,\"$Ms\",\"get memory[0]\",[]],[\"invoke\",453,\"$Ms\",\"get table[0]\",[]]]"; diff --git a/tests/corpus/webassembly-spec-table/main.mjs b/tests/corpus/webassembly-spec-table/main.mjs new file mode 100644 index 000000000..38c7c67d5 --- /dev/null +++ b/tests/corpus/webassembly-spec-table/main.mjs @@ -0,0 +1,5 @@ +// Executes WebAssembly spec tests (13 files); see tests/wasm-spec/runner.mjs. +import { run } from "../../wasm-spec/runner.mjs"; +import { modules, script } from "./data.mjs"; + +run(modules, script); diff --git a/tests/corpus/webassembly-typed.ts b/tests/corpus/webassembly-typed.ts new file mode 100644 index 000000000..967996135 --- /dev/null +++ b/tests/corpus/webassembly-typed.ts @@ -0,0 +1,51 @@ +// The WebAssembly API from TypeScript: lib.dom's types (declared by +// scriptc.d.ts), exports read through casts, and the error classes in +// catch clauses. The module text is tests/wasm-spec/corpus/api.wat. +const bytes: Uint8Array = Buffer.from("AGFzbQEAAAABLwlgAX8Bf2ACf38Bf2ABfwBgAABgAAF/YAJ+fgF+YAJ/fwJ/f2ABfQF9YAN/f38AAi0EA2VudgNsb2cAAgNlbnYEZmFpbAAAA2VudgRiYXNlA38AA2VudgNiaWcDfgADEhEAAAMBAQQFBgcAAAQAAAAICAQFAXABAggFBAEBAQQGFwN/AUEAC3wARAAAAAAAAApAC34AIwELB5kBEwZtZW1vcnkCAAV0YWJsZQEAB2NvdW50ZXIDAgJwaQMDBGJpZzIDBANhZGQABQVhcHBseQAGBGJ1bXAABwVtdWw2NAAIBmRpdm1vZAAJBm5hcnJvdwAKBnN0cmxlbgALBGdyb3cADAVwYWdlcwANCGNhbGxGYWlsAA4EdHJhcAAPB3JlY3Vyc2UAEARmaWxsABEEY29weQASCAEECQgBAEEACwICAwqHAhEHACAAQQJsCwcAIAAgAGwLBgAjABAACwcAIAAgAWoLCQAgASAAEQAACwsAIwJBAWokAiMCCwcAIAAgAX4LDAAgACABbSAAIAFvCwQAIAALIAEBfwJAA0AgACABai0AAEUNASABQQFqIQEMAAsLIAELBgAgAEAACwQAPwALCQAgABABQQFqC1kAAkACQAJAAkACQAJAAkAgAA4GAAECAwQFBgsAC0EBQQBuDwtB/////wcoAgAPC0EBQQJBABEBAA8LQQFBBxEAAA8LRAAAAAAAAPh/qg8LQYCAgIB4QX9tCwwAIABBAWoQEEEBagsLACAAIAEgAvwLAAsMACAAIAEgAvwKAAALCw4BAEEQCwhzY3JpcHRjAA==", "base64"); + +const logs: string[] = []; +// lib.dom's ImportValue has no bigint; Node accepts one for an i64 global. +const imports = { + env: { + log: (v: number): void => { + logs.push(`start ${v}`); + }, + fail: (v: number): number => v + 1, + base: 7, + big: 1n, + }, +} as unknown as WebAssembly.Imports; + +async function main(): Promise { + const { module, instance } = await WebAssembly.instantiate(bytes, imports); + console.log(logs.join(","), module instanceof WebAssembly.Module); + const exports = instance.exports; + const add = exports.add as (a: number, b: number) => number; + const mul64 = exports.mul64 as (a: bigint, b: bigint) => bigint; + const strlen = exports.strlen as (p: number) => number; + const trap = exports.trap as (kind: number) => number; + console.log(add(20, 22), mul64(3n, 4n), strlen(16)); + const memory = exports.memory as WebAssembly.Memory; + const text = new Uint8Array(memory.buffer, 16, strlen(16)); + console.log(new TextDecoder().decode(text), memory.buffer.byteLength); + const counter = exports.counter as WebAssembly.Global; + counter.value = 41; + console.log((exports.bump as () => number)(), counter.value); + for (let kind = 0; kind < 3; kind++) { + try { + trap(kind); + } catch (e) { + if (e instanceof WebAssembly.RuntimeError) console.log(`RuntimeError: ${e.message}`); + else throw e; + } + } + const second = new WebAssembly.Instance(module, imports); + console.log((second.exports.add as (a: number, b: number) => number)(1, 2), WebAssembly.validate(bytes)); + try { + await WebAssembly.compile(new Uint8Array([0, 97, 115, 109])); + } catch (e) { + console.log(e instanceof WebAssembly.CompileError); + } +} + +await main(); diff --git a/tests/corpus/webassembly-worker.ts b/tests/corpus/webassembly-worker.ts new file mode 100644 index 000000000..02bdf22c6 --- /dev/null +++ b/tests/corpus/webassembly-worker.ts @@ -0,0 +1,68 @@ +import { Worker, isMainThread, parentPort, workerData } from "node:worker_threads"; + +// The codemode shape: the main thread compiles a module once and sends the +// WebAssembly.Module to a fresh Worker per job, through workerData and +// through postMessage; each worker instantiates it with its own imports, +// runs it, and reports back. Traps in a worker (out-of-bounds memory and +// stack exhaustion, both caught by the per-thread fault handling) stay in +// that worker. The module text is tests/wasm-spec/corpus/api.wat. +const bytes = Buffer.from("AGFzbQEAAAABLwlgAX8Bf2ACf38Bf2ABfwBgAABgAAF/YAJ+fgF+YAJ/fwJ/f2ABfQF9YAN/f38AAi0EA2VudgNsb2cAAgNlbnYEZmFpbAAAA2VudgRiYXNlA38AA2VudgNiaWcDfgADEhEAAAMBAQQFBgcAAAQAAAAICAQFAXABAggFBAEBAQQGFwN/AUEAC3wARAAAAAAAAApAC34AIwELB5kBEwZtZW1vcnkCAAV0YWJsZQEAB2NvdW50ZXIDAgJwaQMDBGJpZzIDBANhZGQABQVhcHBseQAGBGJ1bXAABwVtdWw2NAAIBmRpdm1vZAAJBm5hcnJvdwAKBnN0cmxlbgALBGdyb3cADAVwYWdlcwANCGNhbGxGYWlsAA4EdHJhcAAPB3JlY3Vyc2UAEARmaWxsABEEY29weQASCAEECQgBAEEACwICAwqHAhEHACAAQQJsCwcAIAAgAGwLBgAjABAACwcAIAAgAWoLCQAgASAAEQAACwsAIwJBAWokAiMCCwcAIAAgAX4LDAAgACABbSAAIAFvCwQAIAALIAEBfwJAA0AgACABai0AAEUNASABQQFqIQEMAAsLIAELBgAgAEAACwQAPwALCQAgABABQQFqC1kAAkACQAJAAkACQAJAAkAgAA4GAAECAwQFBgsAC0EBQQBuDwtB/////wcoAgAPC0EBQQJBABEBAA8LQQFBBxEAAA8LRAAAAAAAAPh/qg8LQYCAgIB4QX9tCwwAIABBAWoQEEEBagsLACAAIAEgAvwLAAsMACAAIAEgAvwKAAALCw4BAEEQCwhzY3JpcHRjAA==", "base64"); + +interface Job { + module: WebAssembly.Module; + input: number; +} + +function run(module: WebAssembly.Module, input: number): string { + const seen: number[] = []; + const imports = { + env: { + log: (v: number): void => { + seen.push(v); + }, + fail: (v: number): number => v * 2, + base: input, + big: BigInt(input), + }, + } as unknown as WebAssembly.Imports; + const instance = new WebAssembly.Instance(module, imports); + const exports = instance.exports; + const apply = exports.apply as (fn: number, v: number) => number; + const callFail = exports.callFail as (v: number) => number; + const trap = exports.trap as (kind: number) => number; + const recurse = exports.recurse as (v: number) => number; + const traps: string[] = []; + for (const attempt of [() => trap(2), () => recurse(0), () => trap(1)]) { + try { + attempt(); + } catch (e) { + traps.push(e instanceof Error ? `${e.name}: ${e.message}` : String(e)); + } + } + return `job ${input}: start ${seen.join(",")} apply ${apply(1, input + 3)} callFail ${callFail(input)} traps ${traps.join(" | ")}`; +} + +if (isMainThread) { + const module = await WebAssembly.compile(bytes); + console.log(run(module, 0)); + for (let input = 1; input <= 3; input++) { + const line = await new Promise((resolve, reject) => { + const worker = new Worker(new URL(import.meta.url), { workerData: { module, input } satisfies Job }); + worker.once("message", (message: string) => resolve(message)); + worker.once("error", reject); + }); + console.log(line); + } + const worker = new Worker(new URL(import.meta.url), { workerData: null }); + const reply = new Promise((resolve) => worker.once("message", (message: string) => resolve(message))); + worker.postMessage({ module, input: 9 } satisfies Job); + console.log(await reply); + console.log("main still works:", run(module, 4).slice(0, 18)); +} else if (workerData !== null) { + const job = workerData as Job; + parentPort!.postMessage(`${job.module instanceof WebAssembly.Module} ${run(job.module, job.input)}`); +} else { + parentPort!.once("message", (job: Job) => { + parentPort!.postMessage(run(job.module, job.input)); + }); +} diff --git a/tests/corpus/webassembly-wpt-jsapi.mjs b/tests/corpus/webassembly-wpt-jsapi.mjs new file mode 100644 index 000000000..419e655ab --- /dev/null +++ b/tests/corpus/webassembly-wpt-jsapi.mjs @@ -0,0 +1,1117 @@ +// A port of web-platform-tests wasm/jsapi tests for the parts W5 adds: +// global/constructor, global/value-get-set, global/valueOf, +// memory/constructor, memory/grow, table/constructor, table/get-set, +// table/grow, module/imports, module/exports and module/customSections +// (WPT, 3-Clause BSD). Each test keeps its WPT name and body, with these +// changes: modules that WasmModuleBuilder builds at run time are inline +// base64 literals (built by the same builder), a minimal testharness prints +// one line per test, and the assertions the port cannot express are left +// out: the classes as values (prototypes, function name and length, +// property descriptors, branding through Function.prototype.call), +// Symbol arguments, Object.isFrozen and Object.isExtensible of +// ArrayBuffers (general scriptc gaps), and the old buffer's detachment +// after Memory.grow (a documented difference). assert_Global's parameter carries a JSDoc type: +// scriptc answers a Global's valueOf() only on receivers typed as one. +const modules = { + empty: "AGFzbQEAAAA=", + imports: "AGFzbQEAAAABBAFgAAACRAQGbW9kdWxlAmZuAAAGbW9kdWxlBmdsb2JhbAN/AAZtb2R1bGUGbWVtb3J5AgEAgAEGbW9kdWxlBXRhYmxlAXABAIAB", + importsEmptyModule: "AGFzbQEAAAABBAFgAAACLAQAAmZuAAAABmdsb2JhbAN/AAAGbWVtb3J5AgEAgAEABXRhYmxlAXABAIAB", + importsEmptyNames: "AGFzbQEAAAABBAFgAAACHQQBYQAAAAFiAAN/AAFjAAIBAIABAWQAAXABAIAB", + importsEmptyBoth: "AGFzbQEAAAABBAFgAAACGQQAAAAAAAADfwAAAAIBAIABAAABcAEAgAE=", + exports: "AGFzbQEAAAABBwJgAABgAAADAwIAAQQEAXAAAQUFAQEAgAIGEgJ/AUEHC3wBRDMzMzMzM/M/CwcwBgJmbgAAA2ZuMgABBXRhYmxlAQAGZ2xvYmFsAwAHZ2xvYmFsMgMBBm1lbW9yeQIACgcCAgALAgALABEEbmFtZQEKAgACZm4BA2ZuMg==", + exportsEmptyFunction: "AGFzbQEAAAABBAFgAAADAgEABwQBAAAACgQBAgALAAoEbmFtZQEDAQAA", + exportsEmptyTable: "AGFzbQEAAAAEBAFwAAEHBAEAAQA=", + exportsEmptyGlobal: "AGFzbQEAAAAGBgF/AUEHCwcEAQADAA==", + custom: "AGFzbQEAAAAAEARuYW1lV2ViQXNzZW1ibHkACgRuYW1lSlNBUEkADwNmb29XZWJBc3NlbWJseQ==", + customSurrogates: "AGFzbQEAAAAAFgp5ZWXwkJC3ZWV5V2ViQXNzZW1ibHk=", + customReplacement: "AGFzbQEAAAAAEwduYe+/vW1lV2ViQXNzZW1ibHk=", + customCopy: "AGFzbQEAAAAACARjb3B5ESIz", + fn: "AGFzbQEAAAABBAFgAAADAgEABwYBAmZuAAAKBAECAAsADARuYW1lAQUBAAJmbg==", + functions: "AGFzbQEAAAABCAJgAXwAYAAAAwMCAAEHDAICZm4AAANmbjIAAQoHAgIACwIACwARBG5hbWUBCgIAAmZuAQNmbjI=", +}; +const binary = (name) => Buffer.from(modules[name], "base64"); + +// ── a minimal testharness ───────────────────────────────────────────────── +class AssertionError extends Error {} +function fail(message) { + throw new AssertionError(message); +} +function same(a, b) { + return a === b ? a !== 0 || 1 / a === 1 / b : a !== a && b !== b; +} +function format_value(v) { + if (typeof v === "string") return JSON.stringify(v); + if (typeof v === "bigint") return `${v}n`; + if (typeof v === "number") return same(v, -0) ? "-0" : String(v); + if (typeof v === "boolean") return String(v); + if (v === null) return "null"; + if (v === undefined) return "undefined"; + return typeof v; +} +function assert_equals(actual, expected, description = "") { + if (!same(actual, expected)) fail(`${description} expected ${format_value(expected)} but got ${format_value(actual)}`); +} +function assert_not_equals(actual, expected, description = "") { + if (same(actual, expected)) fail(`${description} got disallowed value ${format_value(actual)}`); +} +function assert_true(actual, description = "") { + if (actual !== true) fail(`${description} expected true got ${format_value(actual)}`); +} +function assert_false(actual, description = "") { + if (actual !== false) fail(`${description} expected false got ${format_value(actual)}`); +} +function assert_array_equals(actual, expected, description = "") { + if (actual.length !== expected.length) fail(`${description} lengths differ, expected ${expected.length} got ${actual.length}`); + for (let i = 0; i < expected.length; i++) { + if (!same(actual[i], expected[i])) fail(`${description} property ${i}, expected ${format_value(expected[i])} but got ${format_value(actual[i])}`); + } +} +function assert_throws_js(name, func, description = "") { + try { + func(); + } catch (e) { + if (e instanceof AssertionError) throw e; + if (!(e instanceof Error) || e.name !== name) fail(`${description} threw ${e instanceof Error ? e.name : format_value(e)}, expected ${name}`); + return; + } + fail(`${description} did not throw`); +} +let passed = 0; +let failed = 0; +function test(func, name) { + try { + func(); + passed++; + console.log(`PASS ${name}`); + } catch (e) { + failed++; + console.log(`FAIL ${name}: ${e instanceof Error ? e.message : format_value(e)}`); + } +} + +// ── global/constructor.any.js ───────────────────────────────────────────── +/** @param {WebAssembly.Global} actual (typed so that valueOf() reaches the Global) */ +function assert_Global(actual, expected) { + assert_equals(actual.value, expected, "value"); + assert_equals(actual.valueOf(), expected, "valueOf"); +} + +test(() => { + // @ts-ignore: no descriptor + assert_throws_js("TypeError", () => new WebAssembly.Global()); +}, "No arguments"); + +test(() => { + const argument = { value: "i32" }; + // @ts-ignore: called without new + assert_throws_js("TypeError", () => WebAssembly.Global(argument)); +}, "Calling"); + +test(() => { + const order = []; + new WebAssembly.Global( + { + get value() { + order.push("descriptor value"); + return { + toString() { + order.push("descriptor value toString"); + return "f64"; + }, + }; + }, + get mutable() { + order.push("descriptor mutable"); + return false; + }, + }, + { + valueOf() { + order.push("value valueOf()"); + }, + }, + ); + assert_array_equals(order, ["descriptor mutable", "descriptor value", "descriptor value toString", "value valueOf()"]); +}, "Order of evaluation"); + +test(() => { + const invalidArguments = [undefined, null, false, true, "", "test", 1, NaN, {}]; + for (const invalidArgument of invalidArguments) { + // @ts-ignore: an invalid descriptor + assert_throws_js("TypeError", () => new WebAssembly.Global(invalidArgument), `new Global(${format_value(invalidArgument)})`); + } +}, "Invalid descriptor argument"); + +test(() => { + const invalidTypes = ["i16", "i128", "f16", "f128", "u32", "u64", "i32\0"]; + for (const value of invalidTypes) { + const argument = { value }; + // @ts-ignore: an invalid type + assert_throws_js("TypeError", () => new WebAssembly.Global(argument)); + } +}, "Invalid type argument"); + +test(() => { + const argument = { value: "v128" }; + // @ts-ignore: v128 + assert_throws_js("TypeError", () => new WebAssembly.Global(argument)); +}, "Construct v128 global"); + +test(() => { + const argument = { value: "i64" }; + const global = new WebAssembly.Global(argument); + assert_Global(global, 0n); +}, "i64 with default"); + +for (const type of ["i32", "f32", "f64"]) { + test(() => { + const argument = { value: type }; + const global = new WebAssembly.Global(argument); + assert_Global(global, 0); + }, `Default value for type ${type}`); + + const valueArguments = [ + { value: undefined, expected: 0, name: "undefined" }, + { value: null, expected: 0, name: "null" }, + { value: true, expected: 1, name: "true" }, + { value: false, expected: 0, name: "false" }, + { value: 2, expected: 2, name: "2" }, + { value: "3", expected: 3, name: '"3"' }, + { value: { toString() { return "5"; } }, expected: 5, name: "object with toString returning string" }, + { value: { valueOf() { return "8"; } }, expected: 8, name: "object with valueOf returning string" }, + { value: { toString() { return 6; } }, expected: 6, name: "object with toString returning number" }, + { value: { valueOf() { return 9; } }, expected: 9, name: "object with valueOf returning number" }, + ]; + for (const { value, expected, name } of valueArguments) { + test(() => { + const argument = { value: type }; + const global = new WebAssembly.Global(argument, value); + assert_Global(global, expected); + }, `Explicit value ${name} for type ${type}`); + } + + test(() => { + const argument = { value: type }; + assert_throws_js("TypeError", () => new WebAssembly.Global(argument, 0n)); + }, `BigInt value for type ${type}`); +} + +const bigintArguments = [ + { value: undefined, expected: 0n, name: "undefined" }, + { value: true, expected: 1n, name: "true" }, + { value: false, expected: 0n, name: "false" }, + { value: "3", expected: 3n, name: '"3"' }, + { value: 123n, expected: 123n, name: "123n" }, + { value: { toString() { return "5"; } }, expected: 5n, name: "object with toString returning string" }, + { value: { valueOf() { return "8"; } }, expected: 8n, name: "object with valueOf returning string" }, + { value: { toString() { return 6n; } }, expected: 6n, name: "object with toString returning bigint" }, + { value: { valueOf() { return 9n; } }, expected: 9n, name: "object with valueOf returning bigint" }, +]; +for (const { value, expected, name } of bigintArguments) { + test(() => { + const argument = { value: "i64" }; + const global = new WebAssembly.Global(argument, value); + assert_Global(global, expected); + }, `Explicit value ${name} for type i64`); +} + +const invalidBigints = [ + { value: null, name: "null" }, + { value: 666, name: "666" }, + { value: { toString() { return 5; } }, name: "object" }, + { value: { valueOf() { return 8; } }, name: "object" }, +]; +for (const { value: invalidBigint, name } of invalidBigints) { + test(() => { + const argument = { value: "i64" }; + assert_throws_js("TypeError", () => new WebAssembly.Global(argument, invalidBigint)); + }, `Pass non-bigint as i64 Global value: ${name}`); +} + +test(() => { + const argument = { value: "i32" }; + const global = new WebAssembly.Global(argument, 0, {}); + assert_Global(global, 0); +}, "Stray argument"); + +// ── global/value-get-set.any.js and global/valueOf.any.js ──────────────── +for (const type of ["i32", "i64", "f32", "f64"]) { + const [initial, value, invalid] = type === "i64" ? [0n, 1n, 2] : [0, 1, 2n]; + const immutableOptions = [ + { opts: {}, name: "missing" }, + { opts: { mutable: undefined }, name: "undefined" }, + { opts: { mutable: null }, name: "null" }, + { opts: { mutable: false }, name: "false" }, + { opts: { mutable: "" }, name: "empty string" }, + { opts: { mutable: 0 }, name: "zero" }, + ]; + for (const { opts, name } of immutableOptions) { + test(() => { + const global = new WebAssembly.Global({ ...opts, value: type }); + assert_equals(global.value, initial, "initial value"); + assert_equals(global.valueOf(), initial, "initial valueOf"); + assert_throws_js("TypeError", () => { + global.value = value; + }); + assert_equals(global.value, initial, "post-set value"); + assert_equals(global.valueOf(), initial, "post-set valueOf"); + }, `Immutable ${type} (${name})`); + + test(() => { + const global = new WebAssembly.Global({ ...opts, value: type }); + let touched = false; + const value = { + valueOf() { + touched = true; + return 1; + }, + toString() { + touched = true; + return "1"; + }, + }; + assert_throws_js("TypeError", () => { + global.value = value; + }); + assert_false(touched, "should not call valueOf or toString"); + assert_equals(global.value, initial, "post-set value"); + assert_equals(global.valueOf(), initial, "post-set valueOf"); + }, `Immutable ${type} with ToNumber side-effects (${name})`); + } + + const mutableOptions = [ + { opts: { mutable: true }, name: "true" }, + { opts: { mutable: 1 }, name: "one" }, + { opts: { mutable: "x" }, name: "string" }, + ]; + for (const { opts, name } of mutableOptions) { + test(() => { + const global = new WebAssembly.Global({ ...opts, value: type }); + assert_equals(global.value, initial, "initial value"); + assert_equals(global.valueOf(), initial, "initial valueOf"); + global.value = value; + assert_throws_js("TypeError", () => { + global.value = invalid; + }); + assert_equals(global.value, value, "post-set value"); + assert_equals(global.valueOf(), value, "post-set valueOf"); + }, `Mutable ${type} (${name})`); + } +} + +test(() => { + const argument = { value: "i64", mutable: true }; + const global = new WebAssembly.Global(argument); + assert_equals(global.value, 0n, "initial value using ToJSValue"); + const valid = [ + { input: 123n, output: 123n }, + { input: 2n ** 63n, output: -(2n ** 63n) }, + { input: true, output: 1n }, + { input: false, output: 0n }, + { input: "456", output: 456n }, + ]; + for (const { input, output } of valid) { + global.value = input; + assert_equals(global.valueOf(), output, "post-set valueOf"); + } + const invalid = [undefined, null, 0, 1, 4.2]; + for (const input of invalid) { + assert_throws_js("TypeError", () => { + global.value = input; + }); + } +}, "i64 mutability"); + +test(() => { + const argument = { value: "i32" }; + const global = new WebAssembly.Global(argument, 0); + assert_equals(global.valueOf({}), 0); +}, "valueOf: Stray argument"); + +// ── memory/constructor.any.js ───────────────────────────────────────────── +function assert_ArrayBuffer(actual, { size = 0 }, message) { + assert_equals(actual.toString(), "[object ArrayBuffer]", `${message}: toString()`); + assert_equals(actual.byteLength, 0x10000 * size, `${message}: size`); + if (size > 0) { + const array = new Uint8Array(actual); + assert_equals(array[0], 0, `${message}: first element`); + assert_equals(array[array.byteLength - 1], 0, `${message}: last element`); + } +} + +function assert_Memory(memory, { size = 0 }) { + assert_equals(memory.buffer, memory.buffer, "buffer should be idempotent"); + assert_ArrayBuffer(memory.buffer, { size }); +} + +test(() => { + // @ts-ignore: no descriptor + assert_throws_js("TypeError", () => new WebAssembly.Memory()); +}, "Memory: No arguments"); + +test(() => { + const argument = { initial: 0 }; + // @ts-ignore: called without new + assert_throws_js("TypeError", () => WebAssembly.Memory(argument)); +}, "Memory: Calling"); + +test(() => { + const invalidArguments = [undefined, null, false, true, "", "test", 1, NaN, {}]; + for (const invalidArgument of invalidArguments) { + // @ts-ignore: an invalid descriptor + assert_throws_js("TypeError", () => new WebAssembly.Memory(invalidArgument), `new Memory(${format_value(invalidArgument)})`); + } +}, "Memory: Invalid descriptor argument"); + +test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Memory({ initial: undefined })); +}, "Undefined initial value in descriptor"); + +const outOfRangeValues = [NaN, Infinity, -Infinity, -1, 0x100000000, 0x1000000000]; +for (const value of outOfRangeValues) { + test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Memory({ initial: value })); + }, `Memory: Out-of-range initial value in descriptor: ${format_value(value)}`); + + test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Memory({ initial: 0, maximum: value })); + }, `Memory: Out-of-range maximum value in descriptor: ${format_value(value)}`); +} + +test(() => { + assert_throws_js("RangeError", () => new WebAssembly.Memory({ initial: 10, maximum: 9 })); +}, "Memory: Initial value exceeds maximum"); + +test(() => { + const order = []; + new WebAssembly.Memory({ + get maximum() { + order.push("maximum"); + return { + valueOf() { + order.push("maximum valueOf"); + return 1; + }, + }; + }, + get initial() { + order.push("initial"); + return { + valueOf() { + order.push("initial valueOf"); + return 1; + }, + }; + }, + }); + assert_array_equals(order, ["initial", "initial valueOf", "maximum", "maximum valueOf"]); +}, "Memory: Order of evaluation for descriptor"); + +test(() => { + const argument = { initial: 0 }; + const memory = new WebAssembly.Memory(argument); + assert_Memory(memory, { size: 0 }); +}, "Zero initial"); + +test(() => { + const argument = { initial: 4 }; + const memory = new WebAssembly.Memory(argument); + assert_Memory(memory, { size: 4 }); +}, "Non-zero initial"); + +test(() => { + const argument = { initial: 0 }; + const memory = new WebAssembly.Memory(argument, {}); + assert_Memory(memory, { size: 0 }); +}, "Memory: Stray argument"); + +// ── memory/grow.any.js ──────────────────────────────────────────────────── +test(() => { + const argument = { initial: 0 }; + const memory = new WebAssembly.Memory(argument); + // @ts-ignore: no delta + assert_throws_js("TypeError", () => memory.grow()); +}, "grow: Missing arguments"); + +for (const { initial, delta, label } of [ + { initial: 0, delta: 2, label: "Zero initial" }, + { initial: { valueOf() { return 0; } }, delta: { valueOf() { return 2; } }, label: "Zero initial with valueOf" }, + { initial: 3, delta: 2, label: "Non-zero initial" }, +]) { + test(() => { + const memory = new WebAssembly.Memory({ initial }); + const before = Number(initial); + const oldMemory = memory.buffer; + assert_ArrayBuffer(oldMemory, { size: before }, "Buffer before growing"); + const result = memory.grow(delta); + assert_equals(result, before); + const newMemory = memory.buffer; + assert_not_equals(oldMemory, newMemory); + assert_ArrayBuffer(newMemory, { size: before + 2 }, "New buffer after growing"); + }, `grow: ${label}`); +} + +test(() => { + const argument = { initial: 0, maximum: 2 }; + const memory = new WebAssembly.Memory(argument); + const result = memory.grow(2); + assert_equals(result, 0); + assert_ArrayBuffer(memory.buffer, { size: 2 }, "New buffer after growing"); +}, "grow: Zero initial with respected maximum"); + +test(() => { + const argument = { initial: 0, maximum: 2 }; + const memory = new WebAssembly.Memory(argument); + assert_equals(memory.grow(1), 0); + assert_equals(memory.grow(1), 1); + assert_ArrayBuffer(memory.buffer, { size: 2 }, "Buffer after growing twice"); +}, "grow: Zero initial with respected maximum grown twice"); + +test(() => { + const argument = { initial: 1, maximum: 2 }; + const memory = new WebAssembly.Memory(argument); + const oldMemory = memory.buffer; + assert_throws_js("RangeError", () => memory.grow(2)); + assert_equals(memory.buffer, oldMemory); + assert_ArrayBuffer(memory.buffer, { size: 1 }, "Buffer after trying to grow"); +}, "grow: Zero initial growing too much"); + +const outOfRangeDeltas = [undefined, NaN, Infinity, -Infinity, -1, 0x100000000, 0x1000000000]; +for (const value of outOfRangeDeltas) { + test(() => { + const argument = { initial: 0 }; + const memory = new WebAssembly.Memory(argument); + assert_throws_js("TypeError", () => memory.grow(value)); + }, `grow: Out-of-range argument: ${format_value(value)}`); +} + +test(() => { + const argument = { initial: 0 }; + const memory = new WebAssembly.Memory(argument); + const result = memory.grow(2, {}); + assert_equals(result, 0); +}, "grow: Stray argument"); + +// ── table/constructor.any.js ────────────────────────────────────────────── +function assert_equal_to_array(table, expected, message = "") { + assert_equals(table.length, expected.length, `${message}: length`); + assert_throws_js("TypeError", () => table.get(-1), `${message}: table.get(-1)`); + for (let i = 0; i < expected.length; ++i) { + assert_equals(table.get(i), expected[i], `${message}: table.get(${i} of ${expected.length})`); + } + assert_throws_js("RangeError", () => table.get(expected.length), `${message}: table.get(${expected.length} of ${expected.length})`); + assert_throws_js("RangeError", () => table.get(expected.length + 1), `${message}: table.get(${expected.length + 1} of ${expected.length})`); +} + +function assert_Table(actual, expected) { + assert_equals(actual.length, expected.length, "length"); + for (let i = 0; i < expected.length; ++i) { + assert_equals(actual.get(i), null, `actual.get(${i})`); + } +} + +test(() => { + // @ts-ignore: no descriptor + assert_throws_js("TypeError", () => new WebAssembly.Table()); +}, "Table: No arguments"); + +test(() => { + const argument = { element: "anyfunc", initial: 0 }; + // @ts-ignore: called without new + assert_throws_js("TypeError", () => WebAssembly.Table(argument)); +}, "Table: Calling"); + +test(() => { + // @ts-ignore: an empty descriptor + assert_throws_js("TypeError", () => new WebAssembly.Table({})); +}, "Empty descriptor"); + +test(() => { + const invalidArguments = [undefined, null, false, true, "", "test", 1, NaN, {}]; + for (const invalidArgument of invalidArguments) { + // @ts-ignore: an invalid descriptor + assert_throws_js("TypeError", () => new WebAssembly.Table(invalidArgument), `new Table(${format_value(invalidArgument)})`); + } +}, "Table: Invalid descriptor argument"); + +test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Table({ element: "anyfunc", initial: undefined })); +}, "Table: Undefined initial value in descriptor"); + +test(() => { + // @ts-ignore: an undefined element + assert_throws_js("TypeError", () => new WebAssembly.Table({ element: undefined, initial: 0 })); +}, "Undefined element value in descriptor"); + +for (const value of outOfRangeValues) { + test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Table({ element: "anyfunc", initial: value })); + }, `Table: Out-of-range initial value in descriptor: ${format_value(value)}`); + + test(() => { + assert_throws_js("TypeError", () => new WebAssembly.Table({ element: "anyfunc", initial: 0, maximum: value })); + }, `Table: Out-of-range maximum value in descriptor: ${format_value(value)}`); +} + +test(() => { + assert_throws_js("RangeError", () => new WebAssembly.Table({ element: "anyfunc", initial: 10, maximum: 9 })); +}, "Table: Initial value exceeds maximum"); + +test(() => { + const argument = { element: "anyfunc", initial: 0 }; + const table = new WebAssembly.Table(argument); + assert_Table(table, { length: 0 }); +}, "Basic (zero)"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_Table(table, { length: 5 }); +}, "Basic (non-zero)"); + +test(() => { + const argument = { element: "anyfunc", initial: 0 }; + const table = new WebAssembly.Table(argument, null, {}); + assert_Table(table, { length: 0 }); +}, "Table: Stray argument"); + +test(() => { + const table = new WebAssembly.Table({ + // @ts-ignore: an object element + element: { + toString() { + return "anyfunc"; + }, + }, + initial: 1, + }); + assert_Table(table, { length: 1 }); +}, "Type conversion for descriptor.element"); + +test(() => { + const order = []; + new WebAssembly.Table({ + get maximum() { + order.push("maximum"); + return { + valueOf() { + order.push("maximum valueOf"); + return 1; + }, + }; + }, + get initial() { + order.push("initial"); + return { + valueOf() { + order.push("initial valueOf"); + return 1; + }, + }; + }, + get element() { + order.push("element"); + return { + toString() { + order.push("element toString"); + return "anyfunc"; + }, + }; + }, + }); + assert_array_equals(order, ["element", "element toString", "initial", "initial valueOf", "maximum", "maximum valueOf"]); +}, "Table: Order of evaluation for descriptor"); + +test(() => { + const testObject = {}; + const argument = { element: "externref", initial: 3 }; + const table = new WebAssembly.Table(argument, testObject); + assert_equals(table.length, 3); + assert_equals(table.get(0), testObject); + assert_equals(table.get(1), testObject); + assert_equals(table.get(2), testObject); +}, "initialize externref table with default value"); + +test(() => { + const argument = { element: "i32", initial: 3 }; + // @ts-ignore: an invalid element + assert_throws_js("TypeError", () => new WebAssembly.Table(argument)); +}, "initialize table with a wrong element value"); + +test(() => { + const fn = new WebAssembly.Instance(new WebAssembly.Module(binary("fn"))).exports.fn; + const argument = { element: "anyfunc", initial: 3 }; + const table = new WebAssembly.Table(argument, fn); + assert_equals(table.length, 3); + assert_equals(table.get(0), fn); + assert_equals(table.get(1), fn); + assert_equals(table.get(2), fn); +}, "initialize anyfunc table with default value"); + +test(() => { + const argument = { element: "anyfunc", initial: 3 }; + assert_throws_js("TypeError", () => new WebAssembly.Table(argument, {})); + assert_throws_js("TypeError", () => new WebAssembly.Table(argument, "cannot be used as a wasm function")); + assert_throws_js("TypeError", () => new WebAssembly.Table(argument, 37)); +}, "initialize anyfunc table with a bad default value"); + +test(() => { + assert_throws_js("RangeError", () => new WebAssembly.Table({ element: "anyfunc", initial: 3, maximum: 2 }, 37)); +}, "initialize anyfunc table with a bad default value and a bad descriptor"); + +// ── table/get-set.any.js ────────────────────────────────────────────────── +const functions = new WebAssembly.Instance(new WebAssembly.Module(binary("functions")), {}).exports; + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + // @ts-ignore: no index + assert_throws_js("TypeError", () => table.get()); +}, "Missing arguments: get"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + // @ts-ignore: no index + assert_throws_js("TypeError", () => table.set()); +}, "Missing arguments: set"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null, null, null, null, null]); + const { fn, fn2 } = functions; + assert_equals(table.set(0, fn), undefined, "set() returns undefined."); + table.set(2, fn2); + table.set(4, fn); + assert_equal_to_array(table, [fn, null, fn2, null, fn]); + table.set(0, null); + assert_equal_to_array(table, [null, null, fn2, null, fn]); +}, "Basic"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null, null, null, null, null]); + const { fn, fn2 } = functions; + table.set(0, fn); + table.set(2, fn2); + table.set(4, fn); + assert_equal_to_array(table, [fn, null, fn2, null, fn]); + table.grow(4); + assert_equal_to_array(table, [fn, null, fn2, null, fn, null, null, null, null]); +}, "Growing"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null, null, null, null, null]); + const { fn } = functions; + assert_throws_js("TypeError", () => table.set(-1, fn)); + assert_throws_js("RangeError", () => table.set(5, fn)); + assert_equal_to_array(table, [null, null, null, null, null]); +}, "Setting out-of-bounds"); + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null]); + const invalidArguments = [undefined, true, false, "test", 7, NaN, {}]; + for (const argument of invalidArguments) { + assert_throws_js("TypeError", () => table.set(0, argument), `set(${format_value(argument)})`); + } + assert_equal_to_array(table, [null]); +}, "Setting non-function"); + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null]); + const fn = function () {}; + assert_throws_js("TypeError", () => table.set(0, fn)); + assert_equal_to_array(table, [null]); +}, "Setting non-wasm function"); + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, [null]); + const fn = () => {}; + assert_throws_js("TypeError", () => table.set(0, fn)); + assert_equal_to_array(table, [null]); +}, "Setting non-wasm arrow function"); + +const outOfRangeIndices = [ + { value: undefined, name: "undefined" }, + { value: NaN, name: "NaN" }, + { value: Infinity, name: "Infinity" }, + { value: -Infinity, name: "-Infinity" }, + { value: -1, name: "-1" }, + { value: 0x100000000, name: "4294967296" }, + { value: 0x1000000000, name: "68719476736" }, + { value: "0x100000000", name: '"0x100000000"' }, + { value: { valueOf() { return 0x100000000; } }, name: "object" }, +]; +for (const { value, name } of outOfRangeIndices) { + test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_throws_js("TypeError", () => table.get(value)); + }, `Getting out-of-range argument: ${name}`); + + test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_throws_js("TypeError", () => table.set(value, null)); + }, `Setting out-of-range argument: ${name}`); +} + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + let called = 0; + const value = { + valueOf() { + called++; + return 0; + }, + }; + assert_throws_js("TypeError", () => table.set(value, {})); + assert_equals(called, 1); +}, "Order of argument conversion"); + +test(() => { + const { fn } = functions; + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_equals(table.get(0, {}), null); + assert_equals(table.set(0, fn, {}), undefined); +}, "get-set: Stray argument"); + +test(() => { + const fn = new WebAssembly.Instance(new WebAssembly.Module(binary("fn"))).exports.fn; + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument, fn); + assert_equals(table.get(0), fn); + table.set(0); + assert_equals(table.get(0), null); + table.set(0, fn); + assert_equals(table.get(0), fn); + assert_throws_js("TypeError", () => table.set(0, {})); + assert_throws_js("TypeError", () => table.set(0, 37)); +}, "Arguments for anyfunc table set"); + +test(() => { + const testObject = {}; + const argument = { element: "externref", initial: 1 }; + const table = new WebAssembly.Table(argument, testObject); + assert_equals(table.get(0), testObject); + table.set(0); + assert_equals(table.get(0), undefined); + table.set(0, testObject); + assert_equals(table.get(0), testObject); + table.set(0, 37); + assert_equals(table.get(0), 37); +}, "Arguments for externref table set"); + +// ── table/grow.any.js ───────────────────────────────────────────────────── +function nulls(n) { + return Array(n).fill(null); +} + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + // @ts-ignore: no delta + assert_throws_js("TypeError", () => table.grow()); +}, "Table grow: Missing arguments"); + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, nulls(5), "before"); + const result = table.grow(3); + assert_equals(result, 5); + assert_equal_to_array(table, nulls(8), "after"); +}, "Table grow: Basic"); + +test(() => { + const argument = { element: "anyfunc", initial: 3, maximum: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, nulls(3), "before"); + const result = table.grow(2); + assert_equals(result, 3); + assert_equal_to_array(table, nulls(5), "after"); +}, "Reached maximum"); + +test(() => { + const argument = { element: "anyfunc", initial: 2, maximum: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, nulls(2), "before"); + assert_throws_js("RangeError", () => table.grow(4)); + assert_equal_to_array(table, nulls(2), "after"); +}, "Exceeded maximum"); + +for (const { value, name } of outOfRangeIndices) { + test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_throws_js("TypeError", () => table.grow(value)); + }, `Table grow: Out-of-range argument: ${name}`); +} + +test(() => { + const argument = { element: "anyfunc", initial: 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, nulls(5), "before"); + const result = table.grow(3, null, {}); + assert_equals(result, 5); + assert_equal_to_array(table, nulls(8), "after"); +}, "Table grow: Stray argument"); + +test(() => { + const fn = new WebAssembly.Instance(new WebAssembly.Module(binary("fn"))).exports.fn; + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument, fn); + assert_equal_to_array(table, [fn], "before"); + const result = table.grow(2, fn); + assert_equals(result, 1); + assert_equal_to_array(table, [fn, fn, fn], "after"); +}, "Grow with exported-function argument"); + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_throws_js("TypeError", () => table.grow(2, {})); +}, "Grow with non-function argument"); + +test(() => { + const argument = { element: "anyfunc", initial: 1 }; + const table = new WebAssembly.Table(argument); + assert_throws_js("TypeError", () => table.grow(2, () => true)); +}, "Grow with JS-function argument"); + +// ── module/imports.any.js and module/exports.any.js ────────────────────── +function assert_descriptors(actual, expected, keys) { + assert_true(Array.isArray(actual), "Should be array"); + assert_true(Object.isExtensible(actual), "isExtensible"); + assert_equals(actual.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert_true(Object.isExtensible(actual[i]), "isExtensible"); + assert_array_equals(Object.keys(actual[i]), keys, "keys"); + for (const key of keys) assert_equals(actual[i][key], expected[i][key], key); + } +} +const assert_imports = (imports, expected) => assert_descriptors(imports, expected, ["module", "name", "kind"]); +const assert_exports = (exports, expected) => assert_descriptors(exports, expected, ["name", "kind"]); +const emptyModule = new WebAssembly.Module(binary("empty")); + +for (const which of ["imports", "exports"]) { + test(() => { + // @ts-ignore: no module + assert_throws_js("TypeError", () => (which === "imports" ? WebAssembly.Module.imports() : WebAssembly.Module.exports())); + }, `${which}: Missing arguments`); + + test(() => { + const invalidArguments = [undefined, null, true, "", 1, {}]; + for (const argument of invalidArguments) { + assert_throws_js( + "TypeError", + // @ts-ignore: not a module + () => (which === "imports" ? WebAssembly.Module.imports(argument) : WebAssembly.Module.exports(argument)), + `${which}(${format_value(argument)})`, + ); + } + }, `${which}: Non-Module arguments`); + + test(() => { + const result = which === "imports" ? WebAssembly.Module.imports(emptyModule) : WebAssembly.Module.exports(emptyModule); + assert_true(Array.isArray(result)); + }, `${which}: Return type`); + + test(() => { + if (which === "imports") assert_imports(WebAssembly.Module.imports(emptyModule), []); + else assert_exports(WebAssembly.Module.exports(emptyModule), []); + }, `${which}: Empty module`); + + test(() => { + if (which === "imports") + assert_not_equals(WebAssembly.Module.imports(emptyModule), WebAssembly.Module.imports(emptyModule)); + else assert_not_equals(WebAssembly.Module.exports(emptyModule), WebAssembly.Module.exports(emptyModule)); + }, `${which}: Empty module: array caching`); +} + +test(() => { + const module = new WebAssembly.Module(binary("imports")); + const imports = WebAssembly.Module.imports(module); + const expected = [ + { module: "module", kind: "function", name: "fn" }, + { module: "module", kind: "global", name: "global" }, + { module: "module", kind: "memory", name: "memory" }, + { module: "module", kind: "table", name: "table" }, + ]; + assert_imports(imports, expected); +}, "imports"); + +for (const { key, label, expected } of [ + { + key: "importsEmptyModule", + label: "imports with empty module name", + expected: [ + { module: "", kind: "function", name: "fn" }, + { module: "", kind: "global", name: "global" }, + { module: "", kind: "memory", name: "memory" }, + { module: "", kind: "table", name: "table" }, + ], + }, + { + key: "importsEmptyNames", + label: "imports with empty names", + expected: [ + { module: "a", kind: "function", name: "" }, + { module: "b", kind: "global", name: "" }, + { module: "c", kind: "memory", name: "" }, + { module: "d", kind: "table", name: "" }, + ], + }, + { + key: "importsEmptyBoth", + label: "imports with empty module names and names", + expected: [ + { module: "", kind: "function", name: "" }, + { module: "", kind: "global", name: "" }, + { module: "", kind: "memory", name: "" }, + { module: "", kind: "table", name: "" }, + ], + }, +]) { + test(() => { + const module = new WebAssembly.Module(binary(key)); + assert_imports(WebAssembly.Module.imports(module), expected); + }, label); +} + +test(() => { + assert_imports(WebAssembly.Module.imports(emptyModule, {}), []); +}, "imports: Stray argument"); + +test(() => { + const module = new WebAssembly.Module(binary("exports")); + const exports = WebAssembly.Module.exports(module); + const expected = [ + { kind: "function", name: "fn" }, + { kind: "function", name: "fn2" }, + { kind: "table", name: "table" }, + { kind: "global", name: "global" }, + { kind: "global", name: "global2" }, + { kind: "memory", name: "memory" }, + ]; + assert_exports(exports, expected); +}, "exports"); + +for (const { key, kind } of [ + { key: "exportsEmptyFunction", kind: "function" }, + { key: "exportsEmptyTable", kind: "table" }, + { key: "exportsEmptyGlobal", kind: "global" }, +]) { + test(() => { + const module = new WebAssembly.Module(binary(key)); + assert_exports(WebAssembly.Module.exports(module), [{ kind, name: "" }]); + }, `exports with empty name: ${kind}`); +} + +test(() => { + assert_exports(WebAssembly.Module.exports(emptyModule, {}), []); +}, "exports: Stray argument"); + +// ── module/customSections.any.js ────────────────────────────────────────── +function assert_sections(sections, expected) { + assert_true(Array.isArray(sections), "Should be array"); + assert_true(Object.isExtensible(sections), "isExtensible"); + assert_equals(sections.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert_true(sections[i] instanceof ArrayBuffer, "ArrayBuffer"); + assert_array_equals(new Uint8Array(sections[i]), expected[i]); + } +} + +test(() => { + // @ts-ignore: no arguments + assert_throws_js("TypeError", () => WebAssembly.Module.customSections()); + // @ts-ignore: no name + assert_throws_js("TypeError", () => WebAssembly.Module.customSections(emptyModule)); +}, "customSections: Missing arguments"); + +test(() => { + const invalidArguments = [undefined, null, true, "", 1, {}]; + for (const argument of invalidArguments) { + // @ts-ignore: not a module + assert_throws_js("TypeError", () => WebAssembly.Module.customSections(argument, ""), `customSections(${format_value(argument)})`); + } +}, "customSections: Non-Module arguments"); + +test(() => { + assert_sections(WebAssembly.Module.customSections(emptyModule, ""), []); +}, "customSections: Empty module"); + +test(() => { + assert_not_equals(WebAssembly.Module.customSections(emptyModule, ""), WebAssembly.Module.customSections(emptyModule, "")); +}, "customSections: Empty module: array caching"); + +const bytes1 = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121]; +const bytes2 = [74, 83, 65, 80, 73]; + +test(() => { + const module = new WebAssembly.Module(binary("custom")); + assert_sections(WebAssembly.Module.customSections(module, "name"), [bytes1, bytes2]); + assert_sections(WebAssembly.Module.customSections(module, "foo"), [bytes1]); + assert_sections(WebAssembly.Module.customSections(module, ""), []); + assert_sections(WebAssembly.Module.customSections(module, "\0"), []); + assert_sections(WebAssembly.Module.customSections(module, "name\0"), []); + assert_sections(WebAssembly.Module.customSections(module, "foo\0"), []); +}, "Custom sections"); + +test(() => { + const name = "yee𐐷eey"; + const module = new WebAssembly.Module(binary("customSurrogates")); + assert_sections(WebAssembly.Module.customSections(module, name), [bytes1]); + assert_sections(WebAssembly.Module.customSections(module, "yee�eey"), []); + assert_sections(WebAssembly.Module.customSections(module, "yee��eey"), []); +}, "Custom sections with surrogate pairs"); + +test(() => { + const module = new WebAssembly.Module(binary("customReplacement")); + assert_sections(WebAssembly.Module.customSections(module, "name"), []); + assert_sections(WebAssembly.Module.customSections(module, "na�me"), [bytes1]); + assert_sections(WebAssembly.Module.customSections(module, "na\uDC01me"), []); +}, "Custom sections with U+FFFD"); + +test(() => { + assert_sections(WebAssembly.Module.customSections(emptyModule, "", {}), []); +}, "customSections: Stray argument"); + +test(() => { + const module = new WebAssembly.Module(binary("customCopy")); + const first = WebAssembly.Module.customSections(module, "copy"); + const second = WebAssembly.Module.customSections(module, "copy"); + assert_equals(first.length, 1); + assert_equals(second.length, 1); + assert_not_equals(first, second); + assert_not_equals(first[0], second[0]); +}, "Custom section buffers are independent copies"); + +test(() => { + const bytes = [0x11, 0x22, 0x33]; + const module = new WebAssembly.Module(binary("customCopy")); + const first = WebAssembly.Module.customSections(module, "copy"); + const second = WebAssembly.Module.customSections(module, "copy"); + const view = new Uint8Array(first[0]); + view[0] = 0xff; + view[1] = 0xee; + view[2] = 0xdd; + const again = WebAssembly.Module.customSections(module, "copy"); + assert_array_equals(new Uint8Array(again[0]), bytes); + assert_array_equals(new Uint8Array(second[0]), bytes); +}, "Mutating a custom section buffer does not change other copies"); + +console.log(`${passed} passed, ${failed} failed`); diff --git a/tests/coverage-fixtures/wasm/ext.so b/tests/coverage-fixtures/wasm/ext.so new file mode 100644 index 000000000..d8b646108 Binary files /dev/null and b/tests/coverage-fixtures/wasm/ext.so differ diff --git a/tests/coverage-fixtures/wasm/glue.js b/tests/coverage-fixtures/wasm/glue.js index 631560632..4a18af315 100644 --- a/tests/coverage-fixtures/wasm/glue.js +++ b/tests/coverage-fixtures/wasm/glue.js @@ -8,6 +8,15 @@ export function hasModule() { return existsSync(new URL("./add.wasm", import.meta.url).pathname); } +// WebAssembly shared libraries (quickjs-wasi's extensions) use .so: ext.so +// is a module, native.so is not and is not reported. +export function sharedLibraries() { + return [ + existsSync(new URL("./ext.so", import.meta.url).pathname), + existsSync(new URL("./native.so", import.meta.url).pathname), + ]; +} + export function inlineModule() { return ANSWER; } diff --git a/tests/coverage-fixtures/wasm/main.ts b/tests/coverage-fixtures/wasm/main.ts index a2d80b6b3..4e54283e7 100644 --- a/tests/coverage-fixtures/wasm/main.ts +++ b/tests/coverage-fixtures/wasm/main.ts @@ -1,9 +1,10 @@ // The WebAssembly modules this program can load are visible to the build in -// four ways (wasm/discover.ts): a path the compiler resolves (glue.js), an -// inline base64 literal (glue.js), a .wasm file shipped by a package whose -// code mentions WebAssembly (wasm-fixture-pkg), and the scriptc.wasm list in -// package.json (build/generated.wasm). -import { hasModule, inlineModule } from "./glue.js"; +// four ways (wasm/discover.ts): a path the compiler resolves (glue.js, +// including a .so shared library), an inline base64 literal (glue.js), a +// .wasm file shipped by a package whose code mentions WebAssembly +// (wasm-fixture-pkg), and the scriptc.wasm list in package.json +// (build/generated.wasm). +import { hasModule, inlineModule, sharedLibraries } from "./glue.js"; import { describeModule } from "wasm-fixture-pkg"; -console.log(hasModule(), inlineModule().length, describeModule()); +console.log(hasModule(), inlineModule().length, describeModule(), sharedLibraries()); diff --git a/tests/coverage-fixtures/wasm/native.so b/tests/coverage-fixtures/wasm/native.so new file mode 100644 index 000000000..66d7d9f62 Binary files /dev/null and b/tests/coverage-fixtures/wasm/native.so differ diff --git a/tests/diagnostics/arrow-bind.ts b/tests/diagnostics/arrow-bind.ts index c78db514b..0b677c5ef 100644 --- a/tests/diagnostics/arrow-bind.ts +++ b/tests/diagnostics/arrow-bind.ts @@ -1,4 +1,5 @@ -// Typed preset and rest signatures still exceed the callable adapter. +// Typed rest signatures still exceed the callable adapter. (A typed preset +// binds to a fixed signature and compiles.) const preset = ((value: number) => value).bind(null, 1); const rest = ((...values: number[]) => values.length).bind(null); export {}; diff --git a/tests/diagnostics/child-process.ts b/tests/diagnostics/child-process.ts index f96bce418..02b4349e8 100644 --- a/tests/diagnostics/child-process.ts +++ b/tests/diagnostics/child-process.ts @@ -42,3 +42,13 @@ const staticWorker = new URL("./child-process.ts", import.meta.url); fork(staticWorker, [], { serialization: "advanced" }); fork(staticWorker, [], { stdio: ["ignore", "ignore", "ignore", "ignore"] }); // Keep each fence on its own statement so diagnostics remain site-specific. +// An unknown 'data' chunk takes the setEncoding state established before +// the listener registers; a setEncoding placed elsewhere leaves it unclear. +const pipedOut = piped.stdout!; +pipedOut.on("data", (chunk: unknown) => console.log(String(chunk))); +pipedOut.setEncoding("utf8"); +// A setEncoding through a copy that can hold the same stream (a `let` +// binding here) leaves the state unclear as well. +let pipedErr = piped.stderr!; +pipedErr.setEncoding("utf8"); +piped.stderr!.on("data", (chunk: unknown) => console.log(String(chunk))); diff --git a/tests/diagnostics/comptime.ts b/tests/diagnostics/comptime.ts index 9ba882aaf..645779ea7 100644 --- a/tests/diagnostics/comptime.ts +++ b/tests/diagnostics/comptime.ts @@ -20,3 +20,14 @@ const nested = comptime(() => comptime(() => 1)); const eventually = comptime(async () => 1); const lied = comptime(() => 1 as unknown as string); + +// A record type reachable from its own fields has no literal form. +interface Chain { + value: number; + next: Chain | null; +} +const chain: Chain = comptime(() => ({ value: 1, next: null }) as Chain); + +// A union reachable from itself through an array has no literal form either. +type Tree = number | Tree[]; +const tree: Tree = comptime((): Tree => [1, [2, [3]]]); diff --git a/tests/diagnostics/fromentries-aliased-entries.ts b/tests/diagnostics/fromentries-aliased-entries.ts new file mode 100644 index 000000000..ee5cc5338 --- /dev/null +++ b/tests/diagnostics/fromentries-aliased-entries.ts @@ -0,0 +1,13 @@ +// `Object.fromEntries(...) as T` keeps the object only when the entries' +// values are scalars or checked-dynamic values. Native arrays and records +// in the entries would be copied, severing their identity, so the +// assertion keeps the exact-shape fence (corpus 6467 covers the cases that +// lower). +type Scores = { a: number[]; b: number[] }; +const shared = [10]; +const scores = Object.fromEntries([ + ["a", shared], + ["b", shared], +]) as Scores; +scores.a.push(11); +console.log(shared.length, scores.b.length); diff --git a/tests/diagnostics/json-shape/main.ts b/tests/diagnostics/json-shape/main.ts index 1d9552506..a46338d52 100644 --- a/tests/diagnostics/json-shape/main.ts +++ b/tests/diagnostics/json-shape/main.ts @@ -1,7 +1,7 @@ -/* A JSON document whose shape doesn't bake: a null-valued field has no - * standalone STATIC type, so the import reports the dynamic-family type - * diagnostic (SC2011 at the import site — the shape maps in the embedded - * engine) and uses of the binding poison. */ +/* A JSON document whose value doesn't bake: `1e400` parses to Infinity, + * which no number literal spells, so the import reports the bake failure + * at the import site and uses of the binding poison. (Its null-valued + * field bakes as null.) */ import bad from "./nulled.json" with { type: "json" }; console.log(bad.name); diff --git a/tests/diagnostics/json-shape/nulled.json b/tests/diagnostics/json-shape/nulled.json index fa4738449..5e506a6af 100644 --- a/tests/diagnostics/json-shape/nulled.json +++ b/tests/diagnostics/json-shape/nulled.json @@ -1 +1 @@ -{ "name": "x", "deprecated": null } +{ "name": "x", "deprecated": null, "limit": 1e400 } diff --git a/tests/diagnostics/util-inherits-runtime-class.ts b/tests/diagnostics/util-inherits-runtime-class.ts deleted file mode 100644 index f79b379b9..000000000 --- a/tests/diagnostics/util-inherits-runtime-class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// util.inherits onto a runtime-provided class (stream.Readable, the from2 -// and multistream shape in JavaScript) has no prototype object to link a -// constructor function's prototype to: the call fences where it is written -// instead of throwing Node's ERR_INVALID_ARG_TYPE at run time. -import { inherits } from "node:util"; -import { Readable } from "node:stream"; - -function Source(): void {} -inherits(Source, Readable); -console.log(typeof Source); diff --git a/tests/diagnostics/variadic-wrapper-fences.ts b/tests/diagnostics/variadic-wrapper-fences.ts new file mode 100644 index 000000000..d2ad65646 --- /dev/null +++ b/tests/diagnostics/variadic-wrapper-fences.ts @@ -0,0 +1,28 @@ +// Variadic generic wrappers specialize per call site; the forms that have +// no fixed signature or no static name keep precise refusals. +type AnyFn = (...args: any) => any; + +// `arguments` with no fixed signature to lower against. +const loose = function () { + return arguments[0]; +}; + +// `fn.name` where the argument's name is only known at run time. +function named(fn: F): string { + return fn.name; +} +function one(): number { + return 1; +} +function two(): number { + return 2; +} +const pick = (flag: boolean) => (flag ? one : two); +console.log(named(pick(true))); + +// Forwarding a fixed tuple to a variadic function value. +function forward(sink: (...xs: number[]) => number, ...args: A): number { + return sink.apply(null, args); +} +console.log(forward((...xs: number[]) => xs.length, 1, 2)); +export { loose }; diff --git a/tests/diagnostics/webassembly-fences.ts b/tests/diagnostics/webassembly-fences.ts index 56b2991de..fe90d41c9 100644 --- a/tests/diagnostics/webassembly-fences.ts +++ b/tests/diagnostics/webassembly-fences.ts @@ -1,30 +1,17 @@ -// No WebAssembly module compiles to native code yet: every reached use of -// the API refuses at its site, in each spelling, while declarations that -// only mention its types compile. -interface LoaderOptions { - wasm?: BufferSource | WebAssembly.Module; - imports?: WebAssembly.Imports; -} - -async function load(options: LoaderOptions, bytes: Uint8Array): Promise { - console.log(WebAssembly.validate(bytes)); +// The parts of the WebAssembly API scriptc does not implement yet refuse at +// each reached use, in each spelling. compile, instantiate, validate, the +// Module, Instance, Memory, Table and Global constructors, Module.imports, +// exports and customSections, and the error classes compile +// (tests/corpus/webassembly-*). +async function load(bytes: Uint8Array): Promise { const module = await WebAssembly.compile(bytes); - const { instance } = await WebAssembly.instantiate(bytes, options.imports); - console.log(instance instanceof WebAssembly.Instance, module); - const direct = new WebAssembly.Instance(new WebAssembly.Module(bytes)); - console.log(direct.exports); - const memory = new WebAssembly.Memory({ initial: 1 }); - console.log(memory.buffer.byteLength); - const api = globalThis.WebAssembly; - console.log(api); console.log(WebAssembly.Module.imports(module).length); + const streamed = await WebAssembly.instantiateStreaming(fetch("https://example.com/x.wasm")); + console.log(streamed.instance); + const Ctor = WebAssembly.Module; + console.log(Ctor); + const Memory = WebAssembly.Memory; + console.log(new Memory({ initial: 1 })); } -// pi's codemode spelling: the global object viewed through a cast. -interface WebAssemblyGlobal { - compile(bytes: Uint8Array): Promise; -} -const { WebAssembly: viewed } = globalThis as unknown as { WebAssembly: WebAssemblyGlobal }; -console.log(typeof viewed.compile); - -await load({}, new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0])); +await load(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0])); diff --git a/tests/fixtures/node-types/README.md b/tests/fixtures/node-types/README.md index 0784c57fe..243ce0b81 100644 --- a/tests/fixtures/node-types/README.md +++ b/tests/fixtures/node-types/README.md @@ -21,6 +21,7 @@ What the fixture pins (see tests/harness/project-config.test.ts): (process.uptime, Buffer.from, setInterval) reports the SC2020-family fence naming @types/node, instead of typechecking its way into a broken binary — and never a raw "Cannot find name" error. +- `event-loop-metrics.ts` and `timeout-type.ts` — performance.eventLoopUtilization, monitorEventLoopDelay's IntervalHistogram and NodeJS.Timeout as declared types lower under @types/node exactly as under the fallback declarations. - `source-import/` — an imported TypeScript source may use the `RequestInfo` global supplied by TypeScript's default DOM lib while scriptc adopts the project's @types/node declarations. Projects WITHOUT @types/node (every other fixture and the whole corpus) keep diff --git a/tests/fixtures/node-types/child-stdin-fences.ts b/tests/fixtures/node-types/child-stdin-fences.ts deleted file mode 100644 index 0859d8513..000000000 --- a/tests/fixtures/node-types/child-stdin-fences.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { spawn } from "node:child_process"; - -const child = spawn("node", []); -child.stdin.write("x", "utf8"); -child.stdin.end("x"); -child.stdin.destroy(new Error("stop")); diff --git a/tests/fixtures/node-types/child-stdin-streams.ts b/tests/fixtures/node-types/child-stdin-streams.ts new file mode 100644 index 000000000..c433d7bfb --- /dev/null +++ b/tests/fixtures/node-types/child-stdin-streams.ts @@ -0,0 +1,40 @@ +// child.stdin forms beyond write(string): a write with an encoding, end +// with a final chunk, and destroy with an error observed by an 'error' +// listener. They compile through the general stream representation, where +// child.stdin is the child's bridged Writable. +import { spawn } from "node:child_process"; + +function feed(): Promise { + return new Promise((resolve) => { + const child = spawn("cat", [], { stdio: ["pipe", "pipe", "inherit"] }); + let out = ""; + child.stdout.on("data", (chunk: Buffer) => { + out += chunk.toString(); + }); + child.on("close", (code) => { + console.log("fed", JSON.stringify(out), code); + resolve(); + }); + child.stdin.write("first ", "utf8"); + child.stdin.end("second\n"); + }); +} + +function abort(): Promise { + return new Promise((resolve) => { + const child = spawn("cat", [], { stdio: ["pipe", "ignore", "inherit"] }); + child.stdin.on("error", (err) => console.log("stdin error", err.message)); + child.on("close", (code) => { + console.log("aborted", code); + resolve(); + }); + child.stdin.destroy(new Error("stop")); + }); +} + +async function main(): Promise { + await feed(); + await abort(); +} + +void main(); diff --git a/tests/fixtures/node-types/event-loop-metrics.ts b/tests/fixtures/node-types/event-loop-metrics.ts new file mode 100644 index 000000000..f5c97c41b --- /dev/null +++ b/tests/fixtures/node-types/event-loop-metrics.ts @@ -0,0 +1,49 @@ +// Event-loop monitoring under @types/node: monitorEventLoopDelay's histogram, +// eventLoopUtilization deltas, and an unref'd interval typed NodeJS.Timeout. +import { monitorEventLoopDelay, performance } from "node:perf_hooks"; + +const histogram = monitorEventLoopDelay({ resolution: 10 }); +console.log("enable", histogram.enable(), histogram.enable()); +const first = performance.eventLoopUtilization(); +console.log("before loop", first.idle, first.active, first.utilization); + +let last = performance.eventLoopUtilization(); +let ticks = 0; +// The unref'd interval keeps nothing alive; this timer holds the loop open +// until the third sample. +const keepAlive = setTimeout(() => console.log("never"), 10_000); +const interval: NodeJS.Timeout = setInterval(() => { + const now = performance.eventLoopUtilization(); + const delta = performance.eventLoopUtilization(now, last); + last = now; + ticks++; + const p50 = histogram.percentile(50); + const p99 = histogram.percentile(99); + console.log( + "tick", + ticks, + delta.utilization >= 0 && delta.utilization <= 1, + delta.idle >= 0, + p50 > 0, + p99 >= p50, + histogram.max >= p99, + histogram.min <= p50, + histogram.count > 0, + ); + histogram.reset(); + console.log("after reset", histogram.count, histogram.max, histogram.min, Number.isNaN(histogram.mean)); + if (ticks === 3) { + clearInterval(interval); + clearTimeout(keepAlive); + console.log("disable", histogram.disable(), histogram.disable()); + const since = performance.eventLoopUtilization(first); + console.log("since", since.utilization > 0 && since.utilization <= 1, since.idle > 0); + try { + histogram.percentile(0); + } catch (e) { + console.log((e as Error).message, (e as { code?: string }).code); + } + } +}, 50); +interval.unref(); +console.log("hasRef", interval.hasRef()); diff --git a/tests/fixtures/node-types/node-stream-interfaces.ts b/tests/fixtures/node-types/node-stream-interfaces.ts new file mode 100644 index 000000000..2809dc315 --- /dev/null +++ b/tests/fixtures/node-types/node-stream-interfaces.ts @@ -0,0 +1,61 @@ +// @types/node's stream interfaces fed by every producer: NodeJS.ReadableStream +// and stream.Readable slots take file streams, a gunzip Transform and a +// child's stdout; NodeJS.WritableStream and stream.Writable slots take file +// streams and process.stdout. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { Readable, Writable } from "node:stream"; +import * as zlib from "node:zlib"; + +function drain(label: string, src: NodeJS.ReadableStream): Promise { + return new Promise((resolve, reject) => { + let text = ""; + src.on("data", (chunk: Buffer | string) => { + text += chunk.toString(); + }); + src.on("error", reject); + src.on("end", () => { + console.log(label, "end"); + resolve(text); + }); + }); +} + +function emit(dst: NodeJS.WritableStream, line: string): void { + dst.write(`${line}\n`); +} + +function finish(dst: Writable): Promise { + return new Promise((resolve) => dst.end(() => resolve())); +} + +async function main(): Promise { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "scriptc-node-types-streams-")); + const plain = path.join(dir, "plain.txt"); + const packed = path.join(dir, "packed.gz"); + fs.writeFileSync(plain, "from a file\n"); + fs.writeFileSync(packed, zlib.gzipSync(Buffer.from("from gunzip\n"))); + const file: Readable = fs.createReadStream(plain); + console.log(JSON.stringify(await drain("file", file))); + console.log(JSON.stringify(await drain("gunzip", fs.createReadStream(packed).pipe(zlib.createGunzip())))); + const child = spawn("sh", ["-c", "printf 'from a child\\n'"], { stdio: ["ignore", "pipe", "inherit"] }); + if (child.stdout) console.log(JSON.stringify(await drain("child", child.stdout))); + + const target = path.join(dir, "out.txt"); + const out: Writable = fs.createWriteStream(target); + emit(out, "to a file"); + emit(process.stdout, "to stdout"); + await finish(out); + console.log(JSON.stringify(fs.readFileSync(target, "utf8"))); + await new Promise((resolve) => { + const piped = fs.createReadStream(plain); + piped.on("end", () => resolve()); + piped.pipe(process.stdout); + }); + emit(process.stdout, "stdout still open"); + fs.rmSync(dir, { recursive: true }); +} + +void main(); diff --git a/tests/fixtures/node-types/stream-construction.ts b/tests/fixtures/node-types/stream-construction.ts new file mode 100644 index 000000000..a28643f7c --- /dev/null +++ b/tests/fixtures/node-types/stream-construction.ts @@ -0,0 +1,121 @@ +// Streams constructed under @types/node: option-bag Transform and +// PassThrough streams with @types/node's TransformCallback, a gunzip stage, +// fs.ReadStream listeners, and child-process listeners declared with +// unknown chunks and non-null exit types. +import { spawn } from "node:child_process"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { PassThrough, Transform } from "node:stream"; +import { createGunzip, gzipSync } from "node:zlib"; + +interface Progress { + bytes: number; + chunks: number; +} + +function createCounter(progress: Progress) { + return new Transform({ + transform(chunk, _encoding, callback) { + const length = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length; + progress.bytes += length; + progress.chunks++; + callback(null, chunk); + }, + flush(callback) { + callback(); + }, + }); +} + +function gunzipThrough(payload: Buffer): Promise { + return new Promise((resolve) => { + const progress: Progress = { bytes: 0, chunks: 0 }; + const counter = createCounter(progress); + const gunzip = createGunzip(); + const out = new PassThrough(); + const parts: string[] = []; + counter.pipe(gunzip).pipe(out); + out.on("data", (d: Buffer) => parts.push(d.toString())); + out.on("end", () => resolve(`${parts.join("")} ${progress.bytes > 0} ${progress.chunks}`)); + counter.end(payload); + }); +} + +function readFileStream(file: string): Promise { + return new Promise((resolve) => { + const stream = fs.createReadStream(file); + let text = ""; + const release = () => console.log("released"); + stream.on("close", release); + stream.on("error", release); + stream.on("data", (chunk) => { + text += chunk.toString(); + }); + stream.on("end", () => resolve(text)); + }); +} + +function run(script: string): Promise { + return new Promise((resolve, reject) => { + const child = spawn("/bin/sh", ["-c", script], { stdio: "pipe" }); + let stdout = ""; + let stderr = ""; + if (child.stdout) { + child.stdout.setEncoding("utf8"); + child.stdout.on("data", (c) => { + stdout += c; + }); + } + if (child.stderr) { + child.stderr.on("data", (c) => { + const chunk = String(c); + stderr += chunk; + }); + } + child.on("error", reject); + child.on("close", (code: number, signal: string) => { + if (code === 0) return resolve(stdout); + reject(new Error(`Exited with ${code || signal}: ${stderr.trim()}`)); + }); + }); +} + +// setEncoding returns its stream: a listener on the returned value, or on +// the stream after `const out = stream.setEncoding(...)`, receives strings. +function readEncoded(script: string): Promise { + return new Promise((resolve) => { + const child = spawn("/bin/sh", ["-c", script], { stdio: "pipe" }); + let outText = ""; + let errText = ""; + const out = child.stdout.setEncoding("utf8"); + out.on("data", (c: unknown) => { + outText += typeof c + ":" + String(c) + ";"; + }); + const err = child.stderr.setEncoding("utf8"); + child.stderr.on("data", (c: unknown) => { + errText += typeof c + ":" + String(c) + ";"; + }); + void err; + child.on("close", () => resolve(outText + " err " + errText)); + }); +} + +async function main(): Promise { + console.log("gunzip", await gunzipThrough(gzipSync(Buffer.from("payload")))); + const file = path.join(os.tmpdir(), `scriptc-stream-construction-${process.pid}.txt`); + fs.writeFileSync(file, "file text\n"); + console.log("file", JSON.stringify(await readFileStream(file))); + fs.unlinkSync(file); + console.log("run", JSON.stringify(await run("echo hi; echo warn >&2"))); + console.log("encoded", JSON.stringify(await readEncoded("printf hi; printf warn >&2"))); + for (const script of ["echo bad >&2; exit 3", "kill -TERM $$"]) { + try { + await run(script); + } catch (e) { + console.log("error", (e as Error).message); + } + } +} + +void main(); diff --git a/tests/fixtures/node-types/timeout-type.ts b/tests/fixtures/node-types/timeout-type.ts new file mode 100644 index 000000000..42daee86d --- /dev/null +++ b/tests/fixtures/node-types/timeout-type.ts @@ -0,0 +1,30 @@ +// NodeJS.Timeout as a declared type under @types/node: fields, clearTimeout, +// ref/unref/hasRef, refresh. +class Poller { + private timer: NodeJS.Timeout | undefined; + private count = 0; + start(): void { + this.timer = setInterval(() => { + this.count++; + console.log("poll", this.count); + if (this.count === 3) this.stop(); + }, 5); + } + stop(): void { + if (this.timer) { + clearInterval(this.timer); + this.timer = undefined; + console.log("stopped"); + } + } +} +new Poller().start(); +const t: NodeJS.Timeout = setTimeout(() => console.log("never"), 1000); +console.log(t.hasRef()); +t.unref(); +console.log(t.hasRef()); +t.ref(); +console.log(t.hasRef()); +clearTimeout(t); +const timers: NodeJS.Timeout[] = [setTimeout(() => console.log("a"), 30), setTimeout(() => console.log("b"), 31)]; +console.log(timers.length); diff --git a/tests/harness/__snapshots__/arrow-bind.ts.txt b/tests/harness/__snapshots__/arrow-bind.ts.txt index 4618bdfe2..d63201d59 100644 --- a/tests/harness/__snapshots__/arrow-bind.ts.txt +++ b/tests/harness/__snapshots__/arrow-bind.ts.txt @@ -1,17 +1,8 @@ -arrow-bind.ts:2:16 - error SC1100: passing 'unknown' values where '((null | undefined)[]) => number' is expected is not supported yet +arrow-bind.ts:4:14 - error SC1100: passing 'unknown' values where '(number[]) => number' is expected is not supported yet - 1 | // Typed preset and rest signatures still exceed the callable adapter. - 2 | const preset = ((value: number) => value).bind(null, 1); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 3 | const rest = ((...values: number[]) => values.length).bind(null); - - hint: validate with 'as ' first — the cast checks the dynamic value at runtime and throws on mismatch - -arrow-bind.ts:3:14 - error SC1100: passing 'unknown' values where '(number[]) => number' is expected is not supported yet - - 2 | const preset = ((value: number) => value).bind(null, 1); - 3 | const rest = ((...values: number[]) => values.length).bind(null); + 3 | const preset = ((value: number) => value).bind(null, 1); + 4 | const rest = ((...values: number[]) => values.length).bind(null); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 4 | export {}; + 5 | export {}; hint: validate with 'as ' first — the cast checks the dynamic value at runtime and throws on mismatch \ No newline at end of file diff --git a/tests/harness/__snapshots__/child-process.ts.txt b/tests/harness/__snapshots__/child-process.ts.txt index 2d83132f5..f5f9f8f86 100644 --- a/tests/harness/__snapshots__/child-process.ts.txt +++ b/tests/harness/__snapshots__/child-process.ts.txt @@ -91,4 +91,18 @@ child-process.ts:43:64 - error SC2020: 'fork without a fourth-slot IPC channel' | ^~~~~~~~ 44 | // Keep each fence on its own statement so diagnostics remain site-specific. - hint: the fourth stdio entry must be "ipc" \ No newline at end of file + hint: the fourth stdio entry must be "ipc" + +child-process.ts:48:21 - error SC1090: untyped child-stream 'data' listeners whose setEncoding state is unclear at their registration sites (declare the chunk as 'Buffer' or 'string') are not supported yet + + 47 | const pipedOut = piped.stdout!; + 48 | pipedOut.on("data", (chunk: unknown) => console.log(String(chunk))); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 49 | pipedOut.setEncoding("utf8"); + +child-process.ts:54:26 - error SC1090: untyped child-stream 'data' listeners whose setEncoding state is unclear at their registration sites (declare the chunk as 'Buffer' or 'string') are not supported yet + + 53 | pipedErr.setEncoding("utf8"); + 54 | piped.stderr!.on("data", (chunk: unknown) => console.log(String(chunk))); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 55 | \ No newline at end of file diff --git a/tests/harness/__snapshots__/comptime.ts.txt b/tests/harness/__snapshots__/comptime.ts.txt index 2b1411ae5..757c30e6c 100644 --- a/tests/harness/__snapshots__/comptime.ts.txt +++ b/tests/harness/__snapshots__/comptime.ts.txt @@ -45,4 +45,18 @@ comptime.ts:22:23 - error SC1110: comptime evaluation failed: expected 'string' 21 | 22 | const lied = comptime(() => 1 as unknown as string); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 23 | \ No newline at end of file + 23 | + +comptime.ts:29:22 - error SC1090: baking comptime results of type '{ next: null | ...; value: number }' into the binary (number, string, boolean, and arrays, records and unions of those lower to literals; a record or union type reachable from itself does not) is not supported yet + + 28 | } + 29 | const chain: Chain = comptime(() => ({ value: 1, next: null }) as Chain); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 30 | + +comptime.ts:33:20 - error SC1090: baking comptime results of type '(...)[] | number' into the binary (number, string, boolean, and arrays, records and unions of those lower to literals; a record or union type reachable from itself does not) is not supported yet + + 32 | type Tree = number | Tree[]; + 33 | const tree: Tree = comptime((): Tree => [1, [2, [3]]]); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 34 | \ No newline at end of file diff --git a/tests/harness/__snapshots__/coverage-wasm.txt b/tests/harness/__snapshots__/coverage-wasm.txt index 5b5bea36a..9d0ca414a 100644 --- a/tests/harness/__snapshots__/coverage-wasm.txt +++ b/tests/harness/__snapshots__/coverage-wasm.txt @@ -1,19 +1,22 @@ scriptc coverage tests/coverage-fixtures/wasm/main.ts - statements analyzed 8 - compile statically 6 (75%) - in dynamic tier 2 (operate on values typed only at runtime; --explain-dynamic lists them) + statements analyzed 9 + compile statically 9 (100%) + in dynamic tier 4 (operate on values typed only at runtime; --explain-dynamic lists them) npm package compilation: wasm-fixture-pkg static - WebAssembly modules: (found at build time; none compile to native code yet) + WebAssembly modules: (found at build time; valid ones compile to native code) inline module 39 bytes valid 1 function, 0 imports, 1 export found: inline at tests/coverage-fixtures/wasm/glue.js:5 tests/coverage-fixtures/wasm/add.wasm 41 bytes valid 1 function, 0 imports, 1 export found: path at tests/coverage-fixtures/wasm/glue.js:8 + tests/coverage-fixtures/wasm/ext.so 36 bytes valid + 1 function, 0 imports, 1 export + found: path at tests/coverage-fixtures/wasm/glue.js:15 tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm 27 bytes invalid: type mismatch (at byte 27) 1 function, 0 imports, 0 exports found: shipped by the package at tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg @@ -22,10 +25,4 @@ scriptc coverage tests/coverage-fixtures/wasm/main.ts features: simd found: configured by tests/coverage-fixtures/wasm/package.json - in unreached code (never lowered — cannot fail a build) - ×1 SC2004 uses of 'instance' inherit the blocker on its declaration - at tests/coverage-fixtures/wasm/glue.js:17:10 - hint: the declaration of 'instance' did not compile — fix the diagnostic reported there and these sites clear with it - ×1 SC2020 'WebAssembly.instantiate' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - at tests/coverage-fixtures/wasm/glue.js:16:30 - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) \ No newline at end of file + fully static — all analyzed statements compile to native code. \ No newline at end of file diff --git a/tests/harness/__snapshots__/fromentries-aliased-entries.ts.txt b/tests/harness/__snapshots__/fromentries-aliased-entries.ts.txt new file mode 100644 index 000000000..7b0f02266 --- /dev/null +++ b/tests/harness/__snapshots__/fromentries-aliased-entries.ts.txt @@ -0,0 +1,8 @@ +fromentries-aliased-entries.ts:8:16 - error SC2002: record shapes must match exactly or width-coerce: expected '{ a: number[]; b: number[] }', got '{ [key: string]: number[] }' — 'a' is not a declared field of the source, and the source's index signature could hold it at runtime (a completed undefined would drop that value) + + 7 | const shared = [10]; + 8 | const scores = Object.fromEntries([ + | ^~~~~~~~~~~~~~~~~~~~ + 9 | ["a", shared], + + hint: width subtyping compiles as a copy (each expected field copied off the source; extra fields drop) — this pair is outside the copy's rules; build a literal with exactly the expected fields instead \ No newline at end of file diff --git a/tests/harness/__snapshots__/json-shape/main.ts.txt b/tests/harness/__snapshots__/json-shape/main.ts.txt index b03f098a6..85f5d2917 100644 --- a/tests/harness/__snapshots__/json-shape/main.ts.txt +++ b/tests/harness/__snapshots__/json-shape/main.ts.txt @@ -1,6 +1,6 @@ -json-shape/main.ts:5:8 - error SC2001: values of type '{ name: string; deprecated: null; }' cannot be compiled yet (supported: number, string, boolean, arrays, Maps, Sets, RegExp, read-only Date values, functions, classes, records, unions of those, and 'unknown') +json-shape/main.ts:5:8 - error SC1110: comptime evaluation failed: expected 'number' at $.limit, got Infinity (only finite numbers can be written as literals) - 4 | * engine) and uses of the binding poison. */ + 4 | * field bakes as null.) */ 5 | import bad from "./nulled.json" with { type: "json" }; | ^~~ 6 | diff --git a/tests/harness/__snapshots__/util-inherits-runtime-class.ts.txt b/tests/harness/__snapshots__/util-inherits-runtime-class.ts.txt deleted file mode 100644 index 98c780646..000000000 --- a/tests/harness/__snapshots__/util-inherits-runtime-class.ts.txt +++ /dev/null @@ -1,8 +0,0 @@ -util-inherits-runtime-class.ts:9:18 - error SC2020: 'util.inherits onto the runtime-provided class 'Readable'' is part of the standard library types but has no scriptc lowering yet - - 8 | function Source(): void {} - 9 | inherits(Source, Readable); - | ^~~~~~~~ - 10 | console.log(typeof Source); - - hint: declare the subclass with extends \ No newline at end of file diff --git a/tests/harness/__snapshots__/variadic-wrapper-fences.ts.txt b/tests/harness/__snapshots__/variadic-wrapper-fences.ts.txt new file mode 100644 index 000000000..0cb2774d2 --- /dev/null +++ b/tests/harness/__snapshots__/variadic-wrapper-fences.ts.txt @@ -0,0 +1,29 @@ +variadic-wrapper-fences.ts:6:7 - error SC2009: values of type '() => any' cannot be compiled: the function shape is supported, but its signature is variadic ('arguments'-reading), and a compiled signature is fixed-arity + + 5 | // `arguments` with no fixed signature to lower against. + 6 | const loose = function () { + | ^~~~~ + 7 | return arguments[0]; + + hint: the outer shape is supported — the named component is the blocker; restate it inside the compilable set (number, string, boolean, arrays, Maps, Sets, RegExp, functions, classes, records, unions of those, and 'unknown') + +variadic-wrapper-fences.ts:7:10 - error SC1090: 'arguments' in a function expression whose value is not asserted to one fixed-arity signature (assert it, as in `function () { … } as F`, and the function lowers against that signature) is not supported yet + + 6 | const loose = function () { + 7 | return arguments[0]; + | ^~~~~~~~~ + 8 | }; + +variadic-wrapper-fences.ts:12:10 - error SC1090: reading 'fn.name' when the call passes a function whose name is only known at run time (generic wrappers fold the name of a function declaration, a const-bound function, or a wrapper call's result) is not supported yet (instantiating 'named' with <() => number>) + + 11 | function named(fn: F): string { + 12 | return fn.name; + | ^~~~~~~ + 13 | } + +variadic-wrapper-fences.ts:25:10 - error SC1090: forwarding a fixed argument tuple through 'apply' to a variadic function value is not supported yet (instantiating 'forward' with <[number, number]>) + + 24 | function forward(sink: (...xs: number[]) => number, ...args: A): number { + 25 | return sink.apply(null, args); + | ^~~~~~~~~~~~~~~~~~~~~~ + 26 | } \ No newline at end of file diff --git a/tests/harness/__snapshots__/webassembly-fences.ts.txt b/tests/harness/__snapshots__/webassembly-fences.ts.txt index da38a2c57..49c423707 100644 --- a/tests/harness/__snapshots__/webassembly-fences.ts.txt +++ b/tests/harness/__snapshots__/webassembly-fences.ts.txt @@ -1,98 +1,26 @@ -webassembly-fences.ts:10:15 - error SC2020: 'WebAssembly.validate' is not supported yet: scriptc does not compile WebAssembly modules to native code yet +webassembly-fences.ts:9:26 - error SC2020: 'WebAssembly.instantiateStreaming' is not supported yet: scriptc implements WebAssembly.compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, and the error classes over modules translated at build time, but not this part of the API - 9 | async function load(options: LoaderOptions, bytes: Uint8Array): Promise { - 10 | console.log(WebAssembly.validate(bytes)); - | ^~~~~~~~~~~~~~~~~~~~ - 11 | const module = await WebAssembly.compile(bytes); + 8 | console.log(WebAssembly.Module.imports(module).length); + 9 | const streamed = await WebAssembly.instantiateStreaming(fetch("https://example.com/x.wasm")); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 10 | console.log(streamed.instance); - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) + hint: the streaming functions, Tag and Exception, and the classes used as values other than with new and instanceof are planned; 'scriptc coverage' lists the modules this program loads (https://scriptc.dev/limitations) -webassembly-fences.ts:11:24 - error SC2020: 'WebAssembly.compile' is not supported yet: scriptc does not compile WebAssembly modules to native code yet +webassembly-fences.ts:11:16 - error SC2020: 'WebAssembly.Module' is not supported yet: scriptc implements WebAssembly.compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, and the error classes over modules translated at build time, but not this part of the API - 10 | console.log(WebAssembly.validate(bytes)); - 11 | const module = await WebAssembly.compile(bytes); - | ^~~~~~~~~~~~~~~~~~~ - 12 | const { instance } = await WebAssembly.instantiate(bytes, options.imports); + 10 | console.log(streamed.instance); + 11 | const Ctor = WebAssembly.Module; + | ^~~~~~~~~~~~~~~~~~ + 12 | console.log(Ctor); - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) + hint: the streaming functions, Tag and Exception, and the classes used as values other than with new and instanceof are planned; 'scriptc coverage' lists the modules this program loads (https://scriptc.dev/limitations) -webassembly-fences.ts:12:30 - error SC2020: 'WebAssembly.instantiate' is not supported yet: scriptc does not compile WebAssembly modules to native code yet +webassembly-fences.ts:13:18 - error SC2020: 'WebAssembly.Memory' is not supported yet: scriptc implements WebAssembly.compile, instantiate, validate, the Module, Instance, Memory, Table and Global constructors, Module.imports, exports and customSections, and the error classes over modules translated at build time, but not this part of the API - 11 | const module = await WebAssembly.compile(bytes); - 12 | const { instance } = await WebAssembly.instantiate(bytes, options.imports); - | ^~~~~~~~~~~~~~~~~~~~~~~ - 13 | console.log(instance instanceof WebAssembly.Instance, module); + 12 | console.log(Ctor); + 13 | const Memory = WebAssembly.Memory; + | ^~~~~~~~~~~~~~~~~~ + 14 | console.log(new Memory({ initial: 1 })); - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:13:35 - error SC2020: 'WebAssembly.Instance' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 12 | const { instance } = await WebAssembly.instantiate(bytes, options.imports); - 13 | console.log(instance instanceof WebAssembly.Instance, module); - | ^~~~~~~~~~~~~~~~~~~~ - 14 | const direct = new WebAssembly.Instance(new WebAssembly.Module(bytes)); - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:14:22 - error SC2020: 'new WebAssembly.Instance' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 13 | console.log(instance instanceof WebAssembly.Instance, module); - 14 | const direct = new WebAssembly.Instance(new WebAssembly.Module(bytes)); - | ^~~~~~~~~~~~~~~~~~~~ - 15 | console.log(direct.exports); - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:16:22 - error SC2020: 'new WebAssembly.Memory' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 15 | console.log(direct.exports); - 16 | const memory = new WebAssembly.Memory({ initial: 1 }); - | ^~~~~~~~~~~~~~~~~~ - 17 | console.log(memory.buffer.byteLength); - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:17:15 - error SC2004: uses of 'memory' inherit the blocker on its declaration - - 16 | const memory = new WebAssembly.Memory({ initial: 1 }); - 17 | console.log(memory.buffer.byteLength); - | ^~~~~~~~~~~~~~~~~~~~~~~~ - 18 | const api = globalThis.WebAssembly; - - hint: the declaration of 'memory' did not compile — fix the diagnostic reported there and these sites clear with it - -webassembly-fences.ts:18:15 - error SC2020: 'globalThis.WebAssembly' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 17 | console.log(memory.buffer.byteLength); - 18 | const api = globalThis.WebAssembly; - | ^~~~~~~~~~~~~~~~~~~~~~ - 19 | console.log(api); - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:19:15 - error SC2004: uses of 'api' inherit the blocker on its declaration - - 18 | const api = globalThis.WebAssembly; - 19 | console.log(api); - | ^~~ - 20 | console.log(WebAssembly.Module.imports(module).length); - - hint: the declaration of 'api' did not compile — fix the diagnostic reported there and these sites clear with it - -webassembly-fences.ts:20:15 - error SC2020: 'WebAssembly.Module.imports' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 19 | console.log(api); - 20 | console.log(WebAssembly.Module.imports(module).length); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~ - 21 | } - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) - -webassembly-fences.ts:27:33 - error SC2020: 'globalThis.WebAssembly' is not supported yet: scriptc does not compile WebAssembly modules to native code yet - - 26 | } - 27 | const { WebAssembly: viewed } = globalThis as unknown as { WebAssembly: WebAssemblyGlobal }; - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 28 | console.log(typeof viewed.compile); - - hint: WebAssembly support is planned as translation of each module whose bytes the build can see (an inline literal, or a file read from a path the compiler resolves) into native code; 'scriptc coverage' lists the modules this program would load (https://scriptc.dev/limitations) \ No newline at end of file + hint: the streaming functions, Tag and Exception, and the classes used as values other than with new and instanceof are planned; 'scriptc coverage' lists the modules this program loads (https://scriptc.dev/limitations) \ No newline at end of file diff --git a/tests/harness/corpus-costs/5817-constructor-function-instanceof.cjs.json b/tests/harness/corpus-costs/5817-constructor-function-instanceof.cjs.json new file mode 100644 index 000000000..15eedbeaa --- /dev/null +++ b/tests/harness/corpus-costs/5817-constructor-function-instanceof.cjs.json @@ -0,0 +1 @@ +{ "plain": 2655, "san": 7944 } diff --git a/tests/harness/corpus-costs/5818-constructor-function-emitter-defaults.cjs.json b/tests/harness/corpus-costs/5818-constructor-function-emitter-defaults.cjs.json new file mode 100644 index 000000000..0f4eb2e02 --- /dev/null +++ b/tests/harness/corpus-costs/5818-constructor-function-emitter-defaults.cjs.json @@ -0,0 +1 @@ +{ "plain": 2746, "san": 51663 } diff --git a/tests/harness/corpus-costs/6380-variadic-wrapper-arguments-apply.ts.json b/tests/harness/corpus-costs/6380-variadic-wrapper-arguments-apply.ts.json new file mode 100644 index 000000000..553943f5a --- /dev/null +++ b/tests/harness/corpus-costs/6380-variadic-wrapper-arguments-apply.ts.json @@ -0,0 +1 @@ +{ "plain": 3870, "san": 3660 } diff --git a/tests/harness/corpus-costs/6381-variadic-wrapper-async.ts.json b/tests/harness/corpus-costs/6381-variadic-wrapper-async.ts.json new file mode 100644 index 000000000..5cad95fef --- /dev/null +++ b/tests/harness/corpus-costs/6381-variadic-wrapper-async.ts.json @@ -0,0 +1 @@ +{ "plain": 3550, "san": 4820 } diff --git a/tests/harness/corpus-costs/6382-variadic-wrapper-methods-this.ts.json b/tests/harness/corpus-costs/6382-variadic-wrapper-methods-this.ts.json new file mode 100644 index 000000000..644fc5fea --- /dev/null +++ b/tests/harness/corpus-costs/6382-variadic-wrapper-methods-this.ts.json @@ -0,0 +1 @@ +{ "plain": 3000, "san": 6260 } diff --git a/tests/harness/corpus-costs/6383-variadic-wrapper-rest-tuple.ts.json b/tests/harness/corpus-costs/6383-variadic-wrapper-rest-tuple.ts.json new file mode 100644 index 000000000..f83a73df7 --- /dev/null +++ b/tests/harness/corpus-costs/6383-variadic-wrapper-rest-tuple.ts.json @@ -0,0 +1 @@ +{ "plain": 3140, "san": 4540 } diff --git a/tests/harness/corpus-costs/6384-variadic-wrapper-nested.ts.json b/tests/harness/corpus-costs/6384-variadic-wrapper-nested.ts.json new file mode 100644 index 000000000..21dee9274 --- /dev/null +++ b/tests/harness/corpus-costs/6384-variadic-wrapper-nested.ts.json @@ -0,0 +1 @@ +{ "plain": 3220, "san": 2960 } diff --git a/tests/harness/corpus-costs/6385-variadic-wrapper-shared-local-names.ts.json b/tests/harness/corpus-costs/6385-variadic-wrapper-shared-local-names.ts.json new file mode 100644 index 000000000..187f1764f --- /dev/null +++ b/tests/harness/corpus-costs/6385-variadic-wrapper-shared-local-names.ts.json @@ -0,0 +1 @@ +{ "plain": 2200, "san": 3300 } diff --git a/tests/harness/corpus-costs/6390-catch-binding-predicate.ts.json b/tests/harness/corpus-costs/6390-catch-binding-predicate.ts.json new file mode 100644 index 000000000..5b661172c --- /dev/null +++ b/tests/harness/corpus-costs/6390-catch-binding-predicate.ts.json @@ -0,0 +1 @@ +{ "plain": 3020, "san": 3560 } diff --git a/tests/harness/corpus-costs/6391-nullish-function-default.ts.json b/tests/harness/corpus-costs/6391-nullish-function-default.ts.json new file mode 100644 index 000000000..a3ae15ea4 --- /dev/null +++ b/tests/harness/corpus-costs/6391-nullish-function-default.ts.json @@ -0,0 +1 @@ +{ "plain": 4100, "san": 3150 } diff --git a/tests/harness/corpus-costs/6392-optional-chain-protocol-calls.ts.json b/tests/harness/corpus-costs/6392-optional-chain-protocol-calls.ts.json new file mode 100644 index 000000000..3fa72b729 --- /dev/null +++ b/tests/harness/corpus-costs/6392-optional-chain-protocol-calls.ts.json @@ -0,0 +1 @@ +{ "plain": 4400, "san": 4200 } diff --git a/tests/harness/corpus-costs/6393-function-types-any-params.ts.json b/tests/harness/corpus-costs/6393-function-types-any-params.ts.json new file mode 100644 index 000000000..73f790694 --- /dev/null +++ b/tests/harness/corpus-costs/6393-function-types-any-params.ts.json @@ -0,0 +1 @@ +{ "plain": 2790, "san": 3150 } diff --git a/tests/harness/corpus-costs/6394-in-key-error-subclasses.ts.json b/tests/harness/corpus-costs/6394-in-key-error-subclasses.ts.json new file mode 100644 index 000000000..6fe8b6765 --- /dev/null +++ b/tests/harness/corpus-costs/6394-in-key-error-subclasses.ts.json @@ -0,0 +1 @@ +{ "plain": 2900, "san": 3120 } diff --git a/tests/harness/corpus-costs/6395-generic-object-entries.ts.json b/tests/harness/corpus-costs/6395-generic-object-entries.ts.json new file mode 100644 index 000000000..d38b11826 --- /dev/null +++ b/tests/harness/corpus-costs/6395-generic-object-entries.ts.json @@ -0,0 +1 @@ +{ "plain": 2990, "san": 3030 } diff --git a/tests/harness/corpus-costs/6396-generic-any-instantiation.ts.json b/tests/harness/corpus-costs/6396-generic-any-instantiation.ts.json new file mode 100644 index 000000000..d38f92d43 --- /dev/null +++ b/tests/harness/corpus-costs/6396-generic-any-instantiation.ts.json @@ -0,0 +1 @@ +{ "plain": 2590, "san": 2850 } diff --git a/tests/harness/corpus-costs/6397-event-loop-metrics.ts.json b/tests/harness/corpus-costs/6397-event-loop-metrics.ts.json new file mode 100644 index 000000000..26c5a51a4 --- /dev/null +++ b/tests/harness/corpus-costs/6397-event-loop-metrics.ts.json @@ -0,0 +1 @@ +{ "plain": 3300, "san": 4140 } diff --git a/tests/harness/corpus-costs/6398-conditional-fixed-arity.ts.json b/tests/harness/corpus-costs/6398-conditional-fixed-arity.ts.json new file mode 100644 index 000000000..c8912b309 --- /dev/null +++ b/tests/harness/corpus-costs/6398-conditional-fixed-arity.ts.json @@ -0,0 +1 @@ +{ "plain": 3630, "san": 3870 } diff --git a/tests/harness/corpus-costs/6400-override-any-base.ts.json b/tests/harness/corpus-costs/6400-override-any-base.ts.json new file mode 100644 index 000000000..5ff4195cc --- /dev/null +++ b/tests/harness/corpus-costs/6400-override-any-base.ts.json @@ -0,0 +1 @@ +{"plain":4713} diff --git a/tests/harness/corpus-costs/6401-override-param-variance.ts.json b/tests/harness/corpus-costs/6401-override-param-variance.ts.json new file mode 100644 index 000000000..0f324b571 --- /dev/null +++ b/tests/harness/corpus-costs/6401-override-param-variance.ts.json @@ -0,0 +1 @@ +{"plain":3445} diff --git a/tests/harness/corpus-costs/6402-override-js-base/main.ts.json b/tests/harness/corpus-costs/6402-override-js-base/main.ts.json new file mode 100644 index 000000000..dafa7b34e --- /dev/null +++ b/tests/harness/corpus-costs/6402-override-js-base/main.ts.json @@ -0,0 +1 @@ +{"plain":5309} diff --git a/tests/harness/corpus-costs/6403-error-code-write.ts.json b/tests/harness/corpus-costs/6403-error-code-write.ts.json new file mode 100644 index 000000000..e4d08c9bb --- /dev/null +++ b/tests/harness/corpus-costs/6403-error-code-write.ts.json @@ -0,0 +1 @@ +{"plain":3632} diff --git a/tests/harness/corpus-costs/6404-error-in-and-assign.ts.json b/tests/harness/corpus-costs/6404-error-in-and-assign.ts.json new file mode 100644 index 000000000..12a27db7d --- /dev/null +++ b/tests/harness/corpus-costs/6404-error-in-and-assign.ts.json @@ -0,0 +1 @@ +{"plain":4787} diff --git a/tests/harness/corpus-costs/6405-wrapped-default-parameters.ts.json b/tests/harness/corpus-costs/6405-wrapped-default-parameters.ts.json new file mode 100644 index 000000000..2fe355bec --- /dev/null +++ b/tests/harness/corpus-costs/6405-wrapped-default-parameters.ts.json @@ -0,0 +1 @@ +{"plain":4127} diff --git a/tests/harness/corpus-costs/6406-npm-instance-receiver/main.ts.json b/tests/harness/corpus-costs/6406-npm-instance-receiver/main.ts.json new file mode 100644 index 000000000..0e304e2ed --- /dev/null +++ b/tests/harness/corpus-costs/6406-npm-instance-receiver/main.ts.json @@ -0,0 +1 @@ +{"plain":4693} diff --git a/tests/harness/corpus-costs/6409-catch-binding-shapes.ts.json b/tests/harness/corpus-costs/6409-catch-binding-shapes.ts.json new file mode 100644 index 000000000..072cdc179 --- /dev/null +++ b/tests/harness/corpus-costs/6409-catch-binding-shapes.ts.json @@ -0,0 +1 @@ +{"plain":3726} diff --git a/tests/harness/corpus-costs/6410-wrapper-untyped-results.ts.json b/tests/harness/corpus-costs/6410-wrapper-untyped-results.ts.json new file mode 100644 index 000000000..970974165 --- /dev/null +++ b/tests/harness/corpus-costs/6410-wrapper-untyped-results.ts.json @@ -0,0 +1 @@ +{"plain":3837} diff --git a/tests/harness/corpus-costs/6411-prototype-reset-constructors/main.ts.json b/tests/harness/corpus-costs/6411-prototype-reset-constructors/main.ts.json new file mode 100644 index 000000000..b2731b1c1 --- /dev/null +++ b/tests/harness/corpus-costs/6411-prototype-reset-constructors/main.ts.json @@ -0,0 +1 @@ +{"plain":4711} diff --git a/tests/harness/corpus-costs/6412-js-error-tostring-override/main.ts.json b/tests/harness/corpus-costs/6412-js-error-tostring-override/main.ts.json new file mode 100644 index 000000000..64c9f2e6d --- /dev/null +++ b/tests/harness/corpus-costs/6412-js-error-tostring-override/main.ts.json @@ -0,0 +1 @@ +{"plain":3803} diff --git a/tests/harness/corpus-costs/6413-override-js-async-base/main.ts.json b/tests/harness/corpus-costs/6413-override-js-async-base/main.ts.json new file mode 100644 index 000000000..eeb8f92e9 --- /dev/null +++ b/tests/harness/corpus-costs/6413-override-js-async-base/main.ts.json @@ -0,0 +1 @@ +{"plain":3820} diff --git a/tests/harness/corpus-costs/6414-catch-values-roundtrip.ts.json b/tests/harness/corpus-costs/6414-catch-values-roundtrip.ts.json new file mode 100644 index 000000000..502f0220d --- /dev/null +++ b/tests/harness/corpus-costs/6414-catch-values-roundtrip.ts.json @@ -0,0 +1 @@ +{"plain":4942} diff --git a/tests/harness/corpus-costs/6415-error-code-dynamic-writes.ts.json b/tests/harness/corpus-costs/6415-error-code-dynamic-writes.ts.json new file mode 100644 index 000000000..fb3867563 --- /dev/null +++ b/tests/harness/corpus-costs/6415-error-code-dynamic-writes.ts.json @@ -0,0 +1 @@ +{"plain":3425} diff --git a/tests/harness/corpus-costs/6453-constructor-function-emitter.cjs.json b/tests/harness/corpus-costs/6453-constructor-function-emitter.cjs.json new file mode 100644 index 000000000..a09a333d5 --- /dev/null +++ b/tests/harness/corpus-costs/6453-constructor-function-emitter.cjs.json @@ -0,0 +1 @@ +{ "plain": 4300, "san": 51474 } diff --git a/tests/harness/corpus-costs/6454-constructor-function-stream-bases.cjs.json b/tests/harness/corpus-costs/6454-constructor-function-stream-bases.cjs.json new file mode 100644 index 000000000..25987b67f --- /dev/null +++ b/tests/harness/corpus-costs/6454-constructor-function-stream-bases.cjs.json @@ -0,0 +1 @@ +{ "plain": 3371, "san": 3844 } diff --git a/tests/harness/corpus-costs/6465-optional-members-over-index-signature.ts.json b/tests/harness/corpus-costs/6465-optional-members-over-index-signature.ts.json new file mode 100644 index 000000000..93c788dd2 --- /dev/null +++ b/tests/harness/corpus-costs/6465-optional-members-over-index-signature.ts.json @@ -0,0 +1 @@ +{ "plain": 3225, "san": 26787 } diff --git a/tests/harness/corpus-costs/6466-never-assertion-argument.ts.json b/tests/harness/corpus-costs/6466-never-assertion-argument.ts.json new file mode 100644 index 000000000..4b7e88af5 --- /dev/null +++ b/tests/harness/corpus-costs/6466-never-assertion-argument.ts.json @@ -0,0 +1 @@ +{ "plain": 2895, "san": 23565 } diff --git a/tests/harness/corpus-costs/6467-fromentries-record-assertion.ts.json b/tests/harness/corpus-costs/6467-fromentries-record-assertion.ts.json new file mode 100644 index 000000000..390533b9e --- /dev/null +++ b/tests/harness/corpus-costs/6467-fromentries-record-assertion.ts.json @@ -0,0 +1 @@ +{ "plain": 3093, "san": 22400 } diff --git a/tests/harness/corpus-costs/6468-generic-unknown-record-entries.ts.json b/tests/harness/corpus-costs/6468-generic-unknown-record-entries.ts.json new file mode 100644 index 000000000..8489daced --- /dev/null +++ b/tests/harness/corpus-costs/6468-generic-unknown-record-entries.ts.json @@ -0,0 +1 @@ +{ "plain": 4560, "san": 4770 } diff --git a/tests/harness/corpus-costs/6468-node-stdio-writable-slot.ts.json b/tests/harness/corpus-costs/6468-node-stdio-writable-slot.ts.json new file mode 100644 index 000000000..3fafdfc4b --- /dev/null +++ b/tests/harness/corpus-costs/6468-node-stdio-writable-slot.ts.json @@ -0,0 +1 @@ +{ "plain": 3000, "san": 3500 } diff --git a/tests/harness/corpus-costs/6469-node-stdio-writable-js-pipe/main.ts.json b/tests/harness/corpus-costs/6469-node-stdio-writable-js-pipe/main.ts.json new file mode 100644 index 000000000..3fafdfc4b --- /dev/null +++ b/tests/harness/corpus-costs/6469-node-stdio-writable-js-pipe/main.ts.json @@ -0,0 +1 @@ +{ "plain": 3000, "san": 3500 } diff --git a/tests/harness/corpus-costs/webassembly-api.mjs.json b/tests/harness/corpus-costs/webassembly-api.mjs.json new file mode 100644 index 000000000..dd2a34243 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-api.mjs.json @@ -0,0 +1 @@ +{ "plain": 6776, "san": 5737 } diff --git a/tests/harness/corpus-costs/webassembly-dylink/main.mjs.json b/tests/harness/corpus-costs/webassembly-dylink/main.mjs.json new file mode 100644 index 000000000..0d6b0acf9 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-dylink/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 6843, "san": 50107 } diff --git a/tests/harness/corpus-costs/webassembly-externref-lifetimes.mjs.json b/tests/harness/corpus-costs/webassembly-externref-lifetimes.mjs.json new file mode 100644 index 000000000..d88c1b461 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-externref-lifetimes.mjs.json @@ -0,0 +1 @@ +{ "plain": 3200, "san": 5700 } diff --git a/tests/harness/corpus-costs/webassembly-jsapi.mjs.json b/tests/harness/corpus-costs/webassembly-jsapi.mjs.json new file mode 100644 index 000000000..0cf9acaeb --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-jsapi.mjs.json @@ -0,0 +1 @@ +{ "plain": 7155, "san": 9278 } diff --git a/tests/harness/corpus-costs/webassembly-lifetimes.mjs.json b/tests/harness/corpus-costs/webassembly-lifetimes.mjs.json new file mode 100644 index 000000000..0c9bada83 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-lifetimes.mjs.json @@ -0,0 +1 @@ +{ "plain": 2996, "san": 7565 } diff --git a/tests/harness/corpus-costs/webassembly-spec-control/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-control/main.mjs.json new file mode 100644 index 000000000..223969e02 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-control/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 6916, "san": 8022 } diff --git a/tests/harness/corpus-costs/webassembly-spec-float/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-float/main.mjs.json new file mode 100644 index 000000000..3a4a79b75 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-float/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 5393, "san": 6409 } diff --git a/tests/harness/corpus-costs/webassembly-spec-imports/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-imports/main.mjs.json new file mode 100644 index 000000000..ab57737bf --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-imports/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 4431, "san": 4894 } diff --git a/tests/harness/corpus-costs/webassembly-spec-int/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-int/main.mjs.json new file mode 100644 index 000000000..c3541f5ca --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-int/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 4576, "san": 5275 } diff --git a/tests/harness/corpus-costs/webassembly-spec-memory/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-memory/main.mjs.json new file mode 100644 index 000000000..074a854fe --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-memory/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 6100, "san": 7066 } diff --git a/tests/harness/corpus-costs/webassembly-spec-table/main.mjs.json b/tests/harness/corpus-costs/webassembly-spec-table/main.mjs.json new file mode 100644 index 000000000..da0d7c4e2 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-spec-table/main.mjs.json @@ -0,0 +1 @@ +{ "plain": 6712, "san": 7095 } diff --git a/tests/harness/corpus-costs/webassembly-typed.ts.json b/tests/harness/corpus-costs/webassembly-typed.ts.json new file mode 100644 index 000000000..e698fa802 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-typed.ts.json @@ -0,0 +1 @@ +{ "plain": 3602, "san": 3848 } diff --git a/tests/harness/corpus-costs/webassembly-worker.ts.json b/tests/harness/corpus-costs/webassembly-worker.ts.json new file mode 100644 index 000000000..b91ffeb21 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-worker.ts.json @@ -0,0 +1 @@ +{ "plain": 4051, "san": 4892 } diff --git a/tests/harness/corpus-costs/webassembly-wpt-jsapi.mjs.json b/tests/harness/corpus-costs/webassembly-wpt-jsapi.mjs.json new file mode 100644 index 000000000..dcd63ffe0 --- /dev/null +++ b/tests/harness/corpus-costs/webassembly-wpt-jsapi.mjs.json @@ -0,0 +1 @@ +{ "plain": 14016, "san": 15948 } diff --git a/tests/harness/coverage.test.ts b/tests/harness/coverage.test.ts index a23d4789d..cc91c0922 100644 --- a/tests/harness/coverage.test.ts +++ b/tests/harness/coverage.test.ts @@ -44,8 +44,9 @@ test("unreached blockers report in their own group", async () => { }); test("WebAssembly modules the build can see report with their sources", async () => { - // A resolved path and an inline literal (glue.js), a packaged .wasm - // (wasm-fixture-pkg), and package.json's scriptc.wasm list. + // A resolved path, a resolved .so shared library and an inline literal + // (glue.js), a packaged .wasm (wasm-fixture-pkg), and package.json's + // scriptc.wasm list. A resolved .so that is not a module is not reported. await expect(report(fixture("wasm/main.ts"))).toMatchFileSnapshot( "__snapshots__/coverage-wasm.txt", ); @@ -61,6 +62,7 @@ test("WebAssembly modules the build can see report with their sources", async () ).toEqual([ ["inline", "valid", [], ["inline"]], ["tests/coverage-fixtures/wasm/add.wasm", "valid", [], ["path", "config"]], + ["tests/coverage-fixtures/wasm/ext.so", "valid", [], ["path"]], [ "tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm", "invalid", @@ -70,7 +72,7 @@ test("WebAssembly modules the build can see report with their sources", async () ["tests/coverage-fixtures/wasm/build/generated.wasm", "unsupported", ["simd"], ["config"]], ]); const envelope = coverageEnvelope(coverage, { compilerVersion: "test" }); - expect(envelope.wasmModules?.map((m) => m.sha256.length)).toEqual([64, 64, 64, 64]); + expect(envelope.wasmModules?.map((m) => m.sha256.length)).toEqual([64, 64, 64, 64, 64]); }); test("divergences report as warnings, never as blockers", async () => { diff --git a/tests/harness/errors.test.ts b/tests/harness/errors.test.ts index 6d93675ef..c35022f51 100644 --- a/tests/harness/errors.test.ts +++ b/tests/harness/errors.test.ts @@ -1040,7 +1040,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () `(function () { var root = this; console.log("before"); - console.log(root === eval("this")); + process.on("__proto__", () => root); console.log("after"); }).call(this); `, @@ -1051,7 +1051,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () "speculative-apply", `(function () { console.log("before"); - console.log(typeof eval("1")); + process.on("__proto__", () => {}); }).apply(null, []); `, "before\n", @@ -1062,7 +1062,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () `class Base {} class Derived extends (function () { console.log("before"); - console.log(typeof eval("1")); + process.on("__proto__", () => {}); return Base; })() {} console.log(typeof Derived); @@ -1076,7 +1076,7 @@ console.log(typeof Derived); expect(r.stdout).toBe(stdout); expect(r.stderr).toMatch( new RegExp( - `^Uncaught Error: values of type '\\(x: string\\) => any' cannot be compiled: .* \\[SC2009 at .*${name}\\.cjs:${line}\\]\\n$`, + `^Uncaught Error: 'process\\.on\\("__proto__", \\.\\.\\.\\)' is part of the standard library types but has no scriptc lowering yet \\[SC2020 at .*${name}\\.cjs:${line}\\]\\n$`, ), ); }); diff --git a/tests/harness/library-asyncfree.test.ts b/tests/harness/library-asyncfree.test.ts index 0adbef7bc..7c4d029cc 100644 --- a/tests/harness/library-asyncfree.test.ts +++ b/tests/harness/library-asyncfree.test.ts @@ -73,6 +73,21 @@ describe("async_free detection over the IR", () => { ); }); + test("the event-loop metrics refuse", async () => { + expect( + await surfaceOf( + "eld", + `import { monitorEventLoopDelay } from "node:perf_hooks";\nconst h = monitorEventLoopDelay();\nconsole.log(h.enable());\n`, + ), + ).toContain("monitorEventLoopDelay"); + expect( + await surfaceOf( + "elu", + `import { performance } from "node:perf_hooks";\nconsole.log(performance.eventLoopUtilization().idle >= 0);\n`, + ), + ).toContain("eventLoopUtilization"); + }); + test("child_process refuses even in its synchronous spelling", async () => { expect( await surfaceOf( diff --git a/tests/harness/library-profile.test.ts b/tests/harness/library-profile.test.ts index eb1bcc4cd..2b28a6cd0 100644 --- a/tests/harness/library-profile.test.ts +++ b/tests/harness/library-profile.test.ts @@ -569,10 +569,13 @@ describe("library profile fences", () => { expect(processIds).toContain("node-builtin.process.isTTY"); expect(r.profile.fences[1]!.surfaces.every((s) => s.detector !== undefined)).toBe(true); // The user-timing timeline reads the same clock (mark() and measure() - // default to performance.now()), so it joins the perf_hooks family. + // default to performance.now()), and so do the event-loop metrics, so + // they join the perf_hooks family. expect(r.profile.fences[2]!.surfaces.map((s) => s.id)).toEqual([ + "node-builtin.perf_hooks.monitorEventLoopDelay", "node-builtin.perf_hooks.performance.clearMarks", "node-builtin.perf_hooks.performance.clearMeasures", + "node-builtin.perf_hooks.performance.eventLoopUtilization", "node-builtin.perf_hooks.performance.getEntries", "node-builtin.perf_hooks.performance.mark", "node-builtin.perf_hooks.performance.measure", diff --git a/tests/harness/npm.test.ts b/tests/harness/npm.test.ts index 25baaded6..168fdb6bd 100644 --- a/tests/harness/npm.test.ts +++ b/tests/harness/npm.test.ts @@ -60,7 +60,7 @@ const KNOWN: Record = { }, "island-web-plumbing": { run: "SC2020" }, "lazy-traps": { build: "SC2013" }, - "misc-shims": { build: "SC2013" }, + "misc-shims": { run: "SC2020" }, "namespace": { build: "SC1013" }, "node24-async-events": { run: "SC2020" }, "node24-commonjs-metadata": { run: "SC2020" }, diff --git a/tests/harness/project-config.test.ts b/tests/harness/project-config.test.ts index 742eb5b4f..1e1905368 100644 --- a/tests/harness/project-config.test.ts +++ b/tests/harness/project-config.test.ts @@ -52,6 +52,32 @@ test("node-types: filesystem capacity supports typed number and BigInt results u expect(comparableStderr(native.stderr)).toBe(node.stderr); }); +for (const [name, title] of [ + [ + "event-loop-metrics", + "eventLoopUtilization and monitorEventLoopDelay follow @types/node's types", + ], + ["timeout-type", "NodeJS.Timeout fields, ref/unref/hasRef and clearInterval under @types/node"], +] as const) { + test(`node-types: ${title}`, async () => { + const outDir = outDirFor(name); + const entry = join(nodeTypesDir, `${name}.ts`); + const result = await compile(entry, { + outPath: join(outDir, process.platform === "win32" ? `${name}.exe` : name), + outDir, + sanitize, + }); + expect(result.ok, !result.ok ? JSON.stringify(result.diagnostics, null, 2) : "").toBe(true); + if (!result.ok) return; + const [native, node] = await Promise.all([ + execFileAsync(result.binaryPath), + execFileAsync(process.execPath, ["--disable-warning=MODULE_TYPELESS_PACKAGE_JSON", entry]), + ]); + expect(native.stdout).toBe(node.stdout); + expect(comparableStderr(native.stderr)).toBe(node.stderr); + }); +} + test("node-types: http header arrays and server.address() follow @types/node's types", async () => { const outDir = outDirFor("http-headers-address"); const entry = join(nodeTypesDir, "http-headers-address.ts"); @@ -518,6 +544,42 @@ test("node-types: stream subclasses extend the @types/node stream classes", asyn expect(comparableStderr(native.stderr)).toBe(node.stderr); }); +test("node-types: NodeJS stream interfaces and stream.Readable/Writable take every stream producer", async () => { + const outDir = outDirFor("node-stream-interfaces"); + const entry = join(nodeTypesDir, "node-stream-interfaces.ts"); + const result = await compile(entry, { + outPath: join(outDir, "node-stream-interfaces"), + outDir, + sanitize, + }); + expect(result.ok, !result.ok ? JSON.stringify(result.diagnostics, null, 2) : "").toBe(true); + if (!result.ok) return; + const [native, node] = await Promise.all([ + execFileAsync(result.binaryPath), + execFileAsync(process.execPath, ["--disable-warning=MODULE_TYPELESS_PACKAGE_JSON", entry]), + ]); + expect(native.stdout).toBe(node.stdout); + expect(comparableStderr(native.stderr)).toBe(node.stderr); +}); + +test("node-types: streams construct and child listeners take @types/node's parameter types", async () => { + const outDir = outDirFor("stream-construction"); + const entry = join(nodeTypesDir, "stream-construction.ts"); + const result = await compile(entry, { + outPath: join(outDir, "stream-construction"), + outDir, + sanitize, + }); + expect(result.ok, !result.ok ? JSON.stringify(result.diagnostics, null, 2) : "").toBe(true); + if (!result.ok) return; + const [native, node] = await Promise.all([ + execFileAsync(result.binaryPath), + execFileAsync(process.execPath, ["--disable-warning=MODULE_TYPELESS_PACKAGE_JSON", entry]), + ]); + expect(native.stdout).toBe(node.stdout); + expect(comparableStderr(native.stderr)).toBe(node.stderr); +}); + test("node-types: promisified setTimeout and setImmediate lower as timers/promises", async () => { const outDir = outDirFor("promisify-timers"); const entry = join(nodeTypesDir, "promisify-timers.ts"); @@ -590,26 +652,22 @@ test("node-types: promisified dns lookups settle with the lookup objects", async expect(comparableStderr(native.stderr)).toBe(node.stderr); }); -test("node-types: unsupported child stdin forms remain named fences", async () => { - const dir = outDirFor("node-child-stdin-fences"); - const entry = join(nodeTypesDir, "child-stdin-fences.ts"); +test("node-types: child stdin forms beyond write(string) compile through the general stream representation", async () => { + const dir = outDirFor("node-child-stdin-streams"); + const entry = join(nodeTypesDir, "child-stdin-streams.ts"); const result = await compile(entry, { - outPath: join(dir, "child-stdin-fences"), + outPath: join(dir, "child-stdin-streams"), outDir: dir, sanitize, }); - expect(result.ok).toBe(false); - if (result.ok) return; - expect(result.diagnostics.map((diagnostic) => diagnostic.code)).toEqual([ - "SC2020", - "SC2020", - "SC2020", - ]); - expect(result.diagnostics.map((diagnostic) => diagnostic.message)).toEqual([ - expect.stringContaining("child stdin write with 2 arguments"), - expect.stringContaining("Writable.end"), - expect.stringContaining("Writable.destroy"), + expect(result.ok, !result.ok ? JSON.stringify(result.diagnostics, null, 2) : "").toBe(true); + if (!result.ok) return; + const [native, node] = await Promise.all([ + execFileAsync(result.binaryPath), + execFileAsync(process.execPath, ["--disable-warning=MODULE_TYPELESS_PACKAGE_JSON", entry]), ]); + expect(native.stdout).toBe(node.stdout); + expect(comparableStderr(native.stderr)).toBe(node.stderr); }); test("node-types: callback exec uses the typed ExecException overloads", async () => { diff --git a/tests/harness/self-hosting-native-toolchain.test.ts b/tests/harness/self-hosting-native-toolchain.test.ts index edb4b8b0f..f924845f1 100644 --- a/tests/harness/self-hosting-native-toolchain.test.ts +++ b/tests/harness/self-hosting-native-toolchain.test.ts @@ -30,6 +30,7 @@ const features: NativeLinkFeatures = { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -44,6 +45,7 @@ const features: NativeLinkFeatures = { tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, }; test("native toolchain configuration, staging and helper validation are static", async () => { diff --git a/tests/harness/self-hosting-runtime-features.test.ts b/tests/harness/self-hosting-runtime-features.test.ts index d2c2b589b..8d65d72cd 100644 --- a/tests/harness/self-hosting-runtime-features.test.ts +++ b/tests/harness/self-hosting-runtime-features.test.ts @@ -50,6 +50,7 @@ const featureCalls: readonly [string, IrLibFn][] = [ ["bigint", "bigint.parse"], ["searchParams", "sp.new"], ["qs", "qs.parse"], + ["dynBuiltinClass", "dyn.builtinClass"], ["parseArgs", "util.parseArgs"], ["parseArgs", "util.isDeepStrictEqual"], ["parseArgs", "util.styleText"], diff --git a/tests/harness/self-hosting-runtime-pack.test.ts b/tests/harness/self-hosting-runtime-pack.test.ts index 37db7637f..f8a280ef4 100644 --- a/tests/harness/self-hosting-runtime-pack.test.ts +++ b/tests/harness/self-hosting-runtime-pack.test.ts @@ -31,6 +31,7 @@ const base: NativeLinkFeatures = { bigint: false, searchParams: false, qs: false, + dynBuiltinClass: false, parseArgs: false, stream: false, net: false, @@ -45,6 +46,7 @@ const base: NativeLinkFeatures = { tlsCa: false, cipher: false, webcrypto: false, + perfLoop: false, }; test("runtime manifest validation and selection are entirely static", async () => { diff --git a/tests/harness/webassembly-memory-growth.test.ts b/tests/harness/webassembly-memory-growth.test.ts new file mode 100644 index 000000000..02fafe5ca --- /dev/null +++ b/tests/harness/webassembly-memory-growth.test.ts @@ -0,0 +1,96 @@ +/* WebAssembly memory growth while JavaScript holds views of the buffer — + * scriptc-only. + * + * Node detaches the previous ArrayBuffer when a memory grows (its views + * read as empty). scriptc does not detach it yet: the previous buffer and + * its views keep their length and keep aliasing the memory's storage, + * which therefore never moves, also in the explicitly bounds-checked + * configuration (sanitized builds, Windows) that has no guard pages. These + * pins check that writes through an old view and through the guest reach + * the same storage after growth, from JavaScript and from the guest. + * Under SCRIPTC_SAN=1 an access through a view of moved storage is an + * AddressSanitizer report. + */ +import { execFile } from "node:child_process"; +import { createHash } from "node:crypto"; +import { mkdirSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { promisify } from "node:util"; +import { describe, expect, test } from "vitest"; +import { compile } from "@scriptc/compiler"; + +const execFileAsync = promisify(execFile); +const repoRoot = join(import.meta.dirname, "../.."); +const cacheDir = join(repoRoot, "node_modules/.cache/scriptc-tests"); +const sanitize = process.env["SCRIPTC_SAN"] === "1"; + +// (module +// (memory (export "memory") 1 64) +// (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) +// (func (export "poke") (param i32 i32) (i32.store8 (local.get 0) (local.get 1))) +// (func (export "peek") (param i32) (result i32) (i32.load8_u (local.get 0)))) +const growthModule = + "AGFzbQEAAAABCwJgAX8Bf2ACf38AAwQDAAEABQQBAQFABx8EBm1lbW9yeQIABGdyb3cAAARwb2tlAAEEcGVlawACChoDBgAgAEAACwkAIAAgAToAAAsHACAALQAACw=="; + +async function run(name: string, source: string): Promise { + const key = createHash("sha256") + .update(source) + .update(sanitize ? "san" : "plain") + .digest("hex") + .slice(0, 16); + const outDir = join(cacheDir, `wasm-growth-${key}`); + mkdirSync(outDir, { recursive: true }); + const file = join(outDir, `${name}.mjs`); + writeFileSync(file, source); + const result = await compile(file, { + outPath: join(outDir, name), + outDir, + sanitize, + backend: "llvm", + }); + if (!result.ok) { + throw new Error( + "program failed to compile:\n" + + result.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n"), + ); + } + const { stdout } = await execFileAsync(result.binaryPath, [], { encoding: "utf8" }); + return stdout; +} + +describe(`WebAssembly memory growth with live views${sanitize ? " (sanitized)" : ""}`, () => { + test("Memory.prototype.grow keeps earlier views on the memory's storage", async () => { + const out = await run( + "js-growth", + `const bytes = Buffer.from("${growthModule}", "base64"); +const { memory } = new WebAssembly.Instance(new WebAssembly.Module(bytes)).exports; +const view = new Uint8Array(memory.buffer); +view[0] = 7; +for (let i = 0; i < 40; i++) memory.grow(1); +view[1] = 9; +const now = new Uint8Array(memory.buffer); +now[2] = 11; +console.log(view.length, now.length, now[0], now[1], view[2]); +`, + ); + expect(out).toBe("65536 2686976 7 9 11\n"); + }, 180_000); + + test("memory.grow in the guest keeps earlier views on the memory's storage", async () => { + const out = await run( + "guest-growth", + `const bytes = Buffer.from("${growthModule}", "base64"); +const { exports } = new WebAssembly.Instance(new WebAssembly.Module(bytes)); +const view = new Uint8Array(exports.memory.buffer); +view[0] = 7; +let pages = 0; +for (let i = 0; i < 40; i++) pages = exports.grow(1); +view[1] = 9; +exports.poke(2, 11); +const now = new Uint8Array(exports.memory.buffer); +console.log(pages, view.length, now.length, exports.peek(0), exports.peek(1), view[2], now[2]); +`, + ); + expect(out).toBe("40 65536 2686976 7 9 11 11\n"); + }, 180_000); +}); diff --git a/tests/wasm-spec/corpus/api.wat b/tests/wasm-spec/corpus/api.wat new file mode 100644 index 000000000..353a8421c --- /dev/null +++ b/tests/wasm-spec/corpus/api.wat @@ -0,0 +1,52 @@ +(module + (import "env" "log" (func $log (param i32))) + (import "env" "fail" (func $fail (param i32) (result i32))) + (import "env" "base" (global $base i32)) + (import "env" "big" (global $big i64)) + (memory (export "memory") 1 4) + (table (export "table") 2 8 funcref) + (global $counter (export "counter") (mut i32) (i32.const 0)) + (global (export "pi") f64 (f64.const 3.25)) + (global (export "big2") i64 (global.get $big)) + (data (i32.const 16) "scriptc\00") + (elem (i32.const 0) $double $square) + (type $unop (func (param i32) (result i32))) + (type $binop (func (param i32 i32) (result i32))) + (func $double (type $unop) (i32.mul (local.get 0) (i32.const 2))) + (func $square (type $unop) (i32.mul (local.get 0) (local.get 0))) + (start $init) + (func $init (call $log (global.get $base))) + (func (export "add") (type $binop) (i32.add (local.get 0) (local.get 1))) + (func (export "apply") (param i32 i32) (result i32) + (call_indirect (type $unop) (local.get 1) (local.get 0))) + (func (export "bump") (result i32) + (global.set $counter (i32.add (global.get $counter) (i32.const 1))) + (global.get $counter)) + (func (export "mul64") (param i64 i64) (result i64) (i64.mul (local.get 0) (local.get 1))) + (func (export "divmod") (param i32 i32) (result i32 i32) + (i32.div_s (local.get 0) (local.get 1)) (i32.rem_s (local.get 0) (local.get 1))) + (func (export "narrow") (param f32) (result f32) (local.get 0)) + (func (export "strlen") (param $p i32) (result i32) (local $n i32) + (block $done (loop $next + (br_if $done (i32.eqz (i32.load8_u (i32.add (local.get $p) (local.get $n))))) + (local.set $n (i32.add (local.get $n) (i32.const 1))) + (br $next))) + (local.get $n)) + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) + (func (export "pages") (result i32) (memory.size)) + (func (export "callFail") (param i32) (result i32) (i32.add (call $fail (local.get 0)) (i32.const 1))) + (func (export "trap") (param i32) (result i32) + (block $b6 (block $b5 (block $b4 (block $b3 (block $b2 (block $b1 (block $b0 + (br_table $b0 $b1 $b2 $b3 $b4 $b5 $b6 (local.get 0))) + unreachable) + (return (i32.div_u (i32.const 1) (i32.const 0)))) + (return (i32.load (i32.const 0x7fffffff)))) + (return (call_indirect (type $binop) (i32.const 1) (i32.const 2) (i32.const 0)))) + (return (call_indirect (type $unop) (i32.const 1) (i32.const 7)))) + (return (i32.trunc_f64_s (f64.const nan)))) + (i32.div_s (i32.const 0x80000000) (i32.const -1))) + (func $rec (export "recurse") (param i32) (result i32) + (i32.add (call $rec (i32.add (local.get 0) (i32.const 1))) (i32.const 1))) + (func (export "fill") (param i32 i32 i32) (memory.fill (local.get 0) (local.get 1) (local.get 2))) + (func (export "copy") (param i32 i32 i32) (memory.copy (local.get 0) (local.get 1) (local.get 2))) +) diff --git a/tests/wasm-spec/corpus/dylink-ext.wat b/tests/wasm-spec/corpus/dylink-ext.wat new file mode 100644 index 000000000..87023c646 --- /dev/null +++ b/tests/wasm-spec/corpus/dylink-ext.wat @@ -0,0 +1,42 @@ +;; tests/corpus/webassembly-dylink: an extension shaped like quickjs-wasi's +;; WebAssembly shared libraries (wasi-sdk -shared): it shares the main +;; module's memory and table, places its data and functions at the +;; __memory_base and __table_base the loader assigns, reaches the main +;; module through GOT.mem and GOT.func globals and env imports, and leaves +;; one symbol unresolved and one resolved by its own export. The program's +;; base64 copy appends the dylink.0 section: memory size 48 (alignment 2^2), +;; table size 2, needed "libc.so". +(module + (type $i_i (func (param i32) (result i32))) + (import "env" "memory" (memory 1)) + (import "env" "__indirect_function_table" (table 0 funcref)) + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "env" "__memory_base" (global $mb i32)) + (import "env" "__table_base" (global $tb i32)) + (import "GOT.mem" "counter" (global $got_counter (mut i32))) + (import "GOT.func" "helper" (global $got_helper (mut i32))) + (import "env" "js_register" (func $js_register (param i32 i32) (result i32))) + (import "env" "missing_symbol" (func $missing (param i32) (result i32))) + (import "env" "self_symbol" (func $self (param i32) (result i32))) + (data (global.get $mb) "name=demo\0aversion=1.2\00") + (elem (global.get $tb) $triple $via_helper) + (func $triple (type $i_i) (i32.mul (local.get 0) (i32.const 3))) + (func $via_helper (type $i_i) + (call_indirect (type $i_i) (local.get 0) (global.get $got_helper))) + (func (export "__wasm_apply_data_relocs") + (global.set $got_counter (i32.add (global.get $mb) (i32.const 32)))) + (func (export "__wasm_call_ctors") + (i32.store (global.get $got_counter) (i32.const 5))) + (func (export "qjs_ext_demo_init") (param i32 i32) (result i32) + (drop (call $js_register (local.get 0) (global.get $tb))) + (drop (call $js_register (local.get 0) (i32.add (global.get $tb) (i32.const 1)))) + (i32.sub (local.get 1) (i32.const 200))) + (func (export "qjs_ext_demo_versions") (result i32) (global.get $mb)) + (func (export "self_symbol") (param i32) (result i32) (i32.add (local.get 0) (i32.const 1))) + (func (export "use_self") (param i32) (result i32) (call $self (local.get 0))) + (func (export "use_missing") (param i32) (result i32) (call $missing (local.get 0))) + (func (export "stack_pointer") (result i32) (global.get $sp)) + (func (export "bump_counter") (result i32) + (i32.store (global.get $got_counter) (i32.add (i32.load (global.get $got_counter)) (i32.const 1))) + (i32.load (global.get $got_counter))) +) diff --git a/tests/wasm-spec/corpus/dylink-main.wat b/tests/wasm-spec/corpus/dylink-main.wat new file mode 100644 index 000000000..0cba26bb3 --- /dev/null +++ b/tests/wasm-spec/corpus/dylink-main.wat @@ -0,0 +1,33 @@ +;; tests/corpus/webassembly-dylink: the main module of a dynamically linked +;; program, shaped like quickjs-wasi's quickjs.wasm: it exports its memory, +;; its function table, __stack_pointer, malloc and the entry points an +;; extension's init function calls. +(module + (type $i_i (func (param i32) (result i32))) + (memory (export "memory") 2) + (table (export "__indirect_function_table") 4 funcref) + (global $sp (export "__stack_pointer") (mut i32) (i32.const 65536)) + (global $heap (mut i32) (i32.const 1024)) + (global $registered (mut i32) (i32.const 0)) + (func (export "malloc") (param i32) (result i32) + (local i32) + (local.set 1 (global.get $heap)) + (global.set $heap + (i32.and (i32.add (i32.add (global.get $heap) (local.get 0)) (i32.const 15)) (i32.const -16))) + (local.get 1)) + (func (export "qjs_get_context_ptr") (result i32) (i32.const 100)) + (func (export "qjs_get_runtime_ptr") (result i32) (i32.const 200)) + ;; js_register(ctx, tableIndex): remembers a function an extension adds. + (func (export "js_register") (param i32 i32) (result i32) + (i32.store + (i32.add (i32.const 512) (i32.mul (global.get $registered) (i32.const 4))) + (local.get 1)) + (global.set $registered (i32.add (global.get $registered) (i32.const 1))) + (global.get $registered)) + ;; js_call(n, x): calls the n-th registered function through the table. + (func (export "js_call") (param i32 i32) (result i32) + (call_indirect (type $i_i) + (local.get 1) + (i32.load (i32.add (i32.const 512) (i32.mul (local.get 0) (i32.const 4)))))) + (func (export "helper") (param i32) (result i32) (i32.add (local.get 0) (i32.const 1000))) +) diff --git a/tests/wasm-spec/corpus/externref-lifetimes.wat b/tests/wasm-spec/corpus/externref-lifetimes.wat new file mode 100644 index 000000000..ce7d9769e --- /dev/null +++ b/tests/wasm-spec/corpus/externref-lifetimes.wat @@ -0,0 +1,24 @@ +(module + (import "env" "make" (func $make (result externref))) + (import "env" "clear" (func $clear)) + (global $g (export "slot") (mut externref) (ref.null extern)) + (table $t (export "cells") 1 externref) + ;; An import's result, returned through an export. + (func (export "pass") (result externref) + (call $make)) + ;; A global's reference, read into a local, then replaced by the guest. + (func (export "takeGlobal") (result externref) (local $x externref) + (local.set $x (global.get $g)) + (global.set $g (ref.null extern)) + (local.get $x)) + ;; A table's reference, read into a local, then replaced by the guest. + (func (export "takeTable") (result externref) (local $x externref) + (local.set $x (table.get $t (i32.const 0))) + (table.set $t (i32.const 0) (ref.null extern)) + (local.get $x)) + ;; A global's reference, read into a local, then replaced by JavaScript + ;; during an import call. + (func (export "takeAcrossCall") (result externref) (local $x externref) + (local.set $x (global.get $g)) + (call $clear) + (local.get $x))) diff --git a/tests/wasm-spec/corpus/jsapi-own.wat b/tests/wasm-spec/corpus/jsapi-own.wat new file mode 100644 index 000000000..be2795793 --- /dev/null +++ b/tests/wasm-spec/corpus/jsapi-own.wat @@ -0,0 +1,11 @@ +;; tests/corpus/webassembly-jsapi.mjs: a module that defines and exports a +;; memory, a table and globals, exported twice each, for identity and for +;; importing what one instance exports into another. +(module + (memory (export "mem") (export "mem2") 1 4) + (table (export "tab") 2 8 funcref) + (global (export "g") (export "g2") (mut i32) (i32.const 7)) + (global (export "fixed") f64 (f64.const 1.5)) + (func (export "id") (param i32) (result i32) (local.get 0)) + (elem (i32.const 1) 0) +) diff --git a/tests/wasm-spec/corpus/jsapi.wat b/tests/wasm-spec/corpus/jsapi.wat new file mode 100644 index 000000000..63e2d4241 --- /dev/null +++ b/tests/wasm-spec/corpus/jsapi.wat @@ -0,0 +1,37 @@ +;; tests/corpus/webassembly-jsapi.mjs: imports of every kind, filled by the +;; Memory, Table and Global constructors. The program's base64 copy also +;; carries custom sections ("dylink.0" [1 2 3], "meta" "hello", "dylink.0" +;; [4 5] and "" []), appended after wat2wasm. +(module + (import "env" "log" (func $log (param i32))) + (import "env" "memory" (memory 1 4)) + (import "env" "table" (table 2 8 funcref)) + (import "env" "counter" (global $counter (mut i32))) + (import "env" "scale" (global $scale f64)) + (import "env" "big" (global $big (mut i64))) + (import "env" "ref" (global $ref (mut externref))) + (type $i_i (func (param i32) (result i32))) + (func $double (type $i_i) (i32.mul (local.get 0) (i32.const 2))) + (func $square (type $i_i) (i32.mul (local.get 0) (local.get 0))) + (elem (i32.const 0) $double $square) + (func (export "bump") (result i32) + (global.set $counter (i32.add (global.get $counter) (i32.const 1))) + (global.get $counter)) + (func (export "scaled") (param f64) (result f64) (f64.mul (local.get 0) (global.get $scale))) + (func (export "bigAdd") (param i64) (global.set $big (i64.add (global.get $big) (local.get 0)))) + (func (export "getRef") (result externref) (global.get $ref)) + (func (export "setRef") (param externref) (global.set $ref (local.get 0))) + (func (export "apply") (param i32 i32) (result i32) + (call_indirect (type $i_i) (local.get 1) (local.get 0))) + (func (export "store") (param i32 i32) (i32.store8 (local.get 0) (local.get 1))) + (func (export "load") (param i32) (result i32) (i32.load8_u (local.get 0))) + (func (export "size") (result i32) (memory.size)) + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) + (func (export "tableSize") (result i32) (table.size 0)) + (func (export "say") (param i32) (call $log (local.get 0))) + (export "memory" (memory 0)) + (export "table" (table 0)) + (export "counter" (global $counter)) + (export "alsoCounter" (global $counter)) + (export "double" (func $double)) +) diff --git a/tests/wasm-spec/corpus/lifetimes.wat b/tests/wasm-spec/corpus/lifetimes.wat new file mode 100644 index 000000000..e8569dce9 --- /dev/null +++ b/tests/wasm-spec/corpus/lifetimes.wat @@ -0,0 +1,23 @@ +(module + (import "env" "make" (func $make (result externref))) + (table $slots 1 externref) + (global $slot (mut externref) (ref.null extern)) + (memory 1) + (func (export "put") (param externref) + (table.set $slots (i32.const 0) (local.get 0))) + (func (export "take") (result externref) (local externref) + (local.set 0 (table.get $slots (i32.const 0))) + (table.set $slots (i32.const 0) (ref.null extern)) + (local.get 0)) + (func (export "putg") (param externref) + (global.set $slot (local.get 0))) + (func (export "takeg") (result externref) + (global.get $slot) + (global.set $slot (ref.null extern))) + (func (export "fresh") (result externref) + (call $make)) + ;; i32.load with the memory index written out (memarg flags 0x42, memory + ;; 0, offset 8). + (func (export "load") (result i32) + (i32.load 0 offset=8 (i32.const 0))) + (data (i32.const 8) "abcd")) diff --git a/tests/wasm-spec/corpus/linked.wat b/tests/wasm-spec/corpus/linked.wat new file mode 100644 index 000000000..28834b006 --- /dev/null +++ b/tests/wasm-spec/corpus/linked.wat @@ -0,0 +1,12 @@ +(module + (import "api" "memory" (memory 1)) + (import "api" "table" (table 2 funcref)) + (import "api" "counter" (global $c (mut i32))) + (import "api" "add" (func $add (param i32 i32) (result i32))) + (func (export "read") (param i32) (result i32) (i32.load8_u (local.get 0))) + (func (export "useTable") (param i32 i32) (result i32) + (call_indirect (param i32) (result i32) (local.get 1) (local.get 0))) + (func (export "setCounter") (param i32) (global.set $c (local.get 0))) + (func (export "add3") (param i32 i32 i32) (result i32) + (call $add (call $add (local.get 0) (local.get 1)) (local.get 2))) +) diff --git a/tests/wasm-spec/corpus/refs.wat b/tests/wasm-spec/corpus/refs.wat new file mode 100644 index 000000000..52516fa30 --- /dev/null +++ b/tests/wasm-spec/corpus/refs.wat @@ -0,0 +1,10 @@ +(module + (table $t (export "refs") 1 10 externref) + (global (export "slot") (mut externref) (ref.null extern)) + (func (export "keep") (param externref) (result externref) (local.get 0)) + (func (export "store") (param i32 externref) (table.set $t (local.get 0) (local.get 1))) + (func (export "load") (param i32) (result externref) (table.get $t (local.get 0))) + (func (export "isNull") (param externref) (result i32) (ref.is_null (local.get 0))) + (func (export "grow") (param externref i32) (result i32) (table.grow $t (local.get 0) (local.get 1))) + (func (export "size") (result i32) (table.size $t)) +) diff --git a/tests/wasm-spec/gen.mjs b/tests/wasm-spec/gen.mjs new file mode 100644 index 000000000..2b4e5c9fb --- /dev/null +++ b/tests/wasm-spec/gen.mjs @@ -0,0 +1,273 @@ +/* Regenerates the executed WebAssembly spec-test corpus programs + * (tests/corpus/webassembly-spec-/data.mjs): the binary modules and + * the commands of selected .wast files of the WebAssembly 2.0 core suite, + * which runner.mjs instantiates and invokes under Node and as a compiled + * binary. The differential harness compares the two outputs, so V8 is the + * oracle; the modules are inline base64 literals, which the build + * discovers and translates. + * + * node tests/wasm-spec/gen.mjs --wast2json /bin/wast2json \ + * --spec /test/core + * + * Left out: modules given as text, modules the decoder does not accept + * within the translatable feature level and every command that targets + * them, and commands with v128 values. The runner's spectest module + * provides the harness's memory and table (new WebAssembly.Memory and + * Table), so modules that import them run. Also left out, because they test NaN payloads, which neither + * side preserves the way the other does: actions whose f32 or f64 + * arguments are NaNs other than the canonical quiet NaN (V8 and scriptc + * carry NaN payloads through JavaScript numbers differently), and + * float_exprs.wast's actions that pass a signaling NaN's bit pattern to + * arithmetic that must quiet it (LLVM may fold `x - 0.0` to `x`, leaving + * the payload; WebAssembly requires a quiet NaN). Files with more than + * MAX_ACTIONS actions keep an evenly spaced + * sample of them (every module and register command stays), which keeps + * the generated programs small. + * + * Commands are compact tuples (runner.mjs reads them): + * ["file", name] + * ["module", line, moduleIndex, name?] instantiate, make current + * ["instantiate", line, moduleIndex] assert_un{linkable,instantiable} + * ["register", as, name?] + * ["invoke" | "get", line, name | 0, field, args] args: "type:value" + * The suite's tests are Apache-2.0 licensed (WebAssembly Community + * Group). */ +import { execFileSync } from "node:child_process"; +import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { parseArgs } from "node:util"; +import { analyzeWasm } from "../../packages/compiler/dist/wasm/binary.js"; + +export const GROUPS = { + int: ["i32", "i64", "int_exprs", "int_literals", "conversions", "traps"], + float: [ + "f32", + "f64", + "f32_cmp", + "f64_cmp", + "f32_bitwise", + "f64_bitwise", + "float_exprs", + "float_literals", + "float_misc", + ], + control: [ + "block", + "br", + "br_if", + "br_table", + "call", + "call_indirect", + "fac", + "forward", + "func", + "func_ptrs", + "if", + "labels", + "loop", + "local_get", + "local_set", + "local_tee", + "nop", + "return", + "select", + "stack", + "switch", + "unreachable", + "unwind", + "left-to-right", + "global", + "start", + ], + memory: [ + "address", + "align", + "endianness", + "float_memory", + "load", + "store", + "memory", + "memory_grow", + "memory_redundancy", + "memory_size", + "memory_trap", + "bulk", + "memory_copy", + "memory_fill", + "memory_init", + "data", + ], + table: [ + "table_copy", + "table_fill", + "table_get", + "table_grow", + "table_init", + "table_set", + "table_size", + "elem", + "ref_func", + "ref_is_null", + "ref_null", + "exports", + "linking", + ], + imports: ["imports", "table", "names"], +}; + +const MAX_ACTIONS = 400; + +const { values } = parseArgs({ + options: { wast2json: { type: "string" }, spec: { type: "string" } }, +}); +const repo = join(dirname(new URL(import.meta.url).pathname), "../.."); + +// Writes control and format characters (names.wast has several) as escapes, so the +// generated file holds the same strings without invisible characters in its source. +function escapeInvisible(literal) { + return literal.replace(/[\u007f-\u009f\u2028\u2029\p{Cf}]/gu, (c) => `\\u{${c.codePointAt(0).toString(16)}}`); +} + +function value(v) { + if (v.type === "v128") return null; + return `${v.type}:${v.value}`; +} + +/** Whether a "type:value" argument is a NaN other than the canonical + * quiet one. */ +function oddNaN(arg) { + const [type, text] = arg.split(":"); + if (type === "f32") { + const bits = Number(text); + return (bits & 0x7f800000) === 0x7f800000 && (bits & 0x7fffff) !== 0 && (bits & 0x7fffffff) !== 0x7fc00000; + } + if (type === "f64") { + const bits = BigInt(text); + const exp = 0x7ff0000000000000n; + const mantissa = bits & 0xfffffffffffffn; + return (bits & exp) === exp && mantissa !== 0n && (bits & 0x7fffffffffffffffn) !== 0x7ff8000000000000n; + } + return false; +} + +/** Whether a "type:value" integer argument is the bit pattern of a + * signaling NaN. */ +function signalingPattern(arg) { + const [type, text] = arg.split(":"); + if (type === "i32") { + const bits = Number(text) >>> 0; + return (bits & 0x7fc00000) === 0x7f800000 && (bits & 0x3fffff) !== 0; + } + if (type === "i64") { + const bits = BigInt.asUintN(64, BigInt(text)); + return (bits & 0x7ff8000000000000n) === 0x7ff0000000000000n && (bits & 0x7ffffffffffffn) !== 0n; + } + return false; +} + +/** Keeps every structural command and an evenly spaced sample of at most + * MAX_ACTIONS actions. */ +function sample(commands) { + const actions = commands.filter((c) => c[0] === "invoke" || c[0] === "get").length; + if (actions <= MAX_ACTIONS) return commands; + const step = actions / MAX_ACTIONS; + let seen = 0; + let next = 0; + return commands.filter((c) => { + if (c[0] !== "invoke" && c[0] !== "get") return true; + const keep = seen >= next; + seen++; + if (keep) next += step; + return keep; + }); +} + +for (const [group, names] of Object.entries(GROUPS)) { + const modules = []; + const moduleIndex = new Map(); + const commands = []; + for (const name of names) { + const dir = mkdtempSync(join(tmpdir(), "wasm-spec-")); + try { + execFileSync(values.wast2json, [join(values.spec, `${name}.wast`), "-o", join(dir, "x.json")], { + stdio: "pipe", + }); + const json = JSON.parse(readFileSync(join(dir, "x.json"), "utf8")); + const fileCommands = [["file", `${name}.wast`]]; + // Module names that refer to a module left out: their commands go too. + const skipped = new Set(); + let current = null; + let currentSkipped = false; + for (const c of json.commands) { + const where = c.line; + if (c.type === "module" || c.type === "assert_uninstantiable" || c.type === "assert_unlinkable") { + if (c.module_type === "text" || !c.filename?.endsWith(".wasm")) { + if (c.type === "module") { + currentSkipped = true; + if (c.name) skipped.add(c.name); + } + continue; + } + const bytes = readFileSync(join(dir, c.filename)); + const summary = analyzeWasm(new Uint8Array(bytes)); + if (summary.status !== "valid") { + if (c.type === "module") { + currentSkipped = true; + if (c.name) skipped.add(c.name); + } + continue; + } + const b64 = bytes.toString("base64"); + let index = moduleIndex.get(b64); + if (index === undefined) { + index = modules.length; + modules.push(b64); + moduleIndex.set(b64, index); + } + if (c.type === "module") { + current = c.name ?? null; + currentSkipped = false; + fileCommands.push(["module", where, index, ...(c.name ? [c.name] : [])]); + } else { + fileCommands.push(["instantiate", where, index]); + } + continue; + } + if (c.type === "register") { + const target = c.name ?? current; + if ((c.name ? skipped.has(c.name) : currentSkipped)) continue; + fileCommands.push(["register", c.as, ...(target ? [target] : [])]); + continue; + } + if (!c.action) continue; + const a = c.action; + const target = a.module ?? null; + if (target ? skipped.has(target) : currentSkipped) continue; + const args = (a.args ?? []).map(value); + const expected = (c.expected ?? []).map(value); + if (args.includes(null) || expected.includes(null)) continue; + if (args.some(oddNaN)) continue; + if (name === "float_exprs" && args.some(signalingPattern)) continue; + fileCommands.push([a.type === "get" ? "get" : "invoke", where, target ?? 0, a.field, args]); + } + commands.push(...sample(fileCommands)); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + } + const out = join(repo, `tests/corpus/webassembly-spec-${group}`); + mkdirSync(out, { recursive: true }); + const header = `/* Generated by tests/wasm-spec/gen.mjs from the WebAssembly 2.0 core test + * suite (WebAssembly/spec wg-2.0, Apache-2.0) with wabt 1.0.37 wast2json: + * ${names.map((n) => `${n}.wast`).join(", ")}. Do not edit. */\n`; + const body = + `export const modules = [\n${modules.map((m) => ` "${m}",`).join("\n")}\n];\n` + + `export const script = ${escapeInvisible(JSON.stringify(JSON.stringify(commands)))};\n`; + writeFileSync(join(out, "data.mjs"), header + body); + writeFileSync( + join(out, "main.mjs"), + `// Executes WebAssembly spec tests (${names.length} files); see tests/wasm-spec/runner.mjs.\nimport { run } from "../../wasm-spec/runner.mjs";\nimport { modules, script } from "./data.mjs";\n\nrun(modules, script);\n`, + ); + console.log(`${group}: ${modules.length} modules, ${commands.length} commands`); +} diff --git a/tests/wasm-spec/runner.mjs b/tests/wasm-spec/runner.mjs new file mode 100644 index 000000000..25e8ed393 --- /dev/null +++ b/tests/wasm-spec/runner.mjs @@ -0,0 +1,148 @@ +/* Executes WebAssembly spec-test commands (generated by gen.mjs) and prints + * one line per command. The webassembly-spec-* corpus programs call it; + * the differential harness runs them under Node and as compiled binaries + * and compares the output, so V8 decides every expected value, trap and + * error. Module bytes are inline base64 literals in each program's + * data.mjs, which the build translates. */ + +/** The spec harness's `spectest` module (the reference interpreter's JS + * harness), with its memory and table. */ +function spectestImports(log) { + return { + print() { + log("print"); + }, + print_i32(a) { + log(`print_i32 ${a}`); + }, + print_i64(a) { + log(`print_i64 ${a}`); + }, + print_f32(a) { + log(`print_f32 ${show(a)}`); + }, + print_f64(a) { + log(`print_f64 ${show(a)}`); + }, + print_i32_f32(a, b) { + log(`print_i32_f32 ${a} ${show(b)}`); + }, + print_f64_f64(a, b) { + log(`print_f64_f64 ${show(a)} ${show(b)}`); + }, + global_i32: 666, + global_i64: 666n, + global_f32: 666.6, + global_f64: 666.6, + table: new WebAssembly.Table({ initial: 10, maximum: 20, element: "anyfunc" }), + memory: new WebAssembly.Memory({ initial: 1, maximum: 2 }), + }; +} + +function show(v) { + if (typeof v === "bigint") return `${v}n`; + if (typeof v === "number") return Object.is(v, -0) ? "-0" : String(v); + if (v === null) return "null"; + if (v === undefined) return "undefined"; + if (typeof v === "function") return "function"; + if (Array.isArray(v)) return `[${v.map(show).join(",")}]`; + if (typeof v === "object" && typeof v.ref === "number") return `ref ${v.ref}`; + return typeof v; +} + +const refs = new Map(); + +function decode(arg) { + const colon = arg.indexOf(":"); + const type = arg.slice(0, colon); + const text = arg.slice(colon + 1); + if (type === "i32") return Number(text) | 0; + if (type === "i64") return BigInt.asIntN(64, BigInt(text)); + if (type === "f32") { + const view = new DataView(new ArrayBuffer(4)); + view.setUint32(0, Number(text)); + return view.getFloat32(0); + } + if (type === "f64") { + const view = new DataView(new ArrayBuffer(8)); + view.setBigUint64(0, BigInt(text)); + return view.getFloat64(0); + } + if (text === "null") return null; + const n = Number(text); + let ref = refs.get(n); + if (ref === undefined) { + ref = { ref: n }; + refs.set(n, ref); + } + return ref; +} + +function failure(e) { + return e instanceof Error ? `${e.name}: ${e.message}` : `threw ${show(e)}`; +} + +export function run(modules, script) { + const commands = JSON.parse(script); + const lines = []; + const log = (line) => { + lines.push(line); + }; + const imports = { spectest: spectestImports(log) }; + const named = new Map(); + let current = null; + const instantiate = (index) => + new WebAssembly.Instance(new WebAssembly.Module(Buffer.from(modules[index], "base64")), imports); + let file = ""; + for (const c of commands) { + const op = c[0]; + if (op === "file") { + file = c[1]; + log(`# ${file}`); + continue; + } + if (op === "register") { + const instance = c.length > 2 ? named.get(c[2]) : current; + if (instance) imports[c[1]] = instance.exports; + continue; + } + const at = `${file}:${c[1]}`; + if (op === "module") { + try { + current = instantiate(c[2]); + if (c.length > 3) named.set(c[3], current); + log(`${at} module`); + } catch (e) { + current = null; + log(`${at} module ${failure(e)}`); + } + continue; + } + if (op === "instantiate") { + try { + instantiate(c[2]); + log(`${at} instantiated`); + } catch (e) { + log(`${at} ${e instanceof Error ? e.name : "threw"}`); + } + continue; + } + const instance = c[2] !== 0 ? named.get(c[2]) : current; + if (!instance) { + log(`${at} no instance`); + continue; + } + try { + const target = instance.exports[c[3]]; + if (op === "get") { + log(`${at} ${show(target.value)}`); + continue; + } + const args = c[4].map(decode); + log(`${at} ${show(target(...args))}`); + } catch (e) { + log(`${at} ${failure(e)}`); + } + } + console.log(lines.join("\n")); +}