diff --git a/.gitignore b/.gitignore index e5b54a5fa..4922ef6df 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,9 @@ node_modules/ !tests/fixtures/npm/node_modules/ !tests/corpus/*/node_modules/ !tests/fixtures/npm-static/node_modules/ +!tests/coverage-fixtures/wasm/node_modules/ !tests/fixtures/npm-static/nested/inner/node_modules/ +!tests/fixtures/npm-static/node_modules/*/node_modules/ !tests/fixtures/npm/store/*/node_modules/ !tests/fixtures/npm/cases/*/node_modules/ !tests/library-mode/*/node_modules/ @@ -32,6 +34,7 @@ output/ !tests/fixtures/npm/cases/workspace-copied/members/*/dist/ !tests/fixtures/npm/cases/workspace-copied/node_modules/*/dist/ !tests/fixtures/provenance/node_modules/*/dist/ +!tests/fixtures/npm-static/node_modules/*/dist/ .scriptc/ *.log .DS_Store diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index 52cbf5026..0c5cad25f 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -270,6 +270,7 @@ "packages/compiler/src/backend/llvm/**", "packages/compiler/src/backend/loop-polls.test.ts", "packages/compiler/src/backend/may-throw.test.ts", + "packages/compiler/src/backend/stack-observations.test.ts", "packages/compiler/src/ir/**", "packages/compiler/src/library/*.test.ts", "packages/compiler/test/**", diff --git a/docs/content/docs/cli.mdx b/docs/content/docs/cli.mdx index bbe1da3c6..c4fdf7876 100644 --- a/docs/content/docs/cli.mdx +++ b/docs/content/docs/cli.mdx @@ -133,6 +133,9 @@ Verifies and loads the installed precompiled runtime objects and vendored librar
--explain-dynamic[=<name>]
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.
+
--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/docs/limitations.mdx b/docs/content/docs/limitations.mdx index 6f21e2ce3..ae166836f 100644 --- a/docs/content/docs/limitations.mdx +++ b/docs/content/docs/limitations.mdx @@ -120,6 +120,8 @@ title: "Limitations" ../limitations/builtin-apis/synchronous-iteration.mdx +../limitations/builtin-apis/iterator-helpers.mdx + ../limitations/builtin-apis/regular-expressions.mdx ../limitations/builtin-apis/object-freezing.mdx @@ -238,6 +240,10 @@ title: "Limitations" ../limitations/native-addons.mdx +## WebAssembly modules + +../limitations/webassembly-modules.mdx + ## WASI target ../limitations/wasi-target.mdx diff --git a/docs/content/limitations/builtin-apis/iterator-helpers.mdx b/docs/content/limitations/builtin-apis/iterator-helpers.mdx new file mode 100644 index 000000000..01f779cb6 --- /dev/null +++ b/docs/content/limitations/builtin-apis/iterator-helpers.mdx @@ -0,0 +1 @@ +- **Iterator helpers:** `map`, `filter`, `take`, `drop`, `flatMap`, `toArray`, `forEach`, `reduce`, `some`, `every` and `find` compile on generators, on array, Map and Set iterators, and on the objects the helpers return. Helper objects support `.next()`, `for...of`, spreads, `Array.from` and `yield*`, pull their source lazily, and close it (run its `return()`) at the same points as Node: when `take` reaches its count, when a short-circuiting method finds its answer, when a callback throws, and when the loop consuming the helper exits early. `flatMap` callbacks return arrays or generators. Iterator helpers on string iterators, `Iterator.from`, the `Iterator` global, calling `return()` on a helper object in TypeScript, printing helper objects, and helper calls on untyped iterators in JavaScript are unsupported. diff --git a/docs/content/limitations/builtin-apis/map-and-set.mdx b/docs/content/limitations/builtin-apis/map-and-set.mdx index 1c9c28c20..4ff02758c 100644 --- a/docs/content/limitations/builtin-apis/map-and-set.mdx +++ b/docs/content/limitations/builtin-apis/map-and-set.mdx @@ -1 +1 @@ -- **Map and Set:** Keys and elements support numbers and strings by value, and records, classes, arrays, functions, symbols, server handles, and unions of these reference types by identity. Map values may also be functions. `unknown` slots use native checked values, comparing supported primitives by value and retaining supported object references. Typed nested collections other than `Map` and `Set`, and promises requiring payload adapters, cannot pass into these slots. `Promise` retains its native representation. Stored `keys()`, `values()`, and `entries()` iterators compile, retain element identity, and observe live collection mutations until exhausted. They support `.next()`, `for...of`, array spreads, and mapper-less `Array.from`. Detached collection methods and iterator helper methods such as `.map()` and `.take()` are unsupported. The Set composition methods (`union`, `intersection`, `difference`, `symmetricDifference`, `isSubsetOf`, `isSupersetOf`, `isDisjointFrom`) accept a Set of the same element type or a Map keyed by it; other set-like arguments are unsupported. +- **Map and Set:** Keys and elements support numbers and strings by value, and records, classes, arrays, functions, symbols, server handles, and unions of these reference types by identity. Map values may also be functions. `unknown` slots use native checked values, comparing supported primitives by value and retaining supported object references. Typed nested collections other than `Map` and `Set`, and promises requiring payload adapters, cannot pass into these slots. `Promise` retains its native representation. Stored `keys()`, `values()`, and `entries()` iterators compile, retain element identity, and observe live collection mutations until exhausted. They support `.next()`, `for...of`, array spreads, and mapper-less `Array.from`. They also support the iterator helper methods, such as `.map()` and `.take()`. Detached collection methods are unsupported. The Set composition methods (`union`, `intersection`, `difference`, `symmetricDifference`, `isSubsetOf`, `isSupersetOf`, `isDisjointFrom`) accept a Set of the same element type or a Map keyed by it; other set-like arguments are unsupported. diff --git a/docs/content/limitations/types-and-class-definitions/local-class-expressions.mdx b/docs/content/limitations/types-and-class-definitions/local-class-expressions.mdx index 1f60c6101..d18ecac60 100644 --- a/docs/content/limitations/types-and-class-definitions/local-class-expressions.mdx +++ b/docs/content/limitations/types-and-class-definitions/local-class-expressions.mdx @@ -1 +1 @@ -- **Local class expressions:** Static members, decorators, private brands, generic members, explicitly generic factories returning local constructors, and references through the class's internal name are unsupported. Supported expressions preserve fresh constructor identity and shared captures across constructors, methods, accessors, and arrow fields. Local inheritance requires a compiled base class. Constructors retain identity, `typeof`, `name`, and `length` through `unknown`; cast back to their exact type before construction. Construction and static-member access directly through `unknown` are unsupported. +- **Local class expressions:** Static members, decorators, private brands, generic members, and references through the class's internal name are unsupported. Supported expressions preserve fresh constructor identity and shared captures across constructors, methods, accessors, and arrow fields. Local inheritance requires a compiled base class. Constructors retain identity, `typeof`, `name`, and `length` through `unknown`; cast back to their exact type before construction. Construction and static-member access directly through `unknown` are unsupported. diff --git a/docs/content/limitations/webassembly-modules.mdx b/docs/content/limitations/webassembly-modules.mdx new file mode 100644 index 000000000..492b2fc1a --- /dev/null +++ b/docs/content/limitations/webassembly-modules.mdx @@ -0,0 +1,3 @@ +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 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`. diff --git a/docs/src/generated/node-v24-compatibility-meta.json b/docs/src/generated/node-v24-compatibility-meta.json index f03a39e85..1cf76d3e4 100644 --- a/docs/src/generated/node-v24-compatibility-meta.json +++ b/docs/src/generated/node-v24-compatibility-meta.json @@ -2,6 +2,6 @@ "schemaVersion": 3, "nodeVersion": "24.22.0", "nodeCommit": "f14cd3aa7bf9ca8df2cc5b8bb14beb0f335b1d93", - "artifactVersion": "4421a7b808191ac7f410", + "artifactVersion": "efc18bcd8a7a03fd8622", "rowCount": 3880 } diff --git a/docs/src/generated/node-v24-compatibility.json b/docs/src/generated/node-v24-compatibility.json index 7a9e0e2a2..0e6387ea9 100644 --- a/docs/src/generated/node-v24-compatibility.json +++ b/docs/src/generated/node-v24-compatibility.json @@ -330,8 +330,8 @@ "static": { "supported": 0, "partial": 12, - "refused": 0, - "not-implemented": 80, + "refused": 1, + "not-implemented": 79, "by-design": 0, "unreviewed": 0, "not-applicable": 0 @@ -36590,9 +36590,9 @@ "inherited": true }, "static": { - "status": "not-implemented", - "detail": "No static compiler lowering is registered for this API yet.", - "verification": "registry-gap" + "status": "refused", + "detail": "Explicitly rejected by a named compiler diagnostic.", + "verification": "explicit-refusal" } }, { diff --git a/internal/compatibility/generated/node-v24-backlog.json b/internal/compatibility/generated/node-v24-backlog.json index 0fba7781e..b7d05cbea 100644 --- a/internal/compatibility/generated/node-v24-backlog.json +++ b/internal/compatibility/generated/node-v24-backlog.json @@ -8,8 +8,8 @@ "tiers": { "static": { "audit-partial": 1162, - "verify-gap": 2167, - "replace-refusal": 40, + "verify-gap": 2166, + "replace-refusal": 41, "classify": 2, "implement": 85 } @@ -34178,11 +34178,11 @@ "priority": "high", "tiers": { "static": { - "status": "not-implemented", - "action": "verify-gap", - "verification": "registry-gap", - "confidence": "low", - "source": "compiler-unmatched:globals", + "status": "refused", + "action": "replace-refusal", + "verification": "explicit-refusal", + "confidence": "high", + "source": "surface-manifest:unsupported:stdlib.webassembly", "tests": [] } } diff --git a/internal/compatibility/generated/node-v24-internal.json b/internal/compatibility/generated/node-v24-internal.json index b755a95e8..fba445393 100644 --- a/internal/compatibility/generated/node-v24-internal.json +++ b/internal/compatibility/generated/node-v24-internal.json @@ -342,8 +342,8 @@ "static": { "supported": 0, "partial": 12, - "refused": 0, - "not-implemented": 80, + "refused": 1, + "not-implemented": 79, "by-design": 0, "unreviewed": 0, "not-applicable": 0 @@ -53521,8 +53521,8 @@ "inherited": true }, "static": { - "status": "not-implemented", - "evidence": "compiler-unmatched:globals" + "status": "refused", + "evidence": "surface-manifest:unsupported:stdlib.webassembly" }, "anchorSource": "exact" }, diff --git a/internal/compatibility/src/generate.mjs b/internal/compatibility/src/generate.mjs index dfefc6e48..3433e14f9 100644 --- a/internal/compatibility/src/generate.mjs +++ b/internal/compatibility/src/generate.mjs @@ -203,6 +203,10 @@ function featureOf(row, entries, parentSignature) { function symbolCandidates(row) { const result = new Set([row.apiSymbol]); + // A global's own row (`WebAssembly`) matches the compiler's + // `globalThis.` entries. + if (row.chapter === "globals" && row.apiSymbol && !row.apiSymbol.includes(".")) + result.add(`globalThis.${row.apiSymbol}`); const aliases = [ ["fsPromises.", "fs/promises."], ["dnsPromises.", "dns/promises."], diff --git a/packages/compiler/ambient/scriptc.d.ts b/packages/compiler/ambient/scriptc.d.ts index 424e49065..cec26f139 100644 --- a/packages/compiler/ambient/scriptc.d.ts +++ b/packages/compiler/ambient/scriptc.d.ts @@ -13,6 +13,9 @@ * they MERGE as overloads instead of colliding — the Timeout handle maps * to the numeric timer id either way, and .unref()/.ref()/.hasRef() are * loop-liveness bookkeeping). + * 4. The WebAssembly namespace and BufferSource, which the DOM library + * supplies in ordinary TypeScript projects (types only; every reached + * use of the API is refused at its site). * * This file ships to EVERY program scriptc builds — the lowering program * and preflight's project-world second-chance program alike (a project @@ -108,3 +111,134 @@ declare function clearTimeout(handle?: Timeout | number | null | undefined): voi * baked result is exactly what Node would compute at runtime (the * differential harness verifies this with a `comptime = (f) => f()` shim). */ declare function comptime(compute: () => T): T; + +/* The JavaScript WebAssembly API, as the DOM library declares it (scriptc's + * ES-only type world never loads lib.dom, and @types/node leaves it to + * lib.dom). Packages whose declarations name these types (quickjs-wasi, + * photon-node, ...) typecheck against them. These are types only: the + * type mapper gives every type declared here the checked-dynamic + * representation, and the lowerer refuses each reached use of the API with + * a located diagnostic (frontend/lowering/builtins/webassembly.ts). + * BufferSource admits every ArrayBufferView, as lib.dom did before + * TypeScript 5.7: Node's Buffer types are views over ArrayBufferLike. */ +type BufferSource = ArrayBufferView | ArrayBuffer; +declare namespace WebAssembly { + interface CompileError extends Error {} + var CompileError: { + prototype: CompileError; + new (message?: string): CompileError; + (message?: string): CompileError; + }; + interface Global { + value: ValueTypeMap[T]; + valueOf(): ValueTypeMap[T]; + } + var Global: { + prototype: Global; + new ( + descriptor: GlobalDescriptor, + v?: ValueTypeMap[T], + ): Global; + }; + interface Instance { + readonly exports: Exports; + } + var Instance: { + prototype: Instance; + new (module: Module, importObject?: Imports): Instance; + }; + interface LinkError extends Error {} + var LinkError: { + prototype: LinkError; + new (message?: string): LinkError; + (message?: string): LinkError; + }; + interface Memory { + readonly buffer: ArrayBuffer; + grow(delta: number): number; + } + var Memory: { + prototype: Memory; + new (descriptor: MemoryDescriptor): Memory; + }; + interface Module {} + var Module: { + prototype: Module; + new (bytes: BufferSource): Module; + customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]; + exports(moduleObject: Module): ModuleExportDescriptor[]; + imports(moduleObject: Module): ModuleImportDescriptor[]; + }; + interface RuntimeError extends Error {} + var RuntimeError: { + prototype: RuntimeError; + new (message?: string): RuntimeError; + (message?: string): RuntimeError; + }; + interface Table { + readonly length: number; + get(index: number): any; + grow(delta: number, value?: any): number; + set(index: number, value?: any): void; + } + var Table: { + prototype: Table; + new (descriptor: TableDescriptor, value?: any): Table; + }; + interface GlobalDescriptor { + mutable?: boolean; + value: T; + } + interface MemoryDescriptor { + initial: number; + maximum?: number; + shared?: boolean; + } + interface ModuleExportDescriptor { + kind: ImportExportKind; + name: string; + } + interface ModuleImportDescriptor { + kind: ImportExportKind; + module: string; + name: string; + } + interface TableDescriptor { + element: TableKind; + initial: number; + maximum?: number; + } + interface ValueTypeMap { + anyfunc: Function; + externref: any; + f32: number; + f64: number; + i32: number; + i64: bigint; + v128: never; + } + interface WebAssemblyInstantiatedSource { + instance: Instance; + module: Module; + } + type ImportExportKind = "function" | "global" | "memory" | "table"; + type TableKind = "anyfunc" | "externref"; + type ExportValue = Function | Global | Memory | Table; + type Exports = Record; + type ImportValue = ExportValue | number; + type Imports = Record; + type ModuleImports = Record; + type ValueType = keyof ValueTypeMap; + function compile(bytes: BufferSource): Promise; + function compileStreaming(source: Response | PromiseLike): Promise; + function instantiate( + bytes: BufferSource, + importObject?: Imports, + ): Promise; + function instantiate(moduleObject: Module, importObject?: Imports): Promise; + function instantiateStreaming( + source: Response | PromiseLike, + importObject?: Imports, + ): Promise; + function validate(bytes: BufferSource): boolean; +} diff --git a/packages/compiler/src/backend/llvm/alloc.test.ts b/packages/compiler/src/backend/llvm/alloc.test.ts index 5ba7ff3d1..49971c3ce 100644 --- a/packages/compiler/src/backend/llvm/alloc.test.ts +++ b/packages/compiler/src/backend/llvm/alloc.test.ts @@ -1,5 +1,11 @@ import { describe, expect, test } from "vitest"; -import { type AllocHost, emitObjectAlloc, emitObjectFree, inlineAllocSupported } from "./alloc.js"; +import { + type AllocHost, + disposeHookLoadLines, + emitObjectAlloc, + emitObjectFree, + inlineAllocSupported, +} from "./alloc.js"; function host(inlineAlloc: boolean): AllocHost & { decls: Set; oom: boolean } { const h = { @@ -63,7 +69,12 @@ describe("emitted object allocation", () => { ]); expect(emitObjectFree(h, false)).toEqual([ " call void @scr_obj_free_note()", + " %sf.obs = load i1, ptr @sc_weak_keys", + " br i1 %sf.obs, label %sf.observe, label %sf.block", + "sf.observe:", " call void @scr_weak_dispose(ptr %o)", + " br label %sf.block", + "sf.block:", " call void @scr_rt_free(ptr %o)", ]); expect([...h.decls].some((d) => d.includes("@scr_sa"))).toBe(false); @@ -167,4 +178,30 @@ describe("emitted object allocation", () => { expect(lines.at(-1)).toBe("sf.done:"); } }); + + test("frees test the dispose hook only where the program can observe them", () => { + const h = host(true); + const weak = emitObjectFree(h, false); + expectSingleDefinitions(weak); + expect(weak.slice(0, 2)).toEqual([ + " %sf.obs = load i1, ptr @sc_weak_keys", + " br i1 %sf.obs, label %sf.hooked, label %sf.block", + ]); + const records = emitObjectFree(h, true, "weak-or-source"); + expectSingleDefinitions(records); + expect(records.slice(0, 4)).toEqual([ + " %sf.obsw = load i1, ptr @sc_weak_keys", + " %sf.obss = load i1, ptr @sc_record_sources", + " %sf.obs = or i1 %sf.obsw, %sf.obss", + " br i1 %sf.obs, label %sf.hooked, label %sf.block", + ]); + expect(records).toContain(" call void %sf.hook(ptr %o)"); + }); + + test("loads the dispose hook from emitted code only with the inline allocator", () => { + expect(disposeHookLoadLines(host(false), "%t1")).toBeNull(); + expect(disposeHookLoadLines(host(true), "%t1")).toEqual([ + " %t1 = load ptr, ptr @scr_weak_dispose_hook", + ]); + }); }); diff --git a/packages/compiler/src/backend/llvm/alloc.ts b/packages/compiler/src/backend/llvm/alloc.ts index 7dfc385aa..7fdc4b683 100644 --- a/packages/compiler/src/backend/llvm/alloc.ts +++ b/packages/compiler/src/backend/llvm/alloc.ts @@ -79,6 +79,17 @@ function threadLocalState(host: AllocHost, prefix: string, lines: string[]): str return [...preamble, ...text.split("\n")]; } +/** Lines that load the runtime's dispose hook into `dest`, or null on + * targets without the inline allocator, where the hook's storage is not + * addressed from emitted code. The hook is NULL until a weak collection + * or a kept record source installs it, and then never NULL again. */ +export function disposeHookLoadLines(host: AllocHost, dest: string): string[] | null { + if (host.inlineAlloc !== true) return null; + declareGlobal(host, `@scr_weak_dispose_hook = external global ptr`); + const prefix = dest.replace(/^%/, "").replace(/[^-$._A-Za-z0-9]/g, "_"); + return threadLocalState(host, prefix, [` ${dest} = load ptr, ptr @scr_weak_dispose_hook`]); +} + /** Worker executables: the calling script thread's ScrThreadHot block into * `dest`. Its address also identifies the thread (the owner word of a * lifetime-region chunk; llvm/regions.ts). */ @@ -325,20 +336,56 @@ function allocLines( return lines; } +/* ── dispose observers ──────────────────────────────────────────────── + * The runtime's dispose hook (scr_weak_dispose_hook) has two clients: weak + * collections, whose keys can be any object, and the kept sources of + * checked records (scr_record_source_note and the JSON schema parser), + * keyed by closed records. A program without either can never install the + * hook, so its frees need not test it. Whether the program has them is + * known only once every helper is emitted (dynCheck builders and JSON + * schemas are requested lazily), so the emitted frees and record writers + * test these two module constants, which the emitter defines last + * (LlvmEmitter.emitParts) and LLVM folds away. */ + +/** True when the program constructs a WeakMap or WeakSet. */ +export const WEAK_KEYS_GATE = "@sc_weak_keys"; +/** True when a checked conversion can keep a record's undeclared source. */ +export const RECORD_SOURCES_GATE = "@sc_record_sources"; + +/** Which dispose observers an object type can have: weak-collection keys + * only, or (closed record layouts) kept record sources too. */ +export type FreeObservers = "weak" | "weak-or-source"; + /** * Lines that free the object `%o` after its members were released: the - * RC-audit free note, the weak-collection dispose hook, and the block — - * `scr_cyc_free` for collector-headered objects, `scr_rt_free` otherwise. - * Labels use the `sf.` prefix; the lines end in an open block. + * RC-audit free note, the dispose hook (when the program can observe this + * type's disposals), and the block — `scr_cyc_free` for collector-headered + * objects, `scr_rt_free` otherwise. Labels use the `sf.` prefix; the lines + * end in an open block. */ -export function emitObjectFree(host: AllocHost, cyc: boolean): string[] { - const lines = threadLocalState(host, "sf", freeLines(host, cyc)); +export function emitObjectFree( + host: AllocHost, + cyc: boolean, + observers: FreeObservers = "weak", +): string[] { + const lines = threadLocalState(host, "sf", freeLines(host, cyc, observers)); if (host.objectAudit === false) return lines.filter((line) => line !== FREE_NOTE); host.declare(`declare void @scr_obj_free_note()`); return lines; } -function freeLines(host: AllocHost, cyc: boolean): string[] { +/** Lines that leave in `%.obs` whether the program can observe a + * disposal of this type (folds to a constant). */ +function observedLines(prefix: string, observers: FreeObservers): string[] { + if (observers === "weak") return [` %${prefix}.obs = load i1, ptr ${WEAK_KEYS_GATE}`]; + return [ + ` %${prefix}.obsw = load i1, ptr ${WEAK_KEYS_GATE}`, + ` %${prefix}.obss = load i1, ptr ${RECORD_SOURCES_GATE}`, + ` %${prefix}.obs = or i1 %${prefix}.obsw, %${prefix}.obss`, + ]; +} + +function freeLines(host: AllocHost, cyc: boolean, observers: FreeObservers): string[] { if (host.inlineAlloc !== true) { if (cyc) { host.declare(`declare void @scr_cyc_free(ptr)`); @@ -348,7 +395,12 @@ function freeLines(host: AllocHost, cyc: boolean): string[] { host.declare(`declare void @scr_weak_dispose(ptr)`); return [ ` call void @scr_obj_free_note()`, + ...observedLines("sf", observers), + ` br i1 %sf.obs, label %sf.observe, label %sf.block`, + `sf.observe:`, ` call void @scr_weak_dispose(ptr %o)`, + ` br label %sf.block`, + `sf.block:`, ` call void @scr_rt_free(ptr %o)`, ]; } @@ -356,11 +408,14 @@ function freeLines(host: AllocHost, cyc: boolean): string[] { host.declare(`declare void @scr_rt_free(ptr)`); declareGlobal(host, `@scr_weak_dispose_hook = external global ptr`); const lines = [ + ...observedLines("sf", observers), + ` br i1 %sf.obs, label %sf.hooked, label %sf.block`, + `sf.hooked:`, ` %sf.hook = load ptr, ptr @scr_weak_dispose_hook`, ` %sf.has = icmp ne ptr %sf.hook, null`, ` %sf.hasx = call i1 @llvm.expect.i1(i1 %sf.has, i1 false)`, ` br i1 %sf.hasx, label %sf.observe, label %sf.block`, - `sf.observe: ; weak collections observe the disposal`, + `sf.observe: ; a weak collection or a kept record source observes the disposal`, ` call void %sf.hook(ptr %o)`, ` br label %sf.block`, `sf.block:`, diff --git a/packages/compiler/src/backend/llvm/dyn.ts b/packages/compiler/src/backend/llvm/dyn.ts index 86e97a374..ff4a3de3e 100644 --- a/packages/compiler/src/backend/llvm/dyn.ts +++ b/packages/compiler/src/backend/llvm/dyn.ts @@ -1106,6 +1106,10 @@ export class LlDyn { private readonly jsonSchemas = new Map(); private readonly jsonParsers = new Map(); private readonly recordNameTables = new Map(); + /** Some emitted helper can keep a record's undeclared source: a checked + * record builder that notes it, or a JSON schema of a closed record + * (alloc.ts RECORD_SOURCES_GATE). */ + keepsRecordSources = false; /** Targets the one-pass parser (scr_json_parse_schema) can build * directly: number, boolean and string leaves inside arrays and records @@ -1221,6 +1225,7 @@ export class LlDyn { const index = new Map(shape.fields.map((f, i) => [f.name, i + base])); // The runtime names kept-source keys by this index (record-sources.ts). const order = recordSourceFieldOrder(shape); + if (recordMayKeepSource(shape)) this.keepsRecordSources = true; const fieldTy = `{ ptr, ${S}, ${S}, ptr }`; const entries = order.map((fieldName) => { const field = shape.fields[index.get(fieldName)! - base]!; @@ -1981,6 +1986,7 @@ export class LlDyn { // that has them stays beside the record so its reflective // surfaces still observe them (scr_record_source_note). if (recordMayKeepSource(shape)) { + this.keepsRecordSources = true; const names = this.recordNameTable(t.shapeId, shape); host.declare( `declare void @scr_record_source_note(ptr, ptr, ptr, ptr, ${host.sizeType})`, diff --git a/packages/compiler/src/backend/llvm/emitter.ts b/packages/compiler/src/backend/llvm/emitter.ts index 26c3b840e..efab6eb21 100644 --- a/packages/compiler/src/backend/llvm/emitter.ts +++ b/packages/compiler/src/backend/llvm/emitter.ts @@ -2,7 +2,14 @@ import { type ArraySearchKind, emitArraySearchHelpers } from "./array-search.js" import { emitStringInputs } from "./string-lifetimes.js"; import { emitLlvmLayouts } from "./layouts.js"; import { compileRegexMatcher, type RegexMatcherCode } from "./regex-matchers.js"; -import { CYC_BUF, CYC_HDR, FIRST_EMITTED_CYC_KIND, inlineAllocSupported } from "./alloc.js"; +import { + CYC_BUF, + CYC_HDR, + FIRST_EMITTED_CYC_KIND, + inlineAllocSupported, + RECORD_SOURCES_GATE, + WEAK_KEYS_GATE, +} from "./alloc.js"; import { hasLoneSurrogate, llvmBytes as llBytes, wtf8Bytes } from "../literals.js"; import { InternalCompilerError } from "../../errors.js"; import { createHash } from "node:crypto"; @@ -50,6 +57,7 @@ import { VOID, } from "../../ir/ir.js"; import { moduleRuntimeFeatures, moduleUsesMockTimers } from "../../ir/runtime-features.js"; +import { captureFreeFunctions, observesStacks } from "../stack-observations.js"; import { matchIntegerArrayForLoop, matchIntegerBytesForLoop, @@ -158,6 +166,7 @@ import { mangleFnClosure, mangleFunction, mangleGenDrop, + mangleGenSourceClose, mangleGenSpawn, mangleGlobal, mangleLocal, @@ -1172,18 +1181,14 @@ export class LlEmitter { readonly chainSlots = new Map(); logArgSlots = 0; private readonly stackTraces: boolean; + /** Stack-trace mode: functions no capture can include (no frame push). */ + private readonly unframedFunctions: ReadonlySet; constructor( readonly mod: IrModule, options: LlvmTargetOptions, ) { - this.stackTraces = mod.functions.some( - (fn) => - !everyStmtList(fn.body, { - stmt: () => true, - expr: (expr) => !(expr.kind === "libCall" && expr.fn === "error.stack"), - }), - ); + this.stackTraces = observesStacks(mod); this.nullableUnions = new NullableUnions(mod, options.debugSources === undefined); this.mockTimers = moduleUsesMockTimers(mod); this.debug = @@ -1265,6 +1270,9 @@ export class LlEmitter { // which Windows lacks. this.stacklessAsyncAllowed = this.stacklessGenerators && mod.lib === undefined && !windows; this.publishedTypes = computePublishedTypes(mod); + this.unframedFunctions = this.stackTraces + ? captureFreeFunctions(mod, this.stackChecks, this.publishedTypes) + : new Set(); this.immutableFields = computeImmutableFields(mod); this.constructorFunctions = new Set((mod.classes ?? []).map((c) => `%${c.name}.constructor`)); this.indirectMayThrow = mt.indirect || mod.workers === true; @@ -1964,7 +1972,10 @@ export class LlEmitter { } emitParts(): string[] { - const parts = limitInlineDynReleases(this.emitModuleParts()); + const parts = [ + ...limitInlineDynReleases(this.emitModuleParts()), + ...this.disposeObserverGates(), + ]; if (!this.executableTls) return parts; // A worker executable's thread-locals all live in the executable's own // TLS block: the program's internal ones, and the runtime's external @@ -1987,6 +1998,21 @@ export class LlEmitter { ); } + /** The dispose-observer gates the emitted frees and record writers test + * (alloc.ts): defined after every helper is emitted, because dynCheck + * builders, JSON schemas and weak collection constructors are requested + * lazily. */ + private disposeObserverGates(): string[] { + const weak = [...this.decls].some( + (d) => d.includes("@scr_weak_map_new(") || d.includes("@scr_weak_set_new("), + ); + return [ + `${WEAK_KEYS_GATE} = internal constant i1 ${weak}`, + `${RECORD_SOURCES_GATE} = internal constant i1 ${this.dyn.keepsRecordSources}`, + ``, + ]; + } + private emitModuleParts(): string[] { // Function bodies first (the literal/unit/fn-value tables fill as they // emit), then the file assembles around them — the runtime ABI’s order. @@ -4598,6 +4624,25 @@ export class LlEmitter { dr.push(` call void @free(ptr %ap)`, ` ret void`, `}`, ``); for (const line of dr) out.push(line); + // An iterator helper's return() before its first next() closes the + // source generator in its first argument slot. + const closesSource = fn.generator.closesSource === true; + if (closesSource) { + const field = lifted ? 1 : 0; + this.declare(`declare void @scr_gen_close(ptr)`); + this.declare(`declare void @scr_gen_set_unstarted_return(ptr, ptr)`); + out.push( + `define internal void @${mangleGenSourceClose(fn.name)}(ptr %ap) ${FN_ATTRS} {`, + `entry:`, + ` %sp = getelementptr inbounds %${pack}, ptr %ap, i64 0, i32 ${field}`, + ` %sv = load ptr, ptr %sp`, + ` call void @scr_gen_close(ptr %sv)`, + ` ret void`, + `}`, + ``, + ); + } + // Spawn wrapper: pack the args (+1 moves in), allocate the // SUSPENDED fiber — nothing runs until the first .next(). if (lifted) { @@ -4614,6 +4659,11 @@ export class LlEmitter { settleAsync === null ? ` %gg = call ptr @${genNew}(ptr @${mangleTrampoline(fn.name)}, ptr %ap, ptr @${mangleGenDrop(fn.name)})` : ` %gg = call ptr @scr_async_gen_new(ptr @${mangleTrampoline(fn.name)}, ptr %ap, ptr @${mangleGenDrop(fn.name)}, ptr @${settleAsync})`, + ...(closesSource + ? [ + ` call void @scr_gen_set_unstarted_return(ptr %gg, ptr @${mangleGenSourceClose(fn.name)})`, + ] + : []), ` ret ptr %gg`, `}`, ``, @@ -7125,13 +7175,39 @@ export class LlEmitter { // Stackful native fibers and native coroutine frames retain these frames // while suspended. The active exception context owns the chain, so // concurrent fibers isolate it. - if (this.stackTraces && !this.wasi && fn.sourceName !== undefined) { - this.declare(`declare void @scr_stack_enter(ptr, ptr)`); - this.declare(`declare void @scr_stack_leave(ptr)`); + if ( + this.stackTraces && + !this.wasi && + fn.sourceName !== undefined && + !this.unframedFunctions.has(fn.name) + ) { B.entryAllocas.push(`%source_frame = alloca { ptr, ptr }`); - const frame = ` at ${fn.sourceName} (${fn.loc.file})`; - B.line(`call void @scr_stack_enter(ptr %source_frame, ptr ${this.cstr(frame)})`); - B.returnEpilogue = `call void @scr_stack_leave(ptr %source_frame)`; + const frame = this.cstr(` at ${fn.sourceName} (${fn.loc.file})`); + if ( + B.excCellInvariant && + this.mod.lib === undefined && + this.mod.workers !== true && + this.sizeType === "i64" + ) { + // Executables link the active-cell pointer as a plain global, and a + // synchronous body sees one cell from entry to every return: push + // and pop the frame inline (ScrExcCell.stack is at byte 56 on + // 64-bit targets) instead of calling the runtime twice per call. + this.declare(`@scr_exc_active = external global ptr`); + B.line(`%source_frame.cell = load ptr, ptr @scr_exc_active`); + B.line(`%source_frame.chain = getelementptr inbounds i8, ptr %source_frame.cell, i64 56`); + B.line(`%source_frame.previous = load ptr, ptr %source_frame.chain`); + B.line(`store ptr %source_frame.previous, ptr %source_frame`); + B.line(`%source_frame.text = getelementptr inbounds i8, ptr %source_frame, i64 8`); + B.line(`store ptr ${frame}, ptr %source_frame.text`); + B.line(`store ptr %source_frame, ptr %source_frame.chain`); + B.returnEpilogue = `store ptr %source_frame.previous, ptr %source_frame.chain`; + } else { + this.declare(`declare void @scr_stack_enter(ptr, ptr)`); + this.declare(`declare void @scr_stack_leave(ptr)`); + B.line(`call void @scr_stack_enter(ptr %source_frame, ptr ${frame})`); + B.returnEpilogue = `call void @scr_stack_leave(ptr %source_frame)`; + } } if (this.stackChecks?.has(fn.name)) this.emitStackCheck(); if (this.workerEntryPolls?.has(fn.name)) this.emitPendingCheck(undefined, true); @@ -9492,14 +9568,15 @@ export class LlEmitter { B.line(`${stash} = call ptr @scr_exc_take() ; stash across finally`); B.line(`store ptr ${stash}, ptr ${stashSlot}`); this.scopes.push([{ slot: stashSlot, type: CAUGHT }]); - const suppressHandler = s.suppressFinallyErrors - ? { - label: B.newLabel("try.fs"), - used: false, - frameDepth: this.frames.length, - scopeDepth: this.scopes.length, - } - : null; + const suppressHandler = + s.suppressFinallyErrors || s.dropFinallyErrors + ? { + label: B.newLabel("try.fs"), + used: false, + frameDepth: this.frames.length, + scopeDepth: this.scopes.length, + } + : null; if (suppressHandler) this.tryStack.push(suppressHandler); this.emitBlock(s.finallyBody!); if (suppressHandler) this.tryStack.pop(); @@ -9509,8 +9586,9 @@ export class LlEmitter { this.emitUnwind(); if (suppressHandler?.used) { B.startBlock(suppressHandler.label); - this.declare(`declare void @scr_exc_suppress(ptr)`); - B.line(`call void @scr_exc_suppress(ptr ${stash}) ; consumes stash`); + const cleanup = s.dropFinallyErrors ? "scr_exc_keep_first" : "scr_exc_suppress"; + this.declare(`declare void @${cleanup}(ptr)`); + B.line(`call void @${cleanup}(ptr ${stash}) ; consumes stash`); this.emitUnwind(); } } diff --git a/packages/compiler/src/backend/llvm/lib-dispatch.ts b/packages/compiler/src/backend/llvm/lib-dispatch.ts index 68d943ea1..f21ded106 100644 --- a/packages/compiler/src/backend/llvm/lib-dispatch.ts +++ b/packages/compiler/src/backend/llvm/lib-dispatch.ts @@ -9,6 +9,7 @@ import { emitTestLibCall } from "./lib-test.js"; import { InternalCompilerError } from "../../errors.js"; import { MAY_THROW_LIB_FNS } from "../../ir/builtin-effects.js"; +import type { IrExpr, IrType } from "../../ir/ir.js"; import { LlvmUnsupportedError } from "./unsupported.js"; import type { LlvmEmitterContext, LibCallExpr, LibCallPrefix, LlValue } from "./expr-context.js"; import { @@ -21,6 +22,7 @@ import { isDynUndefined } from "../../ir/runtime-features.js"; import { DYN_KIND } from "./dyn.js"; import { rawBytes } from "./lib-abi.js"; import { emitInlineAtomicsOp } from "./expr-bytes.js"; +import { regexLiteralCaptures } from "./regex-matchers.js"; export function emitAssertInspectLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlValue { const B = host.B; @@ -642,8 +644,66 @@ function emitAssertFailing( * `a.name.localeCompare(b.name)` reads both fields without retaining). */ const READ_ONLY_STRING_LIB_FNS: ReadonlySet = new Set(["str.localeCompare"]); +/** The parameter count of a replace callback the runtime can call through + * the closure ABI (scr_regex_replace_fn), or null when it needs the dyn + * box. Each declared parameter must receive a value of its declared kind + * in every match: the match string at 0; with more than one parameter the + * pattern must be a literal whose captures are known, so position i is a + * capture that every match sets (a string), the offset (a number) right + * after the captures, or the subject (a string) after that. */ +function typedReplacerArity(callback: IrType, pattern: IrExpr): number | null { + if (callback.kind !== "func" || callback.rest || callback.argumentsAll) return null; + if (callback.ret.kind !== "string") return null; + const params = callback.params; + if (params.length > 4) return null; + if (params.length === 0) return 0; + if (params[0]!.kind !== "string") return null; + if (params.length === 1) return 1; + if (pattern.kind !== "regexLit") return null; + const captures = regexLiteralCaptures(pattern.pattern, pattern.flags); + if (!captures) return null; + for (let i = 1; i < params.length; i++) { + const kind = params[i]!.kind; + const ok = + i < captures.count + ? kind === "string" && captures.always[i] === true + : i === captures.count + ? kind === "f64" + : i === captures.count + 1 && kind === "string"; + if (!ok) return null; + } + return params.length; +} + +/** `s.replace(re, fn)` / `replaceAll` with a typed callback the runtime can + * call directly: the dyn box the IR wraps it in is never observable (the + * runtime only calls it, with `this` undefined), so the closure goes to + * scr_regex_replace_fn as it is. Null keeps the generic path. */ +function emitTypedRegexReplace(host: LlvmEmitterContext, e: LibCallExpr): LlValue | null { + const [subject, pattern, callback, all] = e.args; + if (!subject || !pattern || callback?.kind !== "dynFrom" || all?.kind !== "boolLit") return null; + const arity = typedReplacerArity(callback.value.type, pattern); + if (arity === null) return null; + const B = host.B; + const s = host.emitExpr(subject); + const re = host.emitExpr(pattern); + const fn = host.emitExpr(callback.value); + host.declare(`declare ptr @scr_regex_replace_fn(ptr, ptr, ptr, i32, i1 zeroext)`); + const result = B.tmp(); + B.line( + `${result} = call ptr @scr_regex_replace_fn(ptr ${s.name}, ptr ${re.name}, ptr ${fn.name}, i32 ${arity}, i1 zeroext ${all.value})`, + ); + const output = host.own({ name: result, type: e.type }); + host.emitPendingCheck(); + return output; +} + export function emitLibCall(host: LlvmEmitterContext, e: LibCallExpr): LlValue { if (USES_TIMERS_LIB_FNS.has(e.fn)) host.usesTimers = true; + if (e.fn === "regex.replaceCallback") { + const typed = emitTypedRegexReplace(host, e); + if (typed) return typed; + } if (e.fn === "process.nextTick") return host.emitAsyncContextLibCall(e); if ( e.fn === "sp.pipeline" || diff --git a/packages/compiler/src/backend/llvm/lib-shared.ts b/packages/compiler/src/backend/llvm/lib-shared.ts index 6b2f739a8..404e0ed9a 100644 --- a/packages/compiler/src/backend/llvm/lib-shared.ts +++ b/packages/compiler/src/backend/llvm/lib-shared.ts @@ -144,6 +144,7 @@ export const LIB_FN_SYMS: Record = { "num.toFixed0": "scr_num_to_fixed0", "num.toFixed": "scr_num_to_fixed", "num.toStringRadix": "scr_num_to_string_radix", + "num.toStringRadixF64": "scr_num_to_string_radix_f64", "num.sameValue": "scr_num_same_value", "intl.numFormatEnUs": "scr_intl_num_format_en_us", "number.isFinite": "scr_num_is_finite", diff --git a/packages/compiler/src/backend/llvm/regex-matchers.test.ts b/packages/compiler/src/backend/llvm/regex-matchers.test.ts index a3627cb7f..1acd9c465 100644 --- a/packages/compiler/src/backend/llvm/regex-matchers.test.ts +++ b/packages/compiler/src/backend/llvm/regex-matchers.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "vitest"; import { compileRegexMatcher, regexLiteralBailReason, + regexLiteralCaptures, regexLiteralCompiles, } from "./regex-matchers.js"; @@ -11,6 +12,30 @@ function body(pattern: string, flags = "", vector = true): string { return code.lines.join("\n"); } +describe("regex literal captures", () => { + test("counts captures with the whole match and marks the ones every match sets", () => { + expect(regexLiteralCaptures("[&<>]", "g")).toEqual({ count: 1, always: [true] }); + expect(regexLiteralCaptures("(\\w+)=(\\d)+", "")).toEqual({ + count: 3, + always: [true, true, true], + }); + expect(regexLiteralCaptures("(?a)(b)?|(c)", "")).toEqual({ + count: 4, + always: [true, false, false, false], + }); + expect(regexLiteralCaptures("x(?:(a)|(b))y(c)*(d){0,2}(e){1,3}", "")).toEqual({ + count: 6, + always: [true, false, false, false, false, true], + }); + }); + + test("answers null outside the parsed subset", () => { + expect(regexLiteralCaptures("(?=a)(b)", "")).toBeNull(); + expect(regexLiteralCaptures("(a)\\1", "")).toBeNull(); + expect(regexLiteralCaptures("a", "v")).toBeNull(); + }); +}); + describe("regex literal matcher subset", () => { test.each([ ['^(\\d+\\.\\d+\\.\\d+\\.\\d+) - - \\[([^\\]]+)\\] "(\\w+) ([^ ?"]+)(?:\\?([^ "]*))?$', ""], diff --git a/packages/compiler/src/backend/llvm/regex-matchers.ts b/packages/compiler/src/backend/llvm/regex-matchers.ts index ad5c47c86..001f081e5 100644 --- a/packages/compiler/src/backend/llvm/regex-matchers.ts +++ b/packages/compiler/src/backend/llvm/regex-matchers.ts @@ -1639,6 +1639,40 @@ function parseSubset(pattern: string, flags: string): { root: RxNode; ncap: numb } } +/** The capture count of a regex literal (the whole match included) and, + * per capture, whether every match sets it: no alternation of several + * branches and no repetition that can run zero times encloses it. Null + * when the pattern is outside the parsed subset. */ +export function regexLiteralCaptures( + pattern: string, + flags: string, +): { count: number; always: boolean[] } | null { + const parsed = parseSubset(pattern, flags); + if (!parsed) return null; + const always = Array.from({ length: parsed.ncap }, (_, i) => i === 0); + const walk = (node: RxNode, sure: boolean): void => { + switch (node.kind) { + case "cap": + always[node.index] = sure; + walk(node.body, sure); + return; + case "seq": + for (const item of node.items) walk(item, sure); + return; + case "alt": + for (const alt of node.alts) walk(alt, sure && node.alts.length === 1); + return; + case "rep": + walk(node.body, sure && node.min > 0); + return; + default: + return; + } + }; + walk(parsed.root, true); + return { count: parsed.ncap, always }; +} + /** Whether a literal compiles to a native matcher (tests and size caps). */ export function regexLiteralCompiles(pattern: string, flags: string): boolean { return parseSubset(pattern, flags) !== null; diff --git a/packages/compiler/src/backend/llvm/shapes.ts b/packages/compiler/src/backend/llvm/shapes.ts index 162b36425..e390a4552 100644 --- a/packages/compiler/src/backend/llvm/shapes.ts +++ b/packages/compiler/src/backend/llvm/shapes.ts @@ -47,6 +47,7 @@ import { stackUnionBox, type InlineUnionFields, } from "./inline-unions.js"; +import { recordMayKeepSource } from "./record-sources.js"; import { LlvmUnsupportedError } from "./unsupported.js"; /** What the tables need from the emitter: the extern-declaration ledger @@ -1524,7 +1525,9 @@ export function emitRecordShapes( } t++; } - freeBody.push(...emitObjectFree(host, traced)); + // Closed layouts can carry a kept record source (record-sources.ts). + const observers = recordMayKeepSource(shape) ? "weak-or-source" : "weak"; + freeBody.push(...emitObjectFree(host, traced, observers)); defs.push( ...releaseBody( host, @@ -1639,7 +1642,7 @@ export function emitRecordShapes( ` call void ${releaseSym(host, m.type)}(ptr %v${i}) ; ${llvmCommentText(m.name)} (acyclic)`, ); }); - gf.push(...emitObjectFree(host, true), ` ret void`, `}`, ``); + gf.push(...emitObjectFree(host, true, observers), ` ret void`, `}`, ``); defs.push(...gf); } } diff --git a/packages/compiler/src/backend/llvm/walkers.ts b/packages/compiler/src/backend/llvm/walkers.ts index 2f69dd5ec..46dbc86e1 100644 --- a/packages/compiler/src/backend/llvm/walkers.ts +++ b/packages/compiler/src/backend/llvm/walkers.ts @@ -28,6 +28,7 @@ import { traceAdapter, type ShapeHost, } from "./shapes.js"; +import { disposeHookLoadLines, RECORD_SOURCES_GATE } from "./alloc.js"; import { recordMayKeepSource, recordSourceFieldOrder } from "./record-sources.js"; import { LlvmUnsupportedError } from "./unsupported.js"; import { emitUnionPeek, emitUnionTag } from "./union-repr.js"; @@ -397,6 +398,24 @@ export class LlWalkers { const writer = this.recordFieldWriter(shapeId); const lSource = B.newLabel("jw.source"); const lNative = B.newLabel("jw.native"); + // Only a program that can keep record sources looks one up (the gate + // folds to a constant), and only once one was kept: keeping a source + // installs the dispose hook, so a NULL hook means the table is empty. + const lHooked = B.newLabel("jw.hooked"); + const kept = B.tmp(); + B.line(`${kept} = load i1, ptr ${RECORD_SOURCES_GATE}`); + B.condBr(kept, lHooked, lNative); + B.startBlock(lHooked); + const hook = B.tmp(); + const hookLines = disposeHookLoadLines(host, hook); + if (hookLines !== null) { + const lProbe = B.newLabel("jw.probe"); + for (const line of hookLines) B.line(line.trimStart()); + const installed = B.tmp(); + B.line(`${installed} = icmp ne ptr ${hook}, null`); + B.condBr(installed, lProbe, lNative); + B.startBlock(lProbe); + } if (traceAdapter(host, { kind: "record", shapeId }) === null) { // One lookup: the runtime writes the record when it kept a source. host.declare(`declare zeroext i1 @scr_jb_try_record_source(ptr, ptr, ptr)`); diff --git a/packages/compiler/src/backend/mangle.ts b/packages/compiler/src/backend/mangle.ts index 0bc428964..43c9cea71 100644 --- a/packages/compiler/src/backend/mangle.ts +++ b/packages/compiler/src/backend/mangle.ts @@ -204,6 +204,11 @@ export function mangleGenSpawn(fnName: string): string { export function mangleGenDrop(fnName: string): string { return `sc_gd_${sanitize(fnName)}`; } +/** The never-started return() hook of a generator that closes its source + * argument (an iterator helper). */ +export function mangleGenSourceClose(fnName: string): string { + return `sc_gc_${sanitize(fnName)}`; +} /** Emitted ref-kind resolve thunk, interned per inner-type key. */ export function mangleResolveThunk(n: number): string { return `sc_rslv_${n}`; diff --git a/packages/compiler/src/backend/may-throw.ts b/packages/compiler/src/backend/may-throw.ts index ac45129f0..f07bbfa78 100644 --- a/packages/compiler/src/backend/may-throw.ts +++ b/packages/compiler/src/backend/may-throw.ts @@ -580,7 +580,7 @@ function breaksTo( /** Statements no execution reaches: those after a statement that cannot * complete normally in the same statement list. */ -function unreachableStatements(body: readonly IrStmt[]): Set { +export function unreachableStatements(body: readonly IrStmt[]): Set { const dead = new Set(); const { statement } = completion(); const list = (stmts: readonly IrStmt[]): void => { diff --git a/packages/compiler/src/backend/stack-observations.test.ts b/packages/compiler/src/backend/stack-observations.test.ts new file mode 100644 index 000000000..f58c89ad8 --- /dev/null +++ b/packages/compiler/src/backend/stack-observations.test.ts @@ -0,0 +1,137 @@ +import { expect, test } from "vitest"; +import { + F64, + STRING, + VOID, + type IrExpr, + type IrFunction, + type IrModule, + type IrStmt, +} from "../ir/ir.js"; +import { captureFreeFunctions, observesStacks } from "./stack-observations.js"; + +const loc = { file: "stack-observations.ts", start: 0, end: 0 }; +const ERROR = { kind: "object", className: "%Error" } as const; +const err: IrExpr = { loc, kind: "varRef", localId: "e", type: ERROR }; +const stackRead: IrStmt = { + loc, + kind: "exprStmt", + expr: { loc, kind: "libCall", fn: "error.stack", args: [err], type: STRING }, +}; +const call = (callee: string): IrStmt => ({ + loc, + kind: "exprStmt", + expr: { loc, kind: "call", callee, args: [], type: VOID }, +}); +const throwStmt: IrStmt = { loc, kind: "throw", value: err }; +const ret: IrStmt = { loc, kind: "return", value: null }; +const fn = (name: string, body: IrStmt[]): IrFunction => ({ + loc, + name, + params: [], + locals: [], + returnType: VOID, + body, +}); +const mod = (functions: IrFunction[], extra: Partial = {}): IrModule => ({ + irVersion: 16, + sourceFile: "stack-observations.ts", + entry: "%main", + functions, + classes: [], + records: [], + unions: [], + globals: [], + ...extra, +}); + +test("a reachable stack read is observed", () => { + expect(observesStacks(mod([fn("%main", [call("parse")]), fn("parse", [stackRead])]))).toBe(true); +}); + +test("programs without stack reads are not", () => { + expect(observesStacks(mod([fn("%main", [call("helper")]), fn("helper", [ret])]))).toBe(false); +}); + +test("reads after an unconditional throw or return never run", () => { + expect(observesStacks(mod([fn("%main", [throwStmt, stackRead])]))).toBe(false); + expect(observesStacks(mod([fn("%main", [ret, call("parse")]), fn("parse", [stackRead])]))).toBe( + false, + ); + // A terminator ends only its own list: the outer list continues. + const cond: IrExpr = { loc, kind: "numLit", value: 1, type: F64 }; + expect( + observesStacks( + mod([fn("%main", [{ kind: "if", cond, then: [ret], else_: null, loc }, stackRead])]), + ), + ).toBe(true); +}); + +test("functions referenced only from dead code are unreached", () => { + // The production React shape: a DEV-only body behind a throw stub calls + // the stack parser, and a closure created after the stub reaches it too. + const closure: IrStmt = { + loc, + kind: "assign", + localId: "replacer", + value: { + loc, + kind: "closure", + fnName: "replacer", + captures: [], + type: { kind: "func", params: [], ret: VOID }, + }, + }; + const program = mod([ + fn("%main", [call("outline")]), + fn("outline", [throwStmt, closure, call("parse")]), + fn("replacer", [call("parse")]), + fn("parse", [stackRead]), + ]); + expect(observesStacks(program)).toBe(false); + // The same closure created before the stub keeps the read reachable. + const live = mod([ + fn("%main", [call("outline")]), + fn("outline", [closure, throwStmt]), + fn("replacer", [call("parse")]), + fn("parse", [stackRead]), + ]); + expect(observesStacks(live)).toBe(true); +}); + +test("class methods are roots", () => { + const program = mod([fn("%main", [ret]), fn("%Parser.read", [stackRead])], { + classes: [ + { name: "Parser", fields: [], methods: ["read"] } as unknown as NonNullable< + IrModule["classes"] + >[number], + ], + }); + expect(observesStacks(program)).toBe(true); +}); + +test("leaf functions that cannot create an Error need no frame", () => { + const num = (value: number): IrExpr => ({ loc, kind: "numLit", value, type: F64 }); + const add: IrStmt = { + loc, + kind: "return", + value: { loc, kind: "bin", op: "+", left: num(1), right: num(2), type: F64 }, + }; + const construct: IrStmt = { + loc, + kind: "exprStmt", + expr: { loc, kind: "libCall", fn: "error.new", args: [], type: ERROR }, + }; + const program = mod([ + fn("%main", [call("leaf"), call("caller"), call("creates"), call("viaCreates")]), + fn("leaf", [add]), + fn("caller", [call("leaf"), add]), + fn("creates", [construct]), + fn("viaCreates", [call("creates")]), + fn("recursive", [call("recursive")]), + ]); + const free = captureFreeFunctions(program, new Set(["recursive"]), null); + expect([...free].sort()).toEqual(["caller", "leaf"]); + // A worker program keeps every frame. + expect(captureFreeFunctions({ ...program, workers: true }, null, null).size).toBe(0); +}); diff --git a/packages/compiler/src/backend/stack-observations.ts b/packages/compiler/src/backend/stack-observations.ts new file mode 100644 index 000000000..7debf0751 --- /dev/null +++ b/packages/compiler/src/backend/stack-observations.ts @@ -0,0 +1,237 @@ +/* Whole-program stack-trace gate (see observesStacks). Pure function of the + * IR module; the emitter keeps a source frame in every function only when + * it answers true. */ +import { exprFunctionReference, moduleFunctionReferences } from "../ir/function-references.js"; +import { MAY_THROW_LIB_FNS } from "../ir/builtin-effects.js"; +import type { IrExpr, IrFunction, IrModule, IrStmt } from "../ir/ir.js"; +import { MAY_THROW_ARR_METHODS } from "../ir/ir.js"; +import { everyExprChild, everyStmtChild, everyStmtList } from "../ir/traverse.js"; +import { unreachableStatements } from "./may-throw.js"; +import type { PublishedTypes } from "./publication.js"; +import { writesPublished } from "./publication.js"; + +/** Lib calls that read a captured stack trace. */ +const STACK_READS: ReadonlySet = new Set(["error.stack"]); + +function readsStack(expr: IrExpr): boolean { + return expr.kind === "libCall" && STACK_READS.has(expr.fn); +} + +function containsStackRead(fn: IrFunction): boolean { + return !everyStmtList(fn.body, { stmt: () => true, expr: (expr) => !readsStack(expr) }); +} + +/** Visit every expression of `body` that execution can reach: statements + * after one that cannot complete normally in the same list are skipped. */ +function visitLiveExprs(body: IrStmt[], visit: (expr: IrExpr) => void): void { + const dead = unreachableStatements(body); + const expr = (node: IrExpr): boolean => { + visit(node); + return everyExprChild(node, expr, stmt); + }; + const stmt = (node: IrStmt): boolean => dead.has(node) || everyStmtChild(node, expr, stmt); + body.every(stmt); +} + +/** Whether the program can read a captured stack trace, which is what makes + * every function keep a source frame. A read counts when it can execute: + * it sits in live code of a function reachable from the module's roots (its + * entry, library exports, class prototype helpers and every class's + * methods) through live code. Code after a statement that cannot complete + * normally is not live: production builds of libraries such as React's + * Flight server keep development-only stack parsing behind `throw` stubs, + * and those reads must not cost every call of the program a frame. + * Programs without any stack read answer false without the walk. */ +export function observesStacks(mod: IrModule): boolean { + if (!mod.functions.some(containsStackRead)) return false; + const byName = new Map(mod.functions.map((fn) => [fn.name, fn])); + const classNames = new Set((mod.classes ?? []).map((cls) => cls.name)); + const pending: string[] = [...moduleFunctionReferences(mod)]; + // Class methods, accessors and constructors are reachable through + // dispatch the IR does not name per site: all of them are roots. + for (const fn of mod.functions) { + if (!fn.name.startsWith("%")) continue; + for (let dot = fn.name.indexOf("."); dot !== -1; dot = fn.name.indexOf(".", dot + 1)) { + if (classNames.has(fn.name.slice(1, dot))) { + pending.push(fn.name); + break; + } + } + } + const reached = new Set(); + let observed = false; + while (pending.length > 0 && !observed) { + const name = pending.pop()!; + if (reached.has(name)) continue; + reached.add(name); + const fn = byName.get(name); + if (fn === undefined) continue; + visitLiveExprs(fn.body, (expr) => { + if (readsStack(expr)) observed = true; + if (expr.kind === "call" && !reached.has(expr.callee)) pending.push(expr.callee); + const referenced = exprFunctionReference(expr); + if (referenced !== undefined && !reached.has(referenced)) pending.push(referenced); + }); + } + return observed; +} + +/** Expressions that neither create an Error nor throw one by themselves. + * Calls, `new` and virtual calls are capture-free when their callees are. */ +const CAPTURE_FREE_EXPRS: ReadonlySet = new Set([ + "numLit", + "boolLit", + "strLit", + "unitLit", + "varRef", + "incDec", + "assignExpr", + "bin", + "unary", + "logical", + "ternary", + "nullish", + "toBool", + "fieldGet", + "recordGet", + "arrayGet", + "arrayHas", + "arrayState", + "strCmp", + "strEq", + "strConcat", + "upcast", + "unionDisc", + "unionIsTag", + "unionEq", + "instanceOf", + "recordLit", + "arrayLit", + "unionWrap", + "unionNarrow", + "libCall", + "arrIntrinsic", + "call", + "new", + "virtualCall", +]); + +/** Statements that neither create an Error nor throw one by themselves. */ +const CAPTURE_FREE_STMTS: ReadonlySet = new Set([ + "varDecl", + "assign", + "exprStmt", + "if", + "while", + "doWhile", + "for", + "switch", + "block", + "return", + "break", + "continue", + "fieldSet", + "recordSet", + "arraySet", +]); + +/** Functions whose frame no stack capture can ever include: a capture runs + * where an Error is created (by the program or by a throwing runtime + * operation), and these functions only perform operations from a fixed + * list that never create one and only call functions of the same kind. + * Their frames are therefore never observable and the emitter omits them, + * which keeps small leaf methods and helpers free of the per-call frame + * push in programs that read stacks. Recursive functions (the stack guard + * throws RangeError), async and generator bodies, and every function of a + * worker program keep their frames. */ +export function captureFreeFunctions( + mod: IrModule, + stackChecks: ReadonlySet | null, + published: PublishedTypes | null, +): Set { + const free = new Set(); + if (mod.workers === true) return free; + const methodImpls = new Map(); + for (const cls of mod.classes ?? []) { + for (const m of cls.methods ?? []) { + let list = methodImpls.get(m); + if (!list) methodImpls.set(m, (list = [])); + list.push(`%${cls.name}.${m}`); + } + } + const tdzGlobals = new Set((mod.globals ?? []).filter((g) => g.tdz).map((g) => g.id)); + const callees = new Map(); + for (const fn of mod.functions) { + if (fn.async === true || fn.generator !== undefined || stackChecks?.has(fn.name)) continue; + const tdz = new Set([...tdzGlobals, ...fn.locals.filter((l) => l.tdz).map((l) => l.id)]); + const calls: string[] = []; + const bigint = (e: IrExpr): boolean => e.type.kind === "bigint"; + const expr = (e: IrExpr): boolean => { + if (!CAPTURE_FREE_EXPRS.has(e.kind)) return false; + switch (e.kind) { + case "varRef": + case "incDec": + case "assignExpr": + if (tdz.has(e.localId)) return false; + break; + case "bin": + // BigInt division and remainder by zero throw RangeError. + if (bigint(e) || bigint(e.left) || bigint(e.right)) return false; + break; + case "unary": + if (bigint(e) || bigint(e.operand)) return false; + break; + case "libCall": + // Math functions only: they neither throw nor call back. + if (!e.fn.startsWith("math.") || MAY_THROW_LIB_FNS.has(e.fn)) return false; + break; + case "arrIntrinsic": { + // Methods that cannot throw, over numbers, booleans or strings + // (no element conversion can run program code) and without a + // callback argument. + const elem = e.receiver.type.kind === "array" ? e.receiver.type.elem.kind : null; + if ( + MAY_THROW_ARR_METHODS.has(e.method) || + (elem !== "f64" && elem !== "bool" && elem !== "string") || + e.args.some((arg) => arg.type.kind === "func") + ) + return false; + break; + } + case "call": + calls.push(e.callee); + break; + case "new": + calls.push(`%${e.className}.constructor`); + break; + case "virtualCall": { + const impls = methodImpls.get(e.method); + if (impls === undefined) return false; + calls.push(...impls); + break; + } + } + return everyExprChild(e, expr, stmt); + }; + const stmt = (s: IrStmt): boolean => { + if (!CAPTURE_FREE_STMTS.has(s.kind)) return false; + if (s.kind === "assign" && tdz.has(s.localId)) return false; + if (published !== null && writesPublished(published, s)) return false; + return everyStmtChild(s, expr, stmt); + }; + if (fn.body.every(stmt)) callees.set(fn.name, calls); + } + // Drop candidates that call a function outside the set until none do. + for (const name of callees.keys()) free.add(name); + let changed = true; + while (changed) { + changed = false; + for (const [name, calls] of callees) { + if (free.has(name) && !calls.every((callee) => free.has(callee))) { + free.delete(name); + changed = true; + } + } + } + return free; +} diff --git a/packages/compiler/src/cli/command.ts b/packages/compiler/src/cli/command.ts index 6810cc8fb..79442f19e 100644 --- a/packages/compiler/src/cli/command.ts +++ b/packages/compiler/src/cli/command.ts @@ -285,6 +285,11 @@ async function main(args: string[], host: CliHost): Promise { } externalTypes[specifier] = declarationPath; } + const wasmArgs = values.wasm ?? []; + if (wasmArgs.length > 0 && command !== "coverage") { + fail(`--wasm is a coverage-only option\n\n${USAGE}`); + } + const wasmFiles = wasmArgs.map((file) => resolve(file)); const ffiProfilePath = values.ffi !== undefined ? resolve(values.ffi) : undefined; if (values.backend !== undefined && values.backend !== "llvm") { fail(`unknown backend "${values.backend}" (supported: llvm)\n\n${USAGE}`); @@ -364,6 +369,7 @@ async function main(args: string[], host: CliHost): Promise { ...(Object.keys(externalTypes).length > 0 ? { externalTypes } : {}), ...(tier !== undefined ? { tier } : {}), ...(explainDynamic !== undefined ? { explainDynamic: true } : {}), + ...(wasmFiles.length > 0 ? { wasm: wasmFiles } : {}), }); if (printDiagnostics) { // Keep stdout pure JSON for tooling. diff --git a/packages/compiler/src/cli/usage.ts b/packages/compiler/src/cli/usage.ts index b5dcec332..26b439167 100644 --- a/packages/compiler/src/cli/usage.ts +++ b/packages/compiler/src/cli/usage.ts @@ -80,6 +80,11 @@ Options: values and the bindings, fields, functions, classes and modules the dynamic tier would take over, with the refusal behind each; a name shows only that unit's chain + --wasm + coverage only: report a WebAssembly module the program + loads whose path its sources do not spell (repeatable; + modules the sources name, inline modules and packaged + .wasm files are found without it) -h, --help show this help -v, --version print the version `; @@ -103,6 +108,7 @@ export const CLI_OPTIONS = { "external-types": { type: "string", multiple: true }, tier: { type: "string" }, "explain-dynamic": { type: "string" }, + wasm: { type: "string", multiple: true }, lib: { type: "boolean", default: false }, profile: { type: "string" }, help: { type: "boolean", short: "h", default: false }, diff --git a/packages/compiler/src/compile-types.ts b/packages/compiler/src/compile-types.ts index f069df247..2773af71b 100644 --- a/packages/compiler/src/compile-types.ts +++ b/packages/compiler/src/compile-types.ts @@ -171,6 +171,9 @@ export interface AnalyzeOptions { /** `--explain-dynamic`: attach the tier-assignment report * (CoverageInput.tiers). Such analyses bypass the verdict cache. */ explainDynamic?: boolean; + /** `--wasm `: WebAssembly module files the program loads that its + * sources do not name (absolute paths); reported with the discovered ones. */ + wasm?: readonly string[]; } export interface AnalyzeResult { diff --git a/packages/compiler/src/coverage/report.ts b/packages/compiler/src/coverage/report.ts index 8b03f221d..6570f23d1 100644 --- a/packages/compiler/src/coverage/report.ts +++ b/packages/compiler/src/coverage/report.ts @@ -24,6 +24,7 @@ import { renderDiagnostics } from "../diagnostics/render.js"; import type { LowerStats } from "../frontend/lowering/lowerer.js"; import type { ProvenanceSources } from "../frontend/provenance-registry.js"; import type { DemotionUnit, TierReport } from "../frontend/tier-analysis.js"; +import type { WasmModuleReport } from "../wasm/discover.js"; export interface CoverageInput { file: string; @@ -57,6 +58,9 @@ export interface CoverageInput { /** --explain-dynamic: the report-only tier assignment (which bindings, * fields, functions, classes and modules the dynamic tier would take). */ tiers?: TierReport; + /** The WebAssembly modules the build can see (wasm/discover.ts): their + * size, validity and the proposals they use. */ + wasmModules?: WasmModuleReport[]; /** True when tsc preflight failed — no coverage can be computed. */ preflightFailed: boolean; } @@ -217,6 +221,51 @@ 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. + 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)")}`, + ); + for (const m of wasm) { + const name = m.path !== undefined ? displayPath(m.path, opts.root) : "inline module"; + const state = + m.status === "valid" + ? c(GREEN, "valid") + : m.status === "unsupported" + ? c(YELLOW, `uses ${m.unsupported.join(", ")}`) + : c(RED, `${m.status}: ${m.error ?? ""}`); + out.push(` ${name} ${c(DIM, `${groupDigits(m.size)} bytes`)} ${state}`); + const imports = m.importModules.length > 0 ? ` (${m.importModules.join(", ")})` : ""; + out.push( + ` ${c(DIM, `${counted(m.functions, "function")}, ${counted(m.imports, "import")}${imports}, ${counted(m.exports, "export")}`)}`, + ); + if (m.features.length > 0) out.push(` ${c(DIM, `features: ${m.features.join(", ")}`)}`); + const shown = m.sources.slice(0, SITES_SHOWN); + for (const s of shown) { + const at = + s.line !== undefined + ? `${displayPath(s.file, opts.root)}:${s.line}` + : displayPath(s.file, opts.root); + const how = + s.kind === "path" + ? `path at ${at}` + : s.kind === "inline" + ? `inline at ${at}` + : s.kind === "package" + ? `shipped by the package at ${displayPath(dirOf(s.file), opts.root)}` + : `configured by ${at}`; + out.push(` ${c(DIM, `found: ${how}`)}`); + } + if (m.sources.length > shown.length) { + out.push(` ${c(DIM, `found: +${m.sources.length - shown.length} more`)}`); + } + } + out.push(""); + } + // --provenance-sources: per-package attribution — the answer to "did // the DEPENDENCY's statements compile static?", computed by summing // statsByFile entries under each package's source dir. Elided @@ -335,6 +384,27 @@ export function renderCoverage(input: CoverageInput, opts: CoverageRenderOptions return out.join("\n"); } +/** "1 function", "1,698 functions". */ +function counted(n: number, noun: string): string { + return `${groupDigits(n)} ${noun}${n === 1 ? "" : "s"}`; +} + +/** 637405 → "637,405". */ +function groupDigits(n: number): string { + const digits = String(n); + let out = ""; + for (let i = 0; i < digits.length; i++) { + if (i > 0 && (digits.length - i) % 3 === 0) out += ","; + out += digits[i]; + } + return out; +} + +function dirOf(file: string): string { + const slash = file.lastIndexOf("/"); + return slash <= 0 ? file : file.slice(0, slash); +} + function DIMPath(file: string, color: boolean): string { return color ? DIM + file + RESET : file; } @@ -453,6 +523,7 @@ export function coverageEnvelope( }, }), ...(input.tiers !== undefined ? { tiers: tiersEnvelope(input.tiers, locator) } : {}), + ...(input.wasmModules !== undefined ? { wasmModules: input.wasmModules } : {}), groups, diagnostics: located, }; diff --git a/packages/compiler/src/coverage/surface-manifest.ts b/packages/compiler/src/coverage/surface-manifest.ts index 45814cb8b..d82367611 100644 --- a/packages/compiler/src/coverage/surface-manifest.ts +++ b/packages/compiler/src/coverage/surface-manifest.ts @@ -38,7 +38,7 @@ import { InternalCompilerError } from "../errors.js"; * harness asserts refusals match entry codes. renderSurfaceManifest is * byte-deterministic: entries sort by id, keys are emitted in one fixed * order, and the output carries no timestamps or absolute paths. */ -import { FENCE_CODES, UNSUPPORTED } from "../diagnostics/diagnostic.js"; +import { FENCE_CODES, UNSUPPORTED, webAssemblyDiag } from "../diagnostics/diagnostic.js"; import { NODE24_FETCH_COMPAT_PROFILE } from "../compat/fetch-profile.js"; import { SUPPORTED_BUILTIN_MODULES, SUPPORTED_NODE_MODULES } from "../frontend/builtin-modules.js"; import { @@ -275,7 +275,7 @@ export function generateSurfaceManifest(compilerVersion: string): SurfaceManifes status: "static", ...(COLLECTION_ITERATOR_METHODS.has(name) ? { - note: "live native iterators support next(), for...of, and drains; iterator helper methods are refused", + note: "live native iterators support next(), for...of, drains, and the iterator helper methods", } : {}), }); @@ -288,7 +288,7 @@ export function generateSurfaceManifest(compilerVersion: string): SurfaceManifes status: "static", ...(COLLECTION_ITERATOR_METHODS.has(name) ? { - note: "live native iterators support next(), for...of, and drains; iterator helper methods are refused", + note: "live native iterators support next(), for...of, drains, and the iterator helper methods", } : {}), }); @@ -444,6 +444,19 @@ export function generateSurfaceManifest(compilerVersion: string): SurfaceManifes } } + // ── the WebAssembly global: every reached use refuses (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 } : {}), + }); + } + // ── fetch/Web platform: one explicit, versioned compatibility profile ─ const fetchTarget = `Node ${NODE24_FETCH_COMPAT_PROFILE.target.node} / ` + diff --git a/packages/compiler/src/coverage/verdict-cache.ts b/packages/compiler/src/coverage/verdict-cache.ts index 250259685..422bf5e4d 100644 --- a/packages/compiler/src/coverage/verdict-cache.ts +++ b/packages/compiler/src/coverage/verdict-cache.ts @@ -14,6 +14,7 @@ import type { AnalyzeOptions, AnalyzeResult } from "../compile-types.js"; import type { ScrDiagnostic } from "../diagnostics/diagnostic.js"; import type { LowerStats } from "../frontend/lowering/lowerer.js"; import type { NpmStaticStatus } from "./report.js"; +import type { WasmModuleReport } from "../wasm/discover.js"; import { FrontendInputTracker, frontendInputsStillMatch, @@ -38,6 +39,7 @@ export interface CachedCoverage { unreached?: { stats: LowerStats; diagnostics: ScrDiagnostic[]; runtimeFences?: ScrDiagnostic[] }; divergences?: ScrDiagnostic[]; npmStatic?: NpmStaticStatus[]; + wasmModules?: WasmModuleReport[]; preflightFailed: boolean; } @@ -125,6 +127,8 @@ export function verdictKey( external.join("\n"), // Demotion (stage S6) makes the tier mode part of the verdict. ...(opts.tier === "static-only" ? ["tier=static-only"] : []), + // The module files' contents are probes; their names are options. + ...(opts.wasm !== undefined && opts.wasm.length > 0 ? [`wasm=${opts.wasm.join("\n")}`] : []), ].join("\0"), ); } @@ -146,6 +150,7 @@ function cacheable(coverage: AnalyzeResult["coverage"]): CachedCoverage | null { if (coverage.unreached !== undefined) out.unreached = coverage.unreached; if (coverage.divergences !== undefined) out.divergences = coverage.divergences; if (coverage.npmStatic !== undefined) out.npmStatic = coverage.npmStatic; + if (coverage.wasmModules !== undefined) out.wasmModules = coverage.wasmModules; return out; } @@ -162,6 +167,7 @@ function restore(cached: CachedCoverage, sources: CachedSource[]): AnalyzeResult if (cached.unreached !== undefined) coverage.unreached = cached.unreached; if (cached.divergences !== undefined) coverage.divergences = cached.divergences; if (cached.npmStatic !== undefined) coverage.npmStatic = cached.npmStatic; + if (cached.wasmModules !== undefined) coverage.wasmModules = cached.wasmModules; return { coverage, sourceTexts }; } diff --git a/packages/compiler/src/diagnostics/diagnostic.ts b/packages/compiler/src/diagnostics/diagnostic.ts index e6ed50ae1..4acd6bc50 100644 --- a/packages/compiler/src/diagnostics/diagnostic.ts +++ b/packages/compiler/src/diagnostics/diagnostic.ts @@ -751,6 +751,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'). */ +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`, + 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)", + }; +} + /** A resolved native addon needs Node's embedding ABI. The migration uses the * underlying native operation through an ordinary C ABI declaration. */ export function nativeAddonDiag(specifier: string, loc: SrcLoc): ScrDiagnostic { diff --git a/packages/compiler/src/diagnostics/envelope.ts b/packages/compiler/src/diagnostics/envelope.ts index 4c7c158d9..c986fc5b1 100644 --- a/packages/compiler/src/diagnostics/envelope.ts +++ b/packages/compiler/src/diagnostics/envelope.ts @@ -16,6 +16,7 @@ * bumps it. */ import { readFileSync } from "node:fs"; import type { ScrDiagnostic } from "./diagnostic.js"; +import type { WasmModuleReport } from "../wasm/discover.js"; export const DIAGNOSTICS_SCHEMA = "scriptc-diagnostics"; export const DIAGNOSTICS_SCHEMA_VERSION = 1; @@ -138,6 +139,9 @@ export interface DiagnosticsEnvelope { artifact?: string; /** coverage --explain-dynamic only: the report-only tier assignment. */ tiers?: TiersEnvelope; + /** coverage only: the WebAssembly modules the build can see, with their + * size, validity, proposals and the sources that found them. */ + wasmModules?: WasmModuleReport[]; groups: DiagnosticGroup[]; diagnostics: LocatedDiagnostic[]; } diff --git a/packages/compiler/src/frontend/analysis.ts b/packages/compiler/src/frontend/analysis.ts index f17f6af6c..43d0aa2bb 100644 --- a/packages/compiler/src/frontend/analysis.ts +++ b/packages/compiler/src/frontend/analysis.ts @@ -93,6 +93,7 @@ export function analyzeWithFrontend( ...(ffi !== null ? { ffiImports: ffi.functions } : {}), ...(opts.tier !== undefined ? { tierMode: opts.tier } : {}), ...(opts.explainDynamic === true ? { tierReport: { preflight } } : {}), + ...(opts.wasm !== undefined && opts.wasm.length > 0 ? { wasmFiles: opts.wasm } : {}), }); const provenance = provenanceSources(); return { @@ -113,6 +114,7 @@ export function analyzeWithFrontend( ...(lowered.statsByFile ? { statsByFile: lowered.statsByFile } : {}), ...(lowered.provenanceElided ? { provenanceElided: lowered.provenanceElided } : {}), ...(lowered.tiers !== undefined ? { tiers: lowered.tiers } : {}), + ...(lowered.wasmModules !== undefined ? { wasmModules: lowered.wasmModules } : {}), preflightFailed: false, }, sourceTexts: fe.sourceTexts(), diff --git a/packages/compiler/src/frontend/lowering/builtins/webassembly.ts b/packages/compiler/src/frontend/lowering/builtins/webassembly.ts new file mode 100644 index 000000000..dc61853f8 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/builtins/webassembly.ts @@ -0,0 +1,132 @@ +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 { stdlibGlobalNameOf } from "../surfaces.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. */ + +/** Strips the spellings that leave a value unchanged: parentheses, type + * assertions, `satisfies` and non-null assertions. */ +function bare(expr: ts.Expression): ts.Expression { + for (;;) { + if (ts.isParenthesizedExpression(expr) || ts.isNonNullExpression(expr)) expr = expr.expression; + else if (ts.isAsExpression(expr) || ts.isTypeAssertion(expr)) expr = expr.expression; + else if (ts.isSatisfiesExpression(expr)) expr = expr.expression; + else return expr; + } +} + +/** The global object itself, as `globalThis` or `global` spells it. */ +function isGlobalThis(lowerer: Lowerer, expr: ts.Expression): boolean { + const node = bare(expr); + return ( + ts.isIdentifier(node) && + (node.text === "globalThis" || node.text === "global") && + stdlibGlobalNameOf(lowerer, node) === "globalThis" + ); +} + +/** THE WebAssembly namespace value: `WebAssembly` or `globalThis.WebAssembly` + * (and the global object reached through a cast, as in + * `(globalThis as any).WebAssembly`). */ +function isWebAssemblyGlobal(lowerer: Lowerer, expr: ts.Expression): boolean { + expr = bare(expr); + if (ts.isIdentifier(expr)) { + return expr.text === "WebAssembly" && stdlibGlobalNameOf(lowerer, expr) === "WebAssembly"; + } + if (ts.isPropertyAccessExpression(expr)) { + return expr.name.text === "WebAssembly" && isGlobalThis(lowerer, expr.expression); + } + if (ts.isElementAccessExpression(expr)) { + const key = expr.argumentExpression; + return ( + (ts.isStringLiteral(key) || ts.isNoSubstitutionTemplateLiteral(key)) && + key.text === "WebAssembly" && + isGlobalThis(lowerer, expr.expression) + ); + } + return false; +} + +/** The surface a WebAssembly API expression names ('WebAssembly', + * 'globalThis.WebAssembly', 'WebAssembly.compile'), or null. A cheap + * spelling check runs first: almost every expression is rejected without a + * checker query. */ +function webAssemblySurface(lowerer: Lowerer, expr: ts.Expression): string | null { + // `globalThis as unknown as { WebAssembly: ... }`: the cast's target type + // names the member, and the value it checks is the global object's + // WebAssembly (the spelling pi's codemode uses). + if ( + (ts.isAsExpression(expr) || ts.isTypeAssertion(expr)) && + isGlobalThis(lowerer, expr.expression) + ) { + const target = lowerer.checker.getTypeAtLocation(expr.type); + return lowerer.checker.getPropertyOfType(target, "WebAssembly") !== undefined + ? "globalThis.WebAssembly" + : null; + } + const node = bare(expr); + if (ts.isIdentifier(node)) { + return node.text === "WebAssembly" && isWebAssemblyGlobal(lowerer, node) ? "WebAssembly" : null; + } + if (ts.isPropertyAccessExpression(node)) { + if (node.name.text === "WebAssembly") { + return isWebAssemblyGlobal(lowerer, node) ? "globalThis.WebAssembly" : null; + } + // WebAssembly., and members of members + // (WebAssembly.Module.customSections). + const names = [node.name.text]; + let receiver = bare(node.expression); + while (ts.isPropertyAccessExpression(receiver) && receiver.name.text !== "WebAssembly") { + names.unshift(receiver.name.text); + receiver = bare(receiver.expression); + } + const spelled = + (ts.isIdentifier(receiver) && receiver.text === "WebAssembly") || + (ts.isPropertyAccessExpression(receiver) && receiver.name.text === "WebAssembly"); + return spelled && isWebAssemblyGlobal(lowerer, receiver) + ? `WebAssembly.${names.join(".")}` + : null; + } + if (ts.isElementAccessExpression(node)) { + return isWebAssemblyGlobal(lowerer, node) ? "globalThis.WebAssembly" : null; + } + return null; +} + +/** Fences a reached use of the WebAssembly API. `prefix` qualifies a + * construction ('new '). Returns normally when `expr` is anything else. */ +export function refuseWebAssemblyUse(lowerer: Lowerer, expr: ts.Expression, prefix = ""): void { + const surface = webAssemblySurface(lowerer, expr); + if (surface === null) return; + lowerer.pushDiag(webAssemblyDiag(`${prefix}${surface}`, locOf(expr))); + throw new PoisonError(); +} + +/** `typeof WebAssembly` is "object" and `typeof WebAssembly.` is + * "function" for every member the namespace declares, as in Node. The + * operand is an effect-free global read, so nothing else evaluates. */ +export function lowerWebAssemblyTypeof(lowerer: Lowerer, operand: ts.Expression): IrExpr | null { + const surface = webAssemblySurface(lowerer, operand); + if (surface === null) return null; + const loc = locOf(operand); + if (surface === "WebAssembly" || surface === "globalThis.WebAssembly") { + return { kind: "strLit", value: "object", type: STRING, loc }; + } + const t = lowerer.typeOf(operand); + if ( + lowerer.checker.getCallSignatures(t).length > 0 || + lowerer.checker.getConstructSignatures(t).length > 0 + ) { + return { kind: "strLit", value: "function", type: STRING, loc }; + } + return null; +} diff --git a/packages/compiler/src/frontend/lowering/call-signatures.ts b/packages/compiler/src/frontend/lowering/call-signatures.ts index ae59be3b2..d98f80feb 100644 --- a/packages/compiler/src/frontend/lowering/call-signatures.ts +++ b/packages/compiler/src/frontend/lowering/call-signatures.ts @@ -510,6 +510,24 @@ export function requireExactArityValue( ? lowerer.mapTypeOf(lowerer.typeOf(contextual)) : null; if (mapped && typeEquals(mapped, funcType)) return; + // An object-literal METHOD has no contextual type of its own: the + // literal's contextual type names the member slot it fills. An + // overloaded member's slot holds its erased function, which spells the + // completed parameters of an implementation like `m(a?: string)`. + if ( + contextual === null && + ts.isMethodDeclaration(blame) && + blame.parent !== undefined && + ts.isObjectLiteralExpression(blame.parent) && + (ts.isIdentifier(blame.name) || ts.isStringLiteral(blame.name)) + ) { + const literalType = lowerer.checker.getContextualType(blame.parent); + const member = literalType + ? lowerer.checker.getPropertyOfType(literalType, blame.name.text) + : undefined; + const slot = member ? lowerer.memberSlotTypeOf(lowerer.checker.getTypeOfSymbol(member)) : null; + if (slot && typeEquals(slot, funcType)) return; + } // A union-typed slot (`runner || defaultRunner` under a // `CommandRunner | undefined` context): the value can only inhabit // the union's one func arm — judge by it. diff --git a/packages/compiler/src/frontend/lowering/cjs-exports-object.ts b/packages/compiler/src/frontend/lowering/cjs-exports-object.ts new file mode 100644 index 000000000..d72792ae7 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/cjs-exports-object.ts @@ -0,0 +1,430 @@ +/* A CommonJS module's own exports object, seen from inside the module. + * + * The compiled module system has no reflective exports object: each export + * is a module global (collectGlobals) or alias plumbing to a declaration. + * Inside the module that is enough for + * + * - member reads and member calls (`exports.f`, `exports.f(x)`, + * `module.exports.f(x)`): they are the member's export global, the + * storage every `exports.f =` statement assigns; + * - identity comparisons of the object itself (`root === module.exports`, + * `exports === module.exports`): while the module never replaces + * `module.exports` and never rebinds `exports`, both name the module's + * original exports object, which top-level `this` already represents + * (lowerCjsTopLevelThis). `typeof` and truthiness keep their existing + * lowerings. + * + * Every other use of the object as a value (passing it to a function, + * storing it, reading a member through an alias) would need a real object + * whose properties are the exports; those uses keep a named refusal. The + * dynamic CommonJS module object is the two-tier design's S9 stage. */ +import * as ts from "../ts7/adapter.js"; +import type { Lowerer } from "./lowerer.js"; +import { + cjsExportAssignmentOf, + cjsExportTargetLiteral, + isCjsJsFile, + isModuleExportsAccess, + isRequireStatement, + locOf, +} from "../program.js"; +import { isCjsModuleGlobal } from "./lower-node-module.js"; +import { DYN, type IrExpr, type IrGlobal } from "../../ir/ir.js"; + +/** True for the CommonJS wrapper's `exports` binding (not shadowed by any + * source declaration) in a CommonJS JS file. */ +export function isCjsExportsIdentifier(lowerer: Lowerer, node: ts.Expression): boolean { + if (!ts.isIdentifier(node) || node.text !== "exports") return false; + if (!isCjsJsFile(node.getSourceFile(), lowerer.program)) return false; + const symbol = lowerer.checker.getSymbolAtLocation(node); + const decls = symbol ? lowerer.checker.declarationsOf(symbol) : []; + return !decls.some( + (d) => + !d.getSourceFile().isDeclarationFile && + (ts.isVariableDeclaration(d) || + ts.isParameter(d) || + ts.isBindingElement(d) || + ts.isFunctionDeclaration(d) || + ts.isClassDeclaration(d) || + ts.isImportSpecifier(d) || + ts.isNamespaceImport(d) || + ts.isImportEqualsDeclaration(d)), + ); +} + +/** `module.exports` over the CommonJS `module` global in a CommonJS file. */ +export function isCjsModuleExports(lowerer: Lowerer, node: ts.Expression): boolean { + return ( + isModuleExportsAccess(node) && + isCjsModuleGlobal(lowerer, node.expression) && + isCjsJsFile(node.getSourceFile(), lowerer.program) + ); +} + +/** The export global behind a same-module member access `exports.` / + * `module.exports.`, or null (identifier-valued members are alias + * plumbing with no storage, and other receivers are not the exports + * object). */ +export function cjsInFileExportGlobalOf( + lowerer: Lowerer, + access: ts.PropertyAccessExpression, +): IrGlobal | null { + if (access.questionDotToken || !ts.isIdentifier(access.name)) return null; + const sf = access.getSourceFile(); + const recv = + isModuleExportsAccess(access.expression) || + (ts.isIdentifier(access.expression) && + access.expression.text === "exports" && + !lowerer.resolveLocal(access.expression) && + !lowerer.globalOf(access.expression)); + if (!recv || !isCjsJsFile(sf, lowerer.program)) return null; + const sym = + lowerer.checker.getSymbolAtLocation(access.name) ?? + lowerer.cjsModuleExportSymbol(sf, access.name.text); + const resolved = + sym !== undefined && sym.flags & ts.SymbolFlags.Alias + ? lowerer.checker.getAliasedSymbol(sym) + : sym; + return ( + (sym ? lowerer.globalsBySymbol.get(sym) : undefined) ?? + (resolved ? lowerer.globalsBySymbol.get(resolved) : undefined) ?? + null + ); +} + +/** Whether `node` is an operand of an equality operator: only its identity + * is observed. */ +function identityUse(node: ts.Expression): boolean { + let child: ts.Node = node; + let parent = node.parent; + while (parent !== undefined && ts.isParenthesizedExpression(parent)) { + child = parent; + parent = parent.parent; + } + if (parent === undefined || !ts.isBinaryExpression(parent)) return false; + const op = parent.operatorToken.kind; + return ( + (op === ts.SyntaxKind.EqualsEqualsEqualsToken || + op === ts.SyntaxKind.ExclamationEqualsEqualsToken || + op === ts.SyntaxKind.EqualsEqualsToken || + op === ts.SyntaxKind.ExclamationEqualsToken) && + (parent.left === child || parent.right === child) + ); +} + +/** Uses whose answer does not need the object: `typeof`, `void`, and + * truthiness tests (their existing lowerings answer them). */ +function answeredWithoutObject(node: ts.Expression): boolean { + let child: ts.Node = node; + let parent = node.parent; + while (parent !== undefined && ts.isParenthesizedExpression(parent)) { + child = parent; + parent = parent.parent; + } + if (parent === undefined) return false; + if (ts.isTypeOfExpression(parent) || ts.isVoidExpression(parent)) return true; + return truthinessOnly(child as ts.Expression); +} + +function truthinessOnly(node: ts.Expression): boolean { + let child: ts.Node = node; + for (let parent = node.parent; parent !== undefined; child = parent, parent = parent.parent) { + if (ts.isParenthesizedExpression(parent)) continue; + if (ts.isPrefixUnaryExpression(parent)) + return parent.operator === ts.SyntaxKind.ExclamationToken; + if ( + ts.isBinaryExpression(parent) && + (parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || + parent.operatorToken.kind === ts.SyntaxKind.BarBarToken) + ) + continue; + if (ts.isIfStatement(parent) || ts.isWhileStatement(parent) || ts.isDoStatement(parent)) + return parent.expression === child; + if (ts.isForStatement(parent)) return parent.condition === child; + if (ts.isConditionalExpression(parent)) return parent.condition === child; + return false; + } + return false; +} + +/** Which of the module's exports bindings the file ever assigns (any + * nesting, compound operators included), cached per file on the lowerer + * (Lowerer.cjsExportsAssignments). */ +function exportsAssignments( + lowerer: Lowerer, + sf: ts.SourceFile, +): { exports: boolean; moduleExports: boolean } { + const cached = lowerer.cjsExportsAssignments.get(sf); + if (cached !== undefined) return cached; + const out = { exports: false, moduleExports: false }; + lowerer.cjsExportsAssignments.set(sf, out); + ts.walkPreorder(sf, (node) => { + // A fresh `exports = module.exports = {}` reset leaves both bindings + // naming one (new, empty) exports object for the rest of the module. + if (ts.isExpressionStatement(node) && isFreshExportsReset(lowerer, node)) return "skip"; + if ( + !ts.isBinaryExpression(node) || + node.operatorToken.kind < ts.SyntaxKind.FirstAssignment || + node.operatorToken.kind > ts.SyntaxKind.LastAssignment + ) + return undefined; + let target = node.left; + while (ts.isParenthesizedExpression(target)) target = target.expression; + if (isCjsModuleExports(lowerer, target)) out.moduleExports = true; + if (isCjsExportsIdentifier(lowerer, target)) out.exports = true; + return undefined; + }); + return out; +} + +/** Whether `node` still names the module's ORIGINAL exports object wherever + * it runs: `exports` unless the file rebinds it; `module.exports` unless the + * file rebinds `exports` or replaces `module.exports`. */ +function namesOriginalExports(lowerer: Lowerer, node: ts.Expression): boolean { + const assigned = exportsAssignments(lowerer, node.getSourceFile()); + if (assigned.exports) return false; + return ts.isIdentifier(node) || !assigned.moduleExports; +} + +/** The uses this module answers with the original exports object: identity + * comparisons and `typeof` of either spelling, and truthiness or `void` of + * `exports` (`module.exports` truthiness keeps its existing fold). */ +function objectAnsweredUse(node: ts.Expression): boolean { + if (identityUse(node)) return true; + let parent = node.parent; + while (parent !== undefined && ts.isParenthesizedExpression(parent)) parent = parent.parent; + if (parent !== undefined && ts.isTypeOfExpression(parent)) return true; + return ts.isIdentifier(node) && answeredWithoutObject(node); +} + +/** Whether `node` (`exports` or `module.exports`) is a use of the module's + * exports object as a VALUE (not a member access receiver, not an + * assignment target). */ +export function isCjsExportsObjectValue(lowerer: Lowerer, node: ts.Expression): boolean { + if (!isCjsExportsIdentifier(lowerer, node) && !isCjsModuleExports(lowerer, node)) return false; + let outer: ts.Node = node; + while (outer.parent !== undefined && ts.isParenthesizedExpression(outer.parent)) + outer = outer.parent; + const parent = outer.parent; + if (parent === undefined) return false; + if ( + (ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) && + parent.expression === outer + ) + return false; + if ( + ts.isBinaryExpression(parent) && + parent.left === outer && + parent.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && + parent.operatorToken.kind <= ts.SyntaxKind.LastAssignment + ) + return false; + return true; +} + +/** Files whose exports object is observed by identity somewhere: their top- + * level `this` object must exist (lowerFileInit creates it). */ +export function usesCjsExportsIdentity(lowerer: Lowerer, sf: ts.SourceFile): boolean { + if (!isCjsJsFile(sf, lowerer.program)) return false; + let found = false; + ts.walkPreorder(sf, (node) => { + if ( + (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node)) && + isCjsExportsObjectValue(lowerer, node) && + objectAnsweredUse(node) && + namesOriginalExports(lowerer, node) + ) { + found = true; + return "stop"; + } + return undefined; + }); + return found; +} + +/** `exports` / `module.exports` used as a value inside its own module: the + * original exports object for identity, typeof and truthiness, or a named + * refusal. Null when `node` is not such a use. */ +export function lowerCjsExportsObjectValue(lowerer: Lowerer, node: ts.Expression): IrExpr | null { + if (!isCjsExportsObjectValue(lowerer, node)) return null; + const sf = node.getSourceFile(); + // A module that replaces module.exports answers `module.exports` reads + // through the replacement's own machinery (the class-expression whole + // export, the replaced-exports reads). + if (!ts.isIdentifier(node) && exportsAssignments(lowerer, sf).moduleExports) return null; + const spelled = ts.isIdentifier(node) ? "exports" : "module.exports"; + const original = lowerer.cjsExportsThis.get(sf); + if (objectAnsweredUse(node) && original !== undefined && namesOriginalExports(lowerer, node)) { + return { kind: "varRef", localId: original.id, type: DYN, loc: locOf(node) }; + } + // `module.exports` truthiness keeps its existing fold (and anything the + // object is not needed for keeps whatever answered it before). + if (answeredWithoutObject(node)) return null; + lowerer.unsupported( + "SC1090", + node, + identityUse(node) + ? `comparing '${spelled}' in a module that replaces module.exports or rebinds exports (the compiled exports are a static table, not an object with an identity)` + : `'${spelled}' as a value other than a member access, comparison, typeof or truthiness test (the compiled exports are a static table, not an object: read ${spelled}.)`, + ); +} + +/** `exports = module.exports = {}` (either order) as a top-level statement + * that runs before anything could observe or extend the original exports + * object: only directives, require statements and function declarations + * precede it, and the module assigns neither binding anywhere else. Node + * swaps the original empty exports object for another empty one that both + * bindings name; the compiled module's static exports start out exactly + * the same, so the statement is a no-op (semver's internal/re.js). */ +export function isFreshExportsReset(lowerer: Lowerer, stmt: ts.ExpressionStatement): boolean { + const sf = stmt.parent; + if (!ts.isSourceFile(sf) || !isCjsJsFile(sf, lowerer.program)) return false; + let e: ts.Expression = stmt.expression; + const targets: ts.Expression[] = []; + for (;;) { + while (ts.isParenthesizedExpression(e)) e = e.expression; + if (!ts.isBinaryExpression(e) || e.operatorToken.kind !== ts.SyntaxKind.EqualsToken) break; + targets.push(e.left); + e = e.right; + } + if (!ts.isObjectLiteralExpression(e) || e.properties.length !== 0) return false; + if (targets.length !== 2) return false; + const hasExports = targets.some((t) => isCjsExportsIdentifier(lowerer, t)); + const hasModuleExports = targets.some((t) => isCjsModuleExports(lowerer, t)); + if (!hasExports || !hasModuleExports) return false; + for (const prior of sf.statements) { + if (prior === stmt) break; + if (ts.isFunctionDeclaration(prior) || isRequireStatement(prior)) continue; + if (ts.isExpressionStatement(prior) && ts.isStringLiteral(prior.expression)) continue; + return false; + } + let others = 0; + ts.walkPreorder(sf, (node) => { + if ( + !ts.isBinaryExpression(node) || + node.operatorToken.kind < ts.SyntaxKind.FirstAssignment || + node.operatorToken.kind > ts.SyntaxKind.LastAssignment + ) + return undefined; + let target = node.left; + while (ts.isParenthesizedExpression(target)) target = target.expression; + if (isCjsModuleExports(lowerer, target) || isCjsExportsIdentifier(lowerer, target)) others++; + return undefined; + }); + return others === 2; +} + +/** The export global a WRITE `exports. = v` / `module.exports. = + * v` updates when it is not a top-level export statement (inside a + * function, or in value position): only while the module keeps its + * original exports object, which is then the object every requirer reads + * the member from. */ +export function cjsExportMemberWriteGlobalOf( + lowerer: Lowerer, + target: ts.PropertyAccessExpression, +): IrGlobal | null { + const sf = target.getSourceFile(); + if (!isCjsJsFile(sf, lowerer.program)) return null; + const assigned = exportsAssignments(lowerer, sf); + if (assigned.exports || assigned.moduleExports) return null; + return cjsInFileExportGlobalOf(lowerer, target); +} + +/** Whether a function body reads `this` (arrow functions inherit it; other + * nested functions bind their own). */ +function functionUsesThis(fn: ts.FunctionLikeDeclaration): boolean { + if (fn.body === undefined) return false; + let found = false; + ts.walkPreorder(fn.body, (node) => { + if (node !== fn.body && ts.isFunctionLike(node) && !ts.isArrowFunction(node)) return "skip"; + if (node.kind === ts.SyntaxKind.ThisKeyword) { + found = true; + return "stop"; + } + return undefined; + }); + return found; +} + +/** A function declaration, or a variable initialized with a function or + * arrow expression, that never reads `this`. */ +function symbolIsThisFreeFunction(lowerer: Lowerer, sym: ts.Symbol | undefined): boolean { + const decls = sym ? lowerer.checker.declarationsOf(sym) : []; + const fn = decls.find(ts.isFunctionDeclaration); + if (fn !== undefined) return !functionUsesThis(fn); + const v = decls.find(ts.isVariableDeclaration); + let init = v?.initializer; + while (init !== undefined && ts.isParenthesizedExpression(init)) init = init.expression; + return ( + init !== undefined && + (ts.isFunctionExpression(init) || ts.isArrowFunction(init)) && + !functionUsesThis(init) + ); +} + +/** True when every value the module assigns to its export `name` is a + * function that never reads `this`. A call through the exports object + * (`exports.f(x)`) binds `this` to that object, which the static export + * table cannot supply, so only these calls lower; the others keep a fence. */ +export function cjsExportCallIgnoresThis( + lowerer: Lowerer, + sf: ts.SourceFile, + name: string, + depth = 0, +): boolean { + if (depth > 16) return false; + const values: ts.Expression[] = []; + ts.walkPreorder(sf, (node) => { + if ( + ts.isBinaryExpression(node) && + node.operatorToken.kind === ts.SyntaxKind.EqualsToken && + ts.isPropertyAccessExpression(node.left) && + node.left.name.text === name && + (isCjsExportsIdentifier(lowerer, node.left.expression) || + isCjsModuleExports(lowerer, node.left.expression)) + ) { + values.push(node.right); + } + return undefined; + }); + // Entries of a `module.exports = { ... }` table (direct, or a const + // literal the statement names). + let methodEntry: ts.MethodDeclaration | null = null; + let shorthandOnly = false; + for (const stmt of sf.statements) { + const cjs = cjsExportAssignmentOf(stmt); + if (cjs?.kind !== "table") continue; + const table = cjs.obj ?? cjsExportTargetLiteral(cjs.expr.right, sf); + for (const prop of table?.properties ?? []) { + if (prop.name === undefined || !ts.isIdentifier(prop.name) || prop.name.text !== name) + continue; + if (ts.isPropertyAssignment(prop)) values.push(prop.initializer); + else if (ts.isShorthandPropertyAssignment(prop)) { + const value = lowerer.checker.getShorthandAssignmentValueSymbol(prop); + if (!symbolIsThisFreeFunction(lowerer, value)) return false; + shorthandOnly = true; + } else if (ts.isMethodDeclaration(prop)) methodEntry = prop; + } + } + if (methodEntry !== null) return values.length === 0 && !functionUsesThis(methodEntry); + if (values.length === 0) return shorthandOnly; + return values.every((v) => { + let e = v; + while (ts.isParenthesizedExpression(e)) e = e.expression; + if (ts.isFunctionExpression(e) || ts.isArrowFunction(e)) return !functionUsesThis(e); + if (ts.isIdentifier(e)) { + return symbolIsThisFreeFunction(lowerer, lowerer.checker.getSymbolAtLocation(e)); + } + // Another module's member (`exports.f = require("./lib").f`, or through + // a module binding): that module's own export values decide. + if (ts.isPropertyAccessExpression(e) && ts.isIdentifier(e.name)) { + const dep = ts.isIdentifier(e.expression) + ? lowerer.cjsLocalModuleBindingOf(e.expression) + ? lowerer.cjsModuleBindingDepOf(e.expression) + : null + : lowerer.cjsModuleRefDepOf(e.expression); + return dep !== null && cjsExportCallIgnoresThis(lowerer, dep, e.name.text, depth + 1); + } + return false; + }); +} diff --git a/packages/compiler/src/frontend/lowering/cjs-inline-require.ts b/packages/compiler/src/frontend/lowering/cjs-inline-require.ts new file mode 100644 index 000000000..7f31337f5 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/cjs-inline-require.ts @@ -0,0 +1,370 @@ +/* Inline CommonJS `require("./x")` of a program module in expression + * position. A top-level `const m = require("./x")` binding is alias + * plumbing: member reads resolve to the exporter's declarations, and the + * statement lowers to the dependency's run-once %init call. An inline + * require is the same thing without the binding: the %init call runs at + * exactly the call's position (Node evaluates the module there, or + * answers from its cache), and the value is then read statically: + * + * - `require("./x").f` and `require("./x").f(...)` over a module whose + * exports are a table (member exports or `module.exports = {...}`) + * read the member like a binding would; + * - `require("./x")` as a value over a module whose whole export is one + * value (`module.exports = fn` / `= class {}` / `= make()` / `= 42` / + * `= require("./y")`) answers that value. + * + * A table module's exports object as a value has no static + * representation; it keeps a named refusal (a first-class CommonJS module + * object is the two-tier design's S9 stage). */ +import * as ts from "../ts7/adapter.js"; +import type { Lowerer } from "./lowerer.js"; +import { + canonicalBuiltinModule, + cjsExportAssignmentOf, + cjsExportDiscardReason, + cjsExportTargetLiteral, + isCjsJsFile, + isJsSourceFile, + isModuleExportsAccess, + locOf, + npmStaticDepSf7, + requireSpecOf, + resolveImport, +} from "../program.js"; +import { createRequireCalleeFileOf } from "./builtins/module-bindings.js"; +import { isCjsRequireGlobal } from "./lower-node-module.js"; +import { DYN, type IrExpr } from "../../ir/ir.js"; +import { nodeThrowExpr } from "../../ir/build.js"; +import { probeNodeRequireRefusal } from "../npm.js"; + +export interface InlineRequire { + call: ts.CallExpression; + spec: string; + dep: ts.SourceFile; +} + +/** A `require("")` call of the CommonJS global in a CommonJS JS + * file whose target is a compiled program module (relative, aliased, or an + * opted-in --npm-static package). Builtins, JSON documents and + * createRequire bindings answer null: their own lowerings own them. */ +export function inlineProgramRequireOf( + lowerer: Lowerer, + expr: ts.Expression, +): InlineRequire | null { + let e = expr; + while (ts.isParenthesizedExpression(e)) e = e.expression; + if (!ts.isCallExpression(e) || !ts.isIdentifier(e.expression)) return null; + const spec = requireSpecOf(e); + if (spec === null || canonicalBuiltinModule(spec) !== null) return null; + const sf = e.getSourceFile(); + if (!isCjsJsFile(sf, lowerer.program)) return null; + if (!isCjsRequireGlobal(lowerer, e.expression)) return null; + if (createRequireCalleeFileOf(lowerer, e.expression) !== null) return null; + const dep = + resolveImport(lowerer.program, sf, spec, "require") ?? + npmStaticDepSf7(lowerer.program, sf, spec, "require"); + if (!dep || dep.isDeclarationFile || dep.fileName.endsWith(".json")) return null; + return { call: e, spec, dep }; +} + +/** The kept (last, not discarded) top-level `module.exports = ` of a + * CommonJS module whose whole export is a single value, or null when its + * exports are a table: member exports only, or a literal / const-literal / + * Proxy-over-literal table. */ +export function cjsWholeExportValueOf( + sf: ts.SourceFile, +): { assign: ts.BinaryExpression; rhs: ts.Expression } | null { + let kept: ts.BinaryExpression | null = null; + for (const stmt of sf.statements) { + const cjs = cjsExportAssignmentOf(stmt); + if (cjs?.kind === "table" && cjsExportDiscardReason(stmt) === null) kept = cjs.expr; + } + if (kept === null) return null; + let rhs: ts.Expression = kept.right; + while (ts.isParenthesizedExpression(rhs)) rhs = rhs.expression; + if (ts.isObjectLiteralExpression(rhs) || cjsExportTargetLiteral(rhs, sf) !== null) return null; + return { assign: kept, rhs }; +} + +/** True when `dep`'s exports, through `module.exports = require("./y")` + * re-export chains, are a table that member reads resolve against. */ +export function cjsNamespaceModule(lowerer: Lowerer, dep: ts.SourceFile, depth = 0): boolean { + const whole = cjsWholeExportValueOf(dep); + if (whole === null) return true; + const inner = inlineProgramRequireOf(lowerer, whole.rhs); + return inner !== null && depth < 32 && cjsNamespaceModule(lowerer, inner.dep, depth + 1); +} + +/** An inline program-module require over a table module (member reads and + * member calls resolve through it), or null. */ +export function inlineNamespaceRequireOf( + lowerer: Lowerer, + expr: ts.Expression, +): InlineRequire | null { + const req = inlineProgramRequireOf(lowerer, expr); + return req !== null && cjsNamespaceModule(lowerer, req.dep) ? req : null; +} + +/** `value` evaluated after the required module's run-once %init (and its + * module-registry link) at the require's own position. */ +export function withRequireInit(lowerer: Lowerer, req: InlineRequire, value: IrExpr): IrExpr { + if (lowerer.inlineRequireCycleCalls.has(req.call)) { + lowerer.unsupported( + "SC1090", + req.call, + `require() of '${req.spec}' while it is still evaluating (a require cycle: Node answers its partial exports, which the static export table does not model)`, + ); + } + // Every inline program require is a preflight module edge, so its module + // has an initializer; never read its exports without evaluating it. + if (!lowerer.initNameOf.has(req.dep)) { + lowerer.unsupported( + "SC1090", + req.call, + `require() of '${req.spec}' here (the module is not part of the compiled module order)`, + ); + } + const init = lowerer.requireInitStmt(req.spec, req.call); + if (init === null) return value; + return { kind: "seqExpr", stmts: [init], result: value, type: value.type, loc: value.loc }; +} + +/** The whole-export value of `dep` read from the requirer, following + * `module.exports = require("./y")` re-exports (the inner module already + * evaluated inside dep's own %init). Null for table modules and for + * whole-export shapes with no represented value. */ +export function wholeExportValue( + lowerer: Lowerer, + dep: ts.SourceFile, + blame: ts.Node, + depth = 0, +): IrExpr | null { + const whole = cjsWholeExportValueOf(dep); + if (whole === null || depth > 32) return null; + const inner = inlineProgramRequireOf(lowerer, whole.rhs); + if (inner !== null) return wholeExportValue(lowerer, inner.dep, blame, depth + 1); + // An identifier names a declaration of the exporting module (or a + // builtin global): reading it IS the export, exactly what requirer + // bindings alias to. + if (ts.isIdentifier(whole.rhs)) return lowerer.lowerExpr(whole.rhs); + if (ts.isClassExpression(whole.rhs)) { + return lowerer.classValueRef(lowerer.lowerClassExpressionInfo(whole.rhs), blame); + } + const g = lowerer.globalsByDeclNode.get(whole.assign); + if (g === undefined) return null; + return { kind: "varRef", localId: g.id, type: g.type, loc: locOf(blame) }; +} + +/** `require("./x")` as a value (`require("debug")("ns")`, `new + * (require("./C"))()`, `{ verify: require("./verify") }`): the module's + * %init at this position, then its whole-export value. Null when `call` + * is not an inline program-module require. */ +export function lowerInlineRequireValue(lowerer: Lowerer, call: ts.CallExpression): IrExpr | null { + const req = inlineProgramRequireOf(lowerer, call); + if (req === null) return null; + const value = wholeExportValue(lowerer, req.dep, call, 0); + if (value === null) { + lowerer.unsupported( + "SC1090", + call, + cjsNamespaceModule(lowerer, req.dep) + ? `the exports object of '${req.spec}' as a value (its exports compile to a static table: read require(${JSON.stringify(req.spec)}).member directly, or bind const m = require(${JSON.stringify(req.spec)}) at the module's top level)` + : `the whole export of '${req.spec}' as a value (its 'module.exports =' value has no static representation)`, + ); + } + return withRequireInit(lowerer, req, value); +} + +/** Lowers `inner` (a member read or member call whose receiver is the + * inline require) with that require marked as handled, so the receiver + * resolves as a module binding, then sequences the module's %init first. */ +export function lowerWithInlineRequireInit( + lowerer: Lowerer, + req: InlineRequire, + inner: () => IrExpr, +): IrExpr { + lowerer.inlineRequireInitDone.add(req.call); + try { + return withRequireInit(lowerer, req, inner()); + } finally { + lowerer.inlineRequireInitDone.delete(req.call); + } +} + +/** A `require(...)` call of the CommonJS global in a CommonJS file that no + * other lowering claimed (not a builtin, JSON document, program module or + * createRequire binding): a package nothing installed resolves throws + * Node's catchable MODULE_NOT_FOUND at the call, and every other form is + * refused by name instead of as an unlowerable `require` value. */ +export function lowerUncompiledRequireCall( + lowerer: Lowerer, + call: ts.CallExpression, +): IrExpr | null { + if (!ts.isIdentifier(call.expression) || call.expression.text !== "require") return null; + const sf = call.getSourceFile(); + if (!isCjsJsFile(sf, lowerer.program) || !isCjsRequireGlobal(lowerer, call.expression)) + return null; + if (createRequireCalleeFileOf(lowerer, call.expression) !== null) return null; + const spec = requireSpecOf(call); + if (spec === null) { + lowerer.unsupported( + "SC1090", + call, + 'require() with a computed specifier (the compiled module graph is fixed at build time: require("") lowers)', + ); + } + if (canonicalBuiltinModule(spec) !== null) return null; + if (!spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("#")) { + const refusal = probeNodeRequireRefusal(sf.fileName, spec); + if (refusal !== null) { + return nodeThrowExpr(0, "MODULE_NOT_FOUND", refusal.message, DYN, locOf(call)); + } + lowerer.unsupported( + "SC1090", + call, + `require() of the package '${spec}' in an expression (the package is not compiled into this program)`, + ); + } + lowerer.unsupported( + "SC1090", + call, + `require() of '${spec}' in an expression (it does not resolve to a compiled program module)`, + ); +} + +/** The elements of a top-level `const { key: { ... } } = require("./x")` + * declaration over a program module whose nested pattern destructures the + * named export's value (preflight admits exactly these). Plain elements + * stay alias plumbing. */ +export function requireNestedPatternsOf(decl: ts.VariableDeclaration): ts.BindingElement[] { + if (!ts.isObjectBindingPattern(decl.name) || decl.initializer === undefined) return []; + const spec = requireSpecOf(decl.initializer); + if (spec === null || canonicalBuiltinModule(spec) !== null) return []; + if (!isJsSourceFile(decl.getSourceFile())) return []; + return decl.name.elements.filter( + (e) => + e.name !== undefined && + ts.isObjectBindingPattern(e.name) && + e.propertyName !== undefined && + ts.isIdentifier(e.propertyName) && + e.initializer === undefined && + e.dotDotDotToken === undefined, + ); +} + +/** A plain method entry of a `module.exports = { ... }` table: identifier + * name, a body, not a generator. Its value is the method's function. */ +export function cjsTableMethodEntry( + prop: ts.ObjectLiteralElementLike, +): (ts.MethodDeclaration & { name: ts.Identifier; body: ts.Block }) | null { + if (!ts.isMethodDeclaration(prop) || !ts.isIdentifier(prop.name) || prop.body === undefined) + return null; + if (prop.asteriskToken !== undefined) return null; + return prop as ts.MethodDeclaration & { name: ts.Identifier; body: ts.Block }; +} + +/** `exports. = value` / `module.exports. = value` assignments in + * VALUE position inside a top-level statement (`const src = exports.src = + * []`), outside function bodies and outside the statement's own export + * chain (`statementExport`, which the statement-level machinery owns). */ +export function nestedCjsExportAssignmentsOf( + stmt: ts.Statement, + statementExport: ts.BinaryExpression | undefined, +): { name: ts.Identifier; value: ts.Expression }[] { + if (!ts.isVariableStatement(stmt) && !ts.isExpressionStatement(stmt)) return []; + const owned = new Set(); + for (let e: ts.Expression | undefined = statementExport; e !== undefined;) { + while (ts.isParenthesizedExpression(e)) e = e.expression; + if (!ts.isBinaryExpression(e) || e.operatorToken.kind !== ts.SyntaxKind.EqualsToken) break; + owned.add(e); + e = e.right; + } + const out: { name: ts.Identifier; value: ts.Expression }[] = []; + ts.walkPreorder(stmt, (node) => { + if ( + node !== stmt && + (ts.isFunctionLike(node) || ts.isClassDeclaration(node) || ts.isClassExpression(node)) + ) + return "skip"; + if ( + ts.isBinaryExpression(node) && + node.operatorToken.kind === ts.SyntaxKind.EqualsToken && + !owned.has(node) && + ts.isPropertyAccessExpression(node.left) && + node.left.questionDotToken === undefined && + ts.isIdentifier(node.left.name) && + ((ts.isIdentifier(node.left.expression) && node.left.expression.text === "exports") || + isModuleExportsAccess(node.left.expression)) + ) { + out.push({ name: node.left.name, value: node.right }); + } + return undefined; + }); + return out; +} + +/** `const { A, B: b } = ns` at a module's top level, where `ns` is a + * CommonJS module binding over a table module (picomatch's `const { + * MAX_LENGTH, ... } = constants`): each name takes a snapshot of the named + * export's value at this statement, exactly like destructuring the exports + * object would. Null for every other declaration; the plain elements and + * their key names otherwise. */ +export function cjsNamespaceDestructureOf( + lowerer: Lowerer, + decl: ts.VariableDeclaration, +): { dep: ts.SourceFile; elements: { name: ts.Identifier; key: string }[] } | null { + if (!ts.isObjectBindingPattern(decl.name) || decl.initializer === undefined) return null; + const stmt = decl.parent?.parent; + if (stmt === undefined || !ts.isVariableStatement(stmt) || !ts.isSourceFile(stmt.parent)) + return null; + if (!isJsSourceFile(stmt.parent)) return null; + let init: ts.Expression = decl.initializer; + while (ts.isParenthesizedExpression(init)) init = init.expression; + if (!ts.isIdentifier(init) || !lowerer.cjsLocalModuleBindingOf(init)) return null; + const dep = lowerer.cjsModuleBindingDepOf(init); + if (dep === null) return null; + const elements: { name: ts.Identifier; key: string }[] = []; + for (const e of decl.name.elements) { + if (e.initializer !== undefined || e.dotDotDotToken !== undefined) return null; + if (e.name === undefined || !ts.isIdentifier(e.name)) return null; + const key = + e.propertyName === undefined + ? e.name.text + : ts.isIdentifier(e.propertyName) || ts.isStringLiteral(e.propertyName) + ? e.propertyName.text + : null; + if (key === null) return null; + elements.push({ name: e.name, key }); + } + return { dep, elements }; +} + +/** The value of `dep`'s export `key` read from another module: its export + * global, or the function/class declaration it aliases. Null when it has no + * static value. */ +export function cjsExportValueByName( + lowerer: Lowerer, + dep: ts.SourceFile, + key: string, + blame: ts.Node, +): IrExpr | null { + let sym = lowerer.cjsModuleExportSymbol(dep, key); + if (sym === undefined) return null; + if (sym.flags & ts.SymbolFlags.Alias) sym = lowerer.checker.getAliasedSymbol(sym); + const direct = lowerer.globalsBySymbol.get(sym); + if (direct) return { kind: "varRef", localId: direct.id, type: direct.type, loc: locOf(blame) }; + for (const d of lowerer.checker.declarationsOf(sym)) { + const byDecl = lowerer.globalsByDeclNode.get(d); + if (byDecl) return { kind: "varRef", localId: byDecl.id, type: byDecl.type, loc: locOf(blame) }; + // Alias plumbing: a shorthand/identifier table entry or a member + // export naming a declaration. Reading that identifier IS the value. + if (ts.isShorthandPropertyAssignment(d)) return lowerer.lowerShorthandValue(d); + if (ts.isPropertyAssignment(d) && ts.isIdentifier(d.initializer)) { + return lowerer.lowerExpr(d.initializer); + } + if ((ts.isFunctionDeclaration(d) || ts.isClassDeclaration(d)) && d.name !== undefined) { + return lowerer.lowerExpr(d.name); + } + } + return null; +} diff --git a/packages/compiler/src/frontend/lowering/cjs-tsc-interop.ts b/packages/compiler/src/frontend/lowering/cjs-tsc-interop.ts new file mode 100644 index 000000000..f7955fc23 --- /dev/null +++ b/packages/compiler/src/frontend/lowering/cjs-tsc-interop.ts @@ -0,0 +1,223 @@ +/* tsc's CommonJS import interop: `const x_1 = __importDefault(require("./m"))` + * and `const x_1 = __importStar(require("./m"))` at a module's top level, + * with the helpers tsc emits at the top of the file: + * + * var __importDefault = (this && this.__importDefault) || function (mod) { + * return (mod && mod.__esModule) ? mod : { "default": mod }; + * }; + * + * For a CommonJS dependency the helper's answer is fixed by the + * dependency's source: stamped with `__esModule` (tsc output), the binding + * IS the module's exports; otherwise `x_1.default` is the module's exports + * (and __importStar also copies every export onto x_1). Both are the + * static alias model a plain `const x_1 = require("./m")` already has, so + * the binding lowers as a require binding: the statement is the module's + * %init, `x_1.f` / `x_1.default.f` read the exports statically, and + * `x_1.default` over a single-value module is that value. The helper + * declarations themselves are dead once every call is such a binding (the + * self-probe `this.__importDefault` reads the pristine exports object, + * which never has the name), so they lower to nothing. */ +import * as ts from "../ts7/adapter.js"; +import type { Lowerer } from "./lowerer.js"; +import { + isCjsJsFile, + isEsModuleStamp, + npmStaticDepSf7, + requireSpecOf, + resolveImport, +} from "../program.js"; +import { cjsNamespaceModule } from "./cjs-inline-require.js"; + +const HELPERS = new Set([ + "__importDefault", + "__importStar", + "__createBinding", + "__setModuleDefault", +]); + +export interface TscInteropBinding { + helper: "__importDefault" | "__importStar"; + spec: string; + dep: ts.SourceFile; + /** The dependency stamps `__esModule`: the binding IS its exports. */ + stamped: boolean; +} + +/** `var = (this && this.) || ` at a module's top + * level: the tsc helper declaration shape. */ +function tscHelperDeclName(stmt: ts.Statement): string | null { + if (!ts.isVariableStatement(stmt)) return null; + const decls = stmt.declarationList.declarations; + if (decls.length !== 1) return null; + const d = decls[0]!; + if (!ts.isIdentifier(d.name) || !HELPERS.has(d.name.text) || d.initializer === undefined) + return null; + let init: ts.Expression = d.initializer; + while (ts.isParenthesizedExpression(init)) init = init.expression; + if (!ts.isBinaryExpression(init) || init.operatorToken.kind !== ts.SyntaxKind.BarBarToken) + return null; + let probe: ts.Expression = init.left; + while (ts.isParenthesizedExpression(probe)) probe = probe.expression; + if ( + !ts.isBinaryExpression(probe) || + probe.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken || + probe.left.kind !== ts.SyntaxKind.ThisKeyword || + !ts.isPropertyAccessExpression(probe.right) || + probe.right.expression.kind !== ts.SyntaxKind.ThisKeyword || + probe.right.name.text !== d.name.text + ) + return null; + // The fallback is the helper body: a function, or (newer tsc output) a + // conditional or IIFE producing one. It never runs when the helper is dead. + return d.name.text; +} + +/** True when the dependency stamps itself as an ES module translation. */ +function stampsEsModule(dep: ts.SourceFile): boolean { + return dep.statements.some((s) => { + if (!ts.isExpressionStatement(s)) return false; + if (isEsModuleStamp(s.expression)) return true; + const e = s.expression; + return ( + ts.isBinaryExpression(e) && + e.operatorToken.kind === ts.SyntaxKind.EqualsToken && + ts.isPropertyAccessExpression(e.left) && + ts.isIdentifier(e.left.expression) && + e.left.expression.text === "exports" && + e.left.name.text === "__esModule" && + e.right.kind === ts.SyntaxKind.TrueKeyword + ); + }); +} + +/** The interop binding a top-level `const x = __importDefault(require(s))` / + * `__importStar(require(s))` declaration makes, or null. The helper must be + * the module's own tsc helper declaration and the dependency a compiled + * CommonJS program module. */ +export function tscInteropBindingOfDecl( + lowerer: Lowerer, + decl: ts.VariableDeclaration, +): TscInteropBinding | null { + if (!ts.isIdentifier(decl.name) || decl.initializer === undefined) return null; + const stmt = decl.parent?.parent; + if (stmt === undefined || !ts.isVariableStatement(stmt) || !ts.isSourceFile(stmt.parent)) + return null; + const sf = stmt.parent; + if (!isCjsJsFile(sf, lowerer.program)) return null; + let init: ts.Expression = decl.initializer; + while (ts.isParenthesizedExpression(init)) init = init.expression; + if (!ts.isCallExpression(init) || init.arguments.length !== 1) return null; + const callee = init.expression; + if (!ts.isIdentifier(callee)) return null; + if (callee.text !== "__importDefault" && callee.text !== "__importStar") return null; + if (!sf.statements.some((s) => tscHelperDeclName(s) === callee.text)) return null; + const spec = requireSpecOf(init.arguments[0]!); + if (spec === null) return null; + const dep = + resolveImport(lowerer.program, sf, spec, "require") ?? + npmStaticDepSf7(lowerer.program, sf, spec, "require"); + if (!dep || dep.isDeclarationFile || !isCjsJsFile(dep, lowerer.program)) return null; + return { + helper: callee.text as TscInteropBinding["helper"], + spec, + dep, + stamped: stampsEsModule(dep), + }; +} + +/** The interop binding an identifier reads, or null. */ +export function tscInteropBindingOf( + lowerer: Lowerer, + expr: ts.Expression, +): TscInteropBinding | null { + if (!ts.isIdentifier(expr)) return null; + const sym = lowerer.checker.getSymbolAtLocation(expr); + const decl = sym ? lowerer.checker.declarationsOf(sym).find(ts.isVariableDeclaration) : undefined; + return decl ? tscInteropBindingOfDecl(lowerer, decl) : null; +} + +/** The module whose exports `expr` denotes through an interop binding: + * the binding itself when the dependency is stamped (or for __importStar, + * whose copy carries every export), and `binding.default` when it is not. + * Null for anything else. */ +export function tscInteropModuleOf( + lowerer: Lowerer, + expr: ts.Expression, +): TscInteropBinding | null { + let e = expr; + while (ts.isParenthesizedExpression(e)) e = e.expression; + const direct = tscInteropBindingOf(lowerer, e); + if (direct !== null) { + return direct.stamped || direct.helper === "__importStar" ? direct : null; + } + if (ts.isPropertyAccessExpression(e) && !e.questionDotToken && e.name.text === "default") { + const via = tscInteropBindingOf(lowerer, e.expression); + if (via !== null && !via.stamped) return via; + } + return null; +} + +/** `binding.default` over an unstamped single-value dependency: that value + * (the caller lowers the dependency's whole export). */ +export function tscInteropDefaultValueOf( + lowerer: Lowerer, + expr: ts.PropertyAccessExpression, +): TscInteropBinding | null { + if (expr.questionDotToken || expr.name.text !== "default") return null; + const via = tscInteropBindingOf(lowerer, expr.expression); + if (via === null || via.stamped) return null; + return cjsNamespaceModule(lowerer, via.dep) ? null : via; +} + +/** True for a tsc helper declaration every reference to which is a + * recognized interop binding's callee, its own self-probe, or a reference + * from another such dead helper: the statement lowers to nothing. */ +export function isDeadTscHelperDecl(lowerer: Lowerer, stmt: ts.Statement): boolean { + const name = tscHelperDeclName(stmt); + if (name === null) return false; + const sf = stmt.getSourceFile(); + const helperSpans = new Map(); + for (const s of sf.statements) { + const n = tscHelperDeclName(s); + if (n !== null) helperSpans.set(n, s); + } + const dead = new Set(); + for (let changed = true; changed;) { + changed = false; + for (const [helper, decl] of helperSpans) { + if (dead.has(helper)) continue; + let live = false; + ts.walkPreorder(sf, (node) => { + if (!ts.isIdentifier(node) || node.text !== helper) return undefined; + const parent = node.parent; + if (parent !== undefined && ts.isVariableDeclaration(parent) && parent.name === node) + return undefined; + const at = node.getStart(sf); + if (at >= decl.getStart(sf) && at < decl.getEnd()) return undefined; + for (const [other, otherDecl] of helperSpans) { + if (other !== helper && dead.has(other)) { + if (at >= otherDecl.getStart(sf) && at < otherDecl.getEnd()) return undefined; + } + } + const call = parent; + const binding = call?.parent; + if ( + call !== undefined && + ts.isCallExpression(call) && + call.expression === node && + binding !== undefined && + ts.isVariableDeclaration(binding) && + tscInteropBindingOfDecl(lowerer, binding) !== null + ) + return undefined; + live = true; + return "stop"; + }); + if (!live) { + dead.add(helper); + changed = true; + } + } + } + return dead.has(name); +} diff --git a/packages/compiler/src/frontend/lowering/containers/for-of.ts b/packages/compiler/src/frontend/lowering/containers/for-of.ts index 4aa24b0b3..6aa838dea 100644 --- a/packages/compiler/src/frontend/lowering/containers/for-of.ts +++ b/packages/compiler/src/frontend/lowering/containers/for-of.ts @@ -747,7 +747,7 @@ function lowerForOfMapOrSet( * Recurses through every nested statement list; nested functions are * lifted elsewhere and never appear here, so every return found exits * THIS function through the active iteration. */ -function exitBeforeReturns(stmts: IrStmt[], make: () => IrStmt): IrStmt[] { +export function exitBeforeReturns(stmts: IrStmt[], make: () => IrStmt): IrStmt[] { const walk = (list: IrStmt[]): IrStmt[] => list.flatMap((s): IrStmt[] => { switch (s.kind) { diff --git a/packages/compiler/src/frontend/lowering/containers/iterator-helpers.ts b/packages/compiler/src/frontend/lowering/containers/iterator-helpers.ts index f0928d2a1..7cb3753ac 100644 --- a/packages/compiler/src/frontend/lowering/containers/iterator-helpers.ts +++ b/packages/compiler/src/frontend/lowering/containers/iterator-helpers.ts @@ -4,7 +4,10 @@ import * as ts from "../../ts7/adapter.js"; import type { Lowerer } from "../lowerer.js"; import { BOOL, + CAUGHT, F64, + type IrMapIntrinsicMethod, + type IrSetIntrinsicMethod, type IrExpr, type IrFunction, type IrLocal, @@ -16,11 +19,22 @@ import { UNDEFINED_T, VOID, arrayOf, + isUnitType, typeEquals, } from "../../../ir/ir.js"; import { locOf } from "../../program.js"; -import { typeKey } from "../../type-mapper.js"; +import { genResultRecord, typeKey } from "../../type-mapper.js"; import { concatStrings, throwTypeError } from "./dynamic-receivers.js"; +import { + type GenType, + generatorLoopBinding, + genStep, + genValue, + stepDrivable, +} from "../lower-generators.js"; +import { exitBeforeReturns } from "./for-of.js"; +import { iteratorSlotAdapter } from "../iterator-adapters.js"; +import { lowerArrayCallback } from "./callback-arguments.js"; /* ── iterator helpers (ES2025) ─────────────────────────────────────────── */ @@ -37,9 +51,9 @@ import { concatStrings, throwTypeError } from "./dynamic-receivers.js"; * raw value in the message) through an interned checker call inserted * at the argument's evaluation position. The source array is iterated * LIVE by index against a re-read length, exactly the array iterator's - * contract. Everything else — iterator objects stored in bindings, - * generator/Set/Map receivers, Iterator.from — keeps the lib fences. - * Null when the callee isn't a terminal over such a chain. */ + * contract. Chains over generators and other iterator objects lower in + * lowerGeneratorHelperCall. Null when the callee isn't a terminal over + * such a chain. */ export function lowerIteratorHelperCall( lowerer: Lowerer, call: ts.CallExpression, @@ -51,7 +65,7 @@ export function lowerIteratorHelperCall( // Walk receiver: stage* ← values()/entries() ← array-typed source // (entries seeds the chain with [index, element] pairs — the // checker's own tuple type). - const stages: { name: string; argNode: ts.Expression }[] = []; + const stages: StageNode[] = []; let cur: ts.Expression = access.expression; let source: ts.Expression | null = null; let srcProj: "values" | "entries" = "values"; @@ -73,16 +87,14 @@ export function lowerIteratorHelperCall( ts.isSpreadElement(cur.arguments[0]!) ) return null; - stages.push({ name, argNode: cur.arguments[0]! }); + stages.push({ name, argNode: cur.arguments[0]!, access: cur.expression }); cur = cur.expression.expression; } stages.reverse(); // source order for (const s of stages) { - const acc = findStageAccess(call, s); - if (acc !== null && !lowerer.isStdlibMember(acc)) return null; + if (!lowerer.isStdlibMember(s.access)) return null; } if (!lowerer.isStdlibMember(access)) return null; - const loc = locOf(call); // Lower everything in SOURCE ORDER (the chain's own evaluation // order): the source array, each stage argument, the terminal's. const items = lowerer.lowerExpr(source); @@ -90,81 +102,502 @@ export function lowerIteratorHelperCall( // The entries() seed: the interned [number, T] tuple — the same shape // the checker's own [number, T] maps to, so stage callbacks typed // against the lib's pairs intern equal. - let elem: IrType = - srcProj === "entries" - ? { - kind: "record", - shapeId: lowerer.shapes.intern( - [ - { name: "0", type: F64 }, - { name: "1", type: items.type.elem }, - ], - true, - ), - } - : items.type.elem; - type StageIr = - | { - kind: "map" | "filter" | "flatMap"; - fn: IrExpr & { type: IrType & { kind: "func" } }; - out: IrType; - } - | { kind: "take" | "drop"; budget: IrExpr }; - const stageIrs: StageIr[] = []; - for (const s of stages) { - if (s.name === "take" || s.name === "drop") { - const n = lowerer.lowerExpr(s.argNode); - if (n.type.kind !== "f64") lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); - // Node validates at the take()/drop() call — the checked budget - // rides an interned helper call AT this argument position. - stageIrs.push({ + const elem: IrType = + srcProj === "entries" ? entryPairType(lowerer, items.type.elem) : items.type.elem; + return lowerFusedChain( + lowerer, + call, + terminal, + stages, + { kind: "array", type: items.type, proj: srcProj }, + items, + elem, + ); +} + +/** Iterator-helper calls whose receiver is an iterator object: a + * generator, a stored array iterator, a helper result (IteratorObject), + * an `Iterator` value, or a Map/Set iterator (adapted into a + * generator over the live collection). + * + * - A terminal (toArray/forEach/reduce/some/every/find) fuses the chain + * of helper stages before it into one loop over the source generator, + * with the helpers' pull order and closing: the source is closed (its + * `return()` runs) when take's budget is spent, a short-circuit + * terminal hits, or a callback throws, and is not closed when it is + * exhausted or its own `next()` throws. + * - A stage (map/filter/take/drop/flatMap) outside such a chain builds + * an iterator helper object: a generator over its source that pulls + * lazily, closes the source on early exit, and closes it on a + * `return()` before the first `next()` (`closesSource`). + * + * Budgets and callbacks validate at the call, as in Node. Null when the + * call is not such a helper call. */ +export function lowerGeneratorHelperCall( + lowerer: Lowerer, + call: ts.CallExpression, + access: ts.PropertyAccessExpression, +): IrExpr | null { + if (call.questionDotToken || access.questionDotToken) return null; + const name = access.name.text; + const isTerminal = ITER_TERMINALS.has(name); + if (!isTerminal && !ITER_STAGES.has(name)) return null; + if (!isHelperReceiver(lowerer, access.expression)) return null; + if (!lowerer.isStdlibMember(access)) return null; + const loc = locOf(call); + if (!isTerminal) { + const argNode = call.arguments[0]; + if (call.arguments.length !== 1 || argNode === undefined || ts.isSpreadElement(argNode)) { + lowerer.noLowering(`.${name} with ${call.arguments.length} arguments`, call); + } + const src = lowerHelperSource(lowerer, access.expression); + if (name !== "take" && name !== "drop") { + const { stage, out } = lowerStage(lowerer, { name, argNode, access }, src.elem, loc); + return lowerHelperObject(lowerer, call, src.gen, src.elem, stage, out, loc); + } + // The budget check closes the source, so the source is bound first. + const bound = bindSource(lowerer, src.gen, loc); + const { stage, out } = lowerStage(lowerer, { name, argNode, access }, src.elem, loc, bound.ref); + const helper = lowerHelperObject(lowerer, call, bound.ref, src.elem, stage, out, loc); + return { kind: "seqExpr", stmts: [bound.decl], result: helper, type: helper.type, loc }; + } + // The stages before the terminal, back to the first receiver that is + // not itself a helper stage. + const stages: StageNode[] = []; + let cur: ts.Expression = access.expression; + while (isStageCall(lowerer, cur)) { + const stageAccess = cur.expression as ts.PropertyAccessExpression; + stages.push({ name: stageAccess.name.text, argNode: cur.arguments[0]!, access: stageAccess }); + cur = stageAccess.expression; + } + stages.reverse(); // source order + // A chain from m.keys()/values()/entries() (or a Set's) walks the + // collection itself, live, as for-of does. + const collection = collectionIteratorCall(lowerer, cur); + if (collection !== null) { + const items = lowerer.lowerExpr(collection.receiver); + if (items.type.kind !== "map" && items.type.kind !== "set") + lowerer.badType(collection.receiver, lowerer.typeOf(collection.receiver)); + const source: ChainSource = { kind: "collection", type: items.type, proj: collection.proj }; + return lowerFusedChain( + lowerer, + call, + name, + stages, + source, + items, + collectionSeed(lowerer, source), + ); + } + const src = lowerHelperSource(lowerer, cur); + return lowerFusedChain( + lowerer, + call, + name, + stages, + { kind: "generator", type: src.gen.type, elem: src.elem }, + src.gen, + src.elem, + ); +} + +const ITER_STAGES = new Set(["map", "filter", "take", "drop", "flatMap"]); +const ITER_TERMINALS = new Set(["toArray", "forEach", "reduce", "some", "every", "find"]); +/** Native iterators that ride checked runtime values and adapt into + * generators for the helpers. */ +const ADAPTED_ITERATOR_TYPES = new Set(["MapIterator", "SetIterator"]); + +/** `for (x of )` where the head is a run of map/filter/take/drop + * stages over an array iterator, a Map or Set iterator, or a generator: + * one loop over the source with the stages nested in it and the loop body + * innermost, instead of a helper object per stage. The pull order and the + * closing are the helpers': `break`, `return` and throws from the body + * close a generator source (run its `return()`), and take closes it on + * the pass after its last delivery. Chains with flatMap keep the helper + * objects (a `break` there leaves an inner loop). Null when the head is + * not such a chain. */ +export function lowerForOfHelperChain( + lowerer: Lowerer, + stmt: ts.ForOfStatement, + labels: string[] | undefined, +): IrStmt | null { + if (stmt.awaitModifier) return null; + if ( + ts.isVariableDeclarationList(stmt.initializer) && + (stmt.initializer.flags & ts.NodeFlags.Using) !== 0 + ) + return null; + let head: ts.Expression = stmt.expression; + while (ts.isParenthesizedExpression(head)) head = head.expression; + const stages: StageNode[] = []; + let cur: ts.Expression = head; + while (isStageCall(lowerer, cur)) { + const stageAccess = cur.expression as ts.PropertyAccessExpression; + if (stageAccess.name.text === "flatMap") return null; + stages.push({ name: stageAccess.name.text, argNode: cur.arguments[0]!, access: stageAccess }); + cur = stageAccess.expression; + } + if (stages.length === 0) return null; + stages.reverse(); // source order + const arrayRoot = arrayIteratorCall(lowerer, cur); + const collection = arrayRoot === null ? collectionIteratorCall(lowerer, cur) : null; + if (arrayRoot === null && collection === null) { + const mapped = lowerer.mapTypeOf(lowerer.typeOf(cur)); + if (mapped?.kind !== "generator" || !stepDrivable(mapped)) return null; + } + const loc = locOf(stmt); + lowerer.scopes.push(new Map()); + try { + const frame = new HostFrame(lowerer, loc); + let items: IrExpr; + let source: ChainSource; + let elem: IrType; + if (arrayRoot !== null) { + items = lowerer.lowerExpr(arrayRoot.receiver); + if (items.type.kind !== "array") + lowerer.badType(arrayRoot.receiver, lowerer.typeOf(arrayRoot.receiver)); + source = { kind: "array", type: items.type, proj: arrayRoot.proj }; + elem = + arrayRoot.proj === "entries" ? entryPairType(lowerer, items.type.elem) : items.type.elem; + } else if (collection !== null) { + items = lowerer.lowerExpr(collection.receiver); + if (items.type.kind !== "map" && items.type.kind !== "set") + lowerer.badType(collection.receiver, lowerer.typeOf(collection.receiver)); + source = { kind: "collection", type: items.type, proj: collection.proj }; + elem = collectionSeed(lowerer, source); + } else { + const src = lowerHelperSource(lowerer, cur); + items = src.gen; + source = { kind: "generator", type: src.gen.type, elem: src.elem }; + elem = src.elem; + } + const itemsId = frame.local("items", items.type, false); + const out: IrStmt[] = [{ kind: "varDecl", localId: itemsId, init: items, loc }]; + // Stage arguments evaluate in chain order, before the first pull. + const slots: StageSlot[] = []; + for (const s of stages) { + const { stage, out: next } = lowerStage( + lowerer, + s, + elem, + loc, + source.kind === "generator" + ? (varRef(itemsId, source.type, loc) as IrExpr & { type: GenType }) + : null, + ); + const arg = "budget" in stage ? stage.budget : stage.fn; + const argId = frame.local("budget" in stage ? "n" : "f", arg.type, false); + out.push({ kind: "varDecl", localId: argId, init: arg, loc }); + slots.push(stageSlot(frame, stage, argId)); + elem = next; + } + const doneId = frame.local("done", BOOL, true); + out.push(...stagePrologue(slots, doneId, loc)); + // Each delivered value lands in a hidden local the loop binding reads. + const valueId = frame.local("hv", elem, false); + const binds = generatorLoopBinding(lowerer, stmt, varRef(valueId, elem, loc), elem); + let body = lowerer.inCtl( + "loop", + () => lowerer.lowerScopedBlock(stmt.statement), + source.kind === "collection" ? undefined : labels, + ); + if (source.kind === "collection") { + // A return from the body ends the live walk first, as for-of does. + const t = source.type; + body = exitBeforeReturns(body, () => ({ + kind: "exprStmt", + expr: + t.kind === "map" + ? { + kind: "mapIntrinsic", + method: "iterExit", + receiver: varRef(itemsId, t, loc), + args: [], + type: VOID, + loc, + } + : { + kind: "setIntrinsic", + method: "iterExit", + receiver: varRef(itemsId, t, loc), + args: [], + type: VOID, + loc, + }, + loc, + })); + } + const emit = foldStages( + lowerer, + frame, + slots, + (value) => [{ kind: "varDecl", localId: valueId, init: value, loc }, ...binds, ...body], + doneId, + loc, + ); + out.push( + ...sourceLoop( + lowerer, + frame, + itemsId, + source, + doneId, + emit, + loc, + source.kind === "collection" ? undefined : labels, + ), + ); + return { kind: "block", body: out, loc }; + } finally { + lowerer.scopes.pop(); + } +} + +/** `arr.values()` or `arr.entries()` on an array value, as the root of a + * helper chain. */ +function arrayIteratorCall( + lowerer: Lowerer, + expr: ts.Expression, +): { receiver: ts.Expression; proj: "values" | "entries" } | null { + if (!ts.isCallExpression(expr) || !ts.isPropertyAccessExpression(expr.expression)) return null; + if (expr.questionDotToken || expr.expression.questionDotToken || expr.arguments.length !== 0) + return null; + const proj = expr.expression.name.text; + if (proj !== "values" && proj !== "entries") return null; + if (lowerer.mapTypeOf(lowerer.typeOf(expr.expression.expression))?.kind !== "array") return null; + if (!lowerer.isStdlibMember(expr.expression)) return null; + return { receiver: expr.expression.expression, proj }; +} + +/** One helper stage call in a chain, in source order. */ +interface StageNode { + name: string; + argNode: ts.Expression; + access: ts.PropertyAccessExpression; +} + +/** A lowered stage: its callback, or its validated budget. */ +type StageIr = + | { + kind: "map" | "filter" | "flatMap"; + fn: IrExpr & { type: IrType & { kind: "func" } }; + } + | { kind: "take" | "drop"; budget: IrExpr }; + +/** Where a fused chain's elements come from: a live array (by index), or + * a synchronous generator driven like for-of. */ +type ChainSource = + | { kind: "array"; type: IrType & { kind: "array" }; proj: "values" | "entries" } + | { kind: "generator"; type: GenType; elem: IrType } + | { + kind: "collection"; + type: (IrType & { kind: "map" }) | (IrType & { kind: "set" }); + proj: "keys" | "values" | "entries"; + }; + +/** `m.keys()`, `m.values()` or `m.entries()` (or a Set's) on a Map or + * Set value, as the root of a helper chain. */ +function collectionIteratorCall( + lowerer: Lowerer, + expr: ts.Expression, +): { receiver: ts.Expression; proj: "keys" | "values" | "entries" } | null { + if (!ts.isCallExpression(expr) || !ts.isPropertyAccessExpression(expr.expression)) return null; + if (expr.questionDotToken || expr.expression.questionDotToken || expr.arguments.length !== 0) + return null; + const proj = expr.expression.name.text; + if (proj !== "keys" && proj !== "values" && proj !== "entries") return null; + const kind = lowerer.mapTypeOf(lowerer.typeOf(expr.expression.expression))?.kind; + if (kind !== "map" && kind !== "set") return null; + if (!lowerer.isStdlibMember(expr.expression)) return null; + return { receiver: expr.expression.expression, proj }; +} + +/** The element a collection chain starts from: a key (a Set's element), + * a Map's value, or the interned [key, value] pair (a Set's [v, v]). */ +function collectionSeed(lowerer: Lowerer, source: ChainSource & { kind: "collection" }): IrType { + const t = source.type; + const keyT = t.kind === "map" ? t.key : t.elem; + if (source.proj === "keys" || (t.kind === "set" && source.proj === "values")) return keyT; + if (source.proj === "values") return (t as IrType & { kind: "map" }).value; + return { + kind: "record", + shapeId: lowerer.shapes.intern( + [ + { name: "0", type: keyT }, + { name: "1", type: t.kind === "map" ? t.value : keyT }, + ], + true, + ), + }; +} + +/** The interned [number, T] pair an array's entries() yields. */ +function entryPairType(lowerer: Lowerer, elem: IrType): IrType { + return { + kind: "record", + shapeId: lowerer.shapes.intern( + [ + { name: "0", type: F64 }, + { name: "1", type: elem }, + ], + true, + ), + }; +} + +/** Whether `expr` is an iterator object the helpers lower over: a + * synchronous generator-typed value, or a Map/Set iterator. */ +function isHelperReceiver(lowerer: Lowerer, expr: ts.Expression): boolean { + const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr)); + if (mapped?.kind === "generator") return mapped.async !== true; + const symbol = lowerer.typeOf(expr).getSymbol(); + return ( + mapped?.kind === "dyn" && + symbol !== undefined && + ADAPTED_ITERATOR_TYPES.has(symbol.name) && + lowerer.isStdlibSymbol(symbol) + ); +} + +/** Whether `expr` is a stage call (`src.map(f)`) on a helper receiver. */ +function isStageCall(lowerer: Lowerer, expr: ts.Expression): expr is ts.CallExpression { + if (!ts.isCallExpression(expr) || !ts.isPropertyAccessExpression(expr.expression)) return false; + if (expr.questionDotToken || expr.expression.questionDotToken) return false; + if (!ITER_STAGES.has(expr.expression.name.text)) return false; + if (expr.arguments.length !== 1 || ts.isSpreadElement(expr.arguments[0]!)) return false; + return ( + isHelperReceiver(lowerer, expr.expression.expression) && lowerer.isStdlibMember(expr.expression) + ); +} + +/** The source of a helper call as a synchronous generator — the receiver + * itself, or a Map/Set iterator adapted into a generator over the live + * collection — and its element type. A generator whose yield channel is + * checked-dynamic beside a declared element type (`Generator

` boxes a + * record yield next to its `any` return channel) has each value converted + * to the declared type as it is pulled. */ +function lowerHelperSource( + lowerer: Lowerer, + expr: ts.Expression, +): { gen: IrExpr & { type: GenType }; elem: IrType } { + const tsType = lowerer.typeOf(expr); + const mapped = lowerer.mapTypeOf(tsType); + const arg = lowerer.checker.getTypeArguments(tsType as ts.TypeReference)[0]; + if (mapped?.kind === "generator") { + const gen = lowerer.lowerExpr(expr); + if (gen.type.kind !== "generator" || gen.type.async) lowerer.badType(expr, tsType); + const genT = gen.type; + const declared = genT.yieldT.kind === "dyn" && arg ? lowerer.mapTypeOf(arg) : null; + const elem = + declared !== null && + declared.kind !== "dyn" && + declared.kind !== "void" && + !isUnitType(declared) + ? declared + : genT.yieldT; + return { gen: gen as IrExpr & { type: GenType }, elem }; + } + const yieldT = arg ? lowerer.mapTypeOf(arg) : null; + if ( + !yieldT || + yieldT.kind === "void" || + !genResultRecord(yieldT, VOID, lowerer.shapes, lowerer.unions) + ) + lowerer.badType(expr, tsType); + const target: GenType = { kind: "generator", yieldT, retT: VOID, nextT: UNDEFINED_T }; + const adapted = iteratorSlotAdapter(lowerer, lowerer.lowerExpr(expr), target); + if (adapted === null || adapted.type.kind !== "generator") lowerer.badType(expr, tsType); + return { gen: adapted as IrExpr & { type: GenType }, elem: yieldT }; +} + +/** Lower one stage's argument against its input element type: the + * callback (value) or (value, counter), or the take/drop budget with + * Node's eager RangeError check at the argument's position. `out` is + * the stage's output element type. */ +function lowerStage( + lowerer: Lowerer, + s: StageNode, + elem: IrType, + loc: SrcLoc, + source: (IrExpr & { type: GenType }) | null = null, +): { stage: StageIr; out: IrType } { + if (s.name === "take" || s.name === "drop") { + const n = lowerer.lowerExpr(s.argNode); + if (n.type.kind !== "f64") lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); + // Node validates at the take()/drop() call — the checked budget + // rides an interned helper call AT this argument position. A + // generator source is closed before the RangeError, as Node closes + // the iterator the helper was called on. + return { + stage: { kind: s.name, budget: { kind: "call", - callee: internBudgetChecker(lowerer, loc), - args: [n], + callee: internBudgetChecker(lowerer, loc, source?.type ?? null), + args: source === null ? [n] : [n, source], type: F64, loc, }, - }); - continue; - } - const f = lowerer.lowerExpr(s.argNode); - if ( - f.type.kind !== "func" || - f.type.params.length > 2 || - (f.type.params.length >= 1 && !typeEquals(f.type.params[0]!, elem)) || - (f.type.params.length === 2 && f.type.params[1]!.kind !== "f64") - ) { - lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); - } - const fn = f as IrExpr & { type: IrType & { kind: "func" } }; - if (s.name === "map") { - stageIrs.push({ kind: "map", fn, out: fn.type.ret }); - elem = fn.type.ret; - } else if (s.name === "filter") { - if (fn.type.ret.kind !== "bool") lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); - stageIrs.push({ kind: "filter", fn, out: elem }); - } else { - if (fn.type.ret.kind !== "array") { - lowerer.noLowering( - `.flatMap over a callback returning '${lowerer.fmt(fn.type.ret)}'`, - s.argNode, - "an array-returning callback is the supported form (iterators/strings have no lowering here)", - ); - } - stageIrs.push({ kind: "flatMap", fn, out: fn.type.ret.elem }); - elem = fn.type.ret.elem; - } + }, + out: elem, + }; } - // The terminal's own arguments. + // A flatMap callback returns its own array or generator type (an + // unannotated JavaScript arrow would otherwise return checked values). + let expectedReturn: IrType | undefined; + if (s.name === "flatMap") { + const sig = lowerer.checker.getCallSignatures(lowerer.typeOf(s.argNode))[0]; + const ret = sig ? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(sig)) : null; + if (ret?.kind === "array" || ret?.kind === "generator") expectedReturn = ret; + } + // Unannotated JavaScript parameters bind the element type. + const f = lowerArrayCallback( + lowerer, + s.argNode, + [elem], + UNDEFINED_T, + false, + expectedReturn, + ).fnArg; + if ( + f.type.kind !== "func" || + f.type.params.length > 2 || + (f.type.params.length >= 1 && !typeEquals(f.type.params[0]!, elem)) || + (f.type.params.length === 2 && f.type.params[1]!.kind !== "f64") + ) { + lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); + } + const fn = f as IrExpr & { type: IrType & { kind: "func" } }; + if (s.name === "map") return { stage: { kind: "map", fn }, out: fn.type.ret }; + if (s.name === "filter") { + if (fn.type.ret.kind !== "bool") lowerer.badType(s.argNode, lowerer.typeOf(s.argNode)); + return { stage: { kind: "filter", fn }, out: elem }; + } + const ret = fn.type.ret; + if (ret.kind === "array") return { stage: { kind: "flatMap", fn }, out: ret.elem }; + if (ret.kind === "generator" && ret.async !== true && stepDrivable(ret)) + return { stage: { kind: "flatMap", fn }, out: ret.yieldT }; + lowerer.noLowering( + `.flatMap over a callback returning '${lowerer.fmt(ret)}'`, + s.argNode, + "callbacks returning an array or a generator are the supported forms", + ); +} + +/** The terminal's arguments and result type over elements of `elem`. */ +function lowerTerminal( + lowerer: Lowerer, + call: ts.CallExpression, + terminal: string, + elem: IrType, +): { termArgs: IrExpr[]; resultT: IrType } { const termArgs: IrExpr[] = []; - let resultT: IrType; if (terminal === "toArray") { if (call.arguments.length !== 0) lowerer.noLowering(`.toArray with ${call.arguments.length} arguments`, call); - resultT = arrayOf(elem); - } else if ( + return { termArgs, resultT: arrayOf(elem) }; + } + if ( terminal === "forEach" || terminal === "some" || terminal === "every" || @@ -174,7 +607,7 @@ export function lowerIteratorHelperCall( if (call.arguments.length !== 1 || argNode === undefined || ts.isSpreadElement(argNode)) { lowerer.noLowering(`.${terminal} with ${call.arguments.length} arguments`, call); } - const f = lowerer.lowerExpr(argNode); + const f = lowerArrayCallback(lowerer, argNode, [elem], UNDEFINED_T).fnArg; if ( f.type.kind !== "func" || f.type.params.length > 2 || @@ -185,43 +618,84 @@ export function lowerIteratorHelperCall( lowerer.badType(argNode, lowerer.typeOf(argNode)); } termArgs.push(f); - resultT = - terminal === "forEach" ? VOID : terminal === "find" ? lowerer.withUndefinedArm(elem) : BOOL; - } else { - // reduce(f[, initial]) - const fNode = call.arguments[0]; - if ( - call.arguments.length < 1 || - call.arguments.length > 2 || - fNode === undefined || - call.arguments.some((a) => ts.isSpreadElement(a)) - ) { - lowerer.noLowering(`.reduce with ${call.arguments.length} arguments`, call); - } - const f = lowerer.lowerExpr(fNode); - if ( - f.type.kind !== "func" || - f.type.params.length < 2 || - f.type.params.length > 3 || - !typeEquals(f.type.params[1]!, elem) || - (f.type.params.length === 3 && f.type.params[2]!.kind !== "f64") || - !typeEquals(f.type.params[0]!, f.type.ret) - ) { - lowerer.badType(fNode, lowerer.typeOf(fNode)); - } - const accT = (f.type as IrType & { kind: "func" }).ret; - if (call.arguments.length === 1 && !typeEquals(accT, elem)) { - lowerer.noLowering( - ".reduce without an initial value where the accumulator's type differs from the elements'", - call, - "pass the initial value: .reduce(f, init)", - ); - } - termArgs.push(f); - if (call.arguments[1] !== undefined) - termArgs.push(lowerer.lowerExprExpecting(call.arguments[1], accT)); - resultT = accT; + return { + termArgs, + resultT: + terminal === "forEach" ? VOID : terminal === "find" ? lowerer.withUndefinedArm(elem) : BOOL, + }; } + // reduce(f[, initial]) + const fNode = call.arguments[0]; + if ( + call.arguments.length < 1 || + call.arguments.length > 2 || + fNode === undefined || + call.arguments.some((a) => ts.isSpreadElement(a)) + ) { + lowerer.noLowering(`.reduce with ${call.arguments.length} arguments`, call); + } + // The accumulator binds the checker's result type. + const accLead = lowerer.mapTypeOf(lowerer.typeOf(call)) ?? elem; + const f = lowerArrayCallback(lowerer, fNode, [accLead, elem], UNDEFINED_T).fnArg; + if ( + f.type.kind !== "func" || + f.type.params.length < 2 || + f.type.params.length > 3 || + !typeEquals(f.type.params[1]!, elem) || + (f.type.params.length === 3 && f.type.params[2]!.kind !== "f64") || + !typeEquals(f.type.params[0]!, f.type.ret) + ) { + lowerer.badType(fNode, lowerer.typeOf(fNode)); + } + const accT = (f.type as IrType & { kind: "func" }).ret; + if (call.arguments.length === 1 && !typeEquals(accT, elem)) { + lowerer.noLowering( + ".reduce without an initial value where the accumulator's type differs from the elements'", + call, + "pass the initial value: .reduce(f, init)", + ); + } + termArgs.push(f); + if (call.arguments[1] !== undefined) + termArgs.push(lowerer.lowerExprExpecting(call.arguments[1], accT)); + return { termArgs, resultT: accT }; +} + +/** A terminal over a chain of stages from `source`: one interned fused + * function, called with the source, each stage's budget or callback and + * the terminal's arguments (lowered in that, the chain's own, order). */ +function lowerFusedChain( + lowerer: Lowerer, + call: ts.CallExpression, + terminal: string, + stages: StageNode[], + source: ChainSource, + items: IrExpr, + seed: IrType, +): IrExpr { + const loc = locOf(call); + if (source.kind === "generator" && !stepDrivable(source.type)) { + lowerer.noLowering( + `.${terminal} over an iterator yielding '${lowerer.fmt(source.type.yieldT)}'`, + call, + "helpers over iterators of numbers, booleans, strings, arrays, records and class instances are the supported forms", + ); + } + // A take/drop budget check closes a generator source, so the source is + // bound before the stage arguments. + const bound = + source.kind === "generator" && stages.some((s) => s.name === "take" || s.name === "drop") + ? bindSource(lowerer, items as IrExpr & { type: GenType }, loc) + : null; + if (bound !== null) items = bound.ref; + let elem = seed; + const stageIrs: StageIr[] = []; + for (const s of stages) { + const lowered = lowerStage(lowerer, s, elem, loc, bound?.ref ?? null); + stageIrs.push(lowered.stage); + elem = lowered.out; + } + const { termArgs, resultT } = lowerTerminal(lowerer, call, terminal, elem); // The checker's own result type must agree (annotation drift fences). const checkerT = lowerer.mapTypeOf(lowerer.typeOf(call)); if (terminal !== "forEach" && (checkerT === null || !typeEquals(checkerT, resultT))) { @@ -231,11 +705,14 @@ export function lowerIteratorHelperCall( "the chain's element and result types must be representable — annotate the callbacks' types", ); } - const stageKeys = stageIrs.map((s) => { - if (!s) throw new InternalCompilerError("missing iterator stage"); - return "budget" in s ? s.kind : `${s.kind}:${typeKey(s.fn.type)}`; - }); - const key = `iter:${srcProj}:${typeKey(items.type)}:${stageKeys.join(",")}:${terminal}:${termArgs.map((a) => typeKey(a.type)).join(",")}`; + const stageKeys = stageIrs.map((s) => + "budget" in s ? s.kind : `${s.kind}:${typeKey(s.fn.type)}`, + ); + const srcKey = + source.kind === "generator" + ? `${typeKey(source.type)}:${typeKey(source.elem)}` + : `${source.proj}:${typeKey(source.type)}`; + const key = `iter:${srcKey}:${stageKeys.join(",")}:${terminal}:${termArgs.map((a) => typeKey(a.type)).join(",")}`; let helper = lowerer.arrHofHelpers.get(key); if (!helper) { helper = `%iter.${terminal}.${lowerer.arrHofHelpers.size}`; @@ -244,8 +721,7 @@ export function lowerIteratorHelperCall( buildIterChainFn( lowerer, helper, - items.type, - srcProj, + source, stageIrs, terminal, termArgs.map((a) => a.type), @@ -254,35 +730,67 @@ export function lowerIteratorHelperCall( ), ); } - const budgetOrFn = stageIrs.map((s): IrExpr => { - if (!s) throw new InternalCompilerError("missing iterator stage"); - return "budget" in s ? s.budget : s.fn; - }); - return { + const budgetOrFn = stageIrs.map((s): IrExpr => ("budget" in s ? s.budget : s.fn)); + const fused: IrExpr = { kind: "call", callee: helper, args: [items, ...budgetOrFn, ...termArgs], type: resultT, loc, }; + return bound === null + ? fused + : { kind: "seqExpr", stmts: [bound.decl], result: fused, type: resultT, loc }; } -const ITER_STAGES = new Set(["map", "filter", "take", "drop", "flatMap"]); -const ITER_TERMINALS = new Set(["toArray", "forEach", "reduce", "some", "every", "find"]); - -/** The ts.PropertyAccessExpression of stage `s` inside the chain under - * `call` — for the stdlib-membership check. Walks the same spine the - * parser walked; null only on shape drift (checked defensively). */ -function findStageAccess( +/** An iterator helper object for one stage over `src`: an interned + * generator `%iter..N(src, f | n)` typed as the call's checker + * type (IteratorObject). */ +function lowerHelperObject( + lowerer: Lowerer, call: ts.CallExpression, - s: { name: string; argNode: ts.Expression }, -): ts.PropertyAccessExpression | null { - let cur: ts.Expression = (call.expression as ts.PropertyAccessExpression).expression; - while (ts.isCallExpression(cur) && ts.isPropertyAccessExpression(cur.expression)) { - if (cur.arguments[0] === s.argNode) return cur.expression; - cur = cur.expression.expression; + src: IrExpr & { type: GenType }, + srcElem: IrType, + stage: StageIr, + out: IrType, + loc: SrcLoc, +): IrExpr { + const outT = lowerer.mapTypeOf(lowerer.typeOf(call)); + const resultType = + outT?.kind === "generator" + ? genResultRecord(outT.yieldT, outT.retT, lowerer.shapes, lowerer.unions) + : null; + if ( + outT?.kind !== "generator" || + outT.async === true || + !typeEquals(outT.yieldT, out) || + outT.retT.kind !== "void" || + resultType === null + ) { + lowerer.noLowering( + `.${stage.kind} at this result type`, + call, + "the helper's element type must be representable — annotate the callback's types", + ); } - return null; + if (!stepDrivable(src.type)) { + lowerer.noLowering( + `.${stage.kind} over an iterator yielding '${lowerer.fmt(src.type.yieldT)}'`, + call, + "helpers over iterators of numbers, booleans, strings, arrays, records and class instances are the supported forms", + ); + } + const arg = "budget" in stage ? stage.budget : stage.fn; + const key = `iterHelper:${stage.kind}:${typeKey(src.type)}:${typeKey(srcElem)}:${typeKey(arg.type)}:${typeKey(outT)}`; + let name = lowerer.arrHofHelpers.get(key); + if (!name) { + name = `%iter.${stage.kind}.${lowerer.arrHofHelpers.size}`; + lowerer.arrHofHelpers.set(key, name); + lowerer.liftedFns.push( + buildHelperGenFn(lowerer, name, src.type, srcElem, stage, arg.type, outT, resultType, loc), + ); + } + return { kind: "call", callee: name, args: [src, arg], type: outT, loc }; } /** The eager take/drop budget check, interned once per program: @@ -292,11 +800,11 @@ function findStageAccess( * Node's exact behavior: NaN and negative INTEGER budgets throw (the * message carries the RAW argument — take(-1.5) says "-1.5"), -0.5 * truncates to 0 and passes, Infinity passes through. */ -function internBudgetChecker(lowerer: Lowerer, loc: SrcLoc): string { - const key = "iter:budget"; +function internBudgetChecker(lowerer: Lowerer, loc: SrcLoc, srcT: GenType | null): string { + const key = srcT === null ? "iter:budget" : `iter:budget:close:${typeKey(srcT)}`; let name = lowerer.arrHofHelpers.get(key); if (name !== undefined) return name; - name = "%iter.budget"; + name = srcT === null ? "%iter.budget" : `%iter.budget.close.${lowerer.arrHofHelpers.size}`; lowerer.arrHofHelpers.set(key, name); const v = (): IrExpr => ({ kind: "varRef", localId: "v.0", type: F64, loc }); @@ -351,13 +859,52 @@ function internBudgetChecker(lowerer: Lowerer, loc: SrcLoc): string { }, loc, }; + // The source closes first; an error from its return() is dropped, so + // the RangeError is what propagates. + const closeSource: IrStmt[] = + srcT === null + ? [] + : [ + { + kind: "tryCatch", + tryBody: [ + { + kind: "exprStmt", + expr: { + kind: "genResume", + mode: "close", + gen: varRef("src.0", srcT, loc), + arg: null, + type: VOID, + loc, + }, + loc, + }, + ], + catchBody: [], + catchLocalId: "exc.0", + finallyBody: null, + loc, + }, + ]; lowerer.liftedFns.push({ name, - params: [{ localId: "v.0", name: "v", type: F64 }], + params: [ + { localId: "v.0", name: "v", type: F64 }, + ...(srcT === null ? [] : [{ localId: "src.0", name: "src", type: srcT }]), + ], returnType: F64, - locals: [{ id: "v.0", name: "v", type: F64, mutable: true }], + locals: [ + { id: "v.0", name: "v", type: F64, mutable: true }, + ...(srcT === null + ? [] + : [ + { id: "src.0", name: "src", type: srcT, mutable: false }, + { id: "exc.0", name: "exc", type: CAUGHT, mutable: false }, + ]), + ], body: [ - { kind: "if", cond: bad, then: [throwStmt], else_: null, loc }, + { kind: "if", cond: bad, then: [...closeSource, throwStmt], else_: null, loc }, { kind: "return", value: t(), loc }, ], loc, @@ -365,97 +912,30 @@ function internBudgetChecker(lowerer: Lowerer, loc: SrcLoc): string { return name; } -/** The fused chain body. One loop over the LIVE source (length re-read - * per pass), a `done` flag every loop condition carries (take closing - * the pipeline, short-circuit terminals), stage code nested inside in - * source order, flatMap as an inner loop over its returned array. - * Pre-loop, a zero take budget marks done immediately — Node pulls - * nothing at all through a take(0). */ -function buildIterChainFn( +/** A hidden local holding `gen`, and its declaration. */ +function bindSource( lowerer: Lowerer, - name: string, - itemsT: IrType & { kind: "array" }, - srcProj: "values" | "entries", - stages: { kind: string; fn?: IrExpr & { type: IrType & { kind: "func" } } }[], - terminal: string, - termArgTs: IrType[], - resultT: IrType, + gen: IrExpr & { type: GenType }, loc: SrcLoc, -): IrFunction { - const locals: IrLocal[] = [{ id: "items.0", name: "items", type: itemsT, mutable: true }]; - const params: IrParam[] = [{ localId: "items.0", name: "items", type: itemsT }]; - let n = 0; - const addLocal = (base: string, type: IrType, mutable: boolean): string => { - const id = `${base}.${n++}`; - locals.push({ id, name: base, type, mutable }); - return id; +): { ref: IrExpr & { type: GenType }; decl: IrStmt } { + const local = lowerer.declareHiddenLocal("%helperSource", gen.type); + return { + ref: varRef(local.id, gen.type, loc) as IrExpr & { type: GenType }, + decl: { kind: "varDecl", localId: local.id, init: gen, loc }, }; - const addParam = (base: string, type: IrType): string => { - const id = `${base}.${n++}`; - locals.push({ id, name: base, type, mutable: true }); - params.push({ localId: id, name: base, type }); - return id; - }; - const doneId = addLocal("done", BOOL, true); - const done = (): IrExpr => varRef(doneId, BOOL, loc); - const setDone: IrStmt = { kind: "assign", localId: doneId, value: boolLit(true, loc), loc }; - // Parameters in call order: per-stage budget/callback, then terminal's. - interface StageSlot { - kind: string; - paramId: string; - fnT?: (IrType & { kind: "func" }) | undefined; - cntId?: string | undefined; - elem: IrType; - } - // The entries() seed builds each pass's [index, element] pair — the - // same interned tuple the caller computed its stage types against. - const seedT: IrType = - srcProj === "entries" - ? { - kind: "record", - shapeId: lowerer.shapes.intern( - [ - { name: "0", type: F64 }, - { name: "1", type: itemsT.elem }, - ], - true, - ), - } - : itemsT.elem; - let elem: IrType = seedT; - const slots: StageSlot[] = []; - for (const s of stages) { - if (s.kind === "take" || s.kind === "drop") { - const paramId = addParam("n", F64); - const cntId = addLocal(s.kind === "take" ? "taken" : "dropped", F64, true); - slots.push({ kind: s.kind, paramId, cntId, elem }); - continue; - } - const fnT = s.fn!.type; - const paramId = addParam("f", fnT); - const cntId = fnT.params.length === 2 ? addLocal("c", F64, true) : undefined; - const out = - s.kind === "map" - ? fnT.ret - : s.kind === "flatMap" - ? (fnT.ret as IrType & { kind: "array" }).elem - : elem; - slots.push({ kind: s.kind, paramId, fnT, cntId, elem: out }); - elem = out; - } - const termIds = termArgTs.map((t, i) => addParam(i === 0 ? "tf" : "init", t)); - const termFnT = - termArgTs[0]?.kind === "func" ? (termArgTs[0] as IrType & { kind: "func" }) : null; - const termCntId = - (terminal === "reduce" && termFnT !== null && termFnT.params.length === 3) || - (terminal !== "reduce" && - terminal !== "toArray" && - termFnT !== null && - termFnT.params.length === 2) || - terminal === "reduce" - ? addLocal("k", F64, true) - : undefined; - const bump = (id: string): IrStmt => ({ +} + +/** Where chain code allocates its locals: a lifted helper function's own + * frame, or hidden locals of the function being lowered (a fused for-of). */ +interface ChainFrame { + local(base: string, type: IrType, mutable: boolean): string; + /** `id = id + 1` over a number local. */ + bump(id: string): IrStmt; +} + +/** `id = id + 1` over a number local. */ +function bumpLocal(id: string, loc: SrcLoc): IrStmt { + return { kind: "assign", localId: id, value: { @@ -467,18 +947,633 @@ function buildIterChainFn( loc, }, loc, - }); - const callWith = ( - fnT: IrType & { kind: "func" }, - fnId: string, - value: IrExpr, - cntId: string | undefined, - ): IrExpr => { - const args: IrExpr[] = []; - if (fnT.params.length >= 1) args.push(value); - if (cntId !== undefined && fnT.params.length >= 2) args.push(varRef(cntId, F64, loc)); - return { kind: "callValue", callee: varRef(fnId, fnT, loc), args, type: fnT.ret, loc }; }; +} + +/** Hidden locals of the function being lowered. */ +class HostFrame implements ChainFrame { + constructor( + private readonly lowerer: Lowerer, + private readonly loc: SrcLoc, + ) {} + local(base: string, type: IrType, mutable: boolean): string { + const local = this.lowerer.declareHiddenLocal(`%${base}`, type); + local.mutable = mutable; + return local.id; + } + bump(id: string): IrStmt { + return bumpLocal(id, this.loc); + } +} + +/** The locals and parameters of a lifted helper function under + * construction. */ +class LiftedFrame implements ChainFrame { + readonly locals: IrLocal[] = []; + readonly params: IrParam[] = []; + private n = 0; + constructor(private readonly loc: SrcLoc) {} + local(base: string, type: IrType, mutable: boolean): string { + const id = `${base}.${this.n++}`; + this.locals.push({ id, name: base, type, mutable }); + return id; + } + param(base: string, type: IrType): string { + const id = `${base}.${this.n++}`; + this.locals.push({ id, name: base, type, mutable: true }); + this.params.push({ localId: id, name: base, type }); + return id; + } + bump(id: string): IrStmt { + return bumpLocal(id, this.loc); + } +} + +/** Statements that drive the synchronous generator in local `genId` the + * way for-of does. Each pass runs `pre` (which may `break`), steps the + * generator, binds the yielded value and runs `body` over it (`continue` + * moves to the next pass). Leaving the loop while the generator is + * unfinished closes it: a `break` in `pre` or `body`, a throw from the + * body, or a `return()` at a yield inside it. Exhaustion and a throwing + * step leave it unclosed, as in Node. The generator counts as unfinished + * before the first step, so a `pre` that breaks at once (take(0)) closes + * a source it never pulled. `genT` must be stepDrivable. */ +function driveGenerator( + lowerer: Lowerer, + frame: ChainFrame, + genId: string, + genT: GenType, + elemT: IrType, + pre: IrStmt[], + body: (value: IrExpr) => IrStmt[], + loc: SrcLoc, + labels?: string[], +): IrStmt[] { + const g = (): IrExpr & { type: GenType } => + varRef(genId, genT, loc) as IrExpr & { type: GenType }; + const openId = frame.local("open", BOOL, true); + const setOpen = (value: boolean): IrStmt => ({ + kind: "assign", + localId: openId, + value: boolLit(value, loc), + loc, + }); + const vId = frame.local("gv", genT.yieldT, false); + // A checked-dynamic yield converts once into the element type. + const converted = typeEquals(elemT, genT.yieldT) + ? null + : lowerer.coerceToExpected(varRef(vId, genT.yieldT, loc), elemT); + if (converted !== null && !typeEquals(converted.type, elemT)) + throw new InternalCompilerError("lowerer bug: helper source element has no conversion"); + const eId = converted === null ? vId : frame.local("ev", elemT, false); + return [ + { kind: "varDecl", localId: openId, init: boolLit(true, loc), loc }, + { + kind: "tryCatch", + tryBody: [ + { + kind: "while", + cond: boolLit(true, loc), + body: [ + ...pre, + setOpen(false), + { + kind: "if", + cond: genStep(g(), loc), + then: [{ kind: "break", loc }], + else_: null, + loc, + }, + setOpen(true), + { kind: "varDecl", localId: vId, init: genValue(g(), loc), loc }, + ...(converted === null + ? [] + : [{ kind: "varDecl" as const, localId: eId, init: converted, loc }]), + ...body(varRef(eId, elemT, loc)), + ], + ...(labels && { labels }), + loc, + }, + ], + catchBody: null, + catchLocalId: null, + // After a throw, an error from closing the source is dropped. + dropFinallyErrors: true, + finallyBody: [ + { + kind: "if", + cond: varRef(openId, BOOL, loc), + then: [ + { + kind: "exprStmt", + expr: { kind: "genResume", mode: "close", gen: g(), arg: null, type: VOID, loc }, + loc, + }, + ], + else_: null, + loc, + }, + ], + loc, + }, + ]; +} + +/** `for (j = 0; j < arr.length && !stop; j++) body(arr[j])` over a live + * array local (the array iterator's per-step length read). */ +function walkArray( + frame: ChainFrame, + arrId: string, + arrT: IrType & { kind: "array" }, + stop: IrExpr | null, + body: (value: IrExpr) => IrStmt[], + loc: SrcLoc, +): IrStmt { + const jId = frame.local("j", F64, true); + const wId = frame.local("w", arrT.elem, false); + const inBounds: IrExpr = { + kind: "bin", + op: "<", + left: varRef(jId, F64, loc), + right: { + kind: "arrIntrinsic", + method: "length", + receiver: varRef(arrId, arrT, loc), + args: [], + type: F64, + loc, + }, + type: BOOL, + loc, + }; + return { + kind: "for", + init: { kind: "varDecl", localId: jId, init: numLit(0, loc), loc }, + cond: + stop === null + ? inBounds + : { + kind: "logical", + op: "&&", + left: inBounds, + right: { kind: "unary", op: "!", operand: stop, type: BOOL, loc }, + type: BOOL, + loc, + }, + update: frame.bump(jId), + body: [ + { + kind: "varDecl", + localId: wId, + init: { + kind: "arrayGet", + arr: varRef(arrId, arrT, loc), + index: varRef(jId, F64, loc), + type: arrT.elem, + loc, + }, + loc, + }, + ...body(varRef(wId, arrT.elem, loc)), + ], + loc, + }; +} + +/** The live walk over the Map or Set in local `collId` that for-of does: + * iterEnter, then each live index from iterStart below the current + * iterCount until `stop`, then iterExit on every exit (a throw exits + * before rethrowing). The body sees the projected element. */ +function walkCollection( + lowerer: Lowerer, + frame: ChainFrame, + collId: string, + source: ChainSource & { kind: "collection" }, + stop: IrExpr, + body: (value: IrExpr) => IrStmt[], + loc: SrcLoc, + labels?: string[], +): IrStmt[] { + const t = source.type; + const iId = frame.local("i", F64, true); + const iter = (method: string, args: IrExpr[], type: IrType): IrExpr => + t.kind === "map" + ? { + kind: "mapIntrinsic", + method: method as IrMapIntrinsicMethod, + receiver: varRef(collId, t, loc), + args, + type, + loc, + } + : { + kind: "setIntrinsic", + method: method as IrSetIntrinsicMethod, + receiver: varRef(collId, t, loc), + args, + type, + loc, + }; + const keyT = t.kind === "map" ? t.key : t.elem; + const keyRead = (): IrExpr => iter("iterKey", [varRef(iId, F64, loc)], keyT); + const valRead = (): IrExpr => + t.kind === "map" ? iter("iterValue", [varRef(iId, F64, loc)], t.value) : keyRead(); + const seedT = collectionSeed(lowerer, source); + const seed: IrExpr = + source.proj === "entries" + ? { + kind: "recordLit", + fields: [ + { name: "0", value: keyRead() }, + { name: "1", value: valRead() }, + ], + type: seedT, + loc, + } + : source.proj === "values" && t.kind === "map" + ? valRead() + : keyRead(); + const vId = frame.local("v", seedT, false); + const exit = (): IrStmt => ({ kind: "exprStmt", expr: iter("iterExit", [], VOID), loc }); + const caughtId = frame.local("exc", CAUGHT, false); + const loop: IrStmt = { + kind: "for", + init: { kind: "varDecl", localId: iId, init: iter("iterStart", [], F64), loc }, + cond: { + kind: "logical", + op: "&&", + left: { + kind: "bin", + op: "<", + left: varRef(iId, F64, loc), + right: iter("iterCount", [], F64), + type: BOOL, + loc, + }, + right: { kind: "unary", op: "!", operand: stop, type: BOOL, loc }, + type: BOOL, + loc, + }, + update: frame.bump(iId), + body: [ + { + kind: "if", + cond: iter("iterLive", [varRef(iId, F64, loc)], BOOL), + then: [ + { kind: "varDecl", localId: vId, init: seed, loc }, + ...body(varRef(vId, seedT, loc)), + ], + else_: null, + loc, + }, + ], + ...(labels && { labels }), + loc, + }; + return [ + { kind: "exprStmt", expr: iter("iterEnter", [], VOID), loc }, + { + kind: "tryCatch", + tryBody: [loop], + catchBody: [exit(), { kind: "rethrow", localId: caughtId, loc }], + catchLocalId: caughtId, + finallyBody: null, + loc, + }, + exit(), + ]; +} + +/** A flatMap stage's inner walk over the callback's result in local + * `innerId`: an array by index, or a generator driven (and closed on + * early exit) like the source. `stop` ends the walk early. */ +function walkInner( + lowerer: Lowerer, + frame: ChainFrame, + innerId: string, + innerT: IrType, + stop: IrExpr | null, + body: (value: IrExpr) => IrStmt[], + loc: SrcLoc, +): IrStmt[] { + if (innerT.kind === "array") return [walkArray(frame, innerId, innerT, stop, body, loc)]; + if (innerT.kind !== "generator") + throw new InternalCompilerError("lowerer bug: flatMap over a non-iterable result"); + const pre: IrStmt[] = + stop === null + ? [] + : [{ kind: "if", cond: stop, then: [{ kind: "break", loc }], else_: null, loc }]; + return driveGenerator(lowerer, frame, innerId, innerT, innerT.yieldT, pre, body, loc); +} + +/** A stage inside fused chain code: the local holding its budget or + * callback, and its counter when the callback reads one (take/drop count + * in theirs). */ +interface StageSlot { + kind: string; + argId: string; + fnT?: (IrType & { kind: "func" }) | undefined; + cntId?: string | undefined; +} + +/** A stage callback call with (value) or (value, counter), as declared. */ +function callStage( + fnT: IrType & { kind: "func" }, + fnId: string, + value: IrExpr, + cntId: string | undefined, + loc: SrcLoc, +): IrExpr { + const args: IrExpr[] = []; + if (fnT.params.length >= 1) args.push(value); + if (cntId !== undefined && fnT.params.length >= 2) args.push(varRef(cntId, F64, loc)); + return { kind: "callValue", callee: varRef(fnId, fnT, loc), args, type: fnT.ret, loc }; +} + +/** The slot for `stage` whose budget or callback is in local `argId`. */ +function stageSlot(frame: ChainFrame, stage: StageIr, argId: string): StageSlot { + if ("budget" in stage) { + return { + kind: stage.kind, + argId, + cntId: frame.local(stage.kind === "take" ? "taken" : "dropped", F64, true), + }; + } + const fnT = stage.fn.type; + return { + kind: stage.kind, + argId, + fnT, + cntId: fnT.params.length === 2 ? frame.local("c", F64, true) : undefined, + }; +} + +/** The declarations fused chain code starts with: the `done` flag — + * already true when a take budget is zero, so nothing pulls — and each + * stage counter at zero. */ +function stagePrologue(slots: StageSlot[], doneId: string, loc: SrcLoc): IrStmt[] { + let doneInit: IrExpr = boolLit(false, loc); + for (const s of slots) { + if (s.kind !== "take") continue; + const isZero: IrExpr = { + kind: "bin", + op: "===", + left: varRef(s.argId, F64, loc), + right: numLit(0, loc), + type: BOOL, + loc, + }; + doneInit = + doneInit.kind === "boolLit" + ? isZero + : { kind: "logical", op: "||", left: doneInit, right: isZero, type: BOOL, loc }; + } + const out: IrStmt[] = [{ kind: "varDecl", localId: doneId, init: doneInit, loc }]; + for (const s of slots) { + if (s.cntId !== undefined) + out.push({ kind: "varDecl", localId: s.cntId, init: numLit(0, loc), loc }); + } + return out; +} + +/** The per-element code of a chain: each stage nested in source order + * around `last` (the terminal's statements, or a for-of body), folded + * from the end outward. filter and drop skip with `continue`; take spends + * its budget before delivery and sets `done`, so the nth element flows on + * and nothing pulls after it (every pass tests done); flatMap walks its + * callback's array or generator in an inner loop that also tests done. */ +function foldStages( + lowerer: Lowerer, + frame: ChainFrame, + slots: StageSlot[], + last: (value: IrExpr) => IrStmt[], + doneId: string, + loc: SrcLoc, +): (value: IrExpr) => IrStmt[] { + const done = (): IrExpr => varRef(doneId, BOOL, loc); + const setDone: IrStmt = { kind: "assign", localId: doneId, value: boolLit(true, loc), loc }; + let emit = last; + for (let si = slots.length - 1; si >= 0; si--) { + const s = slots[si]!; + const inner = emit; + if (s.kind === "map") { + emit = (value) => { + const vId = frame.local("m", s.fnT!.ret, false); + return [ + { + kind: "varDecl", + localId: vId, + init: callStage(s.fnT!, s.argId, value, s.cntId, loc), + loc, + }, + ...(s.cntId !== undefined ? [frame.bump(s.cntId)] : []), + ...inner(varRef(vId, s.fnT!.ret, loc)), + ]; + }; + } else if (s.kind === "filter") { + emit = (value) => { + const okId = frame.local("ok", BOOL, false); + return [ + { + kind: "varDecl", + localId: okId, + init: callStage(s.fnT!, s.argId, value, s.cntId, loc), + loc, + }, + ...(s.cntId !== undefined ? [frame.bump(s.cntId)] : []), + { + kind: "if", + cond: { kind: "unary", op: "!", operand: varRef(okId, BOOL, loc), type: BOOL, loc }, + then: [{ kind: "continue", loc }], + else_: null, + loc, + }, + ...inner(value), + ]; + }; + } else if (s.kind === "drop") { + emit = (value) => [ + { + kind: "if", + cond: { + kind: "bin", + op: "<", + left: varRef(s.cntId!, F64, loc), + right: varRef(s.argId, F64, loc), + type: BOOL, + loc, + }, + then: [frame.bump(s.cntId!), { kind: "continue", loc }], + else_: null, + loc, + }, + ...inner(value), + ]; + } else if (s.kind === "take") { + emit = (value) => [ + frame.bump(s.cntId!), + { + kind: "if", + cond: { + kind: "bin", + op: ">=", + left: varRef(s.cntId!, F64, loc), + right: varRef(s.argId, F64, loc), + type: BOOL, + loc, + }, + then: [setDone], + else_: null, + loc, + }, + ...inner(value), + ]; + } else { + emit = (value) => { + const innerT = s.fnT!.ret; + const innerId = frame.local("fm", innerT, false); + return [ + { + kind: "varDecl", + localId: innerId, + init: callStage(s.fnT!, s.argId, value, s.cntId, loc), + loc, + }, + ...(s.cntId !== undefined ? [frame.bump(s.cntId)] : []), + ...walkInner(lowerer, frame, innerId, innerT, done(), inner, loc), + ]; + }; + } + } + return emit; +} + +/** The loop over a chain's source in local `itemsId`, running `emit` per + * element until `done`: a live array (length re-read per pass), a Map or + * Set walked live, or a generator driven like for-of (closed when the + * loop leaves it unfinished). `labels` name the loop for a fused for-of + * body's labeled jumps. */ +function sourceLoop( + lowerer: Lowerer, + frame: ChainFrame, + itemsId: string, + source: ChainSource, + doneId: string, + emit: (value: IrExpr) => IrStmt[], + loc: SrcLoc, + labels?: string[], +): IrStmt[] { + const done = (): IrExpr => varRef(doneId, BOOL, loc); + if (source.kind === "collection") + return walkCollection(lowerer, frame, itemsId, source, done(), emit, loc, labels); + if (source.kind === "generator") { + return driveGenerator( + lowerer, + frame, + itemsId, + source.type, + source.elem, + [{ kind: "if", cond: done(), then: [{ kind: "break", loc }], else_: null, loc }], + emit, + loc, + labels, + ); + } + const itemsT = source.type; + const seedT = source.proj === "entries" ? entryPairType(lowerer, itemsT.elem) : itemsT.elem; + const iId = frame.local("i", F64, true); + const vId = frame.local("v", seedT, false); + const elemRead = (): IrExpr => ({ + kind: "arrayGet", + arr: varRef(itemsId, itemsT, loc), + index: varRef(iId, F64, loc), + type: itemsT.elem, + loc, + }); + const seedInit: IrExpr = + source.proj === "entries" + ? { + kind: "recordLit", + fields: [ + { name: "0", value: varRef(iId, F64, loc) }, + { name: "1", value: elemRead() }, + ], + type: seedT, + loc, + } + : elemRead(); + return [ + { + kind: "for", + init: { kind: "varDecl", localId: iId, init: numLit(0, loc), loc }, + cond: { + kind: "logical", + op: "&&", + left: { + kind: "bin", + op: "<", + left: varRef(iId, F64, loc), + right: { + kind: "arrIntrinsic", + method: "length", + receiver: varRef(itemsId, itemsT, loc), + args: [], + type: F64, + loc, + }, + type: BOOL, + loc, + }, + right: { kind: "unary", op: "!", operand: done(), type: BOOL, loc }, + type: BOOL, + loc, + }, + update: frame.bump(iId), + body: [ + { kind: "varDecl", localId: vId, init: seedInit, loc }, + ...emit(varRef(vId, seedT, loc)), + ], + ...(labels && { labels }), + loc, + }, + ]; +} + +/** The fused chain function: the source, each stage's budget or callback + * and the terminal's arguments as parameters; one loop over the source + * with the stages nested in it and the terminal's statements innermost. + * A zero take budget marks done before the first pass: Node pulls nothing + * through a take(0), and closes a generator source. */ +function buildIterChainFn( + lowerer: Lowerer, + name: string, + source: ChainSource, + stages: StageIr[], + terminal: string, + termArgTs: IrType[], + resultT: IrType, + loc: SrcLoc, +): IrFunction { + const frame = new LiftedFrame(loc); + const itemsId = frame.param("items", source.type); + const doneId = frame.local("done", BOOL, true); + const setDone: IrStmt = { kind: "assign", localId: doneId, value: boolLit(true, loc), loc }; + // Parameters in call order: per-stage budget/callback, then terminal's. + const slots = stages.map((s) => + stageSlot(frame, s, frame.param("budget" in s ? "n" : "f", "budget" in s ? F64 : s.fn.type)), + ); + const termIds = termArgTs.map((t, i) => frame.param(i === 0 ? "tf" : "init", t)); + const termFnT = + termArgTs[0]?.kind === "func" ? (termArgTs[0] as IrType & { kind: "func" }) : null; + const termCntId = + (terminal === "reduce" && termFnT !== null && termFnT.params.length === 3) || + (terminal !== "reduce" && + terminal !== "toArray" && + termFnT !== null && + termFnT.params.length === 2) || + terminal === "reduce" + ? frame.local("k", F64, true) + : undefined; // Terminal state. const preLoop: IrStmt[] = []; const postLoop: IrStmt[] = []; @@ -487,7 +1582,7 @@ function buildIterChainFn( let hasAccId = ""; let resId = ""; if (terminal === "toArray") { - outId = addLocal("out", resultT, false); + outId = frame.local("out", resultT, false); preLoop.push({ kind: "varDecl", localId: outId, @@ -496,7 +1591,7 @@ function buildIterChainFn( }); postLoop.push({ kind: "return", value: varRef(outId, resultT, loc), loc }); } else if (terminal === "some" || terminal === "every") { - resId = addLocal("res", BOOL, true); + resId = frame.local("res", BOOL, true); preLoop.push({ kind: "varDecl", localId: resId, @@ -505,14 +1600,14 @@ function buildIterChainFn( }); postLoop.push({ kind: "return", value: varRef(resId, BOOL, loc), loc }); } else if (terminal === "find") { - resId = addLocal("res", resultT, true); + resId = frame.local("res", resultT, true); const undef = lowerer.wrappedUndefined(resultT, loc); if (undef === null) throw new InternalCompilerError("lowerer bug: find result union lacks undefined"); preLoop.push({ kind: "varDecl", localId: resId, init: undef, loc }); postLoop.push({ kind: "return", value: varRef(resId, resultT, loc), loc }); } else if (terminal === "reduce") { - accId = addLocal("acc", resultT, true); + accId = frame.local("acc", resultT, true); if (termIds.length === 2) { preLoop.push({ kind: "varDecl", @@ -521,7 +1616,7 @@ function buildIterChainFn( loc, }); } else { - hasAccId = addLocal("hasAcc", BOOL, true); + hasAccId = frame.local("hasAcc", BOOL, true); preLoop.push({ kind: "varDecl", localId: hasAccId, init: boolLit(false, loc), loc }); postLoop.push({ kind: "if", @@ -547,28 +1642,7 @@ function buildIterChainFn( } if (termCntId !== undefined) preLoop.push({ kind: "varDecl", localId: termCntId, init: numLit(0, loc), loc }); - // done starts true when any take budget is zero (nothing pulls). - let doneInit: IrExpr = boolLit(false, loc); - for (const s of slots) { - if (s.kind !== "take") continue; - const isZero: IrExpr = { - kind: "bin", - op: "===", - left: varRef(s.paramId, F64, loc), - right: numLit(0, loc), - type: BOOL, - loc, - }; - doneInit = - doneInit.kind === "boolLit" - ? isZero - : { kind: "logical", op: "||", left: doneInit, right: isZero, type: BOOL, loc }; - } - preLoop.unshift({ kind: "varDecl", localId: doneId, init: doneInit, loc }); - for (const s of slots) { - if (s.cntId !== undefined) - preLoop.push({ kind: "varDecl", localId: s.cntId, init: numLit(0, loc), loc }); - } + preLoop.unshift(...stagePrologue(slots, doneId, loc)); // The terminal's per-element statements over `value`. const terminalBody = (value: IrExpr): IrStmt[] => { const out: IrStmt[] = []; @@ -586,9 +1660,13 @@ function buildIterChainFn( loc, }); } else if (terminal === "forEach") { - out.push({ kind: "exprStmt", expr: callWith(termFnT!, termIds[0]!, value, termCntId), loc }); + out.push({ + kind: "exprStmt", + expr: callStage(termFnT!, termIds[0]!, value, termCntId, loc), + loc, + }); } else if (terminal === "some" || terminal === "every") { - const hit = callWith(termFnT!, termIds[0]!, value, termCntId); + const hit = callStage(termFnT!, termIds[0]!, value, termCntId, loc); const cond: IrExpr = terminal === "some" ? hit : { kind: "unary", op: "!", operand: hit, type: BOOL, loc }; out.push({ @@ -610,7 +1688,7 @@ function buildIterChainFn( ); out.push({ kind: "if", - cond: callWith(termFnT!, termIds[0]!, value, termCntId), + cond: callStage(termFnT!, termIds[0]!, value, termCntId, loc), then: [ { kind: "assign", @@ -658,230 +1736,203 @@ function buildIterChainFn( out.push({ kind: "assign", localId: accId, value: reducer(), loc }); } } - if (termCntId !== undefined) out.push(bump(termCntId)); + if (termCntId !== undefined) out.push(frame.bump(termCntId)); return out; }; - // Fold stages from the terminal outward. - let emit: (value: IrExpr) => IrStmt[] = terminalBody; - for (let si = slots.length - 1; si >= 0; si--) { - const s = slots[si]!; - const inner = emit; - if (s.kind === "map") { - emit = (value) => { - const vId = addLocal("m", s.fnT!.ret, false); - return [ - { kind: "varDecl", localId: vId, init: callWith(s.fnT!, s.paramId, value, s.cntId), loc }, - ...(s.cntId !== undefined ? [bump(s.cntId)] : []), - ...inner(varRef(vId, s.fnT!.ret, loc)), - ]; - }; - } else if (s.kind === "filter") { - emit = (value) => { - const okId = addLocal("ok", BOOL, false); - return [ - { - kind: "varDecl", - localId: okId, - init: callWith(s.fnT!, s.paramId, value, s.cntId), - loc, - }, - ...(s.cntId !== undefined ? [bump(s.cntId)] : []), - { - kind: "if", - cond: { kind: "unary", op: "!", operand: varRef(okId, BOOL, loc), type: BOOL, loc }, - then: [{ kind: "continue", loc }], - else_: null, - loc, - }, - ...inner(value), - ]; - }; - } else if (s.kind === "drop") { - emit = (value) => [ - { - kind: "if", - cond: { - kind: "bin", - op: "<", - left: varRef(s.cntId!, F64, loc), - right: varRef(s.paramId, F64, loc), - type: BOOL, - loc, - }, - then: [bump(s.cntId!), { kind: "continue", loc }], - else_: null, - loc, - }, - ...inner(value), - ]; - } else if (s.kind === "take") { - // Budget consumed BEFORE delivery: the nth element flows on with - // done already set, so no later element pulls upstream — and a - // downstream `continue` can't skip the close (the loop conditions - // carry !done). - emit = (value) => [ - bump(s.cntId!), - { - kind: "if", - cond: { - kind: "bin", - op: ">=", - left: varRef(s.cntId!, F64, loc), - right: varRef(s.paramId, F64, loc), - type: BOOL, - loc, - }, - then: [setDone], - else_: null, - loc, - }, - ...inner(value), - ]; - } else { - // flatMap: an inner loop over the returned array, `!done` carried. - emit = (value) => { - const innerT = s.fnT!.ret as IrType & { kind: "array" }; - const arrId = addLocal("fm", innerT, false); - const jId = addLocal("j", F64, true); - const wId = addLocal("w", innerT.elem, false); - return [ - { - kind: "varDecl", - localId: arrId, - init: callWith(s.fnT!, s.paramId, value, s.cntId), - loc, - }, - ...(s.cntId !== undefined ? [bump(s.cntId)] : []), - { - kind: "for", - init: { kind: "varDecl", localId: jId, init: numLit(0, loc), loc }, - cond: { - kind: "logical", - op: "&&", - left: { - kind: "bin", - op: "<", - left: varRef(jId, F64, loc), - right: { - kind: "arrIntrinsic", - method: "length", - receiver: varRef(arrId, innerT, loc), - args: [], - type: F64, - loc, - }, - type: BOOL, - loc, - }, - right: { kind: "unary", op: "!", operand: done(), type: BOOL, loc }, - type: BOOL, - loc, - }, - update: { - kind: "assign", - localId: jId, - value: { - kind: "bin", - op: "+", - left: varRef(jId, F64, loc), - right: numLit(1, loc), - type: F64, - loc, - }, - loc, - }, - body: [ - { - kind: "varDecl", - localId: wId, - init: { - kind: "arrayGet", - arr: varRef(arrId, innerT, loc), - index: varRef(jId, F64, loc), - type: innerT.elem, - loc, - }, - loc, - }, - ...inner(varRef(wId, innerT.elem, loc)), - ], - loc, - }, - ]; - }; - } - } - const iId = addLocal("i", F64, true); - const vId = addLocal("v", seedT, false); - const elemRead = (): IrExpr => ({ - kind: "arrayGet", - arr: varRef("items.0", itemsT, loc), - index: varRef(iId, F64, loc), - type: itemsT.elem, - loc, - }); - const seedInit: IrExpr = - srcProj === "entries" - ? { - kind: "recordLit", - fields: [ - { name: "0", value: varRef(iId, F64, loc) }, - { name: "1", value: elemRead() }, - ], - type: seedT, - loc, - } - : elemRead(); - const loop: IrStmt = { - kind: "for", - init: { kind: "varDecl", localId: iId, init: numLit(0, loc), loc }, - cond: { - kind: "logical", - op: "&&", - left: { - kind: "bin", - op: "<", - left: varRef(iId, F64, loc), - right: { - kind: "arrIntrinsic", - method: "length", - receiver: varRef("items.0", itemsT, loc), - args: [], - type: F64, - loc, - }, - type: BOOL, - loc, - }, - right: { kind: "unary", op: "!", operand: done(), type: BOOL, loc }, - type: BOOL, - loc, - }, - update: { - kind: "assign", - localId: iId, - value: { - kind: "bin", - op: "+", - left: varRef(iId, F64, loc), - right: numLit(1, loc), - type: F64, - loc, - }, - loc, - }, + const emit = foldStages(lowerer, frame, slots, terminalBody, doneId, loc); + return { + name, + params: frame.params, + returnType: resultT, + locals: frame.locals, body: [ - { kind: "varDecl", localId: vId, init: seedInit, loc }, - ...emit(varRef(vId, seedT, loc)), + ...preLoop, + ...sourceLoop(lowerer, frame, itemsId, source, doneId, emit, loc), + ...postLoop, ], loc, }; +} + +/** An iterator helper object's generator for one stage over `src`: + * + * map: for (v of src) yield f(v, c++) + * filter: for (v of src) if (f(v, c++)) yield v + * take: for (;;) { if (rem === 0) { close src; return } rem--; pull; yield v } + * drop: for (v of src) { if (dropped < n) { dropped++; continue } yield v } + * flatMap: for (v of src) for (w of f(v, c++)) yield w + * + * The source drive closes `src` on every early exit, including a + * `return()` at one of the yields; `closesSource` closes it on a + * `return()` before the first `next()`. */ +function buildHelperGenFn( + lowerer: Lowerer, + name: string, + srcT: GenType, + srcElem: IrType, + stage: StageIr, + argT: IrType, + outT: GenType, + resultType: IrType & { kind: "record" }, + loc: SrcLoc, +): IrFunction { + const frame = new LiftedFrame(loc); + const srcId = frame.param("src", srcT); + const argId = frame.param(stage.kind === "take" || stage.kind === "drop" ? "n" : "f", argT); + const yieldOf = (value: IrExpr): IrStmt => ({ + kind: "exprStmt", + expr: { + kind: "yieldExpr", + value, + type: outT.nextT.kind === "undefinedT" ? VOID : outT.nextT, + loc, + }, + loc, + }); + const fnT = argT.kind === "func" ? argT : null; + const counted = fnT !== null && fnT.params.length === 2; + const cntId = counted ? frame.local("c", F64, true) : null; + const callF = (value: IrExpr): IrExpr => { + const args: IrExpr[] = []; + if (fnT!.params.length >= 1) args.push(value); + if (cntId !== null) args.push(varRef(cntId, F64, loc)); + return { kind: "callValue", callee: varRef(argId, fnT!, loc), args, type: fnT!.ret, loc }; + }; + const body: IrStmt[] = []; + if (cntId !== null) body.push({ kind: "varDecl", localId: cntId, init: numLit(0, loc), loc }); + const bumpCount = (): IrStmt[] => (cntId !== null ? [frame.bump(cntId)] : []); + const n = (): IrExpr => varRef(argId, F64, loc); + if (stage.kind === "map") { + body.push( + ...driveGenerator( + lowerer, + frame, + srcId, + srcT, + srcElem, + [], + (value) => { + const mId = frame.local("m", fnT!.ret, false); + return [ + { kind: "varDecl", localId: mId, init: callF(value), loc }, + ...bumpCount(), + yieldOf(varRef(mId, fnT!.ret, loc)), + ]; + }, + loc, + ), + ); + } else if (stage.kind === "filter") { + body.push( + ...driveGenerator( + lowerer, + frame, + srcId, + srcT, + srcElem, + [], + (value) => { + const okId = frame.local("ok", BOOL, false); + return [ + { kind: "varDecl", localId: okId, init: callF(value), loc }, + ...bumpCount(), + { kind: "if", cond: varRef(okId, BOOL, loc), then: [yieldOf(value)], else_: null, loc }, + ]; + }, + loc, + ), + ); + } else if (stage.kind === "take") { + // The budget is spent before each pull; a spent budget closes the + // source on the next pass instead of pulling. + const pre: IrStmt[] = [ + { + kind: "if", + cond: { kind: "bin", op: "===", left: n(), right: numLit(0, loc), type: BOOL, loc }, + then: [{ kind: "break", loc }], + else_: null, + loc, + }, + { + kind: "assign", + localId: argId, + value: { kind: "bin", op: "-", left: n(), right: numLit(1, loc), type: F64, loc }, + loc, + }, + ]; + body.push( + ...driveGenerator( + lowerer, + frame, + srcId, + srcT, + srcElem, + pre, + (value) => [yieldOf(value)], + loc, + ), + ); + } else if (stage.kind === "drop") { + const droppedId = frame.local("dropped", F64, true); + body.push({ kind: "varDecl", localId: droppedId, init: numLit(0, loc), loc }); + body.push( + ...driveGenerator( + lowerer, + frame, + srcId, + srcT, + srcElem, + [], + (value) => [ + { + kind: "if", + cond: { + kind: "bin", + op: "<", + left: varRef(droppedId, F64, loc), + right: n(), + type: BOOL, + loc, + }, + then: [frame.bump(droppedId), { kind: "continue", loc }], + else_: null, + loc, + }, + yieldOf(value), + ], + loc, + ), + ); + } else { + body.push( + ...driveGenerator( + lowerer, + frame, + srcId, + srcT, + srcElem, + [], + (value) => { + const innerT = fnT!.ret; + const innerId = frame.local("fm", innerT, false); + return [ + { kind: "varDecl", localId: innerId, init: callF(value), loc }, + ...bumpCount(), + ...walkInner(lowerer, frame, innerId, innerT, null, (w) => [yieldOf(w)], loc), + ]; + }, + loc, + ), + ); + } + body.push({ kind: "return", value: null, loc }); return { name, - params, - returnType: resultT, - locals, - body: [...preLoop, loop, ...postLoop], + params: frame.params, + returnType: VOID, + locals: frame.locals, + body, + generator: { yieldT: outT.yieldT, nextT: outT.nextT, resultType, closesSource: true }, loc, }; } diff --git a/packages/compiler/src/frontend/lowering/error-methods.ts b/packages/compiler/src/frontend/lowering/error-methods.ts index bcbbe13a4..979cf4814 100644 --- a/packages/compiler/src/frontend/lowering/error-methods.ts +++ b/packages/compiler/src/frontend/lowering/error-methods.ts @@ -315,7 +315,13 @@ export function refreshErrorPropertyDispatch( info.def.name, member, value, - [varRef("value", STRING, loc)], + [ + // A JavaScript setter takes its value untyped. + lowerer.coerceToExpected( + varRef("value", STRING, loc), + accessor.sig.params[0]?.type ?? STRING, + ), + ], VOID, loc, ), diff --git a/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts b/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts index 7da847062..ceedc3e94 100644 --- a/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts +++ b/packages/compiler/src/frontend/lowering/expressions/optional-chains.ts @@ -26,7 +26,8 @@ import type { Lowerer } from "../lowerer.js"; * deeper — `x?.trim().toLowerCase()` reads nothing past the guard when x * is nullish, so the whole tail must lower inside it. Walks * property/element accesses and call steps only (parens and `!` break - * the chain per the grammar: `(a?.b).c` throws on undefined in JS); + * the chain per the grammar: `(a?.b).c` throws on undefined in JS, while + * an unparenthesized `a?.b!.c` stays one chain, as TypeScript emits it); * the node's OWN token — and a call's immediate callee token — are the * plain entries' cases, not tails, and handled markers make the chain * lowering's re-dispatch walk past its own step. `f?.()` steps stay out @@ -41,6 +42,10 @@ function chainTailDot( // An active chain's bound receiver read is a LEAF — its own token // was consumed by the chain that bound it. if (lowerer.chainRecvByNode.has(cur)) return null; + if (ts.isNonNullExpression(cur)) { + cur = cur.expression; + continue; + } if (ts.isCallExpression(cur)) { // `f?.()` steps route through their own entry (or are being // handled); a deeper token under one is that chain's business. @@ -91,20 +96,29 @@ export function isOptionalChainTail(lowerer: Lowerer, expr: ts.Expression): bool if (!tail) return false; const recvT = lowerer.mapTypeOf(lowerer.typeOf(tail.expression)); if (recvT?.kind === "dyn") return true; - if (recvT?.kind !== "union") return false; - const def = lowerer.unions.get(recvT.unionId); - return !!def && def.arms.some(isUnitType); + if (recvT?.kind === "union") { + const def = lowerer.unions.get(recvT.unionId); + if (def?.arms.some(isUnitType)) return true; + } + // The checker calls the receiver present, but an unchecked read (`a[0]` + // past the end, a missing index-signature key) can still lower to an + // undefined-armed value, and `a[0]?.b.c` must then short-circuit `.c` + // too. The chain lowering inspects the lowered receiver: a present value + // re-dispatches the plain lowering, so only genuinely optional receivers + // change shape. + return lowerer.isRuntimeOptionalOrigin(tail.expression); } /** True when an EARLIER step of this access chain carries `?.` — JS * short-circuits the whole tail (`a?.b.c` reads nothing when a is * nullish), so a dyn tail read must answer undefined instead of * throwing. Walks the receiver spine only; the argument of the access - * itself is not part of the guard. */ + * itself is not part of the guard. Parentheses end the chain + * (`(a?.b).c` reads `.c` from undefined); `!` does not. */ export function hasOptionalChainGuard(expr: ts.Expression): boolean { let cur: ts.Expression = expr; for (;;) { - if (ts.isParenthesizedExpression(cur) || ts.isNonNullExpression(cur)) { + if (ts.isNonNullExpression(cur)) { cur = cur.expression; continue; } @@ -393,7 +407,8 @@ export function lowerOptionalChain( for (let cur: ts.Expression = expr; cur !== dotNode;) { const next: ts.Expression = ts.isCallExpression(cur) ? cur.expression - : (cur as ts.PropertyAccessExpression | ts.ElementAccessExpression).expression; + : (cur as ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.NonNullExpression) + .expression; if (next === dotNode) break; if (!lowerer.chainNarrowedType.has(next)) { lowerer.chainNarrowedType.set( diff --git a/packages/compiler/src/frontend/lowering/generic-functions.ts b/packages/compiler/src/frontend/lowering/generic-functions.ts index bd785a256..49bb33882 100644 --- a/packages/compiler/src/frontend/lowering/generic-functions.ts +++ b/packages/compiler/src/frontend/lowering/generic-functions.ts @@ -15,7 +15,7 @@ import { isJsSourceFile, locOf } from "../program.js"; import { typeKey } from "../type-mapper.js"; import { PoisonError, dynFallbackType, neverTaintedJsType, newFnCtx } from "./lowerer.js"; import { tryLowerExpression } from "./expressions/try-lower-expression.js"; -import { findGenericMethodOn, type ClassInfo } from "./lower-classes.js"; +import { findGenericMethodOn, storedClassValueType, type ClassInfo } from "./lower-classes.js"; import { nsPathPrefix } from "./lower-namespaces.js"; import { declSymbolOf } from "./lower-modules.js"; import { npmStaticPackageOfPath } from "../npm-static.js"; @@ -292,6 +292,8 @@ export function genericCallInstance( (_param, i) => expr.arguments[i] ?? expr, ); const retTs = lowerer.checker.getReturnTypeOfSignature(rsig); + const local = localClassResultInstance(lowerer, expr, info, rsig, params, retTs); + if (local) return local; const returnType = lowerer.mapTypeOf(retTs); if (!returnType) { fenceGenericSignatureResult(lowerer, expr, retTs); @@ -331,6 +333,150 @@ export function genericCallInstance( ); } +/** A generic factory whose result is one of its own local classes + * (`function base(v: T) { return class { value: T = v }; }`). Each + * instance has its own class, so the instance is keyed on its bindings and + * the result maps inside it, where the local class takes the instance's + * name and bindings. */ +function localClassResultInstance( + lowerer: Lowerer, + expr: ts.CallExpression, + info: GenericFnInfo, + rsig: ts.Signature, + params: ParamShape[], + retTs: ts.Type, +): GenericInstance | null { + if (!localClassOfResult(lowerer, info, retTs)) return null; + const tsBindings = new Map(); + const bindings = lowerer.inferTypeParamBindings(expr, info, rsig, tsBindings); + const bindingKey = info.typeParams + .map((tp) => { + const bound = bindings.get(tp); + return bound ? typeKey(bound) : "?"; + }) + .join(","); + const pending: IrType = { kind: "void" }; + const inst = internGenericInstance(lowerer, expr, info, params, pending, () => bindings, { + extraKey: `@class<${bindingKey}>`, + tsBindings, + }); + if (inst.returnType !== pending) return inst; + const returnType = withInstanceScope(lowerer, info, inst, () => lowerer.mapTypeOf(retTs)); + if (!returnType) { + fenceGenericSignatureResult(lowerer, expr, retTs); + lowerer.badType(expr, retTs); + } + inst.returnType = returnType; + // Values of the class outside the factory (`const b = new B()`, `b.read()`) + // carry the instantiated checker type; record which class it names. A + // call inside another generic instance can have a type that depends on + // that instance's parameters, which no single class answers. + if (lowerer.typeParamBindings !== null) return inst; + const instance = + returnType.kind === "classval" + ? lowerer.checker + .getConstructSignatures(retTs) + .map((sig) => lowerer.checker.getReturnTypeOfSignature(sig)) + : [retTs]; + const className = + returnType.kind === "classval" || returnType.kind === "object" ? returnType.className : null; + if (className !== null) + for (const type of instance) lowerer.localClassInstanceTypes.set(type.id, className); + return inst; +} + +/** The class value a call of a generic factory returns when the result is + * one of the factory's local classes (`class C extends base(42) {}`), or + * null for any other call. */ +export function genericLocalClassResult(lowerer: Lowerer, expr: ts.CallExpression): IrType | null { + if (!ts.isIdentifier(expr.expression)) return null; + const info = lowerer.genericFnOf(expr.expression); + if (!info || info.implicitParams) return null; + const rsig = lowerer.checker.getResolvedSignature(expr); + if (!rsig || !localClassOfResult(lowerer, info, lowerer.checker.getReturnTypeOfSignature(rsig))) + return null; + return genericCallInstance(lowerer, expr, info).returnType; +} + +/** The type of a `const` binding whose initializer calls a generic factory + * returning one of its local classes (`const B = base(7)`), or constructs + * such a class (`const b = new B()`); null for any other binding. */ +export function genericLocalClassBinding(lowerer: Lowerer, node: ts.Node): IrType | null { + const decl = node.parent; + if ( + !ts.isIdentifier(node) || + !decl || + !ts.isVariableDeclaration(decl) || + decl.name !== node || + !decl.initializer || + (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0 + ) + return null; + // An `any` binding keeps the checked-dynamic representation. + if ((lowerer.typeOf(node).flags & ts.TypeFlags.Any) !== 0) return null; + let init = decl.initializer; + while (ts.isParenthesizedExpression(init)) init = init.expression; + if (ts.isCallExpression(init)) return genericLocalClassResult(lowerer, init); + if (!ts.isNewExpression(init)) return null; + const constructed = storedClassValueType(lowerer, init.expression); + if (constructed?.kind !== "classval") return null; + const classDecl = lowerer.classes.get(constructed.className)?.decl; + return classDecl && insideGenericFunction(classDecl) + ? { kind: "object", className: constructed.className } + : null; +} + +/** Whether `node` is declared inside a function with type parameters. */ +function insideGenericFunction(node: ts.Node): boolean { + for (let parent = node.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) + if (ts.isFunctionLike(parent) && (parent.typeParameters?.length ?? 0) > 0) return true; + return false; +} + +/** The class declared inside a generic function that `type` is the + * constructor or instance type of, or null. */ +function localClassOfResult( + lowerer: Lowerer, + info: GenericFnInfo, + type: ts.Type, +): ts.ClassLikeDeclaration | null { + const symbol = type.getSymbol(); + if (!symbol || !(symbol.flags & ts.SymbolFlags.Class)) return null; + const decl = lowerer.checker.valueDeclarationOf(symbol); + if (!decl || !(ts.isClassExpression(decl) || ts.isClassDeclaration(decl))) return null; + for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) + if (parent === info.decl) return decl; + return null; +} + +/** Runs `fn` under an instance's type bindings and local-class names, as + * its body lowers. */ +function withInstanceScope( + lowerer: Lowerer, + info: GenericFnInfo, + inst: GenericInstance, + fn: () => T, +): T { + const prevBindings = lowerer.typeParamBindings; + const prevTsBindings = lowerer.typeParamTsBindings; + const previousPath = lowerer.genericInstantiationPath; + const prevContext = lowerer.instantiationContext; + lowerer.typeParamBindings = inst.bindings; + lowerer.typeParamTsBindings = inst.tsBindings ?? null; + lowerer.genericInstantiationPath = inst.path; + lowerer.instantiationContext = `instantiating '${info.baseName}' with ${inst.typeArgsText}`; + lowerer.localClassInstantiations.push({ owner: info.decl, name: inst.name }); + try { + return fn(); + } finally { + lowerer.localClassInstantiations.pop(); + lowerer.typeParamBindings = prevBindings; + lowerer.typeParamTsBindings = prevTsBindings; + lowerer.genericInstantiationPath = previousPath; + lowerer.instantiationContext = prevContext; + } +} + /** The one instance table both instantiation routes share: key identity IS * signature identity, so a call (`identity(1)`) and a pinned VALUE * (`const f: (x: number) => number = identity`) reuse one compiled diff --git a/packages/compiler/src/frontend/lowering/lower-calls.ts b/packages/compiler/src/frontend/lowering/lower-calls.ts index fc7069b41..af529994d 100644 --- a/packages/compiler/src/frontend/lowering/lower-calls.ts +++ b/packages/compiler/src/frontend/lowering/lower-calls.ts @@ -24,6 +24,13 @@ import { lowerZlibStreamMethodCall, } from "./builtins/compression.js"; import type { Lowerer } from "./lowerer.js"; +import { + inlineNamespaceRequireOf, + lowerInlineRequireValue, + lowerUncompiledRequireCall, + lowerWithInlineRequireInit, +} from "./cjs-inline-require.js"; +import { cjsExportCallIgnoresThis, cjsInFileExportGlobalOf } from "./cjs-exports-object.js"; import { lowerGenMethodCall } from "./lower-generators.js"; import { lowerClassSymbolMethodCall } from "./symbol-methods.js"; import { errorToStringCall } from "./error-methods.js"; @@ -61,7 +68,11 @@ import { lowerProtocolMethodCall } from "./class-protocol-dispatch.js"; import { isJsSourceFile, locOf, requireSpecOf } from "../program.js"; import { lowerJsonRequireCall } from "./json-require.js"; import { lowerAssertInstanceCall } from "./assert-instances.js"; -import { isGenericCallableMemberType, typeKey } from "../type-mapper.js"; +import { + isGenericCallableMemberType, + isOverloadedCallableMemberType, + typeKey, +} from "../type-mapper.js"; import { dynFallbackType, jsFuncNameOf, newFnCtx, staticImportNamespaceType } from "./lowerer.js"; import { NARROW_FIRST, @@ -79,7 +90,10 @@ import { import { lowerArrayFromAsyncCall } from "./containers/array-from-async.js"; import { lowerDynArrayFilterCall, lowerDynArrayFlatMapCall } from "./containers/array-callbacks.js"; import { lowerGroupByStaticCall } from "./containers/collection-grouping.js"; -import { lowerIteratorHelperCall } from "./containers/iterator-helpers.js"; +import { + lowerGeneratorHelperCall, + lowerIteratorHelperCall, +} from "./containers/iterator-helpers.js"; import { lowerObjectAssignIndexShape, lowerObjectConstructor, @@ -235,6 +249,32 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { const json = lowerJsonRequireCall(lowerer, expr); if (json) return json; + // Inline require() of a program module (cjs-inline-require.ts): a + // member call over its export table resolves like a binding's member + // call after the module's %init at this position; the require itself + // as a value answers the module's whole-export value. + if (ts.isPropertyAccessExpression(expr.expression) && !expr.expression.questionDotToken) { + const req = inlineNamespaceRequireOf(lowerer, expr.expression.expression); + if (req !== null && !lowerer.inlineRequireInitDone.has(req.call)) { + // Node calls the member with `this` bound to the module's exports. + if ( + ts.isIdentifier(expr.expression.name) && + !cjsExportCallIgnoresThis(lowerer, req.dep, expr.expression.name.text) + ) { + lowerer.unsupported( + "SC1090", + expr, + `calling '${expr.expression.name.text}' through require(${JSON.stringify(req.spec)}) when the function may read 'this' (Node binds it to the module's exports object, which compiles to a static table — bind the module and call a local function instead)`, + ); + } + return lowerWithInlineRequireInit(lowerer, req, () => lowerCall(lowerer, expr)); + } + } + { + const inlineValue = lowerInlineRequireValue(lowerer, expr); + if (inlineValue) return inlineValue; + } + // A call whose chain ROOTS at an ambient-undefined name (`declare // const value: Y | undefined; value?.foo("a")`, `declare function // chain...; chain(o).mapValues(f).value()`, a trap binding's read): @@ -311,6 +351,12 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { lowerImportMetaResolveCall(lowerer, expr) ?? lowerRequireResolveCall(lowerer, expr); if (resolved) return resolved; } + // Any other require() call of the CommonJS global: MODULE_NOT_FOUND for + // packages nothing installed resolves, a named refusal otherwise. + { + const uncompiled = lowerUncompiledRequireCall(lowerer, expr); + if (uncompiled) return uncompiled; + } // `process.getuid?.()` — intercepted BEFORE the optional-chain // machinery (the member always exists on a POSIX target, so the @@ -1275,6 +1321,32 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { const args = completeFuncValueArgs(lowerer, expr, callee.type, loc); return { kind: "callValue", callee, args, type: callee.type.ret, loc }; } + // `exports.f(x)` / `module.exports.f(x)` inside the module: a call of + // the member's export global (cjs-exports-object.ts), the value every + // `exports.f =` statement assigns. + if (ts.isPropertyAccessExpression(expr.expression) && !expr.questionDotToken) { + const g = cjsInFileExportGlobalOf(lowerer, expr.expression); + if ( + g && + (g.type.kind === "func" || g.type.kind === "dyn") && + !cjsExportCallIgnoresThis(lowerer, expr.getSourceFile(), expr.expression.name.text) + ) { + lowerer.unsupported( + "SC1090", + expr, + `calling '${expr.expression.getText()}' through the module's exports object when the function may read 'this' (Node binds it to the exports object, which compiles to a static table — call a local function instead)`, + ); + } + if (g && (g.type.kind === "func" || g.type.kind === "dyn")) { + const callee: IrExpr = { kind: "varRef", localId: g.id, type: g.type, loc }; + const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc); + if (checked) return checked; + if (callee.type.kind === "func") { + const args = completeFuncValueArgs(lowerer, expr, callee.type, loc); + return { kind: "callValue", callee, args, type: callee.type.ret, loc }; + } + } + } if (ts.isPropertyAccessExpression(expr.expression)) { const intrinsic = fenceNodeModuleMutationCall(lowerer, expr, expr.expression) ?? @@ -1422,6 +1494,8 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr { // array method paths (the terminal names collide with array // methods, but only iterator-typed receivers reach this). lowerIteratorHelperCall(lowerer, expr, expr.expression) ?? + // Helper calls on generators and other iterator objects. + lowerGeneratorHelperCall(lowerer, expr, expr.expression) ?? lowerIteratorStaticFence(lowerer, expr, expr.expression) ?? lowerObjectStaticCall(lowerer, expr, expr.expression) ?? lowerObjectFromEntriesCall(lowerer, expr, expr.expression) ?? @@ -3075,8 +3149,9 @@ function lowerOptionalStringNumber( return { kind: "call", callee: helper, args: [arg], type: F64, loc }; } -/** Iterator types whose helper calls have no lowering on any path (the - * array iterator's chains lower in lowerIteratorHelperCall). */ +/** Iterator types with checked runtime receivers: Map/Set iterators' + * helper calls lower in lowerGeneratorHelperCall; the string iterator's + * have no lowering. */ const UNLOWERED_ITERATOR_TYPES = new Set(["MapIterator", "SetIterator", "StringIterator"]); const ITERATOR_HELPER_METHODS = new Set([ "map", @@ -3143,6 +3218,8 @@ function lowerDynReceiverMethodCall( lowerer.isStdlibMember(access) ) { if (recvSymbol.name === "MapIterator" || recvSymbol.name === "SetIterator") { + const helper = lowerGeneratorHelperCall(lowerer, call, access); + if (helper) return helper; lowerer.noLowering( `collection iterator .${access.name.text}()`, call, @@ -3153,7 +3230,7 @@ function lowerDynReceiverMethodCall( lowerer.noLowering( `${recvSymbol.name}.${access.name.text}`, call, - "iterator helpers lower on chains from arr.values() or arr.entries() that end in a terminal (toArray, forEach, reduce, some, every, find) — spread the string first: [...s].values()", + "iterator helpers lower on generators and on array, Map and Set iterators — spread the string first: [...s].values()", ); } const arrayReceiver = lowerer.checker.isArrayType(recvTs); @@ -4171,10 +4248,32 @@ function lowerNumberToStringCall( } if (call.arguments.length === 1) { if (operand.type.kind !== "f64") return null; + const arg = call.arguments[0]!; + // A number radix needs no box: ToIntegerOrInfinity of a number is a + // truncation, which the typed entry point applies itself. + if (!ts.isSpreadElement(arg) && lowerer.mapTypeOf(lowerer.typeOf(arg))?.kind === "f64") { + const radix = lowerer.lowerExpr(arg); + if (radix.type.kind === "f64") { + return { + kind: "libCall", + fn: "num.toStringRadixF64", + args: [operand, radix], + type: STRING, + loc: locOf(call), + }; + } + return { + kind: "libCall", + fn: "num.toStringRadix", + args: [operand, lowerer.coerceToExpected(radix, DYN)], + type: STRING, + loc: locOf(call), + }; + } return { kind: "libCall", fn: "num.toStringRadix", - args: [operand, lowerer.lowerExprExpecting(call.arguments[0]!, DYN)], + args: [operand, lowerer.lowerExprExpecting(arg, DYN)], type: STRING, loc: locOf(call), }; @@ -6526,9 +6625,9 @@ function recordAssignHelper( } /** The `Iterator` global's statics (ES2025 — Iterator.from, and the - * abstract constructor as a value): no first-class iterator objects - * exist here, so every member fences with the working spelling named - * instead of the generic-method fence's monomorphization wording. */ + * abstract constructor as a value) have no lowering: every member fences + * with the working spelling named instead of the generic-method fence's + * monomorphization wording. */ function lowerIteratorStaticFence( lowerer: Lowerer, call: ts.CallExpression, @@ -6539,8 +6638,8 @@ function lowerIteratorStaticFence( lowerer.noLowering( `Iterator.${access.name.text}`, call, - "first-class iterator objects have no lowering — iterator helpers compile as one chain on an " + - "array iterator, consumed in place: arr.values().map(f).take(n).toArray()", + "iterator helpers apply directly to generators and to array, Map and Set iterators: " + + "arr.values().map(f).take(n).toArray()", ); } @@ -8191,6 +8290,30 @@ function lowerObjectAssignHybrid(lowerer: Lowerer, call: ts.CallExpression): IrE return { kind: "recordLit", fields, type: mapped, loc }; } +/** The accessed member is an overload set (isOverloadedCallableMemberType), + * also under an optional chain whose access still spells `| undefined`. */ +function isOverloadedMemberAccess(lowerer: Lowerer, access: ts.PropertyAccessExpression): boolean { + return isOverloadedCallableMemberType( + lowerer.checker.getNonNullableType(lowerer.typeOf(access)), + lowerer.checker, + ); +} + +/** The result type of the overload a call through an overloaded member + * resolved to: the erased slot's result converts to it. A non-generic + * overload answers through its declaration, because the resolved signature + * of an optional-chain call (`api?.m(x)`) also carries the chain's + * undefined; a generic one answers through its instantiation. */ +function resolvedOverloadResultType(lowerer: Lowerer, call: ts.CallExpression): IrType { + const { checker } = lowerer; + const signature = checker.getResolvedSignature(call); + const decl = signature ? checker.signatureDeclaration(signature) : undefined; + const declared = decl ? checker.getSignatureFromDeclaration(decl) : undefined; + const source = declared && declared.getTypeParameters().length === 0 ? declared : signature; + const result = source ? lowerer.mapTypeOf(checker.getReturnTypeOfSignature(source)) : null; + return result ?? lowerer.irTypeOf(call); +} + export function lowerRecordFieldCall( lowerer: Lowerer, call: ts.CallExpression, @@ -8222,7 +8345,18 @@ export function lowerRecordFieldCall( const callee = lowerer.lowerUnionProperty(access); if (callee?.type.kind !== "func") return null; const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call)); - return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) }; + const value: IrExpr = { + kind: "callValue", + callee, + args, + type: callee.type.ret, + loc: locOf(call), + }; + // An overloaded member's erased result converts to the resolved + // overload's type, as on a single record receiver below. + return isOverloadedMemberAccess(lowerer, access) + ? lowerer.coerceInto(call, value, resolvedOverloadResultType(lowerer, call)) + : value; } const target = lowerer.fieldTarget(access); const loc = locOf(call); @@ -8297,10 +8431,14 @@ export function lowerRecordFieldCall( type: callee.type.ret, loc, }; - // A generic member's field holds its erased instance: the result - // converts to this call's instantiated return type at the call. - if (isGenericCallableMemberType(lowerer.typeOf(access), lowerer.checker)) + // A generic member's field holds its erased instance, and an overloaded + // member's field its erased function (the overloads joined): the result + // converts to this call's instantiated or resolved return type. + const memberType = lowerer.typeOf(access); + if (isGenericCallableMemberType(memberType, lowerer.checker)) result = lowerer.coerceInto(call, result, lowerer.irTypeOf(call)); + else if (isOverloadedMemberAccess(lowerer, access)) + result = lowerer.coerceInto(call, result, resolvedOverloadResultType(lowerer, call)); return init ? { kind: "seqExpr", stmts: [init], result, type: result.type, loc } : result; } diff --git a/packages/compiler/src/frontend/lowering/lower-classes.ts b/packages/compiler/src/frontend/lowering/lower-classes.ts index d09f40ed8..95282f381 100644 --- a/packages/compiler/src/frontend/lowering/lower-classes.ts +++ b/packages/compiler/src/frontend/lowering/lower-classes.ts @@ -18,6 +18,7 @@ import { builtinClassRefOf, } from "./builtins/class-values.js"; import type { FnCtx, Lowerer } from "./lowerer.js"; +import { inlineNamespaceRequireOf, lowerWithInlineRequireInit } from "./cjs-inline-require.js"; import { BOOL, DATE_T, @@ -50,6 +51,7 @@ import { implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, + genericLocalClassResult, type GenericFnInfo, } from "./generic-functions.js"; import { @@ -228,6 +230,11 @@ export function storedClassValueType( if (value?.kind === "classval") return value; } } + // A generic factory's own local class has one class per instance. + if (ts.isCallExpression(expression)) { + const local = genericLocalClassResult(lowerer, expression); + if (local?.kind === "classval") return local; + } const type = lowerer.typeOf(expression); const mapped = lowerer.mapTypeOf(type); if (mapped?.kind === "classval" && !lowerer.classes.has(mapped.className)) { @@ -8475,6 +8482,14 @@ function isCollectionOrErrorClass(ref: BuiltinClassRef | null): boolean { export function lowerNew(lowerer: Lowerer, expr: ts.NewExpression): IrExpr { const loc = locOf(expr); + // `new (require("./x").C)()`: the module's %init at the require's + // position, then construction through the member as for a binding. + if (ts.isPropertyAccessExpression(expr.expression) && !expr.expression.questionDotToken) { + const req = inlineNamespaceRequireOf(lowerer, expr.expression.expression); + if (req !== null && !lowerer.inlineRequireInitDone.has(req.call)) { + return lowerWithInlineRequireInit(lowerer, req, () => lowerNew(lowerer, expr)); + } + } const worker = lowerWorkerNew(lowerer, expr); if (worker) return worker; const readlineUi = lowerReadlineUiNew(lowerer, expr); diff --git a/packages/compiler/src/frontend/lowering/lower-exprs.ts b/packages/compiler/src/frontend/lowering/lower-exprs.ts index 53cb26093..d052f433a 100644 --- a/packages/compiler/src/frontend/lowering/lower-exprs.ts +++ b/packages/compiler/src/frontend/lowering/lower-exprs.ts @@ -11,6 +11,7 @@ import { lowerWorkerMetadata } from "./builtins/workers.js"; import { esmImportBindingKind } from "./builtins/module-bindings.js"; import { lowerReadlineProperty } from "./builtins/readline.js"; import { lowerBlobInstanceof } from "./builtins/blob.js"; +import { lowerWebAssemblyTypeof, refuseWebAssemblyUse } from "./builtins/webassembly.js"; import { lowerKeyObjectInstanceof } from "./builtins/key-object.js"; import { lowerNetAddressInstanceof, lowerNetAddressStaticRead } from "./builtins/net-address.js"; import { isExecExceptionType, refuseExecExceptionCode } from "./builtins/errors.js"; @@ -45,6 +46,18 @@ import { constituentTypes } from "../ts7/checker.js"; import { dirname } from "node:path"; import * as posix from "node:path/posix"; import type { Lowerer } from "./lowerer.js"; +import { + inlineNamespaceRequireOf, + lowerWithInlineRequireInit, + wholeExportValue, +} from "./cjs-inline-require.js"; +import { tscInteropDefaultValueOf } from "./cjs-tsc-interop.js"; +import { + cjsExportMemberWriteGlobalOf, + cjsInFileExportGlobalOf, + isCjsExportsIdentifier, + lowerCjsExportsObjectValue, +} from "./cjs-exports-object.js"; import { lowerMaybePromiseAwait, maybePromiseInstanceOf, @@ -212,6 +225,7 @@ import { isNodeModuleValue, lowerCjsTopLevelThis, lowerNodeModuleIdentifier, + isCjsModuleGlobal, lowerNodeModuleProperty, lowerRequireCacheElement, lowerRequireCacheHas, @@ -450,6 +464,8 @@ 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. + refuseWebAssemblyUse(lowerer, expr); if (ts.isNumericLiteral(expr)) { const value = Number(expr.text.replace(/_/g, "")); @@ -615,6 +631,8 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { ); } if (ts.isTypeOfExpression(expr)) { + const webAssembly = lowerWebAssemblyTypeof(lowerer, expr.expression); + if (webAssembly) return webAssembly; if (lowerer.isStdlibGlobal(expr.expression, "process")) return { kind: "strLit", value: "object", type: STRING, loc }; if (lowerer.isStdlibGlobal(expr.expression, "fetch")) @@ -867,6 +885,10 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { const moduleValue = lowerNodeModuleIdentifier(lowerer, expr); if (moduleValue) return moduleValue; + if (expr.text === "exports") { + const exportsValue = lowerCjsExportsObjectValue(lowerer, expr); + if (exportsValue) return exportsValue; + } if (lowerer.isSelfReference(expr)) { return { kind: "selfRef", type: lowerer.ctx.selfType!, loc }; } @@ -1860,6 +1882,28 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { if (ts.isConditionalExpression(expr)) return lowerTernary(lowerer, expr); if (ts.isPropertyAccessExpression(expr)) { + // `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). + if (!expr.questionDotToken) { + const req = inlineNamespaceRequireOf(lowerer, expr.expression); + if (req !== null && !lowerer.inlineRequireInitDone.has(req.call)) { + return lowerWithInlineRequireInit(lowerer, req, () => lowerExpr(lowerer, expr)); + } + // `module.exports` compared by identity inside its own module, or + // refused by name as any other value (cjs-exports-object.ts). + if (expr.name.text === "exports") { + const exportsValue = lowerCjsExportsObjectValue(lowerer, expr); + if (exportsValue) return exportsValue; + } + // tsc's `x_1.default` over a dependency whose whole export is one + // value: that value (cjs-tsc-interop.ts). + const interop = tscInteropDefaultValueOf(lowerer, expr); + if (interop !== null) { + const value = wholeExportValue(lowerer, interop.dep, expr); + if (value !== null) return value; + } + } { const member = lifetimeRegionMemberOf(lowerer.program, expr, lowerer.experimentalFiles); if (member !== null) @@ -2206,35 +2250,12 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { // global (pure alias plumbing) and fall through unchanged; write // positions belong to the export-assignment machinery. { - const sf = expr.getSourceFile(); - const cjsMemberRecv = - isModuleExportsAccess(expr.expression) || - (ts.isIdentifier(expr.expression) && - expr.expression.text === "exports" && - !lowerer.resolveLocal(expr.expression) && - !lowerer.globalOf(expr.expression)); const writePos = ts.isBinaryExpression(expr.parent) && expr.parent.left === expr && expr.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken; - if ( - !expr.questionDotToken && - cjsMemberRecv && - !writePos && - isCjsJsFile(sf, lowerer.program) - ) { - const sym = - lowerer.checker.getSymbolAtLocation(expr.name) ?? - lowerer.cjsModuleExportSymbol(sf, expr.name.text); - const resolved = - sym !== undefined && sym.flags & ts.SymbolFlags.Alias - ? lowerer.checker.getAliasedSymbol(sym) - : sym; - const g = - (sym ? lowerer.globalsBySymbol.get(sym) : undefined) ?? - (resolved ? lowerer.globalsBySymbol.get(resolved) : undefined); - if (g) return { kind: "varRef", localId: g.id, type: g.type, loc }; - } + const g = cjsInFileExportGlobalOf(lowerer, expr); + if (g && !writePos) return { kind: "varRef", localId: g.id, type: g.type, loc }; } // Namespace-qualified reads (`N.x`, `A.B.C.f`, import= alias // chains): the member is a compile-time-known declaration of a @@ -2830,6 +2851,23 @@ function lowerExprInner(lowerer: Lowerer, expr: ts.Expression): IrExpr { ); } } + // A member a JavaScript module attached to one of its functions + // (`status.message = codes; module.exports = status`), read from + // TypeScript: JavaScript stores such members on the function's own + // property table (`fn.member = v` writes through the function's + // checked-dynamic face), so the read takes the same path and enters + // the static code at the type inference gave the member. + if (recvLowered.type.kind === "func" && jsFunctionExpandoMember(lowerer, expr)) { + const read: IrExpr = { + kind: "dynKeyGet", + value: lowerer.coerceToExpected(recvLowered, DYN), + key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) }, + type: DYN, + loc, + }; + const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr)); + return mapped && mapped.kind !== "void" ? lowerer.coerceInto(expr, read, mapped) : read; + } lowerer.unsupported( "SC1090", expr, @@ -10230,6 +10268,35 @@ export function lowerBinary(lowerer: Lowerer, expr: ts.BinaryExpression): IrExpr // RHS value is the expression's value — its OWN type, so the // consumer sees exactly what the checker typed. if (ts.isPropertyAccessExpression(expr.left) && !expr.left.questionDotToken) { + // `const src = exports.src = []`: an export member assigned in + // value position writes its export global and yields the value. + { + let inFunction = false; + for (let p: ts.Node | undefined = expr.parent; p !== undefined; p = p.parent) { + if (ts.isFunctionLike(p) || ts.isClassDeclaration(p) || ts.isClassExpression(p)) { + inFunction = true; + break; + } + } + const g = inFunction + ? cjsExportMemberWriteGlobalOf(lowerer, expr.left) + : cjsInFileExportGlobalOf(lowerer, expr.left); + if (g) { + const value = lowerer.lowerExprExpecting(expr.right, g.type); + const tmp = lowerer.declareHiddenLocal("%exportValue", value.type); + const result = varRef(tmp.id, value.type, loc); + return { + kind: "seqExpr", + stmts: [ + { kind: "varDecl", localId: tmp.id, init: value, loc }, + { kind: "assign", localId: g.id, value: result, loc }, + ], + result, + type: value.type, + loc, + }; + } + } const recv = tryLowerExpression(lowerer, expr.left.expression); if (recv && recv.type.kind === "dyn") return lowerDynMemberAssignment(lowerer, expr, recv); const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right); @@ -10339,6 +10406,7 @@ export function lowerBinary(lowerer: Lowerer, expr: ts.BinaryExpression): IrExpr op === ts.SyntaxKind.ExclamationEqualsEqualsToken ) { const test = + lowerWebAssemblyTypeofTest(lowerer, expr, loc) ?? lowerErrorCodeTypeofTest(lowerer, expr, loc) ?? lowerer.lowerCaughtTypeofTest(expr, loc) ?? lowerDynTypeofTest(lowerer, expr, loc) ?? @@ -11731,6 +11799,24 @@ function errorRootedObjectOf(lowerer: Lowerer, t: ts.Type): IrType | null { return null; } +/** `typeof WebAssembly === "object"` and `typeof WebAssembly. === + * "function"`: the operand needs no value, so the test folds as bare typeof + * does (builtins/webassembly.ts) before any dyn-typed operand lowers. */ +function lowerWebAssemblyTypeofTest( + lowerer: Lowerer, + expr: ts.BinaryExpression, + loc: SrcLoc, +): IrExpr | null { + const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken; + for (const [a, b] of operandPairs(expr)) { + if (!ts.isTypeOfExpression(a) || !ts.isStringLiteral(b)) continue; + const folded = lowerWebAssemblyTypeof(lowerer, a.expression); + if (folded?.kind !== "strLit") continue; + return { kind: "boolLit", value: (folded.value === b.text) !== negated, type: BOOL, loc }; + } + return null; +} + /** `typeof e.code === "string"` / `"undefined"` (and the `!==` forms) * where e — through parens and as-casts — is a catch binding or a value * of %Error-rooted type: the runtime error's code slot is a string @@ -12428,6 +12514,7 @@ export function caughtLocalOf(lowerer: Lowerer, node: ts.Expression): IrLocal | * 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 { + 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. const sockTest = lowerSocketInstanceOf(lowerer, expr, loc); @@ -15089,6 +15176,9 @@ export function fieldTarget( access: ts.PropertyAccessExpression, ): FieldTarget | null { if (lowerer.cjsLocalModuleBindingOf(access.expression)) return null; + // `module.exports` / `module.id`: CommonJS module surface, never a field. + if (isCjsModuleGlobal(lowerer, access.expression)) return null; + if (isCjsExportsIdentifier(lowerer, access.expression)) return null; if (lowerer.chainBlocked(access)) return null; if ( access.name.text === "stackTraceLimit" && @@ -16379,3 +16469,28 @@ function isBuiltinModuleValueDecl(decl: ts.Node): boolean { ts.isVariableDeclaration(decl)) ); } + +/** True when `access` reads a member that JavaScript sources attach to a + * function by assignment (`fn.member = value`): the receiver's type is + * callable and every declaration of the member is such an assignment in a + * JS file. */ +function jsFunctionExpandoMember(lowerer: Lowerer, access: ts.PropertyAccessExpression): boolean { + if (access.questionDotToken || !ts.isIdentifier(access.name)) return false; + const recvType = lowerer.typeOf(access.expression); + if (lowerer.checker.getCallSignatures(recvType).length === 0) return false; + const member = lowerer.checker.getPropertyOfType(recvType, access.name.text); + const decls = member ? lowerer.checker.declarationsOf(member) : []; + return ( + decls.length > 0 && + decls.every((d) => { + if (!isJsSourceFile(d.getSourceFile())) return false; + const assign = ts.isBinaryExpression(d) ? d : d.parent; + return ( + assign !== undefined && + ts.isBinaryExpression(assign) && + assign.operatorToken.kind === ts.SyntaxKind.EqualsToken && + ts.isPropertyAccessExpression(assign.left) + ); + }) + ); +} diff --git a/packages/compiler/src/frontend/lowering/lower-generators.ts b/packages/compiler/src/frontend/lowering/lower-generators.ts index 2eda4c4ce..a9b467a6a 100644 --- a/packages/compiler/src/frontend/lowering/lower-generators.ts +++ b/packages/compiler/src/frontend/lowering/lower-generators.ts @@ -115,6 +115,16 @@ export function lowerGenMethodCall( if (call.arguments.some(ts.isSpreadElement)) { lowerer.unsupported("SC1090", call, "spread arguments"); } + // Iterator helpers and the built-in iterators have no throw method; an + // iterator-typed value may hold one, so only a generator's own member + // lowers. + if (name === "throw" && !isGeneratorMember(lowerer, access)) { + lowerer.noLowering( + `${lowerer.checker.typeToString(lowerer.typeOf(access.expression))}.throw`, + call, + "throw() lowers on values typed as generators (iterator helpers and built-in iterators have no throw method)", + ); + } const loc = locOf(call); const gen = lowerer.lowerExpr(access.expression); if (gen.type.kind !== "generator") return null; @@ -187,6 +197,23 @@ export function lowerGenMethodCall( return { kind: "genResume", mode: name, gen, arg, type: resultT, loc }; } +/** Whether `access` names a member the lib declares on Generator or + * AsyncGenerator itself. */ +function isGeneratorMember(lowerer: Lowerer, access: ts.PropertyAccessExpression): boolean { + const member = lowerer.checker.getSymbolAtLocation(access.name); + return ( + member !== undefined && + lowerer.checker + .declarationsOf(member) + .some( + (d) => + ts.isInterfaceDeclaration(d.parent) && + (d.parent.name.text === "Generator" || d.parent.name.text === "AsyncGenerator") && + lowerer.isStdlibFile(d.getSourceFile()), + ) + ); +} + /** Extraction of a suspended resume's yield value out of the result * record's V slot, typed back to the yield channel: V IS the channel for * dyn (and for a union channel already equal to V); a non-union channel @@ -319,7 +346,7 @@ export function genValue(gen: IrExpr & { type: GenType }, loc: SrcLoc): IrExpr { return { kind: "genResume", mode: "value", gen, arg: null, type: gen.type.yieldT, loc }; } -function generatorLoopBinding( +export function generatorLoopBinding( lowerer: Lowerer, stmt: ts.ForOfStatement, value: IrExpr, @@ -572,7 +599,9 @@ export function lowerForOfGenerator( catchBody: null, catchLocalId: null, // IteratorClose: every exit that leaves the generator unfinished - // closes it — finallys run; the .return() result is dropped. + // closes it — finallys run; the .return() result is dropped, and + // after a throw from the body an error from the close is too. + dropFinallyErrors: true, finallyBody: [ { kind: "if", diff --git a/packages/compiler/src/frontend/lowering/lower-modules.ts b/packages/compiler/src/frontend/lowering/lower-modules.ts index 3c035cd45..b375668bc 100644 --- a/packages/compiler/src/frontend/lowering/lower-modules.ts +++ b/packages/compiler/src/frontend/lowering/lower-modules.ts @@ -18,7 +18,9 @@ import { isRelativeSpecifier } from "../workspace-registry.js"; import { canonicalBuiltinModule, cjsExportAssignmentOf, + cjsExportChainOf, cjsExportDiscardReason, + cjsExportTargetLiteral, entryPackageFilePredicate, isCjsJsFile, isJsSourceFile, @@ -26,6 +28,7 @@ import { locOf, makeCycleAdmission, orderedImportsOf, + requireSpecOf, resolveImport, resolveNpmImport, } from "../program.js"; @@ -36,6 +39,13 @@ import { withCycleInitFlags, } from "./cycle-initialization.js"; import { markRequireEarlyBindings } from "./require-initialization.js"; +import { + cjsTableMethodEntry, + inlineProgramRequireOf, + nestedCjsExportAssignmentsOf, + requireNestedPatternsOf, +} from "./cjs-inline-require.js"; +import { isDeadTscHelperDecl, tscInteropBindingOfDecl } from "./cjs-tsc-interop.js"; import { collectJsonRequires, isJsonRequireDecl } from "./json-require.js"; import { invalidJsonModuleDiag, @@ -1391,6 +1401,11 @@ export function collectGlobals( deferJsCollectionDiags(lowerer, sf, diagsBefore); } }; + // Export members assigned in VALUE position at the module's top + // level (`const src = exports.src = []`) are exports too. + for (const nested of nestedCjsExportAssignmentsOf(stmt, cjs?.expr)) { + registerExport(nested.name, nested.name.text, nested.value); + } if (cjs?.kind === "member" && ts.isIdentifier(cjs.name)) { // `exports.C = C` naming a CLASS declaration: alias plumbing — // no storage (a class VALUE global would fence for @@ -1398,6 +1413,13 @@ export function collectGlobals( // symbol (cjsMemberExportClassSymbol) and the class registry // applies unchanged. if (lowerer.cjsMemberExportClassSymbol(cjs.expr) !== null) continue; + // A chain `exports.a = exports.b = value`: every member is an + // export holding the chain's one value. + const chain = cjsExportChainOf(cjs.expr); + if (chain !== null) { + for (const nameNode of chain.names) registerExport(nameNode, nameNode.text, chain.value); + continue; + } registerExport(cjs.name, cjs.name.text, cjs.value); continue; } @@ -1429,7 +1451,22 @@ export function collectGlobals( // statement lowering evaluates the call exactly once at its // source position and assigns that slot. Unmappable calls retain // the existing statement-level fence. - const factoryValued = ts.isCallExpression(rhs); + // Any other computed value (`os.homedir || function () {…}`, + // `cond ? a : b`, `new Registry()`, `ns.member`) is the same single + // snapshot: Node stores whatever the expression produced. A + // require() of a program module is not: the exporter re-exports + // that module's exports, which requirers resolve through the + // checker's alias (the statement lowers to the dep's %init). + const factoryValued = + !ts.isIdentifier(rhs) && + !ts.isClassExpression(rhs) && + !ts.isObjectLiteralExpression(rhs) && + !( + requireSpecOf(rhs) !== null && + inlineProgramRequireOf(lowerer, rhs) !== null && + !sf.statements.some((s) => cjsExportAssignmentOf(s)?.kind === "member") + ) && + cjsExportTargetLiteral(rhs, sf) === null; if (cjsScalarLiteral(rhs) || fnValued || factoryValued) { const diagsBefore = lowerer.diags.length; try { @@ -1464,6 +1501,10 @@ export function collectGlobals( if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) { registerExport(prop.name, prop.name.text, prop.initializer); } + // A METHOD entry (`module.exports = { f(x) { … } }`) is an + // expression-valued export whose value is the method's function. + const method = cjsTableMethodEntry(prop); + if (method !== null) registerExport(method.name, method.name.text, method.name); // other property forms fence in the statement lowering } continue; @@ -1527,6 +1568,16 @@ export function collectGlobals( collectNestedVarGlobals(lowerer, sf, stmt, tag); continue; } + // tsc's interop bindings and its then-dead helper declarations own no + // storage either (cjs-tsc-interop.ts). + if ( + isJsSourceFile(sf) && + (isDeadTscHelperDecl(lowerer, stmt) || + (stmt.declarationList.declarations.length === 1 && + tscInteropBindingOfDecl(lowerer, stmt.declarationList.declarations[0]!) !== null)) + ) { + continue; + } // CommonJS require declarations are alias plumbing (preflight owns // the module edges; resolveValueSymbol routes reads through to the // exporter's declarations): no storage, and the statement lowers to @@ -1549,6 +1600,38 @@ export function collectGlobals( stdlibGlobalAliasDecl(lowerer, decl.name, decl.initializer); } } + // `const { codes: { ERR_X } } = require("./errors")`: the outer + // keys stay alias plumbing, but a nested pattern destructures the + // export's value at the require, so its bindings own storage like + // any destructured declaration (lowerVarDeclarator assigns them). + if (ts.isVariableStatement(stmt)) { + const isLetList = + (stmt.declarationList.flags & ts.NodeFlags.Let) !== 0 || + (stmt.declarationList.flags & ts.NodeFlags.BlockScoped) === 0; + for (const decl of stmt.declarationList.declarations) { + for (const element of requireNestedPatternsOf(decl)) { + for (const nameNode of boundIdentifiersOf(element.name!)) { + const symbol = lowerer.checker.getSymbolAtLocation(nameNode); + if (!symbol || lowerer.globalsBySymbol.has(symbol)) continue; + const mapped = lowerer.mapTypeOf(lowerer.typeOf(nameNode)); + const type = mapped && mapped.kind !== "void" ? mapped : DYN; + const g: IrGlobal = { + id: `%g.${tag}${nameNode.text}`, + name: nameNode.text, + type, + mutable: isLetList, + source: bindingSource(nameNode), + ...((type.kind === "func" || type.kind === "dyn") && !isVarDeclared(decl) + ? { tdz: true as const } + : {}), + }; + lowerer.globalsBySymbol.set(symbol, g); + lowerer.globalsList.push(g); + if (isVarDeclared(decl)) noteVarGlobalEntryInit(lowerer, sf, g); + } + } + } + } continue; } // `declare const __VERSION__: string` — AMBIENT: no storage exists diff --git a/packages/compiler/src/frontend/lowering/lower-node-module.ts b/packages/compiler/src/frontend/lowering/lower-node-module.ts index c15749601..292b38e87 100644 --- a/packages/compiler/src/frontend/lowering/lower-node-module.ts +++ b/packages/compiler/src/frontend/lowering/lower-node-module.ts @@ -8,6 +8,7 @@ import * as win32 from "node:path/win32"; import * as ts from "../ts7/adapter.js"; import type { Lowerer } from "./lowerer.js"; import type { FileParts } from "./lower-modules.js"; +import { lowerCjsExportsObjectValue } from "./cjs-exports-object.js"; import { isCjsJsFile, isNodeEsmFile, locOf } from "../program.js"; import { runtimePathForTarget } from "../runtime-resolve.js"; import { @@ -177,6 +178,12 @@ export function cjsModuleRef(lowerer: Lowerer, node: ts.Node): IrExpr | null { return id === undefined ? null : numLit(id, locOf(node)); } +/** True when `node` is the CommonJS `require` global (not shadowed by a + * source binding, and not in an ES module). */ +export function isCjsRequireGlobal(lowerer: Lowerer, node: ts.Expression): boolean { + return cjsGlobal(lowerer, node, "require"); +} + export function isCjsModuleGlobal(lowerer: Lowerer, node: ts.Expression): boolean { return cjsGlobal(lowerer, node, "module"); } @@ -428,6 +435,13 @@ export function lowerNodeModuleIdentifier(lowerer: Lowerer, expr: ts.Identifier) if (!isCjsModuleGlobal(lowerer, expr)) return null; const ref = cjsModuleRef(lowerer, expr); if (ref) return ref; + if (isCjsJsFile(expr.getSourceFile(), lowerer.program)) { + lowerer.unsupported( + "SC1090", + expr, + "the CommonJS 'module' object in this position (module.exports members, the whole module.exports in comparisons, and the module metadata fields lower)", + ); + } lowerer.unsupported("SC1090", expr, "the CommonJS 'module' object in an ES module"); } @@ -441,6 +455,10 @@ export function lowerNodeModuleProperty( const member = expr.name.text; if (member === "exports" && direct && moduleExportsAlwaysTruthy(lowerer, expr)) return boolLit(true, locOf(expr)); + if (member === "exports" && direct) { + const value = lowerCjsExportsObjectValue(lowerer, expr); + if (value) return value; + } if (member === "exports" || member === "require") return null; let moduleRef = direct ? cjsModuleRef(lowerer, expr.expression) diff --git a/packages/compiler/src/frontend/lowering/lower-stmts.ts b/packages/compiler/src/frontend/lowering/lower-stmts.ts index 57e6c2311..dbfa30f63 100644 --- a/packages/compiler/src/frontend/lowering/lower-stmts.ts +++ b/packages/compiler/src/frontend/lowering/lower-stmts.ts @@ -15,6 +15,19 @@ import { requireInitFlagStmt } from "./require-initialization.js"; import { isJsonRequireDecl } from "./json-require.js"; import { bindingSource } from "../binding-source.js"; import type { Lowerer } from "./lowerer.js"; +import { + cjsExportValueByName, + cjsNamespaceDestructureOf, + cjsTableMethodEntry, + inlineProgramRequireOf, + requireNestedPatternsOf, +} from "./cjs-inline-require.js"; +import { + cjsExportMemberWriteGlobalOf, + isCjsExportsIdentifier, + isFreshExportsReset, +} from "./cjs-exports-object.js"; +import { isDeadTscHelperDecl, tscInteropBindingOfDecl } from "./cjs-tsc-interop.js"; import { arrayValueRead, arrayValueStore, @@ -60,6 +73,7 @@ import { import { enforceLibBoundary, lowerSurplusCalls } from "./lib-boundary.js"; import { cjsExportAssignmentOf, + cjsExportChainOf, cjsExportDiscardReason, cjsExportTargetLiteral, isCjsJsFile, @@ -97,6 +111,7 @@ import { lowerForOfSearchParams, lowerForOfSet, } from "./containers/for-of.js"; +import { lowerForOfHelperChain } from "./containers/iterator-helpers.js"; import { objectIterOverIndexShape } from "./containers/indexed-objects.js"; import { strCharsCall } from "./containers/array-construction.js"; import { @@ -107,6 +122,7 @@ import { implicitLocalFnInfoOf, implicitLocalFnNodeOf, implicitMethodCallInfersReturn, + genericLocalClassBinding, } from "./generic-functions.js"; import { bindingNeverReassigned, @@ -663,10 +679,14 @@ export function lowerStmts(lowerer: Lowerer, stmts: readonly ts.Statement[]): Ir out, }; lowerer.activeStmtLists.push(entry); + const inFunction = stmts.length > 0 && enclosedByFunction(stmts[0]!); + let unreachable = false; try { for (let i = 0; i < stmts.length; i++) { const stmt = stmts[i]!; entry.index = i; + if (unreachable && skipsWhenUnreachable(stmt)) continue; + if (inFunction && isAbruptStatement(stmt)) unreachable = true; if (!lowerer.suppressStats) { lowerer.stats.statementsTotal++; if (sf !== undefined) lowerer.bumpFileStat(sf.fileName, "total"); @@ -788,6 +808,54 @@ export function lowerStmts(lowerer: Lowerer, stmts: readonly ts.Statement[]): Ir return out; } +/** Whether a statement list belongs to a function body (at any block + * depth) rather than to a module's top level. */ +function enclosedByFunction(stmt: ts.Statement): boolean { + let owner: ts.Node | undefined = stmt.parent; + while (owner !== undefined && !ts.isFunctionLike(owner) && !ts.isSourceFile(owner)) + owner = owner.parent; + return owner !== undefined && ts.isFunctionLike(owner); +} + +/** `return`, `throw`, `break` and `continue`: the rest of the enclosing + * statement list never runs. */ +function isAbruptStatement(stmt: ts.Statement): boolean { + return ( + ts.isReturnStatement(stmt) || + ts.isThrowStatement(stmt) || + ts.isBreakStatement(stmt) || + ts.isContinueStatement(stmt) + ); +} + +/** Statements after an abrupt statement in a function body that lowering + * skips: they never execute, so neither their unsupported constructs nor the + * functions they reference become part of the program (production builds of + * libraries keep development-only code behind `throw` stubs this way). + * Hoisting keeps its meaning: a reference above the abrupt statement to a + * later function declaration lowers that declaration eagerly + * (predeclareForwardFnDecl), and references to a later `var`, `let` or + * `const` binding resolve through the forward-hoisting machinery to its + * undefined or TDZ state, which skipping its initializer preserves. Class, + * enum, module and import/export declarations and generic function + * declarations still lower. */ +function skipsWhenUnreachable(stmt: ts.Statement): boolean { + if (ts.isFunctionDeclaration(stmt)) return stmt.typeParameters === undefined; + if (ts.isVariableStatement(stmt)) + return !(stmt.modifiers ?? []).some((m) => m.kind === ts.SyntaxKind.ExportKeyword); + return !( + ts.isClassDeclaration(stmt) || + ts.isEnumDeclaration(stmt) || + ts.isModuleDeclaration(stmt) || + ts.isImportDeclaration(stmt) || + ts.isImportEqualsDeclaration(stmt) || + ts.isExportDeclaration(stmt) || + ts.isExportAssignment(stmt) || + ts.isInterfaceDeclaration(stmt) || + ts.isTypeAliasDeclaration(stmt) + ); +} + const TDZ_KINDS = new Set([ "func", "string", @@ -1556,6 +1624,16 @@ function lowerVarDeclarator( const init = lowerer.requireInitStmt(target.spec, decl); return init ? [init] : []; } + // tsc's interop bindings (`const x_1 = __importDefault(require("./m"))`) + // are require bindings (cjs-tsc-interop.ts): the module's %init here. + if (ts.isSourceFile(stmt.parent)) { + const interop = tscInteropBindingOfDecl(lowerer, decl); + if (interop !== null) { + const init = lowerer.requireInitStmt(interop.spec, decl); + return init ? [init] : []; + } + if (isDeadTscHelperDecl(lowerer, stmt)) return []; + } // CommonJS require declarations (JS files): at the module's top // level the BINDINGS are alias plumbing (no storage; // resolveValueSymbol routes the reads), but the require itself is @@ -1576,7 +1654,21 @@ function lowerVarDeclarator( if (lowerer.externalTypes.has(spec)) lowerer.externalHostFence(spec, decl, false); if (ts.isSourceFile(stmt.parent)) { const init = lowerer.requireInitStmt(spec, decl); - return init ? [init] : []; + const out: IrStmt[] = init ? [init] : []; + // Nested patterns destructure the named export's value right after + // the module evaluated (`const { codes: { ERR_X } } = require(...)`). + for (const element of requireNestedPatternsOf(decl)) { + const key = element.propertyName as ts.Identifier; + const value = lowerer.lowerExpr(key); + lowerer.lowerBindingPattern( + element.name as ts.ObjectBindingPattern, + () => lowerer.lowerExpr(key), + value.type, + isLet, + out, + ); + } + return out; } // A nested BUILTIN require (`get inFreeBSDJail() { const { execSync } // = require('child_process'); ... }` — test/common's lazy-getter @@ -1605,6 +1697,35 @@ function lowerVarDeclarator( // `const { createSign } = crypto` over a builtin NAMESPACE binding: // alias plumbing (builtinImportOf routes the reads) — no statement. if (builtinNamespaceDestructureModuleOf(lowerer, decl) !== null) return []; + // `const { A, B } = ns` over a CommonJS module binding: each name + // snapshots the named export's value here (cjs-inline-require.ts). + { + const nsDestructure = cjsNamespaceDestructureOf(lowerer, decl); + if (nsDestructure !== null) { + const out: IrStmt[] = []; + for (const element of nsDestructure.elements) { + const target = lowerer.globalOf(element.name); + const value = cjsExportValueByName(lowerer, nsDestructure.dep, element.key, element.name); + if (target === null || value === null) { + lowerer.unsupported( + "SC1090", + element.name, + `destructuring the export '${element.key}' of a CommonJS module binding (it has no static value)`, + ); + } + out.push({ + kind: "assign", + localId: target.id, + value: typeEquals(value.type, target.type) + ? value + : lowerer.coerceInto(element.name, value, target.type), + loc: locOf(element.name), + ...("tdz" in target && target.tdz ? { initializes: true as const } : {}), + }); + } + return out; + } + } return lowerer.lowerDestructuringDecl(decl, isLet); } // STORED protocol values with statically closed representations: @@ -4913,6 +5034,9 @@ export function lowerVarDecl( ) { type = init.type; } + // `const B = factory(1)` inside a generic instance: the factory's local + // class for the instance the call names. + if (!type && !isLet) type = genericLocalClassBinding(lowerer, decl.name); if (!type) { // The JS declaration fallback (irTypeOf's story): the binding holds // the checked-dynamic kind when even the initializer's type has no @@ -6054,6 +6178,49 @@ function lowerCjsExportStatement( if (whole?.kind !== "table" || cjsExportDiscardReason(stmt) !== null) continue; root = lowerer.globalsByDeclNode.get(whole.expr); } + // A CHAIN `exports.a = exports.b = value`: Node evaluates the value + // once, assigns the innermost member first, and every member holds + // the same value. Each member is its own export global + // (collectGlobals registers the inner ones too). + { + const chain = cjsExportChainOf(cjs.expr); + if (chain !== null && root?.type.kind !== "dyn") { + const globalOfName = (nameNode: ts.Identifier): IrGlobal => { + const symbol = + lowerer.checker.getSymbolAtLocation(nameNode) ?? + lowerer.cjsModuleExportSymbol(sf, nameNode.text); + const g = symbol ? lowerer.globalsBySymbol.get(symbol) : undefined; + if (!g) { + lowerer.lowerExpr(chain.value); + lowerer.badType(chain.value, lowerer.typeOf(chain.value)); + } + return g; + }; + const inner = chain.names[chain.names.length - 1]!; + const innerG = globalOfName(inner); + const body: IrStmt[] = [ + { + kind: "assign", + localId: innerG.id, + value: lowerer.lowerExprExpecting(chain.value, innerG.type), + loc: locOf(chain.value), + }, + ]; + for (let i = chain.names.length - 2; i >= 0; i--) { + const g = globalOfName(chain.names[i]!); + const read: IrExpr = { kind: "varRef", localId: innerG.id, type: innerG.type, loc }; + body.push({ + kind: "assign", + localId: g.id, + value: typeEquals(g.type, innerG.type) + ? read + : lowerer.coerceInto(chain.value, read, g.type), + loc, + }); + } + return { kind: "block", body, loc }; + } + } return assignExport(cjs.name, cjs.value, root); } let tableObj = cjs.obj; @@ -6119,6 +6286,30 @@ function lowerCjsExportStatement( body.push(assignExport(prop.name, prop.initializer)); continue; } + // METHOD entries: the export global holds the method's function, + // created at this statement like a function-expression entry. Node + // calls it with `this` bound to the table, which the static export + // table cannot represent, so a body that uses `this` keeps a fence. + { + const method = cjsTableMethodEntry(prop); + if (method !== null && !resolvedTarget) { + lowerer.rejectThisInObjectMethod(method.body); + const symbol = + lowerer.checker.getSymbolAtLocation(method.name) ?? + lowerer.cjsModuleExportSymbol(cjs.expr.getSourceFile(), method.name.text); + const g = symbol ? lowerer.globalsBySymbol.get(symbol) : undefined; + if (g) { + const fn = lowerer.lowerLambda(method); + body.push({ + kind: "assign", + localId: g.id, + value: typeEquals(fn.type, g.type) ? fn : lowerer.coerceInto(method, fn, g.type), + loc: locOf(method), + }); + continue; + } + } + } // ACCESSOR entries: no storage and no code here — reads lift the // getter as a module-level function and call it per read // (cjsExportAccessorRead); writes through the setter keep their @@ -6134,7 +6325,15 @@ function lowerCjsExportStatement( if (ts.isSpreadAssignment(prop)) { let inner: ts.Expression = prop.expression; while (ts.isParenthesizedExpression(inner)) inner = inner.expression; - if (requireSpecOf(inner) !== null) continue; + if (requireSpecOf(inner) !== null) { + // The spread still EVALUATES the module, at its place among the + // table's entries (a program module joins the graph through this + // inline require; cjs-inline-require.ts). + const req = inlineProgramRequireOf(lowerer, inner); + const init = req !== null ? lowerer.requireInitStmt(req.spec, req.call) : null; + if (init !== null && !resolvedTarget) body.push(init); + continue; + } } lowerer.unsupported( "SC1090", @@ -6167,6 +6366,16 @@ function lowerCjsSingleValueExport( ): IrStmt | null { let rhs: ts.Expression = expr.right; while (ts.isParenthesizedExpression(rhs)) rhs = rhs.expression; + // `module.exports = require("./x")`: the module re-exports x's exports. + // Requirers resolve through the checker's alias to x's own export + // machinery; this statement is x's evaluation at this position. + { + const req = inlineProgramRequireOf(lowerer, rhs); + // With later member exports (`module.exports.extra = …`) the module + // extends that object, so it keeps the factory root registration. + if (req !== null && !lowerer.globalsByDeclNode.has(expr)) + return lowerer.requireInitStmt(req.spec, req.call) ?? { kind: "block", body: [], loc }; + } if (ts.isIdentifier(rhs)) { const sym = lowerer.resolveValueSymbol(rhs); if (!sym) return null; @@ -6177,6 +6386,17 @@ function lowerCjsSingleValueExport( ) { return { kind: "block", body: [], loc }; } + // A require binding (`const x = require("./x"); module.exports = x`) + // re-exports that module exactly like the inline form (the binding's + // own statement already evaluated it), and a builtin global + // (`module.exports = TypeError`) is the global itself: requirer + // bindings alias straight through to it, so nothing is stored. + if ( + lowerer.checker.declarationsOf(sym).some((d) => ts.isSourceFile(d)) || + lowerer.isStdlibSymbol(sym) + ) { + return { kind: "block", body: [], loc }; + } const g = lowerer.globalsBySymbol.get(sym); if (g) { if (g.mutable) { @@ -6398,6 +6618,21 @@ export function lowerExprStatement(lowerer: Lowerer, expr: ts.Expression): IrStm ); } if (topLevelJs && ts.isExpressionStatement(stmtNode)) { + if (isFreshExportsReset(lowerer, stmtNode)) + return { kind: "block", body: [], loc: locOf(expr) }; + // Any other `exports = …` rebinds the wrapper's exports binding: the + // members later attached through it belong to the new value. + if ( + ts.isBinaryExpression(expr) && + expr.operatorToken.kind === ts.SyntaxKind.EqualsToken && + isCjsExportsIdentifier(lowerer, expr.left) + ) { + lowerer.unsupported( + "SC1090", + expr.left, + "rebinding 'exports' (exports = module.exports = value): members attached through 'exports' afterwards are properties of that value, which the static export table does not model — write module.exports. = … and module.exports = value", + ); + } const cjs = cjsExportAssignmentOf(stmtNode); if (cjs) return lowerCjsExportStatement(lowerer, cjs); // The tsc CJS interop stamp — `Object.defineProperty(exports, @@ -6939,6 +7174,19 @@ export function lowerExprStatement(lowerer: Lowerer, expr: ts.Expression): IrStm const parts = lowerDestructuringAssignParts(lowerer, expr.left, expr.right, locOf(expr)); return { kind: "block", body: parts.stmts, loc: locOf(expr) }; } + // `exports.x = v` inside a function updates the member's export + // global (cjs-exports-object.ts). + if (ts.isPropertyAccessExpression(expr.left)) { + const g = cjsExportMemberWriteGlobalOf(lowerer, expr.left); + if (g) { + return { + kind: "assign", + localId: g.id, + value: lowerer.lowerExprExpecting(expr.right, g.type), + loc: locOf(expr), + }; + } + } if (!ts.isIdentifier(expr.left)) { lowerer.unsupported("SC1090", expr.left, "assignment to non-variables"); } @@ -8299,6 +8547,12 @@ export function lowerForOf(lowerer: Lowerer, stmt: ts.ForOfStatement): IrStmt { } } } + // A head that is a chain of iterator-helper stages runs as one loop + // over the chain's source. + { + const fused = lowerForOfHelperChain(lowerer, stmt, labels); + if (fused) return fused; + } // `for (const k of m.keys())` / `.values()` / `.entries()`: the // iterator methods consumed DIRECTLY by a for-of head ride the // container's live walk — exactly `for..of m` with the projection diff --git a/packages/compiler/src/frontend/lowering/lowerer.ts b/packages/compiler/src/frontend/lowering/lowerer.ts index f7b5febcc..4b17af697 100644 --- a/packages/compiler/src/frontend/lowering/lowerer.ts +++ b/packages/compiler/src/frontend/lowering/lowerer.ts @@ -26,6 +26,9 @@ 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 { discoverWasmModules, type WasmModuleReport } from "../../wasm/discover.js"; +import { resolveRequireRuntime } from "../runtime-resolve.js"; import { lowerKeyObjectCall } from "./builtins/key-object.js"; import { hashStreamOf } from "./builtins/hash-stream.js"; import { lowerNetAddressCall, lowerNetAddressNew } from "./builtins/net-address.js"; @@ -231,9 +234,11 @@ import { containsUnion, describeComponentBlocker, describeRecordMemberBlocker, + erasedOverloadMemberType, formatIrType, FETCH_AMBIENT_TYPES, isOsConstantsSymbol, + isOverloadedCallableMemberType, isUnitOnlyTsType, isWorkerHandleType, jsOpenObjectType, @@ -281,6 +286,13 @@ import { appendWorkerModules, } from "./lower-modules.js"; import { prepareCjsModuleGraph, usesCjsTopLevelThis } from "./lower-node-module.js"; +import { + cjsNamespaceModule, + inlineNamespaceRequireOf, + inlineProgramRequireOf, +} from "./cjs-inline-require.js"; +import { tscInteropModuleOf } from "./cjs-tsc-interop.js"; +import { usesCjsExportsIdentity } from "./cjs-exports-object.js"; import { registerBuiltinEventTargetClasses } from "./lower-event-target.js"; import { type ClassInfo, @@ -367,6 +379,7 @@ import { lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, + genericLocalClassBinding, } from "./generic-functions.js"; import { bindingNeverReassigned } from "./binding-analysis.js"; import type { InstantiationPath } from "./instantiation-path.js"; @@ -719,6 +732,8 @@ export interface LowerResult { /** Coverage only (LowerOptions.coverage): the unreached remainder, * lowered in a throwaway pass — blockers in it can never fail a build. */ unreached?: { diagnostics: ScrDiagnostic[]; stats: LowerStats; runtimeFences?: ScrDiagnostic[] }; + /** Coverage only: the WebAssembly modules the build can see (wasm/discover.ts). */ + wasmModules?: WasmModuleReport[]; /** Compile-time-detectable behavior differences from Node (SC6xxx * divergence warnings) in the program's own modules. Never failures. */ divergences?: ScrDiagnostic[]; @@ -739,6 +754,8 @@ export interface LowerOptions { * diagnostics and stats under `unreached` — the whole-program analysis * builds deliberately gave up. */ coverage?: boolean; + /** Coverage only: module files named by --wasm (absolute). */ + wasmFiles?: readonly string[]; /** The platform the build TARGETS ("win32" under a windows cross triple, * the host platform otherwise — see buildTargetPlatform in index.ts). * The whole program compiles for one platform, so the platform-keyed @@ -751,6 +768,8 @@ export interface LowerOptions { * resolution walk and named-import link checks): the program * compiles to that startup crash. */ startupCrash?: StartupCrash | null; + /** LoadResult.inlineRequireCycleCalls. */ + inlineRequireCycleCalls?: ReadonlySet | undefined; /** LIBRARY mode's reachability roots: the profile-mapped exports of the * entry module. Executable builds root at the entry's top level alone * (an unreferenced export dead-strips); a library's exports are called from @@ -843,6 +862,8 @@ export interface LowererMode { * module init — Node refuses the whole graph before anything evaluates, * so nothing runs. */ startupCrash?: StartupCrash | null; + /** LoadResult.inlineRequireCycleCalls. */ + inlineRequireCycleCalls?: ReadonlySet | undefined; /** The build's outbound native FFI declarations. */ ffiImports?: readonly IrFfiImport[]; /** LowerOptions.libraryCallbacks (see there). */ @@ -956,6 +977,7 @@ export function lowerToIr( projectCheckJs: options.projectCheckJs ?? false, targetPlatform, startupCrash, + inlineRequireCycleCalls: options.inlineRequireCycleCalls, ffiImports, libraryCallbacks, forkTargets, @@ -979,6 +1001,7 @@ export function lowerToIr( projectCheckJs: options.projectCheckJs ?? false, targetPlatform, startupCrash, + inlineRequireCycleCalls: options.inlineRequireCycleCalls, ffiImports, libraryCallbacks, forkTargets, @@ -1009,6 +1032,7 @@ export function lowerToIr( reachable, targetPlatform, startupCrash, + inlineRequireCycleCalls: options.inlineRequireCycleCalls, ffiImports, libraryCallbacks, forkTargets, @@ -1067,6 +1091,7 @@ export function lowerToIr( reachable, remainder: true, alreadyFlushed: resultLowerer.flushedSymbols, + inlineRequireCycleCalls: options.inlineRequireCycleCalls, targetPlatform, ffiImports, libraryCallbacks, @@ -1112,6 +1137,23 @@ 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; + }, + }); + timing("wasm-discovery", { modules: wasmModules.length }); + if (wasmModules.length > 0) covered.wasmModules = wasmModules; return covered; } @@ -1629,6 +1671,15 @@ export class Lowerer { readonly checker: ts.TypeChecker; readonly diags: ScrDiagnostic[] = []; readonly fnSigsBySymbol = new Map(); + /** Per file: whether it assigns `exports` and `module.exports` + * (cjs-exports-object.ts). */ + readonly cjsExportsAssignments = new Map< + ts.SourceFile, + { exports: boolean; moduleExports: boolean } + >(); + /** Inline require() calls whose module edge closes a require cycle + * (LoadResult.inlineRequireCycleCalls). */ + readonly inlineRequireCycleCalls: ReadonlySet; /** Immutable callable aliases and compiler-generated adapters. The map * is symbol-keyed, so shadowing and cross-module imports keep the same * exact binding discipline as globals/functions. */ @@ -1855,6 +1906,9 @@ export class Lowerer { * and erased instances). */ erasingDepth = 0; localClassInstantiations: { owner: ts.FunctionLikeDeclaration; name: string }[] = []; + /** Instance types (by checker type id) of the local classes generic + * factory calls return, and the per-instance class each names. */ + readonly localClassInstanceTypes = new Map(); /** The ts-level twin of typeParamBindings, non-null while a CALL-keyed * instance body lowers: type-parameter symbol → the bound CHECKER type, * consulted where the mapped IrType has already widened away information @@ -1925,6 +1979,9 @@ export class Lowerer { /** Per CommonJS file using top-level `this`: the global holding the * object that stands for its original exports (lowerCjsTopLevelThis). */ readonly cjsExportsThis = new Map(); + /** Inline program-module require calls whose %init the enclosing member + * read or member call is already sequencing (cjs-inline-require.ts). */ + readonly inlineRequireInitDone = new Set(); /** Bindings whose unchecked string arithmetic can produce either a number * (NaN for an absent read) or a string. Preserve that result union at bare * reads instead of applying the checker-bare string narrowing adapter. */ @@ -2081,6 +2138,42 @@ export class Lowerer { }; } + /** True when `node`'s lowered value can hold a hidden `undefined` the + * checker type does not admit: an unchecked element or member read, a call + * whose lowered return admits undefined, or a binding whose storage the + * optional-read analysis marked. Whether the value actually carries the + * undefined arm is only known once it is lowered + * (runtimeOptionalSourceValue); this is the syntactic precondition. */ + isRuntimeOptionalOrigin(node: ts.Expression): boolean { + let origin: ts.Expression = node; + while (ts.isParenthesizedExpression(origin)) origin = origin.expression; + if (ts.isElementAccessExpression(origin) || ts.isPropertyAccessExpression(origin)) return true; + if (ts.isCallExpression(origin)) { + const name = ts.isPropertyAccessExpression(origin.expression) + ? origin.expression.name + : origin.expression; + const symbol = ts.isIdentifier(name) ? this.resolveValueSymbol(name) : undefined; + const signature = symbol ? this.fnSigsBySymbol.get(symbol) : undefined; + return ( + this.runtimeOptionalFunctionReturns.has(origin) || + (signature?.returnType.kind === "union" && + this.armTag(signature.returnType.unionId, UNDEFINED_T) >= 0) + ); + } + if (ts.isIdentifier(origin)) { + const local = this.resolveLocal(origin); + const root = local ? this.runtimeOptionalRootOf(local) : null; + const global = this.globalOf(origin); + return ( + (!!root && this.runtimeOptionalStorageLocals.has(root)) || + (!!global && + (this.isRuntimeOptionalGlobal(global) || + (global.type.kind === "union" && this.armTag(global.type.unionId, UNDEFINED_T) >= 0))) + ); + } + return false; + } + /** Recover the original optional union when a checked single-arm helper * was installed before a strict property consumer could name its member. * Recovery covers member reads and storage roots marked by the @@ -2089,32 +2182,7 @@ export class Lowerer { runtimeOptionalSourceValue(node: ts.Expression, value: IrExpr): IrExpr | null { const slot = this.deferredFieldSlot(value); if (slot) return slot; - let origin: ts.Expression = node; - while (ts.isParenthesizedExpression(origin)) origin = origin.expression; - let optionalOrigin = - ts.isElementAccessExpression(origin) || ts.isPropertyAccessExpression(origin); - if (ts.isCallExpression(origin)) { - const name = ts.isPropertyAccessExpression(origin.expression) - ? origin.expression.name - : origin.expression; - const symbol = ts.isIdentifier(name) ? this.resolveValueSymbol(name) : undefined; - const signature = symbol ? this.fnSigsBySymbol.get(symbol) : undefined; - optionalOrigin = - this.runtimeOptionalFunctionReturns.has(origin) || - (signature?.returnType.kind === "union" && - this.armTag(signature.returnType.unionId, UNDEFINED_T) >= 0); - } - if (ts.isIdentifier(origin)) { - const local = this.resolveLocal(origin); - const root = local ? this.runtimeOptionalRootOf(local) : null; - const global = this.globalOf(origin); - optionalOrigin = - (!!root && this.runtimeOptionalStorageLocals.has(root)) || - (!!global && - (this.isRuntimeOptionalGlobal(global) || - (global.type.kind === "union" && this.armTag(global.type.unionId, UNDEFINED_T) >= 0))); - } - if (!optionalOrigin) return null; + if (!this.isRuntimeOptionalOrigin(node)) return null; // A checked JavaScript indexed read can already be boxed. The checker // calls the element present, but that inference is not a runtime guard. @@ -2857,6 +2925,7 @@ export class Lowerer { this.alreadyFlushed = mode.alreadyFlushed ?? new Set(); this.targetPlatform = mode.targetPlatform ?? process.platform; this.startupCrash = mode.startupCrash ?? null; + this.inlineRequireCycleCalls = mode.inlineRequireCycleCalls ?? new Set(); this.projectCheckJs = mode.projectCheckJs ?? false; this.ffiImports = mode.ffiImports ?? []; this.libraryCallbacks = mode.libraryCallbacks ?? false; @@ -2888,7 +2957,11 @@ export class Lowerer { this.mixinTypeContext && this.mixinTypeContext.classNode === decl ? { kind: "object", className: this.mixinTypeContext.className } : null, - localClassInstance: (decl) => { + localClassInstance: (decl, instanceType) => { + // A generic factory's local class, by the instance type a call of + // the factory produced (localClassResultInstance). + const instanceClass = instanceType && this.localClassInstanceTypes.get(instanceType.id); + if (instanceClass) return { kind: "object", className: instanceClass }; // Computed heritage can close over parameters of its factory. // A speculative checker query outside that factory must not lower // the extends expression in the caller's lexical scope. @@ -3168,8 +3241,10 @@ export class Lowerer { ident.parent.name === ident ) { const recv = ident.parent.expression; - if (ts.isIdentifier(recv) && this.cjsLocalModuleBindingOf(recv)) { - const dep = this.localModuleBindingDepOf(recv); + if (this.cjsLocalModuleBindingOf(recv)) { + const dep = ts.isIdentifier(recv) + ? this.localModuleBindingDepOf(recv) + : this.cjsModuleRefDepOf(recv); const exported = dep ? this.cjsModuleExportSymbol(dep, ident.text) : undefined; // A createRequire call is typed as `any`, so tsgo can manufacture a // transient property symbol with no relation to the target module. @@ -3561,6 +3636,21 @@ export class Lowerer { return dep; } + /** The table module a non-identifier module reference names: an inline + * `require("./x")` (cjs-inline-require.ts) or tsc's unstamped + * `x_1.default` interop read (cjs-tsc-interop.ts). */ + cjsModuleRefDepOf(expr: ts.Expression): ts.SourceFile | null { + const inline = inlineNamespaceRequireOf(this, expr); + if (inline !== null) return inline.dep; + const interop = tscInteropModuleOf(this, expr); + return interop !== null && cjsNamespaceModule(this, interop.dep) ? interop.dep : null; + } + + /** The table module a CommonJS module binding identifier names. */ + cjsModuleBindingDepOf(expr: ts.Identifier): ts.SourceFile | null { + return this.localModuleBindingDepOf(expr); + } + /** The compiled module behind a require-like namespace binding: an * ordinary CommonJS require declaration, a canonical createRequire * declaration, or an ESM default import of CommonJS. One resolver keeps @@ -3573,6 +3663,10 @@ export class Lowerer { if (ts.isImportClause(decl)) return this.cjsDefaultImportDepOf(decl); if (!ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) || !decl.initializer) return null; + { + const interop = tscInteropModuleOf(this, expr); + if (interop !== null) return cjsNamespaceModule(this, interop.dep) ? interop.dep : null; + } const directSpec = requireSpecOf(decl.initializer); if (directSpec !== null) { if (isJsonRequireDecl(this, decl)) return null; @@ -3619,6 +3713,10 @@ export class Lowerer { if (wholeAssignment === undefined) return null; let rhs: ts.Expression = wholeAssignment.right; while (ts.isParenthesizedExpression(rhs)) rhs = rhs.expression; + // A pure re-export (`module.exports = require("./core")`) is the inner + // module's export table, read like any namespace binding. + if (inlineProgramRequireOf(this, rhs) !== null && !this.globalsByDeclNode.has(wholeAssignment)) + return null; if (ts.isIdentifier(rhs)) { const value = this.checker.getSymbolAtLocation(rhs); if (value) { @@ -3671,7 +3769,9 @@ export class Lowerer { * symbols → resolveValueSymbol); the bare value keeps the * namespace-object fence, like ESM namespace imports of builtins. */ cjsLocalModuleBindingOf(expr: ts.Expression): boolean { - if (!ts.isIdentifier(expr)) return false; + // An inline `require("./x")` over a table module reads its members like + // a binding (cjs-inline-require.ts sequences the module's %init). + if (!ts.isIdentifier(expr)) return this.cjsModuleRefDepOf(expr) !== null; const sym = this.checker.getSymbolAtLocation(expr); if (this.localModuleBindingDepOf(expr) === null) return false; if (this.createRequireWholeExportSymbolOf(expr) !== null) return false; @@ -3684,6 +3784,8 @@ export class Lowerer { // the object literal) keep the namespace reading — member accesses // resolve through the table's property symbols. if (sym && sym.flags & ts.SymbolFlags.Alias) { + // `module.exports = TypeError`: the binding IS the builtin global. + if (this.isStdlibSymbol(this.checker.getAliasedSymbol(sym))) return false; const d = this.checker.declarationsOf(this.checker.getAliasedSymbol(sym))[0]; if (d && (ts.isClassDeclaration(d) || ts.isFunctionDeclaration(d))) return false; if (d && ts.isVariableDeclaration(d)) { @@ -3781,7 +3883,7 @@ export class Lowerer { const id = `%g.${tag}%loaded`; this.moduleGuardOf.set(fp.sf, id); this.globalsList.push({ id, name: "%loaded", type: BOOL, mutable: true }); - if (usesCjsTopLevelThis(this, fp.sf)) { + if (usesCjsTopLevelThis(this, fp.sf) || usesCjsExportsIdentity(this, fp.sf)) { const exportsThis: IrGlobal = { id: `%g.${tag}%exportsThis`, name: "%exportsThis", @@ -7786,6 +7888,15 @@ export class Lowerer { : mapped; } + /** The runtime type of a record member slot typed `t`: an overloaded + * member's erased function (erasedOverloadMemberType — the type a record + * shape stores for it), otherwise mapTypeOf. */ + memberSlotTypeOf(t: ts.Type): IrType | null { + if (isOverloadedCallableMemberType(t, this.checker)) + return erasedOverloadMemberType(t, this.typeCtx) ?? null; + return this.mapTypeOf(t); + } + /** The one position where a contextual UNION must not be adopted over the * expression's own: the LEFT operand of `&&`, `||`, or `??`. Adopting a * contextual union is normally safe because tsc proved the value @@ -7959,6 +8070,8 @@ export class Lowerer { if (!mapped) { const argumentsType = jsArgumentsFunctionType(this, t); if (argumentsType !== null) return argumentsType; + const localClass = genericLocalClassBinding(this, node); + if (localClass !== null) return localClass; // The checked-dynamic declaration fallback (dynFallbackType): a // JAVASCRIPT binding of any inference residue, or a TypeScript // binding of genuine checker-`any`, becomes the checked-dynamic @@ -11396,6 +11509,7 @@ 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. + refuseWebAssemblyUse(this, expr.expression); return ( lowerLifetimeRegionCall(this, expr) ?? lowerInternTableCall(this, expr) ?? @@ -11621,6 +11735,7 @@ export class Lowerer { } lowerNew(expr: ts.NewExpression): IrExpr { + refuseWebAssemblyUse(this, expr.expression, "new "); const builtin = lowerLifetimeRegionNew(this, expr) ?? lowerInternTableNew(this, expr) ?? diff --git a/packages/compiler/src/frontend/npm-static.test.ts b/packages/compiler/src/frontend/npm-static.test.ts index a97b2f41c..0b4614e34 100644 --- a/packages/compiler/src/frontend/npm-static.test.ts +++ b/packages/compiler/src/frontend/npm-static.test.ts @@ -1,7 +1,7 @@ import { mkdtemp, rm } from "node:fs/promises"; import { join } from "node:path"; import { expect, test } from "vitest"; -import { npmStaticIneligibleReason } from "./npm-static.js"; +import { npmStaticIneligibleReason, npmStaticTransformPkgJson } from "./npm-static.js"; test("an unreadable runtime entry is an eligibility refusal", async () => { const dir = await mkdtemp("/tmp/scriptc-npm-static-unreadable-"); @@ -14,3 +14,25 @@ test("an unreadable runtime entry is an eligibility refusal", async () => { await rm(dir, { recursive: true, force: true }); } }); + +test("a hoisted node condition leaves no types claim behind", () => { + // uuid 14: the node object carries its own "types" key. Left in place, + // tsgo maps the hidden declaration to its same-stem browser build. + const pkg: Record = { + types: "./dist/index.d.ts", + exports: { + ".": { + node: { types: "./dist/index.d.ts", default: "./dist-node/index.js" }, + default: "./dist/index.js", + }, + "./package.json": "./package.json", + }, + }; + npmStaticTransformPkgJson(pkg); + expect(pkg).toEqual({ + exports: { + ".": { default: "./dist-node/index.js" }, + "./package.json": "./package.json", + }, + }); +}); diff --git a/packages/compiler/src/frontend/npm-static.ts b/packages/compiler/src/frontend/npm-static.ts index d2f4ea3e8..3c8fa22e9 100644 --- a/packages/compiler/src/frontend/npm-static.ts +++ b/packages/compiler/src/frontend/npm-static.ts @@ -157,8 +157,6 @@ export function npmStaticTransformPkgJson(pkg: Record): void { return; } const obj = v as Record; - delete obj["types"]; - delete obj["typings"]; // 0. The "node" condition HOISTS: Node's runtime resolution matches it // (yaml's `{ types, node: "./dist/index.js", default: "./browser/ // index.js" }` runs the node dist; the browser dist is a DIFFERENT @@ -187,6 +185,14 @@ export function npmStaticTransformPkgJson(pkg: Record): void { } } } + // 1. The types claims go AFTER the hoist: a node object's own + // "types" key (uuid's `node: { types: "./dist/index.d.ts", default: + // "./dist-node/index.js" }`) splices in with its siblings, and left + // in place tsgo follows it, maps the hidden declaration to its + // same-stem JS (dist/index.js, the browser build) and disagrees with + // this resolver's runtime answer. + delete obj["types"]; + delete obj["typings"]; for (const value of Object.values(obj)) transform(value); }; if (pkg["exports"] !== undefined) transform(pkg["exports"]); @@ -208,6 +214,13 @@ function npmStaticTransformPkgJsonText(text: string): string { } if (doc === null || typeof doc !== "object" || Array.isArray(doc)) return text; npmStaticTransformPkgJson(doc as Record); + // tsgo deduplicates installs by package id (name + version): a second + // copy of the same name@version (express/node_modules/fresh beside + // send/node_modules/fresh) becomes a redirect to the first copy loaded, + // so its own path never joins the program. Node loads every installed + // copy as its own module, and resolve.ts answers each importer's own + // copy; without a version the checker keeps the copies apart too. + delete (doc as Record)["version"]; return JSON.stringify(doc); } @@ -275,6 +288,20 @@ function packageIsUntyped(path: string): boolean { return untyped; } +/** An installed TypeScript source with no runtime JavaScript at its stem + * (tldts ships `index.ts` beside `main: "dist/cjs/index.js"`). Node never + * executes TypeScript under node_modules and resolve.ts answers only + * runtime JS for opted-in packages, yet tsgo's TypeScript-first lookup + * would take the package-root `index.ts` over `main`. A same-stem JS twin + * keeps the source visible: that pair is the shape npmStaticProgramDep + * accepts in the JavaScript's place. */ +function isUnloadableInstalledTsSource(path: string): boolean { + if (!/\.(ts|tsx|mts|cts)$/.test(path) || isDeclarationFileName(path)) return false; + if (!isNodeModulesPathNorm(path)) return false; + const stem = path.replace(/\.(ts|tsx|mts|cts)$/, ""); + return ![".js", ".jsx", ".mjs", ".cjs"].some((ext) => trackedExists(stem + ext)); +} + export interface NpmStaticFsShadow { /** Shadowed CONTENT for a real path (the types-stripped package.json), * or undefined (no shadow — fall through). */ @@ -383,7 +410,7 @@ export function npmStaticFsShadow(services: FrontendServices): NpmStaticFsShadow const target = shadowTargetOf(path); if (!target) return false; if (target.viaTypes) return true; // the @types twin hides whole - return isDeclarationFileName(path); + return isDeclarationFileName(path) || isUnloadableInstalledTsSource(path); }, }; } diff --git a/packages/compiler/src/frontend/pipeline.ts b/packages/compiler/src/frontend/pipeline.ts index c769ed99e..f7ab33429 100644 --- a/packages/compiler/src/frontend/pipeline.ts +++ b/packages/compiler/src/frontend/pipeline.ts @@ -39,6 +39,21 @@ import { THREADS_MODULE } from "./threads-import.js"; import { erasedTypeOnlyImport } from "./type-only-imports.js"; import { EXPERIMENTAL_MODULE } from "./experimental-import.js"; +/** Where a package-anchored preflight diagnostic sits, as + * `:` — the SC2013 refusal that drops the package + * reports only at the consumer's import, so its reason carries the inner + * location. */ +function packageDiagWhere(load: LoadResult, loc: SrcLoc): string { + const file = loc.file.split("\\").join("/"); + const at = file.lastIndexOf("/node_modules/"); + const shown = at >= 0 ? file.slice(at + "/node_modules/".length) : file; + const text = load.program.getSourceFile(loc.file)?.text; + if (text === undefined) return shown; + let line = 1; + for (let i = 0; i < loc.start && i < text.length; i++) if (text.charCodeAt(i) === 10) line++; + return `${shown}:${line}`; +} + export interface ProgramLoadOptions { npmStatic?: readonly string[]; externalTypes?: Readonly> | undefined; @@ -445,7 +460,8 @@ function loadFrontend( const reasons = new Map(npmStaticOffenders()); for (const d of preflight) { const pkg = npmStaticPackageOfPath(d.loc.file); - if (pkg !== null && !reasons.has(pkg)) reasons.set(pkg, `${d.code}: ${d.message}`); + if (pkg !== null && !reasons.has(pkg)) + reasons.set(pkg, `${d.code} at ${packageDiagWhere(load, d.loc)}: ${d.message}`); } if (![...reasons.keys()].some((p) => effective.has(p))) { const named = new Map(); @@ -577,6 +593,7 @@ function loadFrontend( ...opts, frontendServices: finalLoad.services, startupCrash: finalLoad.startupCrash ?? null, + inlineRequireCycleCalls: finalLoad.inlineRequireCycleCalls, projectCheckJs: finalLoad.typeWorld?.projectCheckJs ?? false, externalTypes: finalLoad.externalTypes, externalTypeSpecifiersByFile: finalLoad.externalTypeSpecifiersByFile, diff --git a/packages/compiler/src/frontend/program.ts b/packages/compiler/src/frontend/program.ts index dcdaf9040..a4ab30105 100644 --- a/packages/compiler/src/frontend/program.ts +++ b/packages/compiler/src/frontend/program.ts @@ -338,6 +338,12 @@ export interface LoadResult { * last. Empty until checkPreflight runs (and empty when preflight fails * structurally). */ moduleOrder: ts.SourceFile[]; + /** Inline require() calls whose edge closes a require cycle. Node answers + * them with the still-evaluating module's partial exports, which the + * static export globals do not model; their lowering refuses them by name + * at run time instead of refusing the whole program. Filled by + * checkPreflight. */ + inlineRequireCycleCalls?: ReadonlySet; /** Node's startup refusal, when the graph carries an import edge Node * rejects before ANY module evaluates — a RESOLUTION refusal (a bare * specifier nothing installed resolves, an exports/imports map that @@ -640,9 +646,14 @@ export function entryPackageFilePredicate(entryPath: string): (file: string) => } /** maxNodeModuleJsDepth can omit relative imports within an admitted - * package. Discover its runtime sources to a fixpoint so the checker and - * module resolver see the same graph regardless of import traversal order. */ -function entryPackageProgramRoots7(program: ts.Program, entryPath: string): string[] { + * package, and opted-in packages deep in the dependency graph. Discover + * their runtime sources to a fixpoint so the checker and module resolver + * see the same graph regardless of import traversal order or depth. */ +function entryPackageProgramRoots7( + program: ts.Program, + entryPath: string, + rootNpmStaticEdges: boolean, +): string[] { const belongsToEntry = entryPackageFilePredicate(entryPath); const roots = new Set(); for (const sf of program.getImplementationSourceFiles()) { @@ -661,15 +672,63 @@ function entryPackageProgramRoots7(program: ts.Program, entryPath: string): stri program.getSourceFile(target) === undefined ) roots.add(target); + // An opted-in package's bare edge counts against the same depth + // budget: tsgo charges every node_modules JS hop, so express's + // body-parser → qs → side-channel → get-intrinsic chain runs out of + // depth before its leaves load. Root the runtime file this edge + // lowers to (preflight's own resolution and miss rule) so the leaf + // joins like a shallow one; complete programs add nothing. Only + // the shadowed lowering world does this (the authored world checks + // user code against declarations), and only from package files: a + // program file's own edges are never deeper than one hop. + // (resolveBareModule directly: resolveNpmImport7's workspace + // registration stays with preflight's own walk.) + if ( + target === null && + rootNpmStaticEdges && + npmStaticPackageOfPath(sf.fileName) !== null && + !isRelativeSpecifier(specifier.text) + ) { + const spec = specifier.text; + if (spec.startsWith("#") || canonicalBuiltinModule(spec) !== null) continue; + const npm = resolveBareModule( + sf.fileName, + spec, + undefined, + moduleSpecifierKind7(specifier), + ); + if ( + npm !== null && + isNpmStaticPackage(npm.packageName) && + (isNodeModulesPath(npm.typesFile) || npm.workspaceDir !== undefined) && + isJsSourceFileName(npm.typesFile) && + npmStaticProgramFile(program, npm.typesFile) === null + ) + roots.add(tsgoPath(resolve(npm.typesFile))); + } } } return [...roots].sort(); } +/** "require" for a CommonJS edge (`require("x")`, `import x = require("x")`), + * "import" for every ESM form — the resolution kind preflight uses. */ +function moduleSpecifierKind7(specifier: ts.StringLiteralLike): "import" | "require" { + const parent = specifier.parent; + if (ts.isExternalModuleReference(parent)) return "require"; + return ts.isCallExpression(parent) && + ts.isIdentifier(parent.expression) && + parent.expression.text === "require" + ? "require" + : "import"; +} + function loadProgram7( host: ts.Ts7Host, entryPath: string, externalTypes: ReadonlyMap = new Map(), + /** The --npm-static lowering world: root opted-in packages' deep edges. */ + rootNpmStaticEdges = false, ): LoadResult & { disposeAll: () => void } { const config = adoptProjectConfig7(host, entryPath); const configuredPaths = config.options["paths"]; @@ -717,7 +776,7 @@ function loadProgram7( try { for (let pass = 0; pass < 32; pass++) { const candidates = [ - ...entryPackageProgramRoots7(program, entryPath), + ...entryPackageProgramRoots7(program, entryPath, rootNpmStaticEdges), ...createRequireProgramRoots7(program), ...forkTargetPaths(program, program.getImplementationSourceFiles()), ...workerTargetPaths(program, program.getImplementationSourceFiles()), @@ -931,7 +990,7 @@ export function loadProgram( }; const host = services.createProgramHost({ cwd: dirname(entryPath), fsShadow }); try { - const load = loadProgram7(host, entryPath, externalTypes); + const load = loadProgram7(host, entryPath, externalTypes, npmStaticPackages.length > 0); let authoredHost: ts.Ts7Host | null = null; let authoredLoad: ReturnType | null = null; return { @@ -975,9 +1034,10 @@ export function loadProgram( * preflight diagnostics. Preserve the caller's complete load shape when * mutating it, including its owned services and disposal callback. */ export function checkPreflight(load: T): ScrDiagnostic[] { - const { diags, moduleOrder, startupCrash } = preflight7(load); + const { diags, moduleOrder, startupCrash, inlineRequireCycleCalls } = preflight7(load); load.moduleOrder = moduleOrder; load.startupCrash = startupCrash; + load.inlineRequireCycleCalls = inlineRequireCycleCalls; return diags; } @@ -1842,6 +1902,36 @@ function nestedBareRequiresOf7(sf: ts.SourceFile): ts.CallExpression[] { return out; } +/** INLINE `require("...")` calls in expression position anywhere in a file + * (`require("./x").f`, `require("debug")("ns")`, `module.exports = + * require("./y")`, `{ v: require("./v") }`): each evaluates its module at + * that position, exactly like a bare require statement. Top-level require + * statements and bare require statements are collected by their own + * scans; a require that initializes a nested declaration keeps its + * lowering fence and is not an edge. */ +function inlineRequiresOf7(sf: ts.SourceFile): ts.CallExpression[] { + const out: ts.CallExpression[] = []; + ts.walkPreorder(sf, (n) => { + if (!ts.isCallExpression(n) || requireSpecOf7(n) === null) return; + let outer: ts.Node = n; + while ( + outer.parent !== undefined && + (ts.isParenthesizedExpression(outer.parent) || + ts.isAsExpression(outer.parent) || + ts.isTypeAssertion(outer.parent) || + ts.isNonNullExpression(outer.parent)) + ) { + outer = outer.parent; + } + const parent = outer.parent; + if (parent !== undefined && ts.isExpressionStatement(parent)) return; + if (parent !== undefined && ts.isVariableDeclaration(parent) && parent.initializer === outer) + return; + out.push(n); + }); + return out; +} + type RequireCallBindingKind7 = "ambient" | "createRequire" | "source"; function stripRequireCasts7(expr: ts.Expression): ts.Expression { @@ -2408,6 +2498,13 @@ function nsBindingUsesAreBareStatements7( export interface CycleEdge { dep: ts.SourceFile; stmt?: ts.ImportDeclaration | ts.ExportDeclaration; + /** An inline require() in a deferred position (a function body): Node + * evaluates the dependency when that code runs, after this module's own + * top level, so the edge orders the dependency after the module and + * never closes a cycle through the module's initialization. */ + lazy?: true; + /** The inline require() call behind the edge (inline edges only). */ + call?: ts.CallExpression; } /** True when the reference at `node` can only evaluate AFTER the module @@ -4006,6 +4103,24 @@ function locOf7(node: ts.Node): { file: string; start: number; end: number } { return { file: sf.fileName, start: node.getStart(sf), end: node.getEnd() }; } +/** The program file holding an opted-in package's resolved runtime JS: + * the file itself, or its same-stem TypeScript twin. */ +function npmStaticProgramFile(program: ts.Program, resolvedFile: string): ts.SourceFile | null { + let dep = program.getSourceFile(resolvedFile) ?? null; + if (dep === null) { + // A workspace-linked package shipping its .ts SOURCE beside the + // compiled .js: the checker's resolution preferred the source (it + // outranks the sibling .js under bundler resolution), so the program + // holds the .ts twin at the same stem — the same module, in its + // richer spelling. + for (const ext of [".ts", ".tsx", ".mts", ".cts"]) { + dep = program.getSourceFile(resolvedFile.replace(/\.(js|mjs|cjs)$/, ext)) ?? null; + if (dep !== null) break; + } + } + return dep; +} + /** The PROGRAM source file an opted-in --npm-static package's resolved * entry maps to, or null with the package marked an offender (resolution * still answering declarations, or the file missing from the type-checked @@ -4022,18 +4137,7 @@ function npmStaticProgramDep( ); return null; } - let dep = program.getSourceFile(resolvedFile) ?? null; - if (dep === null) { - // A workspace-linked package shipping its .ts SOURCE beside the - // compiled .js: the checker's resolution preferred the source (it - // outranks the sibling .js under bundler resolution), so the program - // holds the .ts twin at the same stem — the same module, in its - // richer spelling. - for (const ext of [".ts", ".tsx", ".mts", ".cts"]) { - dep = program.getSourceFile(resolvedFile.replace(/\.(js|mjs|cjs)$/, ext)) ?? null; - if (dep !== null) break; - } - } + const dep = npmStaticProgramFile(program, resolvedFile); if (dep === null) { reportNpmStaticOffender( packageName, @@ -4085,6 +4189,7 @@ function preflight7(load: LoadResult): { diags: ScrDiagnostic[]; moduleOrder: ts.SourceFile[]; startupCrash: StartupCrash | null; + inlineRequireCycleCalls: ReadonlySet; } { const { program, entry } = load; const diags: ScrDiagnostic[] = [...load.configDiags]; @@ -4885,6 +4990,21 @@ function preflight7(load: LoadResult): { pattern.elements.every((e) => { if (e.initializer !== undefined || e.dotDotDotToken !== undefined) return false; if (e.name !== undefined && ts.isIdentifier(e.name)) return true; + // A nested pattern under a named export of a program module + // destructures that export's VALUE at the require + // (`const { codes: { ERR_X } } = require("./errors")`): the + // inner bindings are ordinary destructured storage. + if ( + module === null && + builtin === null && + bindingKind !== "createRequire" && + pattern === req.decl!.name && + e.name !== undefined && + ts.isObjectBindingPattern(e.name) && + e.propertyName !== undefined && + ts.isIdentifier(e.propertyName) + ) + return true; if (module === null || e.name === undefined || !ts.isObjectBindingPattern(e.name)) return false; const key = e.propertyName; @@ -4998,6 +5118,32 @@ function preflight7(load: LoadResult): { continue; } } + // Inline requires of program modules are module edges like the bare + // statements above (cjs-inline-require.ts lowers each to the module's + // %init at its position). Only the CommonJS global in a CommonJS file + // counts, and targets outside the compiled graph add nothing here: + // their use sites keep their existing lowering fences. + if (jsRequireFile && !isNodeEsmFile7(sf, program)) { + for (const call of inlineRequiresOf7(sf)) { + if (requireCallBindingKind7(program, call) !== "ambient") continue; + const spec = requireSpecOf7(call)!; + if (load.externalTypes.has(spec) || canonicalBuiltinModule(spec) !== null) continue; + const lazy = inDeferredPosition7(call); + const edgeTo = (dep: ts.SourceFile): CycleEdge => + lazy ? { dep, lazy: true, call } : { dep, call }; + const projectDep = resolveImport7(program, sf, spec, "require"); + if (projectDep !== null) { + if (!projectDep.fileName.endsWith(".json")) deps.push(edgeTo(projectDep)); + continue; + } + if (isRelativeSpecifier(spec) || spec.startsWith("#")) continue; + const npmReq = resolveNpmImport7(sf.fileName, spec, "require"); + if (npmReq !== null && isNpmStaticPackage(npmReq.packageName)) { + const nDep = npmStaticProgramDep(program, npmReq.packageName, npmReq.typesFile); + if (nDep !== null) deps.push(edgeTo(nDep)); + } + } + } } } @@ -5024,8 +5170,12 @@ function preflight7(load: LoadResult): { // reads are all let/const bindings with module storage — the // lowering checks each one (cycleEarlyBindings) and throws Node's // ReferenceError on a read before the declaration ran. - const cycleAdmissionReason = makeCycleAdmission(program, (sf) => edges.get(sf) ?? []); + const cycleAdmissionReason = makeCycleAdmission(program, (sf) => { + const all = edges.get(sf) ?? []; + return all.some((e) => e.call !== undefined) ? all.filter((e) => e.call === undefined) : all; + }); const order: ts.SourceFile[] = []; + const inlineRequireCycleCalls = new Set(); const state = new Map(); const stack: string[] = []; const visit = (sf: ts.SourceFile): void => { @@ -5033,9 +5183,14 @@ function preflight7(load: LoadResult): { stack.push(sf.fileName); for (const e of edges.get(sf) ?? []) { if (e.dep === sf) continue; // self-import: a Node cache hit, not a cycle + if (e.lazy === true) continue; // visited after this module completes const s = state.get(e.dep); if (s === "done") continue; if (s === "visiting") { + if (e.call !== undefined) { + inlineRequireCycleCalls.add(e.call); + continue; + } // A back-edge: Node answers it from the cache (the module is // already evaluating) — admitted by the cheap per-edge rule, the // declaration-only init window rule, or the exact initialization @@ -5059,6 +5214,11 @@ function preflight7(load: LoadResult): { stack.pop(); state.set(sf, "done"); order.push(sf); + // Lazy inline requires run after this module's top level: their + // modules join the order afterwards (cache hits when already loaded). + for (const e of edges.get(sf) ?? []) { + if (e.lazy === true && state.get(e.dep) === undefined) visit(e.dep); + } }; visit(entry); @@ -5112,7 +5272,12 @@ function preflight7(load: LoadResult): { esmNamedImportLinkCheck(program, entry, order, diags), ); - return { diags, moduleOrder: order, startupCrash: resolveCrash ?? linkCrash }; + return { + diags, + moduleOrder: order, + startupCrash: resolveCrash ?? linkCrash, + inlineRequireCycleCalls, + }; } /* ── the CJS named-import link check ───────────────────────────────────── @@ -5815,6 +5980,37 @@ export function cjsExportAssignmentOf( return null; } +/** The members and shared value of a CHAINED member export + * `exports.a = exports.b = module.exports.c = value` (outermost name + * first), or null when the assignment is not a chain of at least two + * identifier-named export members or its value is undefined. */ +export function cjsExportChainOf( + e: ts.BinaryExpression, +): { names: ts.Identifier[]; value: ts.Expression } | null { + const names: ts.Identifier[] = []; + let cur: ts.Expression = e; + for (;;) { + while (ts.isParenthesizedExpression(cur)) cur = cur.expression; + if (!ts.isBinaryExpression(cur) || cur.operatorToken.kind !== ts.SyntaxKind.EqualsToken) break; + const left = cur.left; + if ( + !ts.isPropertyAccessExpression(left) || + left.questionDotToken || + !ts.isIdentifier(left.name) + ) + break; + const recv = left.expression; + if (!((ts.isIdentifier(recv) && recv.text === "exports") || isModuleExportsAccess(recv))) break; + names.push(left.name); + cur = cur.right; + } + // tsc's `exports.a = exports.b = void 0;` preamble is not a value chain + // (the export-statement lowering owns it). + const isVoid = + cur.kind === ts.SyntaxKind.VoidExpression || (ts.isIdentifier(cur) && cur.text === "undefined"); + return names.length >= 2 && !isVoid ? { names, value: cur } : null; +} + /** Why Node would DISCARD this CommonJS export statement, or null when it * survives (Node's export-object identity rules — checker-free, pure * AST): `module.exports = {...}` REPLACES the export object, so members diff --git a/packages/compiler/src/frontend/type-mapper.ts b/packages/compiler/src/frontend/type-mapper.ts index dc7aca503..236b2a6c0 100644 --- a/packages/compiler/src/frontend/type-mapper.ts +++ b/packages/compiler/src/frontend/type-mapper.ts @@ -9,6 +9,7 @@ import { BOOL, bytesOf, canConvertToDyn, + canDynCheckTo, CHILD_T, CRYPTOHASH_T, CRYPTOHMAC_T, @@ -920,6 +921,24 @@ function isDeclaredInAmbientNamespace(d: ts.Declaration, name: string): boolean return false; } +/** A type declared in the shipped WebAssembly namespace (scriptc.d.ts): + * its modules, instances, memories, tables, globals, error classes and the + * Exports/Imports records. */ +export function isWebAssemblyType( + type: ts.Type, + ctx: Pick, +): boolean { + const symbol = type.getAliasSymbol() ?? type.getSymbol(); + if (!symbol) return false; + return ctx.checker + .declarationsOf(symbol) + .some( + (d) => + ctx.isStdlibFile(d.getSourceFile()) && + isDeclaredInAmbientNamespace(d as ts.Declaration, "WebAssembly"), + ); +} + /** True when a type contains a record anywhere (the trigger for the * shape-mismatch diagnostic SC2002 — non-record mismatches are tsc's or * the validator's business). */ @@ -1035,7 +1054,7 @@ export interface TypeMapperCtx { * inside members, self-referential member types), null outside any * mixin context (the type alone cannot name a call site). */ mixinClassInstance?: (decl: ts.ClassLikeDeclaration) => IrType | null; - localClassInstance?: (decl: ts.ClassLikeDeclaration) => IrType | null; + localClassInstance?: (decl: ts.ClassLikeDeclaration, instanceType?: ts.Type) => IrType | null; /** Live class protocols retain identity and receiver dispatch rather than * copying an instance into an unrelated record layout. */ classImplementedProtocol?: (type: ts.Type) => boolean; @@ -1419,6 +1438,14 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { return { kind: "object", className: "%Error" }; } if (isOsConstantsType(type, ctx) || isLegacyUrlType(type, ctx)) return DYN; + // The WebAssembly API's values have the checked-dynamic representation, so + // declarations that merely mention them compile; each reached use of the + // API itself is refused at its site (builtins/webassembly.ts). + if (isWebAssemblyType(type, ctx)) return DYN; + // A union over one of them (quickjs-wasi's `BufferSource | WebAssembly.Module` + // 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; // Immutable (@scriptc/types) is a deep-readonly view: the value is // still the T it maps. const immutableSource = immutableSourceType(type, ctx); @@ -1950,7 +1977,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { } } if (classExprNeedsContext(classDecl)) { - const local = ctx.localClassInstance?.(classDecl); + const local = ctx.localClassInstance?.(classDecl, widened); if (local) contextResolutions++; return local ?? null; } @@ -1989,7 +2016,11 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { } } if (classExprNeedsContext(classDecl)) { - const local = ctx.localClassInstance?.(classDecl); + const ctorSigs = checker.getConstructSignatures(widened); + const local = ctx.localClassInstance?.( + classDecl, + ctorSigs.length === 1 ? checker.getReturnTypeOfSignature(ctorSigs[0]!) : undefined, + ); if (local?.kind === "object") { contextResolutions++; return { kind: "classval", className: local.className }; @@ -3220,7 +3251,10 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { isStdlibInterface("IterableIterator") || // An Iterator annotation holds a single-pass iterator object: a // generator, or a native iterator adapted into one. - isStdlibInterface("Iterator") + isStdlibInterface("Iterator") || + // IteratorObject is what the iterator helpers return: a helper + // generator over its source (containers/iterator-helpers.ts). + isStdlibInterface("IteratorObject") ) { const args = checker.getTypeArguments(widened as ts.TypeReference); const channels = genChannels(args[0], args[1], args[2], ctx); @@ -3915,171 +3949,7 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { if (hybrid) return hybrid; } const callSigs = checker.getCallSignatures(widened); - if (callSigs.length === 1) { - const sig = callSigs[0]!; - if (sig.getTypeParameters().length && ctx.erasingSignature !== sig) return null; - // A SYNTHESIZED rest param (tsc's JS inference for a function body - // reading `arguments` — `(...args: any[]) => any` whose args symbol - // has no declaration): the dotDotDot check below can't see it, and a - // fixed-arity func mapping would LIE about the value's calling - // convention. Detected by the param-count mismatch against the - // signature's own declaration, excluding an erased `this` parameter. - { - const sigDecl = checker.signatureDeclaration(sig); - const declParams = - sigDecl !== undefined && ts.isFunctionLike(sigDecl) ? sigDecl.parameters : undefined; - if ( - declParams !== undefined && - runtimeParameterCount(declParams) !== sig.getParameters().length - ) { - return null; - } - // tsgo never SYNTHESIZES that rest param into the inferred signature - // (5.9.3 did — the count mismatch above was the whole detector - // there), so the declaration's own body answers directly. - if (sigDecl !== undefined && ts.isFunctionLike(sigDecl) && bodyReadsArguments(sigDecl)) { - return null; - } - } - const params: IrType[] = []; - let typedRest = false; - let dynRest = false; - for (const p of sig.getParameters()) { - const decl = checker.valueDeclarationOf(p); - const rest = decl !== undefined && ts.isParameter(decl) && decl.dotDotDotToken !== undefined; - - // arity ABI selected by lambdaSignature. Treating an inferred any[] - // 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; - const optional = - decl !== undefined && - ts.isParameter(decl) && - (decl.questionToken !== undefined || decl.initializer !== undefined); - let pt = mapType(checker.getTypeOfSymbol(p), ctx); - if ( - decl && - ts.isParameter(decl) && - ts.isSetAccessorDeclaration(decl.parent) && - isJsSourceFile(decl.getSourceFile()) - ) - pt = DYN; - // An inferred JavaScript binding pattern consumes an iterable; it - // does not require the caller's array to have exactly this length. - const executor = decl && ts.isParameter(decl) ? decl.parent : null; - const construction = executor?.parent; - const constructorSymbol = - construction && ts.isNewExpression(construction) - ? checker.getSymbolAtLocation(construction.expression) - : undefined; - const nativeExecutor = - executor && - (ts.isArrowFunction(executor) || ts.isFunctionExpression(executor)) && - construction && - ts.isNewExpression(construction) && - construction.arguments?.[0] === executor && - ts.isIdentifier(construction.expression) && - construction.expression.text === "Promise" && - constructorSymbol && - checker - .declarationsOf(constructorSymbol) - .some((site) => ctx.isStdlibFile(site.getSourceFile())); - if ( - !nativeExecutor && - decl && - ts.isParameter(decl) && - !decl.dotDotDotToken && - !ts.isSetAccessorDeclaration(decl.parent) && - isJsSourceFile(decl.getSourceFile()) && - !decl.type && - !/@(?:param|type)\b/.test( - decl.getSourceFile().text.slice(decl.parent?.pos ?? decl.pos, decl.getStart()), - ) - ) - pt = DYN; - if (pt) pt = jsOpenObjectType(decl, pt, ctx.shapes, ctx.unions); - // Belt and braces for non-strict type worlds: an optional param's - // ABI slot is always the undefined-armed union (strictNullChecks - // already spells it that way; arm it here if the world didn't). - if (optional && pt && pt.kind !== "void" && pt.kind !== "dyn") { - const armed = withUndefinedArm(pt, ctx.unions); - if (!armed) return null; - pt = armed; - } - // `...args: unknown[]` / `...args: any[]`: the checked-dynamic - // variadic ABI (no typed slot; the callee's hidden trailing dyn - // array receives every surplus argument, as for JS rest params). - if ( - rest && - (pt?.kind === "dyn" || (!pt && isAnyArrayType(checker.getTypeOfSymbol(p), checker))) - ) { - dynRest = true; - continue; - } - if (!pt) return null; - if (rest) { - if (pt.kind !== "array") return null; - typedRest = true; - } - // `(value: void) => void` (Promise's resolve) is callable with - // no arguments — a void param is dropped, not a mapping failure. - if (pt.kind === "void") continue; - params.push(pt); - } - const retT = checker.getReturnTypeOfSignature(sig); - // `() => never` (a throw-only lambda's inferred type) is assignable to - // `() => void` and its calls never produce a value — map the return - // like declaredReturnType does for declarations. JS null/undefined - // returns can read mutable fields, so callable values use the same - // checked-native return ABI as their implementations. - const sigDecl = checker.signatureDeclaration(sig); - const jsUnitReturn = - sigDecl !== undefined && - isJsSourceFile(sigDecl.getSourceFile()) && - (retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0; - let ret = - jsUnitReturn || (retT.flags & ts.TypeFlags.Any) !== 0 - ? DYN - : retT.flags & ts.TypeFlags.Never - ? VOID - : mapType(retT, ctx); - if (sigDecl && ts.isGetAccessorDeclaration(sigDecl) && isJsSourceFile(sigDecl.getSourceFile())) - ret = DYN; - if (sigDecl && isJsSourceFile(sigDecl.getSourceFile()) && ret?.kind === "array") ret = DYN; - if ( - sigDecl && - ts.isFunctionLike(sigDecl) && - isJsSourceFile(sigDecl.getSourceFile()) && - !sigDecl.type && - !/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) && - ret?.kind === "record" - ) - ret = DYN; - if ( - sigDecl && - ts.isFunctionLike(sigDecl) && - isJsSourceFile(sigDecl.getSourceFile()) && - !sigDecl.type && - !/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) && - (ret?.kind === "date" || - (ret?.kind === "union" && - ctx.unions.get(ret.unionId)?.arms.some((arm) => arm.kind === "func"))) - ) - ret = DYN; - if ( - ret && - sigDecl && - isJsSourceFile(sigDecl.getSourceFile()) && - functionCanReturnUndefined(sigDecl) - ) - ret = withUndefinedArm(ret, ctx.unions) ?? ret; - if (!ret) return null; - return typedRest - ? { kind: "func", params, ret, rest: true, restAbi: "typed" } - : dynRest - ? { kind: "func", params, ret, rest: true } - : funcOf(params, ret); - } + if (callSigs.length === 1) return mapCallSignature(callSigs[0]!, ctx); // Records: object types whose members are all data properties (shorthand // methods in type position count — they're func-typed fields) with // mappable types; no call/construct signatures, no index signatures, not @@ -4353,6 +4223,175 @@ function mapTypeInner(type: ts.Type, ctx: TypeMapperCtx): IrType | null { return null; } +/** One non-overloaded call signature's func type (mapTypeInner's + * single-signature rule; erasedOverloadMemberType maps each overload of a + * member through it). */ +function mapCallSignature(sig: ts.Signature, ctx: TypeMapperCtx): IrType | null { + const { checker } = ctx; + if (sig.getTypeParameters().length && ctx.erasingSignature !== sig) return null; + // A SYNTHESIZED rest param (tsc's JS inference for a function body + // reading `arguments` — `(...args: any[]) => any` whose args symbol + // has no declaration): the dotDotDot check below can't see it, and a + // fixed-arity func mapping would LIE about the value's calling + // convention. Detected by the param-count mismatch against the + // signature's own declaration, excluding an erased `this` parameter. + { + const sigDecl = checker.signatureDeclaration(sig); + const declParams = + sigDecl !== undefined && ts.isFunctionLike(sigDecl) ? sigDecl.parameters : undefined; + if ( + declParams !== undefined && + runtimeParameterCount(declParams) !== sig.getParameters().length + ) { + return null; + } + // tsgo never SYNTHESIZES that rest param into the inferred signature + // (5.9.3 did — the count mismatch above was the whole detector + // there), so the declaration's own body answers directly. + if (sigDecl !== undefined && ts.isFunctionLike(sigDecl) && bodyReadsArguments(sigDecl)) { + return null; + } + } + const params: IrType[] = []; + let typedRest = false; + let dynRest = false; + for (const p of sig.getParameters()) { + const decl = checker.valueDeclarationOf(p); + const rest = decl !== undefined && ts.isParameter(decl) && decl.dotDotDotToken !== undefined; + + // arity ABI selected by lambdaSignature. Treating an inferred any[] + // 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; + const optional = + decl !== undefined && + ts.isParameter(decl) && + (decl.questionToken !== undefined || decl.initializer !== undefined); + let pt = mapType(checker.getTypeOfSymbol(p), ctx); + if ( + decl && + ts.isParameter(decl) && + ts.isSetAccessorDeclaration(decl.parent) && + isJsSourceFile(decl.getSourceFile()) + ) + pt = DYN; + // An inferred JavaScript binding pattern consumes an iterable; it + // does not require the caller's array to have exactly this length. + const executor = decl && ts.isParameter(decl) ? decl.parent : null; + const construction = executor?.parent; + const constructorSymbol = + construction && ts.isNewExpression(construction) + ? checker.getSymbolAtLocation(construction.expression) + : undefined; + const nativeExecutor = + executor && + (ts.isArrowFunction(executor) || ts.isFunctionExpression(executor)) && + construction && + ts.isNewExpression(construction) && + construction.arguments?.[0] === executor && + ts.isIdentifier(construction.expression) && + construction.expression.text === "Promise" && + constructorSymbol && + checker + .declarationsOf(constructorSymbol) + .some((site) => ctx.isStdlibFile(site.getSourceFile())); + if ( + !nativeExecutor && + decl && + ts.isParameter(decl) && + !decl.dotDotDotToken && + !ts.isSetAccessorDeclaration(decl.parent) && + isJsSourceFile(decl.getSourceFile()) && + !decl.type && + !/@(?:param|type)\b/.test( + decl.getSourceFile().text.slice(decl.parent?.pos ?? decl.pos, decl.getStart()), + ) + ) + pt = DYN; + if (pt) pt = jsOpenObjectType(decl, pt, ctx.shapes, ctx.unions); + // Belt and braces for non-strict type worlds: an optional param's + // ABI slot is always the undefined-armed union (strictNullChecks + // already spells it that way; arm it here if the world didn't). + if (optional && pt && pt.kind !== "void" && pt.kind !== "dyn") { + const armed = withUndefinedArm(pt, ctx.unions); + if (!armed) return null; + pt = armed; + } + // `...args: unknown[]` / `...args: any[]`: the checked-dynamic + // variadic ABI (no typed slot; the callee's hidden trailing dyn + // array receives every surplus argument, as for JS rest params). + if ( + rest && + (pt?.kind === "dyn" || (!pt && isAnyArrayType(checker.getTypeOfSymbol(p), checker))) + ) { + dynRest = true; + continue; + } + if (!pt) return null; + if (rest) { + if (pt.kind !== "array") return null; + typedRest = true; + } + // `(value: void) => void` (Promise's resolve) is callable with + // no arguments — a void param is dropped, not a mapping failure. + if (pt.kind === "void") continue; + params.push(pt); + } + const retT = checker.getReturnTypeOfSignature(sig); + // `() => never` (a throw-only lambda's inferred type) is assignable to + // `() => void` and its calls never produce a value — map the return + // like declaredReturnType does for declarations. JS null/undefined + // returns can read mutable fields, so callable values use the same + // checked-native return ABI as their implementations. + const sigDecl = checker.signatureDeclaration(sig); + const jsUnitReturn = + sigDecl !== undefined && + isJsSourceFile(sigDecl.getSourceFile()) && + (retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0; + let ret = + jsUnitReturn || (retT.flags & ts.TypeFlags.Any) !== 0 + ? DYN + : retT.flags & ts.TypeFlags.Never + ? VOID + : mapType(retT, ctx); + if (sigDecl && ts.isGetAccessorDeclaration(sigDecl) && isJsSourceFile(sigDecl.getSourceFile())) + ret = DYN; + if (sigDecl && isJsSourceFile(sigDecl.getSourceFile()) && ret?.kind === "array") ret = DYN; + if ( + sigDecl && + ts.isFunctionLike(sigDecl) && + isJsSourceFile(sigDecl.getSourceFile()) && + !sigDecl.type && + !/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) && + ret?.kind === "record" + ) + ret = DYN; + if ( + sigDecl && + ts.isFunctionLike(sigDecl) && + isJsSourceFile(sigDecl.getSourceFile()) && + !sigDecl.type && + !/@returns?\b/.test(sigDecl.getSourceFile().text.slice(sigDecl.pos, sigDecl.getStart())) && + (ret?.kind === "date" || + (ret?.kind === "union" && + ctx.unions.get(ret.unionId)?.arms.some((arm) => arm.kind === "func"))) + ) + ret = DYN; + if ( + ret && + sigDecl && + isJsSourceFile(sigDecl.getSourceFile()) && + functionCanReturnUndefined(sigDecl) + ) + ret = withUndefinedArm(ret, ctx.unions) ?? ret; + if (!ret) return null; + return typedRest + ? { kind: "func", params, ret, rest: true, restAbi: "typed" } + : dynRest + ? { kind: "func", params, ret, rest: true } + : funcOf(params, ret); +} + /** Retain a literal discriminator before widening erases its values. A * structural match alone is insufficient: `{ kind: "loop", body: ... }` * also fits a smaller `{ kind: "empty" }` record. Choosing that layout @@ -5599,6 +5638,164 @@ export function erasedGenericMemberType(t: ts.Type, ctx: TypeMapperCtx): IrType return erased?.kind === "func" ? erased : undefined; } +/** An OVERLOADED callable member type (`on(event: "a", h: (x: number) => + * void): () => void; on(event: "b", h: (x: string) => void): () => void` + * in a program interface or type literal): two or more call signatures and + * nothing else (no data properties, construct signatures, or index + * signatures), every one declared in TypeScript program source. Such a + * member keeps a record slot holding its erased runtime function + * (erasedOverloadMemberType); calls convert per their resolved overload + * (lowerRecordFieldCall). */ +export function isOverloadedCallableMemberType(t: ts.Type, checker: ts.TypeChecker): boolean { + const sigs = checker.getCallSignatures(t); + if (sigs.length < 2) return false; + if ( + checker.getConstructSignatures(t).length > 0 || + checker.getPropertiesOfType(t).length > 0 || + checker.getIndexInfosOfType(t).length > 0 + ) + return false; + return sigs.every((sig) => { + const decl = checker.signatureDeclaration(sig); + if (decl === undefined) return false; + if (!ts.isMethodSignatureDeclaration(decl) && !ts.isCallSignatureDeclaration(decl)) + return false; + const file = decl.getSourceFile(); + return !file.isDeclarationFile && !isJsSourceFile(file); + }); +} + +/** Scalar arms an overload join may combine into one union. */ +const OVERLOAD_JOIN_SCALARS = new Set(["f64", "string", "bool", "undefinedT", "nullT"]); + +/** The join of one position's types across an overload set: equal types + * stay; scalar mixes form their union; anything else is `unknown` when + * every joined type crosses the checked-dynamic boundary in both directions + * (the call site converts into the slot, the implementation converts out + * of it). Differing callbacks (`(x: number) => void` beside `(x: string) => + * void`) therefore travel as checked function values, which any + * implementation's own callback type adapts from. Null when no join + * exists. */ +function joinOverloadTypes(types: readonly IrType[], ctx: TypeMapperCtx): IrType | null { + const first = types[0]!; + if (types.every((t) => typeEquals(t, first))) return first; + const getRecord = (id: string) => ctx.shapes.get(id); + const getUnion = (id: string) => ctx.unions.get(id); + const arms = new Map(); + let scalar = true; + for (const t of types) { + const parts = t.kind === "union" ? (ctx.unions.get(t.unionId)?.arms ?? []) : [t]; + if (parts.length === 0) scalar = false; + for (const part of parts) { + if (!OVERLOAD_JOIN_SCALARS.has(part.kind)) scalar = false; + arms.set(typeKey(part), part); + } + } + if (scalar && [...arms.values()].some((arm) => !isUnitType(arm))) { + const sorted = [...arms.values()].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1)); + return { kind: "union", unionId: ctx.unions.intern(sorted) }; + } + if ( + types.every( + (t) => + t.kind === "dyn" || + (t.kind !== "void" && + canConvertToDyn(t, getRecord, getUnion) && + canDynCheckTo(t, getRecord, getUnion)), + ) + ) + return DYN; + return null; +} + +/** An overloaded member's runtime type (isOverloadedCallableMemberType). + * JavaScript stores ONE function under the member; overload signatures only + * constrain call sites. The slot's type joins the overloads per parameter + * position and result (joinOverloadTypes), and a position some overloads + * omit is optional. Each overload's own type parameters erase to `unknown` + * first. Calls pick their overload statically, convert arguments into the + * slot's parameter types and the result back to the overload's; an + * implementation converts into the slot like any function value. Undefined + * when the set does not join (rest parameters, a void result beside a + * value result, a component outside the checked-dynamic boundary): the + * member keeps its fence. */ +export function erasedOverloadMemberType(t: ts.Type, ctx: TypeMapperCtx): IrType | undefined { + const funcs: (IrType & { kind: "func" })[] = []; + for (const sig of ctx.checker.getCallSignatures(t)) { + const own = new Set(sig.getTypeParameters()); + const outer = ctx.resolveTypeParam; + const mapped = mapCallSignature( + sig, + own.size === 0 + ? ctx + : { + ...ctx, + erasingSignature: sig, + resolveTypeParam: (param) => (own.has(param) ? DYN : (outer?.(param) ?? null)), + }, + ); + if (mapped?.kind !== "func" || mapped.rest === true || mapped.argumentsAll === true) + return undefined; + funcs.push(mapped); + } + const arity = Math.max(...funcs.map((f) => f.params.length)); + const params: IrType[] = []; + for (let i = 0; i < arity; i++) { + const present = funcs.filter((f) => i < f.params.length).map((f) => f.params[i]!); + let param = joinOverloadTypes(present, ctx); + if (param !== null && present.length < funcs.length && param.kind !== "dyn") + param = withUndefinedArm(param, ctx.unions); + if (param === null) return undefined; + params.push(param); + } + const voids = funcs.filter((f) => f.ret.kind === "void").length; + if (voids !== 0 && voids !== funcs.length) return undefined; + const ret = + voids === funcs.length + ? VOID + : joinOverloadTypes( + funcs.map((f) => f.ret), + ctx, + ); + if (ret === null) return undefined; + return funcOf(params, ret); +} + +/** Why an overloaded member's set has no erased type + * (erasedOverloadMemberType): the first overload, and within it the first + * parameter or result, that does not map; otherwise the join itself. A + * message tail after "its member 'name'". */ +function describeOverloadSetBlocker(t: ts.Type, ctx: TypeMapperCtx): string { + const { checker } = ctx; + for (const sig of checker.getCallSignatures(t)) { + const own = new Set(sig.getTypeParameters()); + const outer = ctx.resolveTypeParam; + const sigCtx: TypeMapperCtx = + own.size === 0 + ? ctx + : { + ...ctx, + erasingSignature: sig, + resolveTypeParam: (param) => (own.has(param) ? DYN : (outer?.(param) ?? null)), + }; + const mapped = mapCallSignature(sig, sigCtx); + if (mapped?.kind === "func" && mapped.rest !== true && mapped.argumentsAll !== true) continue; + const decl = checker.signatureDeclaration(sig); + const spelled = decl ? decl.getText().replace(/\s+/g, " ").replace(/;$/, "") : ""; + const which = spelled ? `overload '${spelled}'` : "one overload"; + if (mapped?.kind === "func") + return `is an overload set, and its ${which} has a rest parameter (an overload set stores one fixed-arity function)`; + for (const param of sig.getParameters()) { + const paramTs = checker.getTypeOfSymbol(param); + if (!mapType(paramTs, sigCtx)) + return `is an overload set, and its ${which} has parameter '${param.name}' of type '${checker.typeToString(paramTs)}', which does not compile`; + } + const retTs = checker.getReturnTypeOfSignature(sig); + return `is an overload set, and its ${which} returns '${checker.typeToString(retTs)}', which does not compile`; + } + return "is an overload set whose signatures do not join into one stored function (a void result beside a value result, or positions whose differing types do not cross the checked-dynamic boundary)"; +} + /** The computed pieces of a record shape mapRecordTypeInner hands back for * the OUTER frame to intern — or, when a back-reference minted a recursive * placeholder for the type mid-construction, to finalize INTO that @@ -5980,9 +6177,14 @@ function mapRecordTypeInner( // can hold them — see isGenericCallableMemberType): the shape keeps // its data fields, and calls of the member monomorphize per call // site against the defining object literal's declaration. + // OVERLOADED members hold their erased runtime function (see + // erasedOverloadMemberType); a set that does not join fails the + // shape as before. let pt = isGenericCallableMemberType(fieldTs, checker) ? erasedGenericMemberType(fieldTs, ctx) - : mapType(fieldTs, ctx); + : isOverloadedCallableMemberType(fieldTs, checker) + ? (erasedOverloadMemberType(fieldTs, ctx) ?? null) + : mapType(fieldTs, ctx); if (pt === undefined) continue; // tsgo PANICS computing `readonly []` through the symbol-type query // (the TupleType conversion — the facade's panic fence answers @@ -6354,6 +6556,10 @@ export function describeRecordMemberBlocker(widened: ts.Type, ctx: TypeMapperCtx return null; } const fieldTs = checker.getTypeOfSymbol(p); + if (isOverloadedCallableMemberType(fieldTs, checker)) { + if (erasedOverloadMemberType(fieldTs, ctx) !== undefined) continue; + return `the record shape is supported, but its member '${p.name}' ${describeOverloadSetBlocker(fieldTs, ctx)}`; + } let pt = isGenericCallableMemberType(fieldTs, checker) ? erasedGenericMemberType(fieldTs, ctx) : mapType(fieldTs, ctx); diff --git a/packages/compiler/src/ir/builtin-effects.ts b/packages/compiler/src/ir/builtin-effects.ts index 155c097d5..2a6c249d4 100644 --- a/packages/compiler/src/ir/builtin-effects.ts +++ b/packages/compiler/src/ir/builtin-effects.ts @@ -137,6 +137,7 @@ export const MAY_THROW_LIB_FNS: ReadonlySet = new Set([ "fetch.streamFrom", "num.toFixed", "num.toStringRadix", + "num.toStringRadixF64", "insp.jsonDyn", // diagnostics_channel: publish runs subscribers synchronously (a throw // propagates — the documented divergence from triggerUncaughtException); diff --git a/packages/compiler/src/ir/builtin-signatures.ts b/packages/compiler/src/ir/builtin-signatures.ts index 8015c104a..56826be26 100644 --- a/packages/compiler/src/ir/builtin-signatures.ts +++ b/packages/compiler/src/ir/builtin-signatures.ts @@ -755,6 +755,9 @@ export const LIB_FN_SIGS = defineLibFnSignatures({ "num.toFixed0": { argTypes: [F64], result: STRING }, "num.toFixed": { argTypes: [F64, F64], result: STRING }, "num.toStringRadix": { argTypes: [F64, DYN], result: STRING }, + /** toString(radix) with a number radix (scr_lib.c): truncates it as + * ToIntegerOrInfinity does, THROWS RangeError outside 2..36. */ + "num.toStringRadixF64": { argTypes: [F64, F64], result: STRING }, /** Object.is over two numbers — the spec's SameValue on doubles: NaN * equals NaN, +0 differs from -0, everything else is `===`. Plain bool * result; never throws. (Union-armed operands take unionEq's sameValue diff --git a/packages/compiler/src/ir/ir.ts b/packages/compiler/src/ir/ir.ts index be6519a9d..1c933f8bd 100644 --- a/packages/compiler/src/ir/ir.ts +++ b/packages/compiler/src/ir/ir.ts @@ -1673,7 +1673,15 @@ export interface IrFunction { * out, `nextT` what `.next(v)` sends in (the yield expression's result * type). `async` alongside this field marks an async generator: its * resume methods queue requests and return promises. */ - generator?: { yieldT: IrType; nextT: IrType; resultType: IrType & { kind: "record" } }; + generator?: { + yieldT: IrType; + nextT: IrType; + resultType: IrType & { kind: "record" }; + /** The first parameter is a generator this one reads from (an + * iterator helper's source): `.return()` before the first `.next()` + * closes it. */ + closesSource?: true; + }; /** Source function name for native error stack frames. */ sourceName?: string; /** Ordinary authored function declarations/expressions own a prototype. */ @@ -1946,6 +1954,11 @@ export type IrStmt = /** Resource-management cleanup: if the guarded body and cleanup both * throw, raise a SuppressedError instead of replacing the first error. */ suppressFinallyErrors?: true; + /** Iterator closing: if the guarded body threw and the cleanup throws + * too, the cleanup's error is dropped and the first one propagates. + * After a generator .return() the cleanup's error replaces it, and on + * normal exits it propagates. */ + dropFinallyErrors?: true; loc: SrcLoc; }; diff --git a/packages/compiler/src/wasm/binary.test.ts b/packages/compiler/src/wasm/binary.test.ts new file mode 100644 index 000000000..5f95f91d2 --- /dev/null +++ b/packages/compiler/src/wasm/binary.test.ts @@ -0,0 +1,244 @@ +import { describe, expect, test } from "vitest"; +import { analyzeWasm, isTranslatableFeature, isWasmHeader } from "./binary.js"; + +/** V8's verdict (the compiler's type world declares no WebAssembly value). */ +const v8Validate = (bytes: Uint8Array): boolean => + ( + globalThis as unknown as { WebAssembly: { validate(bytes: Uint8Array): boolean } } + ).WebAssembly.validate(bytes); + +// A minimal module assembler: enough structure to aim at one decoder rule +// per test. Every module is also checked against V8 (Node is the oracle). + +function leb(n: number): number[] { + const out: number[] = []; + do { + let b = n % 128; + n = Math.floor(n / 128); + if (n > 0) b |= 0x80; + out.push(b); + } while (n > 0); + return out; +} + +function name(text: string): number[] { + const bytes = [...new TextEncoder().encode(text)]; + return [...leb(bytes.length), ...bytes]; +} + +function vec(items: number[][]): number[] { + return [...leb(items.length), ...items.flat()]; +} + +function section(id: number, body: number[]): number[] { + return [id, ...leb(body.length), ...body]; +} + +function module(...sections: number[][]): Uint8Array { + return new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, ...sections.flat()]); +} + +const I32 = 0x7f; +const I64 = 0x7e; +const F32 = 0x7d; +const V128 = 0x7b; +const EXTERNREF = 0x6f; + +const funcType = (params: number[], results: number[]): number[] => [ + 0x60, + ...vec(params.map((p) => [p])), + ...vec(results.map((r) => [r])), +]; +const types = (...fts: number[][]): number[] => section(1, vec(fts)); +const funcs = (...typeIndices: number[]): number[] => + section(3, vec(typeIndices.map((t) => leb(t)))); +const body = (code: number[], locals: number[][] = []): number[] => { + const content = [...vec(locals), ...code, 0x0b]; + return [...leb(content.length), ...content]; +}; +const code = (...bodies: number[][]): number[] => section(10, vec(bodies)); +const memory = (...limits: number[][]): number[] => section(5, vec(limits)); +const exportsOf = (...entries: number[][]): number[] => section(7, vec(entries)); + +function check(bytes: Uint8Array) { + const summary = analyzeWasm(bytes); + const accepted = summary.status === "valid" || summary.status === "unsupported"; + expect(accepted, summary.error ?? "").toBe(v8Validate(bytes)); + return summary; +} + +describe("analyzeWasm", () => { + test("an empty module is valid and uses no proposal", () => { + const s = check(module()); + expect(s).toMatchObject({ status: "valid", error: null, features: [], functions: 0, size: 8 }); + expect(isWasmHeader(module())).toBe(true); + }); + + test("counts functions, imports, exports, memories, tables and globals", () => { + const s = check( + module( + types(funcType([I32, I32], [I32]), funcType([], [])), + section( + 2, + vec([ + [...name("env"), ...name("log"), 0x00, 0x01], + [...name("wasi_snapshot_preview1"), ...name("proc_exit"), 0x00, 0x01], + ]), + ), + funcs(0), + section(4, vec([[0x70, 0x00, 0x01]])), + memory([0x00, 0x01]), + section(6, vec([[I32, 0x01, 0x41, 0x00, 0x0b]])), + exportsOf([...name("add"), 0x00, 0x02], [...name("memory"), 0x02, 0x00]), + code(body([0x20, 0x00, 0x20, 0x01, 0x6a])), + ), + ); + expect(s).toMatchObject({ + status: "valid", + functions: 1, + imports: 2, + exports: 2, + importModules: ["env", "wasi_snapshot_preview1"], + memories: 1, + tables: 1, + globals: 1, + }); + }); + + test.each([ + [ + "sign-extension", + module(types(funcType([I32], [I32])), funcs(0), code(body([0x20, 0x00, 0xc0]))), + ], + [ + "nontrapping-fptoint", + module(types(funcType([F32], [I32])), funcs(0), code(body([0x20, 0x00, 0xfc, 0x00]))), + ], + [ + "bulk-memory", + module( + types(funcType([], [])), + funcs(0), + memory([0x00, 0x01]), + code(body([0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xfc, 0x0b, 0x00])), + ), + ], + [ + "multi-value", + module(types(funcType([], [I32, I64])), funcs(0), code(body([0x41, 0x01, 0x42, 0x02]))), + ], + ["reference-types", module(section(4, vec([[EXTERNREF, 0x00, 0x01]])))], + ["extended-const", module(section(6, vec([[I32, 0x00, 0x41, 0x01, 0x41, 0x02, 0x6a, 0x0b]])))], + [ + "mutable-globals", + module(section(2, vec([[...name("env"), ...name("sp"), 0x03, I32, 0x01]]))), + ], + ])("detects %s and stays translatable", (feature, bytes) => { + const s = check(bytes); + expect(s.status).toBe("valid"); + expect(s.features).toContain(feature); + expect(isTranslatableFeature(feature)).toBe(true); + }); + + test.each([ + [ + "simd", + module( + types(funcType([], [V128])), + funcs(0), + code(body([0xfd, 0x0c, ...Array.from({ length: 16 }, () => 0)])), + ), + ], + ["threads", module(memory([0x03, 0x01, 0x01]))], + ["exceptions", module(types(funcType([], [])), section(13, vec([[0x00, 0x00]])))], + ["tail-call", module(types(funcType([], [])), funcs(0), code(body([0x12, 0x00])))], + ["memory64", module(memory([0x04, 0x01]))], + ["multi-memory", module(memory([0x00, 0x01], [0x00, 0x01]))], + ["gc", module(section(1, vec([[0x5f, 0x00]])))], + ])("reports %s as outside the translatable set", (feature, bytes) => { + const s = check(bytes); + expect(s.status).toBe("unsupported"); + expect(s.unsupported).toEqual([feature]); + expect(isTranslatableFeature(feature)).toBe(false); + }); + + test.each([ + ["bad magic", new Uint8Array([0x00, 0x61, 0x73, 0x6e, 1, 0, 0, 0]), "malformed", "magic"], + ["bad version", new Uint8Array([0x00, 0x61, 0x73, 0x6d, 2, 0, 0, 0]), "malformed", "version"], + ["sections out of order", module(funcs(), types()), "malformed", "unexpected section"], + ["section size mismatch", module([0x01, 0x02, 0x00, 0x00]), "malformed", "section size"], + [ + "overlong integer", + module([0x01, 0x06, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00]), + "malformed", + "integer", + ], + ["invalid UTF-8 name", module(exportsOf([0x01, 0xff, 0x00, 0x00])), "malformed", "UTF-8"], + [ + "function and code counts differ", + module(types(funcType([], [])), funcs(0, 0), code(body([]))), + "malformed", + "inconsistent", + ], + [ + "illegal opcode", + module(types(funcType([], [])), funcs(0), code(body([0xff]))), + "malformed", + "illegal opcode", + ], + [ + "memory.init without a data count section", + module( + types(funcType([], [])), + funcs(0), + memory([0x00, 0x01]), + code(body([0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xfc, 0x08, 0x00, 0x00])), + ), + "malformed", + "data count", + ], + [ + "type mismatch", + module(types(funcType([], [I32])), funcs(0), code(body([0x42, 0x00]))), + "invalid", + "type mismatch", + ], + [ + "unknown function", + module(types(funcType([], [])), funcs(0), code(body([0x10, 0x05]))), + "invalid", + "unknown function", + ], + [ + "duplicate export", + module( + types(funcType([], [])), + funcs(0), + exportsOf([...name("f"), 0x00, 0x00], [...name("f"), 0x00, 0x00]), + code(body([])), + ), + "invalid", + "duplicate export", + ], + ["memory above 4 GiB", module(memory([0x00, ...leb(65537)])), "invalid", "65536 pages"], + [ + "undeclared function reference", + module(types(funcType([], [])), funcs(0), code(body([0xd2, 0x00, 0x1a]))), + "invalid", + "undeclared", + ], + ])("rejects %s", (_label, bytes, status, message) => { + const s = check(bytes); + expect(s.status).toBe(status); + expect(s.error).toContain(message); + }); + + test("never throws on truncated input", () => { + const whole = module( + types(funcType([I32, I32], [I32])), + funcs(0), + code(body([0x20, 0x00, 0x20, 0x01, 0x6a])), + ); + for (let n = 0; n < whole.length; n++) check(whole.subarray(0, n)); + }); +}); diff --git a/packages/compiler/src/wasm/binary.ts b/packages/compiler/src/wasm/binary.ts new file mode 100644 index 000000000..5ddc28cc9 --- /dev/null +++ b/packages/compiler/src/wasm/binary.ts @@ -0,0 +1,1957 @@ +/* The WebAssembly binary decoder and validator. + * + * Decodes a module completely and validates it against the feature level + * scriptc means to translate to native code: the MVP plus the finished + * post-MVP proposals that real npm modules use (sign-extension operators, + * non-trapping float-to-int conversions, bulk memory, multi-value, mutable + * globals, reference types and extended constant expressions). Where the + * WebAssembly 3.0 specification and V8 relax a 2.0 rule inside that set (a + * global initializer may read any earlier immutable global), the decoder + * follows them, because Node is the behavior oracle. + * + * Modules that use a proposal outside that set (SIMD, threads, exception + * handling, tail calls, function references and GC, memory64, multiple + * memories) still decode: the instructions that need the proposal are read + * for their immediates but not type-checked, and the summary names the + * proposal so that the module can be reported as not translatable rather + * than as invalid. Only GC type definitions stop the decode, since their + * layout would need the full GC type system. + * + * 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. */ + +/** Proposals the summary can name, in report order. The first group is the + * translatable set; the rest are reported as unsupported. */ +export const WASM_FEATURES = [ + "mutable-globals", + "sign-extension", + "nontrapping-fptoint", + "bulk-memory", + "multi-value", + "reference-types", + "extended-const", + "simd", + "threads", + "exceptions", + "tail-call", + "function-references", + "gc", + "memory64", + "multi-memory", +] as const; +export type WasmFeature = (typeof WASM_FEATURES)[number]; + +const TRANSLATABLE: ReadonlySet = new Set([ + "mutable-globals", + "sign-extension", + "nontrapping-fptoint", + "bulk-memory", + "multi-value", + "reference-types", + "extended-const", +]); + +/** True for proposals inside the translatable feature level. */ +export function isTranslatableFeature(feature: string): boolean { + return TRANSLATABLE.has(feature); +} + +/** What a decoded module reports. `status` is "valid" when the module + * validates within the translatable feature level, "unsupported" when it + * uses a proposal outside it (and is otherwise well-formed as far as the + * decoder checks), and "malformed" or "invalid" for a module that every + * engine rejects; `error` then says where and why. */ +export interface WasmModuleSummary { + size: number; + status: "valid" | "unsupported" | "malformed" | "invalid"; + error: string | null; + features: string[]; + unsupported: string[]; + functions: number; + imports: number; + exports: number; + importModules: string[]; + memories: number; + tables: number; + globals: number; + customSections: string[]; +} + +/** A decode failure: malformed bytes or an invalid module. */ +export class WasmError extends Error { + kind: "malformed" | "invalid"; + offset: number; + constructor(kind: "malformed" | "invalid", message: string, offset: number) { + super(message); + this.kind = kind; + this.offset = offset; + } +} + +// Value types. Zero is the "unknown" type of unreachable code. +const UNKNOWN = 0; +const I32 = 0x7f; +const I64 = 0x7e; +const F32 = 0x7d; +const F64 = 0x7c; +const V128 = 0x7b; +const FUNCREF = 0x70; +const EXTERNREF = 0x6f; + +// V8's implementation limits that are part of validation (wasm-limits.h). +const MAX_TYPES = 1000000; +const MAX_FUNCTIONS = 1000000; +const MAX_IMPORTS = 100000; +const MAX_EXPORTS = 100000; +const MAX_GLOBALS = 1000000; +const MAX_DATA_SEGMENTS = 100000; +const MAX_LOCALS = 50000; +const MAX_PARAMS = 1000; +const MAX_RESULTS = 1000; +const MAX_FUNCTION_SIZE = 7654321; +const MAX_MEMORY_PAGES = 65536; +const MAX_TABLE_INIT = 10000000; + +interface FuncType { + params: number[]; + results: number[]; +} + +interface Global { + type: number; + mutable: boolean; + imported: boolean; +} + +interface Table { + type: number; +} + +interface Frame { + opcode: number; + start: number[]; + end: number[]; + height: number; + unreachable: boolean; + /** An `if` that has not seen its `else`. */ + hasElse: boolean; +} + +class Reader { + bytes: Uint8Array; + pos: number; + end: number; + constructor(bytes: Uint8Array, pos: number, end: number) { + this.bytes = bytes; + this.pos = pos; + this.end = end; + } + + malformed(message: string): never { + throw new WasmError("malformed", message, this.pos); + } + + eof(): boolean { + return this.pos >= this.end; + } + + u8(): number { + if (this.pos >= this.end) this.malformed("unexpected end"); + const b = this.bytes[this.pos]!; + this.pos++; + return b; + } + + peek(): number { + if (this.pos >= this.end) this.malformed("unexpected end"); + return this.bytes[this.pos]!; + } + + skip(n: number): void { + if (n > this.end - this.pos) this.malformed("unexpected end"); + this.pos += n; + } + + u32(): number { + let result = 0; + let scale = 1; + for (let i = 0; i < 5; i++) { + const b = this.u8(); + if (i === 4 && (b & 0xf0) !== 0) { + this.malformed(b & 0x80 ? "integer representation too long" : "integer too large"); + } + result += (b & 0x7f) * scale; + if ((b & 0x80) === 0) return result; + scale *= 128; + } + return this.malformed("integer representation too long"); + } + + /** A signed LEB128 of `bits` bits (32, 33 or 64); answers the value for + * 32 and 33 bits and 0 for 64 (no caller needs it). */ + sleb(bits: number): number { + const maxBytes = Math.ceil(bits / 7); + let result = 0; + let scale = 1; + for (let i = 0; i < maxBytes; i++) { + const b = this.u8(); + if (i === maxBytes - 1) { + // The final byte's bits above the value's width must repeat its + // sign bit, and it may not continue. + if (b & 0x80) this.malformed("integer representation too long"); + const used = bits - 7 * i; + const unused = (b >> (used - 1)) & ((1 << (8 - used)) - 1) & 0x7f; + const all = (1 << (7 - used + 1)) - 1; + if (unused !== 0 && unused !== all) this.malformed("integer too large"); + } + if (bits < 64) result += (b & 0x7f) * scale; + scale *= 128; + if ((b & 0x80) === 0) { + if (bits < 64 && b & 0x40) result -= scale; + return bits < 64 ? result : 0; + } + } + return this.malformed("integer representation too long"); + } + + u64(): void { + this.sleb(64); + } + + name(): string { + const length = this.u32(); + if (length > this.end - this.pos) this.malformed("length out of bounds"); + const start = this.pos; + this.pos += length; + return utf8(this.bytes, start, this.pos, this); + } +} + +function utf8(bytes: Uint8Array, start: number, end: number, reader: Reader): string { + let out = ""; + let i = start; + while (i < end) { + const b = bytes[i]!; + let cp = 0; + let need = 0; + if (b < 0x80) { + cp = b; + } else if (b >= 0xc2 && b <= 0xdf) { + cp = b & 0x1f; + need = 1; + } else if (b >= 0xe0 && b <= 0xef) { + cp = b & 0x0f; + need = 2; + } else if (b >= 0xf0 && b <= 0xf4) { + cp = b & 0x07; + need = 3; + } else { + reader.malformed("malformed UTF-8 encoding"); + } + if (i + need >= end) reader.malformed("malformed UTF-8 encoding"); + for (let k = 1; k <= need; k++) { + const c = bytes[i + k]!; + if ((c & 0xc0) !== 0x80) reader.malformed("malformed UTF-8 encoding"); + cp = cp * 64 + (c & 0x3f); + } + if ( + (need === 2 && (cp < 0x800 || (cp >= 0xd800 && cp <= 0xdfff))) || + (need === 3 && (cp < 0x10000 || cp > 0x10ffff)) + ) { + reader.malformed("malformed UTF-8 encoding"); + } + out += String.fromCodePoint(cp); + i += need + 1; + } + return out; +} + +/** Load and store natural alignments (log2) by opcode, 0x28..0x3e. */ +const MEMORY_ALIGN = [2, 3, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 2, 3, 2, 3, 0, 1, 0, 1, 2]; +/** Load result / store operand types by opcode, 0x28..0x3e. */ +const MEMORY_TYPE = [ + I32, + I64, + F32, + F64, + I32, + I32, + I32, + I32, + I64, + I64, + I64, + I64, + I64, + I64, + I32, + I64, + F32, + F64, + I32, + I32, + I64, + I64, + I64, +]; + +/** Numeric instruction signatures, 0x45..0xc4: operand type, operand + * count, result type. */ +function numericSignature(op: number): [number, number, number] { + if (op === 0x45) return [I32, 1, I32]; + if (op <= 0x4f) return [I32, 2, I32]; + if (op === 0x50) return [I64, 1, I32]; + if (op <= 0x5a) return [I64, 2, I32]; + if (op <= 0x60) return [F32, 2, I32]; + if (op <= 0x66) return [F64, 2, I32]; + if (op <= 0x69) return [I32, 1, I32]; + if (op <= 0x78) return [I32, 2, I32]; + if (op <= 0x7b) return [I64, 1, I64]; + if (op <= 0x8a) return [I64, 2, I64]; + if (op <= 0x91) return [F32, 1, F32]; + if (op <= 0x98) return [F32, 2, F32]; + if (op <= 0x9f) return [F64, 1, F64]; + if (op <= 0xa6) return [F64, 2, F64]; + switch (op) { + case 0xa7: + return [I64, 1, I32]; + case 0xa8: + case 0xa9: + return [F32, 1, I32]; + case 0xaa: + case 0xab: + return [F64, 1, I32]; + case 0xac: + case 0xad: + return [I32, 1, I64]; + case 0xae: + case 0xaf: + return [F32, 1, I64]; + case 0xb0: + case 0xb1: + return [F64, 1, I64]; + case 0xb2: + case 0xb3: + return [I32, 1, F32]; + case 0xb4: + case 0xb5: + return [I64, 1, F32]; + case 0xb6: + return [F64, 1, F32]; + case 0xb7: + case 0xb8: + return [I32, 1, F64]; + case 0xb9: + case 0xba: + return [I64, 1, F64]; + case 0xbb: + return [F32, 1, F64]; + case 0xbc: + return [F32, 1, I32]; + case 0xbd: + return [F64, 1, I64]; + case 0xbe: + return [I32, 1, F32]; + case 0xbf: + return [I64, 1, F64]; + case 0xc0: + case 0xc1: + return [I32, 1, I32]; + default: + return [I64, 1, I64]; + } +} + +const SECTION_ORDER: Record = { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 13: 6, + 6: 7, + 7: 8, + 8: 9, + 9: 10, + 12: 11, + 10: 12, + 11: 13, +}; + +class ModuleDecoder { + bytes: Uint8Array; + features = new Set(); + types: FuncType[] = []; + funcs: number[] = []; + importedFuncs = 0; + tables: Table[] = []; + memories = 0; + memory64 = false; + globals: Global[] = []; + importedGlobals = 0; + tags = 0; + elemTypes: number[] = []; + dataCount: number | null = null; + dataSegments = 0; + declaredRefs = new Set(); + exportNames = new Set(); + importModules: string[] = []; + customSections: string[] = []; + imports = 0; + exports = 0; + codeCount = 0; + sawCode = false; + /** A type definition outside the function-type subset stopped typing. */ + gcTypes = false; + + constructor(bytes: Uint8Array) { + this.bytes = bytes; + } + + invalid(message: string, offset: number): never { + throw new WasmError("invalid", message, offset); + } + + feature(name: WasmFeature): void { + this.features.add(name); + } + + // ── types ──────────────────────────────────────────────────────────── + + /** A value type; GC and exception-handling reference types are named as + * features and answer UNKNOWN (the code that uses them is not typed). */ + valType(r: Reader): number { + const b = r.u8(); + switch (b) { + case I32: + case I64: + case F32: + case F64: + return b; + case V128: + this.feature("simd"); + return V128; + case FUNCREF: + case EXTERNREF: + return b; + default: + return this.otherRefType(r, b); + } + } + + otherRefType(r: Reader, b: number): number { + if (b === 0x63 || b === 0x64) { + // (ref null ht) / (ref ht): a heap type follows. + this.feature("function-references"); + this.heapType(r); + return UNKNOWN; + } + if (b === 0x69 || b === 0x68 || b === 0x74 || b === 0x75) { + this.feature("exceptions"); + return UNKNOWN; + } + if (b >= 0x6a && b <= 0x73) { + // anyref, eqref, i31ref, structref, arrayref, nullref, ... + this.feature("gc"); + return UNKNOWN; + } + return r.malformed("malformed value type"); + } + + heapType(r: Reader): void { + const b = r.peek(); + if (b >= 0x60 && b <= 0x7f) { + r.u8(); + if (b === 0x69 || b === 0x74) this.feature("exceptions"); + else if (b !== FUNCREF && b !== EXTERNREF) this.feature("gc"); + return; + } + // A concrete heap type: a typed function reference. + const offset = r.pos; + const index = r.sleb(33); + if (index < 0) r.malformed("malformed heap type"); + this.feature("function-references"); + if (index >= this.types.length && !this.gcTypes) this.invalid(`unknown type ${index}`, offset); + } + + refType(r: Reader): number { + const b = r.u8(); + if (b === FUNCREF || b === EXTERNREF) return b; + if (b >= 0x63 && b <= 0x75 && b !== 0x67 && b !== 0x66 && b !== 0x65) { + this.otherRefType(r, b); + return UNKNOWN; + } + return r.malformed("malformed reference type"); + } + + typeSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_TYPES) r.malformed("too many types"); + for (let i = 0; i < count; i++) { + const form = r.u8(); + if (form === 0x60) { + this.types.push(this.funcType(r)); + continue; + } + if (form === 0x4e || form === 0x50 || form === 0x4f || form === 0x5f || form === 0x5e) { + // Recursive groups, subtypes, structs and arrays: the GC type + // system. Stop decoding types; nothing after them can be typed. + this.feature("gc"); + this.gcTypes = true; + r.pos = r.end; + return; + } + r.malformed("malformed function type"); + } + } + + funcType(r: Reader): FuncType { + const params: number[] = []; + const nParams = r.u32(); + if (nParams > MAX_PARAMS) r.malformed("too many parameters"); + for (let i = 0; i < nParams; i++) params.push(this.valType(r)); + const results: number[] = []; + const nResults = r.u32(); + if (nResults > MAX_RESULTS) r.malformed("too many results"); + for (let i = 0; i < nResults; i++) results.push(this.valType(r)); + if (results.length > 1) this.feature("multi-value"); + return { params, results }; + } + + funcTypeAt(index: number, offset: number): FuncType { + if (index >= this.types.length) { + if (this.gcTypes) return { params: [], results: [] }; + this.invalid(`unknown type ${index}`, offset); + } + return this.types[index]!; + } + + limits(r: Reader, kind: "memory" | "table"): { min: number; max: number | null } { + const flags = r.u8(); + if (kind === "memory") { + if (flags > 0x07) r.malformed("malformed limits flags"); + if (flags & 0x02) this.feature("threads"); + if (flags & 0x04) { + this.feature("memory64"); + this.memory64 = true; + } + } else { + // Tables: a maximum flag and the table64 flag; no shared tables. + if ((flags & ~0x05) !== 0) r.malformed("malformed limits flags"); + if (flags & 0x04) this.feature("memory64"); + } + const wide = (flags & 0x04) !== 0; + const min = wide ? (r.u64(), 0) : r.u32(); + let max: number | null = null; + if (flags & 0x01) max = wide ? (r.u64(), 0) : r.u32(); + if (kind === "memory" && flags & 0x02 && max === null && !wide) { + this.invalid("shared memory must have maximum", r.pos); + } + return { min, max }; + } + + memoryType(r: Reader): void { + const offset = r.pos; + const { min, max } = this.limits(r, "memory"); + if (this.memory64) return; + if (min > MAX_MEMORY_PAGES) + this.invalid("memory size must be at most 65536 pages (4GiB)", offset); + if (max !== null && max > MAX_MEMORY_PAGES) { + this.invalid("memory size must be at most 65536 pages (4GiB)", offset); + } + if (max !== null && min > max) + this.invalid("size minimum must not be greater than maximum", offset); + } + + addMemory(): void { + this.memories++; + if (this.memories > 1) this.feature("multi-memory"); + } + + tableType(r: Reader): Table { + const offset = r.pos; + if (r.peek() === 0x40) { + // A table with an explicit initializer (function references). + r.u8(); + if (r.u8() !== 0x00) r.malformed("malformed table type"); + this.feature("function-references"); + } + const type = this.refType(r); + const { min, max } = this.limits(r, "table"); + if (min > MAX_TABLE_INIT) this.invalid("table size must be at most 10000000", offset); + if (max !== null && min > max) + this.invalid("size minimum must not be greater than maximum", offset); + return { type }; + } + + addTable(table: Table): void { + this.tables.push(table); + if (this.tables.length > 1) this.feature("reference-types"); + if (table.type === EXTERNREF) this.feature("reference-types"); + } + + globalType(r: Reader): Global { + const type = this.valType(r); + if (type === FUNCREF || type === EXTERNREF) this.feature("reference-types"); + const mut = r.u8(); + if (mut > 1) r.malformed("malformed mutability"); + return { type, mutable: mut === 1, imported: false }; + } + + // ── sections ───────────────────────────────────────────────────────── + + importSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_IMPORTS) r.malformed("too many imports"); + for (let i = 0; i < count; i++) { + const module = r.name(); + r.name(); + if (!this.importModules.includes(module)) this.importModules.push(module); + this.imports++; + const offset = r.pos; + const kind = r.u8(); + switch (kind) { + case 0x00: { + const index = r.u32(); + this.funcTypeAt(index, offset); + this.funcs.push(index); + this.importedFuncs++; + break; + } + case 0x01: + this.addTable(this.tableType(r)); + break; + case 0x02: + this.memoryType(r); + this.addMemory(); + break; + case 0x03: { + const global = this.globalType(r); + if (global.mutable) this.feature("mutable-globals"); + global.imported = true; + this.globals.push(global); + this.importedGlobals++; + break; + } + case 0x04: + this.tagType(r); + break; + default: + r.malformed("malformed import kind"); + } + } + } + + tagType(r: Reader): void { + const offset = r.pos; + this.feature("exceptions"); + if (r.u8() !== 0x00) r.malformed("malformed tag attribute"); + const type = this.funcTypeAt(r.u32(), offset); + if (type.results.length !== 0 && !this.gcTypes) + this.invalid("non-empty tag result type", offset); + this.tags++; + } + + functionSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_FUNCTIONS) r.malformed("too many functions"); + for (let i = 0; i < count; i++) { + const offset = r.pos; + const index = r.u32(); + this.funcTypeAt(index, offset); + this.funcs.push(index); + } + } + + tableSection(r: Reader): void { + const count = r.u32(); + for (let i = 0; i < count; i++) { + const hasInit = r.peek() === 0x40; + const table = this.tableType(r); + if (hasInit) this.constExpr(r, table.type); + this.addTable(table); + } + } + + memorySection(r: Reader): void { + const count = r.u32(); + for (let i = 0; i < count; i++) { + this.memoryType(r); + this.addMemory(); + } + } + + tagSection(r: Reader): void { + const count = r.u32(); + for (let i = 0; i < count; i++) this.tagType(r); + } + + globalSection(r: Reader): void { + const count = r.u32(); + if (count + this.globals.length > MAX_GLOBALS) r.malformed("too many globals"); + for (let i = 0; i < count; i++) { + const global = this.globalType(r); + this.constExpr(r, global.type); + this.globals.push(global); + } + } + + exportSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_EXPORTS) r.malformed("too many exports"); + for (let i = 0; i < count; i++) { + const offset = r.pos; + const name = r.name(); + if (this.exportNames.has(name)) this.invalid("duplicate export name", offset); + this.exportNames.add(name); + this.exports++; + const kind = r.u8(); + const indexOffset = r.pos; + const index = r.u32(); + switch (kind) { + case 0x00: + if (index >= this.funcs.length) this.invalid(`unknown function ${index}`, indexOffset); + this.declaredRefs.add(index); + break; + case 0x01: + if (index >= this.tables.length) this.invalid(`unknown table ${index}`, indexOffset); + break; + case 0x02: + if (index >= this.memories) this.invalid(`unknown memory ${index}`, indexOffset); + break; + case 0x03: + if (index >= this.globals.length) this.invalid(`unknown global ${index}`, indexOffset); + if (this.globals[index]!.mutable) this.feature("mutable-globals"); + break; + case 0x04: + if (index >= this.tags) this.invalid(`unknown tag ${index}`, indexOffset); + break; + default: + r.malformed("malformed export kind"); + } + } + } + + startSection(r: Reader): void { + const offset = r.pos; + const index = r.u32(); + if (index >= this.funcs.length) this.invalid(`unknown function ${index}`, offset); + const type = this.funcTypeAt(this.funcs[index]!, offset); + if (type.params.length !== 0 || type.results.length !== 0) { + this.invalid("start function must have type [] -> []", offset); + } + } + + elementSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_TABLE_INIT) r.malformed("too many element segments"); + for (let i = 0; i < count; i++) { + const offset = r.pos; + const flags = r.u32(); + if (flags > 7) r.malformed("malformed elements segment kind"); + const passiveOrDeclarative = (flags & 0x01) !== 0; + const explicitTable = (flags & 0x02) !== 0; + const usesExprs = (flags & 0x04) !== 0; + if (flags !== 0) this.feature(usesExprs || explicitTable ? "reference-types" : "bulk-memory"); + let tableIndex = 0; + if (!passiveOrDeclarative) { + if (explicitTable) tableIndex = r.u32(); + if (tableIndex >= this.tables.length) this.invalid(`unknown table ${tableIndex}`, offset); + this.constExpr(r, this.memory64 ? UNKNOWN : I32); + } + let elemType = FUNCREF; + if (passiveOrDeclarative || explicitTable) { + if (usesExprs) { + elemType = this.refType(r); + } else if (r.u8() !== 0x00) { + r.malformed("malformed element kind"); + } + } + if (!passiveOrDeclarative) { + const tableType = this.tables[tableIndex]!.type; + if (elemType !== UNKNOWN && tableType !== UNKNOWN && elemType !== tableType) { + this.invalid("type mismatch", offset); + } + } + const n = r.u32(); + for (let k = 0; k < n; k++) { + if (usesExprs) { + this.constExpr(r, elemType); + } else { + const at = r.pos; + const index = r.u32(); + if (index >= this.funcs.length) this.invalid(`unknown function ${index}`, at); + this.declaredRefs.add(index); + } + } + this.elemTypes.push(elemType); + } + } + + dataCountSection(r: Reader): void { + this.dataCount = r.u32(); + this.feature("bulk-memory"); + } + + dataSection(r: Reader): void { + const count = r.u32(); + if (count > MAX_DATA_SEGMENTS) r.malformed("too many data segments"); + if (this.dataCount !== null && count !== this.dataCount) { + r.malformed("data count and data section have inconsistent lengths"); + } + for (let i = 0; i < count; i++) { + const offset = r.pos; + const flags = r.u32(); + if (flags > 2) r.malformed("malformed data segment kind"); + if (flags !== 1) { + let memory = 0; + if (flags === 2) memory = r.u32(); + if (memory !== 0) this.feature("multi-memory"); + if (memory >= this.memories) this.invalid(`unknown memory ${memory}`, offset); + this.constExpr(r, this.memory64 ? UNKNOWN : I32); + } else { + this.feature("bulk-memory"); + } + const length = r.u32(); + r.skip(length); + } + this.dataSegments = count; + } + + customSection(r: Reader): void { + this.customSections.push(r.name()); + r.pos = r.end; + } + + // ── constant expressions ──────────────────────────────────────────── + + /** A constant expression producing `expected` (UNKNOWN: not checked). + * global.get may read any earlier immutable global, as in 3.0 and V8 + * (2.0 allowed only imported ones in global initializers). */ + constExpr(r: Reader, expected: number): void { + const stack: number[] = []; + const start = r.pos; + for (;;) { + const offset = r.pos; + const op = r.u8(); + switch (op) { + case 0x0b: { + if (expected !== UNKNOWN) { + if (stack.length !== 1 || !matches(stack[0]!, expected)) { + this.invalid("type mismatch", start); + } + } + return; + } + case 0x41: + r.sleb(32); + stack.push(I32); + break; + case 0x42: + r.sleb(64); + stack.push(I64); + break; + case 0x43: + r.skip(4); + stack.push(F32); + break; + case 0x44: + r.skip(8); + stack.push(F64); + break; + case 0x23: { + // A global initializer sees the globals before it (they are all + // that exist yet); offsets see every global. + const index = r.u32(); + if (index >= this.globals.length) this.invalid(`unknown global ${index}`, offset); + const global = this.globals[index]!; + if (global.mutable) this.invalid("constant expression required", offset); + stack.push(global.type); + break; + } + case 0xd0: { + this.feature("reference-types"); + const t = this.refHeapNull(r); + stack.push(t); + break; + } + case 0xd2: { + this.feature("reference-types"); + const index = r.u32(); + if (index >= this.funcs.length) this.invalid(`unknown function ${index}`, offset); + this.declaredRefs.add(index); + stack.push(FUNCREF); + break; + } + case 0x6a: + case 0x6b: + case 0x6c: + case 0x7c: + case 0x7d: + case 0x7e: { + this.feature("extended-const"); + const t = op <= 0x6c ? I32 : I64; + const b = stack.pop(); + const a = stack.pop(); + if (a === undefined || b === undefined || !matches(a, t) || !matches(b, t)) { + this.invalid("type mismatch", offset); + } + stack.push(t); + break; + } + case 0xfd: { + this.feature("simd"); + const sub = r.u32(); + if (sub !== 12) this.invalid("constant expression required", offset); + r.skip(16); + stack.push(V128); + break; + } + case 0xfb: + // GC's struct.new and friends: not typed here. + this.feature("gc"); + return this.skipToEnd(r); + default: + this.invalid("constant expression required", offset); + } + } + } + + skipToEnd(r: Reader): void { + // Only reachable for GC constant expressions, whose immediates this + // decoder does not model: skip to the next end byte. + while (r.u8() !== 0x0b) { + /* scan */ + } + } + + /** ref.null's heap type, as a value type (UNKNOWN for GC heap types). */ + refHeapNull(r: Reader): number { + const b = r.peek(); + if (b === FUNCREF || b === EXTERNREF) { + r.u8(); + return b; + } + this.heapType(r); + return UNKNOWN; + } + + // ── code ───────────────────────────────────────────────────────────── + + codeSection(r: Reader): void { + const count = r.u32(); + this.sawCode = true; + const defined = this.funcs.length - this.importedFuncs; + if (count !== defined) r.malformed("function and code section have inconsistent lengths"); + this.codeCount = count; + for (let i = 0; i < count; i++) { + const size = r.u32(); + if (size > r.end - r.pos) r.malformed("length out of bounds"); + if (size > MAX_FUNCTION_SIZE) r.malformed("function body too large"); + const body = new Reader(this.bytes, r.pos, r.pos + size); + const type = this.funcTypeAt(this.funcs[this.importedFuncs + i]!, r.pos); + new FunctionValidator(this, body, type).run(); + r.pos += size; + } + } + + decode(): void { + const bytes = this.bytes; + const r = new Reader(bytes, 0, bytes.length); + if ( + bytes.length < 4 || + bytes[0] !== 0 || + bytes[1] !== 0x61 || + bytes[2] !== 0x73 || + bytes[3] !== 0x6d + ) { + r.malformed("magic header not detected"); + } + r.pos = 4; + if (bytes.length < 8) r.malformed("unexpected end"); + if (bytes[4] !== 1 || bytes[5] !== 0 || bytes[6] !== 0 || bytes[7] !== 0) { + r.malformed("unknown binary version"); + } + r.pos = 8; + let last = 0; + while (!r.eof()) { + const id = r.u8(); + const size = r.u32(); + if (size > r.end - r.pos) r.malformed("section size out of bounds"); + const section = new Reader(bytes, r.pos, r.pos + size); + if (id !== 0) { + const order = SECTION_ORDER[id]; + if (order === undefined) return r.malformed("malformed section id"); + if (order <= last) r.malformed("unexpected section (out of order or duplicate)"); + last = order; + } + if (!(this.gcTypes && id !== 0)) { + switch (id) { + case 0: + this.customSection(section); + break; + case 1: + this.typeSection(section); + break; + case 2: + this.importSection(section); + break; + case 3: + this.functionSection(section); + break; + case 4: + this.tableSection(section); + break; + case 5: + this.memorySection(section); + break; + case 6: + this.globalSection(section); + break; + case 7: + this.exportSection(section); + break; + case 8: + this.startSection(section); + break; + case 9: + this.elementSection(section); + break; + case 10: + this.codeSection(section); + break; + case 11: + this.dataSection(section); + break; + case 12: + this.dataCountSection(section); + break; + case 13: + this.tagSection(section); + break; + } + } else { + section.pos = section.end; + } + if (section.pos !== section.end) { + r.pos = section.pos; + r.malformed("section size mismatch"); + } + r.pos = section.end; + } + if (!this.gcTypes) { + if (!this.sawCode && this.funcs.length > this.importedFuncs) { + r.malformed("function and code section have inconsistent lengths"); + } + if (this.dataCount !== null && this.dataSegments !== this.dataCount && this.dataCount !== 0) { + r.malformed("data count and data section have inconsistent lengths"); + } + } + } +} + +function isRef(t: number): boolean { + return t === FUNCREF || t === EXTERNREF; +} + +function isNum(t: number): boolean { + return t === I32 || t === I64 || t === F32 || t === F64 || t === V128; +} + +function matches(actual: number, expected: number): boolean { + return actual === expected || actual === UNKNOWN || expected === UNKNOWN; +} + +/** Validates one function body (the algorithm of the specification's + * validation appendix). Once an instruction needs a proposal outside the + * translatable set, the rest of the body is only decoded. */ +class FunctionValidator { + m: ModuleDecoder; + r: Reader; + type: FuncType; + locals: number[] = []; + vals: number[] = []; + ctrls: Frame[] = []; + typed = true; + + constructor(m: ModuleDecoder, r: Reader, type: FuncType) { + this.m = m; + this.r = r; + this.type = type; + } + + invalid(message: string): never { + throw new WasmError("invalid", message, this.r.pos); + } + + /** Stops typing: the rest of the body only decodes. */ + untyped(feature: WasmFeature): void { + this.m.feature(feature); + this.typed = false; + } + + run(): void { + const r = this.r; + for (const p of this.type.params) this.locals.push(p); + const groups = r.u32(); + let total = this.locals.length; + for (let i = 0; i < groups; i++) { + const n = r.u32(); + total += n; + if (total > MAX_LOCALS) r.malformed("too many locals"); + const t = this.m.valType(r); + if (t === V128) this.typed = false; + if (isRef(t)) this.m.feature("reference-types"); + for (let k = 0; k < n; k++) this.locals.push(t); + } + if (this.type.params.includes(V128) || this.type.results.includes(V128)) this.typed = false; + if (this.m.memory64 || this.m.gcTypes) this.typed = false; + this.pushCtrl(-1, [], this.type.results); + while (this.ctrls.length > 0) { + if (r.eof()) r.malformed("unexpected end of section or function"); + this.instruction(); + } + if (!r.eof()) r.malformed("operators remaining after end of function"); + } + + // The operand stack. + push(t: number): void { + this.vals.push(t); + } + + pop(): number { + const frame = this.ctrls[this.ctrls.length - 1]!; + if (this.vals.length === frame.height) { + if (frame.unreachable) return UNKNOWN; + this.invalid("type mismatch"); + } + return this.vals.pop()!; + } + + popExpect(expected: number): number { + const actual = this.pop(); + if (!matches(actual, expected)) this.invalid("type mismatch"); + // Unreachable code's unknown operand stays unknown when pushed back + // (br_if, br_table), so later labels can still meet it. + return actual; + } + + pushAll(types: number[]): void { + for (const t of types) this.push(t); + } + + popAll(types: number[]): number[] { + const out: number[] = []; + for (let i = types.length - 1; i >= 0; i--) out.unshift(this.popExpect(types[i]!)); + return out; + } + + pushCtrl(opcode: number, start: number[], end: number[]): void { + this.ctrls.push({ + opcode, + start, + end, + height: this.vals.length, + unreachable: false, + hasElse: false, + }); + this.pushAll(start); + } + + popCtrl(): Frame { + if (this.ctrls.length === 0) this.invalid("control stack underflow"); + const frame = this.ctrls[this.ctrls.length - 1]!; + this.popAll(frame.end); + if (this.vals.length !== frame.height) this.invalid("type mismatch"); + this.ctrls.pop(); + return frame; + } + + labelTypes(frame: Frame): number[] { + return frame.opcode === 0x03 ? frame.start : frame.end; + } + + setUnreachable(): void { + const frame = this.ctrls[this.ctrls.length - 1]!; + this.vals.length = frame.height; + frame.unreachable = true; + } + + label(depth: number): Frame { + if (depth >= this.ctrls.length) this.invalid(`unknown label ${depth}`); + return this.ctrls[this.ctrls.length - 1 - depth]!; + } + + blockType(): FuncType { + const r = this.r; + const b = r.peek(); + if (b === 0x40) { + r.u8(); + return { params: [], results: [] }; + } + if ( + b === I32 || + b === I64 || + b === F32 || + b === F64 || + b === V128 || + b === FUNCREF || + b === EXTERNREF + ) { + return { params: [], results: [this.m.valType(r)] }; + } + if (b >= 0x60) { + return { params: [], results: [this.m.valType(r)] }; + } + const offset = r.pos; + const index = r.sleb(33); + if (index < 0) r.malformed("malformed block type"); + this.m.feature("multi-value"); + return this.m.funcTypeAt(index, offset); + } + + local(index: number): number { + if (index >= this.locals.length) this.invalid(`unknown local ${index}`); + return this.locals[index]!; + } + + global(index: number): Global { + if (index >= this.m.globals.length) this.invalid(`unknown global ${index}`); + return this.m.globals[index]!; + } + + table(index: number): Table { + if (index >= this.m.tables.length) this.invalid(`unknown table ${index}`); + return this.m.tables[index]!; + } + + /** A memory other than 0 (multi-memory): it must exist; typing stops. */ + otherMemory(index: number): void { + if (index >= this.m.memories) this.invalid(`unknown memory ${index}`); + this.untyped("multi-memory"); + } + + memoryZero(): void { + if (this.m.memories === 0) this.invalid("unknown memory 0"); + } + + func(index: number): FuncType { + if (index >= this.m.funcs.length) this.invalid(`unknown function ${index}`); + return this.m.funcTypeAt(this.m.funcs[index]!, this.r.pos); + } + + /** 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); + } + if (this.m.memory64) r.u64(); + else r.u32(); + if (!this.typed) return; + if (memory >= this.m.memories) this.invalid(`unknown memory ${memory}`); + if (align > naturalAlign) this.invalid("alignment must not be larger than natural"); + } + + instruction(): void { + const r = this.r; + const op = r.u8(); + if (!this.typed) { + this.scan(op); + return; + } + switch (op) { + case 0x00: + this.setUnreachable(); + return; + case 0x01: + return; + case 0x02: + case 0x03: { + const bt = this.blockType(); + this.popAll(bt.params); + this.pushCtrl(op, bt.params, bt.results); + return; + } + case 0x04: { + const bt = this.blockType(); + this.popExpect(I32); + this.popAll(bt.params); + this.pushCtrl(op, bt.params, bt.results); + return; + } + case 0x05: { + const frame = this.ctrls[this.ctrls.length - 1]!; + if (frame.opcode !== 0x04 || frame.hasElse) this.invalid("else without matching if"); + this.popCtrl(); + this.pushCtrl(0x04, frame.start, frame.end); + this.ctrls[this.ctrls.length - 1]!.hasElse = true; + return; + } + case 0x0b: { + const frame = this.popCtrl(); + // An if without else must leave its params as its results. + if (frame.opcode === 0x04 && !frame.hasElse) { + if (frame.start.length !== frame.end.length) this.invalid("type mismatch"); + for (let i = 0; i < frame.start.length; i++) { + if (frame.start[i] !== frame.end[i]) this.invalid("type mismatch"); + } + } + this.pushAll(frame.end); + return; + } + case 0x0c: { + const depth = r.u32(); + this.popAll(this.labelTypes(this.label(depth))); + this.setUnreachable(); + return; + } + case 0x0d: { + const depth = r.u32(); + this.popExpect(I32); + // br_if leaves the label's types (even over unknown operands); + // br_table below leaves what it popped. + const types = this.labelTypes(this.label(depth)); + this.popAll(types); + this.pushAll(types); + return; + } + case 0x0e: { + const n = r.u32(); + const targets: number[] = []; + for (let i = 0; i < n; i++) targets.push(r.u32()); + const defaultDepth = r.u32(); + this.popExpect(I32); + const arity = this.labelTypes(this.label(defaultDepth)).length; + for (const depth of targets) { + const types = this.labelTypes(this.label(depth)); + if (types.length !== arity) this.invalid("type mismatch"); + this.pushAll(this.popAll(types)); + } + this.popAll(this.labelTypes(this.label(defaultDepth))); + this.setUnreachable(); + return; + } + case 0x0f: + this.popAll(this.type.results); + this.setUnreachable(); + return; + case 0x10: { + const type = this.func(r.u32()); + this.popAll(type.params); + this.pushAll(type.results); + return; + } + case 0x11: { + const typeIndex = r.u32(); + const tableIndex = r.u32(); + if (tableIndex !== 0) this.m.feature("reference-types"); + const table = this.table(tableIndex); + if (table.type !== FUNCREF && table.type !== UNKNOWN) this.invalid("type mismatch"); + const type = this.m.funcTypeAt(typeIndex, r.pos); + this.popExpect(I32); + this.popAll(type.params); + this.pushAll(type.results); + return; + } + case 0x12: + case 0x13: + case 0x14: + case 0x15: + this.untyped(op === 0x14 || op === 0x15 ? "function-references" : "tail-call"); + this.scan(op); + return; + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x18: + case 0x19: + case 0x1f: + this.untyped("exceptions"); + this.scan(op); + return; + case 0x1a: + this.pop(); + return; + case 0x1b: { + this.popExpect(I32); + const t1 = this.pop(); + const t2 = this.pop(); + if (!(isNum(t1) || t1 === UNKNOWN) || !(isNum(t2) || t2 === UNKNOWN)) + this.invalid("type mismatch"); + if (t1 !== t2 && t1 !== UNKNOWN && t2 !== UNKNOWN) this.invalid("type mismatch"); + this.push(t1 === UNKNOWN ? t2 : t1); + return; + } + case 0x1c: { + const n = r.u32(); + if (n !== 1) this.invalid("invalid result arity"); + const t = this.m.valType(r); + if (isRef(t)) this.m.feature("reference-types"); + this.popExpect(I32); + this.popExpect(t); + this.popExpect(t); + this.push(t); + return; + } + case 0x20: + this.push(this.local(r.u32())); + return; + case 0x21: + this.popExpect(this.local(r.u32())); + return; + case 0x22: { + const t = this.local(r.u32()); + this.popExpect(t); + this.push(t); + return; + } + case 0x23: + this.push(this.global(r.u32()).type); + return; + case 0x24: { + const global = this.global(r.u32()); + if (!global.mutable) this.invalid("global is immutable"); + this.popExpect(global.type); + return; + } + case 0x25: { + this.m.feature("reference-types"); + const table = this.table(r.u32()); + this.popExpect(I32); + this.push(table.type); + return; + } + case 0x26: { + this.m.feature("reference-types"); + const table = this.table(r.u32()); + this.popExpect(table.type); + this.popExpect(I32); + return; + } + case 0x3f: + case 0x40: { + const memory = r.u8(); + if (memory !== 0) { + // A memory index (multi-memory) or a malformed reserved byte. + r.pos--; + const index = r.u32(); + if (index !== 0) this.otherMemory(index); + if (!this.typed) return; + } + this.memoryZero(); + if (op === 0x40) this.popExpect(I32); + this.push(I32); + return; + } + case 0x41: + r.sleb(32); + this.push(I32); + return; + case 0x42: + r.sleb(64); + this.push(I64); + return; + case 0x43: + r.skip(4); + this.push(F32); + return; + case 0x44: + r.skip(8); + this.push(F64); + return; + case 0xd0: { + this.m.feature("reference-types"); + const t = this.m.refHeapNull(r); + if (t === UNKNOWN) { + this.typed = false; + return; + } + this.push(t); + return; + } + case 0xd1: { + this.m.feature("reference-types"); + const t = this.pop(); + if (!isRef(t) && t !== UNKNOWN) this.invalid("type mismatch"); + this.push(I32); + return; + } + case 0xd2: { + this.m.feature("reference-types"); + const index = r.u32(); + this.func(index); + if (!this.m.declaredRefs.has(index)) this.invalid("undeclared function reference"); + this.push(FUNCREF); + return; + } + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + this.untyped(op === 0xd3 ? "gc" : "function-references"); + this.scan(op); + return; + case 0xfc: + this.prefixFC(); + return; + case 0xfd: + this.untyped("simd"); + this.scanSimd(); + return; + case 0xfe: + this.untyped("threads"); + this.scanAtomic(); + return; + case 0xfb: + this.untyped("gc"); + r.pos = r.end; + this.ctrls.length = 0; + return; + } + if (op >= 0x28 && op <= 0x3e) { + const k = op - 0x28; + this.memarg(MEMORY_ALIGN[k]!); + if (!this.typed) return; + this.memoryZero(); + if (op <= 0x35) { + this.popExpect(I32); + this.push(MEMORY_TYPE[k]!); + } else { + this.popExpect(MEMORY_TYPE[k]!); + this.popExpect(I32); + } + return; + } + if (op >= 0x45 && op <= 0xc4) { + if (op >= 0xc0) this.m.feature("sign-extension"); + const [operand, count, result] = numericSignature(op); + for (let i = 0; i < count; i++) this.popExpect(operand); + this.push(result); + return; + } + r.pos--; + r.malformed(`illegal opcode 0x${op.toString(16)}`); + } + + prefixFC(): void { + const r = this.r; + const sub = r.u32(); + if (sub <= 7) { + this.m.feature("nontrapping-fptoint"); + const from = sub <= 1 || (sub >= 4 && sub <= 5) ? F32 : F64; + const to = sub <= 3 ? I32 : I64; + this.popExpect(from); + this.push(to); + return; + } + switch (sub) { + case 8: { + this.m.feature("bulk-memory"); + const segment = r.u32(); + const memory = r.u32(); + if (memory !== 0) { + this.otherMemory(memory); + return; + } + this.memoryZero(); + const dataCount = this.m.dataCount; + if (dataCount === null) return r.malformed("data count section required"); + if (segment >= dataCount) this.invalid(`unknown data segment ${segment}`); + this.popExpect(I32); + this.popExpect(I32); + this.popExpect(I32); + return; + } + case 9: { + this.m.feature("bulk-memory"); + const segment = r.u32(); + const dataCount = this.m.dataCount; + if (dataCount === null) return r.malformed("data count section required"); + if (segment >= dataCount) this.invalid(`unknown data segment ${segment}`); + return; + } + case 10: { + this.m.feature("bulk-memory"); + const dst = r.u32(); + const src = r.u32(); + if (dst !== 0 || src !== 0) { + this.otherMemory(Math.max(dst, src)); + return; + } + this.memoryZero(); + this.popExpect(I32); + this.popExpect(I32); + this.popExpect(I32); + return; + } + case 11: { + this.m.feature("bulk-memory"); + const memory = r.u32(); + if (memory !== 0) { + this.otherMemory(memory); + return; + } + this.memoryZero(); + this.popExpect(I32); + this.popExpect(I32); + this.popExpect(I32); + return; + } + case 12: { + this.m.feature("bulk-memory"); + const segment = r.u32(); + const table = this.table(r.u32()); + if (segment >= this.m.elemTypes.length) this.invalid(`unknown elem segment ${segment}`); + const elemType = this.m.elemTypes[segment]!; + if (!matches(elemType, table.type)) this.invalid("type mismatch"); + this.popExpect(I32); + this.popExpect(I32); + this.popExpect(I32); + return; + } + case 13: { + this.m.feature("bulk-memory"); + const segment = r.u32(); + if (segment >= this.m.elemTypes.length) this.invalid(`unknown elem segment ${segment}`); + return; + } + case 14: { + this.m.feature("bulk-memory"); + const dst = this.table(r.u32()); + const src = this.table(r.u32()); + if (!matches(src.type, dst.type)) this.invalid("type mismatch"); + this.popExpect(I32); + this.popExpect(I32); + this.popExpect(I32); + return; + } + case 15: { + this.m.feature("reference-types"); + const table = this.table(r.u32()); + this.popExpect(I32); + this.popExpect(table.type); + this.push(I32); + return; + } + case 16: + this.m.feature("reference-types"); + this.table(r.u32()); + this.push(I32); + return; + case 17: { + this.m.feature("reference-types"); + const table = this.table(r.u32()); + this.popExpect(I32); + this.popExpect(table.type); + this.popExpect(I32); + return; + } + } + r.malformed(`illegal opcode 0xfc ${sub}`); + } + + // ── decode-only scanning (proposals outside the translatable set) ───── + + /** One instruction, decoded for its immediates only. Tracks block + * nesting so that the body's final end is found. */ + scan(op: number): void { + const r = this.r; + switch (op) { + case 0x02: + case 0x03: + case 0x04: + case 0x06: + this.scanBlockType(); + this.ctrls.push({ + opcode: op, + start: [], + end: [], + height: 0, + unreachable: true, + hasElse: false, + }); + return; + case 0x1f: { + this.m.feature("exceptions"); + this.scanBlockType(); + const n = r.u32(); + for (let i = 0; i < n; i++) { + const kind = r.u8(); + if (kind > 3) r.malformed("malformed catch kind"); + if (kind < 2) r.u32(); + r.u32(); + } + this.ctrls.push({ + opcode: op, + start: [], + end: [], + height: 0, + unreachable: true, + hasElse: false, + }); + return; + } + case 0x0b: + this.ctrls.pop(); + return; + case 0x18: + // delegate ends its try block. + this.m.feature("exceptions"); + r.u32(); + this.ctrls.pop(); + return; + case 0xfc: + this.scanFC(); + return; + case 0xfd: + this.m.feature("simd"); + this.scanSimd(); + return; + case 0xfe: + this.m.feature("threads"); + this.scanAtomic(); + return; + case 0xfb: + this.m.feature("gc"); + r.pos = r.end; + this.ctrls.length = 0; + return; + } + this.scanImmediates(op); + } + + scanBlockType(): void { + const r = this.r; + const b = r.peek(); + if (b === 0x40) { + r.u8(); + return; + } + if (b >= 0x60) { + this.m.valType(r); + return; + } + if (r.sleb(33) < 0) r.malformed("malformed block type"); + } + + /** The immediates of a single-byte opcode that opens no block. */ + scanImmediates(op: number): void { + const r = this.r; + switch (op) { + case 0x00: + case 0x01: + case 0x05: + case 0x0f: + case 0x1a: + case 0x1b: + case 0x0a: + case 0x19: + case 0xd1: + case 0xd3: + case 0xd4: + if (op === 0x0a || op === 0x19) this.m.feature("exceptions"); + return; + case 0x07: + case 0x08: + case 0x09: + case 0x0c: + case 0x0d: + case 0x10: + case 0x12: + case 0x14: + case 0x15: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0xd2: + case 0xd5: + case 0xd6: + if (op === 0x07 || op === 0x08 || op === 0x09) this.m.feature("exceptions"); + if (op === 0x12) this.m.feature("tail-call"); + if (op === 0x14 || op === 0x15 || op === 0xd5 || op === 0xd6) + this.m.feature("function-references"); + r.u32(); + return; + case 0x0e: { + const n = r.u32(); + for (let i = 0; i <= n; i++) r.u32(); + return; + } + case 0x11: + case 0x13: + if (op === 0x13) this.m.feature("tail-call"); + r.u32(); + r.u32(); + return; + case 0x1c: { + const n = r.u32(); + for (let i = 0; i < n; i++) this.m.valType(r); + return; + } + case 0x3f: + case 0x40: + r.u32(); + return; + case 0x41: + r.sleb(32); + return; + case 0x42: + r.sleb(64); + return; + case 0x43: + r.skip(4); + return; + case 0x44: + r.skip(8); + return; + case 0xd0: + this.m.refHeapNull(r); + return; + } + if (op >= 0x28 && op <= 0x3e) { + this.scanMemarg(); + return; + } + if (op >= 0x45 && op <= 0xc4) { + if (op >= 0xc0) this.m.feature("sign-extension"); + return; + } + r.pos--; + r.malformed(`illegal opcode 0x${op.toString(16)}`); + } + + 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"); + if (this.m.memory64) r.u64(); + else r.u32(); + } + + scanFC(): void { + const r = this.r; + const sub = r.u32(); + if (sub <= 7) { + this.m.feature("nontrapping-fptoint"); + return; + } + if (sub > 17) r.malformed(`illegal opcode 0xfc ${sub}`); + this.m.feature(sub >= 15 ? "reference-types" : "bulk-memory"); + switch (sub) { + case 8: + case 10: + case 12: + case 14: + r.u32(); + r.u32(); + return; + default: + r.u32(); + } + } + + scanSimd(): void { + const r = this.r; + const sub = r.u32(); + if (sub <= 11 || sub === 92 || sub === 93) { + this.scanMemarg(); + return; + } + if (sub === 12 || sub === 13) { + r.skip(16); + return; + } + if (sub >= 21 && sub <= 34) { + r.u8(); + return; + } + if (sub >= 84 && sub <= 91) { + this.scanMemarg(); + r.u8(); + return; + } + if (sub > 0x113) r.malformed(`illegal opcode 0xfd ${sub}`); + } + + scanAtomic(): void { + const r = this.r; + const sub = r.u32(); + if (sub === 0x03) { + if (r.u8() !== 0) r.malformed("zero byte expected"); + return; + } + if (sub > 0x4e || (sub > 0x03 && sub < 0x10)) r.malformed(`illegal opcode 0xfe ${sub}`); + this.scanMemarg(); + } +} + +/** Decodes and validates `bytes` (a whole module). Never throws. */ +export function analyzeWasm(bytes: Uint8Array): WasmModuleSummary { + const m = new ModuleDecoder(bytes); + let status: WasmModuleSummary["status"] = "valid"; + let error: string | null = null; + try { + m.decode(); + } catch (e) { + if (!(e instanceof WasmError)) throw e; + status = e.kind; + error = `${e.message} (at byte ${e.offset})`; + } + const features: string[] = []; + const unsupported: string[] = []; + for (const feature of WASM_FEATURES) { + if (!m.features.has(feature)) continue; + features.push(feature); + if (!TRANSLATABLE.has(feature)) unsupported.push(feature); + } + if (status === "valid" && unsupported.length > 0) status = "unsupported"; + return { + size: bytes.length, + status, + error, + features, + unsupported, + functions: Math.max(0, m.funcs.length - m.importedFuncs), + imports: m.imports, + exports: m.exports, + importModules: m.importModules, + memories: m.memories, + tables: m.tables.length, + globals: m.globals.length, + customSections: m.customSections, + }; +} + +/** True when `bytes` starts with the WebAssembly magic and version 1. */ +export function isWasmHeader(bytes: Uint8Array): boolean { + return ( + bytes.length >= 8 && + bytes[0] === 0 && + bytes[1] === 0x61 && + bytes[2] === 0x73 && + bytes[3] === 0x6d && + bytes[4] === 1 && + bytes[5] === 0 && + bytes[6] === 0 && + bytes[7] === 0 + ); +} diff --git a/packages/compiler/src/wasm/discover.test.ts b/packages/compiler/src/wasm/discover.test.ts new file mode 100644 index 000000000..1a3ba5e26 --- /dev/null +++ b/packages/compiler/src/wasm/discover.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, test } from "vitest"; +import { decodeBase64, packageRootOf } from "./discover.js"; + +describe("decodeBase64", () => { + test("decodes standard and URL-safe spellings, with or without padding", () => { + const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 0xfb, 0xff]); + const standard = Buffer.from(bytes).toString("base64"); + expect(decodeBase64(standard)).toEqual(bytes); + expect(decodeBase64(standard.replace(/=+$/, ""))).toEqual(bytes); + expect(decodeBase64(Buffer.from(bytes).toString("base64url"))).toEqual(bytes); + }); + + test("answers null for text that is not base64", () => { + expect(decodeBase64("AGFzbQ*")).toBeNull(); + expect(decodeBase64("AGFzb")).toBeNull(); + expect(decodeBase64("AGFzbQ===")).toBeNull(); + }); +}); + +describe("packageRootOf", () => { + test("finds the innermost package, scoped or not", () => { + expect(packageRootOf("/p/node_modules/quickjs-wasi/dist/index.js")).toBe( + "/p/node_modules/quickjs-wasi", + ); + expect(packageRootOf("/p/node_modules/a/node_modules/@scope/b/lib/x.js")).toBe( + "/p/node_modules/a/node_modules/@scope/b", + ); + expect(packageRootOf("/p/src/main.ts")).toBeNull(); + }); +}); diff --git a/packages/compiler/src/wasm/discover.ts b/packages/compiler/src/wasm/discover.ts new file mode 100644 index 000000000..610a389f1 --- /dev/null +++ b/packages/compiler/src/wasm/discover.ts @@ -0,0 +1,426 @@ +/* Build-time discovery of the WebAssembly modules a program can load. + * + * `scriptc coverage` reports every module whose bytes the build can see, + * from four sources: + * + * 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"`); + * 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 + * program files mention `WebAssembly` (this finds paths computed at run + * time, such as a loader's default argument); + * 4. config: the `scriptc.wasm` list in the entry's package.json and the + * `--wasm ` flag. + * + * Each module is decoded and validated (binary.ts) and reported once, by + * content, with every source that found it. Nothing here changes what a + * build emits. */ +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { dirname, isAbsolute, join, resolve } from "node:path"; +import * as ts from "../frontend/ts7/adapter.js"; +import { + trackedAccessibleEntries, + trackedFileExists, + trackedReadFile, +} from "../frontend/input-tracker.js"; +import { analyzeWasm, isWasmHeader, type WasmModuleSummary } from "./binary.js"; + +export type WasmSourceKind = "path" | "inline" | "package" | "config"; + +export interface WasmSource { + kind: WasmSourceKind; + /** The source file (path, inline) or the file that names the module. */ + file: string; + /** 1-based line of the site, when there is one. */ + line?: number; +} + +/** One discovered module. JSON-shaped: the coverage verdict cache stores it. */ +export interface WasmModuleReport extends WasmModuleSummary { + sha256: string; + /** The module file, absent for inline modules. */ + path?: string; + sources: WasmSource[]; +} + +export interface WasmDiscoveryInput { + /** The program's source files (entry and modules). */ + files: readonly ts.SourceFile[]; + /** The entry file. */ + entry: string; + /** --wasm files, absolute. */ + configured: readonly string[]; + /** require.resolve from `fromFile`, or null when it does not resolve. */ + resolveRequest: (fromFile: string, specifier: string) => string | null; +} + +const SCAN_KINDS: ReadonlySet = new Set([ + ts.SyntaxKind.StringLiteral, + ts.SyntaxKind.NoSubstitutionTemplateLiteral, + ts.SyntaxKind.CallExpression, + ts.SyntaxKind.NewExpression, + ts.SyntaxKind.BinaryExpression, + ts.SyntaxKind.ArrayLiteralExpression, +]); + +/** The base64 spelling of a module's first bytes ("\0asm"). */ +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; +/** Larger files are reported by size but not read. */ +const MAX_MODULE_BYTES = 256 * 1024 * 1024; + +class Discovery { + input: WasmDiscoveryInput; + byHash = new Map(); + byPath = new Map(); + order: string[] = []; + + constructor(input: WasmDiscoveryInput) { + this.input = input; + } + + /** Records a module and one source that found it; answers its hash. */ + addBytes(bytes: Uint8Array, path: string | undefined, source: WasmSource): string { + const sha256 = createHash("sha256").update(bytes).digest("hex"); + let report = this.byHash.get(sha256); + if (report === undefined) { + const summary = analyzeWasm(bytes); + report = { + size: summary.size, + status: summary.status, + error: summary.error, + features: summary.features, + unsupported: summary.unsupported, + functions: summary.functions, + imports: summary.imports, + exports: summary.exports, + importModules: summary.importModules, + memories: summary.memories, + tables: summary.tables, + globals: summary.globals, + customSections: summary.customSections, + sha256, + sources: [], + }; + this.byHash.set(sha256, report); + this.order.push(sha256); + } + if (report.path === undefined && path !== undefined) report.path = path; + addSource(report, source); + return sha256; + } + + addFile(path: string, source: WasmSource): void { + path = resolve(path); + const known = this.byPath.get(path); + if (known !== undefined) { + addSource(this.byHash.get(known)!, source); + return; + } + // The tracked read makes the coverage verdict cache depend on the file. + if (trackedReadFile(path) === null) return; + let bytes: Uint8Array; + try { + bytes = new Uint8Array(readFileSync(path)); + } catch { + return; + } + if (bytes.length > MAX_MODULE_BYTES) return; + this.byPath.set(path, this.addBytes(bytes, path, source)); + } + + // ── source 1 and 2: the program's source text ─────────────────────── + + scanFile(sf: ts.SourceFile): void { + const text = sf.text; + const paths = text.includes(".wasm"); + const base64 = text.includes(BASE64_MAGIC); + const bytes = BYTES_MAGIC.test(text); + if (!paths && !base64 && !bytes) return; + const file = sf.fileName; + const lineOf = (node: ts.Node): number => + ts.getLineAndCharacterOfPosition(sf, node.getStart()).line + 1; + ts.walkPreorder( + sf, + (node) => { + if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) { + if (base64 && node.text.startsWith(BASE64_MAGIC)) { + const decoded = decodeBase64(node.text); + if (decoded !== null && isWasmHeader(decoded)) { + this.addBytes(decoded, undefined, { kind: "inline", file, line: lineOf(node) }); + } + } + return undefined; + } + if (ts.isArrayLiteralExpression(node)) { + if (bytes) { + const literal = byteArrayLiteral(node); + if (literal !== null && isWasmHeader(literal)) { + this.addBytes(literal, undefined, { kind: "inline", file, line: lineOf(node) }); + return "skip"; + } + } + return undefined; + } + if (!paths) return undefined; + const path = this.resolvedPath(sf, node); + if (path !== null) this.addFile(path, { kind: "path", file, line: lineOf(node) }); + return undefined; + }, + SCAN_KINDS, + ); + } + + /** The module path a resolution expression names, when it ends in .wasm. */ + resolvedPath(sf: ts.SourceFile, node: ts.Node): string | null { + const dir = dirname(sf.fileName); + if (ts.isCallExpression(node)) { + const callee = node.expression; + const first = node.arguments[0]; + if (first === undefined) return null; + // require.resolve / createRequire(...).resolve / import.meta.resolve + if (ts.isPropertyAccessExpression(callee) && callee.name.text === "resolve") { + const specifier = wasmLiteral(first); + if (specifier === null) { + return this.joinedPath(dir, node.arguments); + } + const receiver = callee.expression; + if (ts.isMetaProperty(receiver) || isRequireLike(receiver)) { + if (specifier.startsWith("./") || specifier.startsWith("../")) { + return resolve(dir, specifier); + } + if (isAbsolute(specifier)) return specifier; + return this.input.resolveRequest(sf.fileName, specifier); + } + return null; + } + // path.join(__dirname, "x.wasm") and its resolve/bare spellings + if ( + (ts.isPropertyAccessExpression(callee) && + (callee.name.text === "join" || callee.name.text === "resolve")) || + (ts.isIdentifier(callee) && (callee.text === "join" || callee.text === "resolve")) + ) { + return this.joinedPath(dir, node.arguments); + } + return null; + } + if (ts.isNewExpression(node)) { + // new URL("./x.wasm", import.meta.url) + if (!ts.isIdentifier(node.expression) || node.expression.text !== "URL") return null; + const args = node.arguments; + if (args === undefined || args.length !== 2) return null; + const specifier = wasmLiteral(args[0]!); + const base = args[1]!; + if (specifier === null || !isImportMetaUrl(base)) return null; + if (specifier.startsWith("./") || specifier.startsWith("../")) return resolve(dir, specifier); + return null; + } + if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) { + // __dirname + "/x.wasm" + if (!isDirname(node.left)) return null; + const rest = wasmLiteral(node.right); + return rest === null ? null : join(dir, rest); + } + return null; + } + + joinedPath(dir: string, args: readonly ts.Expression[]): string | null { + if (args.length < 2 || !isDirname(args[0]!)) return null; + const parts: string[] = [dir]; + for (let i = 1; i < args.length; i++) { + const arg = args[i]!; + if (!ts.isStringLiteral(arg) && !ts.isNoSubstitutionTemplateLiteral(arg)) return null; + parts.push(arg.text); + } + if (!parts[parts.length - 1]!.endsWith(".wasm")) return null; + let path = parts[0]!; + for (let i = 1; i < parts.length; i++) path = resolve(path, parts[i]!); + return path; + } + + // ── source 3: package files ───────────────────────────────────────── + + scanPackages(): void { + const roots = new Map(); + for (const sf of this.input.files) { + const root = packageRootOf(sf.fileName); + if (root === null) continue; + const mentions = sf.text.includes("WebAssembly"); + roots.set(root, (roots.get(root) ?? false) || mentions); + } + for (const [root, mentions] of roots) { + if (!mentions) continue; + const found: string[] = []; + collectWasmFiles(root, 0, found); + found.sort(); + for (const path of found) + this.addFile(path, { kind: "package", file: join(root, "package.json") }); + } + } + + // ── source 4: configuration ───────────────────────────────────────── + + scanConfig(): void { + const manifest = nearestPackageJson(dirname(this.input.entry)); + if (manifest !== null) { + const text = trackedReadFile(manifest); + if (text !== null) { + let listed: unknown; + try { + const parsed = JSON.parse(text) as { scriptc?: { wasm?: unknown } }; + listed = parsed.scriptc?.wasm; + } catch { + listed = undefined; + } + if (Array.isArray(listed)) { + for (const entry of listed) { + if (typeof entry === "string") { + this.addFile(resolve(dirname(manifest), entry), { kind: "config", file: manifest }); + } + } + } + } + } + for (const path of this.input.configured) { + this.addFile(path, { kind: "config", file: path }); + } + } + + run(): WasmModuleReport[] { + for (const sf of this.input.files) this.scanFile(sf); + this.scanPackages(); + this.scanConfig(); + return this.order.map((sha) => this.byHash.get(sha)!); + } +} + +function addSource(report: WasmModuleReport, source: WasmSource): void { + for (const s of report.sources) { + if (s.kind === source.kind && s.file === source.file && s.line === source.line) return; + } + report.sources.push(source); +} + +function wasmLiteral(node: ts.Expression): string | null { + if (!ts.isStringLiteral(node) && !ts.isNoSubstitutionTemplateLiteral(node)) return null; + return node.text.endsWith(".wasm") ? node.text : null; +} + +function isDirname(node: ts.Expression): boolean { + return ts.isIdentifier(node) && node.text === "__dirname"; +} + +function isImportMetaUrl(node: ts.Expression): boolean { + return ( + ts.isPropertyAccessExpression(node) && + node.name.text === "url" && + ts.isMetaProperty(node.expression) + ); +} + +/** `require`, a `createRequire(...)` call, or a binding named like one. */ +function isRequireLike(node: ts.Expression): boolean { + if (ts.isIdentifier(node)) return node.text === "require" || /require$/i.test(node.text); + if (ts.isCallExpression(node)) { + const callee = node.expression; + return ( + (ts.isIdentifier(callee) && callee.text === "createRequire") || + (ts.isPropertyAccessExpression(callee) && callee.name.text === "createRequire") + ); + } + return false; +} + +/** The bytes of an array literal of integer literals, or null. */ +function byteArrayLiteral(node: ts.ArrayLiteralExpression): Uint8Array | null { + const elements = node.elements; + const out = new Uint8Array(elements.length); + for (let i = 0; i < elements.length; i++) { + const element = elements[i]!; + if (!ts.isNumericLiteral(element)) return null; + const value = Number(element.text); + if (!Number.isInteger(value) || value < 0 || value > 255) return null; + out[i] = value; + } + 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 { + const marker = "/node_modules/"; + const at = file.lastIndexOf(marker); + if (at < 0) return null; + const rest = file.slice(at + marker.length); + const segments = rest.split("/"); + const take = segments[0]!.startsWith("@") ? 2 : 1; + if (segments.length <= take) return null; + return file.slice(0, at + marker.length) + segments.slice(0, take).join("/"); +} + +function collectWasmFiles(dir: string, depth: number, out: string[]): void { + const entries = trackedAccessibleEntries(dir); + if (entries === null) return; + for (const name of entries.files) if (name.endsWith(".wasm")) out.push(join(dir, name)); + if (depth >= PACKAGE_SCAN_DEPTH) return; + for (const name of entries.directories) { + if (name === "node_modules" || name.startsWith(".")) continue; + collectWasmFiles(join(dir, name), depth + 1, out); + } +} + +function nearestPackageJson(dir: string): string | null { + for (;;) { + const candidate = join(dir, "package.json"); + if (trackedFileExists(candidate)) return candidate; + const parent = dirname(dir); + if (parent === dir) return null; + dir = parent; + } +} + +/** Every WebAssembly module the program's sources, packages and + * configuration make visible to the build, in discovery order. */ +export function discoverWasmModules(input: WasmDiscoveryInput): WasmModuleReport[] { + return new Discovery(input).run(); +} diff --git a/packages/compiler/surface-manifest.json b/packages/compiler/surface-manifest.json index 6dc871976..a167254c2 100644 --- a/packages/compiler/surface-manifest.json +++ b/packages/compiler/surface-manifest.json @@ -4464,7 +4464,7 @@ "kind": "stdlib", "name": "Map.prototype.entries", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.map.forEach", @@ -4489,7 +4489,7 @@ "kind": "stdlib", "name": "Map.prototype.keys", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.map.set", @@ -4502,7 +4502,7 @@ "kind": "stdlib", "name": "Map.prototype.values", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.math.E", @@ -5371,7 +5371,7 @@ "kind": "stdlib", "name": "Set.prototype.entries", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.set.forEach", @@ -5418,7 +5418,7 @@ "kind": "stdlib", "name": "Set.prototype.keys", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.set.symmetricDifference", @@ -5439,7 +5439,7 @@ "kind": "stdlib", "name": "Set.prototype.values", "status": "static", - "note": "live native iterators support next(), for...of, and drains; iterator helper methods are refused" + "note": "live native iterators support next(), for...of, drains, and the iterator helper methods" }, { "id": "stdlib.sharedArrayBuffer", @@ -5630,6 +5630,14 @@ "status": "static", "note": "the lowered call form takes no arguments" }, + { + "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)" + }, { "id": "syntax.async-generators", "kind": "syntax", diff --git a/packages/compiler/test/gen-wasm-spec-cases.mjs b/packages/compiler/test/gen-wasm-spec-cases.mjs new file mode 100644 index 000000000..068053f0e --- /dev/null +++ b/packages/compiler/test/gen-wasm-spec-cases.mjs @@ -0,0 +1,69 @@ +/* Regenerates wasm-spec-cases.txt: the binary modules of the WebAssembly + * specification test suite at the feature level the decoder validates + * (src/wasm/binary.ts), each with the suite's verdict and V8's. + * + * node gen-wasm-spec-cases.mjs --wast2json /bin/wast2json \ + * --spec /test/core \ + * --extended-const /test/core > wasm-spec-cases.txt + * + * Inputs: every .wast of the 2.0 core suite except simd/ (SIMD is outside + * the translatable set; the decoder only reports it), plus the extended + * constant expression proposal's global, data and elem tests. Modules given + * as text for assert_malformed are skipped (they test the text format). + * Identical modules are kept once, at their first location. + * + * Line format: : , where a + * verdict is "valid", "invalid" or "malformed" (V8: "valid" or "invalid"). + * The suite's tests are Apache-2.0 licensed (WebAssembly Community Group). */ +import { execFileSync } from "node:child_process"; +import { mkdtempSync, readFileSync, readdirSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { parseArgs } from "node:util"; + +const { values } = parseArgs({ + options: { + wast2json: { type: "string" }, + spec: { type: "string" }, + "extended-const": { type: "string" }, + }, +}); +const inputs = []; +for (const name of readdirSync(values.spec).sort()) { + if (name.endsWith(".wast")) inputs.push({ label: name, path: join(values.spec, name) }); +} +for (const name of ["global.wast", "data.wast", "elem.wast"]) { + inputs.push({ label: `extended-const/${name}`, path: join(values["extended-const"], name) }); +} +const seen = new Set(); +const lines = [ + "# WebAssembly spec test modules for src/wasm/binary.ts; generated by gen-wasm-spec-cases.mjs.", + "# Sources: WebAssembly/spec wg-2.0 test/core (without simd/) and WebAssembly/extended-const", + "# test/core global, data and elem, converted with wabt 1.0.37 wast2json (Apache-2.0).", + "# : ", +]; +for (const { label, path } of inputs) { + const dir = mkdtempSync(join(tmpdir(), "wasm-spec-")); + try { + execFileSync(values.wast2json, [path, "-o", join(dir, "x.json")], { stdio: "pipe" }); + const json = JSON.parse(readFileSync(join(dir, "x.json"), "utf8")); + for (const command of json.commands) { + let verdict; + if (["module", "assert_unlinkable", "assert_uninstantiable"].includes(command.type)) + verdict = "valid"; + else if (command.type === "assert_invalid") verdict = "invalid"; + else if (command.type === "assert_malformed") verdict = "malformed"; + else continue; + if (command.module_type === "text" || !command.filename?.endsWith(".wasm")) continue; + const bytes = readFileSync(join(dir, command.filename)); + const b64 = bytes.toString("base64"); + if (seen.has(b64)) continue; + seen.add(b64); + const v8 = WebAssembly.validate(bytes) ? "valid" : "invalid"; + lines.push(`${verdict} ${v8} ${label}:${command.line} ${b64}`); + } + } finally { + rmSync(dir, { recursive: true, force: true }); + } +} +process.stdout.write(`${lines.join("\n")}\n`); diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5908-iterator-helper-objects.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5908-iterator-helper-objects.ts.json new file mode 100644 index 000000000..5aa23f5d9 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5908-iterator-helper-objects.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5908-iterator-helper-objects.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5909-iterator-helper-objects-js.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5909-iterator-helper-objects-js.js.json new file mode 100644 index 000000000..fd3454670 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5909-iterator-helper-objects-js.js.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5909-iterator-helper-objects-js.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5997-frame-records-in-record-unions.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5997-frame-records-in-record-unions.ts.json new file mode 100644 index 000000000..7e3fb1c50 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5997-frame-records-in-record-unions.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5997-frame-records-in-record-unions.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6051-generic-class-factory-results.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6051-generic-class-factory-results.ts.json new file mode 100644 index 000000000..fc148dcea --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6051-generic-class-factory-results.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6051-generic-class-factory-results.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6150-cjs-inline-require/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6150-cjs-inline-require/main.js.json new file mode 100644 index 000000000..5f1e322f7 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6150-cjs-inline-require/main.js.json @@ -0,0 +1,20 @@ +{ + "order": [ + "/tests/corpus/6150-cjs-inline-require/lib.js", + "/tests/corpus/6150-cjs-inline-require/inner.js", + "/tests/corpus/6150-cjs-inline-require/reexport-inline.js", + "/tests/corpus/6150-cjs-inline-require/reexport-binding.js", + "/tests/corpus/6150-cjs-inline-require/type-error.js", + "/tests/corpus/6150-cjs-inline-require/pick.js", + "/tests/corpus/6150-cjs-inline-require/registry.js", + "/tests/corpus/6150-cjs-inline-require/make-logger.js", + "/tests/corpus/6150-cjs-inline-require/point.js", + "/tests/corpus/6150-cjs-inline-require/shapes.js", + "/tests/corpus/6150-cjs-inline-require/table.js", + "/tests/corpus/6150-cjs-inline-require/verify.js", + "/tests/corpus/6150-cjs-inline-require/fallback.js", + "/tests/corpus/6150-cjs-inline-require/main.js", + "/tests/corpus/6150-cjs-inline-require/late.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6151-cjs-export-chains/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6151-cjs-export-chains/main.js.json new file mode 100644 index 000000000..883aa872a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6151-cjs-export-chains/main.js.json @@ -0,0 +1,10 @@ +{ + "order": [ + "/tests/corpus/6151-cjs-export-chains/chain.js", + "/tests/corpus/6151-cjs-export-chains/constants.js", + "/tests/corpus/6151-cjs-export-chains/re.js", + "/tests/corpus/6151-cjs-export-chains/sem.js", + "/tests/corpus/6151-cjs-export-chains/main.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6152-cjs-tsc-interop/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6152-cjs-tsc-interop/main.js.json new file mode 100644 index 000000000..19a1b20de --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6152-cjs-tsc-interop/main.js.json @@ -0,0 +1,9 @@ +{ + "order": [ + "/tests/corpus/6152-cjs-tsc-interop/plain.js", + "/tests/corpus/6152-cjs-tsc-interop/stamped.js", + "/tests/corpus/6152-cjs-tsc-interop/fn.js", + "/tests/corpus/6152-cjs-tsc-interop/main.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6153-cjs-exports-object/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6153-cjs-exports-object/main.js.json new file mode 100644 index 000000000..070b131e3 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6153-cjs-exports-object/main.js.json @@ -0,0 +1,7 @@ +{ + "order": [ + "/tests/corpus/6153-cjs-exports-object/lib.js", + "/tests/corpus/6153-cjs-exports-object/main.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6154-cjs-require-nested-destructure/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6154-cjs-require-nested-destructure/main.js.json new file mode 100644 index 000000000..ee9f71d22 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6154-cjs-require-nested-destructure/main.js.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/corpus/6154-cjs-require-nested-destructure/errors.js", + "/tests/corpus/6154-cjs-require-nested-destructure/constants.js", + "/tests/corpus/6154-cjs-require-nested-destructure/main.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6155-cjs-export-table-methods/main.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6155-cjs-export-table-methods/main.js.json new file mode 100644 index 000000000..9ac5f0e41 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6155-cjs-export-table-methods/main.js.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/corpus/6155-cjs-export-table-methods/more.js", + "/tests/corpus/6155-cjs-export-table-methods/lib.js", + "/tests/corpus/6155-cjs-export-table-methods/main.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6156-cjs-function-members-from-ts/main.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6156-cjs-function-members-from-ts/main.ts.json new file mode 100644 index 000000000..e73e603e3 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6156-cjs-function-members-from-ts/main.ts.json @@ -0,0 +1,8 @@ +{ + "order": [ + "/tests/corpus/6156-cjs-function-members-from-ts/status.cjs", + "/tests/corpus/6156-cjs-function-members-from-ts/consumer.cjs", + "/tests/corpus/6156-cjs-function-members-from-ts/main.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6160-number-radix-typed.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6160-number-radix-typed.ts.json new file mode 100644 index 000000000..6df464b2b --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6160-number-radix-typed.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6160-number-radix-typed.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6161-dispose-observer-gates.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6161-dispose-observer-gates.ts.json new file mode 100644 index 000000000..1387cc325 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6161-dispose-observer-gates.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6161-dispose-observer-gates.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6162-dispose-observer-weak-keys.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6162-dispose-observer-weak-keys.ts.json new file mode 100644 index 000000000..ab4838284 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6162-dispose-observer-weak-keys.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6162-dispose-observer-weak-keys.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6163-dispose-observer-workers.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6163-dispose-observer-workers.ts.json new file mode 100644 index 000000000..327aa105f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6163-dispose-observer-workers.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6163-dispose-observer-workers.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6164-regex-replace-typed-callback.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6164-regex-replace-typed-callback.ts.json new file mode 100644 index 000000000..8ca65275f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6164-regex-replace-typed-callback.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6164-regex-replace-typed-callback.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6165-regex-replace-callback-throws.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6165-regex-replace-callback-throws.ts.json new file mode 100644 index 000000000..0f4b99484 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6165-regex-replace-callback-throws.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6165-regex-replace-callback-throws.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6170-flight-dev-stacks-dead.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6170-flight-dev-stacks-dead.ts.json new file mode 100644 index 000000000..f78bd38f5 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6170-flight-dev-stacks-dead.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6170-flight-dev-stacks-dead.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6171-error-stack-capture-sites.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6171-error-stack-capture-sites.ts.json new file mode 100644 index 000000000..b4cdd2191 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6171-error-stack-capture-sites.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6171-error-stack-capture-sites.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6172-unreachable-statements.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6172-unreachable-statements.ts.json new file mode 100644 index 000000000..3ecbd301c --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6172-unreachable-statements.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6172-unreachable-statements.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6180-interface-overload-events.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6180-interface-overload-events.ts.json new file mode 100644 index 000000000..28b4381d2 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6180-interface-overload-events.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6180-interface-overload-events.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6181-interface-overload-arity.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6181-interface-overload-arity.ts.json new file mode 100644 index 000000000..919c56254 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6181-interface-overload-arity.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6181-interface-overload-arity.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6182-interface-overload-types.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6182-interface-overload-types.ts.json new file mode 100644 index 000000000..249d2084e --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6182-interface-overload-types.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6182-interface-overload-types.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6183-interface-overload-flow.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6183-interface-overload-flow.ts.json new file mode 100644 index 000000000..b63d2780c --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6183-interface-overload-flow.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6183-interface-overload-flow.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6230-optional-chain-unchecked-receivers.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6230-optional-chain-unchecked-receivers.ts.json new file mode 100644 index 000000000..338ab8c6e --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/6230-optional-chain-unchecked-receivers.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/6230-optional-chain-unchecked-receivers.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/error-js-accessor-name-message.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/error-js-accessor-name-message.js.json new file mode 100644 index 000000000..e4c388b08 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/error-js-accessor-name-message.js.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/error-js-accessor-name-message.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-feature-probe.js.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-feature-probe.js.json new file mode 100644 index 000000000..70988ec5f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-feature-probe.js.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-feature-probe.js" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-type-mentions.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-type-mentions.ts.json new file mode 100644 index 000000000..b86f1bd8a --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/webassembly-type-mentions.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/webassembly-type-mentions.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/overloaded-members.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/overloaded-members.ts.json new file mode 100644 index 000000000..33ea8a976 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/overloaded-members.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/diagnostics/overloaded-members.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/webassembly-fences.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/webassembly-fences.ts.json new file mode 100644 index 000000000..feb8cb469 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/diagnostics/webassembly-fences.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/diagnostics/webassembly-fences.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/wasm-spec-cases.txt b/packages/compiler/test/wasm-spec-cases.txt new file mode 100644 index 000000000..16d2ae2b6 --- /dev/null +++ b/packages/compiler/test/wasm-spec-cases.txt @@ -0,0 +1,3017 @@ +# WebAssembly spec test modules for src/wasm/binary.ts; generated by gen-wasm-spec-cases.mjs. +# Sources: WebAssembly/spec wg-2.0 test/core (without simd/) and WebAssembly/extended-const +# test/core global, data and elem, converted with wabt 1.0.37 wast2json (Apache-2.0). +# : +valid valid address.wast:3 AGFzbQEAAAABCgJgAX8Bf2ABfwADHx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEFAwEAAQfNAh4IOHVfZ29vZDEAAAg4dV9nb29kMgABCDh1X2dvb2QzAAIIOHVfZ29vZDQAAwg4dV9nb29kNQAECDhzX2dvb2QxAAUIOHNfZ29vZDIABgg4c19nb29kMwAHCDhzX2dvb2Q0AAgIOHNfZ29vZDUACQkxNnVfZ29vZDEACgkxNnVfZ29vZDIACwkxNnVfZ29vZDMADAkxNnVfZ29vZDQADQkxNnVfZ29vZDUADgkxNnNfZ29vZDEADwkxNnNfZ29vZDIAEAkxNnNfZ29vZDMAEQkxNnNfZ29vZDQAEgkxNnNfZ29vZDUAEwgzMl9nb29kMQAUCDMyX2dvb2QyABUIMzJfZ29vZDMAFggzMl9nb29kNAAXCDMyX2dvb2Q1ABgGOHVfYmFkABkGOHNfYmFkABoHMTZ1X2JhZAAbBzE2c19iYWQAHAYzMl9iYWQAHQqKAh4HACAALQAACwcAIAAtAAALBwAgAC0AAQsHACAALQACCwcAIAAtABkLBwAgACwAAAsHACAALAAACwcAIAAsAAELBwAgACwAAgsHACAALAAZCwcAIAAvAQALBwAgAC8AAAsHACAALwABCwcAIAAvAQILBwAgAC8BGQsHACAALgEACwcAIAAuAAALBwAgAC4AAQsHACAALgECCwcAIAAuARkLBwAgACgCAAsHACAAKAAACwcAIAAoAAELBwAgACgBAgsHACAAKAIZCwwAIAAtAP////8PGgsMACAALAD/////DxoLDAAgAC8B/////w8aCwwAIAAuAf////8PGgsMACAAKAL/////DxoLCyABAEEACxphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eg== +valid valid address.wast:223 AGFzbQEAAAABCgJgAX8BfmABfwADKyoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEFAwEAAQfZAyoIOHVfZ29vZDEAAAg4dV9nb29kMgABCDh1X2dvb2QzAAIIOHVfZ29vZDQAAwg4dV9nb29kNQAECDhzX2dvb2QxAAUIOHNfZ29vZDIABgg4c19nb29kMwAHCDhzX2dvb2Q0AAgIOHNfZ29vZDUACQkxNnVfZ29vZDEACgkxNnVfZ29vZDIACwkxNnVfZ29vZDMADAkxNnVfZ29vZDQADQkxNnVfZ29vZDUADgkxNnNfZ29vZDEADwkxNnNfZ29vZDIAEAkxNnNfZ29vZDMAEQkxNnNfZ29vZDQAEgkxNnNfZ29vZDUAEwkzMnVfZ29vZDEAFAkzMnVfZ29vZDIAFQkzMnVfZ29vZDMAFgkzMnVfZ29vZDQAFwkzMnVfZ29vZDUAGAkzMnNfZ29vZDEAGQkzMnNfZ29vZDIAGgkzMnNfZ29vZDMAGwkzMnNfZ29vZDQAHAkzMnNfZ29vZDUAHQg2NF9nb29kMQAeCDY0X2dvb2QyAB8INjRfZ29vZDMAIAg2NF9nb29kNAAhCDY0X2dvb2Q1ACIGOHVfYmFkACMGOHNfYmFkACQHMTZ1X2JhZAAlBzE2c19iYWQAJgczMnVfYmFkACcHMzJzX2JhZAAoBjY0X2JhZAApCvQCKgcAIAAxAAALBwAgADEAAAsHACAAMQABCwcAIAAxAAILBwAgADEAGQsHACAAMAAACwcAIAAwAAALBwAgADAAAQsHACAAMAACCwcAIAAwABkLBwAgADMBAAsHACAAMwAACwcAIAAzAAELBwAgADMBAgsHACAAMwEZCwcAIAAyAQALBwAgADIAAAsHACAAMgABCwcAIAAyAQILBwAgADIBGQsHACAANQIACwcAIAA1AAALBwAgADUAAQsHACAANQECCwcAIAA1AhkLBwAgADQCAAsHACAANAAACwcAIAA0AAELBwAgADQBAgsHACAANAIZCwcAIAApAwALBwAgACkAAAsHACAAKQABCwcAIAApAQILBwAgACkDGQsMACAAMQD/////DxoLDAAgADAA/////w8aCwwAIAAzAf////8PGgsMACAAMgH/////DxoLDAAgADUC/////w8aCwwAIAA0Av////8PGgsMACAAKQP/////DxoLCyABAEEACxphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eg== +valid valid address.wast:514 AGFzbQEAAAABCgJgAX8BfWABfwADBwYAAAAAAAEFAwEAAQdBBggzMl9nb29kMQAACDMyX2dvb2QyAAEIMzJfZ29vZDMAAggzMl9nb29kNAADCDMyX2dvb2Q1AAQGMzJfYmFkAAUKNgYHACAAKgIACwcAIAAqAAALBwAgACoAAQsHACAAKgECCwcAIAAqAggLDAAgACoC/////w8aCwsSAQBBAAsMAAAAAAAAoH8BANB/ +valid valid address.wast:564 AGFzbQEAAAABCgJgAX8BfGABfwADBwYAAAAAAAEFAwEAAQdBBgg2NF9nb29kMQAACDY0X2dvb2QyAAEINjRfZ29vZDMAAgg2NF9nb29kNAADCDY0X2dvb2Q1AAQGNjRfYmFkAAUKNgYHACAAKwMACwcAIAArAAALBwAgACsAAQsHACAAKwECCwcAIAArAxILDAAgACsD/////w8aCwsgAQBBAAsaAAAAAAAAAAAAAAAAAAAAAPR/AQAAAAAA/H8= +valid valid align.wast:3 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALAAAGgs= +valid valid align.wast:4 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALQAAGgs= +valid valid align.wast:5 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALgEAGgs= +valid valid align.wast:6 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALwEAGgs= +valid valid align.wast:7 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKAIAGgs= +valid valid align.wast:8 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMAAAGgs= +valid valid align.wast:9 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMQAAGgs= +valid valid align.wast:10 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMgEAGgs= +valid valid align.wast:11 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMwEAGgs= +valid valid align.wast:12 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANAIAGgs= +valid valid align.wast:13 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANQIAGgs= +valid valid align.wast:14 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKQMAGgs= +valid valid align.wast:15 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKgIAGgs= +valid valid align.wast:16 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKwMAGgs= +valid valid align.wast:17 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE6AAAL +valid valid align.wast:18 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE7AQAL +valid valid align.wast:19 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQE2AgAL +valid valid align.wast:20 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE8AAAL +valid valid align.wast:21 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE9AQAL +valid valid align.wast:22 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE+AgAL +valid valid align.wast:23 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgE3AwAL +valid valid align.wast:24 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDgEMAEEAQwAAgD84AgAL +valid valid align.wast:25 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEgEQAEEARAAAAAAAAPA/OQMACw== +invalid invalid align.wast:306 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALAEAGgs= +invalid invalid align.wast:310 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALQEAGgs= +invalid invalid align.wast:314 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALgIAGgs= +invalid invalid align.wast:318 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEALwIAGgs= +invalid invalid align.wast:322 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKAMAGgs= +invalid invalid align.wast:326 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMAEAGgs= +invalid invalid align.wast:330 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMQEAGgs= +invalid invalid align.wast:334 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMgIAGgs= +invalid invalid align.wast:338 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAMwIAGgs= +invalid invalid align.wast:342 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANAMAGgs= +invalid invalid align.wast:346 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEANQMAGgs= +invalid invalid align.wast:350 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKQQAGgs= +invalid invalid align.wast:354 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKgMAGgs= +invalid invalid align.wast:358 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAKwQAGgs= +invalid invalid align.wast:420 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQA6AQAL +invalid invalid align.wast:424 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQA7AgAL +invalid invalid align.wast:428 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQQA2AwAL +invalid invalid align.wast:432 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgA8AQAL +invalid invalid align.wast:436 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgA9AgAL +invalid invalid align.wast:440 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgA+AwAL +invalid invalid align.wast:444 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQgA3BAAL +invalid invalid align.wast:448 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDgEMAEEAQwAAAAA4AwAL +invalid invalid align.wast:452 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEgEQAEEARAAAAAAAAAAAOQQACw== +valid valid align.wast:458 AGFzbQEAAAABFwRgAX8BfWABfwF8YAJ/fwF/YAJ/fwF+AwUEAAECAwUDAQABB00EEGYzMl9hbGlnbl9zd2l0Y2gAABBmNjRfYWxpZ25fc3dpdGNoAAEQaTMyX2FsaWduX3N3aXRjaAACEGk2NF9hbGlnbl9zd2l0Y2gAAwr7CARjAQJ9QwAAIEEhAQJAAkACQAJAAkAgAA4EAAECAwQLQQAgATgCAEEAKgIAIQIMAwtBACABOAAAQQAqAAAhAgwCC0EAIAE4AQBBACoBACECDAELQQAgATgCAEEAKgIAIQILIAILewECfEQAAAAAAAAkQCEBAkACQAJAAkACQAJAIAAOBQABAgMEBQtBACABOQMAQQArAwAhAgwEC0EAIAE5AABBACsAACECDAMLQQAgATkBAEEAKwEAIQIMAgtBACABOQIAQQArAgAhAgwBC0EAIAE5AwBBACsDACECCyACC+ICAQJ/QQohAgJAAkACQAJAAkACQCAADgUAAQIDBAULIAFBAEYEQEEAIAI6AABBACwAACEDCyABQQFGBEBBACACOgAAQQAsAAAhAwsMBAsgAUEARgRAQQAgAjoAAEEALQAAIQMLIAFBAUYEQEEAIAI6AABBAC0AACEDCwwDCyABQQBGBEBBACACOwEAQQAuAQAhAwsgAUEBRgRAQQAgAjsAAEEALgAAIQMLIAFBAkYEQEEAIAI7AQBBAC4BACEDCwwCCyABQQBGBEBBACACOwEAQQAvAQAhAwsgAUEBRgRAQQAgAjsAAEEALwAAIQMLIAFBAkYEQEEAIAI7AQBBAC8BACEDCwwBCyABQQBGBEBBACACNgIAQQAoAgAhAwsgAUEBRgRAQQAgAjYAAEEAKAAAIQMLIAFBAkYEQEEAIAI2AQBBACgBACEDCyABQQRGBEBBACACNgIAQQAoAgAhAwsLIAMLtAQBAn5CCiECAkACQAJAAkACQAJAAkACQCAADgcAAQIDBAUGBwsgAUEARgRAQQAgAjwAAEEAMAAAIQMLIAFBAUYEQEEAIAI8AABBADAAACEDCwwGCyABQQBGBEBBACACPAAAQQAxAAAhAwsgAUEBRgRAQQAgAjwAAEEAMQAAIQMLDAULIAFBAEYEQEEAIAI9AQBBADIBACEDCyABQQFGBEBBACACPQAAQQAyAAAhAwsgAUECRgRAQQAgAj0BAEEAMgEAIQMLDAQLIAFBAEYEQEEAIAI9AQBBADMBACEDCyABQQFGBEBBACACPQAAQQAzAAAhAwsgAUECRgRAQQAgAj0BAEEAMwEAIQMLDAMLIAFBAEYEQEEAIAI+AgBBADQCACEDCyABQQFGBEBBACACPgAAQQA0AAAhAwsgAUECRgRAQQAgAj4BAEEANAEAIQMLIAFBBEYEQEEAIAI+AgBBADQCACEDCwwCCyABQQBGBEBBACACPgIAQQA1AgAhAwsgAUEBRgRAQQAgAj4AAEEANQAAIQMLIAFBAkYEQEEAIAI+AQBBADUBACEDCyABQQRGBEBBACACPgIAQQA1AgAhAwsMAQsgAUEARgRAQQAgAjcDAEEAKQMAIQMLIAFBAUYEQEEAIAI3AABBACkAACEDCyABQQJGBEBBACACNwEAQQApAQAhAwsgAUEERgRAQQAgAjcCAEEAKQIAIQMLIAFBCEYEQEEAIAI3AwBBACkDACEDCwsgAws= +valid valid align.wast:854 AGFzbQEAAAABCwJgAn9+AGABfwF/AwMCAAEFAwEAAQcQAgVzdG9yZQAABGxvYWQAAQoTAgkAIAAgATcCAAsHACAAKAIACw== +invalid invalid align.wast:873 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKB8AGgs= +malformed invalid align.wast:892 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKCAAGgs= +malformed invalid align.wast:911 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKCEAGgs= +malformed invalid align.wast:930 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKD8AGgs= +malformed invalid align.wast:949 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKEAAGgs= +malformed invalid align.wast:968 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEAKEEAGgs= +valid valid binary-leb128.wast:2 AGFzbQEAAAAFBAEAggA= +valid valid binary-leb128.wast:7 AGFzbQEAAAAFBwEAgoCAgAA= +valid valid binary-leb128.wast:12 AGFzbQEAAAAFBgEBggCCAA== +valid valid binary-leb128.wast:18 AGFzbQEAAAAFCQEBggCCgICAAA== +valid valid binary-leb128.wast:24 AGFzbQEAAAAFAwEAAAsHAYAAQQALAA== +valid valid binary-leb128.wast:32 AGFzbQEAAAAEBAFwAAAJCQECgABBAAsAAA== +valid valid binary-leb128.wast:41 AGFzbQEAAAAAigABMTIzNDU2Nzg5 +valid valid binary-leb128.wast:49 AGFzbQEAAAAAC4gAMTIzNDU2Nzg5 +valid valid binary-leb128.wast:57 AGFzbQEAAAABCAFgggB/fgF/ +valid valid binary-leb128.wast:66 AGFzbQEAAAABCAFgAn9+gQB/ +valid valid binary-leb128.wast:75 AGFzbQEAAAABBQFgAX8AAhcBiABzcGVjdGVzdAlwcmludF9pMzIAAA== +valid valid binary-leb128.wast:87 AGFzbQEAAAABBQFgAX8AAhcBCHNwZWN0ZXN0iQBwcmludF9pMzIAAA== +valid valid binary-leb128.wast:99 AGFzbQEAAAABBQFgAX8AAhcBCHNwZWN0ZXN0CXByaW50X2kzMgCAAA== +valid valid binary-leb128.wast:111 AGFzbQEAAAABBAFgAAADAwGAAAoEAQIACw== +valid valid binary-leb128.wast:120 AGFzbQEAAAABBAFgAAADAgEABwcBggBmMQAACgQBAgAL +valid valid binary-leb128.wast:133 AGFzbQEAAAABBAFgAAADAgEABwcBAmYxAIAACgQBAgAL +valid valid binary-leb128.wast:146 AGFzbQEAAAABBAFgAAADAgEACgWBAAIACw== +valid valid binary-leb128.wast:158 AGFzbQEAAAAGBwF/AEGAAAs= +valid valid binary-leb128.wast:165 AGFzbQEAAAAGBwF/AEH/fws= +valid valid binary-leb128.wast:172 AGFzbQEAAAAGCgF/AEGAgICAAAs= +valid valid binary-leb128.wast:179 AGFzbQEAAAAGCgF/AEH/////fws= +valid valid binary-leb128.wast:187 AGFzbQEAAAAGBwF+AEKAAAs= +valid valid binary-leb128.wast:194 AGFzbQEAAAAGBwF+AEL/fws= +valid valid binary-leb128.wast:201 AGFzbQEAAAAGDwF+AEKAgICAgICAgIAACw== +valid valid binary-leb128.wast:208 AGFzbQEAAAAGDwF+AEL///////////9/Cw== +malformed invalid binary-leb128.wast:218 AGFzbQEAAAAFCAEAgoCAgIAA +malformed invalid binary-leb128.wast:226 AGFzbQEAAAAFCgEBggCCgICAgAA= +malformed invalid binary-leb128.wast:235 AGFzbQEAAAAFAwEAAAsLAYCAgICAAEEACwA= +malformed invalid binary-leb128.wast:246 AGFzbQEAAAAEBAFwAAAJCwGAgICAgABBAAsA +malformed invalid binary-leb128.wast:257 AGFzbQEAAAAAg4CAgIAAATEy +malformed invalid binary-leb128.wast:268 AGFzbQEAAAAACoOAgICAADEyMzQ= +malformed invalid binary-leb128.wast:279 AGFzbQEAAAABDAFggoCAgIAAf34Bfw== +malformed invalid binary-leb128.wast:291 AGFzbQEAAAABDAFgAn9+gYCAgIAAfw== +malformed invalid binary-leb128.wast:303 AGFzbQEAAAABBQFgAX8AAhsBiICAgIAAc3BlY3Rlc3QJcHJpbnRfaTMyAAA= +malformed invalid binary-leb128.wast:318 AGFzbQEAAAABBQFgAX8AAhsBCHNwZWN0ZXN0iYCAgIAAcHJpbnRfaTMyAAA= +malformed invalid binary-leb128.wast:333 AGFzbQEAAAABBQFgAX8AAhsBCHNwZWN0ZXN0CXByaW50X2kzMgCAgICAgAA= +malformed invalid binary-leb128.wast:348 AGFzbQEAAAABBAFgAAADAwGAgICAgAAKBAECAAs= +malformed invalid binary-leb128.wast:360 AGFzbQEAAAABBAFgAAADAgEABwsBgoCAgIAAZjEAAAoEAQIACw== +malformed invalid binary-leb128.wast:376 AGFzbQEAAAABBAFgAAADAgEABwsBAmYxAICAgICAAAoEAQIACw== +malformed invalid binary-leb128.wast:392 AGFzbQEAAAABBAFgAAADAgEACgWBgICAgAACAAs= +malformed invalid binary-leb128.wast:405 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQAoAoKAgICAgICAgIAAGgs= +malformed invalid binary-leb128.wast:424 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQAogoCAgIAAABoL +malformed invalid binary-leb128.wast:443 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAQF/QQBBAzaCgICAgAADCw== +malformed invalid binary-leb128.wast:462 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAQF/QQBBAzYCgoCAgICAgICAgAAL +malformed invalid binary-leb128.wast:483 AGFzbQEAAAAGCwF/AEGAgICAgAAL +malformed invalid binary-leb128.wast:493 AGFzbQEAAAAGCwF/AEH//////38L +malformed invalid binary-leb128.wast:504 AGFzbQEAAAAGEAF+AEKAgICAgICAgICAAAs= +malformed invalid binary-leb128.wast:514 AGFzbQEAAAAGEAF+AEL/////////////fws= +malformed invalid binary-leb128.wast:526 AGFzbQEAAAAFBwEAgoCAgHA= +malformed invalid binary-leb128.wast:534 AGFzbQEAAAAFBwEAgoCAgEA= +malformed invalid binary-leb128.wast:542 AGFzbQEAAAAFCQEBggCCgICAEA== +malformed invalid binary-leb128.wast:551 AGFzbQEAAAAFCQEBggCCgICAQA== +malformed invalid binary-leb128.wast:560 AGFzbQEAAAAFAwEAAAsKAYCAgIAQQQALAA== +malformed invalid binary-leb128.wast:571 AGFzbQEAAAAEBAFwAAAJCgGAgICAEEEACwA= +malformed invalid binary-leb128.wast:582 AGFzbQEAAAAAg4CAgBABMTI= +malformed invalid binary-leb128.wast:593 AGFzbQEAAAAACYOAgIBAMTIzNA== +malformed invalid binary-leb128.wast:604 AGFzbQEAAAABCwFggoCAgBB/fgF/ +malformed invalid binary-leb128.wast:616 AGFzbQEAAAABCwFgAn9+gYCAgEB/ +malformed invalid binary-leb128.wast:628 AGFzbQEAAAABBQFgAX8AAhoBiICAgBBzcGVjdGVzdAlwcmludF9pMzIAAA== +malformed invalid binary-leb128.wast:643 AGFzbQEAAAABBQFgAX8AAhoBCHNwZWN0ZXN0iYCAgEBwcmludF9pMzIAAA== +malformed invalid binary-leb128.wast:658 AGFzbQEAAAABBQFgAX8AAhoBCHNwZWN0ZXN0CXByaW50X2kzMgCAgICAEA== +malformed invalid binary-leb128.wast:673 AGFzbQEAAAABBAFgAAADBgGAgICAEAoEAQIACw== +malformed invalid binary-leb128.wast:686 AGFzbQEAAAABBAFgAAADAgEABwoBgoCAgBBmMQAACgQBAgAL +malformed invalid binary-leb128.wast:702 AGFzbQEAAAABBAFgAAADAgEABwoBAmYxAICAgIAQCgQBAgAL +malformed invalid binary-leb128.wast:718 AGFzbQEAAAABBAFgAAADAgEACgiBgICAEAIACw== +malformed invalid binary-leb128.wast:731 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAQF/QQAoAoKAgICAgICAgBAaCw== +malformed invalid binary-leb128.wast:751 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAQF/QQAoAoKAgICAgICAgEAaCw== +malformed invalid binary-leb128.wast:771 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAQF/QQAogoCAgBAAGgs= +malformed invalid binary-leb128.wast:789 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAQF/QQAogoCAgEAAGgs= +malformed invalid binary-leb128.wast:808 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQBBAzaCgICAEAML +malformed invalid binary-leb128.wast:827 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQBBAzaCgICAQAML +malformed invalid binary-leb128.wast:846 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQBBAzYCgoCAgICAgICAEAs= +malformed invalid binary-leb128.wast:866 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAQF/QQBBAzYCgoCAgICAgICAQAs= +malformed invalid binary-leb128.wast:888 AGFzbQEAAAAGCgF/AEGAgICAcAs= +malformed invalid binary-leb128.wast:898 AGFzbQEAAAAGCgF/AEH/////Dws= +malformed invalid binary-leb128.wast:908 AGFzbQEAAAAGCgF/AEGAgICAHws= +malformed invalid binary-leb128.wast:918 AGFzbQEAAAAGCgF/AEH/////Tws= +malformed invalid binary-leb128.wast:929 AGFzbQEAAAAGDwF+AEKAgICAgICAgIB+Cw== +malformed invalid binary-leb128.wast:939 AGFzbQEAAAAGDwF+AEL///////////8BCw== +malformed invalid binary-leb128.wast:949 AGFzbQEAAAAGDwF+AEKAgICAgICAgIACCw== +malformed invalid binary-leb128.wast:959 AGFzbQEAAAAGDwF+AEL///////////9BCw== +valid valid binary-leb128.wast:969 AGFzbQEAAAABBAFgAAADAgEAChsBGQAA/IAAAPyBgAAA/IaAgAAA/IeAgIAAAAs= +malformed invalid binary-leb128.wast:990 AGFzbQEAAAABBAFgAAADAgEACg0BCwAA/IeAgICAAAAL +valid valid binary-leb128.wast:1015 AGFzbQEAAAAFAwEAAAsIAYIAAEEACwA= +valid valid binary-leb128.wast:1024 AGFzbQEAAAAFAwEAAAsJAYIAgABBAAsA +valid valid binary-leb128.wast:1035 AGFzbQEAAAAEBAFwAAAJBwGAAEEACwA= +valid valid binary-leb128.wast:1052 AGFzbQEAAAAEBAFwAAAJCQGCAABBAAsAAA== +valid valid binary-leb128.wast:1061 AGFzbQEAAAAEBAFwAAAJCgGCAIAAQQALAAA= +malformed invalid binary-leb128.wast:1073 AGFzbQEAAAABBQHgfwAA +valid valid binary.wast:1 AGFzbQEAAAA= +malformed invalid binary.wast:6 +malformed invalid binary.wast:7 AQ== +malformed invalid binary.wast:8 AGFz +malformed invalid binary.wast:9 YXNtAA== +malformed invalid binary.wast:10 bXNhAA== +malformed invalid binary.wast:11 bXNhAAEAAAA= +malformed invalid binary.wast:12 bXNhAAAAAAE= +malformed invalid binary.wast:13 YXNtAQAAAAA= +malformed invalid binary.wast:14 d2FzbQEAAAA= +malformed invalid binary.wast:15 f2FzbQEAAAA= +malformed invalid binary.wast:16 gGFzbQEAAAA= +malformed invalid binary.wast:17 gmFzbQEAAAA= +malformed invalid binary.wast:18 /2FzbQEAAAA= +malformed invalid binary.wast:21 AAAAAW1zYQA= +malformed invalid binary.wast:24 YQBtcwABAAA= +malformed invalid binary.wast:25 c20AYQAAAQA= +malformed invalid binary.wast:28 AEFTTQEAAAA= +malformed invalid binary.wast:31 AIGilAEAAAA= +malformed invalid binary.wast:34 77u/AGFzbQEAAAA= +malformed invalid binary.wast:37 AGFzbQ== +malformed invalid binary.wast:38 AGFzbQE= +malformed invalid binary.wast:39 AGFzbQEAAA== +malformed invalid binary.wast:40 AGFzbQAAAAA= +malformed invalid binary.wast:41 AGFzbQ0AAAA= +malformed invalid binary.wast:42 AGFzbQ4AAAA= +malformed invalid binary.wast:43 AGFzbQABAAA= +malformed invalid binary.wast:44 AGFzbQAAAQA= +malformed invalid binary.wast:45 AGFzbQAAAAE= +malformed invalid binary.wast:48 AGFzbQEAAAAOAQA= +malformed invalid binary.wast:49 AGFzbQEAAAB/AQA= +malformed invalid binary.wast:50 AGFzbQEAAACAAQABAQA= +malformed invalid binary.wast:51 AGFzbQEAAACBAQABAQA= +malformed invalid binary.wast:52 AGFzbQEAAAD/AQABAQA= +malformed invalid binary.wast:56 AGFzbQEAAAABBAFgAAADAwIAAAoMAgQAQQEaBQBBARoL +malformed invalid binary.wast:77 AGFzbQEAAAABBAFgAAADAgEACgYBBABBARo= +malformed invalid binary.wast:93 AGFzbQEAAAABBAFgAAADAgEACgYBBABBARoLAwEBAA== +malformed invalid binary.wast:113 AGFzbQEAAAABBAFgAAADAgEABgUBfwBBAAoEAQIACw== +malformed invalid binary.wast:126 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCQEHAEEAQAEaCw== +malformed valid binary.wast:146 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAQIAAGgs= +malformed valid binary.wast:166 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAQICAABoL +malformed valid binary.wast:185 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDAEKAEEAQICAgAAaCw== +malformed valid binary.wast:204 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDQELAEEAQICAgIAAGgs= +malformed invalid binary.wast:224 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKBwEFAD8BGgs= +malformed valid binary.wast:243 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCAEGAD+AABoL +malformed valid binary.wast:262 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCQEHAD+AgAAaCw== +malformed valid binary.wast:280 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAD+AgIAAGgs= +malformed valid binary.wast:298 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAD+AgICAABoL +malformed invalid binary.wast:317 AGFzbQEAAAABBAFgAAADAgEACgwBCgKAgICAEH8Cfgs= +malformed invalid binary.wast:351 AGFzbQEAAAABBAFgAAADAgEACgwBCgL/////D38Cfgs= +malformed invalid binary.wast:367 AGFzbQEAAAABBgFgAn9/AAMCAQAKHAEaBICAgIAEf4CAgIAEfoCAgIAEfYCAgIAEfAs= +valid valid binary.wast:385 AGFzbQEAAAABBAFgAAADAgEACgoBCAMAfwB+An0L +malformed invalid binary.wast:401 AGFzbQEAAAABBAFgAAADAwIAAA== +malformed invalid binary.wast:411 AGFzbQEAAAAKBAECAAs= +malformed invalid binary.wast:420 AGFzbQEAAAABBAFgAAADAwIAAAoEAQIACw== +malformed invalid binary.wast:431 AGFzbQEAAAABBAFgAAADAgEACgcCAgALAgAL +valid valid binary.wast:441 AGFzbQEAAAADAQA= +valid valid binary.wast:447 AGFzbQEAAAAKAQA= +malformed invalid binary.wast:454 AGFzbQEAAAAMAQMLBQIBAAEA +malformed invalid binary.wast:466 AGFzbQEAAAAMAQELBQIBAAEA +malformed invalid binary.wast:478 AGFzbQEAAAAFAwEAAQwBAQ== +valid valid binary.wast:487 AGFzbQEAAAAMAQA= +malformed invalid binary.wast:494 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDgEMAEEAQQBBAPwIAAALCwMBAQA= +malformed invalid binary.wast:517 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKBwEFAPwJAAsLAwEBAA== +malformed invalid binary.wast:537 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABQMBAAAJBwEFcAHzAAsKBAECAAs= +malformed invalid binary.wast:565 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABQMBAAAJBwEFfwHSAAsKBAECAAs= +valid valid binary.wast:592 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABQMBAAAJBwEFcAHSAAsKBAECAAs= +valid valid binary.wast:617 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABQMBAAAJBwEFcAHQcAsKBAECAAs= +valid valid binary.wast:643 AGFzbQEAAAABAQA= +malformed invalid binary.wast:650 AGFzbQEAAAABBwJgAAA= +malformed invalid binary.wast:661 AGFzbQEAAAABBwFgAABgAAA= +valid valid binary.wast:671 AGFzbQEAAAABBQFgAX8AAgEA +malformed invalid binary.wast:680 AGFzbQEAAAACBAEAAAQ= +malformed invalid binary.wast:690 AGFzbQEAAAACBQEAAAQA +malformed invalid binary.wast:701 AGFzbQEAAAACBAEAAAU= +malformed invalid binary.wast:711 AGFzbQEAAAACBQEAAAUA +malformed invalid binary.wast:722 AGFzbQEAAAACBAEAAIA= +malformed invalid binary.wast:732 AGFzbQEAAAACBQEAAIAA +malformed invalid binary.wast:745 AGFzbQEAAAABBQFgAX8AAhYCCHNwZWN0ZXN0CXByaW50X2kzMgAA +malformed invalid binary.wast:764 AGFzbQEAAAABCQJgAX8AYAF9AAIrAQhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9mMzIAAQ== +valid valid binary.wast:788 AGFzbQEAAAAEAQA= +malformed invalid binary.wast:795 AGFzbQEAAAAEAQE= +malformed invalid binary.wast:805 AGFzbQEAAAAEAwFwAg== +malformed invalid binary.wast:814 AGFzbQEAAAAEBAFwCAA= +malformed invalid binary.wast:824 AGFzbQEAAAAEBgFwgQAAAA== +valid valid binary.wast:835 AGFzbQEAAAAFAQA= +malformed invalid binary.wast:842 AGFzbQEAAAAFAQE= +malformed invalid binary.wast:852 AGFzbQEAAAAFAgEC +malformed invalid binary.wast:860 AGFzbQEAAAAFAwEQAA== +malformed invalid binary.wast:869 AGFzbQEAAAAFBQGBAAAA +malformed invalid binary.wast:878 AGFzbQEAAAAFBQGBAQAA +valid valid binary.wast:888 AGFzbQEAAAAGAQA= +malformed invalid binary.wast:895 AGFzbQEAAAAGBgJ/AEEACw== +malformed invalid binary.wast:906 AGFzbQEAAAAGCwF/AEEAC38AQQAL +valid valid binary.wast:916 AGFzbQEAAAABBAFgAAADAwIAAAcBAAoHAgIACwIACw== +malformed invalid binary.wast:929 AGFzbQEAAAABBAFgAAADAwIAAAcGAgJmMQAACgcCAgALAgAL +malformed invalid binary.wast:950 AGFzbQEAAAABBAFgAAADAwIAAAcLAQJmMQAAAmYyAAEKBwICAAsCAAs= +valid valid binary.wast:970 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQEACgQBAgAL +malformed invalid binary.wast:984 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQcCAEEACwEA +malformed invalid binary.wast:1000 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQoCAEEACwEAAEEA +malformed invalid binary.wast:1017 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQ0BAEEACwEAAEEACwEACgQBAgAL +valid valid binary.wast:1034 AGFzbQEAAAAFAwEAAQsBAA== +malformed invalid binary.wast:1043 AGFzbQEAAAAFAwEAAQsHAgBBAAsBYQ== +malformed invalid binary.wast:1056 AGFzbQEAAAAFAwEAAQsNAQBBAAsBYQBBAQsBYg== +malformed invalid binary.wast:1069 AGFzbQEAAAAFAwEAAQsMAQBBAwsHYWJjZGVm +malformed invalid binary.wast:1083 AGFzbQEAAAAFAwEAAQsMAQBBAAsFYWJjZGVm +valid valid binary.wast:1096 AGFzbQEAAAABBAFgAAADAgEAChEBDwACQEEBBEBBAQ4AAgsLCw== +malformed invalid binary.wast:1114 AGFzbQEAAAABJQxgAABgAABgAABgAABgAABgAABgAABgAABgAABgAABgAABgAAADAgEAChMBEQACQEEBBEBBAQ4BAAECCwsL +valid valid binary.wast:1147 AGFzbQEAAAABBAFgAAADAgEACAEACgQBAgAL +malformed invalid binary.wast:1161 AGFzbQEAAAABBAFgAAADAgEACAEACAEACgQBAgAL +malformed invalid binary.wast:1178 AGFzbQEAAAABBAFgAAADAgEAAwIBAAoHAgIACwIACw== +malformed invalid binary.wast:1190 AGFzbQEAAAABBAFgAAADAwIAAAoEAQIACwoEAQIACw== +malformed invalid binary.wast:1202 AGFzbQEAAAAMAQEMAQE= +malformed invalid binary.wast:1212 AGFzbQEAAAALAQALAQA= +malformed invalid binary.wast:1222 AGFzbQEAAAAGAQAGAQA= +malformed invalid binary.wast:1232 AGFzbQEAAAAHAQAHAQA= +malformed invalid binary.wast:1242 AGFzbQEAAAAEAQAEAQA= +malformed invalid binary.wast:1252 AGFzbQEAAAAJAQAJAQA= +malformed invalid binary.wast:1262 AGFzbQEAAAACAQACAQA= +malformed invalid binary.wast:1272 AGFzbQEAAAABAQABAQA= +malformed invalid binary.wast:1282 AGFzbQEAAAAFAQAFAQA= +malformed invalid binary.wast:1292 AGFzbQEAAAACAQABAQA= +malformed invalid binary.wast:1302 AGFzbQEAAAADAQACAQA= +malformed invalid binary.wast:1312 AGFzbQEAAAAEAQADAQA= +malformed invalid binary.wast:1322 AGFzbQEAAAAFAQAEAQA= +malformed invalid binary.wast:1332 AGFzbQEAAAAGAQAFAQA= +malformed invalid binary.wast:1342 AGFzbQEAAAAHAQAGAQA= +malformed invalid binary.wast:1352 AGFzbQEAAAABBAFgAAADAgEACAEABwEA +malformed invalid binary.wast:1364 AGFzbQEAAAABBAFgAAADAgEACQEACAEA +malformed invalid binary.wast:1376 AGFzbQEAAAAMAQEJAQA= +malformed invalid binary.wast:1386 AGFzbQEAAAAKAQAMAQE= +malformed invalid binary.wast:1396 AGFzbQEAAAALAQAKAQA= +valid valid block.wast:3 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 +invalid invalid block.wast:497 AGFzbQEAAAABBAFgAAADAgEACgkBBwACQEEACws= +invalid invalid block.wast:505 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAAkALCw== +invalid invalid block.wast:509 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAAkALCw== +invalid invalid block.wast:513 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAAkALCw== +invalid invalid block.wast:517 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAAkALCw== +invalid invalid block.wast:522 AGFzbQEAAAABBAFgAAADAgEACgkBBwACQEEBCws= +invalid invalid block.wast:528 AGFzbQEAAAABBAFgAAADAgEACgkBBwACQEIBCws= +invalid invalid block.wast:534 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEMAAIA/Cws= +invalid invalid block.wast:540 AGFzbQEAAAABBAFgAAADAgEAChABDgACQEQAAAAAAADwPwsL +invalid invalid block.wast:546 AGFzbQEAAAABBAFgAAADAgEACgsBCQACQEEBQQILCw== +invalid invalid block.wast:552 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAAn8LCw== +invalid invalid block.wast:558 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAAn4LCw== +invalid invalid block.wast:564 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAAn0LCw== +invalid invalid block.wast:570 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAAnwLCw== +invalid invalid block.wast:576 AGFzbQEAAAABBgFgAAJ/fwMCAQAKBwEFAAIACws= +invalid invalid block.wast:583 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAAJAAn8LGgsL +invalid invalid block.wast:592 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAANAAn8LGgsL +invalid invalid block.wast:601 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEABEACfwsaCws= +invalid invalid block.wast:611 AGFzbQEAAAABBQFgAAF/AwIBAAoIAQYAAn8BCws= +invalid invalid block.wast:617 AGFzbQEAAAABBQFgAAF+AwIBAAoIAQYAAn4BCws= +invalid invalid block.wast:623 AGFzbQEAAAABBQFgAAF9AwIBAAoIAQYAAn0BCws= +invalid invalid block.wast:629 AGFzbQEAAAABBQFgAAF8AwIBAAoIAQYAAnwBCws= +invalid invalid block.wast:635 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCAEGAAIAAQsL +invalid invalid block.wast:641 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAAn9CAAsL +invalid invalid block.wast:647 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAAn9DAAAAAAsL +invalid invalid block.wast:653 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9EAAAAAAAAAAALCw== +invalid invalid block.wast:659 AGFzbQEAAAABBQFgAAF+AwIBAAoJAQcAAn5BAAsL +invalid invalid block.wast:665 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAAn5DAAAAAAsL +invalid invalid block.wast:671 AGFzbQEAAAABBQFgAAF+AwIBAAoQAQ4AAn5EAAAAAAAAAAALCw== +invalid invalid block.wast:677 AGFzbQEAAAABBQFgAAF9AwIBAAoJAQcAAn1BAAsL +invalid invalid block.wast:683 AGFzbQEAAAABBQFgAAF9AwIBAAoJAQcAAn1CAAsL +invalid invalid block.wast:689 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AAn1EAAAAAAAAAAALCw== +invalid invalid block.wast:695 AGFzbQEAAAABBQFgAAF8AwIBAAoJAQcAAnxBAAsL +invalid invalid block.wast:701 AGFzbQEAAAABBQFgAAF8AwIBAAoJAQcAAnxCAAsL +invalid invalid block.wast:707 AGFzbQEAAAABBQFgAAF9AwIBAAoMAQoAAnxDAAAAAAsL +invalid invalid block.wast:713 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAAIAQQALCw== +invalid invalid block.wast:719 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCwEJAEEBAgBBAgsL +invalid invalid block.wast:725 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAn9BAUECCws= +invalid invalid block.wast:732 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAn4AAAAbCws= +invalid invalid block.wast:738 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAn0AAAAbCws= +invalid invalid block.wast:744 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAnwAAAAbCws= +invalid invalid block.wast:750 AGFzbQEAAAABBQFgAAF+AwIBAAoLAQkAAn8AAAAbCws= +invalid invalid block.wast:756 AGFzbQEAAAABBQFgAAF+AwIBAAoLAQkAAn0AAAAbCws= +invalid invalid block.wast:762 AGFzbQEAAAABBQFgAAF+AwIBAAoLAQkAAnwAAAAbCws= +invalid invalid block.wast:768 AGFzbQEAAAABBQFgAAF9AwIBAAoLAQkAAn8AAAAbCws= +invalid invalid block.wast:774 AGFzbQEAAAABBQFgAAF9AwIBAAoLAQkAAn4AAAAbCws= +invalid invalid block.wast:780 AGFzbQEAAAABBQFgAAF9AwIBAAoLAQkAAnwAAAAbCws= +invalid invalid block.wast:786 AGFzbQEAAAABBQFgAAF8AwIBAAoLAQkAAn8AAAAbCws= +invalid invalid block.wast:792 AGFzbQEAAAABBQFgAAF8AwIBAAoLAQkAAn4AAAAbCws= +invalid invalid block.wast:798 AGFzbQEAAAABBQFgAAF8AwIBAAoLAQkAAn0AAAAbCws= +invalid invalid block.wast:805 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAAn8MAAsL +invalid invalid block.wast:811 AGFzbQEAAAABBQFgAAF+AwIBAAoJAQcAAn4MAAsL +invalid invalid block.wast:817 AGFzbQEAAAABBQFgAAF9AwIBAAoJAQcAAn0MAAsL +invalid invalid block.wast:823 AGFzbQEAAAABBQFgAAF8AwIBAAoJAQcAAnwMAAsL +invalid invalid block.wast:829 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAAIADAALCw== +invalid invalid block.wast:836 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAn8MAEEBCws= +invalid invalid block.wast:842 AGFzbQEAAAABBQFgAAF+AwIBAAoLAQkAAn4MAEIBCws= +invalid invalid block.wast:848 AGFzbQEAAAABBQFgAAF9AwIBAAoOAQwAAn0MAEMAAIA/Cws= +invalid invalid block.wast:854 AGFzbQEAAAABBQFgAAF8AwIBAAoSARAAAnwMAEQAAAAAAADwPwsL +invalid invalid block.wast:860 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDQELAAIADABBAUECCws= +invalid invalid block.wast:867 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAAn8BDABBAQsL +invalid invalid block.wast:873 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAAn4BDABCAQsL +invalid invalid block.wast:879 AGFzbQEAAAABBQFgAAF9AwIBAAoPAQ0AAn0BDABDAACAPwsL +invalid invalid block.wast:885 AGFzbQEAAAABBQFgAAF8AwIBAAoTAREAAnwBDABEAAAAAAAA8D8LCw== +invalid invalid block.wast:892 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAn9CAQwAQQELCw== +invalid invalid block.wast:898 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9DAACAPwwAQQELCw== +invalid invalid block.wast:904 AGFzbQEAAAABBQFgAAF/AwIBAAoUARIAAn9EAAAAAAAA8D8MAEEBCws= +invalid invalid block.wast:910 AGFzbQEAAAABBQFgAAF+AwIBAAoNAQsAAn5BAQwAQgELCw== +invalid invalid block.wast:916 AGFzbQEAAAABBQFgAAF+AwIBAAoQAQ4AAn5DAACAPwwAQgELCw== +invalid invalid block.wast:922 AGFzbQEAAAABBQFgAAF+AwIBAAoUARIAAn5EAAAAAAAA8D8MAEIBCws= +invalid invalid block.wast:928 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AAn1BAQwAQwAAgD8LCw== +invalid invalid block.wast:934 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AAn1CAQwAQwAAgD8LCw== +invalid invalid block.wast:940 AGFzbQEAAAABBQFgAAF9AwIBAAoXARUAAn1EAAAAAAAA8D8MAEMAAIA/Cws= +invalid invalid block.wast:946 AGFzbQEAAAABBQFgAAF8AwIBAAoUARIAAn5BAQwARAAAAAAAAPA/Cws= +invalid invalid block.wast:952 AGFzbQEAAAABBQFgAAF8AwIBAAoUARIAAnxCAQwARAAAAAAAAPA/Cws= +invalid invalid block.wast:958 AGFzbQEAAAABBQFgAAF8AwIBAAoXARUAAnxDAACAPwwARAAAAAAAAPA/Cws= +invalid invalid block.wast:964 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDwENAAIAQQAMAEEBQQILCw== +invalid invalid block.wast:970 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDwENAEEBAgBBAAwAQQILCw== +invalid invalid block.wast:977 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn8BDABBAQwACws= +invalid invalid block.wast:983 AGFzbQEAAAABBQFgAAF+AwIBAAoOAQwAAn4BDABCAQwACws= +invalid invalid block.wast:989 AGFzbQEAAAABBQFgAAF9AwIBAAoRAQ8AAn0BDABDAACAPwwACws= +invalid invalid block.wast:995 AGFzbQEAAAABBQFgAAF8AwIBAAoVARMAAnwBDABEAAAAAAAA8D8MAAsL +invalid invalid block.wast:1001 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAAIAAQwAQQFBAgwACws= +invalid invalid block.wast:1008 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAn9CAQwAQQEMAAsL +invalid invalid block.wast:1014 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAn9DAACAPwwAQQEMAAsL +invalid invalid block.wast:1020 AGFzbQEAAAABBQFgAAF/AwIBAAoWARQAAn9EAAAAAAAA8D8MAEEBDAALCw== +invalid invalid block.wast:1026 AGFzbQEAAAABBQFgAAF+AwIBAAoPAQ0AAn5BAQwAQgEMAAsL +invalid invalid block.wast:1032 AGFzbQEAAAABBQFgAAF+AwIBAAoSARAAAn5DAACAPwwAQgEMAAsL +invalid invalid block.wast:1038 AGFzbQEAAAABBQFgAAF+AwIBAAoWARQAAn5EAAAAAAAA8D8MAEIBDAALCw== +invalid invalid block.wast:1044 AGFzbQEAAAABBQFgAAF9AwIBAAoSARAAAn1BAQwAQwAAgD8MAAsL +invalid invalid block.wast:1050 AGFzbQEAAAABBQFgAAF9AwIBAAoSARAAAn1CAQwAQwAAgD8MAAsL +invalid invalid block.wast:1056 AGFzbQEAAAABBQFgAAF9AwIBAAoZARcAAn1EAAAAAAAA8D8MAEMAAIA/DAALCw== +invalid invalid block.wast:1062 AGFzbQEAAAABBQFgAAF8AwIBAAoWARQAAnxBAQwARAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1068 AGFzbQEAAAABBQFgAAF8AwIBAAoWARQAAnxCAQwARAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1074 AGFzbQEAAAABBQFgAAF8AwIBAAoZARcAAnxDAACAPwwARAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1080 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEQEPAAIAQQAMAEEBQQIMAAsL +invalid invalid block.wast:1087 AGFzbQEAAAABBAFgAAADAgEAChABDgACfwJ/QQEMAQsMAAsL +invalid invalid block.wast:1093 AGFzbQEAAAABBAFgAAADAgEAChABDgACfgJ+QgEMAQsMAAsL +invalid invalid block.wast:1099 AGFzbQEAAAABBAFgAAADAgEAChMBEQACfQJ9QwAAgD8MAQsMAAsL +invalid invalid block.wast:1105 AGFzbQEAAAABBAFgAAADAgEAChcBFQACfAJ8RAAAAAAAAPA/DAELDAALCw== +invalid invalid block.wast:1111 AGFzbQEAAAABCQJgAABgAAJ/fwMCAQAKEgEQAAIBAgFBAUECDAELDAALCw== +invalid invalid block.wast:1118 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn8CQAwBC0EBDAALCw== +invalid invalid block.wast:1124 AGFzbQEAAAABBQFgAAF+AwIBAAoQAQ4AAn4CQAwBC0IBDAALCw== +invalid invalid block.wast:1130 AGFzbQEAAAABBQFgAAF9AwIBAAoTAREAAn0CQAwBC0MAAIA/DAALCw== +invalid invalid block.wast:1136 AGFzbQEAAAABBQFgAAF8AwIBAAoXARUAAnwCQAwBC0QAAAAAAADwPwwACws= +invalid invalid block.wast:1142 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEgEQAAIAAkAMAQtBAUECDAALCw== +invalid invalid block.wast:1149 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn8CfwEMAQtBAQwACws= +invalid invalid block.wast:1155 AGFzbQEAAAABBQFgAAF+AwIBAAoRAQ8AAn4CfgEMAQtCAQwACws= +invalid invalid block.wast:1161 AGFzbQEAAAABBQFgAAF9AwIBAAoUARIAAn0CfQEMAQtDAACAPwwACws= +invalid invalid block.wast:1167 AGFzbQEAAAABBQFgAAF8AwIBAAoYARYAAnwCfAEMAQtEAAAAAAAA8D8MAAsL +invalid invalid block.wast:1173 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEwERAAIAAgABDAELQQFBAgwACws= +invalid invalid block.wast:1180 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAn8Cf0IBDAELQQEMAAsL +invalid invalid block.wast:1188 AGFzbQEAAAABBQFgAAF/AwIBAAoVARMAAn8Cf0MAAIA/DAELQQEMAAsL +invalid invalid block.wast:1196 AGFzbQEAAAABBQFgAAF/AwIBAAoZARcAAn8Cf0QAAAAAAADwPwwBC0EBDAALCw== +invalid invalid block.wast:1204 AGFzbQEAAAABBQFgAAF+AwIBAAoSARAAAn4CfkEBDAELQgEMAAsL +invalid invalid block.wast:1212 AGFzbQEAAAABBQFgAAF+AwIBAAoVARMAAn4CfkMAAIA/DAELQgEMAAsL +invalid invalid block.wast:1220 AGFzbQEAAAABBQFgAAF+AwIBAAoZARcAAn4CfkQAAAAAAADwPwwBC0IBDAALCw== +invalid invalid block.wast:1228 AGFzbQEAAAABBQFgAAF9AwIBAAoVARMAAn0CfUEBDAELQwAAgD8MAAsL +invalid invalid block.wast:1236 AGFzbQEAAAABBQFgAAF9AwIBAAoVARMAAn0CfUIBDAELQwAAgD8MAAsL +invalid invalid block.wast:1244 AGFzbQEAAAABBQFgAAF9AwIBAAocARoAAn0CfUQAAAAAAADwPwwBC0MAAIA/DAALCw== +invalid invalid block.wast:1252 AGFzbQEAAAABBQFgAAF8AwIBAAoZARcAAnwCfEEBDAELRAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1260 AGFzbQEAAAABBQFgAAF8AwIBAAoZARcAAnwCfEIBDAELRAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1268 AGFzbQEAAAABBQFgAAF8AwIBAAocARoAAnwCfEMAAIA/DAELRAAAAAAAAPA/DAALCw== +invalid invalid block.wast:1276 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFAESAAIAAgBBAAwBC0EBQQIMAAsL +invalid invalid block.wast:1285 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAAkAMAAtoCw== +invalid invalid block.wast:1291 AGFzbQEAAAABBQFgAAF+AwIBAAoKAQgAAkAMAAt6Cw== +invalid invalid block.wast:1297 AGFzbQEAAAABBQFgAAF9AwIBAAoKAQgAAkAMAAuOCw== +invalid invalid block.wast:1303 AGFzbQEAAAABBQFgAAF8AwIBAAoKAQgAAkAMAAucCw== +invalid invalid block.wast:1309 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAAkAMAAtqCw== +invalid invalid block.wast:1316 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAkABDAALaAs= +invalid invalid block.wast:1322 AGFzbQEAAAABBQFgAAF+AwIBAAoLAQkAAkABDAALegs= +invalid invalid block.wast:1328 AGFzbQEAAAABBQFgAAF9AwIBAAoLAQkAAkABDAALjgs= +invalid invalid block.wast:1334 AGFzbQEAAAABBQFgAAF8AwIBAAoLAQkAAkABDAALnAs= +invalid invalid block.wast:1340 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAkABDAALags= +invalid invalid block.wast:1347 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAAkBCCQwAC3oL +invalid invalid block.wast:1353 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAkBDAAAQQQwAC44L +invalid invalid block.wast:1359 AGFzbQEAAAABBQFgAAF/AwIBAAoTAREAAkBEAAAAAAAAIkAMAAucCw== +invalid invalid block.wast:1365 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAAkBBCQwAC2gL +invalid invalid block.wast:1371 AGFzbQEAAAABBQFgAAF+AwIBAAoPAQ0AAkBDAAAQQQwAC44L +invalid invalid block.wast:1377 AGFzbQEAAAABBQFgAAF+AwIBAAoTAREAAkBEAAAAAAAAIkAMAAucCw== +invalid invalid block.wast:1383 AGFzbQEAAAABBQFgAAF9AwIBAAoMAQoAAkBBCQwAC2gL +invalid invalid block.wast:1389 AGFzbQEAAAABBQFgAAF9AwIBAAoMAQoAAkBCCQwAC3oL +invalid invalid block.wast:1395 AGFzbQEAAAABBQFgAAF9AwIBAAoTAREAAkBEAAAAAAAAIkAMAAucCw== +invalid invalid block.wast:1401 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAAkBBCQwAC2gL +invalid invalid block.wast:1407 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAAkBCCQwAC3oL +invalid invalid block.wast:1413 AGFzbQEAAAABBQFgAAF8AwIBAAoPAQ0AAkBDAAAQQQwAC44L +invalid invalid block.wast:1419 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAkBCCUEKDAALags= +invalid invalid block.wast:1426 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoIAQYAAgEaCws= +invalid invalid block.wast:1432 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKCQEHAAIBGhoLCw== +invalid invalid block.wast:1438 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoNAQsAQwAAAAACARoLCw== +invalid invalid block.wast:1444 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKDgEMAEMAAAAAAgEaGgsL +invalid invalid block.wast:1450 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoLAQkAAkACARoLCws= +invalid invalid block.wast:1456 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKDAEKAAJAAgEaGgsLCw== +invalid invalid block.wast:1462 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoQAQ4AAkBDAAAAAAIBGgsLCw== +invalid invalid block.wast:1468 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKEQEPAAJAQwAAAAACARoaCwsL +valid valid br.wast:3 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= +invalid invalid br.wast:484 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn9BAAJADAELCws= +invalid invalid br.wast:497 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAAJ/DAAMAAtFGgs= +invalid invalid br.wast:506 AGFzbQEAAAABBAFgAAADAgEAChEBDwBBAAJ/DABBAQ0AC0UaCw== +invalid invalid br.wast:515 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAAJ/DAAOAAALRRoL +invalid invalid br.wast:524 AGFzbQEAAAABBAFgAAADAgEACgwBCgACfwwADwtFGgs= +invalid invalid br.wast:535 AGFzbQEAAAABBAFgAAADAgEAChABDgACfwwAQQFBAhsLRRoL +invalid invalid br.wast:546 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABChICCwACfwwAEAELRRoLBAAgAAs= +invalid invalid br.wast:558 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoVAgQAIAALDgACfwwAQQARAAALRRoL +invalid invalid br.wast:574 AGFzbQEAAAABBAFgAAADAgEAChEBDwEBfwJ/DAAhACAAC0UaCw== +invalid invalid br.wast:586 AGFzbQEAAAABBAFgAAADAgEACg8BDQEBfwJ/DAAiAAtFGgs= +invalid invalid br.wast:598 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDwENAAJ/DAAkACMAC0UaCw== +invalid invalid br.wast:610 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDQELAAJ/DABAAAtFGgs= +invalid invalid br.wast:622 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAAJ/DAAoAgALRRoL +invalid invalid br.wast:634 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAAJ/DABBADYCAAtFGgs= +invalid invalid br.wast:647 AGFzbQEAAAABBAFgAAADAgEACgYBBAAMAQs= +invalid invalid br.wast:651 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQAJADAULCws= +invalid invalid br.wast:655 AGFzbQEAAAABBAFgAAADAgEACgoBCAAMgYCAgAEL +valid valid br_if.wast:3 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== +invalid invalid br_if.wast:481 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEADQBoCws= +invalid invalid br_if.wast:485 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEADQB6Cws= +invalid invalid br_if.wast:489 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEADQCMCws= +invalid invalid br_if.wast:493 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEADQCaCws= +invalid invalid br_if.wast:498 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEBDQBoCws= +invalid invalid br_if.wast:502 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEIBDQB6Cws= +invalid invalid br_if.wast:506 AGFzbQEAAAABBAFgAAADAgEACg8BDQACQEMAAIA/DQCMCws= +invalid invalid br_if.wast:510 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEIBDQCaCws= +invalid invalid br_if.wast:515 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAn9BAA0AQQELCw== +invalid invalid br_if.wast:521 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAn9BAQ0AQQELCw== +invalid invalid br_if.wast:527 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEAQQANAAsL +invalid invalid br_if.wast:533 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEAQQENAAsL +invalid invalid br_if.wast:540 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn8BQQANAEEBCws= +invalid invalid br_if.wast:546 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn8BQQENAEEBCws= +invalid invalid br_if.wast:552 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9CAUEADQAaQQELCw== +invalid invalid br_if.wast:569 AGFzbQEAAAABBAFgAAADAgEACgkBBwACQA0ACws= +invalid invalid br_if.wast:575 AGFzbQEAAAABBAFgAAADAgEACgoBCAACQAENAAsL +invalid invalid br_if.wast:581 AGFzbQEAAAABBAFgAAADAgEACgsBCQACQEIADQALCw== +invalid invalid br_if.wast:587 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn9BAAENAEEBCws= +invalid invalid br_if.wast:593 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9BAAJAQQENAQsLCw== +invalid invalid br_if.wast:599 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAn9BAEIADQBBAQsL +invalid invalid br_if.wast:606 AGFzbQEAAAABBAFgAAADAgEAChIBEAACQEEAQQAEfw0ACwtFGgs= +invalid invalid br_if.wast:618 AGFzbQEAAAABBAFgAAADAgEAChQBEgACQEEAQQAEf0EBDQALC0UaCw== +invalid invalid br_if.wast:630 AGFzbQEAAAABBAFgAAADAgEACgwBCgACfw0ADwtFGgs= +invalid invalid br_if.wast:641 AGFzbQEAAAABBAFgAAADAgEACg4BDAACf0EBDQAPC0UaCw== +invalid invalid br_if.wast:654 AGFzbQEAAAABBAFgAAADAgEACggBBgBBAQ0BCw== +invalid invalid br_if.wast:658 AGFzbQEAAAABBAFgAAADAgEACg4BDAACQAJAQQENBQsLCw== +invalid invalid br_if.wast:662 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAQ2BgICAAQs= +valid valid br_table.wast:3 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 +invalid invalid br_table.wast:1193 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAkBBAQ4AAEEBCws= +invalid invalid br_table.wast:1200 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAAkAOAABBAQsL +invalid invalid br_table.wast:1207 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAn8BQQEOAABBAQsL +invalid invalid br_table.wast:1213 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAn9CAUEBDgIAAABBAQsL +invalid invalid br_table.wast:1221 AGFzbQEAAAABBAFgAAADAgEAChYBFAACQAJ9QwAAAABBAA4BAAELGgsL +invalid invalid br_table.wast:1232 AGFzbQEAAAABBAFgAAADAgEAChIBEAACfwJ+QQBBAA4BAAELCws= +invalid invalid br_table.wast:1243 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQAEOAgAAAAsL +invalid invalid br_table.wast:1249 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEIADgAACws= +invalid invalid br_table.wast:1255 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9BAAEOAQAAQQELCw== +invalid invalid br_table.wast:1261 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn9BAAJAQQAOAAELCws= +invalid invalid br_table.wast:1267 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn9BAEIADgEAAEEBCws= +invalid invalid br_table.wast:1283 AGFzbQEAAAABBAFgAAADAgEAChMBEQACQEEAQQAEfw4AAAsLRRoL +invalid invalid br_table.wast:1295 AGFzbQEAAAABBAFgAAADAgEAChUBEwACQEEAQQAEf0EBDgAACwtFGgs= +invalid invalid br_table.wast:1307 AGFzbQEAAAABBAFgAAADAgEACg0BCwACfw4AAA8LRRoL +invalid invalid br_table.wast:1318 AGFzbQEAAAABBAFgAAADAgEACg8BDQACf0EBDgAADwtFGgs= +invalid invalid br_table.wast:1330 AGFzbQEAAAABBgFgAX8BfwMCAQAKEgEQAAN/An9BASAADgEAAQsLCw== +invalid invalid br_table.wast:1342 AGFzbQEAAAABBgFgAX8BfwMCAQAKEgEQAAJ/A39BASAADgEAAQsLCw== +invalid invalid br_table.wast:1356 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEBDgECAQsL +invalid invalid br_table.wast:1362 AGFzbQEAAAABBAFgAAADAgEAChABDgACQAJAQQEOAQAFCwsL +invalid invalid br_table.wast:1368 AGFzbQEAAAABBAFgAAADAgEAChIBEAACQEEBDgIAgYCAgAEACws= +invalid invalid br_table.wast:1375 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEBDgEBAgsL +invalid invalid br_table.wast:1387 AGFzbQEAAAABBAFgAAADAgEAChIBEAACQEEBDgIAAIGAgIABCws= +valid valid bulk.wast:2 AGFzbQEAAAAFAwEAAQsGAQEDZm9v +valid valid bulk.wast:6 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAAAwkNAQVwA9IAC9BwC9IBCwoHAgIACwIACw== +valid valid bulk.wast:13 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHEgIEZmlsbAAAB2xvYWQ4X3UAAQoVAgsAIAAgASAC/AsACwcAIAAtAAAL +valid valid bulk.wast:57 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxICBGNvcHkAAAdsb2FkOF91AAEKFgIMACAAIAEgAvwKAAALBwAgAC0AAAsLCgEAQQALBKq7zN0= +valid valid bulk.wast:115 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHEgIEaW5pdAAAB2xvYWQ4X3UAAQwBAQoWAgwAIAAgASAC/AgAAAsHACAALQAACwsHAQEEqrvM3Q== +valid valid bulk.wast:154 AGFzbQEAAAABCAJgAABgAX8AAwUEAAEAAQUDAQABBzsEDGRyb3BfcGFzc2l2ZQAADGluaXRfcGFzc2l2ZQABC2Ryb3BfYWN0aXZlAAILaW5pdF9hY3RpdmUAAwwBAgonBAUA/AkACwwAQQBBACAA/AgAAAsFAPwJAQsMAEEAQQAgAPwIAQALCwoCAQF4AEEACwF4 +valid valid bulk.wast:181 AGFzbQEAAAABBAFgAAADAgEADAFBCgcBBQD8CUALC4MBQQEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQA= +valid valid bulk.wast:196 AGFzbQEAAAABBAFgAAADAgEADAEBCgcBBQD8CQALCwoBAQdnb29kYnll +valid valid bulk.wast:199 AGFzbQEAAAABEANgAAF/YAN/f38AYAF/AX8DBQQAAAECBAQBcAADBw8CBGluaXQAAgRjYWxsAAMJCAEBAAQAAQABCiAEBABBAAsEAEEBCwwAIAAgASAC/AwAAAsHACAAEQAACw== +valid valid bulk.wast:244 AGFzbQEAAAABCAJgAABgAX8AAwYFAAABAAEEBAFwAAEHOwQMZHJvcF9wYXNzaXZlAAEMaW5pdF9wYXNzaXZlAAILZHJvcF9hY3RpdmUAAwtpbml0X2FjdGl2ZQAECQsCAQABAABBAAsBAAoqBQIACwUA/A0ACwwAQQBBACAA/AwAAAsFAPwNAQsMAEEAQQAgAPwMAQAL +valid valid bulk.wast:274 AGFzbQEAAAABBAFgAAADAgEACcQBQQEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAoHAQUA/A1ACw== +valid valid bulk.wast:297 AGFzbQEAAAABBAFgAAADAgEACQUBAQABAAoHAQUA/A0ACw== +valid valid bulk.wast:300 AGFzbQEAAAABEANgAAF/YAN/f38AYAF/AX8DBgUAAAABAgQEAXAACgcPAgRjb3B5AAMEY2FsbAAECQkBAEEACwMAAQIKJQUEAEEACwQAQQELBABBAgsMACAAIAEgAvwOAAALBwAgABEAAAs= +valid valid call.wast:3 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 +invalid invalid call.wast:381 AGFzbQEAAAABBAFgAAADAwIAAAoKAgUAEAFFCwIACw== +invalid invalid call.wast:388 AGFzbQEAAAABCAJgAABgAAF+AwMCAAEKDAIFABABRQsEAEIBCw== +invalid invalid call.wast:396 AGFzbQEAAAABCAJgAABgAX8AAwMCAAEKCQIEABABCwIACw== +invalid invalid call.wast:403 AGFzbQEAAAABCQJgAABgAnx/AAMDAgABCgkCBAAQAQsCAAs= +invalid invalid call.wast:410 AGFzbQEAAAABBAFgAAADAwIAAAoLAgYAQQEQAQsCAAs= +invalid invalid call.wast:417 AGFzbQEAAAABBAFgAAADAwIAAAoUAg8ARAAAAAAAAABAQQEQAQsCAAs= +invalid invalid call.wast:425 AGFzbQEAAAABCQJgAABgAn9/AAMDAgABCgwCBwABQQEQAQsCAAs= +invalid invalid call.wast:432 AGFzbQEAAAABCQJgAABgAn9/AAMDAgABCgwCBwBBAQEQAQsCAAs= +invalid invalid call.wast:439 AGFzbQEAAAABCQJgAABgAn98AAMDAgABChQCDwBEAAAAAAAA8D9BARABCwIACw== +invalid invalid call.wast:446 AGFzbQEAAAABCQJgAABgAnx/AAMDAgABChQCDwBBAUQAAAAAAADwPxABCwIACw== +invalid invalid call.wast:454 AGFzbQEAAAABCAJgAABgAX8AAwMCAAEKDAIHAAJAEAELCwIACw== +invalid invalid call.wast:463 AGFzbQEAAAABCQJgAABgAn9/AAMDAgABCg4CCQACQEEAEAELCwIACw== +invalid invalid call.wast:472 AGFzbQEAAAABCAJgAABgAX8AAwMCAAEKDAIHAANAEAELCwIACw== +invalid invalid call.wast:481 AGFzbQEAAAABCQJgAABgAn9/AAMDAgABCg4CCQADQEEAEAELCwIACw== +invalid invalid call.wast:490 AGFzbQEAAAABCAJgAABgAX8AAwMCAAEKDgIJAEEABEAQAQsLAgAL +invalid invalid call.wast:499 AGFzbQEAAAABCQJgAABgAn9/AAMDAgABChACCwBBAARAQQAQAQsLAgAL +invalid invalid call.wast:512 AGFzbQEAAAABBAFgAAADAgEACgYBBAAQAQs= +invalid invalid call.wast:516 AGFzbQEAAAABBAFgAAADAgEACgoBCAAQlJjb4gML +valid valid call_indirect.wast:3 AGFzbQEAAAABmAEdYAAAYAABf2AAAX5gAAF9YAABfGAAAnx/YAF/AX9gAX4BfmABfQF9YAF8AXxgAn98An98YAJ/fgJ+f2ACfX8Bf2ACf34BfmACfH0BfWACfnwBfGABfwF/YAF+AX5gAX0BfWABfAF8YAF+AGAEfnx/fgBgAX4Bf2AEfnx/fgF/YAACf3xgAAJ+f2ABfwF+YAF/AX1gAX8BfANRUAECAwQFBgcICQoLDQ8MDhAREhMAAQIDBAUCAQIDBAECAwQFGBkNGgYbHAcHBggJBggJBgYAAAABAQEBAgEDAQAAAQEAAwQEBAEDAQEBAQECBAUBcAEgIAUDAQABBg0BfAFEAAAAAAAAJEALB8QHOwh0eXBlLWkzMgAUCHR5cGUtaTY0ABUIdHlwZS1mMzIAFgh0eXBlLWY2NAAXDHR5cGUtZjY0LWkzMgAYCnR5cGUtaW5kZXgAGQ50eXBlLWZpcnN0LWkzMgAaDnR5cGUtZmlyc3QtaTY0ABsOdHlwZS1maXJzdC1mMzIAHA50eXBlLWZpcnN0LWY2NAAdD3R5cGUtc2Vjb25kLWkzMgAeD3R5cGUtc2Vjb25kLWk2NAAfD3R5cGUtc2Vjb25kLWYzMgAgD3R5cGUtc2Vjb25kLWY2NAAhEHR5cGUtYWxsLWY2NC1pMzIAIhB0eXBlLWFsbC1pMzItZjY0ACMQdHlwZS1hbGwtaTMyLWk2NAAkCGRpc3BhdGNoACUXZGlzcGF0Y2gtc3RydWN0dXJhbC1pNjQAJhdkaXNwYXRjaC1zdHJ1Y3R1cmFsLWkzMgAnF2Rpc3BhdGNoLXN0cnVjdHVyYWwtZjMyACgXZGlzcGF0Y2gtc3RydWN0dXJhbC1mNjQAKQdmYWMtaTY0ACoHZmliLWk2NAArB2ZhYy1pMzIALAdmYWMtZjMyAC0HZmFjLWY2NAAuB2ZpYi1pMzIALwdmaWItZjMyADAHZmliLWY2NAAxBGV2ZW4AMgNvZGQAMwdydW5hd2F5ADQObXV0dWFsLXJ1bmF3YXkANQ9hcy1zZWxlY3QtZmlyc3QANw1hcy1zZWxlY3QtbWlkADgOYXMtc2VsZWN0LWxhc3QAOQ9hcy1pZi1jb25kaXRpb24AOg5hcy1icl9pZi1maXJzdAA7DWFzLWJyX2lmLWxhc3QAPBFhcy1icl90YWJsZS1maXJz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 +valid valid call_indirect.wast:623 AGFzbQEAAAABEQNgAn9/AX9gAABgA39/fwF/AwoJAAAAAAABAgICBAwDcAECAnABAwNwAAQHHAMGY2FsbC0xAAYGY2FsbC0yAAcGY2FsbC0zAAgJIwQAQQALAgABAgFBAAsAAwIDBAICQQALAAIBAgICQQMLAAEFClAJBwAgACABagsHACAAIAFrCwcAIAAgAWwLBwAgACABbgsHACAAIAFwCwIACwsAIAAgASACEQAACwsAIAAgASACEQABCwsAIAAgASACEQACCw== +invalid invalid call_indirect.wast:791 AGFzbQEAAAABBAFgAAADAgEACgkBBwBBABEAAAs= +invalid invalid call_indirect.wast:799 AGFzbQEAAAABBAFgAAADAgEABAQBcAAACgoBCABBABEAAEUL +invalid invalid call_indirect.wast:807 AGFzbQEAAAABCAJgAAF+YAAAAwIBAQQEAXAAAAoKAQgAQQARAABFCw== +invalid invalid call_indirect.wast:816 AGFzbQEAAAABCAJgAX8AYAAAAwIBAQQEAXAAAAoJAQcAQQARAAAL +invalid invalid call_indirect.wast:824 AGFzbQEAAAABCQJgAnx/AGAAAAMCAQEEBAFwAAAKCQEHAEEAEQAACw== +invalid invalid call_indirect.wast:832 AGFzbQEAAAABBAFgAAADAgEABAQBcAAACgsBCQBBAUEAEQAACw== +invalid invalid call_indirect.wast:840 AGFzbQEAAAABBAFgAAADAgEABAQBcAAAChQBEgBEAAAAAAAAAEBBAUEAEQAACw== +invalid invalid call_indirect.wast:851 AGFzbQEAAAABCAJgAX8AYAAAAwIBAQQEAXAAAAoKAQgAQQEBEQAACw== +invalid invalid call_indirect.wast:859 AGFzbQEAAAABCAJgAX8AYAAAAwIBAQQEAXAAAAoLAQkAQQBCAREAAAs= +invalid invalid call_indirect.wast:868 AGFzbQEAAAABCQJgAn9/AGAAAAMCAQEEBAFwAAAKDAEKAAFBAUEAEQAACw== +invalid invalid call_indirect.wast:878 AGFzbQEAAAABCQJgAn9/AGAAAAMCAQEEBAFwAAAKDAEKAEEBAUEAEQAACw== +invalid invalid call_indirect.wast:888 AGFzbQEAAAABCQJgAn98AGAAAAMCAQEEBAFwAAAKFAESAEQAAAAAAADwP0EBQQARAAAL +invalid invalid call_indirect.wast:898 AGFzbQEAAAABCQJgAnx/AGAAAAMCAQEEBAFwAAAKFAESAEEBRAAAAAAAAPA/QQARAAAL +invalid invalid call_indirect.wast:909 AGFzbQEAAAABCAJgAX8AYAAAAwMCAAEEBQFwAQEBCQcBAEEACwEACg8CAgALCgACQEEAEQAACws= +invalid invalid call_indirect.wast:922 AGFzbQEAAAABCQJgAn9/AGAAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoRAgIACwwAAkBBAEEAEQAACws= +invalid invalid call_indirect.wast:935 AGFzbQEAAAABCAJgAX8AYAAAAwMCAAEEBQFwAQEBCQcBAEEACwEACg8CAgALCgADQEEAEQAACws= +invalid invalid call_indirect.wast:948 AGFzbQEAAAABCQJgAn9/AGAAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoRAgIACwwAA0BBAEEAEQAACws= +invalid invalid call_indirect.wast:961 AGFzbQEAAAABCAJgAX8AYAAAAwMCAAEEBQFwAQEBCQcBAEEACwEAChMCAgALDgBBAEEABEBBABEAAAsL +invalid invalid call_indirect.wast:977 AGFzbQEAAAABCQJgAn9/AGAAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoVAgIACxAAQQBBAARAQQBBABEAAAsL +invalid invalid call_indirect.wast:995 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgkBBwBBABEAAAs= +invalid invalid call_indirect.wast:1006 AGFzbQEAAAABBAFgAAADAgEABAQBcAAACgkBBwBBABEBAAs= +invalid invalid call_indirect.wast:1013 AGFzbQEAAAABBAFgAAADAgEABAQBcAAACg0BCwBBABGUmNviAwAL +invalid invalid call_indirect.wast:1022 AGFzbQEAAAABCAJgAX8AYAAAAwIBAQQEAXAAAQoSARAAQQEEQEEAEf////8PAAsL +invalid invalid call_indirect.wast:1038 AGFzbQEAAAAEBQFwAQICCQgBAEEACwIAAA== +valid valid call_indirect.wast:1047 AGFzbQEAAAABCAJgAABgAAF/AwwLAAAAAAAAAAAAAQEEBAFwAAEKZgsGAAARAAALBwAAEQAAAQsJAAARAAARAAALCQAAEQAAEQAACwwAABEAABEAABEAAAsGAAARAAALBgAAEQAACwkAABEAABEAAAsJAAARAAARAAALBwAAEQAAGwsKAAARAAAbEQAACw== +valid valid comments.wast:0 AGFzbQEAAAABBQFgAAF/AwQDAAAABxADAmYxAAACZjIAAQJmMwACChkDBwBBAUECDwsHAEEBQQIPCwcAQQFBAg8L +valid valid const.wast:5 AGFzbQEAAAABBAFgAAADAgEACgoBCABBlZrvOhoL +valid valid const.wast:6 AGFzbQEAAAABBAFgAAADAgEACgsBCQBB3/e/1nkaCw== +valid valid const.wast:24 AGFzbQEAAAABBAFgAAADAgEACgoBCABClZrvOhoL +valid valid const.wast:25 AGFzbQEAAAABBAFgAAADAgEACg8BDQBC7/m+75rx2ZIBGgs= +valid valid const.wast:43 AGFzbQEAAAABBAFgAAADAgEACgoBCABDo3nrTBoL +valid valid const.wast:44 AGFzbQEAAAABBAFgAAADAgEACgoBCABDe01/bBoL +valid valid const.wast:46 AGFzbQEAAAABBAFgAAADAgEACgoBCABD/y9ZLRoL +valid valid const.wast:55 AGFzbQEAAAABBAFgAAADAgEACgoBCABDtKKRWxoL +valid valid const.wast:56 AGFzbQEAAAABBAFgAAADAgEACgoBCABDtKIRZRoL +valid valid const.wast:58 AGFzbQEAAAABBAFgAAADAgEACgoBCABDtKIRUhoL +valid valid const.wast:145 AGFzbQEAAAABBAFgAAADAgEACg4BDABEAAAAVDRvnUEaCw== +valid valid const.wast:146 AGFzbQEAAAABBAFgAAADAgEACg4BDABE+hZeW6/pj0UaCw== +valid valid const.wast:148 AGFzbQEAAAABBAFgAAADAgEACg4BDABEEUMr1v8lqz0aCw== +valid valid const.wast:153 AGFzbQEAAAABBAFgAAADAgEACg4BDABEWKQMVDRvnUEaCw== +valid valid const.wast:154 AGFzbQEAAAABBAFgAAADAgEACg4BDABE1ctrW6/pj0UaCw== +valid valid const.wast:156 AGFzbQEAAAABBAFgAAADAgEACg4BDABEEuw21v8lqz0aCw== +valid valid const.wast:164 AGFzbQEAAAABBAFgAAADAgEACg4BDABE37yaeFY08kQaCw== +valid valid const.wast:165 AGFzbQEAAAABBAFgAAADAgEACg4BDABE37yaeFY0IkYaCw== +valid valid const.wast:167 AGFzbQEAAAABBAFgAAADAgEACg4BDABE37yaeFY0wkMaCw== +valid valid const.wast:264 AGFzbQEAAAABBAFgAAADAgEACgcBBQBBfxoL +valid valid const.wast:265 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBgICAgHgaCw== +valid valid const.wast:286 AGFzbQEAAAABBAFgAAADAgEACgcBBQBCfxoL +valid valid const.wast:287 AGFzbQEAAAABBAFgAAADAgEAChABDgBCgICAgICAgICAfxoL +valid valid const.wast:308 AGFzbQEAAAABBAFgAAADAgEACgoBCABDAAAAfxoL +valid valid const.wast:309 AGFzbQEAAAABBAFgAAADAgEACgoBCABDAAAA/xoL +valid valid const.wast:310 AGFzbQEAAAABBAFgAAADAgEACgoBCABD//9/fxoL +valid valid const.wast:311 AGFzbQEAAAABBAFgAAADAgEACgoBCABD//9//xoL +valid valid const.wast:335 AGFzbQEAAAABBAFgAAADAgEACgoBCABDmXaWfhoL +valid valid const.wast:336 AGFzbQEAAAABBAFgAAADAgEACgoBCABDmXaW/hoL +valid valid const.wast:357 AGFzbQEAAAABBAFgAAADAgEACg4BDABEAAAAAAAA4H8aCw== +valid valid const.wast:358 AGFzbQEAAAABBAFgAAADAgEACg4BDABEAAAAAAAA4P8aCw== +valid valid const.wast:359 AGFzbQEAAAABBAFgAAADAgEACg4BDABE////////738aCw== +valid valid const.wast:360 AGFzbQEAAAABBAFgAAADAgEACg4BDABE////////7/8aCw== +valid valid const.wast:382 AGFzbQEAAAABBAFgAAADAgEACg4BDABEoMjrhfPM4X8aCw== +valid valid const.wast:383 AGFzbQEAAAABBAFgAAADAgEACg4BDABEoMjrhfPM4f8aCw== +valid valid const.wast:404 AGFzbQEAAAABBAFgAAADAgEACgoBCABDAQCAfxoL +valid valid const.wast:405 AGFzbQEAAAABBAFgAAADAgEACg4BDABEAQAAAAAA8H8aCw== +valid valid const.wast:406 AGFzbQEAAAABBAFgAAADAgEACgoBCABD////fxoL +valid valid const.wast:407 AGFzbQEAAAABBAFgAAADAgEACg4BDABE/////////38aCw== +valid valid const.wast:440 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAIAmCw== +valid valid const.wast:442 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAICmCw== +valid valid const.wast:444 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAIAmCw== +valid valid const.wast:446 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAICmCw== +valid valid const.wast:464 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAIAmCw== +valid valid const.wast:466 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAICmCw== +valid valid const.wast:492 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAIAmCw== +valid valid const.wast:494 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAICmCw== +valid valid const.wast:564 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAIBYCw== +valid valid const.wast:566 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAIDYCw== +valid valid const.wast:568 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAIBYCw== +valid valid const.wast:570 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAIDYCw== +valid valid const.wast:588 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAIBYCw== +valid valid const.wast:590 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAIDYCw== +valid valid const.wast:616 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAIBYCw== +valid valid const.wast:618 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAIDYCw== +valid valid const.wast:668 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAAAACw== +valid valid const.wast:670 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMAAACACw== +valid valid const.wast:672 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAAAACw== +valid valid const.wast:674 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMBAACACw== +valid valid const.wast:692 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAAAACw== +valid valid const.wast:694 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMCAACACw== +valid valid const.wast:720 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAAAACw== +valid valid const.wast:722 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEMDAACACw== +valid valid const.wast:726 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEP//39/Cw== +valid valid const.wast:728 AGFzbQEAAAABBQFgAAF9AwIBAAcFAQFmAAAKCQEHAEP//3//Cw== +valid valid const.wast:740 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABwGgs= +valid valid const.wast:742 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABwmgs= +valid valid const.wast:744 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABwGgs= +valid valid const.wast:746 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABwmgs= +valid valid const.wast:764 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABwGgs= +valid valid const.wast:766 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABwmgs= +valid valid const.wast:788 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAABwGgs= +valid valid const.wast:790 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAABwmgs= +valid valid const.wast:846 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABgfgs= +valid valid const.wast:848 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABg/gs= +valid valid const.wast:850 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABgfgs= +valid valid const.wast:852 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABg/gs= +valid valid const.wast:858 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABgfgs= +valid valid const.wast:860 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABg/gs= +valid valid const.wast:864 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABwZQs= +valid valid const.wast:866 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAABw5Qs= +valid valid const.wast:868 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABwZQs= +valid valid const.wast:870 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAABw5Qs= +valid valid const.wast:888 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABwZQs= +valid valid const.wast:890 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAABw5Qs= +valid valid const.wast:916 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAABwZQs= +valid valid const.wast:918 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAABw5Qs= +valid valid const.wast:921 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAAAARgs= +valid valid const.wast:923 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAAAAxgs= +valid valid const.wast:925 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAAAARgs= +valid valid const.wast:927 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAAAAxgs= +valid valid const.wast:945 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAAAARgs= +valid valid const.wast:947 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAAAAxgs= +valid valid const.wast:973 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAAAARgs= +valid valid const.wast:975 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAAAAxgs= +valid valid const.wast:978 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAACwQws= +valid valid const.wast:980 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAACwwws= +valid valid const.wast:982 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAACwQws= +valid valid const.wast:984 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAACwwws= +valid valid const.wast:990 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAACwQws= +valid valid const.wast:992 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAACwwws= +valid valid const.wast:996 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAAAAAAs= +valid valid const.wast:998 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQAAAAAAAAAgAs= +valid valid const.wast:1000 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAAAAAAs= +valid valid const.wast:1002 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQBAAAAAAAAgAs= +valid valid const.wast:1020 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAAAAAAs= +valid valid const.wast:1022 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQCAAAAAAAAgAs= +valid valid const.wast:1048 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAAAQAAs= +valid valid const.wast:1050 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAEQDAAAAAAAQgAs= +valid valid const.wast:1054 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAET////////vfws= +valid valid const.wast:1056 AGFzbQEAAAABBQFgAAF8AwIBAAcFAQFmAAAKDQELAET////////v/ws= +valid valid conversions.wast:1 AGFzbQEAAAABPQxgAX8BfmABfgF/YAF9AX9gAXwBf2ABfQF+YAF8AX5gAX8BfWABfgF9YAF/AXxgAX4BfGABfQF8YAF8AX0DIiEAAAECAgMDBAQFBQICAwMEBAUFBgcICQYHCAkKCwYJAgUHkQUhEGk2NC5leHRlbmRfaTMyX3MAABBpNjQuZXh0ZW5kX2kzMl91AAEMaTMyLndyYXBfaTY0AAIPaTMyLnRydW5jX2YzMl9zAAMPaTMyLnRydW5jX2YzMl91AAQPaTMyLnRydW5jX2Y2NF9zAAUPaTMyLnRydW5jX2Y2NF91AAYPaTY0LnRydW5jX2YzMl9zAAcPaTY0LnRydW5jX2YzMl91AAgPaTY0LnRydW5jX2Y2NF9zAAkPaTY0LnRydW5jX2Y2NF91AAoTaTMyLnRydW5jX3NhdF9mMzJfcwALE2kzMi50cnVuY19zYXRfZjMyX3UADBNpMzIudHJ1bmNfc2F0X2Y2NF9zAA0TaTMyLnRydW5jX3NhdF9mNjRfdQAOE2k2NC50cnVuY19zYXRfZjMyX3MADxNpNjQudHJ1bmNfc2F0X2YzMl91ABATaTY0LnRydW5jX3NhdF9mNjRfcwARE2k2NC50cnVuY19zYXRfZjY0X3UAEhFmMzIuY29udmVydF9pMzJfcwATEWYzMi5jb252ZXJ0X2k2NF9zABQRZjY0LmNvbnZlcnRfaTMyX3MAFRFmNjQuY29udmVydF9pNjRfcwAWEWYzMi5jb252ZXJ0X2kzMl91ABcRZjMyLmNvbnZlcnRfaTY0X3UAGBFmNjQuY29udmVydF9pMzJfdQAZEWY2NC5jb252ZXJ0X2k2NF91ABoPZjY0LnByb21vdGVfZjMyABsOZjMyLmRlbW90ZV9mNjQAHBNmMzIucmVpbnRlcnByZXRfaTMyAB0TZjY0LnJlaW50ZXJwcmV0X2k2NAAeE2kzMi5yZWludGVycHJldF9mMzIAHxNpNjQucmVpbnRlcnByZXRfZjY0ACAKzwEhBQAgAKwLBQAgAK0LBQAgAKcLBQAgAKgLBQAgAKkLBQAgAKoLBQAgAKsLBQAgAK4LBQAgAK8LBQAgALALBQAgALELBgAgAPwACwYAIAD8AQsGACAA/AILBgAgAPwDCwYAIAD8BAsGACAA/AULBgAgAPwGCwYAIAD8BwsFACAAsgsFACAAtAsFACAAtwsFACAAuQsFACAAswsFACAAtQsFACAAuAsFACAAugsFACAAuwsFACAAtgsFACAAvgsFACAAvwsFACAAvAsFACAAvQs= +invalid invalid conversions.wast:678 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAQwAAAACnCw== +invalid invalid conversions.wast:679 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgCoCw== +invalid invalid conversions.wast:680 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgCpCw== +invalid invalid conversions.wast:681 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgCqCw== +invalid invalid conversions.wast:682 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgCrCw== +invalid invalid conversions.wast:683 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgC8Cw== +invalid invalid conversions.wast:684 AGFzbQEAAAABBQFgAAF+AwIBAAoKAQgAQwAAAACsCw== +invalid invalid conversions.wast:685 AGFzbQEAAAABBQFgAAF+AwIBAAoKAQgAQwAAAACtCw== +invalid invalid conversions.wast:686 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQCuCw== +invalid invalid conversions.wast:687 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQCvCw== +invalid invalid conversions.wast:688 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQCwCw== +invalid invalid conversions.wast:689 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQCxCw== +invalid invalid conversions.wast:690 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQC9Cw== +invalid invalid conversions.wast:691 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCyCw== +invalid invalid conversions.wast:692 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCzCw== +invalid invalid conversions.wast:693 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQQC0Cw== +invalid invalid conversions.wast:694 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQQC1Cw== +invalid invalid conversions.wast:695 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQQC2Cw== +invalid invalid conversions.wast:696 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgC+Cw== +invalid invalid conversions.wast:697 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgC3Cw== +invalid invalid conversions.wast:698 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgC4Cw== +invalid invalid conversions.wast:699 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQQC5Cw== +invalid invalid conversions.wast:700 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQQC6Cw== +invalid invalid conversions.wast:701 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQQC7Cw== +invalid invalid conversions.wast:702 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQQC/Cw== +valid valid custom.wast:1 AGFzbQEAAAAAJBBhIGN1c3RvbSBzZWN0aW9udGhpcyBpcyB0aGUgcGF5bG9hZAAgEGEgY3VzdG9tIHNlY3Rpb250aGlzIGlzIHBheWxvYWQAERBhIGN1c3RvbSBzZWN0aW9uABAAdGhpcyBpcyBwYXlsb2FkAAEAACQQAABjdXN0b20gc2VjdGlvAHRoaXMgaXMgdGhlIHBheWxvYWQAJBDvu79hIGN1c3RvbSBzZWN0dGhpcyBpcyB0aGUgcGF5bG9hZAAkEGEgY3VzdG9tIHNlY3TijKN0aGlzIGlzIHRoZSBwYXlsb2FkAB8WbW9kdWxlIHdpdGhpbiBhIG1vZHVsZQBhc20BAAAA +valid valid custom.wast:14 AGFzbQEAAAAADgZjdXN0b21wYXlsb2FkAA4GY3VzdG9tcGF5bG9hZAEBAAAOBmN1c3RvbXBheWxvYWQADgZjdXN0b21wYXlsb2FkAgEAAA4GY3VzdG9tcGF5bG9hZAAOBmN1c3RvbXBheWxvYWQDAQAADgZjdXN0b21wYXlsb2FkAA4GY3VzdG9tcGF5bG9hZAQBAAAOBmN1c3RvbXBheWxvYWQADgZjdXN0b21wYXlsb2FkBQEAAA4GY3VzdG9tcGF5bG9hZAAOBmN1c3RvbXBheWxvYWQGAQAADgZjdXN0b21wYXlsb2FkAA4GY3VzdG9tcGF5bG9hZAcBAAAOBmN1c3RvbXBheWxvYWQADgZjdXN0b21wYXlsb2FkCQEAAA4GY3VzdG9tcGF5bG9hZAAOBmN1c3RvbXBheWxvYWQKAQAADgZjdXN0b21wYXlsb2FkAA4GY3VzdG9tcGF5bG9hZAsBAAAOBmN1c3RvbXBheWxvYWQADgZjdXN0b21wYXlsb2Fk +valid valid custom.wast:50 AGFzbQEAAAABBwFgAn9/AX8AGgZjdXN0b210aGlzIGlzIHRoZSBwYXlsb2FkAwIBAAcKAQZhZGRUd28AAAoJAQcAIAAgAWoLABsHY3VzdG9tMnRoaXMgaXMgdGhlIHBheWxvYWQ= +malformed invalid custom.wast:61 AGFzbQEAAAAA +malformed invalid custom.wast:69 AGFzbQEAAAAAAA== +malformed invalid custom.wast:77 AGFzbQEAAAAAAAAFAQAHAAA= +malformed invalid custom.wast:85 AGFzbQEAAAAAJhBhIGN1c3RvbSBzZWN0aW9udGhpcyBpcyB0aGUgcGF5bG9hZA== +malformed invalid custom.wast:93 AGFzbQEAAAAAJRBhIGN1c3RvbSBzZWN0aW9udGhpcyBpcyB0aGUgcGF5bG9hZAAkEGEgY3VzdG9tIHNlY3Rpb250aGlzIGlzIHRoZSBwYXlsb2Fk +malformed invalid custom.wast:102 AGFzbQEAAAABBwFgAn9/AX8AJRBhIGN1c3RvbSBzZWN0aW9udGhpcyBpcyB0aGUgcGF5bG9hZAMCAQAKCQEHACAAIAFqCwAbB2N1c3RvbTJ0aGlzIGlzIHRoZSBwYXlsb2Fk +malformed invalid custom.wast:115 AGFzbQEAAAAAYXNtAQAAAA== +malformed invalid custom.wast:123 AGFzbQEAAAAFAwEAAQwBAgsGAQBBAAsA +valid valid data.wast:5 AGFzbQEAAAAFAwEAAQuzARwAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMBAAEEYWJjZABBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwBBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwBBAAsAAEEBCwRhYmNkAEEACwAAQQALA2FiYwEAAQRhYmNk +valid valid data.wast:39 AGFzbQEAAAAFAwEAAQsHAQBBAAsBYQ== +valid valid data.wast:43 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwcBAEEACwFh +valid valid data.wast:48 AGFzbQEAAAAFAwEAAQsiBQBBAAsBYQBBAwsBYgBB5AALA2NkZQBBBQsBeABBAwsBYw== +valid valid data.wast:56 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCycGAEEACwFhAEEBCwFiAEECCwNjZGUAQQMLAWYAQQILAWcAQQELAWg= +valid valid data.wast:66 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAUDAQABCwcBACMACwFh +valid valid data.wast:71 AGFzbQEAAAACKwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAAELBwEAIwALAWE= +invalid valid data.wast:89 AGFzbQEAAAAFAwEAAQYGAX8AQQALCwcBACMACwFh +valid valid data.wast:100 AGFzbQEAAAAFAwEAAQsPAgBBAAsBYQBB//8DCwFi +valid valid data.wast:105 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCw8CAEEACwFhAEH//wMLAWI= +valid valid data.wast:111 AGFzbQEAAAAFAwEAAgsJAQBB//8HCwFh +valid valid data.wast:116 AGFzbQEAAAAFAwEAAAsGAQBBAAsA +valid valid data.wast:120 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwYBAEEACwA= +valid valid data.wast:125 AGFzbQEAAAAFBAEBAAALBgEAQQALAA== +valid valid data.wast:130 AGFzbQEAAAAFAwEAAQsIAQBBgIAECwA= +valid valid data.wast:149 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwcBAEEACwFh +valid valid data.wast:154 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAwsHAQBBAAsBYQ== +valid valid data.wast:159 AGFzbQEAAAACKwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAAALBwEAIwALAWE= +valid valid data.wast:165 AGFzbQEAAAACLAIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdAZtZW1vcnkCAQADCwcBACMACwFh +valid valid data.wast:171 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAACwcBAEEBCwFh +valid valid data.wast:176 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAwsHAQBBAQsBYQ== +valid valid data.wast:184 AGFzbQEAAAAFAwEAAAsHAQBBAAsBYQ== +valid valid data.wast:192 AGFzbQEAAAAFBAEBAAALBwEAQQALAWE= +valid valid data.wast:200 AGFzbQEAAAAFBAEBAAELBwEAQQALAWE= +valid valid data.wast:207 AGFzbQEAAAAFAwEAAAsGAQBBAQsA +valid valid data.wast:214 AGFzbQEAAAAFBAEBAAELBgEAQQELAA== +valid valid data.wast:231 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAUDAQAACwcBACMACwFh +valid valid data.wast:240 AGFzbQEAAAAFBAEBAQILCQEAQYCABAsBYQ== +valid valid data.wast:247 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwkBAEGAgAQLAWE= +valid valid data.wast:255 AGFzbQEAAAAFAwEAAgsJAQBBgIAICwFh +valid valid data.wast:263 AGFzbQEAAAAFBAEBAgMLCQEAQYCACAsBYQ== +valid valid data.wast:271 AGFzbQEAAAAFAwEAAQsHAQBBfwsBYQ== +valid valid data.wast:278 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwcBAEF/CwFh +valid valid data.wast:286 AGFzbQEAAAAFAwEAAgsIAQBBnH8LAWE= +valid valid data.wast:293 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgABCwgBAEGcfwsBYQ== +invalid invalid data.wast:303 AGFzbQEAAAALBgEAQQALAA== +invalid invalid data.wast:311 AGFzbQEAAAAFAwEAAAsHAQIBQQALAA== +invalid invalid data.wast:335 AGFzbQEAAAALBwECAUEACwA= +invalid invalid data.wast:347 AGFzbQEAAAAFAwEAAAtFAQIBQQALPgABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9 +invalid invalid data.wast:369 AGFzbQEAAAALRQECAUEACz4AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PQ== +invalid invalid data.wast:388 AGFzbQEAAAAFAwEAAQsGAQBCAAsA +invalid invalid data.wast:396 AGFzbQEAAAAFAwEAAQsGAQDQcAsA +invalid invalid data.wast:404 AGFzbQEAAAAFAwEAAQsEAQALAA== +invalid invalid data.wast:412 AGFzbQEAAAAFAwEAAQsIAQBBAEEACwA= +invalid invalid data.wast:420 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABQMBAAELCAEAIwAjAAsA +invalid invalid data.wast:429 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABQMBAAELCAEAIwBBAAsA +invalid invalid data.wast:438 AGFzbQEAAAAFAwEAAQsHAQBBAGgLAA== +invalid invalid data.wast:446 AGFzbQEAAAAFAwEAAQsFAQABCwA= +invalid invalid data.wast:454 AGFzbQEAAAAFAwEAAQsHAQABQQALAA== +invalid invalid data.wast:462 AGFzbQEAAAAFAwEAAQsHAQBBAAELAA== +invalid invalid data.wast:470 AGFzbQEAAAACCwEEdGVzdAFnA38BBQMBAAELBgEAIwALAA== +invalid invalid data.wast:479 AGFzbQEAAAAFAwEAAQsGAQAjAAsA +invalid invalid data.wast:487 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABQMBAAELBgEAIwELAA== +invalid invalid data.wast:496 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWkzMgN/AQUDAQABCwYBACMACwA= +valid valid elem.wast:4 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgmkAz0BAAAFcATSAAvSAAvQcAvSAQsBAAABAAQAAAEBAQAABXAE0gAL0gAL0HAL0gELAQAAAQAEAAABAQBBAAsABEEACwLSAAvQcAsAQQALAABBAAsCAAEAQQALAABBAAsCAAEAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAEQQALAtIAC9BwCwBBAAsABEEACwLSAAvQcAsAQQALAABBAAsCAAEAQQALAABBAAsCAAEAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAAAQQALAARBAAsC0gAL0HALAEEACwIAAABBAAsCAAADAAAHcATSAAvSAAvQcAvSAQsDAAADAAQAAAEBAwAAB3AE0gAL0gAL0HAL0gELAwAAAwAEAAABAQoHAgIACwIACw== +valid valid elem.wast:80 AGFzbQEAAAABBAFgAAADAwIAAAQFAXABAwMJDwEEQQALA9IAC9BwC9IBCwoHAgIACwIACw== +valid valid elem.wast:90 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEACwEACgQBAgAL +valid valid elem.wast:95 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBAAsBAAoEAQIACw== +valid valid elem.wast:101 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCR8FAEEACwEAAEEDCwEAAEEHCwEAAEEFCwEAAEEDCwEACgQBAgAL +valid valid elem.wast:110 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkfBQBBCQsBAABBAwsBAABBBwsBAABBAwsBAABBBQsBAAoEAQIACw== +valid valid elem.wast:120 AGFzbQEAAAABBAFgAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMCAQAEBQFwAOgHCQcBACMACwEACgQBAgAL +valid valid elem.wast:134 AGFzbQEAAAABBQFgAAF/AwUEAAAAAAQEAXAACgcTAgZjYWxsLTcAAgZjYWxsLTkAAwkNAgBBBwsBAABBCQsBAQodBAUAQcEACwUAQcIACwcAQQcRAAALBwBBCREAAAs= +valid valid elem.wast:153 AGFzbQEAAAABBQFgAAF/AwUEAAAAAAQEAXAACwcTAgZjYWxsLTcAAgZjYWxsLTkAAwkXAgRBBgsC0HAL0gALBEEJCwLSAQvQcAsKHQQFAEHBAAsFAEHCAAsHAEEHEQAACwcAQQkRAAAL +invalid valid elem.wast:171 AGFzbQEAAAABBAFgAAADAgEABAQBcAABBgYBfwBBAAsJBwEAIwALAQAKBAECAAs= +valid valid elem.wast:182 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEJCwEACgQBAgAL +valid valid elem.wast:187 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBCQsBAAoEAQIACw== +valid valid elem.wast:193 AGFzbQEAAAAEBAFwAAAJBgEAQQALAA== +valid valid elem.wast:197 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAACQYBAEEACwA= +valid valid elem.wast:202 AGFzbQEAAAAEBQFwAQAACQYBAEEACwA= +valid valid elem.wast:207 AGFzbQEAAAAEBAFwABQJBgEAQRQLAA== +valid valid elem.wast:212 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAAAwIBAAkHAQBBAAsBAAoEAQIACw== +valid valid elem.wast:218 AGFzbQEAAAABBAFgAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAZAMCAQAJBwEAQQALAQAKBAECAAs= +valid valid elem.wast:224 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAAAwIBAAkHAQBBAQsBAAoEAQIACw== +valid valid elem.wast:230 AGFzbQEAAAABBAFgAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAHgMCAQAJBwEAQQELAQAKBAECAAs= +valid valid elem.wast:239 AGFzbQEAAAABBAFgAAADAgEABAQBcAAACQcBAEEACwEACgQBAgAL +valid valid elem.wast:248 AGFzbQEAAAABBAFgAAADAgEABAUBcAEAAAkHAQBBAAsBAAoEAQIACw== +valid valid elem.wast:257 AGFzbQEAAAABBAFgAAADAgEABAUBcAEAAQkHAQBBAAsBAAoEAQIACw== +valid valid elem.wast:266 AGFzbQEAAAAEBAFwAAAJBgEAQQELAA== +valid valid elem.wast:273 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEEKCwEACgQBAgAL +valid valid elem.wast:281 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBCgsBAAoEAQIACw== +valid valid elem.wast:290 AGFzbQEAAAABBAFgAAADAgEABAUBcAEKFAkHAQBBCgsBAAoEAQIACw== +valid valid elem.wast:307 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEF/CwEACgQBAgAL +valid valid elem.wast:315 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBfwsBAAoEAQIACw== +valid valid elem.wast:324 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQcBAEF2CwEACgQBAgAL +valid valid elem.wast:332 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAKAwIBAAkHAQBBdgsBAAoEAQIACw== +valid valid elem.wast:342 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQRpbml0AAEJBwEAQQALAQAKEQICAAsMAEEAQQBBAfwMAAAL +valid valid elem.wast:352 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQRpbml0AAEJBQEDAAEAChECAgALDABBAEEAQQH8DAAACw== +invalid invalid elem.wast:365 AGFzbQEAAAABBAFgAAADAgEACQcBAEEACwEACgQBAgAL +invalid invalid elem.wast:375 AGFzbQEAAAAEBAFwAAEJBgEAQgALAA== +invalid invalid elem.wast:383 AGFzbQEAAAAEBAFwAAEJBgEA0HALAA== +invalid invalid elem.wast:391 AGFzbQEAAAAEBAFwAAEJBAEACwA= +invalid invalid elem.wast:399 AGFzbQEAAAAEBAFwAAEJCAEAQQBBAAsA +invalid invalid elem.wast:407 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABAQBcAABCQgBACMAIwALAA== +invalid invalid elem.wast:416 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABAQBcAABCQgBACMAQQALAA== +invalid invalid elem.wast:426 AGFzbQEAAAAEBAFwAAEJBwEAQQBoCwA= +invalid invalid elem.wast:434 AGFzbQEAAAAEBAFwAAEJBQEAAQsA +invalid invalid elem.wast:442 AGFzbQEAAAAEBAFwAAEJBwEAAUEACwA= +invalid invalid elem.wast:450 AGFzbQEAAAAEBAFwAAEJBwEAQQABCwA= +invalid invalid elem.wast:458 AGFzbQEAAAACCwEEdGVzdAFnA38BBAQBcAABCQYBACMACwA= +invalid invalid elem.wast:467 AGFzbQEAAAAEBAFwAAEJBgEAIwALAA== +invalid invalid elem.wast:475 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABAQBcAABCQYBACMBCwA= +invalid invalid elem.wast:484 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWkzMgN/AQQEAXAAAQkGAQAjAAsA +invalid invalid elem.wast:495 AGFzbQEAAAAEBAFwAAEJCQEEQQALAdBvCw== +invalid invalid elem.wast:503 AGFzbQEAAAAEBAFwAAEJCwEEQQALAdBw0HAL +invalid invalid elem.wast:511 AGFzbQEAAAAEBAFwAAEJCQEEQQALAUEACw== +invalid invalid elem.wast:527 AGFzbQEAAAABBQFgAAFwAwIBAAQEAXAAAQkJAQRBAAsBEAALCgYBBADQcAs= +valid valid elem.wast:537 AGFzbQEAAAABBQFgAAF/AwQDAAAABAQBcAAKBxQBEGNhbGwtb3ZlcndyaXR0ZW4AAgkNAgBBCQsBAABBCQsBAQoVAwUAQcEACwUAQcIACwcAQQkRAAAL +valid valid elem.wast:550 AGFzbQEAAAABBQFgAAF/AhQBCHNwZWN0ZXN0BXRhYmxlAXAACgMEAwAAAAccARhjYWxsLW92ZXJ3cml0dGVuLWVsZW1lbnQAAgkNAgBBCQsBAABBCQsBAQoVAwUAQcEACwUAQcIACwcAQQkRAAAL +valid valid elem.wast:565 AGFzbQEAAAABBQFgAAF/AwYFAAAAAAAEBAFwAAoHKwQMc2hhcmVkLXRhYmxlAQAGY2FsbC03AAIGY2FsbC04AAMGY2FsbC05AAQJDQIAQQgLAQAAQQkLAQEKJQUFAEHBAAsFAEHCAAsHAEEHEQAACwcAQQgRAAALBwBBCREAAAs= +valid valid elem.wast:589 AGFzbQEAAAABBQFgAAF/AhoBB21vZHVsZTEMc2hhcmVkLXRhYmxlAXAACgMDAgAACQ0CAEEHCwEAAEEICwEBCg0CBQBBwwALBQBBxAAL +valid valid elem.wast:602 AGFzbQEAAAABBQFgAAF/AhoBB21vZHVsZTEMc2hhcmVkLXRhYmxlAXAACgMDAgAACQ0CAEEICwEAAEEJCwEBCg0CBQBBxQALBQBBxgAL +invalid invalid elem.wast:618 AGFzbQEAAAABBAFgAAADAgEABAQBbwABCQcBAEEACwEACgQBAgAL +invalid invalid elem.wast:623 AGFzbQEAAAAEBAFwAAEJCwEGAEEAC28B0G8L +invalid invalid elem.wast:628 AGFzbQEAAAABBAFgAAADAwIAAAQEAW8AAQkFAQEAAQAKEQICAAsMAEEAQQBBAfwMAAAL +invalid invalid elem.wast:637 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQcBBW8B0G8LCg4BDABBAEEAQQH8DAAACw== +valid valid elem.wast:646 AGFzbQEAAAABCwJgAX8Bb2ACf28AAwMCAAEEBAFvAAIHFQMFdGFibGUBAANnZXQAAANzZXQAAQoRAgYAIAAlAAsIACAAIAEmAAs= +valid valid elem.wast:664 AGFzbQEAAAACFAEIZXhwb3J0ZXIFdGFibGUBbwACCQsBBgBBAAtvAdBvCw== +valid valid elem.wast:673 AGFzbQEAAAABBQFgAAF/AwIBAAYGAXAA0gALBwUBAWYDAAoGAQQAQSoL +valid valid elem.wast:682 AGFzbQEAAAABBQFgAAF/Ag4BB21vZHVsZTQBZgNwAAMCAQAEBAFwAAoHFgESY2FsbF9pbXBvcnRlZF9lbGVtAAAJCQEEQQALASMACwoJAQcAQQARAAAL +valid valid endianness.wast:1 AGFzbQEAAAABJAdgAn9/AGACf34AYAF/AX9gAX8BfmABfgF+YAF9AX1gAXwBfAMYFwAAAQICAwICAgQEBAQEBQYCAgQEBAUGBQMBAAEH4QERDGkzMl9sb2FkMTZfcwAGDGkzMl9sb2FkMTZfdQAHCGkzMl9sb2FkAAgMaTY0X2xvYWQxNl9zAAkMaTY0X2xvYWQxNl91AAoMaTY0X2xvYWQzMl9zAAsMaTY0X2xvYWQzMl91AAwIaTY0X2xvYWQADQhmMzJfbG9hZAAOCGY2NF9sb2FkAA8LaTMyX3N0b3JlMTYAEAlpMzJfc3RvcmUAEQtpNjRfc3RvcmUxNgASC2k2NF9zdG9yZTMyABMJaTY0X3N0b3JlABQJZjMyX3N0b3JlABUJZjY0X3N0b3JlABYK9gIXFgAgACABOgAAIABBAWogAUEIdjoAAAsUACAAIAEQACAAQQJqIAFBEHYQAAsWACAAIAGnEAEgAEEEaiABQiCIpxABCxMAIAAtAAAgAEEBai0AAEEIdHILEQAgABADIABBAmoQA0EQdHILEwAgABAErSAAQQRqEAStQiCGhAsNAEEAIAAQAEEALgEACw0AQQAgABAAQQAvAQALDQBBACAAEAFBACgCAAsOAEEAIACnEABBADIBAAsOAEEAIACnEABBADMBAAsOAEEAIACnEAFBADQCAAsOAEEAIACnEAFBADUCAAsNAEEAIAAQAkEAKQMACw4AQQAgALwQAUEAKgIACw4AQQAgAL0QAkEAKwMACw0AQQAgADsBAEEAEAMLDQBBACAANgIAQQAQBAsOAEEAIAA9AQBBABADrQsOAEEAIAA+AgBBABAErQsNAEEAIAA3AwBBABAFCw4AQQAgADgCAEEAEAS+Cw4AQQAgADkDAEEAEAW/Cw== +valid valid exports.wast:3 AGFzbQEAAAABBAFgAAADAgEABwUBAWEAAAoEAQIACw== +valid valid exports.wast:4 AGFzbQEAAAABBAFgAAADAgEABwkCAWEAAAFiAAAKBAECAAs= +valid valid exports.wast:5 AGFzbQEAAAABBAFgAAADAwIAAAcJAgFhAAABYgABCgcCAgALAgAL +valid valid exports.wast:8 AGFzbQEAAAABBAFgAAADAgEABw0DAWEAAAFiAAABYwAACgQBAgAL +valid valid exports.wast:9 AGFzbQEAAAABBQFgAX8AAwIBAAcJAgFhAAABYgAACgQBAgAL +valid valid exports.wast:16 AGFzbQEAAAABBgFgAX8BfwMCAQAHBQEBZQAACgoBCAAgAEEBag8L +valid valid exports.wast:28 AGFzbQEAAAABBQFgAAF/AwIBAAcNAwFhAAABYgAAAWMAAAoGAQQAQSoL +invalid invalid exports.wast:39 AGFzbQEAAAAHBQEBYQAA +invalid invalid exports.wast:43 AGFzbQEAAAABBAFgAAADAgEABwUBAWEAAQoEAQIACw== +invalid invalid exports.wast:47 AGFzbQEAAAABBQFgAX8AAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAABwUBAWEAAQ== +invalid invalid exports.wast:51 AGFzbQEAAAABBAFgAAADAgEABwkCAWEAAAFhAAAKBAECAAs= +invalid invalid exports.wast:55 AGFzbQEAAAABBAFgAAADAwIAAAcJAgFhAAABYQABCgcCAgALAgAL +invalid invalid exports.wast:59 AGFzbQEAAAABBAFgAAADAgEABgYBfwBBAAsHCQIBYQAAAWEDAAoEAQIACw== +invalid invalid exports.wast:63 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABwkCAWEAAAFhAQAKBAECAAs= +invalid invalid exports.wast:67 AGFzbQEAAAABBAFgAAADAgEABQMBAAAHCQIBYQAAAWECAAoEAQIACw== +valid valid exports.wast:74 AGFzbQEAAAAGBgF/AEEACwcFAQFhAwA= +valid valid exports.wast:75 AGFzbQEAAAAGBgF/AEEACwcJAgFhAwABYgMA +valid valid exports.wast:76 AGFzbQEAAAAGCwJ/AEEAC38AQQALBwkCAWEDAAFiAwE= +valid valid exports.wast:85 AGFzbQEAAAAGBgF/AEEqCwcFAQFlAwA= +invalid invalid exports.wast:96 AGFzbQEAAAAHBQEBYQMA +invalid invalid exports.wast:100 AGFzbQEAAAAGBgF/AEEACwcFAQFhAwE= +invalid invalid exports.wast:104 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAcFAQFhAwE= +invalid invalid exports.wast:108 AGFzbQEAAAAGBgF/AEEACwcJAgFhAwABYQMA +invalid invalid exports.wast:112 AGFzbQEAAAAGCwJ/AEEAC38AQQALBwkCAWEDAAFhAwE= +invalid invalid exports.wast:116 AGFzbQEAAAABBAFgAAADAgEABgYBfwBBAAsHCQIBYQMAAWEAAAoEAQIACw== +invalid invalid exports.wast:120 AGFzbQEAAAAEBAFwAAAGBgF/AEEACwcJAgFhAwABYQEA +invalid invalid exports.wast:124 AGFzbQEAAAAFAwEAAAYGAX8AQQALBwkCAWEDAAFhAgA= +valid valid exports.wast:131 AGFzbQEAAAAEBAFwAAAHBQEBYQEA +valid valid exports.wast:132 AGFzbQEAAAAEBAFwAAAHCQIBYQEAAWIBAA== +valid valid exports.wast:133 AGFzbQEAAAAEBwJwAABwAAAHCQIBYQEAAWIBAQ== +valid valid exports.wast:136 AGFzbQEAAAAEBQFwAQABBwUBAWEBAA== +invalid invalid exports.wast:151 AGFzbQEAAAAHBQEBYQEA +invalid invalid exports.wast:155 AGFzbQEAAAAEBAFwAAAHBQEBYQEB +invalid invalid exports.wast:159 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKFAcFAQFhAQE= +invalid invalid exports.wast:163 AGFzbQEAAAAEBAFwAAAHCQIBYQEAAWEBAA== +invalid invalid exports.wast:167 AGFzbQEAAAAEBwJwAABwAAAHCQIBYQEAAWEBAQ== +invalid invalid exports.wast:171 AGFzbQEAAAABBAFgAAADAgEABAQBcAAABwkCAWEBAAFhAAAKBAECAAs= +invalid invalid exports.wast:175 AGFzbQEAAAAEBAFwAAAGBgF/AEEACwcJAgFhAQABYQMA +invalid invalid exports.wast:179 AGFzbQEAAAAEBAFwAAAFAwEAAAcJAgFhAQABYQIA +valid valid exports.wast:186 AGFzbQEAAAAFAwEAAAcFAQFhAgA= +valid valid exports.wast:187 AGFzbQEAAAAFAwEAAAcJAgFhAgABYgIA +valid valid exports.wast:192 AGFzbQEAAAAFBAEBAAEHBQEBYQIA +invalid invalid exports.wast:207 AGFzbQEAAAAHBQEBYQIA +invalid invalid exports.wast:211 AGFzbQEAAAAFAwEAAAcFAQFhAgE= +invalid invalid exports.wast:215 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAgcFAQFhAgE= +invalid invalid exports.wast:219 AGFzbQEAAAAFAwEAAAcJAgFhAgABYQIA +invalid invalid exports.wast:228 AGFzbQEAAAABBAFgAAADAgEABQMBAAAHCQIBYQIAAWEAAAoEAQIACw== +invalid invalid exports.wast:232 AGFzbQEAAAAFAwEAAAYGAX8AQQALBwkCAWECAAFhAwA= +invalid invalid exports.wast:236 AGFzbQEAAAAEBAFwAAAFAwEAAAcJAgFhAgABYQEA +valid valid f32.wast:5 AGFzbQEAAAABDAJgAn19AX1gAX0BfQMMCwAAAAABAAABAQEBB00LA2FkZAAAA3N1YgABA211bAACA2RpdgADBHNxcnQABANtaW4ABQNtYXgABgRjZWlsAAcFZmxvb3IACAV0cnVuYwAJB25lYXJlc3QACgpPCwcAIAAgAZILBwAgACABkwsHACAAIAGUCwcAIAAgAZULBQAgAJELBwAgACABlgsHACAAIAGXCwUAIACNCwUAIACOCwUAIACPCwUAIACQCw== +invalid invalid f32.wast:2523 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACSCw== +invalid invalid f32.wast:2524 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACVCw== +invalid invalid f32.wast:2525 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACXCw== +invalid invalid f32.wast:2526 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACWCw== +invalid invalid f32.wast:2527 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACUCw== +invalid invalid f32.wast:2528 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACTCw== +invalid invalid f32.wast:2529 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCNCw== +invalid invalid f32.wast:2530 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCOCw== +invalid invalid f32.wast:2531 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCQCw== +invalid invalid f32.wast:2532 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCRCw== +invalid invalid f32.wast:2533 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCPCw== +valid valid f32_bitwise.wast:4 AGFzbQEAAAABDAJgAX0BfWACfX0BfQMEAwAAAQcYAwNhYnMAAANuZWcAAQhjb3B5c2lnbgACChUDBQAgAIsLBQAgAIwLBwAgACABmAs= +invalid invalid f32_bitwise.wast:374 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAACYCw== +invalid invalid f32_bitwise.wast:375 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCLCw== +invalid invalid f32_bitwise.wast:376 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAQgCMCw== +valid valid f32_cmp.wast:4 AGFzbQEAAAABBwFgAn19AX8DBwYAAAAAAAAHHwYCZXEAAAJuZQABAmx0AAICbGUAAwJndAAEAmdlAAUKMQYHACAAIAFbCwcAIAAgAVwLBwAgACABXQsHACAAIAFfCwcAIAAgAV4LBwAgACABYAs= +invalid invalid f32_cmp.wast:2417 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABbCw== +invalid invalid f32_cmp.wast:2418 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABgCw== +invalid invalid f32_cmp.wast:2419 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABeCw== +invalid invalid f32_cmp.wast:2420 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABfCw== +invalid invalid f32_cmp.wast:2421 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABdCw== +invalid invalid f32_cmp.wast:2422 AGFzbQEAAAABBQFgAAF9AwIBAAoQAQ4AQgBEAAAAAAAAAABcCw== +valid valid f64.wast:5 AGFzbQEAAAABDAJgAnx8AXxgAXwBfAMMCwAAAAABAAABAQEBB00LA2FkZAAAA3N1YgABA211bAACA2RpdgADBHNxcnQABANtaW4ABQNtYXgABgRjZWlsAAcFZmxvb3IACAV0cnVuYwAJB25lYXJlc3QACgpPCwcAIAAgAaALBwAgACABoQsHACAAIAGiCwcAIAAgAaMLBQAgAJ8LBwAgACABpAsHACAAIAGlCwUAIACbCwUAIACcCwUAIACdCwUAIACeCw== +invalid invalid f64.wast:2523 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKAL +invalid invalid f64.wast:2524 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKML +invalid invalid f64.wast:2525 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKUL +invalid invalid f64.wast:2526 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKQL +invalid invalid f64.wast:2527 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKIL +invalid invalid f64.wast:2528 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKEL +invalid invalid f64.wast:2529 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCbCw== +invalid invalid f64.wast:2530 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCcCw== +invalid invalid f64.wast:2531 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCeCw== +invalid invalid f64.wast:2532 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCfCw== +invalid invalid f64.wast:2533 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCdCw== +valid valid f64_bitwise.wast:4 AGFzbQEAAAABDAJgAXwBfGACfHwBfAMEAwAAAQcYAwNhYnMAAANuZWcAAQhjb3B5c2lnbgACChUDBQAgAJkLBQAgAJoLBwAgACABpgs= +invalid invalid f64_bitwise.wast:374 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAKYL +invalid invalid f64_bitwise.wast:375 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCZCw== +invalid invalid f64_bitwise.wast:376 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgCaCw== +valid valid f64_cmp.wast:4 AGFzbQEAAAABBwFgAnx8AX8DBwYAAAAAAAAHHwYCZXEAAAJuZQABAmx0AAICbGUAAwJndAAEAmdlAAUKMQYHACAAIAFhCwcAIAAgAWILBwAgACABYwsHACAAIAFlCwcAIAAgAWQLBwAgACABZgs= +invalid invalid f64_cmp.wast:2417 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGEL +invalid invalid f64_cmp.wast:2418 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGYL +invalid invalid f64_cmp.wast:2419 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGQL +invalid invalid f64_cmp.wast:2420 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGUL +invalid invalid f64_cmp.wast:2421 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGML +invalid invalid f64_cmp.wast:2422 AGFzbQEAAAABBQFgAAF8AwIBAAoMAQoAQgBDAAAAAGIL +valid valid fac.wast:1 AGFzbQEAAAABGgRgAX4BfmABfgJ+fmACfn4Dfn5+YAJ+fgF+AwkIAAAAAAABAgAHSwYHZmFjLXJlYwAADWZhYy1yZWMtbmFtZWQAAQhmYWMtaXRlcgACDmZhYy1pdGVyLW5hbWVkAAMHZmFjLW9wdAAEB2ZhYy1zc2EABwrrAQgXACAAQgBRBH5CAQUgACAAQgF9EAB+CwsXACAAQgBRBH5CAQUgACAAQgF9EAF+CwsvAQJ+IAAhAUIBIQICQANAIAFCAFEEQAwCBSABIAJ+IQIgAUIBfSEBCwwACwsgAgsvAQJ+IAAhAUIBIQICQANAIAFCAFEEQAwCBSABIAJ+IQIgAUIBfSEBCwwACwsgAgssAQF+QgEhAQJAIABCAlMNAANAIAEgAH4hASAAQn98IQAgAEIBVQ0ACwsgAQsGACAAIAALCAAgACABIAALHABCASAAAwMQBhAGfhAGQgF9EAVCAFYNABoPCws= +valid valid float_exprs.wast:6 AGFzbQEAAAABCAFgA3x8fAF8AwIBAAcWARJmNjQubm9fY29udHJhY3Rpb24AAAoMAQoAIAAgAaIgAqAL +valid valid float_exprs.wast:19 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBxsCCmYzMi5ub19mbWEAAApmNjQubm9fZm1hAAEKFwIKACAAIAGUIAKSCwoAIAAgAaIgAqAL +valid valid float_exprs.wast:40 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfYWRkX3plcm8AABRmNjQubm9fZm9sZF9hZGRfemVybwABChsCCgAgAEMAAAAAkgsOACAARAAAAAAAAAAAoAs= +valid valid float_exprs.wast:54 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfemVyb19zdWIAABRmNjQubm9fZm9sZF96ZXJvX3N1YgABChsCCgBDAAAAACAAkwsOAEQAAAAAAAAAACAAoQs= +valid valid float_exprs.wast:68 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfc3ViX3plcm8AABRmNjQubm9fZm9sZF9zdWJfemVybwABChsCCgAgAEMAAAAAkwsOACAARAAAAAAAAAAAoQs= +valid valid float_exprs.wast:80 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbXVsX3plcm8AABRmNjQubm9fZm9sZF9tdWxfemVybwABChsCCgAgAEMAAAAAlAsOACAARAAAAAAAAAAAogs= +valid valid float_exprs.wast:99 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfbXVsX29uZQAAE2Y2NC5ub19mb2xkX211bF9vbmUAAQobAgoAIABDAACAP5QLDgAgAEQAAAAAAADwP6IL +valid valid float_exprs.wast:111 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfemVyb19kaXYAABRmNjQubm9fZm9sZF96ZXJvX2RpdgABChsCCgBDAAAAACAAlQsOAEQAAAAAAAAAACAAows= +valid valid float_exprs.wast:129 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfZGl2X29uZQAAE2Y2NC5ub19mb2xkX2Rpdl9vbmUAAQobAgoAIABDAACAP5ULDgAgAEQAAAAAAADwP6ML +valid valid float_exprs.wast:141 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X25lZzEAABRmNjQubm9fZm9sZF9kaXZfbmVnMQABChsCCgAgAEMAAIC/lQsOACAARAAAAAAAAPC/ows= +valid valid float_exprs.wast:153 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbmVnMF9zdWIAABRmNjQubm9fZm9sZF9uZWcwX3N1YgABChsCCgBDAAAAgCAAkwsOAEQAAAAAAAAAgCAAoQs= +valid valid float_exprs.wast:165 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbmVnMV9tdWwAABRmNjQubm9fZm9sZF9uZWcxX211bAABChsCCgBDAACAvyAAlAsOAEQAAAAAAADwvyAAogs= +valid valid float_exprs.wast:177 AGFzbQEAAAABCwJgAX0Bf2ABfAF/AwMCAAEHLQITZjMyLm5vX2ZvbGRfZXFfc2VsZgAAE2Y2NC5ub19mb2xkX2VxX3NlbGYAAQoRAgcAIAAgAFsLBwAgACAAYQs= +valid valid float_exprs.wast:189 AGFzbQEAAAABCwJgAX0Bf2ABfAF/AwMCAAEHLQITZjMyLm5vX2ZvbGRfbmVfc2VsZgAAE2Y2NC5ub19mb2xkX25lX3NlbGYAAQoRAgcAIAAgAFwLBwAgACAAYgs= +valid valid float_exprs.wast:201 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfc3ViX3NlbGYAABRmNjQubm9fZm9sZF9zdWJfc2VsZgABChECBwAgACAAkwsHACAAIAChCw== +valid valid float_exprs.wast:215 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X3NlbGYAABRmNjQubm9fZm9sZF9kaXZfc2VsZgABChECBwAgACAAlQsHACAAIACjCw== +valid valid float_exprs.wast:233 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHKQIRZjMyLm5vX2ZvbGRfZGl2XzMAABFmNjQubm9fZm9sZF9kaXZfMwABChsCCgAgAEMAAEBAlQsOACAARAAAAAAAAAhAows= +valid valid float_exprs.wast:253 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABByECDWYzMi5ub19mYWN0b3IAAA1mNjQubm9fZmFjdG9yAAEKHQINACAAIAKUIAEgApSSCw0AIAAgAqIgASACoqAL +valid valid float_exprs.wast:273 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBykCEWYzMi5ub19kaXN0cmlidXRlAAARZjY0Lm5vX2Rpc3RyaWJ1dGUAAQoXAgoAIAAgAZIgApQLCgAgACABoCACogs= +valid valid float_exprs.wast:293 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBzMCFmYzMi5ub19yZWdyb3VwX2Rpdl9tdWwAABZmNjQubm9fcmVncm91cF9kaXZfbXVsAAEKFwIKACAAIAEgApWUCwoAIAAgASACo6IL +valid valid float_exprs.wast:313 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBzMCFmYzMi5ub19yZWdyb3VwX211bF9kaXYAABZmNjQubm9fcmVncm91cF9tdWxfZGl2AAEKFwIKACAAIAGUIAKVCwoAIAAgAaIgAqML +valid valid float_exprs.wast:333 AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHMwIWZjMyLm5vX3JlYXNzb2NpYXRlX2FkZAAAFmY2NC5ub19yZWFzc29jaWF0ZV9hZGQAAQodAg0AIAAgAZIgApIgA5ILDQAgACABoCACoCADoAs= +valid valid float_exprs.wast:353 AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHMwIWZjMyLm5vX3JlYXNzb2NpYXRlX211bAAAFmY2NC5ub19yZWFzc29jaWF0ZV9tdWwAAQodAg0AIAAgAZQgApQgA5QLDQAgACABoiACoiADogs= +valid valid float_exprs.wast:373 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHKQIRZjMyLm5vX2ZvbGRfZGl2XzAAABFmNjQubm9fZm9sZF9kaXZfMAABChsCCgAgAEMAAAAAlQsOACAARAAAAAAAAAAAows= +valid valid float_exprs.wast:399 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfZGl2X25lZzAAABRmNjQubm9fZm9sZF9kaXZfbmVnMAABChsCCgAgAEMAAACAlQsOACAARAAAAAAAAACAows= +valid valid float_exprs.wast:425 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcvAhRmMzIubm9fZm9sZF90b19oeXBvdAAAFGY2NC5ub19mb2xkX3RvX2h5cG90AAEKHwIOACAAIACUIAEgAZSSkQsOACAAIACiIAEgAaKgnws= +valid valid float_exprs.wast:447 AGFzbQEAAAABBgFgAX0BfQMCAQAHIQEdZjMyLm5vX2FwcHJveGltYXRlX3JlY2lwcm9jYWwAAAoMAQoAQwAAgD8gAJUL +valid valid float_exprs.wast:460 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHRAIiZjMyLm5vX2FwcHJveGltYXRlX3JlY2lwcm9jYWxfc3FydAAAG2Y2NC5ub19mdXNlX3JlY2lwcm9jYWxfc3FydAABCh0CCwBDAACAPyAAkZULDwBEAAAAAAAA8D8gAJ+jCw== +valid valid float_exprs.wast:481 AGFzbQEAAAABBgFgAX0BfQMCAQAHJgEiZjMyLm5vX2FwcHJveGltYXRlX3NxcnRfcmVjaXByb2NhbAAACg0BCwBDAACAPyAAlZEL +valid valid float_exprs.wast:494 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdRBBFpMzIubm9fZm9sZF9mMzJfcwAAEWkzMi5ub19mb2xkX2YzMl91AAERaTY0Lm5vX2ZvbGRfZjY0X3MAAhFpNjQubm9fZm9sZF9mNjRfdQADCh0EBgAgALKoCwYAIACzqQsGACAAubALBgAgALqxCw== +valid valid float_exprs.wast:523 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9hZGRfc3ViAAATZjY0Lm5vX2ZvbGRfYWRkX3N1YgABChcCCgAgACABkiABkwsKACAAIAGgIAGhCw== +valid valid float_exprs.wast:544 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9zdWJfYWRkAAATZjY0Lm5vX2ZvbGRfc3ViX2FkZAABChcCCgAgACABkyABkgsKACAAIAGhIAGgCw== +valid valid float_exprs.wast:565 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9tdWxfZGl2AAATZjY0Lm5vX2ZvbGRfbXVsX2RpdgABChcCCgAgACABlCABlQsKACAAIAGiIAGjCw== +valid valid float_exprs.wast:586 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9kaXZfbXVsAAATZjY0Lm5vX2ZvbGRfZGl2X211bAABChcCCgAgACABlSABlAsKACAAIAGjIAGiCw== +valid valid float_exprs.wast:607 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHMQIVZjMyLm5vX2ZvbGRfZGl2Ml9tdWwyAAAVZjY0Lm5vX2ZvbGRfZGl2Ml9tdWwyAAEKKwIQACAAQwAAAECVQwAAAECUCxgAIABEAAAAAAAAAECjRAAAAAAAAABAogs= +valid valid float_exprs.wast:619 AGFzbQEAAAABBgFgAXwBfAMCAQAHGgEWbm9fZm9sZF9kZW1vdGVfcHJvbW90ZQAACggBBgAgALa7Cw== +valid valid float_exprs.wast:633 AGFzbQEAAAABBgFgAX0BfQMCAQAHGgEWbm9fZm9sZF9wcm9tb3RlX2RlbW90ZQAACggBBgAgALu2Cw== +valid valid float_exprs.wast:655 AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfYWRkAAAcbm9fZGVtb3RlX21peGVkX2FkZF9jb21tdXRlZAABChUCCQAgACABu6C2CwkAIAC7IAGgtgs= +valid valid float_exprs.wast:677 AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfc3ViAAAcbm9fZGVtb3RlX21peGVkX3N1Yl9jb21tdXRlZAABChUCCQAgACABu6G2CwkAIAC7IAGhtgs= +valid valid float_exprs.wast:699 AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfbXVsAAAcbm9fZGVtb3RlX21peGVkX211bF9jb21tdXRlZAABChUCCQAgACABu6K2CwkAIAC7IAGitgs= +valid valid float_exprs.wast:721 AGFzbQEAAAABDQJgAnx9AX1gAn18AX0DAwIAAQc2AhNub19kZW1vdGVfbWl4ZWRfZGl2AAAcbm9fZGVtb3RlX21peGVkX2Rpdl9jb21tdXRlZAABChUCCQAgACABu6O2CwkAIAC7IAGjtgs= +valid valid float_exprs.wast:742 AGFzbQEAAAABCwJgAX0BfWABfAF8AxEQAAAAAAEBAQEAAAAAAQEBAQfBBBAhZjMyLmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAAhZjMyLmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAEhZjMyLmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAIhZjMyLmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAMhZjY0LmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAQhZjY0LmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAUhZjY0LmkzMi5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAYhZjY0LmkzMi5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAchZjMyLmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAghZjMyLmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAAkhZjMyLmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF91AAohZjMyLmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF91AAshZjY0Lmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF9zAAwhZjY0Lmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF9zAA0hZjY0Lmk2NC5ub19mb2xkX3RydW5jX3NfY29udmVydF91AA4hZjY0Lmk2NC5ub19mb2xkX3RydW5jX3VfY29udmVydF91AA8KcRAGACAAqLILBgAgAKmyCwYAIACoswsGACAAqbMLBgAgAKq3CwYAIACrtwsGACAAqrgLBgAgAKu4CwYAIACutAsGACAAr7QLBgAgAK61CwYAIACvtQsGACAAsLkLBgAgALG5CwYAIACwugsGACAAsboL +valid valid float_exprs.wast:817 AGFzbQEAAAABCwJgAn99AGABfwF9AwQDAAABBQQBAQEBBxYDBGluaXQAAANydW4AAQVjaGVjawACCjkDCQAgACABOAIACyUBAX8CQANAIAIgAioCACABlTgCACACQQRqIQIgAiAASQ0ACwsLBwAgACoCAAs= +valid valid float_exprs.wast:852 AGFzbQEAAAABCwJgAn98AGABfwF8AwQDAAABBQQBAQEBBxYDBGluaXQAAANydW4AAQVjaGVjawACCjkDCQAgACABOQMACyUBAX8CQANAIAIgAisDACABozkDACACQQhqIQIgAiAASQ0ACwsLBwAgACsDAAs= +valid valid float_exprs.wast:889 AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQdRCAdmMzIudWx0AAAHZjMyLnVsZQABB2YzMi51Z3QAAgdmMzIudWdlAAMHZjY0LnVsdAAEB2Y2NC51bGUABQdmNjQudWd0AAYHZjY0LnVnZQAHCkkICAAgACABYEULCAAgACABXkULCAAgACABX0ULCAAgACABXUULCAAgACABZkULCAAgACABZEULCAAgACABZUULCAAgACABY0UL +valid valid float_exprs.wast:936 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDCQgAAAAAAQEBAQfBAQgVZjMyLm5vX2ZvbGRfbHRfc2VsZWN0AAAVZjMyLm5vX2ZvbGRfbGVfc2VsZWN0AAEVZjMyLm5vX2ZvbGRfZ3Rfc2VsZWN0AAIVZjMyLm5vX2ZvbGRfZ2Vfc2VsZWN0AAMVZjY0Lm5vX2ZvbGRfbHRfc2VsZWN0AAQVZjY0Lm5vX2ZvbGRfbGVfc2VsZWN0AAUVZjY0Lm5vX2ZvbGRfZ3Rfc2VsZWN0AAYVZjY0Lm5vX2ZvbGRfZ2Vfc2VsZWN0AAcKaQgMACAAIAEgACABXRsLDAAgACABIAAgAV8bCwwAIAAgASAAIAFeGwsMACAAIAEgACABYBsLDAAgACABIAAgAWMbCwwAIAAgASAAIAFlGwsMACAAIAEgACABZBsLDAAgACABIAAgAWYbCw== +valid valid float_exprs.wast:983 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDCQgAAAAAAQEBAQehAQgRZjMyLm5vX2ZvbGRfbHRfaWYAABFmMzIubm9fZm9sZF9sZV9pZgABEWYzMi5ub19mb2xkX2d0X2lmAAIRZjMyLm5vX2ZvbGRfZ2VfaWYAAxFmNjQubm9fZm9sZF9sdF9pZgAEEWY2NC5ub19mb2xkX2xlX2lmAAURZjY0Lm5vX2ZvbGRfZ3RfaWYABhFmNjQubm9fZm9sZF9nZV9pZgAHCoEBCA8AIAAgAV0EfSAABSABCwsPACAAIAFfBH0gAAUgAQsLDwAgACABXgR9IAAFIAELCw8AIAAgAWAEfSAABSABCwsPACAAIAFjBHwgAAUgAQsLDwAgACABZQR8IAAFIAELCw8AIAAgAWQEfCAABSABCwsPACAAIAFmBHwgAAUgAQsL +valid valid float_exprs.wast:1062 AGFzbQEAAAABCwJgAX0BfWABfAF8AwkIAAAAAAEBAQEH+QEIHGYzMi5ub19mb2xkX2x0X3NlbGVjdF90b19hYnMAABxmMzIubm9fZm9sZF9sZV9zZWxlY3RfdG9fYWJzAAEcZjMyLm5vX2ZvbGRfZ3Rfc2VsZWN0X3RvX2FicwACHGYzMi5ub19mb2xkX2dlX3NlbGVjdF90b19hYnMAAxxmNjQubm9fZm9sZF9sdF9zZWxlY3RfdG9fYWJzAAQcZjY0Lm5vX2ZvbGRfbGVfc2VsZWN0X3RvX2FicwAFHGY2NC5ub19mb2xkX2d0X3NlbGVjdF90b19hYnMABhxmNjQubm9fZm9sZF9nZV9zZWxlY3RfdG9fYWJzAAcKmQEIEAAgAIwgACAAQwAAAABdGwsQACAAjCAAIABDAAAAgF8bCxAAIAAgAIwgAEMAAACAXhsLEAAgACAAjCAAQwAAAABgGwsUACAAmiAAIABEAAAAAAAAAABjGwsUACAAmiAAIABEAAAAAAAAAIBlGwsUACAAIACaIABEAAAAAAAAAIBkGwsUACAAIACaIABEAAAAAAAAAABmGws= +valid valid float_exprs.wast:1109 AGFzbQEAAAABCwJgAX0BfWABfAF8AwkIAAAAAAEBAQEH2QEIGGYzMi5ub19mb2xkX2x0X2lmX3RvX2FicwAAGGYzMi5ub19mb2xkX2xlX2lmX3RvX2FicwABGGYzMi5ub19mb2xkX2d0X2lmX3RvX2FicwACGGYzMi5ub19mb2xkX2dlX2lmX3RvX2FicwADGGY2NC5ub19mb2xkX2x0X2lmX3RvX2FicwAEGGY2NC5ub19mb2xkX2xlX2lmX3RvX2FicwAFGGY2NC5ub19mb2xkX2d0X2lmX3RvX2FicwAGGGY2NC5ub19mb2xkX2dlX2lmX3RvX2FicwAHCrEBCBMAIABDAAAAAF0EfSAAjAUgAAsLEwAgAEMAAACAXwR9IACMBSAACwsTACAAQwAAAIBeBH0gAAUgAIwLCxMAIABDAAAAAGAEfSAABSAAjAsLFwAgAEQAAAAAAAAAAGMEfCAAmgUgAAsLFwAgAEQAAAAAAAAAgGUEfCAAmgUgAAsLFwAgAEQAAAAAAAAAgGQEfCAABSAAmgsLFwAgAEQAAAAAAAAAAGYEfCAABSAAmgsL +valid valid float_exprs.wast:1189 AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBzcCGGYzMi5pbmNvcnJlY3RfY29ycmVjdGlvbgAAGGY2NC5pbmNvcnJlY3RfY29ycmVjdGlvbgABCkUCGQBDvp+qP0PNzJw/kkO+n6o/k0PNzJw/kwspAESHFtnO91P1P0SamZmZmZnzP6BEhxbZzvdT9T+hRJqZmZmZmfM/oQs= +valid valid float_exprs.wast:1204 AGFzbQEAAAABBQFgAAF9AwIBAAcNAQljYWxjdWxhdGUAAApKAUgBBX1DAEAcQyEAQ1VVUEMhAUMVx+M/IQIgAYwgAJQgACAClCABk5UhAyABjCAAlCAAIAKUIAGTlSEEAkAgAyAEWw0AAAsgBAs= +valid valid float_exprs.wast:1223 AGFzbQEAAAABBQFgAAF8AwIBAAcNAQljYWxjdWxhdGUAAApWAVQBBXxEAAAAAACIY0AhAERLBquqqgpqQCEBRJbQ46riePw/IQIgAZogAKIgACACoiABoaMhAyABmiAAoiAAIAKiIAGhoyEEAkAgAyAEYQ0AAAsgBAs= +valid valid float_exprs.wast:1245 AGFzbQEAAAABBgFgAX0BfQMCAQAHEAEMbGx2bV9wcjI2NzQ2AAAKEgEQAEMAAAAAQwAAAIAgAJOTCw== +valid valid float_exprs.wast:1256 AGFzbQEAAAABBgFgAX8BfQMCAQAHEAEMbGx2bV9wcjI3MTUzAAAKFAESACAAQf////8AcbJDAAAAy5IL +valid valid float_exprs.wast:1267 AGFzbQEAAAABBwFgAn9/AX0DAgEABxABDGxsdm1fcHIyNzAzNgAAChcBFQAgAEHL/4d0crIgAUGAgJAHcbKSCw== +valid valid float_exprs.wast:1284 AGFzbQEAAAABFwNgBHx8fHwBfGADfHx8AXxgA319fQF9AwQDAAECByIDCHRoZXBhc3QwAAAIdGhlcGFzdDEAAQh0aGVwYXN0MgACCiUDDQAgACABoiACIAOiowsKACAAIAGiIAKhCwoAIAAgAZQgApQL +valid valid float_exprs.wast:1305 AGFzbQEAAAABBgFgAX0BfQMCAQAHCwEHaW52ZXJzZQAACgwBCgBDAACAPyAAlQs= +valid valid float_exprs.wast:1316 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHJwIQZjMyX3NxcnRfbWludXNfMgAAEGY2NF9zcXJ0X21pbnVzXzIAAQodAgsAIACRQwAAAECTCw8AIACfRAAAAAAAAABAoQs= +valid valid float_exprs.wast:1331 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2ZvbGRfcmVjaXBfcmVjaXAAABdmNjQubm9fZm9sZF9yZWNpcF9yZWNpcAABCisCEABDAACAP0MAAIA/IACVlQsYAEQAAAAAAADwP0QAAAAAAADwPyAAo6ML +valid valid float_exprs.wast:1363 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc7AhpmMzIubm9fYWxnZWJyYWljX2ZhY3RvcmluZwAAGmY2NC5ub19hbGdlYnJhaWNfZmFjdG9yaW5nAAEKHQINACAAIAGSIAAgAZOUCw0AIAAgAaAgACABoaIL +valid valid float_exprs.wast:1387 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc7AhpmMzIubm9fYWxnZWJyYWljX2ZhY3RvcmluZwAAGmY2NC5ub19hbGdlYnJhaWNfZmFjdG9yaW5nAAEKHQINACAAIACUIAEgAZSTCw0AIAAgAKIgASABoqEL +valid valid float_exprs.wast:1412 AGFzbQEAAAABDAJgA39/fwBgAX8BfQMDAgABBQQBAQEBByACEWYzMi5zaW1wbGVfeDRfc3VtAAAIZjMyLmxvYWQAAQpuAmQBCH0gACoCACEDIAAqAgQhBCAAKgIIIQUgACoCDCEGIAEqAgAhByABKgIEIQggASoCCCEJIAEqAgwhCiACIAMgB5I4AgAgAiAEIAiSOAIEIAIgBSAJkjgCCCACIAYgCpI4AgwLBwAgACoCAAsLNgEAQQALMAEAAAABAACAAQAAAAEAAIABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +valid valid float_exprs.wast:1451 AGFzbQEAAAABDAJgA39/fwBgAX8BfAMDAgABBQQBAQEBByACEWY2NC5zaW1wbGVfeDRfc3VtAAAIZjY0LmxvYWQAAQpuAmQBCHwgACsDACEDIAArAwghBCAAKwMQIQUgACsDGCEGIAErAwAhByABKwMIIQggASsDECEJIAErAxghCiACIAMgB6A5AwAgAiAEIAigOQMIIAIgBSAJoDkDECACIAYgCqA5AxgLBwAgACsDAAsLZgEAQQALYAEAAAAAAAAAAQAAAAAAAIABAAAAAAAAAAEAAAAAAACAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +valid valid float_exprs.wast:1493 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 +valid valid float_exprs.wast:1587 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 +valid valid float_exprs.wast:1640 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9uZWdfc3ViAAATZjY0Lm5vX2ZvbGRfbmVnX3N1YgABChMCCAAgACABk4wLCAAgACABoZoL +valid valid float_exprs.wast:1660 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQctAhNmMzIubm9fZm9sZF9uZWdfYWRkAAATZjY0Lm5vX2ZvbGRfbmVnX2FkZAABChMCCAAgACABkowLCAAgACABoJoL +valid valid float_exprs.wast:1680 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc1AhdmMzIubm9fZm9sZF9hZGRfbmVnX25lZwAAF2Y2NC5ub19mb2xkX2FkZF9uZWdfbmVnAAEKFQIJACAAjCABjJILCQAgAJogAZqgCw== +valid valid float_exprs.wast:1700 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHLQITZjMyLm5vX2ZvbGRfYWRkX25lZwAAE2Y2NC5ub19mb2xkX2FkZF9uZWcAAQoTAggAIACMIACSCwgAIACaIACgCw== +valid valid float_exprs.wast:1720 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHMwIWZjMyLm5vX2ZvbGRfNnhfdmlhX2FkZAAAFmY2NC5ub19mb2xkXzZ4X3ZpYV9hZGQAAQopAhMAIAAgAJIgAJIgAJIgAJIgAJILEwAgACAAoCAAoCAAoCAAoCAAoAs= +valid valid float_exprs.wast:1749 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBy0CE2YzMi5ub19mb2xkX2Rpdl9kaXYAABNmNjQubm9fZm9sZF9kaXZfZGl2AAEKFwIKACAAIAGVIAKVCwoAIAAgAaMgAqML +valid valid float_exprs.wast:1773 AGFzbQEAAAABEQJgBH19fX0BfWAEfHx8fAF8AwMCAAEHLwIUZjMyLm5vX2ZvbGRfbXVsX2RpdnMAABRmNjQubm9fZm9sZF9tdWxfZGl2cwABCh0CDQAgACABlSACIAOVlAsNACAAIAGjIAIgA6OiCw== +valid valid float_exprs.wast:1795 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBy8CFGYzMi5ub19mb2xkX2FkZF9kaXZzAAAUZjY0Lm5vX2ZvbGRfYWRkX2RpdnMAAQodAg0AIAAgApUgASAClZILDQAgACACoyABIAKjoAs= +valid valid float_exprs.wast:1817 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2ZvbGRfc3FydF9zcXVhcmUAABdmNjQubm9fZm9sZF9zcXJ0X3NxdWFyZQABChMCCAAgACAAlJELCAAgACAAop8L +valid valid float_exprs.wast:1839 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcxAhVmMzIubm9fZm9sZF9tdWxfc3FydHMAABVmNjQubm9fZm9sZF9tdWxfc3FydHMAAQoVAgkAIACRIAGRlAsJACAAnyABn6IL +valid valid float_exprs.wast:1861 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcxAhVmMzIubm9fZm9sZF9kaXZfc3FydHMAABVmNjQubm9fZm9sZF9kaXZfc3FydHMAAQoVAgkAIACRIAGRlQsJACAAnyABn6ML +valid valid float_exprs.wast:1883 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc3AhhmMzIubm9fZm9sZF9tdWxfc3FydF9kaXYAABhmNjQubm9fZm9sZF9tdWxfc3FydF9kaXYAAQoZAgsAIAAgAZGUIAGVCwsAIAAgAZ+iIAGjCw== +valid valid float_exprs.wast:1906 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABB00CI2YzMi5ub19mbHVzaF9pbnRlcm1lZGlhdGVfc3Vibm9ybWFsAAAjZjY0Lm5vX2ZsdXNoX2ludGVybWVkaWF0ZV9zdWJub3JtYWwAAQoXAgoAIAAgAZQgApQLCgAgACABoiACogs= +valid valid float_exprs.wast:1920 AGFzbQEAAAABEwNgAn19AX9gAnx8AX9gAnx9AX0DCAcAAAABAQECB38HD2YzMi5yZWNvZGluZ19lcQAAD2YzMi5yZWNvZGluZ19sZQABD2YzMi5yZWNvZGluZ19sdAACD2Y2NC5yZWNvZGluZ19lcQADD2Y2NC5yZWNvZGluZ19sZQAED2Y2NC5yZWNvZGluZ19sdAAFD3JlY29kaW5nX2RlbW90ZQAGCkwHCgAgACABlCAAWwsKACAAIAGUIABfCwoAIAAgAZQgAF0LCgAgACABoiAAYQsKACAAIAGiIABlCwoAIAAgAaIgAGMLCAAgALYgAZQL +valid valid float_exprs.wast:1964 AGFzbQEAAAABDwJgA319fQF/YAN8fHwBfwMDAgABB0ECHWYzMi5ub19leHRlbmRlZF9wcmVjaXNpb25fZGl2AAAdZjY0Lm5vX2V4dGVuZGVkX3ByZWNpc2lvbl9kaXYAAQoXAgoAIAAgAZUgAlsLCgAgACABoyACYQs= +valid valid float_exprs.wast:1980 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHNQIXZjMyLm5vX2Rpc3RyaWJ1dGVfZXhhY3QAABdmNjQubm9fZGlzdHJpYnV0ZV9leGFjdAABCjECEwBDAAAAwSAAlEMAAABBIACUkgsbAEQAAAAAAAAgwCAAokQAAAAAAAAgQCAAoqAL +valid valid float_exprs.wast:1994 AGFzbQEAAAABKQZgAX0BfWAEfX19fQF9YAN9fX0BfWABfAF8YAR8fHx8AXxgA3x8fAF8AwsKAAECAgEDBAUFBAe1AQoIZjMyLnNxcnQAAA9mMzIueGtjZF9zcXJ0XzIAAQ9mMzIueGtjZF9zcXJ0XzMAAg9mMzIueGtjZF9zcXJ0XzUAAxZmMzIueGtjZF9iZXR0ZXJfc3FydF81AAQIZjY0LnNxcnQABQ9mNjQueGtjZF9zcXJ0XzIABg9mNjQueGtjZF9zcXJ0XzMABw9mNjQueGtjZF9zcXJ0XzUACBZmNjQueGtjZF9iZXR0ZXJfc3FydF81AAkKiQEKBQAgAJELEAAgACABlSACIAMgApOVkgsKACAAIAGUIAKVCw0AIAAgAZUgAiAAlZILEwAgACABIAKUkiADIAEgApSTlQsFACAAnwsQACAAIAGjIAIgAyACoaOgCwoAIAAgAaIgAqMLDQAgACABoyACIACjoAsTACAAIAEgAqKgIAMgASACoqGjCw== +valid valid float_exprs.wast:2045 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcpAhFmMzIuY29tcHV0ZV9yYWRpeAAAEWY2NC5jb21wdXRlX3JhZGl4AAEKnQECQwADQCAAIACSIgBDAACAP5IgAJNDAACAv5JDAAAAAFsNAAsDQCAAIAFDAACAP5IiAZIgAJMgAZNDAAAAAFwNAAsgAQtXAANAIAAgAKAiAEQAAAAAAADwP6AgAKFEAAAAAAAA8L+gRAAAAAAAAAAAYQ0ACwNAIAAgAUQAAAAAAADwP6AiAaAgAKEgAaFEAAAAAAAAAABiDQALIAEL +valid valid float_exprs.wast:2129 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc3AhhmMzIubm9fZm9sZF9zdWIxX211bF9hZGQAABhmNjQubm9fZm9sZF9zdWIxX211bF9hZGQAAQonAhAAIABDAACAP5MgAZQgAZILFAAgAEQAAAAAAADwP6EgAaIgAaAL +valid valid float_exprs.wast:2143 AGFzbQEAAAABDwJgA319fQF/YAN8fHwBfwMFBAAAAQEHiQEEH2YzMi5ub19mb2xkX2FkZF9sZV9tb25vdG9uaWNpdHkAAB9mMzIubm9fZm9sZF9hZGRfZ2VfbW9ub3RvbmljaXR5AAEfZjY0Lm5vX2ZvbGRfYWRkX2xlX21vbm90b25pY2l0eQACH2Y2NC5ub19mb2xkX2FkZF9nZV9tb25vdG9uaWNpdHkAAwo5BA0AIAAgApIgASACkl8LDQAgACACkiABIAKSYAsNACAAIAKgIAEgAqBlCw0AIAAgAqAgASACoGYL +valid valid float_exprs.wast:2164 AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQdpCApmMzIubm90X2x0AAAKZjMyLm5vdF9sZQABCmYzMi5ub3RfZ3QAAgpmMzIubm90X2dlAAMKZjY0Lm5vdF9sdAAECmY2NC5ub3RfbGUABQpmNjQubm90X2d0AAYKZjY0Lm5vdF9nZQAHCkkICAAgACABXUULCAAgACABX0ULCAAgACABXkULCAAgACABYEULCAAgACABY0ULCAAgACABZUULCAAgACABZEULCAAgACABZkUL +valid valid float_exprs.wast:2203 AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBx0CC2YzMi5lcHNpbG9uAAALZjY0LmVwc2lsb24AAQpVAh8AQwAAgD9DAABAQEMAAIBAQwAAQECVQwAAgD+TlJMLMwBEAAAAAAAA8D9EAAAAAAAACEBEAAAAAAAAEEBEAAAAAAAACECjRAAAAAAAAPA/oaKhCw== +valid valid float_exprs.wast:2218 AGFzbQEAAAABCQJgAAF9YAABfAMDAgABBx0CC2YzMi5lcHNpbG9uAAALZjY0LmVwc2lsb24AAQpnAioBAn1DAACAPyEAA0AgACIBQwAAAD+UIgBDAACAP5JDAACAP14NAAsgAQs6AQJ8RAAAAAAAAPA/IQADQCAAIgFEAAAAAAAA4D+iIgBEAAAAAAAA8D+gRAAAAAAAAPA/ZA0ACyABCw== +valid valid float_exprs.wast:2272 AGFzbQEAAAABDQJgAn19AX9gAnx8AX8DCQgAAAAAAQEBAQe5AQgUZjMyLm5vX3RyaWNob3RvbXlfbHQAABRmMzIubm9fdHJpY2hvdG9teV9sZQABFGYzMi5ub190cmljaG90b215X2d0AAIUZjMyLm5vX3RyaWNob3RvbXlfZ2UAAxRmNjQubm9fdHJpY2hvdG9teV9sdAAEFGY2NC5ub190cmljaG90b215X2xlAAUUZjY0Lm5vX3RyaWNob3RvbXlfZ3QABhRmNjQubm9fdHJpY2hvdG9teV9nZQAHCnEIDQAgACABXSAAIAFgcgsNACAAIAFfIAAgAV5yCw0AIAAgAV4gACABX3ILDQAgACABYCAAIAFdcgsNACAAIAFjIAAgAWZyCw0AIAAgAWUgACABZHILDQAgACABZCAAIAFlcgsNACAAIAFmIAAgAWNyCw== +valid valid float_exprs.wast:2304 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== +valid valid float_exprs.wast:2420 AGFzbQEAAAABDQFgCHx8fHx8fHx8AXwDAwIAAAcyAhNkb3RfcHJvZHVjdF9leGFtcGxlAAAYd2l0aF9iaW5hcnlfc3VtX2NvbGxhcHNlAAEKNQIZACAAIASiIAEgBaKgIAIgBqKgIAMgB6KgCxkAIAAgBKIgASAFoqAgAiAGoiADIAeioKAL +valid valid float_exprs.wast:2454 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQcnAhBmMzIuY29udHJhY3QyZm1hAAAQZjY0LmNvbnRyYWN0MmZtYQABCh8CDgAgACAAlCABIAGUk5ELDgAgACAAoiABIAGioZ8L +valid valid float_exprs.wast:2475 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBz8CHGYzMi5kaXZpc2lvbl9ieV9zbWFsbF9udW1iZXIAABxmNjQuZGl2aXNpb25fYnlfc21hbGxfbnVtYmVyAAEKFwIKACAAIAEgApWTCwoAIAAgASACo6EL +valid valid float_exprs.wast:2490 AGFzbQEAAAABDwJgA319fQF9YAN8fHwBfAMDAgABBycCEGYzMi5nb2xkZW5fcmF0aW8AABBmNjQuZ29sZGVuX3JhdGlvAAEKGQILACAAIAEgApGSlAsLACAAIAEgAp+gogs= +valid valid float_exprs.wast:2503 AGFzbQEAAAABCwJgAX0BfWABfAF8AwMCAAEHJwIQZjMyLnNpbHZlcl9tZWFucwAAEGY2NC5zaWx2ZXJfbWVhbnMAAQo5AhcAQwAAAD8gACAAIACUQwAAgECSkZKUCx8ARAAAAAAAAOA/IAAgACAAokQAAAAAAAAQQKCfoKIL +valid valid float_exprs.wast:2532 AGFzbQEAAAABBwFgAnx8AX8DAgEABw4BCnBvaW50X2ZvdXIAAAoTAREAIAAgAaNEmpmZmZmZ2T9jCw== +valid valid float_exprs.wast:2542 AGFzbQEAAAABBgFgAX8BfAMCAQAHBwEDdGF1AAAKywEByAEBBHxEAAAAAAAAAAAhAQJAIABBAUgNAEQAAAAAAADwPyECRAAAAAAAAAAAIQMDQCABIAJEAAAAAAAAIEAgA0QAAAAAAAAgQKIiBEQAAAAAAADwP6CjRAAAAAAAABBAIAREAAAAAAAAEECgo6FEAAAAAAAAAEAgBEQAAAAAAAAUQKCjoUQAAAAAAAAAQCAERAAAAAAAABhAoKOhoqAhASADRAAAAAAAAPA/oCEDIAJEAAAAAAAAsD+iIQIgAEF/aiIADQALCyABCw== +valid valid float_exprs.wast:2612 AGFzbQEAAAABDQJgAn19AX1gAnx8AXwDAwIAAQc9AhtmMzIubm9fZm9sZF9jb25kaXRpb25hbF9pbmMAABtmNjQubm9fZm9sZF9jb25kaXRpb25hbF9pbmMAAQo1AhUAIAAgAEMAAIA/kiABQwAAAABdGwsdACAAIABEAAAAAAAA8D+gIAFEAAAAAAAAAABjGws= +valid valid float_literals.wast:3 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== +valid valid float_literals.wast:224 AGFzbQEAAAABhYCAgAABYAABfAOCgICAAAEAB46AgIAAAQo0Mjk0OTY3MjQ5AAAKkYCAgAABi4CAgAAARAAAIPr//+9BCw== +valid valid float_memory.wast:5 AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBACoCAAsHAEEAKAIACwwAQQBDAACgfzgCAAsNAEEAQYCAgP0HNgIACwkAQQBBADYCAAsLCgEAQQALBAAAoH8= +valid valid float_memory.wast:30 AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBACsDAAsHAEEAKQMACxAAQQBEAAAAAAAA9H85AwALEgBBAEKAgICAgICA+v8ANwMACwkAQQBCADcDAAsLDgEAQQALCAAAAAAAAPR/ +valid valid float_memory.wast:57 AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBASoCAAsHAEEBKAIACwwAQQFDAACgfzgCAAsNAEEBQYCAgP0HNgIACwkAQQFBADYCAAsLCwEAQQALBQAAAKB/ +valid valid float_memory.wast:82 AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBASsDAAsHAEEBKQMACxAAQQFEAAAAAAAA9H85AwALEgBBAUKAgICAgICA+v8ANwMACwkAQQFCADcDAAsLDwEAQQALCQAAAAAAAAD0fw== +valid valid float_memory.wast:109 AGFzbQEAAAABDANgAAF9YAABf2AAAAMGBQABAgICBQQBAQEBBzcFCGYzMi5sb2FkAAAIaTMyLmxvYWQAAQlmMzIuc3RvcmUAAglpMzIuc3RvcmUAAwVyZXNldAAECjYFBwBBACoCAAsHAEEAKAIACwwAQQBDAQDQfzgCAAsNAEEAQYGAwP4HNgIACwkAQQBBADYCAAsLCgEAQQALBAEA0H8= +valid valid float_memory.wast:134 AGFzbQEAAAABDANgAAF8YAABfmAAAAMGBQABAgICBQQBAQEBBzcFCGY2NC5sb2FkAAAIaTY0LmxvYWQAAQlmNjQuc3RvcmUAAglpNjQuc3RvcmUAAwVyZXNldAAECj8FBwBBACsDAAsHAEEAKQMACxAAQQBEAQAAAAAA/H85AwALEgBBAEKBgICAgICA/v8ANwMACwkAQQBCADcDAAsLDgEAQQALCAEAAAAAAPx/ +valid valid float_misc.wast:17 AGFzbQEAAAABFwRgAn19AX1gAX0BfWACfHwBfGABfAF8Ax0cAAAAAAEBAQABAQEBAAACAgICAwMDAgMDAwMCAge3AhwHZjMyLmFkZAAAB2YzMi5zdWIAAQdmMzIubXVsAAIHZjMyLmRpdgADCGYzMi5zcXJ0AAQHZjMyLmFicwAFB2YzMi5uZWcABgxmMzIuY29weXNpZ24ABwhmMzIuY2VpbAAICWYzMi5mbG9vcgAJCWYzMi50cnVuYwAKC2YzMi5uZWFyZXN0AAsHZjMyLm1pbgAMB2YzMi5tYXgADQdmNjQuYWRkAA4HZjY0LnN1YgAPB2Y2NC5tdWwAEAdmNjQuZGl2ABEIZjY0LnNxcnQAEgdmNjQuYWJzABMHZjY0Lm5lZwAUDGY2NC5jb3B5c2lnbgAVCGY2NC5jZWlsABYJZjY0LmZsb29yABcJZjY0LnRydW5jABgLZjY0Lm5lYXJlc3QAGQdmNjQubWluABoHZjY0Lm1heAAbCsUBHAcAIAAgAZILBwAgACABkwsHACAAIAGUCwcAIAAgAZULBQAgAJELBQAgAIsLBQAgAIwLBwAgACABmAsFACAAjQsFACAAjgsFACAAjwsFACAAkAsHACAAIAGWCwcAIAAgAZcLBwAgACABoAsHACAAIAGhCwcAIAAgAaILBwAgACABowsFACAAnwsFACAAmQsFACAAmgsHACAAIAGmCwUAIACbCwUAIACcCwUAIACdCwUAIACeCwcAIAAgAaQLBwAgACABpQs= +valid valid forward.wast:1 AGFzbQEAAAABBgFgAX8BfwMDAgAABw4CBGV2ZW4AAANvZGQAAQorAhQAIABBAEYEf0EBBSAAQQFrEAELCxQAIABBAEYEf0EABSAAQQFrEAALCw== +valid valid func.wast:3 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= +valid valid func.wast:422 AGFzbQEAAAABDANgAX8AYAABfGAAAAMGBQEAAAECCikFCwBEAAAAAAAAAAALAgALAgALCwBEAAAAAAAAAAALCQBBABACEAMaCw== +invalid invalid func.wast:436 AGFzbQEAAAABCQJgAX8AYAABfAMFBAEAAQIKHwQLAEQAAAAAAAAAAAsCAAsLAEQAAAAAAADwPwsCAAs= +valid valid func.wast:459 AGFzbQEAAAABCgJgAAF/YAF/AX8DBQQBAQEABw0DAWYAAAFnAAIBcAADCiEEBgEBfyABCwYBAX8gAQsGACAAEAELCgEBf0EqIQAgAAs= +valid valid func.wast:488 AGFzbQEAAAABHQRgAABgAABgCH5+fH58fn1/AGAIfH58fnx+fX8AAwwLAAMAAwMCAgAAAAAEBQFwAQcHB3cEGXNpZ25hdHVyZS1leHBsaWNpdC1yZXVzZWQABxlzaWduYXR1cmUtaW1wbGljaXQtcmV1c2VkAAgcc2lnbmF0dXJlLWV4cGxpY2l0LWR1cGxpY2F0ZQAJHHNpZ25hdHVyZS1pbXBsaWNpdC1kdXBsaWNhdGUACgkNAQBBAAsHBAIBBAAFBgqFAgsCAAsCAAsCAAsCAAsCAAsCAAsCAAsMAEEBEQAAQQQRAAALiQEARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEAEQMARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEECEQMARAAAAAAAAAAAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEDEQMACwcAQQERAQALTgBCAEIARAAAAAAAAAAAQgBEAAAAAAAAAABCAEMAAAAAQQBBBRECAEIAQgBEAAAAAAAAAABCAEQAAAAAAAAAAEIAQwAAAABBAEEGEQIACw== +invalid invalid func.wast:634 AGFzbQEAAAABBQFgAAF+AwIBAAoIAQYBAX8gAAs= +invalid invalid func.wast:638 AGFzbQEAAAABBAFgAAADAgEACgkBBwEBfSAARQs= +invalid invalid func.wast:642 AGFzbQEAAAABBAFgAAADAgEACgsBCQIBfAF+IAGaCw== +invalid invalid func.wast:650 AGFzbQEAAAABBgFgAX8BfgMCAQAKBgEEACAACw== +invalid invalid func.wast:654 AGFzbQEAAAABBQFgAX0AAwIBAAoHAQUAIABFCw== +invalid invalid func.wast:658 AGFzbQEAAAABBgFgAnx+AAMCAQAKBwEFACABmgs= +invalid invalid func.wast:666 AGFzbQEAAAABBQFgAAF/AwIBAAoEAQIACw== +invalid invalid func.wast:670 AGFzbQEAAAABBQFgAAF+AwIBAAoEAQIACw== +invalid invalid func.wast:674 AGFzbQEAAAABBQFgAAF9AwIBAAoEAQIACw== +invalid invalid func.wast:678 AGFzbQEAAAABBQFgAAF8AwIBAAoEAQIACw== +invalid invalid func.wast:682 AGFzbQEAAAABBgFgAAJ8fwMCAQAKBAECAAs= +invalid invalid func.wast:687 AGFzbQEAAAABBQFgAAF/AwIBAAoFAQMAAQs= +invalid invalid func.wast:693 AGFzbQEAAAABBgFgAAJ/fwMCAQAKBQEDAAEL +invalid invalid func.wast:699 AGFzbQEAAAABBAFgAAADAgEACgYBBABBAAs= +invalid invalid func.wast:705 AGFzbQEAAAABBAFgAAADAgEACggBBgBBAEIACw== +invalid invalid func.wast:711 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAQwAAAAAL +invalid invalid func.wast:717 AGFzbQEAAAABBgFgAAJ9fQMCAQAKCQEHAEMAAAAACw== +invalid invalid func.wast:723 AGFzbQEAAAABBQFgAAF9AwIBAAoOAQwAQwAAAABDAAAAAAs= +invalid invalid func.wast:730 AGFzbQEAAAABBQFgAAF/AwIBAAoFAQMADws= +invalid invalid func.wast:736 AGFzbQEAAAABBgFgAAJ/fwMCAQAKBQEDAA8L +invalid invalid func.wast:742 AGFzbQEAAAABBQFgAAF/AwIBAAoGAQQAAQ8L +invalid invalid func.wast:748 AGFzbQEAAAABBgFgAAJ/fgMCAQAKBgEEAAEPCw== +invalid invalid func.wast:754 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgAPCw== +invalid invalid func.wast:760 AGFzbQEAAAABBgFgAAJ+fgMCAQAKBwEFAEIADws= +invalid invalid func.wast:767 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAD0EBCw== +invalid invalid func.wast:773 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAA9BAUECCw== +invalid invalid func.wast:779 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAEEBD0ECCw== +invalid invalid func.wast:785 AGFzbQEAAAABBQFgAAF/AwIBAAoIAQYAAQ9BAQs= +invalid invalid func.wast:791 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCAEGAAEPQQEL +invalid invalid func.wast:797 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAQgEPQQEL +invalid invalid func.wast:803 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCwEJAEIBD0EBQQIL +invalid invalid func.wast:809 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAQgEPQQEPCw== +invalid invalid func.wast:815 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDAEKAEEBD0EBQQIPCw== +invalid invalid func.wast:822 AGFzbQEAAAABBQFgAAF/AwIBAAoGAQQADAAL +invalid invalid func.wast:828 AGFzbQEAAAABBgFgAAJ/fwMCAQAKBgEEAAwACw== +invalid invalid func.wast:834 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAQwAAAAAMAAs= +invalid invalid func.wast:840 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCAEGAEEADAAL +invalid invalid func.wast:846 AGFzbQEAAAABBQFgAAF/AwIBAAoIAQYADABBAQs= +invalid invalid func.wast:852 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCgEIAAwAQQFBAgs= +invalid invalid func.wast:858 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAQgEMAEEBCw== +invalid invalid func.wast:864 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDAEKAEEBDABBAUECCw== +invalid invalid func.wast:870 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgEMAEEBDAAL +invalid invalid func.wast:877 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAkAMAQtBAQwACw== +invalid invalid func.wast:883 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDwENAAJADAELQQFBAgwACw== +invalid invalid func.wast:889 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAkABDAELQQEMAAs= +invalid invalid func.wast:895 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAAJAAQwBC0EBQQIMAAs= +invalid invalid func.wast:901 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAkBCAQwBC0EBDAAL +invalid invalid func.wast:907 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEQEPAAJ/QQEMAQtBAUECDAAL +valid valid func_ptrs.wast:1 AGFzbQEAAAABGwdgAABgAABgAABgAAF/YAABf2ABfwF/YAF/AAIWAQhzcGVjdGVzdAlwcmludF9pMzIABgMHBgABBAUFBgccBANvbmUAAwN0d28ABAV0aHJlZQAFBGZvdXIABgojBgIACwIACwQAQQ0LBwAgAEEBagsHACAAQQJrCwYAIAAQAAs= +invalid invalid func_ptrs.wast:32 AGFzbQEAAAAJBgEAQQALAA== +invalid invalid func_ptrs.wast:48 AGFzbQEAAAADAgEqCgQBAgAL +invalid invalid func_ptrs.wast:49 AGFzbQEAAAACFgEIc3BlY3Rlc3QJcHJpbnRfaTMyACs= +valid valid func_ptrs.wast:51 AGFzbQEAAAABDgNgAAF/YAABf2ABfwF/AwgHAAAAAQECAgQFAXABBwcHEQIFY2FsbHQABQVjYWxsdQAGCQ0BAEEACwcAAQIDBAACCioHBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwcAIAARAAALBwAgABEBAAs= +valid valid func_ptrs.wast:93 AGFzbQEAAAABCgJgAAF/YAF/AX8DBAMAAAEEBQFwAQICBwkBBWNhbGx0AAIJCAEAQQALAgABChMDBABBAQsEAEECCwcAIAARAAAL +valid valid global.wast:3 AGFzbQEAAAABNw1gAn9/AX9gAAF/YAABfmAAAW9gAX8AYAF+AGABbwBgAAF9YAABfGABfQBgAXwAYAAAYAF/AX8CLwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdApnbG9iYWxfaTY0A34AAzMyAQIDAwECAQIEBQYHCAcICQoLAQEBAQEBAQEBAQEBAQABAQELCwEBDAEBCwEMDAEBAQEEBQFwAQEBBQMBAAEGVg1/AEF+C30AQwAAQMALfABEAAAAAAAAEMALfgBCewt/AUF0C30BQwAAUMELfAFEAAAAAAAALMALfgFCcQt/ACMAC34AIwELbwDQbwtvAdBvC3AA0HALB7EFLwVnZXQtYQAABWdldC1iAAEFZ2V0LXIAAgZnZXQtbXIAAwVnZXQteAAEBWdldC15AAUGZ2V0LXoxAAYGZ2V0LXoyAAcFc2V0LXgACAVzZXQteQAJBnNldC1tcgAKBWdldC0zAAsFZ2V0LTQADAVnZXQtNwANBWdldC04AA4Fc2V0LTcADwVzZXQtOAAQD2FzLXNlbGVjdC1maXJzdAASDWFzLXNlbGVjdC1taWQAEw5hcy1zZWxlY3QtbGFzdAAUDWFzLWxvb3AtZmlyc3QAFQthcy1sb29wLW1pZAAWDGFzLWxvb3AtbGFzdAAXD2FzLWlmLWNvbmRpdGlvbgAYCmFzLWlmLXRoZW4AGQphcy1pZi1lbHNlABoOYXMtYnJfaWYtZmlyc3QAGw1hcy1icl9pZi1sYXN0ABwRYXMtYnJfdGFibGUtZmlyc3QAHRBhcy1icl90YWJsZS1sYXN0AB4WYXMtY2FsbF9pbmRpcmVjdC1maXJzdAAgFGFzLWNhbGxfaW5kaXJlY3QtbWlkACEVYXMtY2FsbF9pbmRpcmVjdC1sYXN0ACIOYXMtc3RvcmUtZmlyc3QAIw1hcy1zdG9yZS1sYXN0ACQPYXMtbG9hZC1vcGVyYW5kACUUYXMtbWVtb3J5Lmdyb3ctdmFsdWUAJg1hcy1jYWxsLXZhbHVlACgPYXMtcmV0dXJuLXZhbHVlACkPYXMtZHJvcC1vcGVyYW5kACoLYXMtYnItdmFsdWUAKxJhcy1sb2NhbC5zZXQtdmFsdWUALBJhcy1sb2NhbC50ZWUtdmFsdWUALRNhcy1nbG9iYWwuc2V0LXZhbHVlAC4QYXMtdW5hcnktb3BlcmFuZAAvEWFzLWJpbmFyeS1vcGVyYW5kADASYXMtY29tcGFyZS1vcGVyYW5kADEJBwEAQQALAR8KsAMyBAAjAgsEACMFCwQAIwwLBAAjDQsEACMGCwQAIwkLBAAjCgsEACMLCwYAIAAkBgsGACAAJAkLBgAgACQNCwQAIwMLBAAjBAsEACMHCwQAIwgLBgAgACQHCwYAIAAkCAsCAAsJACMGQQJBAxsLCQBBAiMGQQMbCwkAQQJBAyMGGwsLAAN/IwYQERARCwsLAAN/EBEjBhARCwsLAAN/EBEQESMGCwsQACMGBH8QEUECBRARQQMLCwwAQQEEfyMGBUECCwsMAEEABH9BAgUjBgsLDgACfyMGQQINAEEDDwsLDgACf0ECIwYNAEEDDwsLDQACfyMGQQIOAQAACwsNAAJ/QQIjBg4BAAALCwQAIAALDgACfyMGQQJBABEAAAsLDgACf0ECIwZBABEAAAsLDgACf0ECQQAjBhEAAAsLCQAjBkEBNgIACwkAQQAjBjYCAAsHACMGKAIACwYAIwZAAAsEACAACwYAIwYQJwsFACMGDwsFACMGGgsJAAJ/IwYMAAsLCAAjBiEAIAALBgAjBiIACwgAIwYkBiMGCwUAIwZFCwcAIwYjBmwLBwAjAEEBSws= +invalid invalid global.wast:273 AGFzbQEAAAABBAFgAAADAgEABgkBfQBDAAAAAAsKCwEJAEMAAIA/JAAL +invalid invalid global.wast:278 AGFzbQEAAAABBAFgAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMCAQAKCAEGAEEBJAAL +valid valid global.wast:283 AGFzbQEAAAAGCQF9AUMAAAAACwcFAQFhAwA= +invalid invalid global.wast:287 AGFzbQEAAAAGCgF9AEMAAAAAjAs= +invalid invalid global.wast:292 AGFzbQEAAAAGBgF9ACAACw== +invalid invalid global.wast:297 AGFzbQEAAAAGCgF9AEMAAIA/jAs= +invalid invalid global.wast:302 AGFzbQEAAAAGBwF/AEEAAQs= +invalid invalid global.wast:307 AGFzbQEAAAAGBwF/AEEAaAs= +invalid invalid global.wast:312 AGFzbQEAAAAGBQF/AAEL +invalid invalid global.wast:317 AGFzbQEAAAAGCQF/AEMAAAAACw== +invalid invalid global.wast:322 AGFzbQEAAAAGCAF/AEEAQQAL +invalid invalid global.wast:327 AGFzbQEAAAAGBAF/AAs= +invalid invalid global.wast:332 AGFzbQEAAAACBgEAAANvAAYGAXAAIwAL +invalid invalid global.wast:337 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABggBfwAjACMACw== +invalid invalid global.wast:342 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABggBfwBBACMACw== +invalid invalid global.wast:347 AGFzbQEAAAAGBgF/ACMACw== +invalid valid global.wast:352 AGFzbQEAAAAGCwJ/AEEAC38AIwAL +invalid invalid global.wast:361 AGFzbQEAAAAGCwJ/ACMBC38AQQAL +invalid invalid global.wast:366 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38ABgYBfwAjAgs= +invalid invalid global.wast:371 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWkzMgN/AQYGAX8AIwAL +valid valid global.wast:375 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AA== +malformed invalid global.wast:379 AGFzbQEAAAACmICAgAABCHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwQ= +malformed invalid global.wast:392 AGFzbQEAAAACmICAgAABCHNwZWN0ZXN0Cmdsb2JhbF9pMzIDf/8= +valid valid global.wast:405 AGFzbQEAAAAGBgF/AEEACw== +malformed invalid global.wast:409 AGFzbQEAAAAGhoCAgAABfwRBAAs= +malformed invalid global.wast:421 AGFzbQEAAAAGhoCAgAABf/9BAAs= +invalid invalid global.wast:435 AGFzbQEAAAABBQFgAAF/AwIBAAoGAQQAIwAL +invalid invalid global.wast:440 AGFzbQEAAAABBQFgAAF/AwIBAAYGAX8AQQALCgYBBAAjAQs= +invalid invalid global.wast:448 AGFzbQEAAAABBQFgAAF/AhgBCHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwADAgEACgYBBAAjAQs= +invalid invalid global.wast:456 AGFzbQEAAAABBQFgAAF/AhgBCHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwADAgEABgYBfwBBAAsKBgEEACMCCw== +invalid invalid global.wast:466 AGFzbQEAAAABBAFgAAADAgEACggBBgBBACQACw== +invalid invalid global.wast:471 AGFzbQEAAAABBAFgAAADAgEABgYBfwBBAAsKCAEGAEEAJAEL +invalid invalid global.wast:479 AGFzbQEAAAABBAFgAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMCAQAKCAEGAEEAJAEL +invalid invalid global.wast:487 AGFzbQEAAAABBAFgAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMCAQAGBgF/AEEACwoIAQYAQQAkAgs= +invalid invalid global.wast:497 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKBgEEACQACw== +invalid invalid global.wast:506 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKCwEJAEEAAkAkAAsL +invalid invalid global.wast:516 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKCwEJAEEAA0AkAAsL +invalid invalid global.wast:526 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDQELAEEAQQAEQCQACws= +invalid invalid global.wast:536 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKEAEOAEEAQQAEf0EABSQACws= +invalid invalid global.wast:546 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDQELAEEAAkAkAAwACws= +invalid invalid global.wast:556 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDQELAEEAAkAkAA0ACws= +invalid invalid global.wast:566 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDgEMAEEAAkAkAA4AAAsL +invalid invalid global.wast:576 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKBwEFACQADws= +invalid invalid global.wast:585 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKCwEJACQAQQFBAhsL +invalid invalid global.wast:594 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBgYBfwFBAAsKDQIGACQAEAELBAAgAAs= +invalid invalid global.wast:604 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQYGAX8BQQALCQcBAEEACwEAChMCBAAgAAsMAAJ/JABBABEAAAsL +valid valid i32.wast:3 AGFzbQEAAAABDAJgAn9/AX9gAX8BfwMgHwAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAH3gEfA2FkZAAAA3N1YgABA211bAACBWRpdl9zAAMFZGl2X3UABAVyZW1fcwAFBXJlbV91AAYDYW5kAAcCb3IACAN4b3IACQNzaGwACgVzaHJfcwALBXNocl91AAwEcm90bAANBHJvdHIADgNjbHoADwNjdHoAEAZwb3BjbnQAEQlleHRlbmQ4X3MAEgpleHRlbmQxNl9zABMDZXF6ABQCZXEAFQJuZQAWBGx0X3MAFwRsdF91ABgEbGVfcwAZBGxlX3UAGgRndF9zABsEZ3RfdQAcBGdlX3MAHQRnZV91AB4K7QEfBwAgACABagsHACAAIAFrCwcAIAAgAWwLBwAgACABbQsHACAAIAFuCwcAIAAgAW8LBwAgACABcAsHACAAIAFxCwcAIAAgAXILBwAgACABcwsHACAAIAF0CwcAIAAgAXULBwAgACABdgsHACAAIAF3CwcAIAAgAXgLBQAgAGcLBQAgAGgLBQAgAGkLBQAgAMALBQAgAMELBQAgAEULBwAgACABRgsHACAAIAFHCwcAIAAgAUgLBwAgACABSQsHACAAIAFMCwcAIAAgAU0LBwAgACABSgsHACAAIAFLCwcAIAAgAU4LBwAgACABTws= +invalid invalid i32.wast:444 AGFzbQEAAAABBAFgAAADAgEACgYBBABFGgs= +invalid invalid i32.wast:452 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAAJARRoLCw== +invalid invalid i32.wast:461 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAANARRoLCw== +invalid invalid i32.wast:470 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAEEABEBFGgsL +invalid invalid i32.wast:479 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAEEABH9BAAVFCxoL +invalid invalid i32.wast:488 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAAJARQwAGgsL +invalid invalid i32.wast:497 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAAJARUEBDQAaCws= +invalid invalid i32.wast:506 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAAJARQ4AABoLCw== +invalid invalid i32.wast:515 AGFzbQEAAAABBAFgAAADAgEACgcBBQBFDxoL +invalid invalid i32.wast:523 AGFzbQEAAAABBAFgAAADAgEACgsBCQBFQQFBAhsaCw== +invalid invalid i32.wast:531 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABCg0CBgBFEAEaCwQAIAAL +invalid invalid i32.wast:540 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoTAgQAIAALDAACf0VBABEAABoLCw== +invalid invalid i32.wast:556 AGFzbQEAAAABBAFgAAADAgEACgwBCgEBf0UhACAAGgs= +invalid invalid i32.wast:565 AGFzbQEAAAABBAFgAAADAgEACgoBCAEBf0UiABoL +invalid invalid i32.wast:574 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKCgEIAEUkACMAGgs= +invalid invalid i32.wast:583 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCAEGAEVAABoL +invalid invalid i32.wast:592 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCQEHAEUoAgAaCw== +invalid invalid i32.wast:601 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEVBATYCAAs= +invalid invalid i32.wast:611 AGFzbQEAAAABBAFgAAADAgEACgYBBABqGgs= +invalid invalid i32.wast:619 AGFzbQEAAAABBAFgAAADAgEACggBBgBBAGoaCw== +invalid invalid i32.wast:627 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAEEAAkBqGgsL +invalid invalid i32.wast:636 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAAJAQQBqGgsL +invalid invalid i32.wast:645 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAEEAA0BqGgsL +invalid invalid i32.wast:654 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAANAQQBqGgsL +invalid invalid i32.wast:663 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAQQBqBEAaCws= +invalid invalid i32.wast:672 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAEEAQQAEQGoFGgsL +invalid invalid i32.wast:681 AGFzbQEAAAABBAFgAAADAgEAChUBEwBBAEEAQQAEf0EABWpBAAsaGgs= +invalid invalid i32.wast:691 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAEEABH9BAAVqCxoL +invalid invalid i32.wast:701 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAAkBqDAAaCws= +invalid invalid i32.wast:710 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAAJAQQBqDAAaCws= +invalid invalid i32.wast:719 AGFzbQEAAAABBAFgAAADAgEAChEBDwBBAEEAAkBqQQENABoLCw== +invalid invalid i32.wast:728 AGFzbQEAAAABBAFgAAADAgEAChEBDwBBAAJAQQBqQQENABoLCw== +invalid invalid i32.wast:737 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAEEAAkBqDgAAGgsL +invalid invalid i32.wast:746 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAAJAQQBqDgAAGgsL +invalid invalid i32.wast:755 AGFzbQEAAAABBAFgAAADAgEACgcBBQBqDxoL +invalid invalid i32.wast:763 AGFzbQEAAAABBAFgAAADAgEACgkBBwBBAGoPGgs= +invalid invalid i32.wast:771 AGFzbQEAAAABBAFgAAADAgEACgsBCQBqQQFBAhsaCw== +invalid invalid i32.wast:779 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAGpBAUECGxoL +invalid invalid i32.wast:787 AGFzbQEAAAABCgJgAABgAn9/AX8DAwIAAQoNAgYAahABGgsEACAACw== +invalid invalid i32.wast:796 AGFzbQEAAAABCgJgAABgAn9/AX8DAwIAAQoPAggAQQBqEAEaCwQAIAAL +invalid invalid i32.wast:805 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoTAgQAIAALDAACf2pBABEAABoLCw== +invalid invalid i32.wast:821 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoVAgQAIAALDgACf0EAakEAEQAAGgsL +invalid invalid i32.wast:837 AGFzbQEAAAABBAFgAAADAgEACgwBCgEBf2ohACAAGgs= +invalid invalid i32.wast:846 AGFzbQEAAAABBAFgAAADAgEACg4BDAEBf0EAaiEAIAAaCw== +invalid invalid i32.wast:855 AGFzbQEAAAABBAFgAAADAgEACgoBCAEBf2oiABoL +invalid invalid i32.wast:864 AGFzbQEAAAABBAFgAAADAgEACgwBCgEBf0EAaiIAGgs= +invalid invalid i32.wast:873 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKCgEIAGokACMAGgs= +invalid invalid i32.wast:882 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDAEKAEEAaiQAIwAaCw== +invalid invalid i32.wast:891 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCAEGAGpAABoL +invalid invalid i32.wast:900 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAEEAakAAGgs= +invalid invalid i32.wast:909 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCQEHAGooAgAaCw== +invalid invalid i32.wast:918 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAEEAaigCABoL +invalid invalid i32.wast:927 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAGpBATYCAAs= +invalid invalid i32.wast:936 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDAEKAEEBakEANgIACw== +invalid invalid i32.wast:948 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAGoL +invalid invalid i32.wast:949 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHEL +invalid invalid i32.wast:950 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAG0L +invalid invalid i32.wast:951 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAG4L +invalid invalid i32.wast:952 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAGwL +invalid invalid i32.wast:953 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHIL +invalid invalid i32.wast:954 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAG8L +invalid invalid i32.wast:955 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHAL +invalid invalid i32.wast:956 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHcL +invalid invalid i32.wast:957 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHgL +invalid invalid i32.wast:958 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHQL +invalid invalid i32.wast:959 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHUL +invalid invalid i32.wast:960 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHYL +invalid invalid i32.wast:961 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAGsL +invalid invalid i32.wast:962 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAHML +invalid invalid i32.wast:963 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgBFCw== +invalid invalid i32.wast:964 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgBnCw== +invalid invalid i32.wast:965 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgBoCw== +invalid invalid i32.wast:966 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAQgBpCw== +invalid invalid i32.wast:967 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEYL +invalid invalid i32.wast:968 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAE4L +invalid invalid i32.wast:969 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAE8L +invalid invalid i32.wast:970 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEoL +invalid invalid i32.wast:971 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEsL +invalid invalid i32.wast:972 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEwL +invalid invalid i32.wast:973 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAE0L +invalid invalid i32.wast:974 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEgL +invalid invalid i32.wast:975 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEkL +invalid invalid i32.wast:976 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQgBDAAAAAEcL +valid valid i64.wast:3 AGFzbQEAAAABFwRgAn5+AX5gAX4BfmABfgF/YAJ+fgF/AyEgAAAAAAAAAAAAAAAAAAAAAQEBAQEBAgMDAwMDAwMDAwMH6wEgA2FkZAAAA3N1YgABA211bAACBWRpdl9zAAMFZGl2X3UABAVyZW1fcwAFBXJlbV91AAYDYW5kAAcCb3IACAN4b3IACQNzaGwACgVzaHJfcwALBXNocl91AAwEcm90bAANBHJvdHIADgNjbHoADwNjdHoAEAZwb3BjbnQAEQlleHRlbmQ4X3MAEgpleHRlbmQxNl9zABMKZXh0ZW5kMzJfcwAUA2VxegAVAmVxABYCbmUAFwRsdF9zABgEbHRfdQAZBGxlX3MAGgRsZV91ABsEZ3RfcwAcBGd0X3UAHQRnZV9zAB4EZ2VfdQAfCvMBIAcAIAAgAXwLBwAgACABfQsHACAAIAF+CwcAIAAgAX8LBwAgACABgAsHACAAIAGBCwcAIAAgAYILBwAgACABgwsHACAAIAGECwcAIAAgAYULBwAgACABhgsHACAAIAGHCwcAIAAgAYgLBwAgACABiQsHACAAIAGKCwUAIAB5CwUAIAB6CwUAIAB7CwUAIADCCwUAIADDCwUAIADECwUAIABQCwcAIAAgAVELBwAgACABUgsHACAAIAFTCwcAIAAgAVQLBwAgACABVwsHACAAIAFYCwcAIAAgAVULBwAgACABVgsHACAAIAFZCwcAIAAgAVoL +invalid invalid i64.wast:457 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAHwL +invalid invalid i64.wast:458 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIML +invalid invalid i64.wast:459 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAH8L +invalid invalid i64.wast:460 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIAL +invalid invalid i64.wast:461 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAH4L +invalid invalid i64.wast:462 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIQL +invalid invalid i64.wast:463 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIEL +invalid invalid i64.wast:464 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIIL +invalid invalid i64.wast:465 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIkL +invalid invalid i64.wast:466 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIoL +invalid invalid i64.wast:467 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIYL +invalid invalid i64.wast:468 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIcL +invalid invalid i64.wast:469 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIgL +invalid invalid i64.wast:470 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAH0L +invalid invalid i64.wast:471 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAIUL +invalid invalid i64.wast:472 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQBQCw== +invalid invalid i64.wast:473 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQB5Cw== +invalid invalid i64.wast:474 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQB6Cw== +invalid invalid i64.wast:475 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAQQB7Cw== +invalid invalid i64.wast:476 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFEL +invalid invalid i64.wast:477 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFkL +invalid invalid i64.wast:478 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFoL +invalid invalid i64.wast:479 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFUL +invalid invalid i64.wast:480 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFYL +invalid invalid i64.wast:481 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFcL +invalid invalid i64.wast:482 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFgL +invalid invalid i64.wast:483 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFML +invalid invalid i64.wast:484 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFQL +invalid invalid i64.wast:485 AGFzbQEAAAABBQFgAAF+AwIBAAoMAQoAQQBDAAAAAFIL +valid valid if.wast:3 AGFzbQEAAAABXRBgAn9/AX9gAABgAAF/YAF/AGADf3x/A398f2ABfwF/YAF/An9/YAADf35/YAACf39gAAJ9fWABfwN/f35gAAN/f35gAn9/An9/YAN+fn8Cfn9gAn5+AX5gAX4BfgM2NQEDBQYABQUFBQUFBQUFBQUABQUFAwMFBQUFAwUFBQUFBQAFAAUFBQIFCgUFBQUFBQUNDgEBBAUBcAEBAQUDAQABBgYBfwFBCgsHzgYyBWVtcHR5AAEIc2luZ3VsYXIAAgVtdWx0aQADBm5lc3RlZAAED2FzLXNlbGVjdC1maXJzdAAFDWFzLXNlbGVjdC1taWQABg5hcy1zZWxlY3QtbGFzdAAHDWFzLWxvb3AtZmlyc3QACAthcy1sb29wLW1pZAAJDGFzLWxvb3AtbGFzdAAKD2FzLWlmLWNvbmRpdGlvbgALDmFzLWJyX2lmLWZpcnN0AAwNYXMtYnJfaWYtbGFzdAANEWFzLWJyX3RhYmxlLWZpcnN0AA4QYXMtYnJfdGFibGUtbGFzdAAPFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAERRhcy1jYWxsX2luZGlyZWN0LW1pZAASFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAATDmFzLXN0b3JlLWZpcnN0ABQNYXMtc3RvcmUtbGFzdAAVFGFzLW1lbW9yeS5ncm93LXZhbHVlABYNYXMtY2FsbC12YWx1ZQAYD2FzLXJldHVybi12YWx1ZQAZD2FzLWRyb3Atb3BlcmFuZAAaC2FzLWJyLXZhbHVlABsSYXMtbG9jYWwuc2V0LXZhbHVlABwSYXMtbG9jYWwudGVlLXZhbHVlAB0TYXMtZ2xvYmFsLnNldC12YWx1ZQAeD2FzLWxvYWQtb3BlcmFuZAAfEGFzLXVuYXJ5LW9wZXJhbmQAIBFhcy1iaW5hcnktb3BlcmFuZAAhD2FzLXRlc3Qtb3BlcmFuZAAiEmFzLWNvbXBhcmUtb3BlcmFuZAAjEmFzLWJpbmFyeS1vcGVyYW5kcwAkE2FzLWNvbXBhcmUtb3BlcmFuZHMAJRFhcy1taXhlZC1vcGVyYW5kcwAmCmJyZWFrLWJhcmUAJwticmVhay12YWx1ZQAoEWJyZWFrLW11bHRpLXZhbHVlACkFcGFyYW0AKgZwYXJhbXMAKwlwYXJhbXMtaWQALAtw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 +invalid invalid if.wast:836 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAUEABEALCw== +invalid invalid if.wast:844 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAQQAEQAsL +invalid invalid if.wast:848 AGFzbQEAAAABBQFgAAF+AwIBAAoJAQcAQQAEQAsL +invalid invalid if.wast:852 AGFzbQEAAAABBQFgAAF9AwIBAAoJAQcAQQAEQAsL +invalid invalid if.wast:856 AGFzbQEAAAABBQFgAAF8AwIBAAoJAQcAQQAEQAsL +invalid invalid if.wast:878 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAQRAQQELCw== +invalid invalid if.wast:890 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAQRABUEBCws= +invalid invalid if.wast:896 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAQRAQQEFQQELCw== +invalid invalid if.wast:903 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAQRAQQFBAgsL +invalid invalid if.wast:915 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAQRABUEBQQILCw== +invalid invalid if.wast:921 AGFzbQEAAAABBAFgAAADAgEAChIBEABBAQRAQQFBAgVBAkEBCws= +invalid invalid if.wast:928 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQQEEfwVBAAsL +invalid invalid if.wast:934 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAQQEEf0EACws= +invalid invalid if.wast:940 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcAQQEEfwsL +invalid invalid if.wast:947 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDgEMAEEBBAAFQQBBAgsL +invalid invalid if.wast:953 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDQELAEEBBABBAEEBCws= +invalid invalid if.wast:959 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAEEBBAALCw== +invalid invalid if.wast:966 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAQQEEf0EBCws= +invalid invalid if.wast:972 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDQELAEEBBABBAUEBCws= +invalid invalid if.wast:979 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAQQEEfwEFQQALCw== +invalid invalid if.wast:985 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAQQEEf0EABQELCw== +invalid invalid if.wast:991 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQQEEfwEFAQsL +invalid invalid if.wast:998 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDwENAEEBBAABBUEAQQALCw== +invalid invalid if.wast:1004 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDwENAEEBBABBAEEABQELCw== +invalid invalid if.wast:1010 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDAEKAEEBBAABBQELCw== +invalid invalid if.wast:1017 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQEEf0IBBUEBCws= +invalid invalid if.wast:1023 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQEEf0EBBUIBCws= +invalid invalid if.wast:1029 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQEEf0IBBUIBCws= +invalid invalid if.wast:1036 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAEEBBABBAQVBAUEBCws= +invalid invalid if.wast:1042 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAEEBBABBAUEBBUEBCws= +invalid invalid if.wast:1048 AGFzbQEAAAABBgFgAAJ/fwMCAQAKDgEMAEEBBABBAQVBAQsL +invalid invalid if.wast:1055 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEgEQAEEAQQEEAEEBBUEBQQELCw== +invalid invalid if.wast:1062 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEgEQAEEAQQEEAEEBQQEFQQELCw== +invalid invalid if.wast:1069 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAEEAQQEEAEEBBUEBCws= +invalid invalid if.wast:1077 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQEEf0EBQQEFQQELCw== +invalid invalid if.wast:1083 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQEEf0EBBUEBQQELCw== +invalid invalid if.wast:1089 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAQQEEf0EBQQEFQQFBAQsL +invalid invalid if.wast:1096 AGFzbQEAAAABBQFgAAF/AwIBAAoVARMAQQEEf0IBBUQAAAAAAADwPwsL +invalid invalid if.wast:1102 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEgEQAEEBBABBAUEBQQEFQQELCw== +invalid invalid if.wast:1109 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQAEfgAAABsFQgALCw== +invalid invalid if.wast:1119 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQEEfkIABQAAABsLCw== +invalid invalid if.wast:1129 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAQQEEfgAAABsFAAAAGwsL +invalid invalid if.wast:1140 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQEEfwwABUEBCws= +invalid invalid if.wast:1146 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQEEf0EBBQwACws= +invalid invalid if.wast:1152 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAEEBBAAMAAVBAUEBCws= +invalid invalid if.wast:1158 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEAEOAEEBBABBAUEBBQwACws= +invalid invalid if.wast:1165 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQEEfwwAQQEFQQELCw== +invalid invalid if.wast:1174 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQEEf0EBBQwAQQELCw== +invalid invalid if.wast:1183 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFAESAEEBBAAMAEEBQQEFQQFBAQsL +invalid invalid if.wast:1192 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFAESAEEBBABBAUEBBQwAQQFBAQsL +invalid invalid if.wast:1202 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AQQEEfwEMAEEBBUEBCws= +invalid invalid if.wast:1211 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AQQEEf0EBBQEMAEEBCws= +invalid invalid if.wast:1220 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFQETAEEBBAABDABBAUEBBUEBQQELCw== +invalid invalid if.wast:1229 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFQETAEEBBABBAUEBBQEMAEEBQQELCw== +invalid invalid if.wast:1239 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAQQEEf0IBDABBAQVBAQsL +invalid invalid if.wast:1248 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAQQEEf0EBBUIBDABBAQsL +invalid invalid if.wast:1257 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFgEUAEEBBABCAQwAQQFBAQVBAUEBCws= +invalid invalid if.wast:1266 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFgEUAEEBBABBAUEBBUIBDABBAUEBCws= +invalid invalid if.wast:1275 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFAESAEEBQQEEAEIBDABBAQVBAQsL +invalid invalid if.wast:1285 AGFzbQEAAAABBgFgAAJ/fwMCAQAKFAESAEEBQQEEAEEBBUIBDABBAQsL +invalid invalid if.wast:1296 AGFzbQEAAAABBAFgAAADAgEACgcBBQAEQAsL +invalid invalid if.wast:1304 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAAJABEALCws= +invalid invalid if.wast:1313 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAANABEALCws= +invalid invalid if.wast:1322 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAEEABEAEQAsLCw== +invalid invalid if.wast:1331 AGFzbQEAAAABBAFgAAADAgEAChQBEgBBAEEABH9BAAUEQAtBAAsaCw== +invalid invalid if.wast:1341 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAAJABEALDAAaCws= +invalid invalid if.wast:1350 AGFzbQEAAAABBAFgAAADAgEAChEBDwBBAAJABEALQQENABoLCw== +invalid invalid if.wast:1359 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAAJABEALDgAAGgsL +invalid invalid if.wast:1368 AGFzbQEAAAABBAFgAAADAgEACgkBBwAEQAsPGgs= +invalid invalid if.wast:1376 AGFzbQEAAAABBAFgAAADAgEACg0BCwAEQAtBAUECGxoL +invalid invalid if.wast:1384 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABCg8CCAAEQAsQARoLBAAgAAs= +invalid invalid if.wast:1393 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQkHAQBBAAsBAAoVAgQAIAALDgACfwRAC0EAEQAAGgsL +invalid invalid if.wast:1409 AGFzbQEAAAABBAFgAAADAgEACg4BDAEBfwRACyEAIAAaCw== +invalid invalid if.wast:1418 AGFzbQEAAAABBAFgAAADAgEACgwBCgEBfwRACyIAGgs= +invalid invalid if.wast:1427 AGFzbQEAAAABBAFgAAADAgEABgYBfwFBAAsKDAEKAARACyQAIwAaCw== +invalid invalid if.wast:1436 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIAARAC0AAGgs= +invalid invalid if.wast:1445 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJAARACygCABoL +invalid invalid if.wast:1454 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDAEKAARAC0EBNgIACw== +invalid invalid if.wast:1464 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoKAQgAQQEEARoLCw== +invalid invalid if.wast:1470 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKCwEJAEEBBAEaGgsL +invalid invalid if.wast:1476 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoPAQ0AQwAAAABBAQQBGgsL +invalid invalid if.wast:1482 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKEAEOAEMAAAAAQQEEARoaCws= +invalid invalid if.wast:1488 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoNAQsAAkBBAQQBGgsLCw== +invalid invalid if.wast:1494 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKDgEMAAJAQQEEARoaCwsL +invalid invalid if.wast:1500 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoSARAAAkBDAAAAAEEBBAEaCwsL +invalid invalid if.wast:1506 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKEwERAAJAQwAAAABBAQQBGhoLCws= +valid valid imports.wast:3 AGFzbQEAAAABHgdgAABgAX8AYAF9AGAAAX9gAAF9YAF/AX9gAX4BfgMIBwABAgMEBQYECAJwAApwAQoUBQMBAAIGFAN/AEE3C30AQwAAMEILfgFCwgALB60BDQRmdW5jAAAIZnVuYy1pMzIAAQhmdW5jLWYzMgACCWZ1bmMtPmkzMgADCWZ1bmMtPmYzMgAEDWZ1bmMtaTMyLT5pMzIABQ1mdW5jLWk2NC0+aTY0AAYKZ2xvYmFsLWkzMgMACmdsb2JhbC1mMzIDAQ5nbG9iYWwtbXV0LWk2NAMCDHRhYmxlLTEwLWluZgEAC3RhYmxlLTEwLTIwAQEMbWVtb3J5LTItaW5mAgAKIQcCAAsCAAsCAAsEAEEWCwcAQwAAMEELBAAgAAsEACAACw== +valid valid imports.wast:26 AGFzbQEAAAABJAhgAX8AYAF+AGABfQBgAXwAYAF/AGACf30AYAJ8fABgAX4BfgKDAxIIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTY0AAEIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTY0AAEIc3BlY3Rlc3QJcHJpbnRfZjMyAAIIc3BlY3Rlc3QJcHJpbnRfZjY0AAMIc3BlY3Rlc3QNcHJpbnRfaTMyX2YzMgAFCHNwZWN0ZXN0DXByaW50X2Y2NF9mNjQABghzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9mNjQAAwR0ZXN0DWZ1bmMtaTY0LT5pNjQABwhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIAAAhzcGVjdGVzdAlwcmludF9pMzIABAhzcGVjdGVzdAlwcmludF9pMzIABAMDAgABBAUBcAECAgczCAJwMQALAnAyAAwCcDMADQJwNAANAnA1AA4CcDYADwdwcmludDMyABIHcHJpbnQ2NAATCQgBAEEACwICBQpoAiwBAX0gALIhASAAEAAgAEEBakMAAChCEAYgABACIAAQCCABEAQgAEEAEQAACzkBAXwgABAKuSEBIAAQASABRAAAAAAAAPA/oEQAAAAAAIBKQBAHIAAQAyABEAUgARAJIAFBAREDAAs= +invalid invalid imports.wast:89 AGFzbQEAAAABBQFgAAF/Ag0BBHRlc3QEZnVuYwAB +valid valid imports.wast:97 AGFzbQEAAAABBQFgAX8AAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAAcNAQlwcmludF9pMzIAAQoIAQYAIAAQAAs= +valid valid imports.wast:107 AGFzbQEAAAABCwJgAX8AYAJ/fwF/AhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQcNAQlwcmludF9pMzIAAQoJAQcAIAAgAWoL +valid valid imports.wast:116 AGFzbQEAAAABBAFgAAACDQEEdGVzdARmdW5jAAA= +valid valid imports.wast:117 AGFzbQEAAAABBQFgAX8AAhEBBHRlc3QIZnVuYy1pMzIAAA== +valid valid imports.wast:118 AGFzbQEAAAABBQFgAX0AAhEBBHRlc3QIZnVuYy1mMzIAAA== +valid valid imports.wast:119 AGFzbQEAAAABBQFgAAF/AhIBBHRlc3QJZnVuYy0+aTMyAAA= +valid valid imports.wast:120 AGFzbQEAAAABBQFgAAF9AhIBBHRlc3QJZnVuYy0+ZjMyAAA= +valid valid imports.wast:121 AGFzbQEAAAABBgFgAX8BfwIWAQR0ZXN0DWZ1bmMtaTMyLT5pMzIAAA== +valid valid imports.wast:122 AGFzbQEAAAABBgFgAX4BfgIWAQR0ZXN0DWZ1bmMtaTY0LT5pNjQAAA== +valid valid imports.wast:125 AGFzbQEAAAABBAFgAAACEAEEdGVzdAd1bmtub3duAAA= +valid valid imports.wast:129 AGFzbQEAAAABBAFgAAACFAEIc3BlY3Rlc3QHdW5rbm93bgAA +valid valid imports.wast:134 AGFzbQEAAAABBQFgAX8AAg0BBHRlc3QEZnVuYwAA +valid valid imports.wast:138 AGFzbQEAAAABBQFgAAF/Ag0BBHRlc3QEZnVuYwAA +valid valid imports.wast:142 AGFzbQEAAAABBgFgAX8BfwINAQR0ZXN0BGZ1bmMAAA== +valid valid imports.wast:146 AGFzbQEAAAABBAFgAAACEQEEdGVzdAhmdW5jLWkzMgAA +valid valid imports.wast:150 AGFzbQEAAAABBQFgAAF/AhEBBHRlc3QIZnVuYy1pMzIAAA== +valid valid imports.wast:154 AGFzbQEAAAABBQFgAX0AAhEBBHRlc3QIZnVuYy1pMzIAAA== +valid valid imports.wast:158 AGFzbQEAAAABBQFgAX4AAhEBBHRlc3QIZnVuYy1pMzIAAA== +valid valid imports.wast:162 AGFzbQEAAAABBgFgAX8BfwIRAQR0ZXN0CGZ1bmMtaTMyAAA= +valid valid imports.wast:166 AGFzbQEAAAABBAFgAAACEgEEdGVzdAlmdW5jLT5pMzIAAA== +valid valid imports.wast:170 AGFzbQEAAAABBQFgAX8AAhIBBHRlc3QJZnVuYy0+aTMyAAA= +valid valid imports.wast:174 AGFzbQEAAAABBQFgAAF9AhIBBHRlc3QJZnVuYy0+aTMyAAA= +valid valid imports.wast:178 AGFzbQEAAAABBQFgAAF+AhIBBHRlc3QJZnVuYy0+aTMyAAA= +valid valid imports.wast:182 AGFzbQEAAAABBgFgAX8BfwISAQR0ZXN0CWZ1bmMtPmkzMgAA +valid valid imports.wast:186 AGFzbQEAAAABBAFgAAACFgEEdGVzdA1mdW5jLWkzMi0+aTMyAAA= +valid valid imports.wast:190 AGFzbQEAAAABBQFgAX8AAhYBBHRlc3QNZnVuYy1pMzItPmkzMgAA +valid valid imports.wast:194 AGFzbQEAAAABBQFgAAF/AhYBBHRlc3QNZnVuYy1pMzItPmkzMgAA +valid valid imports.wast:199 AGFzbQEAAAABBQFgAAF/AhMBBHRlc3QKZ2xvYmFsLWkzMgAA +valid valid imports.wast:203 AGFzbQEAAAABBAFgAAACFQEEdGVzdAx0YWJsZS0xMC1pbmYAAA== +valid valid imports.wast:207 AGFzbQEAAAABBAFgAAACFQEEdGVzdAxtZW1vcnktMi1pbmYAAA== +valid valid imports.wast:211 AGFzbQEAAAABBAFgAAACFwEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgAA +valid valid imports.wast:215 AGFzbQEAAAABBAFgAAACEgEIc3BlY3Rlc3QFdGFibGUAAA== +valid valid imports.wast:219 AGFzbQEAAAABBAFgAAACEwEIc3BlY3Rlc3QGbWVtb3J5AAA= +valid valid imports.wast:226 AGFzbQEAAAABEQRgAAF/YAABfmAAAX1gAAF8AqIBBwhzcGVjdGVzdApnbG9iYWxfaTMyA38ACHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwAIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdApnbG9iYWxfaTMyA38ACHNwZWN0ZXN0Cmdsb2JhbF9pNjQDfgAIc3BlY3Rlc3QKZ2xvYmFsX2YzMgN9AAhzcGVjdGVzdApnbG9iYWxfZjY0A3wAAwgHAAAAAAECAwc5BwVnZXQtMAAABWdldC0xAAEFZ2V0LXgAAgVnZXQteQADBWdldC00AAQFZ2V0LTUABQVnZXQtNgAGCiQHBAAjAAsEACMBCwQAIwILBAAjAwsEACMECwQAIwULBAAjBgs= +valid valid imports.wast:254 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38A +valid valid imports.wast:255 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA30A +valid valid imports.wast:256 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN+AQ== +valid valid imports.wast:259 AGFzbQEAAAACEQEEdGVzdAd1bmtub3duA38A +valid valid imports.wast:263 AGFzbQEAAAACFQEIc3BlY3Rlc3QHdW5rbm93bgN/AA== +valid valid imports.wast:268 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA34A +valid valid imports.wast:272 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA30A +valid valid imports.wast:276 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA3wA +valid valid imports.wast:280 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyA38B +valid valid imports.wast:284 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA38A +valid valid imports.wast:288 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA34A +valid valid imports.wast:292 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA3wA +valid valid imports.wast:296 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtZjMyA30B +valid valid imports.wast:300 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN/AQ== +valid valid imports.wast:304 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN9AQ== +valid valid imports.wast:308 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN8AQ== +valid valid imports.wast:312 AGFzbQEAAAACGAEEdGVzdA5nbG9iYWwtbXV0LWk2NAN+AA== +valid valid imports.wast:317 AGFzbQEAAAACDgEEdGVzdARmdW5jA38A +valid valid imports.wast:321 AGFzbQEAAAACFgEEdGVzdAx0YWJsZS0xMC1pbmYDfwA= +valid valid imports.wast:325 AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYDfwA= +valid valid imports.wast:329 AGFzbQEAAAACFwEIc3BlY3Rlc3QJcHJpbnRfaTMyA38A +valid valid imports.wast:333 AGFzbQEAAAACEwEIc3BlY3Rlc3QFdGFibGUDfwA= +valid valid imports.wast:337 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5A38A +valid valid imports.wast:344 AGFzbQEAAAABCgJgAAF/YAF/AX8CFQEIc3BlY3Rlc3QFdGFibGUBcAEKFAMEAwEAAAcIAQRjYWxsAAAJCAEAQQELAgECChMDBwAgABEAAAsEAEELCwQAQRYL +valid valid imports.wast:381 AGFzbQEAAAACJwIIc3BlY3Rlc3QFdGFibGUBcAAACHNwZWN0ZXN0BXRhYmxlAXAAAAQHAnAACnAACg== +valid valid imports.wast:388 AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAK +valid valid imports.wast:389 AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAF +valid valid imports.wast:390 AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAA +valid valid imports.wast:391 AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAo= +valid valid imports.wast:392 AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAU= +valid valid imports.wast:393 AGFzbQEAAAACFgEEdGVzdAt0YWJsZS0xMC0yMAFwAAA= +valid valid imports.wast:394 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoU +valid valid imports.wast:395 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQUU +valid valid imports.wast:396 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQAU +valid valid imports.wast:397 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoZ +valid valid imports.wast:398 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQUZ +valid valid imports.wast:399 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQAZ +valid valid imports.wast:400 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAK +valid valid imports.wast:401 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAF +valid valid imports.wast:402 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAA +valid valid imports.wast:403 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKFA== +valid valid imports.wast:404 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEFFA== +valid valid imports.wast:405 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEAFA== +valid valid imports.wast:406 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKGQ== +valid valid imports.wast:407 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEFGQ== +valid valid imports.wast:410 AGFzbQEAAAACEgEEdGVzdAd1bmtub3duAXAACg== +valid valid imports.wast:414 AGFzbQEAAAACFgEIc3BlY3Rlc3QHdW5rbm93bgFwAAo= +valid valid imports.wast:419 AGFzbQEAAAACFwEEdGVzdAx0YWJsZS0xMC1pbmYBcAAM +valid valid imports.wast:423 AGFzbQEAAAACGAEEdGVzdAx0YWJsZS0xMC1pbmYBcAEKFA== +valid valid imports.wast:427 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQwU +valid valid imports.wast:431 AGFzbQEAAAACFwEEdGVzdAt0YWJsZS0xMC0yMAFwAQoS +valid valid imports.wast:435 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAM +valid valid imports.wast:439 AGFzbQEAAAACFQEIc3BlY3Rlc3QFdGFibGUBcAEKDw== +valid valid imports.wast:444 AGFzbQEAAAACDwEEdGVzdARmdW5jAXAACg== +valid valid imports.wast:448 AGFzbQEAAAACFQEEdGVzdApnbG9iYWwtaTMyAXAACg== +valid valid imports.wast:452 AGFzbQEAAAACFwEEdGVzdAxtZW1vcnktMi1pbmYBcAAK +valid valid imports.wast:456 AGFzbQEAAAACGAEIc3BlY3Rlc3QJcHJpbnRfaTMyAXAACg== +valid valid imports.wast:464 AGFzbQEAAAABBgFgAX8BfwIVAQhzcGVjdGVzdAZtZW1vcnkCAQECAwIBAAcIAQRsb2FkAAAKCQEHACAAKAIACwsHAQBBCgsBEA== +invalid valid imports.wast:488 AGFzbQEAAAACCwIAAAIAAQAAAgAB +invalid valid imports.wast:492 AGFzbQEAAAACBgEAAAIAAQUDAQAA +invalid valid imports.wast:496 AGFzbQEAAAAFBQIAAAAA +valid valid imports.wast:500 AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAI= +valid valid imports.wast:501 AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAE= +valid valid imports.wast:502 AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAA= +valid valid imports.wast:503 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAB +valid valid imports.wast:504 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAA +valid valid imports.wast:505 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAg== +valid valid imports.wast:506 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAg== +valid valid imports.wast:507 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAw== +valid valid imports.wast:508 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEAAw== +valid valid imports.wast:511 AGFzbQEAAAACEQEEdGVzdAd1bmtub3duAgAB +valid valid imports.wast:515 AGFzbQEAAAACFQEIc3BlY3Rlc3QHdW5rbm93bgIAAQ== +valid valid imports.wast:520 AGFzbQEAAAACFgEEdGVzdAxtZW1vcnktMi1pbmYCAAM= +valid valid imports.wast:524 AGFzbQEAAAACFwEEdGVzdAxtZW1vcnktMi1pbmYCAQID +valid valid imports.wast:528 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAC +valid valid imports.wast:532 AGFzbQEAAAACFQEIc3BlY3Rlc3QGbWVtb3J5AgEBAQ== +valid valid imports.wast:537 AGFzbQEAAAACEgEEdGVzdAhmdW5jLWkzMgIAAQ== +valid valid imports.wast:541 AGFzbQEAAAACFAEEdGVzdApnbG9iYWwtaTMyAgAB +valid valid imports.wast:545 AGFzbQEAAAACFgEEdGVzdAx0YWJsZS0xMC1pbmYCAAE= +valid valid imports.wast:549 AGFzbQEAAAACFwEIc3BlY3Rlc3QJcHJpbnRfaTMyAgAB +valid valid imports.wast:553 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgIAAQ== +valid valid imports.wast:557 AGFzbQEAAAACEwEIc3BlY3Rlc3QFdGFibGUCAAE= +valid valid imports.wast:570 AGFzbQEAAAABBgFgAX8BfwIVAQhzcGVjdGVzdAZtZW1vcnkCAQADAwIBAAcIAQRncm93AAAKCAEGACAAQAAL +valid valid imports.wast:657 AGFzbQEAAAABKQpgAABgAX8AYAJ/fwBgAX4AYAF9AGABfABgAAF/YAABfmAAAX1gAAF8AugCEAhub3Qgd2FzbQpvdmVybG9hZGVkAAAIbm90IHdhc20Kb3ZlcmxvYWRlZAABCG5vdCB3YXNtCm92ZXJsb2FkZWQAAghub3Qgd2FzbQpvdmVybG9hZGVkAAMIbm90IHdhc20Kb3ZlcmxvYWRlZAAECG5vdCB3YXNtCm92ZXJsb2FkZWQABQhub3Qgd2FzbQpvdmVybG9hZGVkAAYIbm90IHdhc20Kb3ZlcmxvYWRlZAAHCG5vdCB3YXNtCm92ZXJsb2FkZWQACAhub3Qgd2FzbQpvdmVybG9hZGVkAAkIbm90IHdhc20Kb3ZlcmxvYWRlZAN/AAhub3Qgd2FzbQpvdmVybG9hZGVkA34ACG5vdCB3YXNtCm92ZXJsb2FkZWQDfQAIbm90IHdhc20Kb3ZlcmxvYWRlZAN8AAhub3Qgd2FzbQpvdmVybG9hZGVkAXAAAAhub3Qgd2FzbQpvdmVybG9hZGVkAgAA +valid valid inline-module.wast:1 AGFzbQEAAAABBAFgAAADAwIAAAUDAQAABwUBAWYAAQoHAgIACwIACw== +valid valid int_exprs.wast:6 AGFzbQEAAAABDQJgAn9/AX9gAn5+AX8DBQQAAAEBB20EGGkzMi5ub19mb2xkX2NtcF9zX29mZnNldAAAGGkzMi5ub19mb2xkX2NtcF91X29mZnNldAABGGk2NC5ub19mb2xkX2NtcF9zX29mZnNldAACGGk2NC5ub19mb2xkX2NtcF91X29mZnNldAADCjkEDQAgAEEBaiABQQFqSAsNACAAQQFqIAFBAWpJCw0AIABCAXwgAUIBfFMLDQAgAEIBfCABQgF8VAs= +valid valid int_exprs.wast:25 AGFzbQEAAAABBgFgAX4BfgMCAQAHHQEZaTY0Lm5vX2ZvbGRfd3JhcF9leHRlbmRfcwAACggBBgAgAKesCw== +valid valid int_exprs.wast:35 AGFzbQEAAAABBgFgAX4BfgMCAQAHHQEZaTY0Lm5vX2ZvbGRfd3JhcF9leHRlbmRfdQAACggBBgAgAKetCw== +valid valid int_exprs.wast:44 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9zaGxfc2hyX3MAABVpMzIubm9fZm9sZF9zaGxfc2hyX3UAARVpNjQubm9fZm9sZF9zaGxfc2hyX3MAAhVpNjQubm9fZm9sZF9zaGxfc2hyX3UAAwotBAoAIABBAXRBAXULCgAgAEEBdEEBdgsKACAAQgGGQgGHCwoAIABCAYZCAYgL +valid valid int_exprs.wast:63 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9zaHJfc19zaGwAABVpMzIubm9fZm9sZF9zaHJfdV9zaGwAARVpNjQubm9fZm9sZF9zaHJfc19zaGwAAhVpNjQubm9fZm9sZF9zaHJfdV9zaGwAAwotBAoAIABBAXVBAXQLCgAgAEEBdkEBdAsKACAAQgGHQgGGCwoAIABCAYhCAYYL +valid valid int_exprs.wast:82 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9kaXZfc19tdWwAABVpMzIubm9fZm9sZF9kaXZfdV9tdWwAARVpNjQubm9fZm9sZF9kaXZfc19tdWwAAhVpNjQubm9fZm9sZF9kaXZfdV9tdWwAAwotBAoAIABBBm1BBmwLCgAgAEEGbkEGbAsKACAAQgZ/QgZ+CwoAIABCBoBCBn4L +valid valid int_exprs.wast:101 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdlBBZpMzIubm9fZm9sZF9kaXZfc19zZWxmAAAWaTMyLm5vX2ZvbGRfZGl2X3Vfc2VsZgABFmk2NC5ub19mb2xkX2Rpdl9zX3NlbGYAAhZpNjQubm9fZm9sZF9kaXZfdV9zZWxmAAMKIQQHACAAIABtCwcAIAAgAG4LBwAgACAAfwsHACAAIACACw== +valid valid int_exprs.wast:120 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdlBBZpMzIubm9fZm9sZF9yZW1fc19zZWxmAAAWaTMyLm5vX2ZvbGRfcmVtX3Vfc2VsZgABFmk2NC5ub19mb2xkX3JlbV9zX3NlbGYAAhZpNjQubm9fZm9sZF9yZW1fdV9zZWxmAAMKIQQHACAAIABvCwcAIAAgAHALBwAgACAAgQsHACAAIACCCw== +valid valid int_exprs.wast:139 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQdhBBVpMzIubm9fZm9sZF9tdWxfZGl2X3MAABVpMzIubm9fZm9sZF9tdWxfZGl2X3UAARVpNjQubm9fZm9sZF9tdWxfZGl2X3MAAhVpNjQubm9fZm9sZF9tdWxfZGl2X3UAAwotBAoAIABBBmxBBm0LCgAgAEEGbEEGbgsKACAAQgZ+QgZ/CwoAIABCBn5CBoAL +valid valid int_exprs.wast:158 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLQITaTMyLm5vX2ZvbGRfZGl2X3NfMgAAE2k2NC5ub19mb2xkX2Rpdl9zXzIAAQoRAgcAIABBAm0LBwAgAEICfws= +valid valid int_exprs.wast:171 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLQITaTMyLm5vX2ZvbGRfcmVtX3NfMgAAE2k2NC5ub19mb2xkX3JlbV9zXzIAAQoRAgcAIABBAm8LBwAgAEICgQs= +valid valid int_exprs.wast:184 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfMAAAC2kzMi5kaXZfdV8wAAELaTY0LmRpdl9zXzAAAgtpNjQuZGl2X3VfMAADCiEEBwAgAEEAbQsHACAAQQBuCwcAIABCAH8LBwAgAEIAgAs= +valid valid int_exprs.wast:203 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfMwAAC2kzMi5kaXZfdV8zAAELaTY0LmRpdl9zXzMAAgtpNjQuZGl2X3VfMwADCiEEBwAgAEEDbQsHACAAQQNuCwcAIABCA38LBwAgAEIDgAs= +valid valid int_exprs.wast:226 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfNQAAC2kzMi5kaXZfdV81AAELaTY0LmRpdl9zXzUAAgtpNjQuZGl2X3VfNQADCiEEBwAgAEEFbQsHACAAQQVuCwcAIABCBX8LBwAgAEIFgAs= +valid valid int_exprs.wast:249 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIuZGl2X3NfNwAAC2kzMi5kaXZfdV83AAELaTY0LmRpdl9zXzcAAgtpNjQuZGl2X3VfNwADCiEEBwAgAEEHbQsHACAAQQduCwcAIABCB38LBwAgAEIHgAs= +valid valid int_exprs.wast:272 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfMwAAC2kzMi5yZW1fdV8zAAELaTY0LnJlbV9zXzMAAgtpNjQucmVtX3VfMwADCiEEBwAgAEEDbwsHACAAQQNwCwcAIABCA4ELBwAgAEIDggs= +valid valid int_exprs.wast:295 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfNQAAC2kzMi5yZW1fdV81AAELaTY0LnJlbV9zXzUAAgtpNjQucmVtX3VfNQADCiEEBwAgAEEFbwsHACAAQQVwCwcAIABCBYELBwAgAEIFggs= +valid valid int_exprs.wast:318 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwUEAAABAQc5BAtpMzIucmVtX3NfNwAAC2kzMi5yZW1fdV83AAELaTY0LnJlbV9zXzcAAgtpNjQucmVtX3VfNwADCiEEBwAgAEEHbwsHACAAQQdwCwcAIABCB4ELBwAgAEIHggs= +valid valid int_exprs.wast:341 AGFzbQEAAAABCwJgAX8Bf2ABfgF+AwMCAAEHLwIUaTMyLm5vX2ZvbGRfZGl2X25lZzEAABRpNjQubm9fZm9sZF9kaXZfbmVnMQABChECBwAgAEF/bQsHACAAQn9/Cw== +valid valid int_literals.wast:1 AGFzbQEAAAABCQJgAAF/YAABfgMfHgAAAAAAAAAAAAAAAQEBAQEBAQEBAQEAAAAAAQEBAQe3Ax4IaTMyLnRlc3QAAAhpMzIudW1heAABCGkzMi5zbWF4AAIMaTMyLm5lZ19zbWF4AAMIaTMyLnNtaW4ABAxpMzIuYWx0X3NtaW4ABQxpMzIuaW5jX3NtaW4ABgxpMzIubmVnX3plcm8ABw1pMzIubm90X29jdGFsAAgUaTMyLnVuc2lnbmVkX2RlY2ltYWwACQ1pMzIucGx1c19zaWduAAoIaTY0LnRlc3QACwhpNjQudW1heAAMCGk2NC5zbWF4AA0MaTY0Lm5lZ19zbWF4AA4IaTY0LnNtaW4ADwxpNjQuYWx0X3NtaW4AEAxpNjQuaW5jX3NtaW4AEQxpNjQubmVnX3plcm8AEg1pNjQubm90X29jdGFsABMUaTY0LnVuc2lnbmVkX2RlY2ltYWwAFA1pNjQucGx1c19zaWduABUMaTMyLWRlYy1zZXAxABYMaTMyLWRlYy1zZXAyABcMaTMyLWhleC1zZXAxABgMaTMyLWhleC1zZXAyABkMaTY0LWRlYy1zZXAxABoMaTY0LWRlYy1zZXAyABsMaTY0LWhleC1zZXAxABwMaTY0LWhleC1zZXAyAB0KlQIeCQBBjaC33QAPCwUAQX8PCwkAQf////8HDwsJAEGBgICAeA8LCQBBgICAgHgPCwkAQYCAgIB4DwsMAEGAgICAeEEBag8LBQBBAA8LBQBBCg8LBQBBfw8LBQBBKg8LDQBC7tSZ3eDN7tUMDwsFAEJ/DwsOAEL///////////8ADwsOAEKBgICAgICAgIB/DwsOAEKAgICAgICAgIB/DwsOAEKAgICAgICAgIB/DwsRAEKAgICAgICAgIB/QgF8DwsFAEIADwsFAEIKDwsFAEJ/DwsFAEIqDwsGAEHAhD0LBQBB6AcLCABBmYG80AALBgBBj9QGCwYAQsCEPQsFAELoBwsLAEKZs4KA8IG8BQsGAEKP1AYL +valid valid labels.wast:1 AGFzbQEAAAABCgJgAAF/YAF/AX8DExIAAAAAAQAAAAABAQAAAAAAAAAHmgESBWJsb2NrAAAFbG9vcDEAAQVsb29wMgACBWxvb3AzAAMFbG9vcDQABAVsb29wNQAFBWxvb3A2AAYCaWYABwNpZjIACAZzd2l0Y2gACQZyZXR1cm4ACgZicl9pZjAACwZicl9pZjEADAZicl9pZjIADQZicl9pZjMADgJicgAPCXNoYWRvd2luZwAQDHJlZGVmaW5pdGlvbgARCoMGEgsAAn9BAQwAQQALCyMBAX9BACEAAn8DfyAAQQFqIQAgAEEFRgRAIAAMAgsMAAsLCzQBAX9BACEAAn8DfyAAQQFqIQAgAEEFRgRADAELIABBCEYEQCAADAILIABBAWohAAwACwsLIwEBf0EAIQACfwN/IABBAWohACAAQQVGBEAgAAwCCyAACwsLIwEBf0EBIQECfwN/IAEgAWohASABIABLBEAgAQwCCwwACwsLCgADf0EBC0EBagsLAAN/QQANAEEDCwuEAQEBf0EAIQACQEEBBEAMAEGaBSEACyAAQQFqIQBBAQRADABBmgUhAAVB+AYhAAsgAEEBaiEAQQEEQAwAQZoFIQAFQfgGIQALIABBAWohAEEABEBB+AYhAAUMAEGaBSEACyAAQQFqIQBBAARAQfgGIQAFDABBmgUhAAsgAEEBaiEACyAAC4QBAQF/QQAhAAJAQQEEQAwAQZoFIQALIABBAWohAEEBBEAMAEGaBSEABUH4BiEACyAAQQFqIQBBAQRADABBmgUhAAVB+AYhAAsgAEEBaiEAQQAEQEH4BiEABQwAQZoFIQALIABBAWohAEEABEBB+AYhAAUMAEGaBSEACyAAQQFqIQALIAALLQACf0EKAn8CQAJAAkACQAJAIAAOBAQAAQIDCwtBAgwDC0EDDAMLC0EFC2wLCxgAAkACQAJAIAAOAQABDAILQQAPCwtBAgtWAQF/QQAhAAJ/AkBBAA0AIABBAXIhAEEBDQAgAEECciEACwJ/IABBBHIhACAAC0EADQAaIABBCHIhAAJ/IABBEHIhACAAC0EBDQAaIABBIHIhACAACwsTAAJ/An9BAQwAC0EBDQAaQQALCxgAAn9BAQRAAn9BAQwAC0EBDQEaC0EACwskAQF/An8Cf0EBIQAgAAsCf0ECIQAgAAsNABpBAAtBAGoaIAALIQACf0EBBEACf0EBDAALDAEFAkACf0EBDAALGgsLQQELCwwAAn9BAQwAQQJzCwsSAAJ/An9BAgsCf0EDDAALagsL +invalid invalid labels.wast:318 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEBDQCMAQsL +invalid invalid labels.wast:322 AGFzbQEAAAABBAFgAAADAgEAChABDgACQEMAAAAAQQENAAsL +valid valid left-to-right.wast:1 AGFzbQEAAAABQA1gAn9/AX9gAn5+AX9gAn19AX9gAnx8AX9gAABgAAF/YAABfmAAAX1gAAF8YAJ/fwBgAn5+AGACfX0AYAJ8fAADhAGCAQAAAQECAgMDBAQFBQUFBQUGBgYFBQcHBwUFCAgIBQUJCgsMBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEBQFwAQgIBQMBAAEHqghfB2kzMl9hZGQAIwdpMzJfc3ViACQHaTMyX211bAAlCWkzMl9kaXZfcwAmCWkzMl9kaXZfdQAnCWkzMl9yZW1fcwAoCWkzMl9yZW1fdQApB2kzMl9hbmQAKgZpMzJfb3IAKwdpMzJfeG9yACwHaTMyX3NobAAtCWkzMl9zaHJfdQAuCWkzMl9zaHJfcwAvBmkzMl9lcQAwBmkzMl9uZQAxCGkzMl9sdF9zADIIaTMyX2xlX3MAMwhpMzJfbHRfdQA0CGkzMl9sZV91ADUIaTMyX2d0X3MANghpMzJfZ2VfcwA3CGkzMl9ndF91ADgIaTMyX2dlX3UAOQlpMzJfc3RvcmUAOgppMzJfc3RvcmU4ADsLaTMyX3N0b3JlMTYAPAhpMzJfY2FsbAA9EWkzMl9jYWxsX2luZGlyZWN0AD4KaTMyX3NlbGVjdAA/B2k2NF9hZGQAQAdpNjRfc3ViAEEHaTY0X211bABCCWk2NF9kaXZfcwBDCWk2NF9kaXZfdQBECWk2NF9yZW1fcwBFCWk2NF9yZW1fdQBGB2k2NF9hbmQARwZpNjRfb3IASAdpNjRfeG9yAEkHaTY0X3NobABKCWk2NF9zaHJfdQBLCWk2NF9zaHJfcwBMBmk2NF9lcQBNBmk2NF9uZQBOCGk2NF9sdF9zAE8IaTY0X2xlX3MAUAhpNjRfbHRfdQBRCGk2NF9sZV91AFIIaTY0X2d0X3MAUwhpNjRfZ2VfcwBUCGk2NF9ndF91AFUIaTY0X2dlX3UAVglpNjRfc3RvcmUAVwppNjRfc3RvcmU4AFgLaTY0X3N0b3JlMTYAWQtpNjRfc3RvcmUzMgBaCGk2NF9jYWxsAFsRaTY0X2NhbGxfaW5kaXJlY3QAXAppNjRfc2VsZWN0AF0HZjMyX2FkZABeB2YzMl9zdWIAXwdmMzJfbXVsAGAHZjMyX2RpdgBhDGYzMl9jb3B5c2lnbgBiBmYzMl9lcQBjBmYzMl9uZQBkBmYzMl9sdABlBmYzMl9sZQBmBmYzMl9ndABnBmYzMl9nZQBoB2YzMl9taW4AaQdmMzJfbWF4AGoJZjMyX3N0b3JlAGsIZjMyX2NhbGwAbBFmMzJfY2FsbF9pbmRpcmVjdABtCmYzMl9zZWxlY3QAbgdmNjRfYWRkAG8HZjY0X3N1YgBwB2Y2NF9tdWwAcQdmNjRfZGl2AHIMZjY0X2NvcHlzaWduAHMGZjY0X2VxAHQGZjY0X25lAHUGZjY0X2x0AHYGZjY0X2xlAHcGZjY0X2d0AHgGZjY0X2dlAHkHZjY0X21pbgB6B2Y2NF9tYXgAewlmNjRfc3RvcmUAfAhmNjRfY2FsbAB9EWY2NF9jYWxsX2luZGlyZWN0AH4KZjY0X3NlbGVjdAB/BWJyX2lmAIABCGJyX3RhYmxlAIEBCQ4BAEEACwgAAQIDBAUGBwqqDYIBBABBfwsEAEF+CwQAQX8LBABBfgsEAEF/CwQAQX4LBABBfwsEAEF+CwkAQQhBADYCAAsnAEELQQotAAA6AABBCkEJLQAAOgAAQQlBCC0AADoAAEEIQX06AAALBwBBCCgCAAsNABAJQQhBAToAAEEACw0AEAlBCEECOgAAQQELDQAQCUEIQQM6AABBAQsNABAJQQhBBDoAAEEACw0AEAlBCEEFOgAAQQALDQAQCUEIQQE6AABCAAsNABAJQQhBAjoAAEIBCw0AEAlBCEEDOgAAQgELDQAQCUEIQQQ6AABBAgsNABAJQQhBBToAAEEACxAAEAlBCEEBOgAAQwAAAAALEAAQCUEIQQI6AABDAACAPwsQABAJQQhBAzoAAEMAAIA/Cw0AEAlBCEEEOgAAQQQLDQAQCUEIQQU6AABBAAsUABAJQQhBAToAAEQAAAAAAAAAAAsUABAJQQhBAjoAAEQAAAAAAADwPwsUABAJQQhBAzoAAEQAAAAAAADwPwsNABAJQQhBBDoAAEEGCw0AEAlBCEEFOgAAQQALAgALAgALAgALAgALDAAQCBALEAxqGhAKCwwAEAgQCxAMaxoQCgsMABAIEAsQDGwaEAoLDAAQCBALEAxtGhAKCwwAEAgQCxAMbhoQCgsMABAIEAsQDG8aEAoLDAAQCBALEAxwGhAKCwwAEAgQCxAMcRoQCgsMABAIEAsQDHIaEAoLDAAQCBALEAxzGhAKCwwAEAgQCxAMdBoQCgsMABAIEAsQDHYaEAoLDAAQCBALEAx1GhAKCwwAEAgQCxAMRhoQCgsMABAIEAsQDEcaEAoLDAAQCBALEAxIGhAKCwwAEAgQCxAMTBoQCgsMABAIEAsQDEkaEAoLDAAQCBALEAxNGhAKCwwAEAgQCxAMShoQCgsMABAIEAsQDE4aEAoLDAAQCBALEAxLGhAKCwwAEAgQCxAMTxoQCgsNABAIEAsQDDYCABAKCw0AEAgQCxAMOgAAEAoLDQAQCBALEAw7AQAQCgsMABAIEAsQDBAfEAoLEAAQCBALEAwQDhEAABoQCgsOABAIEAsQDBAPGxoQCgsMABAIEBAQEXwaEAoLDAAQCBAQEBF9GhAKCwwAEAgQEBARfhoQCgsMABAIEBAQEX8aEAoLDAAQCBAQEBGAGhAKCwwAEAgQEBARgRoQCgsMABAIEBAQEYIaEAoLDAAQCBAQEBGDGhAKCwwAEAgQEBARhBoQCgsMABAIEBAQEYUaEAoLDAAQCBAQEBGGGhAKCwwAEAgQEBARiBoQCgsMABAIEBAQEYcaEAoLDAAQCBAQEBFRGhAKCwwAEAgQEBARUhoQCgsMABAIEBAQEVMaEAoLDAAQCBAQEBFXGhAKCwwAEAgQEBARVBoQCgsMABAIEBAQEVgaEAoLDAAQCBAQEBFVGhAKCwwAEAgQEBARWRoQCgsMABAIEBAQEVYaEAoLDAAQCBAQEBFaGhAKCw0AEAgQCxARNwMAEAoLDQAQCBALEBE8AAAQCgsNABAIEAsQET0BABAKCw0AEAgQCxARPgIAEAoLDAAQCBAQEBEQIBAKCxAAEAgQEBAREBMRAQAaEAoLDgAQCBAQEBEQFBsaEAoLDAAQCBAVEBaSGhAKCwwAEAgQFRAWkxoQCgsMABAIEBUQFpQaEAoLDAAQCBAVEBaVGhAKCwwAEAgQFRAWmBoQCgsMABAIEBUQFlsaEAoLDAAQCBAVEBZcGhAKCwwAEAgQFRAWXRoQCgsMABAIEBUQFl8aEAoLDAAQCBAVEBZeGhAKCwwAEAgQFRAWYBoQCgsMABAIEBUQFpYaEAoLDAAQCBAVEBaXGhAKCw0AEAgQCxAWOAIAEAoLDAAQCBAVEBYQIRAKCxAAEAgQFRAWEBgRAgAaEAoLDgAQCBAVEBYQGRsaEAoLDAAQCBAaEBugGhAKCwwAEAgQGhAboRoQCgsMABAIEBoQG6IaEAoLDAAQCBAaEBujGhAKCwwAEAgQGhAbphoQCgsMABAIEBoQG2EaEAoLDAAQCBAaEBtiGhAKCwwAEAgQGhAbYxoQCgsMABAIEBoQG2UaEAoLDAAQCBAaEBtkGhAKCwwAEAgQGhAbZhoQCgsMABAIEBoQG6QaEAoLDAAQCBAaEBulGhAKCw0AEAgQCxAbOQMAEAoLDAAQCBAaEBsQIhAKCxAAEAgQGhAbEB0RAwAaEAoLDgAQCBAaEBsQHhsaEAoLEwACfxAIEAsQDEEAcQ0AGhAKCwsVAAJ/EAgCfxALEAwOAQEACxoQCgsL +valid valid linking.wast:3 AGFzbQEAAAABBQFgAAF/AwMCAAAHCAEEY2FsbAAACgsCBAAQAQsEAEECCw== +valid valid linking.wast:9 AGFzbQEAAAABBQFgAAF/AgsBAk1mBGNhbGwAAAMEAwAAAAchAwdNZi5jYWxsAAAMY2FsbCBNZi5jYWxsAAEEY2FsbAACChADBAAQAAsEABADCwQAQQML +valid valid linking.wast:22 AGFzbQEAAAABBQFgAX8AAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAABwkBBXByaW50AAA= +valid valid linking.wast:28 AGFzbQEAAAABBQFgAX4AAhQBCnJlZXhwb3J0X2YFcHJpbnQAAA== +valid valid linking.wast:32 AGFzbQEAAAABBgFgAX8BfwIUAQpyZWV4cG9ydF9mBXByaW50AAA= +valid valid linking.wast:39 AGFzbQEAAAABCQJgAAF/YAF/AAMEAwAAAQYMAn8AQSoLfwFBjgELBy0FBGdsb2IDAANnZXQAAAhtdXRfZ2xvYgMBB2dldF9tdXQAAQdzZXRfbXV0AAIKEgMEACMACwQAIwELBgAgACQBCw== +valid valid linking.wast:50 AGFzbQEAAAABCQJgAAF/YAF/AAI+BQJNZwRnbG9iA38AAk1nCG11dF9nbG9iA38BAk1nA2dldAAAAk1nB2dldF9tdXQAAAJNZwdzZXRfbXV0AAEDAgEABgYBfwBBKwsHSQcHTWcuZ2xvYgMABk1nLmdldAAABGdsb2IDAgNnZXQAAwtNZy5tdXRfZ2xvYgMBCk1nLmdldF9tdXQAAQpNZy5zZXRfbXV0AAIKBgEEACMCCw== +valid valid linking.wast:87 AGFzbQEAAAACEAECTWcIbXV0X2dsb2IDfwA= +valid valid linking.wast:91 AGFzbQEAAAACDAECTWcEZ2xvYgN/AQ== +valid valid linking.wast:96 AGFzbQEAAAAGFQRwANBwC3AB0HALbwDQbwtvAdBvCwc9BAxnLWNvbnN0LWZ1bmMDAApnLXZhci1mdW5jAwEOZy1jb25zdC1leHRlcm4DAgxnLXZhci1leHRlcm4DAw== +valid valid linking.wast:104 AGFzbQEAAAACYQQHTXJlZl9leAxnLWNvbnN0LWZ1bmMDcAAHTXJlZl9leA5nLWNvbnN0LWV4dGVybgNvAAdNcmVmX2V4CmctdmFyLWZ1bmMDcAEHTXJlZl9leAxnLXZhci1leHRlcm4DbwE= +valid valid linking.wast:113 AGFzbQEAAAACGwEHTXJlZl9leA5nLWNvbnN0LWV4dGVybgNwAA== +valid valid linking.wast:117 AGFzbQEAAAACGQEHTXJlZl9leAxnLWNvbnN0LWZ1bmMDbwA= +valid valid linking.wast:123 AGFzbQEAAAACFwEHTXJlZl9leApnLXZhci1mdW5jA28B +valid valid linking.wast:127 AGFzbQEAAAACGQEHTXJlZl9leAxnLXZhci1leHRlcm4DcAE= +valid valid linking.wast:134 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8DBAMAAAIEBAFwAAoHEgMDdGFiAQABaAABBGNhbGwAAgkKAQBBAgsEAAAAAAoTAwQAQQQLBABBfAsHACAAEQAACw== +valid valid linking.wast:149 AGFzbQEAAAABDQNgAABgAAF/YAF/AX8CEgICTXQEY2FsbAACAk10AWgAAQMEAwECAgQFAXABBQUHIQMHTXQuY2FsbAAADGNhbGwgTXQuY2FsbAADBGNhbGwABAkLAQBBAAsFAgICAQAKFQMEAEEFCwYAIAAQAAsHACAAEQEACw== +valid valid linking.wast:191 AGFzbQEAAAABCgJgAAF/YAF/AX8CEwICTXQBaAAAAk10A3RhYgFwAAUDAwIAAQcIAQRjYWxsAAIJCAEAQQELAgEACg4CBABBBgsHACAAEQAACw== +valid valid linking.wast:229 AGFzbQEAAAABBAFgAAACDAECTXQDdGFiAXAAAAMCAQAJBwEAQQkLAQAKBAECAAs= +valid valid linking.wast:235 AGFzbQEAAAAGBgF/AEEFCwcFAQFnAwA= +valid valid linking.wast:237 AGFzbQEAAAACCQECRzEBZwN/AAYGAX8AIwALBwUBAWcDAQ== +valid valid linking.wast:244 AGFzbQEAAAABBAFgAAACDAECTXQDdGFiAXAAAAMCAQAJBwEAQQoLAQAKBAECAAs= +valid valid linking.wast:253 AGFzbQEAAAABBQFgAAF/AhYCAk10A3RhYgFwAAoCTXQDbWVtAgABAwIBAAkNAgBBBwsBAABBCQsBAAoGAQQAQQAL +valid valid linking.wast:267 AGFzbQEAAAABBQFgAAF/AgwBAk10A3RhYgFwAAoDAgEACRECAEEHCwEAAEEICwUAAAAAAAoGAQQAQQAL +valid valid linking.wast:279 AGFzbQEAAAABBQFgAAF/AgwBAk10A3RhYgFwAAoDAgEABQMBAAEJBwEAQQcLAQAKBgEEAEEACwsJAQBBgIAECwFk +valid valid linking.wast:291 AGFzbQEAAAAEBwJwAAFvAAEHFQIGdC1mdW5jAQAIdC1leHRlcm4BAQ== +valid valid linking.wast:297 AGFzbQEAAAACLQIJTXRhYmxlX2V4BnQtZnVuYwFwAAEJTXRhYmxlX2V4CHQtZXh0ZXJuAW8AAQ== +valid valid linking.wast:303 AGFzbQEAAAACFgEJTXRhYmxlX2V4BnQtZnVuYwFvAAE= +valid valid linking.wast:307 AGFzbQEAAAACGAEJTXRhYmxlX2V4CHQtZXh0ZXJuAXAAAQ== +valid valid linking.wast:314 AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAQUHDgIDbWVtAgAEbG9hZAAACgkBBwAgAC0AAAsLEAEAQQoLCgABAgMEBQYHCAk= +valid valid linking.wast:324 AGFzbQEAAAABBgFgAX8BfwILAQJNbQRsb2FkAAADAgEABQMBAAEHEgIHTW0ubG9hZAAABGxvYWQAAQoJAQcAIAAtAAALCwwBAEEKCwbw8fLz9PU= +valid valid linking.wast:340 AGFzbQEAAAABBgFgAX8BfwILAQJNbQNtZW0CAAEDAgEABwgBBGxvYWQAAAoJAQcAIAAtAAALCw4BAEEFCwigoaKjpKWmpw== +valid valid linking.wast:354 AGFzbQEAAAACCwECTW0DbWVtAgAACwkBAEH//wMLAWE= +valid valid linking.wast:360 AGFzbQEAAAACCwECTW0DbWVtAgAACwkBAEGAgAQLAWE= +valid valid linking.wast:367 AGFzbQEAAAABBgFgAX8BfwIMAQJNbQNtZW0CAQEIAwIBAAcIAQRncm93AAAKCAEGACAAQAAL +valid valid linking.wast:385 AGFzbQEAAAABBAFgAAACJwMIc3BlY3Rlc3QFcHJpbnQAAAJNbQNtZW0CAAECTW0DdGFiAXAAAAsJAQBBAAsDYWJj +valid valid linking.wast:398 AGFzbQEAAAACCwECTW0DbWVtAgABCyICAEEACwNhYmMAQfb/EwsSenp6enp6enp6enp6enp6enp6 +valid valid linking.wast:410 AGFzbQEAAAABBAFgAAACCwECTW0DbWVtAgABAwIBAAQEAXAAAAkHAQBBAAsBAAoEAQIACwsJAQBBAAsDYWJj +valid valid linking.wast:422 AGFzbQEAAAABBQFgAAF/AwMCAAAEBAFwAAEFAwEAAQcxBAZtZW1vcnkCAAV0YWJsZQEADWdldCBtZW1vcnlbMF0AAAxnZXQgdGFibGVbMF0AAQoRAgcAQQAtAAALBwBBABEAAAs= +valid valid linking.wast:436 AGFzbQEAAAABCAJgAAF/YAAAAhsCAk1zBm1lbW9yeQIAAQJNcwV0YWJsZQFwAAEDAwIAAQgBAQkHAQBBAAsBAAoMAgYAQa29AwsDAAALCwsBAEEACwVoZWxsbw== +valid valid load.wast:3 AGFzbQEAAAABFQRgA39/fwF/YAABf2AAAGACf38BfwMnJgECAQECAQEBAQEBAwMBAAEBAQEBAQECAQIBAQICAgIBAQEBAQEBBAUBcAEBAQUDAQABBgYBfwFBAAsHtwUlC2FzLWJyLXZhbHVlAAANYXMtYnJfaWYtY29uZAABDmFzLWJyX2lmLXZhbHVlAAITYXMtYnJfaWYtdmFsdWUtY29uZAADEWFzLWJyX3RhYmxlLWluZGV4AAQRYXMtYnJfdGFibGUtdmFsdWUABRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAGD2FzLXJldHVybi12YWx1ZQAHCmFzLWlmLWNvbmQACAphcy1pZi10aGVuAAkKYXMtaWYtZWxzZQAKD2FzLXNlbGVjdC1maXJzdAALEGFzLXNlbGVjdC1zZWNvbmQADA5hcy1zZWxlY3QtY29uZAANDWFzLWNhbGwtZmlyc3QADwthcy1jYWxsLW1pZAAQDGFzLWNhbGwtbGFzdAARFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAEhRhcy1jYWxsX2luZGlyZWN0LW1pZAATFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAUFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAFRJhcy1sb2NhbC5zZXQtdmFsdWUAFhJhcy1sb2NhbC50ZWUtdmFsdWUAFxNhcy1nbG9iYWwuc2V0LXZhbHVlABgPYXMtbG9hZC1hZGRyZXNzABkQYXMtbG9hZE4tYWRkcmVzcwAaEGFzLXN0b3JlLWFkZHJlc3MAGw5hcy1zdG9yZS12YWx1ZQAcEWFzLXN0b3JlTi1hZGRyZXNzAB0PYXMtc3RvcmVOLXZhbHVlAB4QYXMtdW5hcnktb3BlcmFuZAAfDmFzLWJpbmFyeS1sZWZ0ACAPYXMtYmluYXJ5LXJpZ2h0ACEPYXMtdGVzdC1vcGVyYW5kACIPYXMtY29tcGFyZS1sZWZ0ACMQYXMtY29tcGFyZS1yaWdodAAkE2FzLW1lbW9yeS5ncm93LXNpemUAJQkHAQBBAAsBDgqGBCYMAAJ/QQAoAgAMAAsLDAACQEEAKAIADQALCxEAAn9BACgCAEEBDQAaQQcLCxEAAn9BBkEAKAIADQAaQQcLCw8AAkBBACgCAA4CAAAACwsTAAJ/QQAoAgBBAQ4CAAAAQQcLCxIAAn9BBkEAKAIADgEAAEEHCwsIAEEAKAIADwsPAEEAKAIABH9BAAVBAQsLDwBBAQR/QQAoAgAFQQALCw8AQQAEf0EABUEAKAIACwsMAEEAKAIAIAAgARsLDAAgAEEAKAIAIAEbCwwAQQBBAUEAKAIAGwsEAEF/Cw0AQQAoAgBBAkEDEA4LDQBBAUEAKAIAQQMQDgsNAEEBQQJBACgCABAOCxAAQQAoAgBBAkEDQQARAAALEABBAUEAKAIAQQNBABEAAAsQAEEBQQJBACgCAEEAEQAACxAAQQFBAkEDQQAoAgARAAALCwEBf0EAKAIAIQALCwEBf0EAKAIAIgALCwEBf0EAKAIAJAALCgBBACgCACgCAAsKAEEAKAIALAAACwwAQQAoAgBBBzYCAAsMAEECQQAoAgA2AgALDABBACwAAEEHOgAACwwAQQJBACgCADsBAAsJAEHkACgCAGcLCwBB5AAoAgBBCmoLCwBBCkHkACgCAGsLCQBB5AAoAgBFCwsAQeQAKAIAQQpMCwsAQQpB5AAoAgBHCwoAQeQAKAIAQAAL +invalid invalid load.wast:312 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAKAIACw== +invalid invalid load.wast:316 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEALAAACw== +invalid invalid load.wast:320 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEALQAACw== +invalid invalid load.wast:324 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEALgEACw== +invalid invalid load.wast:328 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEALwEACw== +invalid invalid load.wast:332 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAKQMACw== +invalid invalid load.wast:336 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAMAAACw== +invalid invalid load.wast:340 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAMQAACw== +invalid invalid load.wast:344 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAMgEACw== +invalid invalid load.wast:348 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAMwEACw== +invalid invalid load.wast:352 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEANAIACw== +invalid invalid load.wast:356 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEANQIACw== +invalid invalid load.wast:360 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAKgIACw== +invalid invalid load.wast:364 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEAKwMACw== +invalid invalid load.wast:371 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgwBCgBDAAAAACgCAAs= +invalid invalid load.wast:372 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgwBCgBDAAAAACwAAAs= +invalid invalid load.wast:373 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgwBCgBDAAAAAC0AAAs= +invalid invalid load.wast:374 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgwBCgBDAAAAAC4BAAs= +invalid invalid load.wast:375 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgwBCgBDAAAAAC8BAAs= +invalid invalid load.wast:376 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAACkDAAs= +invalid invalid load.wast:377 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADAAAAs= +invalid invalid load.wast:378 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADEAAAs= +invalid invalid load.wast:379 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADIBAAs= +invalid invalid load.wast:380 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADMBAAs= +invalid invalid load.wast:381 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADQCAAs= +invalid invalid load.wast:382 AGFzbQEAAAABBQFgAAF+AwIBAAUDAQABCgwBCgBDAAAAADUCAAs= +invalid invalid load.wast:383 AGFzbQEAAAABBQFgAAF9AwIBAAUDAQABCgwBCgBDAAAAACoCAAs= +invalid invalid load.wast:384 AGFzbQEAAAABBQFgAAF8AwIBAAUDAQABCgwBCgBDAAAAACsDAAs= +invalid invalid load.wast:388 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCAEGACgCABoL +invalid invalid load.wast:397 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDQELAEEAAkAoAgAaCws= +invalid invalid load.wast:407 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDQELAEEAA0AoAgAaCws= +invalid invalid load.wast:417 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDwENAEEAQQAEQCgCABoLCw== +invalid invalid load.wast:427 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEgEQAEEAQQAEf0EABSgCAAsaCw== +invalid invalid load.wast:437 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDwENAEEAAkAoAgAMABoLCw== +invalid invalid load.wast:447 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEQEPAEEAAkAoAgBBAQ0AGgsL +invalid invalid load.wast:457 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKEAEOAEEAAkAoAgAOAAAaCws= +invalid invalid load.wast:467 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCQEHACgCAA8aCw== +invalid invalid load.wast:476 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDQELACgCAEEBQQIbGgs= +invalid invalid load.wast:485 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQMBAAAKDwIIACgCABABGgsEACAACw== +invalid invalid load.wast:495 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQUDAQAACQcBAEEACwEAChUCBAAgAAsOAAJ/KAIAQQARAAAaCws= +invalid invalid load.wast:512 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDgEMAQF/KAIAIQAgABoL +invalid invalid load.wast:522 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKDAEKAQF/KAIAIgAaCw== +invalid invalid load.wast:532 AGFzbQEAAAABBAFgAAADAgEABQMBAAAGBgF/AUEACwoMAQoAKAIAJAAjABoL +invalid invalid load.wast:542 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCgEIACgCAEAAGgs= +invalid invalid load.wast:551 AGFzbQEAAAABBAFgAAADAgEABQMBAAAKCwEJACgCACgCABoL +invalid invalid load.wast:560 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDAEKACgCAEEBNgIACw== +valid valid local_get.wast:3 AGFzbQEAAAABNgpgAAF/YAABfmAAAX1gAAF8YAF/AX9gAX4BfmABfQF9YAF8AXxgBX59fH9/AGAFfn18f38BfAMUEwABAgMEBQYHCAkEBAQEBAQEBAQHswITDnR5cGUtbG9jYWwtaTMyAAAOdHlwZS1sb2NhbC1pNjQAAQ50eXBlLWxvY2FsLWYzMgACDnR5cGUtbG9jYWwtZjY0AAMOdHlwZS1wYXJhbS1pMzIABA50eXBlLXBhcmFtLWk2NAAFDnR5cGUtcGFyYW0tZjMyAAYOdHlwZS1wYXJhbS1mNjQABwp0eXBlLW1peGVkAAgEcmVhZAAJDmFzLWJsb2NrLXZhbHVlAAoNYXMtbG9vcC12YWx1ZQALC2FzLWJyLXZhbHVlAAwOYXMtYnJfaWYtdmFsdWUADRNhcy1icl9pZi12YWx1ZS1jb25kAA4RYXMtYnJfdGFibGUtdmFsdWUADw9hcy1yZXR1cm4tdmFsdWUAEAphcy1pZi10aGVuABEKYXMtaWYtZWxzZQASCo4CEwYBAX8gAAsGAQF+IAALBgEBfSAACwYBAXwgAAsEACAACwQAIAALBAAgAAsEACAACywDAX0CfgF8IABQGiABjBogApoaIANFGiAERRogBYwaIAZQGiAHUBogCJoaCz8DAX0CfgF8QwAAsEAhBUIGIQZEAAAAAAAAIEAhCCAAuiABuyACIAO4IAS3IAW7IAa6IAe6IAigoKCgoKCgoAsHAAJ/IAALCwcAA38gAAsLCQACfyAADAALCwsAAn8gAEEBDQALCwsAAn8gACAADQALCx0AAkACQAJAIAAOAgABAkEADwtBAQ8LQQIPC0EDCwUAIAAPCwwAIAAEfyAABUEACwsMACAABH9BAQUgAAsL +invalid invalid local_get.wast:153 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcBAX0gAEUL +invalid invalid local_get.wast:157 AGFzbQEAAAABBQFgAAF8AwIBAAoLAQkCAXwBfiABmgs= +invalid invalid local_get.wast:169 AGFzbQEAAAABBgFgAX0BfwMCAQAKBwEFACAARQs= +invalid invalid local_get.wast:173 AGFzbQEAAAABBwFgAnx+AXwDAgEACgcBBQAgAZoL +invalid invalid local_get.wast:181 AGFzbQEAAAABBAFgAAADAgEACggBBgEBfyAACw== +invalid invalid local_get.wast:185 AGFzbQEAAAABBAFgAAADAgEACggBBgEBfiAACw== +invalid invalid local_get.wast:189 AGFzbQEAAAABBAFgAAADAgEACggBBgEBfSAACw== +invalid invalid local_get.wast:193 AGFzbQEAAAABBAFgAAADAgEACggBBgEBfCAACw== +invalid invalid local_get.wast:201 AGFzbQEAAAABBAFgAAADAgEACgsBCQIBfwF+IAMaCw== +invalid invalid local_get.wast:205 AGFzbQEAAAABBAFgAAADAgEACg4BDAIBfwF+IPek6gYaCw== +invalid invalid local_get.wast:210 AGFzbQEAAAABBgFgAn9+AAMCAQAKBwEFACACGgs= +invalid invalid local_get.wast:214 AGFzbQEAAAABBgFgAn9+AAMCAQAKCwEJACD38s7UAhoL +invalid invalid local_get.wast:219 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkCAX8BfiADGgs= +invalid invalid local_get.wast:223 AGFzbQEAAAABBQFgAX4AAwIBAAoOAQwCAX8BfiD3qJlmGgs= +valid valid local_set.wast:3 AGFzbQEAAAABJQdgAABgAX8AYAF+AGABfQBgAXwAYAV+fXx/fwBgBX59fH9/AX4DFBMAAAAAAQIDBAUGAQEBAQEBAQEBB7QCEw50eXBlLWxvY2FsLWkzMgAADnR5cGUtbG9jYWwtaTY0AAEOdHlwZS1sb2NhbC1mMzIAAg50eXBlLWxvY2FsLWY2NAADDnR5cGUtcGFyYW0taTMyAAQOdHlwZS1wYXJhbS1pNjQABQ50eXBlLXBhcmFtLWYzMgAGDnR5cGUtcGFyYW0tZjY0AAcKdHlwZS1taXhlZAAIBXdyaXRlAAkOYXMtYmxvY2stdmFsdWUACg1hcy1sb29wLXZhbHVlAAsLYXMtYnItdmFsdWUADA5hcy1icl9pZi12YWx1ZQANE2FzLWJyX2lmLXZhbHVlLWNvbmQADhFhcy1icl90YWJsZS12YWx1ZQAPD2FzLXJldHVybi12YWx1ZQAQCmFzLWlmLXRoZW4AEQphcy1pZi1lbHNlABIK0gITCAEBf0EAIQALCAEBfkIAIQALCwEBfUMAAAAAIQALDwEBfEQAAAAAAAAAACEACwYAQQohAAsGAEILIQALCQBDmpkxQSEACw0ARGZmZmZmZihAIQALQAMBfQJ+AXxCACEAQwAAAAAhAUQAAAAAAAAAACECQQAhA0EAIQRDAAAAACEFQgAhBkIAIQdEAAAAAAAAAAAhCAtPAwF9An4BfEOamZm+IQFBKCEDQXkhBEMAALBAIQVCBiEGRAAAAAAAACBAIQggALogAbsgAiADuCAEtyAFuyAGuiAHuiAIoKCgoKCgoKCwCwkAAkBBASEACwsJAANAQQMhAAsLCwACQEEJIQAMAAsLDQACQEEIIQBBAQ0ACwsNAAJAQQZBCSEADQALCw4AAkBBCiEAQQEOAAALCwcAQQchAA8LCwAgAARAQQMhAAsLDAAgAARABUEBIQALCw== +invalid invalid local_set.wast:148 AGFzbQEAAAABBAFgAAADAgEACgkBBwEBfwEhAAs= +invalid invalid local_set.wast:152 AGFzbQEAAAABBAFgAAADAgEACg0BCwEBf0MAAAAAIQAL +invalid invalid local_set.wast:156 AGFzbQEAAAABBAFgAAADAgEAChEBDwEBfUQAAAAAAAAAACEACw== +invalid invalid local_set.wast:160 AGFzbQEAAAABBAFgAAADAgEAChMBEQIBfAF+RAAAAAAAAAAAIQEL +invalid invalid local_set.wast:169 AGFzbQEAAAABBQFgAX8AAwIBAAoHAQUAASEACw== +invalid invalid local_set.wast:173 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAQwAAAAAhAAs= +invalid invalid local_set.wast:177 AGFzbQEAAAABBQFgAX0AAwIBAAoPAQ0ARAAAAAAAAAAAIQAL +invalid invalid local_set.wast:181 AGFzbQEAAAABBgFgAnx+AAMCAQAKDwENAEQAAAAAAAAAACEBCw== +invalid invalid local_set.wast:186 AGFzbQEAAAABBQFgAX8AAwIBAAoGAQQAIQAL +invalid invalid local_set.wast:194 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAQQACQCEACws= +invalid invalid local_set.wast:203 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAQQADQCEACws= +invalid invalid local_set.wast:212 AGFzbQEAAAABBQFgAX8AAwIBAAoNAQsAQQBBAQRAIQALCw== +invalid invalid local_set.wast:221 AGFzbQEAAAABBQFgAX8AAwIBAAoQAQ4AQQBBAAR/QQAFIQALCw== +invalid invalid local_set.wast:230 AGFzbQEAAAABBQFgAX8AAwIBAAoNAQsAQQACQCEADAALCw== +invalid invalid local_set.wast:239 AGFzbQEAAAABBQFgAX8AAwIBAAoNAQsAQQACQCEADQALCw== +invalid invalid local_set.wast:248 AGFzbQEAAAABBQFgAX8AAwIBAAoOAQwAQQACQCEADgAACws= +invalid invalid local_set.wast:257 AGFzbQEAAAABBQFgAX8AAwIBAAoHAQUAIQAPCw== +invalid invalid local_set.wast:265 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAIQBBAUECGws= +invalid invalid local_set.wast:273 AGFzbQEAAAABCgJgAX8AYAF/AX8DAwIAAQoNAgYAIQAQAQsEACAACw== +invalid invalid local_set.wast:282 AGFzbQEAAAABCgJgAX8Bf2ABfwADAwIAAQQFAXABAQEJBwEAQQALAQAKEwIEACAACwwAAn8hAEEAEQAACws= +invalid invalid local_set.wast:301 AGFzbQEAAAABBQFgAX0AAwIBAAoNAQsBAX9DAAAAACEBCw== +invalid invalid local_set.wast:305 AGFzbQEAAAABBgFgAn5/AAMCAQAKDQELAQF9QwAAAAAhAQs= +invalid invalid local_set.wast:309 AGFzbQEAAAABBQFgAX4AAwIBAAoMAQoCAXwBfkIAIQEL +invalid invalid local_set.wast:317 AGFzbQEAAAABBgFgAX8BfwMCAQAKCAEGAEEBIQAL +invalid invalid local_set.wast:321 AGFzbQEAAAABBgFgAX4BfgMCAQAKCAEGAEIBIQAL +invalid invalid local_set.wast:325 AGFzbQEAAAABBgFgAX0BfQMCAQAKCwEJAEMAAIA/IQAL +invalid invalid local_set.wast:329 AGFzbQEAAAABBgFgAXwBfAMCAQAKDwENAEQAAAAAAADwPyEACw== +invalid invalid local_set.wast:337 AGFzbQEAAAABBAFgAAADAgEACgwBCgIBfwF+QQAhAws= +invalid invalid local_set.wast:341 AGFzbQEAAAABBAFgAAADAgEACg8BDQIBfwF+QQAh96TqBgs= +invalid invalid local_set.wast:346 AGFzbQEAAAABBgFgAn9+AAMCAQAKCAEGAEEAIQIL +invalid invalid local_set.wast:350 AGFzbQEAAAABBgFgAn9+AAMCAQAKDAEKAEEAIffyztQCCw== +invalid invalid local_set.wast:355 AGFzbQEAAAABBQFgAX8AAwIBAAoMAQoCAX8BfkEAIQML +invalid invalid local_set.wast:359 AGFzbQEAAAABBQFgAX4AAwIBAAoPAQ0CAX8BfkEAIfeomWYL +valid valid local_tee.wast:3 AGFzbQEAAAABWBBgA39/fwF/YAABf2AAAX5gAAF9YAABfGABfwF/YAF+AX5gAX0BfWABfAF8YAV+fXx/fwBgBX59fH9/AX5gBX59fH9/AXxgAABgAX8AYAJ/fwF/YAF+AX8DOjkBAgMEBQYHCAkKCwwFBQUFBQUFDQUFDQUFBQUFBQ4OBQAFBQUFBQUFDAUMBQUNDQ0NBwUFBQUFDwUEBQFwAQEBBQMBAAEGBgF/AUEACwfPBzcOdHlwZS1sb2NhbC1pMzIAAA50eXBlLWxvY2FsLWk2NAABDnR5cGUtbG9jYWwtZjMyAAIOdHlwZS1sb2NhbC1mNjQAAw50eXBlLXBhcmFtLWkzMgAEDnR5cGUtcGFyYW0taTY0AAUOdHlwZS1wYXJhbS1mMzIABg50eXBlLXBhcmFtLWY2NAAHCnR5cGUtbWl4ZWQACAV3cml0ZQAJBnJlc3VsdAAKDmFzLWJsb2NrLWZpcnN0AAwMYXMtYmxvY2stbWlkAA0NYXMtYmxvY2stbGFzdAAODWFzLWxvb3AtZmlyc3QADwthcy1sb29wLW1pZAAQDGFzLWxvb3AtbGFzdAARC2FzLWJyLXZhbHVlABINYXMtYnJfaWYtY29uZAATDmFzLWJyX2lmLXZhbHVlABQTYXMtYnJfaWYtdmFsdWUtY29uZAAVEWFzLWJyX3RhYmxlLWluZGV4ABYRYXMtYnJfdGFibGUtdmFsdWUAFxdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAYD2FzLXJldHVybi12YWx1ZQAZCmFzLWlmLWNvbmQAGgphcy1pZi10aGVuABsKYXMtaWYtZWxzZQAcD2FzLXNlbGVjdC1maXJzdAAdEGFzLXNlbGVjdC1zZWNvbmQAHg5hcy1zZWxlY3QtY29uZAAfDWFzLWNhbGwtZmlyc3QAIQthcy1jYWxsLW1pZAAiDGFzLWNhbGwtbGFzdAAjFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAJBRhcy1jYWxsX2luZGlyZWN0LW1pZAAlFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAmFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAJxJhcy1sb2NhbC5zZXQtdmFsdWUAKBJhcy1sb2NhbC50ZWUtdmFsdWUAKRNhcy1nbG9iYWwuc2V0LXZhbHVlACoPYXMtbG9hZC1hZGRyZXNzACsQYXMtbG9hZE4tYWRkcmVzcwAsEGFzLXN0b3JlLWFkZHJlc3MALQ5hcy1zdG9yZS12YWx1ZQAuEWFzLXN0b3JlTi1hZGRyZXNzAC8PYXMtc3RvcmVOLXZhbHVlADAQYXMtdW5hcnktb3BlcmFuZAAxDmFzLWJpbmFyeS1sZWZ0ADIPYXMtYmluYXJ5LXJpZ2h0ADMPYXMtdGVzdC1vcGVyYW5kADQPYXMtY29tcGFyZS1sZWZ0ADUQYXMtY29tcGFyZS1yaWdodAA2EmFzLWNvbnZlcnQtb3BlcmFuZAA3E2FzLW1lbW9yeS5ncm93LXNpemUAOAkHAQBBAAsBIAqDBzkIAQF/QQAiAAsIAQF+QgAiAAsLAQF9QwAAAAAiAAsPAQF8RAAAAAAAAAAAIgALBgBBCiIACwYAQgsiAAsJAEOamTFBIgALDQBEZmZmZmZmKEAiAAtSAwF9An4BfEIAIgBQGkMAAAAAIgGMGkQAAAAAAAAAACICmhpBACIDRRpBACIERRpDAAAAACIFjBpCACIGUBpCACIHUBpEAAAAAAAAAAAiCJoaC1UDAX0CfgF8Q5qZmb4iARpBKCIDGkF5IgQaQwAAsEAiBRpCBiIGGkQAAAAAAAAgQCIIGiAAuiABuyACIAO4IAS3IAW7IAa6IAe6IAigoKCgoKCgoLALTwMBfQJ+AXxCASIAukMAAABAIgG7RGZmZmZmZgpAIgJBBCIDuEEFIgS3QwAAsEAiBbtCBiIGukIAIge6RAAAAAAAACBAIgigoKCgoKCgoAsCAAsLAAJ/QQEiABALCwsNAAJ/EAtBASIAEAsLCw0AAn8QCxALQQEiAAsLCwADf0EDIgAQCwsLDQADfxALQQQiABALCwsNAAN/EAsQC0EFIgALCwsAAn9BCSIADAALCwsAAkBBASIADQALCxAAAn9BCCIAQQENABpBBwsLEAACf0EGQQkiAA0AGkEHCwsOAAJAQQAiAA4CAAAACwsSAAJ/QQoiAEEBDgIAAABBBwsLEQACf0EGQQsiAA4BAABBBwsLBwBBByIADwsOAEECIgAEf0EABUEBCwsOACAABH9BAyIABSAACwsOACAABH8gAAVBBCIACwsLAEEFIgAgACABGwsLACAAQQYiACABGwsLAEEAQQFBByIAGwsEAEF/CwwAQQwiAEECQQMQIAsMAEEBQQ0iAEEDECALDABBAUECQQ4iABAgCw8AQQEiAEECQQNBABEAAAsPAEEBQQIiAEEDQQARAAALDwBBAUECQQMiAEEAEQAACw8AQQFBAkEDQQAiABEAAAsKAQF/QQEiACEACwgAQQEiACIACwoBAX9BASIAJAALCQBBASIAKAIACwkAQQMiACwAAAsLAEEeIgBBBzYCAAsLAEECQQEiADYCAAsLAEEBIgBBBzoAAAsLAEECQQEiADsBAAsKAEPi8YB/IgCMCwkAQQMiAEEKagsJAEEKQQQiAGsLBwBBACIARQsJAEErIgBBCkwLCQBBCkEqIgBHCwcAQikiAKcLCABBKCIAQAAL +invalid invalid local_tee.wast:371 AGFzbQEAAAABBQFgAAF+AwIBAAoKAQgBAX9BACIACw== +invalid invalid local_tee.wast:375 AGFzbQEAAAABBAFgAAADAgEACg4BDAEBfUMAAAAAIgBFCw== +invalid invalid local_tee.wast:379 AGFzbQEAAAABBAFgAAADAgEACg0BCwIBfAF+QgAiAZoL +invalid invalid local_tee.wast:384 AGFzbQEAAAABBAFgAAADAgEACgkBBwEBfwEiAAs= +invalid invalid local_tee.wast:388 AGFzbQEAAAABBAFgAAADAgEACg0BCwEBf0MAAAAAIgAL +invalid invalid local_tee.wast:392 AGFzbQEAAAABBAFgAAADAgEAChEBDwEBfUQAAAAAAAAAACIACw== +invalid invalid local_tee.wast:396 AGFzbQEAAAABBAFgAAADAgEAChMBEQIBfAF+RAAAAAAAAAAAIgEL +invalid invalid local_tee.wast:417 AGFzbQEAAAABBQFgAX8AAwIBAAoHAQUAASIACw== +invalid invalid local_tee.wast:421 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAQwAAAAAiAAs= +invalid invalid local_tee.wast:425 AGFzbQEAAAABBQFgAX0AAwIBAAoPAQ0ARAAAAAAAAAAAIgAL +invalid invalid local_tee.wast:429 AGFzbQEAAAABBgFgAnx+AAMCAQAKDwENAEQAAAAAAAAAACIBCw== +invalid invalid local_tee.wast:434 AGFzbQEAAAABBQFgAX8AAwIBAAoHAQUAIgAaCw== +invalid invalid local_tee.wast:442 AGFzbQEAAAABBQFgAX8AAwIBAAoMAQoAQQACQCIAGgsL +invalid invalid local_tee.wast:451 AGFzbQEAAAABBQFgAX8AAwIBAAoMAQoAQQADQCIAGgsL +invalid invalid local_tee.wast:460 AGFzbQEAAAABBQFgAX8AAwIBAAoOAQwAQQBBAARAIgAaCws= +invalid invalid local_tee.wast:469 AGFzbQEAAAABBQFgAX8AAwIBAAoRAQ8AQQBBAAR/QQAFIgALGgs= +invalid invalid local_tee.wast:478 AGFzbQEAAAABBQFgAX8AAwIBAAoOAQwAQQACQCIADAAaCws= +invalid invalid local_tee.wast:487 AGFzbQEAAAABBQFgAX8AAwIBAAoQAQ4AQQACQCIAQQENABoLCw== +invalid invalid local_tee.wast:496 AGFzbQEAAAABBQFgAX8AAwIBAAoPAQ0AQQACQCIADgAAGgsL +invalid invalid local_tee.wast:505 AGFzbQEAAAABBQFgAX8AAwIBAAoIAQYAIgAPGgs= +invalid invalid local_tee.wast:513 AGFzbQEAAAABBQFgAX8AAwIBAAoMAQoAIgBBAUECGxoL +invalid invalid local_tee.wast:521 AGFzbQEAAAABCgJgAX8AYAF/AX8DAwIAAQoOAgcAIgAQARoLBAAgAAs= +invalid invalid local_tee.wast:530 AGFzbQEAAAABCgJgAX8Bf2ABfwADAwIAAQQFAXABAQEJBwEAQQALAQAKFAIEACAACw0AAn8iAEEAEQAAGgsL +invalid invalid local_tee.wast:546 AGFzbQEAAAABBQFgAX8AAwIBAAoLAQkAIgAhACAAGgs= +invalid invalid local_tee.wast:554 AGFzbQEAAAABBQFgAX8AAwIBAAoJAQcAIgAiABoL +invalid invalid local_tee.wast:562 AGFzbQEAAAABBQFgAX8AAwIBAAYGAX8BQQALCgsBCQAiACQAIwAaCw== +invalid invalid local_tee.wast:571 AGFzbQEAAAABBQFgAX8AAwIBAAUDAQAACgkBBwAiAEAAGgs= +invalid invalid local_tee.wast:580 AGFzbQEAAAABBQFgAX8AAwIBAAUDAQAACgoBCAAiACgCABoL +invalid invalid local_tee.wast:589 AGFzbQEAAAABBQFgAX8AAwIBAAUDAQABCgsBCQAiAEEBNgIACw== +invalid invalid local_tee.wast:599 AGFzbQEAAAABBQFgAX0AAwIBAAoNAQsBAX9DAAAAACIBCw== +invalid invalid local_tee.wast:603 AGFzbQEAAAABBgFgAn5/AAMCAQAKDQELAQF9QwAAAAAiAQs= +invalid invalid local_tee.wast:607 AGFzbQEAAAABBQFgAX4AAwIBAAoMAQoCAXwBfkIAIgEL +invalid invalid local_tee.wast:615 AGFzbQEAAAABBAFgAAADAgEACg0BCwIBfwF+QQAiAxoL +invalid invalid local_tee.wast:619 AGFzbQEAAAABBAFgAAADAgEAChABDgIBfwF+QQAi96TqBhoL +invalid invalid local_tee.wast:624 AGFzbQEAAAABBgFgAn9+AAMCAQAKCQEHAEEAIgIaCw== +invalid invalid local_tee.wast:628 AGFzbQEAAAABBgFgAn9+AAMCAQAKDQELAEEAIvfyztQCGgs= +invalid invalid local_tee.wast:633 AGFzbQEAAAABBQFgAX8AAwIBAAoNAQsCAX8BfkEAIgMaCw== +invalid invalid local_tee.wast:637 AGFzbQEAAAABBQFgAX4AAwIBAAoQAQ4CAX8BfkEAIveomWYaCw== +valid valid loop.wast:3 AGFzbQEAAAABTg5gAn9/AX9gAABgAAF/YAF/AGADf3x/A398f2AAA39+f2ABfwF/YAACf39gAAJ9fWAAA39/fmADf39+AGACf38Cf39gAX4BfmACfX0BfQM5OAEBAgICAgICAgECAgICAgIAAgICAQECBgICAQICAgICAgICAgICAgICCQICAgICAgICAgIMDA0BBAUBcAEBAQUDAQABBgYBfwFBAAsHyAY1BWVtcHR5AAEIc2luZ3VsYXIAAgVtdWx0aQADBm5lc3RlZAAEBGRlZXAABQ9hcy1zZWxlY3QtZmlyc3QABg1hcy1zZWxlY3QtbWlkAAcOYXMtc2VsZWN0LWxhc3QACA9hcy1pZi1jb25kaXRpb24ACQphcy1pZi10aGVuAAoKYXMtaWYtZWxzZQALDmFzLWJyX2lmLWZpcnN0AAwNYXMtYnJfaWYtbGFzdAANEWFzLWJyX3RhYmxlLWZpcnN0AA4QYXMtYnJfdGFibGUtbGFzdAAPFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAERRhcy1jYWxsX2luZGlyZWN0LW1pZAASFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAATDmFzLXN0b3JlLWZpcnN0ABQNYXMtc3RvcmUtbGFzdAAVFGFzLW1lbW9yeS5ncm93LXZhbHVlABYNYXMtY2FsbC12YWx1ZQAYD2FzLXJldHVybi12YWx1ZQAZD2FzLWRyb3Atb3BlcmFuZAAaC2FzLWJyLXZhbHVlABsSYXMtbG9jYWwuc2V0LXZhbHVlABwSYXMtbG9jYWwudGVlLXZhbHVlAB0TYXMtZ2xvYmFsLnNldC12YWx1ZQAeD2FzLWxvYWQtb3BlcmFuZAAfEGFzLXVuYXJ5LW9wZXJhbmQAIBFhcy1iaW5hcnktb3BlcmFuZAAhD2FzLXRlc3Qtb3BlcmFuZAAiEmFzLWNvbXBhcmUtb3BlcmFuZAAjEmFzLWJpbmFyeS1vcGVyYW5kcwAkE2FzLWNvbXBhcmUtb3BlcmFuZHMAJRFhcy1taXhlZC1vcGVyYW5kcwAmCmJyZWFrLWJhcmUAJwticmVhay12YWx1ZQAoEWJyZWFrLW11bHRpLXZhbHVlACkOYnJlYWstcmVwZWF0ZWQAKgticmVhay1pbm5lcgArCmNvbnQtaW5uZXIALAVwYXJhbQAtBnBh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 +invalid invalid loop.wast:601 AGFzbQEAAAABBAFgAAADAgEACgkBBwADQEEACws= +invalid invalid loop.wast:609 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAA0ALCw== +invalid invalid loop.wast:613 AGFzbQEAAAABBQFgAAF+AwIBAAoHAQUAA0ALCw== +invalid invalid loop.wast:617 AGFzbQEAAAABBQFgAAF9AwIBAAoHAQUAA0ALCw== +invalid invalid loop.wast:621 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAA0ALCw== +invalid invalid loop.wast:626 AGFzbQEAAAABBAFgAAADAgEACgkBBwADQEEBCws= +invalid invalid loop.wast:632 AGFzbQEAAAABBAFgAAADAgEACgsBCQADQEEBQQILCw== +invalid invalid loop.wast:638 AGFzbQEAAAABBQFgAAF/AwIBAAoHAQUAA38LCw== +invalid invalid loop.wast:644 AGFzbQEAAAABBgFgAAJ/fwMCAQAKBwEFAAMACws= +invalid invalid loop.wast:650 AGFzbQEAAAABBQFgAAF/AwIBAAoIAQYAA38BCws= +invalid invalid loop.wast:656 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCAEGAAMAAQsL +invalid invalid loop.wast:662 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAA39DAAAAAAsL +invalid invalid loop.wast:668 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCQEHAAMAQQALCw== +invalid invalid loop.wast:674 AGFzbQEAAAABBgFgAAJ/fwMCAQAKCwEJAEEBAwBBAgsL +invalid invalid loop.wast:680 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAA39BAUECCws= +invalid invalid loop.wast:686 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAA34AAAAbCws= +invalid invalid loop.wast:693 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAAJAA38LGgsL +invalid invalid loop.wast:702 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAANAA38LGgsL +invalid invalid loop.wast:711 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEABEADfwsaCws= +invalid invalid loop.wast:721 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoIAQYAAwEaCws= +invalid invalid loop.wast:727 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKCQEHAAMBGhoLCw== +invalid invalid loop.wast:733 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoNAQsAQwAAAAADARoLCw== +invalid invalid loop.wast:739 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKDgEMAEMAAAAAAwEaGgsL +invalid invalid loop.wast:745 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoLAQkAAkADARoLCws= +invalid invalid loop.wast:751 AGFzbQEAAAABCQJgAABgAn98AAMCAQAKDAEKAAJAAwEaGgsLCw== +invalid invalid loop.wast:757 AGFzbQEAAAABCAJgAABgAX8AAwIBAAoQAQ4AAkBDAAAAAAMBGgsLCw== +invalid invalid loop.wast:763 AGFzbQEAAAABCQJgAABgAn1/AAMCAQAKEQEPAAJAQwAAAAADARoaCwsL +valid valid memory.wast:3 AGFzbQEAAAAFAwEAAA== +valid valid memory.wast:4 AGFzbQEAAAAFAwEAAQ== +valid valid memory.wast:5 AGFzbQEAAAAFBAEBAAA= +valid valid memory.wast:6 AGFzbQEAAAAFBAEBAAE= +valid valid memory.wast:7 AGFzbQEAAAAFBQEBAYAC +valid valid memory.wast:8 AGFzbQEAAAAFBgEBAICABA== +invalid valid memory.wast:11 AGFzbQEAAAACFAEIc3BlY3Rlc3QGbWVtb3J5AgAABQMBAAA= +valid valid memory.wast:13 AGFzbQEAAAABBQFgAAF/AwIBAAUEAQEAAAcLAQdtZW1zaXplAAAKBgEEAD8ACwsGAQBBAAsA +valid valid memory.wast:17 AGFzbQEAAAABBQFgAAF/AwIBAAUEAQEBAQcLAQdtZW1zaXplAAAKBgEEAD8ACwsHAQBBAAsBeA== +invalid invalid memory.wast:22 AGFzbQEAAAALBwEAQQALAXg= +invalid invalid memory.wast:25 AGFzbQEAAAABBAFgAAADAgEACgoBCABBACoCABoL +invalid invalid memory.wast:29 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAEMAAAAAOAIACw== +invalid invalid memory.wast:33 AGFzbQEAAAABBAFgAAADAgEACgoBCABBACwAABoL +invalid invalid memory.wast:37 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAEEAOgAACw== +invalid invalid memory.wast:41 AGFzbQEAAAABBAFgAAADAgEACgcBBQA/ABoL +invalid invalid memory.wast:45 AGFzbQEAAAABBAFgAAADAgEACgkBBwBBAEAAGgs= +invalid invalid memory.wast:51 AGFzbQEAAAAFBAEBAQA= +invalid invalid memory.wast:55 AGFzbQEAAAAFBQEAgYAE +invalid invalid memory.wast:59 AGFzbQEAAAAFBwEAgICAgAg= +invalid invalid memory.wast:63 AGFzbQEAAAAFBwEA/////w8= +invalid invalid memory.wast:67 AGFzbQEAAAAFBgEBAIGABA== +invalid invalid memory.wast:71 AGFzbQEAAAAFCAEBAICAgIAI +invalid invalid memory.wast:75 AGFzbQEAAAAFCAEBAP////8P +valid valid memory.wast:92 AGFzbQEAAAABEwRgAAF/YAABfGABfwF/YAF+AX4DDQwAAQICAgIDAwMDAwMFAwEAAQehAQwEZGF0YQAABGNhc3QAAQtpMzJfbG9hZDhfcwACC2kzMl9sb2FkOF91AAMMaTMyX2xvYWQxNl9zAAQMaTMyX2xvYWQxNl91AAULaTY0X2xvYWQ4X3MABgtpNjRfbG9hZDhfdQAHDGk2NF9sb2FkMTZfcwAIDGk2NF9sb2FkMTZfdQAJDGk2NF9sb2FkMzJfcwAKDGk2NF9sb2FkMzJfdQALCp8CDE4AQQAtAABBwQBGQQMtAABBpwFGcUEGLQAAQQBGQRMtAABBAEZxcUEULQAAQdcARkEXLQAAQc0ARnFBGC0AAEEARkH/By0AAEEARnFxcQs4AEEIQseffzcDAEEIKwMAQseff79hBEBEAAAAAAAAAAAPC0EJQgA3AABBD0HFgAE7AABBCSsAAAsOAEEIIAA6AABBCCwAAAsOAEEIIAA6AABBCC0AAAsOAEEIIAA7AQBBCC4BAAsOAEEIIAA7AQBBCC8BAAsOAEEIIAA8AABBCDAAAAsOAEEIIAA8AABBCDEAAAsOAEEIIAA9AQBBCDIBAAsOAEEIIAA9AQBBCDMBAAsOAEEIIAA+AgBBCDQCAAsOAEEIIAA+AgBBCDUCAAsLFAIAQQALBUFCQ6dEAEEUCwRXQVNN +valid valid memory.wast:246 AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAQEGFgN/AEGQzgALfwBBkM4AC38AQZDOAAsHOgUGbWVtb3J5AgAKX19kYXRhX2VuZAMAC19fc3RhY2tfdG9wAwELX19oZWFwX2Jhc2UDAgRsb2FkAAAKCQEHACAALQAACw== +valid valid memory_copy.wast:6 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABCg0CAwABCwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:48 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDUECQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:90 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBGUEPQQL8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:132 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDUEZQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:174 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBFEEWQQT8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:216 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBGUEBQQP8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:258 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBCkEMQQf8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:300 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABChYCDABBDEEKQQf8CgAACwcAIAAtAAALCxQCAEECCwQDAQQBAEEMCwUHBQIDBg== +valid valid memory_copy.wast:342 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsaAQBBAAsUAAECAwQFBgcICQoLDA0ODxAREhM= +valid valid memory_copy.wast:703 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsbAQBBAAsVAAECAwQFBgcICQoLDA0ODxAREhMU +valid valid memory_copy.wast:1065 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBB7P8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw== +valid valid memory_copy.wast:1426 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwsdAQBB6/8DCxUAAQIDBAUGBwgJCgsMDQ4PEBESExQ= +valid valid memory_copy.wast:1788 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBBzv8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw== +valid valid memory_copy.wast:2510 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBB4v8DCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw== +valid valid memory_copy.wast:3593 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQMBAAEHFwMDbWVtAgADcnVuAAAHbG9hZDhfdQABChYCDAAgACABIAL8CgAACwcAIAAtAAALCxwBAEHs/wMLFAABAgMEBQYHCAkKCwwNDg8QERIT +valid valid memory_copy.wast:3954 AGFzbQEAAAABDAJgA39/fwBgAX8BfwMDAgABBQQBAQEBBxcDA21lbQIAA3J1bgAAB2xvYWQ4X3UAAQoWAgwAIAAgASAC/AoAAAsHACAALQAACwscAQBBgOADCxQAAQIDBAUGBwgJCgsMDQ4PEBESEw== +invalid invalid memory_copy.wast:4316 AGFzbQEAAAABBAFgAAADAgEABwoBBnRlc3RmbgAACg4BDABBCkEUQR78CgAACw== +invalid invalid memory_copy.wast:4322 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBBCkEUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4329 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABBCkEUQh78CgAACw== +invalid invalid memory_copy.wast:4336 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBBCkEURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4343 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBBCkMAAKBBQR78CgAACw== +invalid invalid memory_copy.wast:4350 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBBCkMAAKBBQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4357 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBBCkMAAKBBQh78CgAACw== +invalid invalid memory_copy.wast:4364 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBBCkMAAKBBRAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4371 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABBCkIUQR78CgAACw== +invalid invalid memory_copy.wast:4378 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBBCkIUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4385 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABBCkIUQh78CgAACw== +invalid invalid memory_copy.wast:4392 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBBCkIURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4399 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBBCkQAAAAAAAA0QEEe/AoAAAs= +invalid invalid memory_copy.wast:4406 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBBCkQAAAAAAAA0QEMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4413 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBBCkQAAAAAAAA0QEIe/AoAAAs= +invalid invalid memory_copy.wast:4420 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBBCkQAAAAAAAA0QEQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4427 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBDAAAgQUEUQR78CgAACw== +invalid invalid memory_copy.wast:4434 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBDAAAgQUEUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4441 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBDAAAgQUEUQh78CgAACw== +invalid invalid memory_copy.wast:4448 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBDAAAgQUEURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4455 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBDAAAgQUMAAKBBQR78CgAACw== +invalid invalid memory_copy.wast:4462 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBDAAAgQUMAAKBBQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4469 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBDAAAgQUMAAKBBQh78CgAACw== +invalid invalid memory_copy.wast:4476 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBDAAAgQUMAAKBBRAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4483 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBDAAAgQUIUQR78CgAACw== +invalid invalid memory_copy.wast:4490 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBDAAAgQUIUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4497 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBDAAAgQUIUQh78CgAACw== +invalid invalid memory_copy.wast:4504 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBDAAAgQUIURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4511 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBDAAAgQUQAAAAAAAA0QEEe/AoAAAs= +invalid invalid memory_copy.wast:4518 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBDAAAgQUQAAAAAAAA0QEMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4525 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBDAAAgQUQAAAAAAAA0QEIe/AoAAAs= +invalid invalid memory_copy.wast:4532 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh8BHQBDAAAgQUQAAAAAAAA0QEQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4539 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABCCkEUQR78CgAACw== +invalid invalid memory_copy.wast:4546 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBCCkEUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4553 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABCCkEUQh78CgAACw== +invalid invalid memory_copy.wast:4560 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBCCkEURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4567 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBCCkMAAKBBQR78CgAACw== +invalid invalid memory_copy.wast:4574 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBCCkMAAKBBQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4581 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBCCkMAAKBBQh78CgAACw== +invalid invalid memory_copy.wast:4588 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBCCkMAAKBBRAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4595 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABCCkIUQR78CgAACw== +invalid invalid memory_copy.wast:4602 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChEBDwBCCkIUQwAA8EH8CgAACw== +invalid invalid memory_copy.wast:4609 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg4BDABCCkIUQh78CgAACw== +invalid invalid memory_copy.wast:4616 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBCCkIURAAAAAAAAD5A/AoAAAs= +invalid invalid memory_copy.wast:4623 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBCCkQAAAAAAAA0QEEe/AoAAAs= +invalid invalid memory_copy.wast:4630 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBCCkQAAAAAAAA0QEMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4637 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBCCkQAAAAAAAA0QEIe/AoAAAs= +invalid invalid memory_copy.wast:4644 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBCCkQAAAAAAAA0QEQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4651 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBEAAAAAAAAJEBBFEEe/AoAAAs= +invalid invalid memory_copy.wast:4658 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBEAAAAAAAAJEBBFEMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4665 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBEAAAAAAAAJEBBFEIe/AoAAAs= +invalid invalid memory_copy.wast:4672 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBEAAAAAAAAJEBBFEQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4679 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBEAAAAAAAAJEBDAACgQUEe/AoAAAs= +invalid invalid memory_copy.wast:4686 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBEAAAAAAAAJEBDAACgQUMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4693 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBEAAAAAAAAJEBDAACgQUIe/AoAAAs= +invalid invalid memory_copy.wast:4700 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh8BHQBEAAAAAAAAJEBDAACgQUQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4707 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBEAAAAAAAAJEBCFEEe/AoAAAs= +invalid invalid memory_copy.wast:4714 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChgBFgBEAAAAAAAAJEBCFEMAAPBB/AoAAAs= +invalid invalid memory_copy.wast:4721 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChUBEwBEAAAAAAAAJEBCFEIe/AoAAAs= +invalid invalid memory_copy.wast:4728 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBEAAAAAAAAJEBCFEQAAAAAAAA+QPwKAAAL +invalid invalid memory_copy.wast:4735 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBEAAAAAAAAJEBEAAAAAAAANEBBHvwKAAAL +invalid invalid memory_copy.wast:4742 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh8BHQBEAAAAAAAAJEBEAAAAAAAANEBDAADwQfwKAAAL +invalid invalid memory_copy.wast:4749 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChwBGgBEAAAAAAAAJEBEAAAAAAAANEBCHvwKAAAL +invalid invalid memory_copy.wast:4756 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACiMBIQBEAAAAAAAAJEBEAAAAAAAANEBEAAAAAAAAPkD8CgAACw== +valid valid memory_copy.wast:4763 AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpAAhYAQQpB1QBBCvwLAEEJQQpBBfwKAAALJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCw== +valid valid memory_copy.wast:4789 AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpAAhYAQQpB1QBBCvwLAEEQQQ9BBfwKAAALJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCw== +valid valid memory_copy.wast:4815 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoTAREAQYD+A0GAgAJBgQL8CgAACw== +valid valid memory_copy.wast:4821 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYB+QYCAAUGBAvwKAAAL +valid valid memory_copy.wast:4827 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoTAREAQYCAAkGA/gNBgQL8CgAACw== +valid valid memory_copy.wast:4833 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCAAUGAfkGBAvwKAAAL +valid valid memory_copy.wast:4839 AGFzbQEAAAABCwJgAABgA39/fwF/AwMCAAEFBAEBAQEHFQIEdGVzdAAACmNoZWNrUmFuZ2UAAQpUAioAQQBB1QBBgIAC/AsAQYCAAkGqAUGAgAL8CwBBgKACQYDgAUEA/AoAAAsnAANAIAAgAUYEQEF/DwsgAC0AACACRgRAIABBAWohAAwBCwsgAA8L +valid valid memory_copy.wast:4863 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCABEGA4AFBAPwKAAAL +valid valid memory_copy.wast:4869 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCACEGA4AFBAPwKAAAL +valid valid memory_copy.wast:4875 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCgAkGAgARBAPwKAAAL +valid valid memory_copy.wast:4881 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCgAkGAgAhBAPwKAAAL +valid valid memory_copy.wast:4887 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCABEGAgARBAPwKAAAL +valid valid memory_copy.wast:4893 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwgBBHRlc3QAAAoSARAAQYCACEGAgAhBAPwKAAAL +valid valid memory_copy.wast:4899 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= +valid valid memory_fill.wast:6 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo5AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsPAEGA/gNB1QBBgAL8CwAL +valid valid memory_fill.wast:28 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo5AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsPAEGA/gNB1QBBgQL8CwAL +valid valid memory_fill.wast:46 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAfkHVAEGBAvwLAAs= +valid valid memory_fill.wast:64 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo2AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsMAEESQdUAQQD8CwAL +valid valid memory_fill.wast:84 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAgARB1QBBAPwLAAs= +valid valid memory_fill.wast:102 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEGAgAhB1QBBAPwLAAs= +valid valid memory_fill.wast:120 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQo4AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsOAEEBQaoBQf7/A/wLAAs= +valid valid memory_fill.wast:145 AGFzbQEAAAABCwJgA39/fwF/YAAAAwMCAAEFBAEBAQEHFQIKY2hlY2tSYW5nZQAABHRlc3QAAQpAAicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsWAEESQdUAQQr8CwBBFUGqAUEE/AsACw== +invalid invalid memory_fill.wast:175 AGFzbQEAAAABBAFgAAADAgEABwoBBnRlc3RmbgAACg0BCwBBCkEUQR78CwAL +invalid invalid memory_fill.wast:181 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBBCkEUQwAA8EH8CwAL +invalid invalid memory_fill.wast:188 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBBCkEUQh78CwAL +invalid invalid memory_fill.wast:195 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBBCkEURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:202 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBBCkMAAKBBQR78CwAL +invalid invalid memory_fill.wast:209 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBBCkMAAKBBQwAA8EH8CwAL +invalid invalid memory_fill.wast:216 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBBCkMAAKBBQh78CwAL +invalid invalid memory_fill.wast:223 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBBCkMAAKBBRAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:230 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBBCkIUQR78CwAL +invalid invalid memory_fill.wast:237 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBBCkIUQwAA8EH8CwAL +invalid invalid memory_fill.wast:244 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBBCkIUQh78CwAL +invalid invalid memory_fill.wast:251 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBBCkIURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:258 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBBCkQAAAAAAAA0QEEe/AsACw== +invalid invalid memory_fill.wast:265 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBBCkQAAAAAAAA0QEMAAPBB/AsACw== +invalid invalid memory_fill.wast:272 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBBCkQAAAAAAAA0QEIe/AsACw== +invalid invalid memory_fill.wast:279 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBBCkQAAAAAAAA0QEQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:286 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBDAAAgQUEUQR78CwAL +invalid invalid memory_fill.wast:293 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBDAAAgQUEUQwAA8EH8CwAL +invalid invalid memory_fill.wast:300 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBDAAAgQUEUQh78CwAL +invalid invalid memory_fill.wast:307 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBDAAAgQUEURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:314 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBDAAAgQUMAAKBBQR78CwAL +invalid invalid memory_fill.wast:321 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChYBFABDAAAgQUMAAKBBQwAA8EH8CwAL +invalid invalid memory_fill.wast:328 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBDAAAgQUMAAKBBQh78CwAL +invalid invalid memory_fill.wast:335 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChoBGABDAAAgQUMAAKBBRAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:342 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBDAAAgQUIUQR78CwAL +invalid invalid memory_fill.wast:349 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBDAAAgQUIUQwAA8EH8CwAL +invalid invalid memory_fill.wast:356 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBDAAAgQUIUQh78CwAL +invalid invalid memory_fill.wast:363 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBDAAAgQUIURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:370 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBDAAAgQUQAAAAAAAA0QEEe/AsACw== +invalid invalid memory_fill.wast:377 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChoBGABDAAAgQUQAAAAAAAA0QEMAAPBB/AsACw== +invalid invalid memory_fill.wast:384 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBDAAAgQUQAAAAAAAA0QEIe/AsACw== +invalid invalid memory_fill.wast:391 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh4BHABDAAAgQUQAAAAAAAA0QEQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:398 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBCCkEUQR78CwAL +invalid invalid memory_fill.wast:405 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBCCkEUQwAA8EH8CwAL +invalid invalid memory_fill.wast:412 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBCCkEUQh78CwAL +invalid invalid memory_fill.wast:419 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBCCkEURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:426 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBCCkMAAKBBQR78CwAL +invalid invalid memory_fill.wast:433 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChMBEQBCCkMAAKBBQwAA8EH8CwAL +invalid invalid memory_fill.wast:440 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBCCkMAAKBBQh78CwAL +invalid invalid memory_fill.wast:447 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBCCkMAAKBBRAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:454 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBCCkIUQR78CwAL +invalid invalid memory_fill.wast:461 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChABDgBCCkIUQwAA8EH8CwAL +invalid invalid memory_fill.wast:468 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACg0BCwBCCkIUQh78CwAL +invalid invalid memory_fill.wast:475 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBCCkIURAAAAAAAAD5A/AsACw== +invalid invalid memory_fill.wast:482 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBCCkQAAAAAAAA0QEEe/AsACw== +invalid invalid memory_fill.wast:489 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBCCkQAAAAAAAA0QEMAAPBB/AsACw== +invalid invalid memory_fill.wast:496 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBCCkQAAAAAAAA0QEIe/AsACw== +invalid invalid memory_fill.wast:503 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBCCkQAAAAAAAA0QEQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:510 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBEAAAAAAAAJEBBFEEe/AsACw== +invalid invalid memory_fill.wast:517 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBEAAAAAAAAJEBBFEMAAPBB/AsACw== +invalid invalid memory_fill.wast:524 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBEAAAAAAAAJEBBFEIe/AsACw== +invalid invalid memory_fill.wast:531 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBEAAAAAAAAJEBBFEQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:538 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBEAAAAAAAAJEBDAACgQUEe/AsACw== +invalid invalid memory_fill.wast:545 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChoBGABEAAAAAAAAJEBDAACgQUMAAPBB/AsACw== +invalid invalid memory_fill.wast:552 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBEAAAAAAAAJEBDAACgQUIe/AsACw== +invalid invalid memory_fill.wast:559 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh4BHABEAAAAAAAAJEBDAACgQUQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:566 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBEAAAAAAAAJEBCFEEe/AsACw== +invalid invalid memory_fill.wast:573 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChcBFQBEAAAAAAAAJEBCFEMAAPBB/AsACw== +invalid invalid memory_fill.wast:580 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChQBEgBEAAAAAAAAJEBCFEIe/AsACw== +invalid invalid memory_fill.wast:587 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBEAAAAAAAAJEBCFEQAAAAAAAA+QPwLAAs= +invalid invalid memory_fill.wast:594 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBEAAAAAAAAJEBEAAAAAAAANEBBHvwLAAs= +invalid invalid memory_fill.wast:601 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACh4BHABEAAAAAAAAJEBEAAAAAAAANEBDAADwQfwLAAs= +invalid invalid memory_fill.wast:608 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAAChsBGQBEAAAAAAAAJEBEAAAAAAAANEBCHvwLAAs= +invalid invalid memory_fill.wast:615 AGFzbQEAAAABBAFgAAADAgEABQQBAQEBBwoBBnRlc3RmbgAACiIBIABEAAAAAAAAJEBEAAAAAAAANEBEAAAAAAAAPkD8CwAL +valid valid memory_fill.wast:621 AGFzbQEAAAABDgJgA39/fwF/YAN/f38AAwMCAAEFBAEBAQEHFAIKY2hlY2tSYW5nZQAAA3J1bgABCjUCJwADQCAAIAFGBEBBfw8LIAAtAAAgAkYEQCAAQQFqIQAMAQsLIAAPCwsAIAAgASAC/AsACw== +valid valid memory_grow.wast:1 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8DBwYAAQABAgAFAwEAAAdXBgxsb2FkX2F0X3plcm8AAA1zdG9yZV9hdF96ZXJvAAERbG9hZF9hdF9wYWdlX3NpemUAAhJzdG9yZV9hdF9wYWdlX3NpemUAAwRncm93AAQEc2l6ZQAFCjUGBwBBACgCAAsJAEEAQQI2AgALCQBBgIAEKAIACwsAQYCABEEDNgIACwYAIABAAAsEAD8ACw== +valid valid memory_grow.wast:36 AGFzbQEAAAABBgFgAX8BfwMCAQAFAwEAAAcIAQRncm93AAAKCAEGACAAQAAL +valid valid memory_grow.wast:50 AGFzbQEAAAABBgFgAX8BfwMCAQAFBAEBAAoHCAEEZ3JvdwAACggBBgAgAEAACw== +valid valid memory_grow.wast:66 AGFzbQEAAAABDAJgAX8Bf2ACf38BfwMDAgABBQMBAAEHHAIEZ3JvdwAAEWNoZWNrLW1lbW9yeS16ZXJvAAEKPAIGACAAQAALMwEBf0EBIQICQANAIAAtAAAhAiACQQBHDQEgACABTw0BIABBAWohACAAIAFNDQALCyACCw== +valid valid memory_grow.wast:101 AGFzbQEAAAABFQRgA39/fwF/YAABf2AAAGACf38BfwMnJgECAQECAQEBAQEBAwMBAAEBAQEBAQECAQIBAQICAgIBAQEBAQEBBAUBcAEBAQUDAQABBgYBfwFBAAsHtwUlC2FzLWJyLXZhbHVlAAANYXMtYnJfaWYtY29uZAABDmFzLWJyX2lmLXZhbHVlAAITYXMtYnJfaWYtdmFsdWUtY29uZAADEWFzLWJyX3RhYmxlLWluZGV4AAQRYXMtYnJfdGFibGUtdmFsdWUABRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAGD2FzLXJldHVybi12YWx1ZQAHCmFzLWlmLWNvbmQACAphcy1pZi10aGVuAAkKYXMtaWYtZWxzZQAKD2FzLXNlbGVjdC1maXJzdAALEGFzLXNlbGVjdC1zZWNvbmQADA5hcy1zZWxlY3QtY29uZAANDWFzLWNhbGwtZmlyc3QADwthcy1jYWxsLW1pZAAQDGFzLWNhbGwtbGFzdAARFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAEhRhcy1jYWxsX2luZGlyZWN0LW1pZAATFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAUFmFzLWNhbGxfaW5kaXJlY3QtaW5kZXgAFRJhcy1sb2NhbC5zZXQtdmFsdWUAFhJhcy1sb2NhbC50ZWUtdmFsdWUAFxNhcy1nbG9iYWwuc2V0LXZhbHVlABgPYXMtbG9hZC1hZGRyZXNzABkQYXMtbG9hZE4tYWRkcmVzcwAaEGFzLXN0b3JlLWFkZHJlc3MAGw5hcy1zdG9yZS12YWx1ZQAcEWFzLXN0b3JlTi1hZGRyZXNzAB0PYXMtc3RvcmVOLXZhbHVlAB4QYXMtdW5hcnktb3BlcmFuZAAfDmFzLWJpbmFyeS1sZWZ0ACAPYXMtYmluYXJ5LXJpZ2h0ACEPYXMtdGVzdC1vcGVyYW5kACIPYXMtY29tcGFyZS1sZWZ0ACMQYXMtY29tcGFyZS1yaWdodAAkE2FzLW1lbW9yeS5ncm93LXNpemUAJQkHAQBBAAsBDgraAyYLAAJ/QQBAAAwACwsLAAJAQQBAAA0ACwsQAAJ/QQBAAEEBDQAaQQcLCxAAAn9BBkEAQAANABpBBwsLDgACQEEAQAAOAgAAAAsLEgACf0EAQABBAQ4CAAAAQQcLCxEAAn9BBkEAQAAOAQAAQQcLCwcAQQBAAA8LDgBBAEAABH9BAAVBAQsLDgBBAQR/QQBAAAVBAAsLDgBBAAR/QQAFQQBAAAsLCwBBAEAAIAAgARsLCwAgAEEAQAAgARsLCwBBAEEBQQBAABsLBABBfwsMAEEAQABBAkEDEA4LDABBAUEAQABBAxAOCwwAQQFBAkEAQAAQDgsPAEEAQABBAkEDQQARAAALDwBBAUEAQABBA0EAEQAACw8AQQFBAkEAQABBABEAAAsPAEEBQQJBA0EAQAARAAALCgEBf0EAQAAhAAsKAQF/QQBAACIACwoBAX9BAEAAJAALCQBBAEAAKAIACwkAQQBAACwAAAsLAEEAQABBBzYCAAsLAEECQQBAADYCAAsLAEEAQABBBzoAAAsLAEECQQBAADsBAAsHAEEAQABnCwkAQQBAAEEKagsJAEEKQQBAAGsLBwBBAEAARQsJAEEAQABBCkwLCQBBCkEAQABHCwgAQQBAAEAACw== +valid valid memory_grow.wast:312 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABBxECBm1lbW9yeQIABGdyb3cAAAoIAQYAQQFAAAs= +valid valid memory_grow.wast:318 AGFzbQEAAAABBQFgAAF/AhgBDGdyb3duLW1lbW9yeQZtZW1vcnkCAAIDAgEABxECBm1lbW9yeQIABGdyb3cAAAoIAQYAQQFAAAs= +valid valid memory_grow.wast:325 AGFzbQEAAAABBQFgAAF/AiEBFWdyb3duLWltcG9ydGVkLW1lbW9yeQZtZW1vcnkCAAMDAgEABwgBBHNpemUAAAoGAQQAPwAL +invalid invalid memory_grow.wast:334 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACgYBBABAAAs= +invalid invalid memory_grow.wast:343 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACgsBCQBBAAJ/QAALCw== +invalid invalid memory_grow.wast:353 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACgsBCQBBAAN/QAALCw== +invalid invalid memory_grow.wast:363 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACg0BCwBBAEEABH9AAAsL +invalid invalid memory_grow.wast:374 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgsBCQBDAAAAAEAACw== +invalid invalid memory_grow.wast:384 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCAEGAEEAQAAL +invalid invalid memory_grow.wast:393 AGFzbQEAAAABBQFgAAF9AwIBAAUDAQABCggBBgBBAEAACw== +valid valid memory_init.wast:6 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABCg0CAwABCwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY= +valid valid memory_init.wast:50 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEChYCDABBB0EAQQT8CAEACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY= +valid valid memory_init.wast:94 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEChYCDABBD0EBQQP8CAMACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY= +valid valid memory_init.wast:138 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQQBAQEBBxwDB21lbW9yeTACAAR0ZXN0AAAHbG9hZDhfdQABDAEEClgCTgBBB0EAQQT8CAEA/AkBQQ9BAUED/AgDAPwJA0EUQQ9BBfwKAABBFUEdQQH8CgAAQRhBCkEB/AoAAEENQQtBBPwKAABBE0EUQQX8CgAACwcAIAAtAAALCyEEAEECCwQDAQQBAQQCBwEIAEEMCwUHBQIDBgEFBQkCBwY= +invalid invalid memory_init.wast:190 AGFzbQEAAAABBAFgAAADAgEABwgBBHRlc3QAAAoHAQUA/AkACw== +invalid invalid memory_init.wast:196 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCgcBBQD8CQQLCwQBAQE3 +valid valid memory_init.wast:203 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCgoBCAD8CQD8CQALCwQBAQE3 +valid valid memory_init.wast:211 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChIBEAD8CQBB0glBAUEB/AgAAAsLBAEBATc= +valid valid memory_init.wast:219 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAUEB/AgAAAsLBwEAQQALATc= +invalid invalid memory_init.wast:227 AGFzbQEAAAABBAFgAAADAgEABwgBBHRlc3QAAAoPAQ0AQdIJQQFBAfwIAQAL +invalid invalid memory_init.wast:233 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAUEB/AgBAAsLBAEBATc= +valid valid memory_init.wast:240 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBBAUEAQQH8CAAAQQFBAEEB/AgAAAsLBAEBATc= +valid valid memory_init.wast:248 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAEEF/AgAAAsLBAEBATc= +valid valid memory_init.wast:255 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAkED/AgAAAsLBAEBATc= +valid valid memory_init.wast:262 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBB/v8DQQFBA/wIAAALCwQBAQE3 +valid valid memory_init.wast:269 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBBEEA/AgAAAsLBAEBATc= +valid valid memory_init.wast:276 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg8BDQBB0glBAUEA/AgAAAsLBAEBATc= +valid valid memory_init.wast:283 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgYAEQQBBAPwIAAALCwQBAQE3 +valid valid memory_init.wast:290 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgIAEQQBBAPwIAAALCwQBAQE3 +valid valid memory_init.wast:297 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgIAEQQFBAPwIAAALCwQBAQE3 +valid valid memory_init.wast:304 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChABDgBBgYAEQQRBAPwIAAALCwQBAQE3 +invalid invalid memory_init.wast:312 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBBAUEBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:320 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABBAUEBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:328 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBBAUEBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:336 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBBAUMAAIA/QQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:344 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBBAUMAAIA/QwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:352 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBBAUMAAIA/QgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:360 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBBAUMAAIA/RAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:368 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABBAUIBQQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:376 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBBAUIBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:384 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABBAUIBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:392 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBBAUIBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:400 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBBAUQAAAAAAADwP0EB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:408 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBBAUQAAAAAAADwP0MAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:416 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBBAUQAAAAAAADwP0IB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:424 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBBAUQAAAAAAADwP0QAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:432 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBDAACAP0EBQQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:440 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBDAACAP0EBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:448 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBDAACAP0EBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:456 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBDAACAP0EBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:464 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBDAACAP0MAAIA/QQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:472 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChcBFQBDAACAP0MAAIA/QwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:480 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBDAACAP0MAAIA/QgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:488 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChsBGQBDAACAP0MAAIA/RAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:496 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBDAACAP0IBQQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:504 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBDAACAP0IBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:512 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBDAACAP0IBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:520 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBDAACAP0IBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:528 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBDAACAP0QAAAAAAADwP0EB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:536 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChsBGQBDAACAP0QAAAAAAADwP0MAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:544 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBDAACAP0QAAAAAAADwP0IB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:552 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCh8BHQBDAACAP0QAAAAAAADwP0QAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:560 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABCAUEBQQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:568 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBCAUEBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:576 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABCAUEBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:584 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBCAUEBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:592 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBCAUMAAIA/QQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:600 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChQBEgBCAUMAAIA/QwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:608 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBCAUMAAIA/QgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:616 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBCAUMAAIA/RAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:624 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABCAUIBQQH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:632 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChEBDwBCAUIBQwAAgD/8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:640 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCg4BDABCAUIBQgH8CAAACwsEAQEBNw== +invalid invalid memory_init.wast:648 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBCAUIBRAAAAAAAAPA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:656 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBCAUQAAAAAAADwP0EB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:664 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBCAUQAAAAAAADwP0MAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:672 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBCAUQAAAAAAADwP0IB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:680 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBCAUQAAAAAAADwP0QAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:688 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBEAAAAAAAA8D9BAUEB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:696 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBEAAAAAAAA8D9BAUMAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:704 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBEAAAAAAAA8D9BAUIB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:712 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBEAAAAAAAA8D9BAUQAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:720 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBEAAAAAAAA8D9DAACAP0EB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:728 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChsBGQBEAAAAAAAA8D9DAACAP0MAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:736 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBEAAAAAAAA8D9DAACAP0IB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:744 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCh8BHQBEAAAAAAAA8D9DAACAP0QAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:752 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBEAAAAAAAA8D9CAUEB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:760 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChgBFgBEAAAAAAAA8D9CAUMAAIA//AgAAAsLBAEBATc= +invalid invalid memory_init.wast:768 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChUBEwBEAAAAAAAA8D9CAUIB/AgAAAsLBAEBATc= +invalid invalid memory_init.wast:776 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBEAAAAAAAA8D9CAUQAAAAAAADwP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:784 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBEAAAAAAAA8D9EAAAAAAAA8D9BAfwIAAALCwQBAQE3 +invalid invalid memory_init.wast:792 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCh8BHQBEAAAAAAAA8D9EAAAAAAAA8D9DAACAP/wIAAALCwQBAQE3 +invalid invalid memory_init.wast:800 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBChwBGgBEAAAAAAAA8D9EAAAAAAAA8D9CAfwIAAALCwQBAQE3 +invalid invalid memory_init.wast:808 AGFzbQEAAAABBAFgAAADAgEABQMBAAEHCAEEdGVzdAAADAEBCiMBIQBEAAAAAAAA8D9EAAAAAAAA8D9EAAAAAAAA8D/8CAAACwsEAQEBNw== +valid valid memory_init.wast:815 AGFzbQEAAAABDQJgA39/fwF/YAJ/fwADAwIAAQUEAQEBAQcUAgpjaGVja1JhbmdlAAADcnVuAAEMAQEKNgInAANAIAAgAUYEQEF/DwsgAC0AACACRgRAIABBAWohAAwBCwsgAA8LDAAgAEEAIAH8CAAACwsTAQEQQkJCQkJCQkJCQkJCQkJCQg== +valid valid memory_init.wast:907 AGFzbQEAAAABDQJgA39/fwF/YAJ/fwADAwIAAQUDAQABBxQCCmNoZWNrUmFuZ2UAAANydW4AAQwBAQo2AicAA0AgACABRgRAQX8PCyAALQAAIAJGBEAgAEEBaiEADAELCyAADwsMACAAQQAgAfwIAAALCxMBARBCQkJCQkJCQkJCQkJCQkJC +valid valid memory_init.wast:954 AGFzbQEAAAABBAFgAAADAgEABQMBAAEMAUEKDgEMAEEAQQBBAPwIQAALC4MBQQEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQA= +valid valid memory_redundancy.wast:5 AGFzbQEAAAABEQRgAABgAAF/YAABfWABfwF/AwcGAAEBAgMBBQQBAQEBB2sGD3plcm9fZXZlcnl0aGluZwAAEnRlc3Rfc3RvcmVfdG9fbG9hZAABE3Rlc3RfcmVkdW5kYW50X2xvYWQAAg90ZXN0X2RlYWRfc3RvcmUAAwZtYWxsb2MABA9tYWxsb2NfYWxpYXNpbmcABQqlAQYeAEEAQQA2AgBBBEEANgIAQQhBADYCAEEMQQA2AgALGABBCEEANgIAQQVDAAAAgDgCAEEIKAIACyIBAn9BCCgCACEAQQVBgICAgHg2AgBBCCgCACEBIAAgAWoLHwEBfUEIQaPGjJkCNgIAQQsqAgAhAEEIQQA2AgAgAAsEAEEQCyMBAn9BBBAEIQBBBBAEIQEgAEEqNgIAIAFBKzYCACAAKAIACw== +valid valid memory_size.wast:1 AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQMBAAAHDwIEc2l6ZQAABGdyb3cAAQoOAgQAPwALBwAgAEAAGgs= +valid valid memory_size.wast:15 AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQMBAAEHDwIEc2l6ZQAABGdyb3cAAQoOAgQAPwALBwAgAEAAGgs= +valid valid memory_size.wast:29 AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQQBAQACBw8CBHNpemUAAARncm93AAEKDgIEAD8ACwcAIABAABoL +valid valid memory_size.wast:47 AGFzbQEAAAABCQJgAAF/YAF/AAMDAgABBQQBAQMIBw8CBHNpemUAAARncm93AAEKDgIEAD8ACwcAIABAABoL +invalid invalid memory_size.wast:69 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKBgEEAD8ACw== +invalid invalid memory_size.wast:78 AGFzbQEAAAABBQFgAAF9AwIBAAUDAQABCgYBBAA/AAs= +valid valid memory_trap.wast:1 AGFzbQEAAAABDwNgAAF/YAJ/fwBgAX8BfwMFBAABAgIFAwEAAQceAwVzdG9yZQABBGxvYWQAAgttZW1vcnkuZ3JvdwADCioECQA/AEGAgARsCwwAEAAgAGogATYCAAsKABAAIABqKAIACwYAIABAAAs= +valid valid memory_trap.wast:35 AGFzbQEAAAABKQhgAX8Bf2ABfwF+YAF/AX1gAX8BfGACf38AYAJ/fgBgAn99AGACf3wAAxgXAAECAwAAAAABAQEBAQEEBQYHBAQFBQUFAwEAAQezAhcIaTMyLmxvYWQAAAhpNjQubG9hZAABCGYzMi5sb2FkAAIIZjY0LmxvYWQAAwtpMzIubG9hZDhfcwAEC2kzMi5sb2FkOF91AAUMaTMyLmxvYWQxNl9zAAYMaTMyLmxvYWQxNl91AAcLaTY0LmxvYWQ4X3MACAtpNjQubG9hZDhfdQAJDGk2NC5sb2FkMTZfcwAKDGk2NC5sb2FkMTZfdQALDGk2NC5sb2FkMzJfcwAMDGk2NC5sb2FkMzJfdQANCWkzMi5zdG9yZQAOCWk2NC5zdG9yZQAPCWYzMi5zdG9yZQAQCWY2NC5zdG9yZQARCmkzMi5zdG9yZTgAEgtpMzIuc3RvcmUxNgATCmk2NC5zdG9yZTgAFAtpNjQuc3RvcmUxNgAVC2k2NC5zdG9yZTMyABYKywEXBwAgACgCAAsHACAAKQMACwcAIAAqAgALBwAgACsDAAsHACAALAAACwcAIAAtAAALBwAgAC4BAAsHACAALwEACwcAIAAwAAALBwAgADEAAAsHACAAMgEACwcAIAAzAQALBwAgADQCAAsHACAANQIACwkAIAAgATYCAAsJACAAIAE3AwALCQAgACABOAIACwkAIAAgATkDAAsJACAAIAE6AAALCQAgACABOwEACwkAIAAgATwAAAsJACAAIAE9AQALCQAgACABPgIACwsdAgBBAAsIYWJjZGVmZ2gAQfj/AwsIYWJjZGVmZ2g= +valid valid names.wast:4 AGFzbQEAAAABBQFgAAF/AwIBAAcHAQNmb28AAAoGAQQAQQAL +valid valid names.wast:12 AGFzbQEAAAABBQFgAAF/AwIBAAcHAQNmb28AAAoGAQQAQQEL +valid valid names.wast:19 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+/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BQBB8wALBQBB9AALBQBB9QALBQBB9gALBQBB9wALBQBB+AALBQBB+QALBQBB+gALBQBB+wALBQBB/AALBQBB/QALBQBB/gALBQBB/wALBQBBgAELBQBBgQELBQBBggELBQBBgwELBQBBhAELBQBBhQELBQBBhgELBQBBhwELBQBBiAELBQBBiQELBQBBigELBQBBiwELBQBBjAELBQBBjQELBQBBjgELBQBBjwELBQBBkAELBQBBkQELBQBBkgELBQBBkwELBQBBlAELBQBBlQELBQBBlgELBQBBlwELBQBBmAELBQBBmQELBQBBmgELBQBBmwELBQBBnAELBQBBnQELBQBBngELBQBBnwELBQBBoAELBQBBoQELBQBBogELBQBBowELBQBBpAELBQBBpQELBQBBpgELBQBBpwELBQBBqAELBQBBqQELBQBBqgELBQBBqwELBQBBrAELBQBBrQELBQBBrgELBQBBrwELBQBBsAELBQBBsQELBQBBsgELBQBBswELBQBBtAELBQBBtQELBQBBtgELBQBBtwELBQBBuAELBQBBuQELBQBBugELBQBBuwELBQBBvAELBQBBvQELBQBBvgELBQBBvwELBQBBwAELBQBBwQELBQBBwgELBQBBwwELBQBBxAELBQBBxQELBQBBxgELBQBBxwELBQBByAELBQBByQELBQBBygELBQBBywELBQBBzAELBQBBzQELBQBBzgELBQBBzwELBQBB0AELBQBB0QELBQBB0gELBQBB0wELBQBB1AELBQBB1QELBQBB1gELBQBB1wELBQBB2AELBQBB2QELBQBB2gELBQBB2wELBQBB3AELBQBB3QELBQBB3gELBQBB3wELBQBB4AELBQBB4QELBQBB4gELBQBB4wELBQBB5AELBQBB5QELBQBB5gELBQBB5wELBQBB6AELBQBB6QELBQBB6gELBQBB6wELBQBB7AELBQBB7QELBQBB7gELBQBB7wELBQBB8AELBQBB8QELBQBB8gELBQBB8wELBQBB9AELBQBB9QELBQBB9gELBQBB9wELBQBB+AELBQBB+QELBQBB+gELBQBB+wELBQBB/AELBQBB/QELBQBB/gELBQBB/wELBQBBgAILBQBBgQILBQBBggILBQBBgwILBQBBhAILBQBBhQILBQBBhgILBQBBhwILBQBBiAILBQBBiQILBQBBigILBQBBiwILBQBBjAILBQBBjQILBQBBjgILBQBBjwILBQBBkAILBQBBkQILBQBBkgILBQBBkwILBQBBlAILBQBBlQILBQBBlgILBQBBlwILBQBBmAILBQBBmQILBQBBmgILBQBBmwILBQBBnAILBQBBnQILBQBBngILBQBBnwILBQBBoAILBQBBoQILBQBBogILBQBBowILBQBBpAILBQBBpQILBQBBpgILBQBBpwILBQBBqAILBQBBqQILBQBBqgILBQBBqwILBQBBrAILBQBBrQILBQBBrgILBQBBrwILBQBBsAILBQBBsQILBQBBsgILBQBBswILBQBBtAILBQBBtQILBQBBtgILBQBBtwILBQBBuAILBQBBuQILBQBBugILBQBBuwILBQBBvAILBQBBvQILBQBBvgILBQBBvwILBQBBwAILBQBBwQILBQBBwgILBQBBwwILBQBBxAILBQBBxQILBQBBxgILBQBBxwILBQBByAILBQBByQILBQBBygILBQBBywILBQBBzAILBQBBzQILBQBBzgILBQBBzwILBQBB0AILBQBB0QILBQBB0gILBQBB0wILBQBB1AILBQBB1QILBQBB1gILBQBB1wILBQBB2AILBQBB2QILBQBB2gILBQBB2wILBQBB3AILBQBB3QILBQBB3gILBQBB3wILBQBB4AILBQBB4QILBQBB4gILBQBB4wILBQBB5AILBQBB5QILBQBB5gILBQBB5wILBQBB6AILBQBB6QILBQBB6gILBQBB6wILBQBB7AILBQBB7QILBQBB7gILBQBB7wILBQBB8AILBQBB8QILBQBB8gILBQBB8wILBQBB9AILBQBB9QILBQBB9gILBQBB9wILBQBB+AILBQBB+QILBQBB+gILBQBB+wILBQBB/AILBQBB/QILBQBB/gILBQBB/wILBQBBgAMLBQBBgQMLBQBBggMLBQBBgwMLBQBBhAMLBQBBhQMLBQBBhgMLBQBBhwMLBQBBiAMLBQBBiQMLBQBBigMLBQBBiwMLBQBBjAMLBQBBjQMLBQBBjgMLBQBBjwMLBQBBkAMLBQBBkQMLBQBBkgMLBQBBkwMLBQBBlAMLBQBBlQMLBQBBlgMLBQBBlwMLBQBBmAMLBQBBmQMLBQBBmgMLBQBBmwMLBQBBnAMLBQBBnQMLBQBBngMLBQBBnwMLBQBBoAMLBQBBoQMLBQBBogMLBQBBowMLBQBBpAMLBQBBpQMLBQBBpgMLBQBBpwMLBQBBqAMLBQBBqQMLBQBBqgMLBQBBqwMLBQBBrAMLBQBBrQMLBQBBrgMLBQBBrwMLBQBBsAMLBQBBsQMLBQBBsgMLBQBBswMLBQBBtAMLBQBBtQMLBQBBtgMLBQBBtwMLBQBBuAMLBQBBuQMLBQBBugMLBQBBuwMLBQBBvAMLBQBBvQMLBQBBvgMLBQBBvwMLBQBBwAMLBQBBwQMLBQBBwgMLBQBBwwMLBQBBxAMLBQBBxQMLBQBBxgMLBQBBxwMLBQBByAMLBQBByQMLBQBBygMLBQBBywMLBQBBzAMLBQBBzQMLBQBBzgMLBQBBzwMLBQBB0AMLBQBB0QMLBQBB0gMLBQBB0wMLBQBB1AMLBQBB1QMLBQBB1gMLBQBB1wMLBQBB2AMLBQBB2QMLBQBB2gMLBQBB2wMLBQBB3AMLBQBB3QMLBQBB3gML +valid valid names.wast:1095 AGFzbQEAAAABCgJgAX8AYAJ/fwACKwIIc3BlY3Rlc3QJcHJpbnRfaTMyAAAIc3BlY3Rlc3QJcHJpbnRfaTMyAAADAgEBBwsBB3ByaW50MzIAAgoMAQoAIAAQACABEAEL +valid valid nop.wast:3 AGFzbQEAAAABIwdgAn9/AX9gAABgA39/fwF/YAABf2ABfwBgAX8Bf2ACf38AA1RTAQIDAwMDBAQEBQUFBQUDAwMDAwMDAwQEBAUFBQUFBQUFBQUFBQUFAgICAgIFBQUFBQUFBQUFBQUFBQUFBQADAwMDAwUFBQUFBQMDAwUFBQYGBgYEBQFwAQEBBQMBAAEGBgF/AUEACwfqC1ANYXMtZnVuYy1maXJzdAACC2FzLWZ1bmMtbWlkAAMMYXMtZnVuYy1sYXN0AAQSYXMtZnVuYy1ldmVyeXdoZXJlAAUNYXMtZHJvcC1maXJzdAAGDGFzLWRyb3AtbGFzdAAHEmFzLWRyb3AtZXZlcnl3aGVyZQAID2FzLXNlbGVjdC1maXJzdAAJDmFzLXNlbGVjdC1taWQxAAoOYXMtc2VsZWN0LW1pZDIACw5hcy1zZWxlY3QtbGFzdAAMFGFzLXNlbGVjdC1ldmVyeXdoZXJlAA0OYXMtYmxvY2stZmlyc3QADgxhcy1ibG9jay1taWQADw1hcy1ibG9jay1sYXN0ABATYXMtYmxvY2stZXZlcnl3aGVyZQARDWFzLWxvb3AtZmlyc3QAEgthcy1sb29wLW1pZAATDGFzLWxvb3AtbGFzdAAUEmFzLWxvb3AtZXZlcnl3aGVyZQAVD2FzLWlmLWNvbmRpdGlvbgAWCmFzLWlmLXRoZW4AFwphcy1pZi1lbHNlABgLYXMtYnItZmlyc3QAGQphcy1ici1sYXN0ABoQYXMtYnItZXZlcnl3aGVyZQAbDmFzLWJyX2lmLWZpcnN0ABwMYXMtYnJfaWYtbWlkAB0NYXMtYnJfaWYtbGFzdAAeE2FzLWJyX2lmLWV2ZXJ5d2hlcmUAHxFhcy1icl90YWJsZS1maXJzdAAgD2FzLWJyX3RhYmxlLW1pZAAhEGFzLWJyX3RhYmxlLWxhc3QAIhZhcy1icl90YWJsZS1ldmVyeXdoZXJlACMPYXMtcmV0dXJuLWZpcnN0ACQOYXMtcmV0dXJuLWxhc3QAJRRhcy1yZXR1cm4tZXZlcnl3aGVyZQAmDWFzLWNhbGwtZmlyc3QAJwxhcy1jYWxsLW1pZDEAKAxhcy1jYWxsLW1pZDIAKQxhcy1jYWxsLWxhc3QAKhJhcy1jYWxsLWV2ZXJ5d2hlcmUAKw5hcy11bmFyeS1maXJzdAAsDWFzLXVuYXJ5LWxhc3QALRNhcy11bmFyeS1ldmVyeXdoZXJlAC4PYXMtYmluYXJ5LWZpcnN0AC8NYXMtYmluYXJ5LW1pZAAwDmFzLWJpbmFyeS1sYXN0ADEUYXMtYmluYXJ5LWV2ZXJ5d2hlcmUAMg1hcy10ZXN0LWZpcnN0ADMMYXMtdGVzdC1sYXN0ADQSYXMtdGVzdC1ldmVyeXdoZXJlADUQYXMtY29tcGFyZS1maXJzdAA2DmFzLWNvbXBhcmUtbWlkADcPYXMtY29tcGFyZS1sYXN0ADgVYXMtY29tcGFyZS1ldmVyeXdoZXJlADkUYXMtbWVtb3J5Lmdyb3ctZmlyc3QAOhNhcy1tZW1vcnkuZ3Jvdy1sYXN0ADsZYXMtbWVtb3J5Lmdyb3ctZXZlcnl3aGVyZQA8FmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAPhVhcy1jYWxsX2luZGlyZWN0LW1pZDEAPxVhcy1jYWxsX2luZGlyZWN0LW1pZDIAQBVhcy1jYWxsX2luZGlyZWN0LWxhc3QAQRthcy1jYWxsX2luZGlyZWN0LWV2ZXJ5d2hlcmUAQhJhcy1sb2NhbC5zZXQtZmlyc3QAQxFhcy1sb2NhbC5zZXQtbGFzdABEF2FzLWxvY2FsLnNldC1ldmVyeXdoZXJlAEUSYXMtbG9jYWwudGVlLWZpcnN0AEYRYXMtbG9jYWwudGVlLWxhc3QARxdhcy1sb2NhbC50ZWUtZXZlcnl3aGVyZQBIE2FzLWdsb2JhbC5zZXQtZmlyc3QASRJhcy1nbG9iYWwuc2V0LWxhc3QAShhhcy1nbG9iYWwuc2V0LWV2ZXJ5d2hlcmUASw1hcy1sb2FkLWZpcnN0AEwMYXMtbG9hZC1sYXN0AE0SYXMtbG9hZC1ldmVyeXdoZXJlAE4OYXMtc3RvcmUtZmlyc3QATwxhcy1zdG9yZS1taWQAUA1hcy1zdG9yZS1sYXN0AFETYXMtc3RvcmUtZXZlcnl3aGVyZQBSCQcBAEEACwE9CqIHUwIACwoAIAAgASACa2oLBQABQQELBwAQAAFBAgsHABAAQQMBCwsAAQEQAAFBBAEBCwYAASAAGgsGACAAARoLCQABASAAAQEaCwoAASAAIAAgABsLCgAgAAEgACAAGwsKACAAIAABIAAbCwoAIAAgACAAARsLEAABIAABASAAAQEgAAEBGwsIAAJ/AUECCwsKAAJ/EAABQQILCwsAAn8BEABBAwELCw4AAn8BARAAAUEEAQELCwgAA38BQQILCwoAA38QAAFBAgsLCgADfxAAQQMBCwsOAAN/AQEQAAFBBAEBCwsKACAAAQRAEAALCwsAIAAEQAEFEAALCwsAIAAEQBAABQELCwoAAn8BIAAMAAsLCgACfyAAAQwACwsNAAJ/AQEgAAEBDAALCwwAAn8BIAAgAA0ACwsMAAJ/IAABIAANAAsLDAACfyAAIAABDQALCxEAAn8BASAAAQEgAAEBDQALCw4AAn8BIAAgAA4BAAALCw4AAn8gAAEgAA4BAAALCw4AAn8gACAAAQ4BAAALCxMAAn8BASAAAQEgAAEBDgEAAAsLBgABIAAPCwYAIAABDwsJAAEBIAABAQ8LCwABIAAgASACEAELCwAgAAEgASACEAELCwAgACABASACEAELCwAgACABIAIBEAELEgABASAAAQEgAQEBIAIBARABCwYAASAAaAsGACAAAWgLCQABASAAAQFoCwgAASAAIABqCwgAIAABIABqCwgAIAAgAAFqCwwAASAAAQEgAAEBagsGAAEgAEULBgAgAAFFCwkAAQEgAAEBRQsIAAEgACAARwsIACAAASAARwsIACAAIAABSQsMAAEgAAEBIAABAUwLBwABIABAAAsHACAAAUAACwoAAQEgAAEBQAALBAAgAAsPAAJ/AUEBQQJBABEAAAsLDwACf0EBAUECQQARAAALCw8AAn9BAUECAUEAEQAACwsPAAJ/QQFBAkEAAREAAAsLFgACfwEBQQEBAUECAQFBAAEBEQAACwsJAAFBAiEAIAALCQBBAgEhACAACwwAAQFBAgEBIQAgAAsHAAFBAiIACwcAQQIBIgALCgABAUECAQEiAAsJAAFBAiQAIwALCQBBAgEkACMACwwAAQFBAgEBJAAjAAsIAAEgACgCAAsIACAAASgCAAsLAAEBIAABASgCAAsKAAEgACABNgIACwoAIAABIAE2AgALCgAgACABATYCAAsPAAEBIAABASABAQE2AgAL +invalid invalid nop.wast:416 AGFzbQEAAAABBQFgAAF+AwIBAAoFAQMAAQs= +invalid invalid nop.wast:420 AGFzbQEAAAABBQFgAAF9AwIBAAoFAQMAAQs= +invalid invalid nop.wast:424 AGFzbQEAAAABBQFgAAF8AwIBAAoFAQMAAQs= +valid valid ref_func.wast:1 AGFzbQEAAAABBgFgAX8BfwMCAQAHBQEBZgAACgYBBAAgAAs= +valid valid ref_func.wast:6 AGFzbQEAAAABDQNgAX8Bf2AAAGAAAX8CBwEBTQFmAAADDw4AAQEBAQECAgIBAQAAAAQEAXAAAQYaBXAA0gALcADSAQtwAdIAC3AA0gMLcADSBAsHUAgJaXNfbnVsbC1mAAcJaXNfbnVsbC1nAAgJaXNfbnVsbC12AAkFc2V0LWYACgVzZXQtZwALBmNhbGwtZgAMBmNhbGwtZwANBmNhbGwtdgAOCRADAwACAwUDAAIEBgMAAgABCm4OBwAgAEEBagsIANIFGtIGGgsCAAsCAAsCAAsCAAsFANIA0QsFANIB0QsFACMC0QsGANIAJAILBgDSASQCCw8AQQDSACYAIABBABEAAAsPAEEA0gEmACAAQQARAAALDwBBACMCJgAgAEEAEQAACw== +invalid invalid ref_func.wast:69 AGFzbQEAAAABBgFgAX8BfwINAgFNAWYAAAFNAWcAAAYGAXAA0gcL +valid valid ref_func.wast:80 AGFzbQEAAAABBAFgAAADCAcAAAAAAAAABAQBcAABBgYBcADSAAsHBQEBZgABCRUEAEEACwECAEEACwEDAQABBAEAAQUKIwcCAAsCAAsCAAsCAAsCAAsCAAsPANIA0gHSAtID0gTSBQ8L +invalid invalid ref_func.wast:109 AGFzbQEAAAABBAFgAAADAgEACgcBBQDSABoL +invalid invalid ref_func.wast:113 AGFzbQEAAAABBAFgAAADAgEACAEACgcBBQDSABoL +valid valid ref_is_null.wast:1 AGFzbQEAAAABFwVgAXABf2ABbwF/YAAAYAFvAGABfwF/AwgHAAECAwIEBAQHAnAAAm8AAgdHBgdmdW5jcmVmAAAJZXh0ZXJucmVmAAEEaW5pdAADBmRlaW5pdAAEDGZ1bmNyZWYtZWxlbQAFDmV4dGVybnJlZi1lbGVtAAYJBwEAQQELAQIKOgcFACAA0QsFACAA0QsCAAsIAEEBIAAmAQsOAEEB0HAmAEEB0G8mAQsIACAAJQAQAAsIACAAJQEQAQs= +invalid invalid ref_is_null.wast:52 AGFzbQEAAAABBQFgAX8AAwIBAAoHAQUAIADRCw== +invalid invalid ref_is_null.wast:56 AGFzbQEAAAABBAFgAAADAgEACgUBAwDRCw== +valid valid ref_null.wast:1 AGFzbQEAAAABCQJgAAFvYAABcAMDAgABBgsCbwDQbwtwANBwCwcXAglleHRlcm5yZWYAAAdmdW5jcmVmAAEKCwIEANBvCwQA0HAL +valid valid return.wast:3 AGFzbQEAAAABIQdgA39/fwF/YAAAYAABf2AAAX5gAAF9YAABfGACf38BfwM+PQEBAQEBAgMEBQEFAgIBAgEBAQICAgICAQICAwICAwIGBgYGAgACAgICAgICAgICBAMCAgICBAIDAgICAgIEBQFwAQEBBQMBAAEGBgF/AUEACwf4BzsIdHlwZS1pMzIAAQh0eXBlLWk2NAACCHR5cGUtZjMyAAMIdHlwZS1mNjQABA50eXBlLWkzMi12YWx1ZQAFDnR5cGUtaTY0LXZhbHVlAAYOdHlwZS1mMzItdmFsdWUABw50eXBlLWY2NC12YWx1ZQAIB251bGxhcnkACQV1bmFyeQAKDWFzLWZ1bmMtZmlyc3QACwthcy1mdW5jLW1pZAAMDGFzLWZ1bmMtbGFzdAANDWFzLWZ1bmMtdmFsdWUADg5hcy1ibG9jay1maXJzdAAPDGFzLWJsb2NrLW1pZAAQDWFzLWJsb2NrLWxhc3QAEQ5hcy1ibG9jay12YWx1ZQASDWFzLWxvb3AtZmlyc3QAEwthcy1sb29wLW1pZAAUDGFzLWxvb3AtbGFzdAAVC2FzLWJyLXZhbHVlABYNYXMtYnJfaWYtY29uZAAXDmFzLWJyX2lmLXZhbHVlABgTYXMtYnJfaWYtdmFsdWUtY29uZAAZEWFzLWJyX3RhYmxlLWluZGV4ABoRYXMtYnJfdGFibGUtdmFsdWUAGxdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAcD2FzLXJldHVybi12YWx1ZQAdCmFzLWlmLWNvbmQAHgphcy1pZi10aGVuAB8KYXMtaWYtZWxzZQAgD2FzLXNlbGVjdC1maXJzdAAhEGFzLXNlbGVjdC1zZWNvbmQAIg5hcy1zZWxlY3QtY29uZAAjDWFzLWNhbGwtZmlyc3QAJQthcy1jYWxsLW1pZAAmDGFzLWNhbGwtbGFzdAAnFWFzLWNhbGxfaW5kaXJlY3QtZnVuYwAoFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAKRRhcy1jYWxsX2luZGlyZWN0LW1pZAAqFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAArEmFzLWxvY2FsLnNldC12YWx1ZQAsEmFzLWxvY2FsLnRlZS12YWx1ZQAtE2FzLWdsb2JhbC5zZXQtdmFsdWUALg9hcy1sb2FkLWFkZHJlc3MALxBhcy1sb2FkTi1hZGRyZXNzADAQYXMtc3RvcmUtYWRkcmVzcwAxDmFzLXN0b3JlLXZhbHVlADIRYXMtc3RvcmVOLWFkZHJlc3MAMw9hcy1zdG9yZU4tdmFsdWUANBBhcy11bmFyeS1vcGVyYW5kADUOYXMtYmluYXJ5LWxlZnQANg9hcy1iaW5hcnktcmlnaHQANw9hcy10ZXN0LW9wZXJhbmQAOA9hcy1jb21wYXJlLWxlZnQAORBhcy1jb21wYXJlLXJpZ2h0ADoSYXMtY29udmVydC1vcGVyYW5kADsTYXMtbWVtb3J5Lmdyb3ctc2l6ZQA8CQcBAEEACwEkCqkFPQIACwUAD2gaCwUAD3oaCwUAD4waCwUAD5oaCwkAAn9BAQ9oCwsJAAJ+QgIPegsLDAACfUMAAEBAD4wLCxAAAnxEAAAAAAAAEEAPmgsLAwAPCwwARAAAAAAAAAhADwsHAEEBD0ECCwkAEABBAg9BAwsGAAEQAA8LCAABEABBAw8LCAACQA8QAAsLCgACQBAADxAACwsJAAJAARAADwsLCwACfwEQAEECDwsLCgADf0EDD0ECCwsMAAN/EABBBA9BAgsLCwADfwEQAEEFDwsLCgACf0EJDwwACwsIAAJADw0ACwsPAAJ/QQgPQQENABpBBwsLDwACf0EGQQkPDQAaQQcLCw8AAkBCCQ8OAgAAAAtCfwsRAAJ/QQoPQQEOAgAAAEEHCwsQAAJ/QQZBCw8OAQAAQQcLCwYAQgcPDwsNAEECDwR/QQAFQQELCw0AIAAEf0EDDwUgAQsLDQAgAAR/IAEFQQQPCwsKAEEFDyAAIAEbCwoAIABBBg8gARsLCgBBAEEBQQcPGwsEAEF/CwsAQQwPQQJBAxAkCwsAQQFBDQ9BAxAkCwsAQQFBAkEODxAkCw4AQRQPQQFBAkEDEQAACw4AQQBBFQ9BAkEDEQAACw4AQQBBAUEWD0EDEQAACw4AQQBBAUECQRcPEQAACwsBAX1BEQ8hAEF/CwkBAX9BAQ8iAAsHAEEBDyQACwsAQ5qZ2T8PKgIACwgAQh4PMAAACxMAQR4PRAAAAAAAABxAOQMAQX8LDABBAkEfDzcDAEF/CwwAQSAPQQc6AABBfwsMAEECQSEPPQEAQX8LCQBDmplZQA+MCwgAQQMPQQpqCwgAQgpCLQ99CwYAQSwPRQsPAEErD0QAAAAAAAAkQGULCwBDAAAgQUEqD1wLBgBBKQ+nCwcAQSgPQAAL +invalid invalid return.wast:315 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAQQACQA8LCw== +invalid invalid return.wast:324 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAQQADQA8LCw== +invalid invalid return.wast:333 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQQBBAARADwsL +invalid invalid return.wast:342 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AQQBBAAR/QQAFDwsaCw== +invalid invalid return.wast:351 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQQACQA8MAAsL +invalid invalid return.wast:360 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQACQA9BAQ0ACws= +invalid invalid return.wast:369 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAQQACQA8OAAALCw== +invalid invalid return.wast:378 AGFzbQEAAAABBQFgAAF/AwIBAAoGAQQADw8L +invalid invalid return.wast:386 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAD0EBQQIbCw== +invalid invalid return.wast:394 AGFzbQEAAAABCgJgAAF/YAF/AX8DAwIAAQoMAgUADxABCwQAIAAL +invalid invalid return.wast:403 AGFzbQEAAAABCgJgAX8Bf2AAAX8DAwIAAQQFAXABAQEJBwEAQQALAQAKEgIEACAACwsAAn8PQQARAAALCw== +invalid invalid return.wast:418 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkBAX8PIQAgAAs= +invalid invalid return.wast:427 AGFzbQEAAAABBQFgAAF/AwIBAAoJAQcBAX8PIgAL +invalid invalid return.wast:436 AGFzbQEAAAABBQFgAAF/AwIBAAYGAX8BQQALCgkBBwAPJAAjAAs= +invalid invalid return.wast:445 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACgcBBQAPQAAL +invalid invalid return.wast:454 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQAACggBBgAPKAIACw== +invalid invalid return.wast:463 AGFzbQEAAAABBQFgAAF/AwIBAAUDAQABCgoBCAAPQQE2AgAL +invalid invalid return.wast:472 AGFzbQEAAAABBQFgAAF8AwIBAAoGAQQAAQ8L +invalid invalid return.wast:476 AGFzbQEAAAABBQFgAAF8AwIBAAoHAQUAQgEPCw== +valid valid select.wast:1 AGFzbQEAAAABPQpgAn9/AX9gAABgA39/fwF/YAN+fn8BfmADfX1/AX1gA3x8fwF8YANwcH8BcGADb29/AW9gAX8Bf2ABfwADLy4BAgMEBQIDBAUGBwgICAgICAkICAgICAgACAgICQkICAgICQgICAgICAgICAgIBAkCcAEBAXABAQEFAwEAAQYGAX8BQQoLB/AFKwpzZWxlY3QtaTMyAAEKc2VsZWN0LWk2NAACCnNlbGVjdC1mMzIAAwpzZWxlY3QtZjY0AAQMc2VsZWN0LWkzMi10AAUMc2VsZWN0LWk2NC10AAYMc2VsZWN0LWYzMi10AAcMc2VsZWN0LWY2NC10AAgOc2VsZWN0LWZ1bmNyZWYACRBzZWxlY3QtZXh0ZXJucmVmAAoPYXMtc2VsZWN0LWZpcnN0AAsNYXMtc2VsZWN0LW1pZAAMDmFzLXNlbGVjdC1sYXN0AA0NYXMtbG9vcC1maXJzdAAOC2FzLWxvb3AtbWlkAA8MYXMtbG9vcC1sYXN0ABAPYXMtaWYtY29uZGl0aW9uABEKYXMtaWYtdGhlbgASCmFzLWlmLWVsc2UAEw5hcy1icl9pZi1maXJzdAAUDWFzLWJyX2lmLWxhc3QAFRFhcy1icl90YWJsZS1maXJzdAAWEGFzLWJyX3RhYmxlLWxhc3QAFxZhcy1jYWxsX2luZGlyZWN0LWZpcnN0ABkUYXMtY2FsbF9pbmRpcmVjdC1taWQAGhVhcy1jYWxsX2luZGlyZWN0LWxhc3QAGw5hcy1zdG9yZS1maXJzdAAcDWFzLXN0b3JlLWxhc3QAHRRhcy1tZW1vcnkuZ3Jvdy12YWx1ZQAeDWFzLWNhbGwtdmFsdWUAIA9hcy1yZXR1cm4tdmFsdWUAIQ9hcy1kcm9wLW9wZXJhbmQAIgthcy1ici12YWx1ZQAjEmFzLWxvY2FsLnNldC12YWx1ZQAkEmFzLWxvY2FsLnRlZS12YWx1ZQAlE2FzLWdsb2JhbC5zZXQtdmFsdWUAJg9hcy1sb2FkLW9wZXJhbmQAJxBhcy11bmFyeS1vcGVyYW5kACgRYXMtYmluYXJ5LW9wZXJhbmQAKQ9hcy10ZXN0LW9wZXJhbmQAKg9hcy1jb21wYXJlLWxlZnQAKxBhcy1jb21wYXJlLXJpZ2h0ACwSYXMtY29udmVydC1vcGVyYW5kAC0JDwIAQQALAQACAUEACwABGAqABS4CAAsJACAAIAEgAhsLCQAgACABIAIbCwkAIAAgASACGwsJACAAIAEgAhsLCwAgACABIAIcAX8LCwAgACABIAIcAX4LCwAgACABIAIcAX0LCwAgACABIAIcAXwLCwAgACABIAIcAXALCwAgACABIAIcAW8LDgBBAEEBIAAbQQJBAxsLDgBBAkEAQQEgABtBAxsLDgBBAkEDQQBBASAAGxsLEAADf0ECQQMgABsQABAACwsQAAN/EABBAkEDIAAbEAALCxAAA38QABAAQQJBAyAAGwsLDgBBAkEDIAAbBEAQAAsLEQBBAQR/QQJBAyAAGwVBBAsLEQBBAAR/QQIFQQJBAyAAGwsLEAACf0ECQQMgABtBBA0ACwsQAAJ/QQJBAkEDIAAbDQALCxIAAn9BAkEDIAAbQQIOAQAACwsSAAJ/QQJBAkEDIAAbDgEAAAsLBAAgAAsTAAJ/QQJBAyAAG0EBQQARAAELCxMAAn9BAUECQQMgABtBABEAAQsLEwACf0EBQQRBAkEDIAAbEQABCwsOAEEAQQQgABtBATYCAAsOAEEIQQFBAiAAGzYCAAsLAEEBQQIgABtAAAsEACAACwsAQQFBAiAAGxAfCwoAQQFBAiAAGw8LCgBBAUECIAAbGgsOAAJ/QQFBAiAAGwwACwsPAQF/QQFBAiAAGyEAIAALCwBBAUECIAAbIgALDQBBAUECIAAbJAAjAAsMAEEAQQQgABsoAgALCgBBAEEBIAAbRQsRAEEBQQIgABtBAUECIAAbbAsNAAJ/QQBBASAAG0ULCw8AAn9BAUECIAAbQQFMCwsPAAJ/QQFBAEEBIAAbRwsLDQACf0IBQgAgABunCws= +invalid invalid select.wast:320 AGFzbQEAAAABBAFgAAADAgEACgkBBwABAUEBGws= +invalid invalid select.wast:328 AGFzbQEAAAABBgFgAAJ/fwMCAQAKEgEQAEEAQQBBAEEAQQEcAn9/Cw== +invalid invalid select.wast:340 AGFzbQEAAAABBQFgAW8AAwIBAAoMAQoAIAAgAEEBGxoL +invalid invalid select.wast:347 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAUIBQQEbGgs= +invalid invalid select.wast:353 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAUMAAIA/QQEbGgs= +invalid invalid select.wast:359 AGFzbQEAAAABBAFgAAADAgEAChMBEQBBAUQAAAAAAADwP0EBGxoL +invalid invalid select.wast:388 AGFzbQEAAAABBAFgAAADAgEACgYBBAAbGgs= +invalid invalid select.wast:396 AGFzbQEAAAABBAFgAAADAgEACggBBgBBABsaCw== +invalid invalid select.wast:404 AGFzbQEAAAABBAFgAAADAgEACgoBCABBAEEAGxoL +invalid invalid select.wast:412 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAQQACQBsaCws= +invalid invalid select.wast:421 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAAkBBABsaCws= +invalid invalid select.wast:430 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAAJAQQBBABsaCws= +invalid invalid select.wast:439 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAQQADQBsaCws= +invalid invalid select.wast:448 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAA0BBABsaCws= +invalid invalid select.wast:457 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAANAQQBBABsaCws= +invalid invalid select.wast:466 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEAQQAEQBsaCws= +invalid invalid select.wast:475 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAEEABEBBABsaCws= +invalid invalid select.wast:484 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAARAQQBBABsaCws= +invalid invalid select.wast:496 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAUEBQgEbGgs= +invalid invalid select.wast:500 AGFzbQEAAAABBAFgAAADAgEACg8BDQBBAUEBQwAAgD8bGgs= +invalid invalid select.wast:504 AGFzbQEAAAABBAFgAAADAgEAChMBEQBBAUEBRAAAAAAAAPA/GxoL +invalid invalid select.wast:511 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAQgFCAUEBGws= +valid valid select.wast:518 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAAEBAFwAAEKUAsEAAAbCwUAABsBCwUAABsbCwUAABsbCwYAABsbGwsGAAAcAX8LBgAAHAF/CwcAABwBfxsLCQAAHAF/HAF/CwcAABsRAQALCAAAGxEBABsL +valid valid skip-stack-guard-page.wast:2 AGFzbQEAAAABCAJgAX8AYAAAAwMCAAEFAwEAAQcYARR0ZXN0LWd1YXJkLXBhZ2Utc2tpcAAACuCQAQIUACAAQQBGBEAQAQUgAEEBaxAACwvHkAEBoAh+EAFBACkAACEAQQApAAEhAUEAKQACIQJBACkAAyEDQQApAAQhBEEAKQAFIQVBACkABiEGQQApAAchB0EAKQAIIQhBACkACSEJQQApAAohCkEAKQALIQtBACkADCEMQQApAA0hDUEAKQAOIQ5BACkADyEPQQApABAhEEEAKQARIRFBACkAEiESQQApABMhE0EAKQAUIRRBACkAFSEVQQApABYhFkEAKQAXIRdBACkAGCEYQQApABkhGUEAKQAaIRpBACkAGyEbQQApABwhHEEAKQAdIR1BACkAHiEeQQApAB8hH0EAKQAgISBBACkAISEhQQApACIhIkEAKQAjISNBACkAJCEkQQApACUhJUEAKQAmISZBACkAJyEnQQApACghKEEAKQApISlBACkAKiEqQQApACshK0EAKQAsISxBACkALSEtQQApAC4hLkEAKQAvIS9BACkAMCEwQQApADEhMUEAKQAyITJBACkAMyEzQQApADQhNEEAKQA1ITVBACkANiE2QQApADchN0EAKQA4IThBACkAOSE5QQApADohOkEAKQA7ITtBACkAPCE8QQApAD0hPUEAKQA+IT5BACkAPyE/QQApAEAhQEEAKQBBIUFBACkAQiFCQQApAEMhQ0EAKQBEIURBACkARSFFQQApAEYhRkEAKQBHIUdBACkASCFIQQApAEkhSUEAKQBKIUpBACkASyFLQQApAEwhTEEAKQBNIU1BACkATiFOQQApAE8hT0EAKQBQIVBBACkAUSFRQQApAFIhUkEAKQBTIVNBACkAVCFUQQApAFUhVUEAKQBWIVZBACkAVyFXQQApAFghWEEAKQBZIVlBACkAWiFaQQApAFshW0EAKQBcIVxBACkAXSFdQQApAF4hXkEAKQBfIV9BACkAYCFgQQApAGEhYUEAKQBiIWJBACkAYyFjQQApAGQhZEEAKQBlIWVBACkAZiFmQQApAGchZ0EAKQBoIWhBACkAaSFpQQApAGohakEAKQBrIWtBACkAbCFsQQApAG0hbUEAKQBuIW5BACkAbyFvQQApAHAhcEEAKQBxIXFBACkAciFyQQApAHMh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QQAg3wc3AN8HQQAg4Ac3AOAHQQAg4Qc3AOEHQQAg4gc3AOIHQQAg4wc3AOMHQQAg5Ac3AOQHQQAg5Qc3AOUHQQAg5gc3AOYHQQAg5wc3AOcHQQAg6Ac3AOgHQQAg6Qc3AOkHQQAg6gc3AOoHQQAg6wc3AOsHQQAg7Ac3AOwHQQAg7Qc3AO0HQQAg7gc3AO4HQQAg7wc3AO8HQQAg8Ac3APAHQQAg8Qc3APEHQQAg8gc3APIHQQAg8wc3APMHQQAg9Ac3APQHQQAg9Qc3APUHQQAg9gc3APYHQQAg9wc3APcHQQAg+Ac3APgHQQAg+Qc3APkHQQAg+gc3APoHQQAg+wc3APsHQQAg/Ac3APwHQQAg/Qc3AP0HQQAg/gc3AP4HQQAg/wc3AP8HQQAggAg3AIAIQQAggQg3AIEIQQAgggg3AIIIQQAggwg3AIMIQQAghAg3AIQIQQAghQg3AIUIQQAghgg3AIYIQQAghwg3AIcIQQAgiAg3AIgIQQAgiQg3AIkIQQAgigg3AIoIQQAgiwg3AIsIQQAgjAg3AIwIQQAgjQg3AI0IQQAgjgg3AI4IQQAgjwg3AI8IQQAgkAg3AJAIQQAgkQg3AJEIQQAgkgg3AJIIQQAgkwg3AJMIQQAglAg3AJQIQQAglQg3AJUIQQAglgg3AJYIQQAglwg3AJcIQQAgmAg3AJgIQQAgmQg3AJkIQQAgmgg3AJoIQQAgmwg3AJsIQQAgnAg3AJwIQQAgnQg3AJ0IQQAgngg3AJ4IQQAgnwg3AJ8ICw== +valid valid stack.wast:1 AGFzbQEAAAABDQNgAX4BfmAAAX9gAAADCQgAAAAAAAECAQYGAX8BQQALB1cGCGZhYy1leHByAAAJZmFjLXN0YWNrAAENZmFjLXN0YWNrLXJhdwACCWZhYy1taXhlZAADDWZhYy1taXhlZC1yYXcABBBub3QtcXVpdGUtYS10cmVlAAcKjwIILwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILLwECfiAAIQFCASECAkADQCABQgBRBEAMAgUgASACfiECIAFCAX0hAQsMAAsLIAILDQEBf0EBIwBqJAAjAAsFABAFGgsJABAFEAUQBmoL +valid valid stack.wast:156 AGFzbQEAAAABDANgAABgAX8AYAABfwMCAQAEBAFwAAEKtAMBsQMAAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBAEEAEQEACwNAQQBBABEBAAtBAARAQQBBABEBAAtBAARAQQBBABEBAAVBAEEAEQEACwJ/QQARAgALGgN/QQARAgALGkEABH9BABECAAVBABECAAsaAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALAkBBAEEAEQEACwNAQQBBABEBAAtBAARAQQBBABEBAAtBAARAQQBBABEBAAVBAEEAEQEACwJ/QQARAgALGgN/QQARAgALGkEABH9BABECAAVBABECAAsaAkBBABEAAAsDQEEAEQAAC0EABEBBABEAAAtBAARAQQARAAAFQQARAAALQQARAAAL +invalid invalid start.wast:2 AGFzbQEAAAABBAFgAAADAgEACAEBCgQBAgAL +invalid invalid start.wast:7 AGFzbQEAAAABBQFgAAF/AwIBAAgBAAoHAQUAQQAPCw== +invalid invalid start.wast:14 AGFzbQEAAAABBQFgAX8AAwIBAAgBAAoEAQIACw== +valid valid start.wast:21 AGFzbQEAAAABCAJgAABgAAF/AwQDAAEABQQBAQEBBw0CA2luYwAAA2dldAABCAECCiMDDwBBAEEALQAAQQFqOgAACwgAQQAtAAAPCwgAEAAQABAACwsHAQBBAAsBQQ== +valid valid start.wast:80 AGFzbQEAAAABCAJgAX8AYAAAAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQgBAQoIAQYAQQEQAAs= +valid valid start.wast:86 AGFzbQEAAAABCAJgAX8AYAAAAhYBCHNwZWN0ZXN0CXByaW50X2kzMgAAAwIBAQgBAQoIAQYAQQIQAAs= +valid valid start.wast:92 AGFzbQEAAAABBAFgAAACEgEIc3BlY3Rlc3QFcHJpbnQAAAgBAA== +valid valid start.wast:98 AGFzbQEAAAABBAFgAAADAgEACAEACgUBAwAACw== +valid valid store.wast:3 AGFzbQEAAAABBAFgAAADCgkAAAAAAAAAAAAFAwEAAQeXAQkOYXMtYmxvY2stdmFsdWUAAA1hcy1sb29wLXZhbHVlAAELYXMtYnItdmFsdWUAAg5hcy1icl9pZi12YWx1ZQADE2FzLWJyX2lmLXZhbHVlLWNvbmQABBFhcy1icl90YWJsZS12YWx1ZQAFD2FzLXJldHVybi12YWx1ZQAGCmFzLWlmLXRoZW4ABwphcy1pZi1lbHNlAAgKiAEJDAACQEEAQQE2AgALCwwAA0BBAEEBNgIACwsOAAJAQQBBATYCAAwACwsQAAJAQQBBATYCAEEBDQALCxAAAkBBBkEAQQE2AgANAAsLEQACQEEAQQE2AgBBAQ4AAAsLCgBBAEEBNgIADwsOAEEBBEBBAEEBNgIACwsPAEEABEAFQQBBATYCAAsL +invalid invalid store.wast:112 AGFzbQEAAAABBgFgAX8BfwMCAQAFAwEAAQoLAQkAQQBBATYCAAs= +invalid invalid store.wast:116 AGFzbQEAAAABBgFgAX4BfgMCAQAFAwEAAQoLAQkAQQBCATcDAAs= +invalid invalid store.wast:120 AGFzbQEAAAABBgFgAX0BfQMCAQAFAwEAAQoOAQwAQQBDAACAPzgCAAs= +invalid invalid store.wast:124 AGFzbQEAAAABBgFgAXwBfAMCAQAFAwEAAQoSARAAQQBEAAAAAAAA8D85AwAL +invalid invalid store.wast:128 AGFzbQEAAAABBgFgAX8BfwMCAQAFAwEAAQoLAQkAQQBBAToAAAs= +invalid invalid store.wast:132 AGFzbQEAAAABBgFgAX8BfwMCAQAFAwEAAQoLAQkAQQBBATsBAAs= +invalid invalid store.wast:136 AGFzbQEAAAABBgFgAX4BfgMCAQAFAwEAAQoLAQkAQQBCATwAAAs= +invalid invalid store.wast:140 AGFzbQEAAAABBgFgAX4BfgMCAQAFAwEAAQoLAQkAQQBCAT0BAAs= +invalid invalid store.wast:144 AGFzbQEAAAABBgFgAX4BfgMCAQAFAwEAAQoLAQkAQQBCAT4CAAs= +invalid invalid store.wast:150 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKBwEFADYCAAs= +invalid invalid store.wast:159 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCQEHAEEANgIACw== +invalid invalid store.wast:168 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQQACQDYCAAsL +invalid invalid store.wast:178 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAAkBBADYCAAsL +invalid invalid store.wast:188 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQQADQDYCAAsL +invalid invalid store.wast:198 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAA0BBADYCAAsL +invalid invalid store.wast:208 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQQAEQDYCAAsL +invalid invalid store.wast:218 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEABEBBADYCAAsL +invalid invalid store.wast:228 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAEEAQQAEf0EABTYCAAsL +invalid invalid store.wast:238 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAEEABH9BAAVBADYCAAsL +invalid invalid store.wast:248 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAEEAQQACQDYCAAwACws= +invalid invalid store.wast:258 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEAEOAEEAAkBBADYCAAwACws= +invalid invalid store.wast:268 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAEEAQQACQDYCAEEBDQALCw== +invalid invalid store.wast:278 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAEEAAkBBADYCAEEBDQALCw== +invalid invalid store.wast:288 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAEEAQQACQDYCAA4AAAsL +invalid invalid store.wast:298 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAEEAAkBBADYCAA4AAAsL +invalid invalid store.wast:308 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCAEGADYCAA8L +invalid invalid store.wast:317 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCgEIAEEANgIADws= +invalid invalid store.wast:326 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDAEKADYCAEEBQQIbCw== +invalid invalid store.wast:335 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEANgIAQQFBAhsL +invalid invalid store.wast:344 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQMBAAEKDgIHADYCABABCwQAIAAL +invalid invalid store.wast:354 AGFzbQEAAAABCQJgAABgAX8BfwMDAgABBQMBAAEKEAIJAEEANgIAEAELBAAgAAs= +invalid invalid store.wast:364 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQUDAQABCQcBAEEACwEAChQCBAAgAAsNAAJ/NgIAQQARAAALCw== +invalid invalid store.wast:380 AGFzbQEAAAABCQJgAX8Bf2AAAAMDAgABBAUBcAEBAQUDAQABCQcBAEEACwEAChYCBAAgAAsPAAJ/QQA2AgBBABEAAAsL +invalid invalid store.wast:399 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQQA2AgAL +invalid invalid store.wast:400 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQQA6AAAL +invalid invalid store.wast:401 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQQA7AQAL +invalid invalid store.wast:402 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQQA3AwAL +invalid invalid store.wast:403 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQgA8AAAL +invalid invalid store.wast:404 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQgA9AQAL +invalid invalid store.wast:405 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEMAAAAAQgA+AgAL +invalid invalid store.wast:406 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEQEPAEMAAAAAQwAAAAA4AgAL +invalid invalid store.wast:407 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKFQETAEMAAAAARAAAAAAAAAAAOQMACw== +invalid invalid store.wast:409 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQwAAAAA2AgAL +invalid invalid store.wast:410 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQwAAAAA6AAAL +invalid invalid store.wast:411 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQwAAAAA7AQAL +invalid invalid store.wast:412 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKDgEMAEEAQwAAAAA3AwAL +invalid invalid store.wast:413 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAEEARAAAAAAAAAAAPAAACw== +invalid invalid store.wast:414 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAEEARAAAAAAAAAAAPQEACw== +invalid invalid store.wast:415 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKEgEQAEEARAAAAAAAAAAAPgIACw== +invalid invalid store.wast:416 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCwEJAEEAQQA4AgAL +invalid invalid store.wast:417 AGFzbQEAAAABBAFgAAADAgEABQMBAAEKCwEJAEEAQgA5AwAL +valid valid switch.wast:1 AGFzbQEAAAABDwNgAX8Bf2ABfgF+YAABfwMFBAABAAIHHgQEc3RtdAAABGV4cHIAAQNhcmcAAgZjb3JuZXIAAwreAQRXAQF/QeQAIQECQAJAAkACQAJAAkACQAJAAkACQCAADggAAQIDBAUGCAcLIAAPCwELC0EAIABrIQEMBQsMBAtB5QAhAQwDC0HlACEBC0HmACEBCwsgAQ8LTAEBfkLkACEBAn4CQAJAAkACQAJAAkACQAJAAkAgAKcOCAABAgMGBQQIBwsgAA8LAQsLQgAgAH0MBQtC5QAhAQsLCyABDAELQnsLDwsqAAJ/QQoCf0HkAAJ/QegHAn9BAiAAbEEDIABxDgMBAgMAC2oLagtqCw8LDAACQEEADgAAC0EBCw== +invalid invalid switch.wast:150 AGFzbQEAAAABBAFgAAADAgEACgkBBwBBAA4AAws= +invalid invalid table-sub.wast:2 AGFzbQEAAAABBAFgAAADAgEABAcCcAAKbwAKCg4BDABBAEEBQQL8DgABCw== +invalid invalid table-sub.wast:13 AGFzbQEAAAABBAFgAAADAgEABAQBcAAKCQQBBW8ACg4BDABBAEEBQQL8DAAACw== +valid valid table.wast:3 AGFzbQEAAAAEBAFwAAA= +valid valid table.wast:4 AGFzbQEAAAAEBAFwAAE= +valid valid table.wast:5 AGFzbQEAAAAEBQFwAQAA +valid valid table.wast:6 AGFzbQEAAAAEBQFwAQAB +valid valid table.wast:7 AGFzbQEAAAAEBgFwAQGAAg== +valid valid table.wast:8 AGFzbQEAAAAEBwFwAQCAgAQ= +valid valid table.wast:9 AGFzbQEAAAAECQFwAQD/////Dw== +valid valid table.wast:11 AGFzbQEAAAAEBwJwAABwAAA= +valid valid table.wast:12 AGFzbQEAAAACFAEIc3BlY3Rlc3QFdGFibGUBcAAABAQBcAAA +invalid invalid table.wast:19 AGFzbQEAAAAEBQFwAQEA +invalid invalid table.wast:23 AGFzbQEAAAAECQFwAf////8PAA== +valid valid table_copy.wast:6 AGFzbQEAAAABBQFgAAF/AwYFAAAAAAAHHwUDZWYwAAADZWYxAAEDZWYyAAIDZWYzAAMDZWY0AAQKGgUEAEEACwQAQQELBABBAgsEAEEDCwQAQQQL +valid valid table_copy.wast:15 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCi4IBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwMAAQsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:107 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BAkED/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:199 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBD0EC/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:291 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BGUED/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:383 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRRBFkEE/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:475 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBAUED/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:567 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBDEEH/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:659 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQxBCkEH/A4AAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:751 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgIBQQMLAAQBAwEEAgFBCwsABQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBAEEU/A4BAAsHACAAEQAACwcAIAARAAEL +valid valid table_copy.wast:843 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCi4IBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwMAAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:935 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BAkED/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1027 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBD0EC/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1119 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQ1BGUED/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1211 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRRBFkEE/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1303 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQRlBAUED/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1395 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBDEEH/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1487 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQxBCkEH/A4BAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1579 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwkIAAAAAAABAgIECQJwAR4ecAEeHgceAwR0ZXN0AAoIY2hlY2tfdDAACwhjaGVja190MQAMCToGAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYAQQMLBAEDAQQAQQsLBQYDAgUHCjcIBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwwAQQpBAEEU/A4AAQsHACAAEQABCwcAIAARAAAL +valid valid table_copy.wast:1671 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wOAAAL +valid valid table_copy.wast:1696 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEF+QQFBAvwOAAAL +valid valid table_copy.wast:1721 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBBvwOAAAL +valid valid table_copy.wast:1746 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQX5BAvwOAAAL +valid valid table_copy.wast:1771 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBAPwOAAAL +valid valid table_copy.wast:1796 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQ9BAPwOAAAL +valid valid table_copy.wast:1821 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQ9BAPwOAAAL +valid valid table_copy.wast:1846 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR5BAPwOAAAL +valid valid table_copy.wast:1871 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR9BAPwOAAAL +valid valid table_copy.wast:1896 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQR5BAPwOAAAL +valid valid table_copy.wast:1921 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQR9BAPwOAAAL +valid valid table_copy.wast:1946 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wOAQAL +valid valid table_copy.wast:1971 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEF+QQFBAvwOAQAL +valid valid table_copy.wast:1996 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBBvwOAQAL +valid valid table_copy.wast:2021 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQX5BAvwOAQAL +valid valid table_copy.wast:2046 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQRlBAPwOAQAL +valid valid table_copy.wast:2071 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQ9BAPwOAQAL +valid valid table_copy.wast:2096 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQ9BAPwOAQAL +valid valid table_copy.wast:2121 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR5BAPwOAQAL +valid valid table_copy.wast:2146 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQR9BAPwOAQAL +valid valid table_copy.wast:2171 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQR5BAPwOAQAL +valid valid table_copy.wast:2196 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEeHgcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQR9BAPwOAQAL +valid valid table_copy.wast:2221 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEACwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL +valid valid table_copy.wast:2282 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ8BAEEACwkAAQIDBAUGBwgKZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw== +valid valid table_copy.wast:2343 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEYCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL +valid valid table_copy.wast:2404 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ8BAEEXCwkAAQIDBAUGBwgKZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw== +valid valid table_copy.wast:2465 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEELCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL +valid valid table_copy.wast:2587 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCQ4BAEEVCwgAAQIDBAUGBwpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL +valid valid table_copy.wast:2709 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBQFwASBAB2QSAmYwAAACZjEAAQJmMgACAmYzAAMCZjQABAJmNQAFAmY2AAYCZjcABwJmOAAIAmY5AAkDZjEwAAoDZjExAAsDZjEyAAwDZjEzAA0DZjE0AA4DZjE1AA8EdGVzdAAQA3J1bgARCREBAEEVCwsAAQIDBAUGBwgJCgpmEgQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLBABBCgsEAEELCwQAQQwLBABBDQsEAEEOCwQAQQ8LBwAgABEAAAsMACAAIAEgAvwOAAAL +valid valid table_copy.wast:2770 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBwFwAYABgAEHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFwEAQfAACxAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIAAgASAC/A4AAAs= +valid valid table_copy.wast:2927 AGFzbQEAAAABEANgAAF/YAF/AX9gA39/fwADExIAAAAAAAAAAAAAAAAAAAAAAQIEBwFwAYABgAEHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFgEAQQALEAABAgMEBQYHCAkKCwwNDg8KZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgACABIAL8DgAACw== +valid valid table_fill.wast:1 AGFzbQEAAAABDAJgA39vfwBgAX8BbwMEAwAAAQQEAW8ACgccAwRmaWxsAAALZmlsbC1hYmJyZXYAAQNnZXQAAgogAwsAIAAgASAC/BEACwsAIAAgASAC/BEACwYAIAAlAAs= +invalid invalid table_fill.wast:75 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgcBBQD8EQAL +invalid invalid table_fill.wast:84 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgsBCQDQb0EB/BEACw== +invalid invalid table_fill.wast:93 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgsBCQBBAUEB/BEACw== +invalid invalid table_fill.wast:102 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgsBCQBBAdBv/BEACw== +invalid invalid table_fill.wast:111 AGFzbQEAAAABBAFgAAADAgEABAQBbwAAChABDgBDAACAP9BvQQH8EQAL +invalid invalid table_fill.wast:120 AGFzbQEAAAABBQFgAW8AAwIBAAQEAXAAAAoNAQsAQQEgAEEB/BEACw== +invalid invalid table_fill.wast:129 AGFzbQEAAAABBAFgAAADAgEABAQBbwAAChABDgBBAdBvQwAAgD/8EQAL +invalid invalid table_fill.wast:139 AGFzbQEAAAABBQFgAW8AAwIBAAQHAm8AAXAAAQoNAQsAQQAgAEEB/BEBCw== +invalid invalid table_fill.wast:150 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8AAQoNAQsAQQDQb0EB/BEACw== +valid valid table_get.wast:1 AGFzbQEAAAABFwVgAABgAW8AYAF/AW9gAX8BcGABfwF/AwYFAAECAwQEBwJvAAJwAAMHOAQEaW5pdAABDWdldC1leHRlcm5yZWYAAgtnZXQtZnVuY3JlZgADD2lzX251bGwtZnVuY3JlZgAECQkBAgFBAQsAAQAKKwUCAAsQAEEBIAAmAEECQQElASYBCwYAIAAlAAsGACAAJQELBwAgABAD0Qs= +invalid invalid table_get.wast:42 AGFzbQEAAAABBQFgAAFvAwIBAAQEAW8ACgoGAQQAJQAL +invalid invalid table_get.wast:51 AGFzbQEAAAABBQFgAAFvAwIBAAQEAW8ACgoLAQkAQwAAgD8lAAs= +invalid invalid table_get.wast:61 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCggBBgBBACUACw== +invalid invalid table_get.wast:70 AGFzbQEAAAABBQFgAAFwAwIBAAQEAW8ACgoIAQYAQQElAAs= +invalid invalid table_get.wast:80 AGFzbQEAAAABBQFgAAFwAwIBAAQHAnAAAW8AAQoIAQYAQQAlAQs= +valid valid table_grow.wast:1 AGFzbQEAAAABFQRgAX8Bb2ACf28AYAJ/bwF/YAABfwMGBQABAgIDBAQBbwAABykFA2dldAAAA3NldAABBGdyb3cAAgtncm93LWFiYnJldgADBHNpemUABAorBQYAIAAlAAsIACAAIAEmAAsJACABIAD8DwALCQAgASAA/A8ACwUA/BAACw== +valid valid table_grow.wast:42 AGFzbQEAAAABBQFgAAF/AwIBAAQEAXAAEAcIAQRncm93AAAJBQEDAAEACgsBCQDSAEFw/A8ACw== +valid valid table_grow.wast:53 AGFzbQEAAAABBgFgAX8BfwMCAQAEBAFvAAAHCAEEZ3JvdwAACgsBCQDQbyAA/A8ACw== +valid valid table_grow.wast:67 AGFzbQEAAAABBgFgAX8BfwMCAQAEBQFvAQAKBwgBBGdyb3cAAAoLAQkA0G8gAPwPAAs= +valid valid table_grow.wast:84 AGFzbQEAAAABDAJgAX8Bf2ACf38BcAMDAgABBAQBcAAKBxsCBGdyb3cAABBjaGVjay10YWJsZS1udWxsAAEJBQEDAAEBCj0CCQDQcCAA/A8ACzEBAXDSASECAkADQCAAJQAhAiAC0UUNASAAIAFPDQEgAEEBaiEAIAAgAU0NAAsLIAIL +valid valid table_grow.wast:111 AGFzbQEAAAABBQFgAAF/AwIBAAQEAXAAAQcQAgV0YWJsZQEABGdyb3cAAAoLAQkA0HBBAfwPAAs= +valid valid table_grow.wast:117 AGFzbQEAAAABBQFgAAF/AhcBC2dyb3duLXRhYmxlBXRhYmxlAXAAAgMCAQAHEAIFdGFibGUBAARncm93AAAKCwEJANBwQQH8DwAL +valid valid table_grow.wast:124 AGFzbQEAAAABBQFgAAF/AiABFGdyb3duLWltcG9ydGVkLXRhYmxlBXRhYmxlAXAAAwMCAQAHCAEEc2l6ZQAACgcBBQD8EAAL +invalid invalid table_grow.wast:135 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8AAAoHAQUA/A8ACw== +invalid invalid table_grow.wast:144 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8AAAoJAQcA0G/8DwAL +invalid invalid table_grow.wast:153 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8AAAoJAQcAQQH8DwAL +invalid invalid table_grow.wast:162 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8AAAoOAQwA0G9DAACAP/wPAAs= +invalid invalid table_grow.wast:171 AGFzbQEAAAABBgFgAW8BfwMCAQAEBAFwAAAKCwEJACAAQQH8DwAL +invalid invalid table_grow.wast:181 AGFzbQEAAAABBAFgAAADAgEABAQBbwABCgsBCQDQb0EA/A8ACw== +invalid invalid table_grow.wast:190 AGFzbQEAAAABBQFgAAF9AwIBAAQEAW8AAQoLAQkA0G9BAPwPAAs= +valid valid table_init.wast:15 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgovBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEHQQBBBPwMAQALBwAgABEAAAs= +valid valid table_init.wast:73 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgovBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEPQQFBA/wMAwALBwAgABEAAAs= +valid valid table_init.wast:131 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCSMEAEECCwQDAQQBAQAEAgcBCABBDAsFBwUCAwYBAAUFCQIHBgpxBwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQtOAEEHQQBBBPwMAQD8DQFBD0EBQQP8DAMA/A0DQRRBD0EF/A4AAEEVQR1BAfwOAABBGEEKQQH8DgAAQQ1BC0EE/A4AAEETQRRBBfwOAAALBwAgABEAAAs= +valid valid table_init.wast:197 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKLwcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBB0EAQQT8DAEBCwcAIAARAAEL +valid valid table_init.wast:255 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKLwcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBD0EBQQP8DAMBCwcAIAARAAEL +valid valid table_init.wast:313 AGFzbQEAAAABDQNgAAF/YAAAYAF/AX8CKQUBYQNlZjAAAAFhA2VmMQAAAWEDZWYyAAABYQNlZjMAAAFhA2VmNAAAAwgHAAAAAAABAgQJAnABHh5wAR4eBxACBHRlc3QACgVjaGVjawALCScEAgFBAgsABAMBBAEBAAQCBwEIAgFBDAsABQcFAgMGAQAFBQkCBwYKcQcEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLTgBBB0EAQQT8DAEB/A0BQQ9BAUED/AwDAfwNA0EUQQ9BBfwOAQFBFUEdQQH8DgEBQRhBCkEB/A4BAUENQQtBBPwOAQFBE0EUQQX8DgEBCwcAIAARAAEL +invalid invalid table_init.wast:379 AGFzbQEAAAABBAFgAAADAgEABwgBBHRlc3QAAAoHAQUA/A0ACw== +invalid invalid table_init.wast:385 AGFzbQEAAAABBAFgAAADAgEABwgBBHRlc3QAAAoOAQwAQQxBAUEB/AwAAAs= +invalid invalid table_init.wast:391 AGFzbQEAAAABCAJgAAF/YAAAAwMCAAEHCAEEdGVzdAABCQUBAQABAAoMAgQAQQALBQD8DQQL +invalid invalid table_init.wast:399 AGFzbQEAAAABCAJgAAF/YAAAAwMCAAEHCAEEdGVzdAABCQUBAQABAAoTAgQAQQALDABBDEEBQQH8DAQACw== +valid valid table_init.wast:407 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCjkLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsFAPwNAgs= +valid valid table_init.wast:431 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQFBAfwMAgAL +valid valid table_init.wast:455 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkoLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsWAEEMQQFBAfwMAQBBFUEBQQH8DAEACw== +valid valid table_init.wast:479 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCjwLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsIAPwNAfwNAQs= +valid valid table_init.wast:503 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkMLBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsPAPwNAUEMQQFBAfwMAQAL +valid valid table_init.wast:527 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQBBBfwMAQAL +valid valid table_init.wast:551 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQJBA/wMAQAL +valid valid table_init.wast:575 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEcQQFBA/wMAQAL +valid valid table_init.wast:599 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQRBAPwMAQAL +valid valid table_init.wast:623 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEMQQVBAPwMAQAL +valid valid table_init.wast:647 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQJBAPwMAQAL +valid valid table_init.wast:671 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQJBAPwMAQAL +valid valid table_init.wast:695 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEeQQRBAPwMAQAL +valid valid table_init.wast:719 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJIwQAQQILBAMBBAEBAAQCBwEIAEEMCwUHBQIDBgEABQUJAgcGCkALBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsMAEEfQQVBAPwMAQAL +valid valid table_init.wast:743 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBGkEBQQP8DAEBCw== +valid valid table_init.wast:767 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBDEEEQQD8DAEBCw== +valid valid table_init.wast:791 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBDEEFQQD8DAEBCw== +valid valid table_init.wast:815 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHEECQQD8DAEBCw== +valid valid table_init.wast:839 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHUECQQD8DAEBCw== +valid valid table_init.wast:863 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHEEEQQD8DAEBCw== +valid valid table_init.wast:887 AGFzbQEAAAABCAJgAAF/YAAAAwwLAAAAAAAAAAAAAAEECQJwAR4ecAEcHAcIAQR0ZXN0AAoJJwQCAUECCwAEAwEEAQEABAIHAQgCAUEMCwAFBwUCAwYBAAUFCQIHBgpACwQAQQALBABBAQsEAEECCwQAQQMLBABBBAsEAEEFCwQAQQYLBABBBwsEAEEICwQAQQkLDABBHUEFQQD8DAEBCw== +invalid invalid table_init.wast:912 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEEBQQFDAACAP/wMAAAL +invalid invalid table_init.wast:921 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEEBQQFCAfwMAAAL +invalid invalid table_init.wast:930 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEEBQQFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:939 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEEBQwAAgD9BAfwMAAAL +invalid invalid table_init.wast:948 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEEBQwAAgD9DAACAP/wMAAAL +invalid invalid table_init.wast:957 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEEBQwAAgD9CAfwMAAAL +invalid invalid table_init.wast:966 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEEBQwAAgD9EAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:975 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEEBQgFBAfwMAAAL +invalid invalid table_init.wast:984 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEEBQgFDAACAP/wMAAAL +invalid invalid table_init.wast:993 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEEBQgFCAfwMAAAL +invalid invalid table_init.wast:1002 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEEBQgFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1011 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEEBRAAAAAAAAPA/QQH8DAAACw== +invalid invalid table_init.wast:1020 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEEBRAAAAAAAAPA/QwAAgD/8DAAACw== +invalid invalid table_init.wast:1029 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEEBRAAAAAAAAPA/QgH8DAAACw== +invalid invalid table_init.wast:1038 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEEBRAAAAAAAAPA/RAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1047 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEMAAIA/QQFBAfwMAAAL +invalid invalid table_init.wast:1056 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEMAAIA/QQFDAACAP/wMAAAL +invalid invalid table_init.wast:1065 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEMAAIA/QQFCAfwMAAAL +invalid invalid table_init.wast:1074 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEMAAIA/QQFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1083 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEMAAIA/QwAAgD9BAfwMAAAL +invalid invalid table_init.wast:1092 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGgICAAsVAEMAAIA/QwAAgD9DAACAP/wMAAAL +invalid invalid table_init.wast:1101 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEMAAIA/QwAAgD9CAfwMAAAL +invalid invalid table_init.wast:1110 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHgICAAsZAEMAAIA/QwAAgD9EAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1119 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEMAAIA/QgFBAfwMAAAL +invalid invalid table_init.wast:1128 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEMAAIA/QgFDAACAP/wMAAAL +invalid invalid table_init.wast:1137 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEMAAIA/QgFCAfwMAAAL +invalid invalid table_init.wast:1146 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEMAAIA/QgFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1155 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEMAAIA/RAAAAAAAAPA/QQH8DAAACw== +invalid invalid table_init.wast:1164 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHgICAAsZAEMAAIA/RAAAAAAAAPA/QwAAgD/8DAAACw== +invalid invalid table_init.wast:1173 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEMAAIA/RAAAAAAAAPA/QgH8DAAACw== +invalid invalid table_init.wast:1182 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKIgICAAsdAEMAAIA/RAAAAAAAAPA/RAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1191 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEIBQQFBAfwMAAAL +invalid invalid table_init.wast:1200 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEIBQQFDAACAP/wMAAAL +invalid invalid table_init.wast:1209 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEIBQQFCAfwMAAAL +invalid invalid table_init.wast:1218 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEIBQQFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1227 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEIBQwAAgD9BAfwMAAAL +invalid invalid table_init.wast:1236 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFwICAAsSAEIBQwAAgD9DAACAP/wMAAAL +invalid invalid table_init.wast:1245 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEIBQwAAgD9CAfwMAAAL +invalid invalid table_init.wast:1254 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEIBQwAAgD9EAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1263 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEIBQgFBAfwMAAAL +invalid invalid table_init.wast:1272 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKFAICAAsPAEIBQgFDAACAP/wMAAAL +invalid invalid table_init.wast:1281 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKEQICAAsMAEIBQgFCAfwMAAAL +invalid invalid table_init.wast:1290 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEIBQgFEAAAAAAAA8D/8DAAACw== +invalid invalid table_init.wast:1299 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEIBRAAAAAAAAPA/QQH8DAAACw== +invalid invalid table_init.wast:1308 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEIBRAAAAAAAAPA/QwAAgD/8DAAACw== +invalid invalid table_init.wast:1317 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEIBRAAAAAAAAPA/QgH8DAAACw== +invalid invalid table_init.wast:1326 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEIBRAAAAAAAAPA/RAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1335 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEQAAAAAAADwP0EBQQH8DAAACw== +invalid invalid table_init.wast:1344 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEQAAAAAAADwP0EBQwAAgD/8DAAACw== +invalid invalid table_init.wast:1353 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEQAAAAAAADwP0EBQgH8DAAACw== +invalid invalid table_init.wast:1362 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEQAAAAAAADwP0EBRAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1371 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEQAAAAAAADwP0MAAIA/QQH8DAAACw== +invalid invalid table_init.wast:1380 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHgICAAsZAEQAAAAAAADwP0MAAIA/QwAAgD/8DAAACw== +invalid invalid table_init.wast:1389 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEQAAAAAAADwP0MAAIA/QgH8DAAACw== +invalid invalid table_init.wast:1398 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKIgICAAsdAEQAAAAAAADwP0MAAIA/RAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1407 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEQAAAAAAADwP0IBQQH8DAAACw== +invalid invalid table_init.wast:1416 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGwICAAsWAEQAAAAAAADwP0IBQwAAgD/8DAAACw== +invalid invalid table_init.wast:1425 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKGAICAAsTAEQAAAAAAADwP0IBQgH8DAAACw== +invalid invalid table_init.wast:1434 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEQAAAAAAADwP0IBRAAAAAAAAPA//AwAAAs= +invalid invalid table_init.wast:1443 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEQAAAAAAADwP0QAAAAAAADwP0EB/AwAAAs= +invalid invalid table_init.wast:1452 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKIgICAAsdAEQAAAAAAADwP0QAAAAAAADwP0MAAIA//AwAAAs= +invalid invalid table_init.wast:1461 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKHwICAAsaAEQAAAAAAADwP0QAAAAAAADwP0IB/AwAAAs= +invalid invalid table_init.wast:1470 AGFzbQEAAAABBAFgAAADAwIAAAQEAXAACgcIAQR0ZXN0AAEJBwEBAAMAAAAKJgICAAshAEQAAAAAAADwP0QAAAAAAADwP0QAAAAAAADwP/wMAAAL +valid valid table_init.wast:1478 AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABIEAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBACAB/AwAAAs= +valid valid table_init.wast:1602 AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQHAXABoAHAAgdkEgJmMAAAAmYxAAECZjIAAgJmMwADAmY0AAQCZjUABQJmNgAGAmY3AAcCZjgACAJmOQAJA2YxMAAKA2YxMQALA2YxMgAMA2YxMwANA2YxNAAOA2YxNQAPBHRlc3QAEANydW4AEQkUAQEAEAABAgMEBQYHCAkKCwwNDg8KZhIEAEEACwQAQQELBABBAgsEAEEDCwQAQQQLBABBBQsEAEEGCwQAQQcLBABBCAsEAEEJCwQAQQoLBABBCwsEAEEMCwQAQQ0LBABBDgsEAEEPCwcAIAARAAALDAAgAEEAIAH8DAAACw== +valid valid table_init.wast:1982 AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABQEAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBACAB/AwAAAs= +valid valid table_init.wast:2076 AGFzbQEAAAABDwNgAAF/YAF/AX9gAn9/AAMTEgAAAAAAAAAAAAAAAAAAAAABAgQFAXABEBAHZBICZjAAAAJmMQABAmYyAAICZjMAAwJmNAAEAmY1AAUCZjYABgJmNwAHAmY4AAgCZjkACQNmMTAACgNmMTEACwNmMTIADANmMTMADQNmMTQADgNmMTUADwR0ZXN0ABADcnVuABEJFAEBABAAAQIDBAUGBwgJCgsMDQ4PCmYSBABBAAsEAEEBCwQAQQILBABBAwsEAEEECwQAQQULBABBBgsEAEEHCwQAQQgLBABBCQsEAEEKCwQAQQsLBABBDAsEAEENCwQAQQ4LBABBDwsHACAAEQAACwwAIABBCCAB/AwAAAs= +valid valid table_init.wast:2122 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCcQBQQEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAEAAAoOAQwAQQBBAEEA/AxAAAs= +valid valid table_set.wast:1 AGFzbQEAAAABIgdgAABgAX8Bb2ABfwFwYAJ/bwBgAn9wAGACf38AYAF/AX8DCAcAAQIDBAUGBAcCbwABcAACB2IGDWdldC1leHRlcm5yZWYAAQtnZXQtZnVuY3JlZgACDXNldC1leHRlcm5yZWYAAwtzZXQtZnVuY3JlZgAEEHNldC1mdW5jcmVmLWZyb20ABQ9pc19udWxsLWZ1bmNyZWYABgkJAQIBQQELAAEACjcHAgALBgAgACUACwYAIAAlAQsIACAAIAEmAAsIACAAIAEmAQsKACAAIAElASYBCwcAIAAQAtEL +invalid invalid table_set.wast:55 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCgYBBAAmAAs= +invalid invalid table_set.wast:64 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCggBBgDQbyYACw== +invalid invalid table_set.wast:73 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCggBBgBBASYACw== +invalid invalid table_set.wast:82 AGFzbQEAAAABBAFgAAADAgEABAQBbwAKCg0BCwBDAACAP9BvJgAL +invalid invalid table_set.wast:91 AGFzbQEAAAABBQFgAW8AAwIBAAQEAXAACgoKAQgAQQEgACYACw== +invalid invalid table_set.wast:101 AGFzbQEAAAABBQFgAW8AAwIBAAQHAm8AAXAAAQoKAQgAQQAgACYBCw== +invalid invalid table_set.wast:112 AGFzbQEAAAABBQFgAAF/AwIBAAQEAW8ACgoKAQgAQQDQbyYACw== +valid valid table_size.wast:1 AGFzbQEAAAABCQJgAAF/YAF/AAMJCAAAAAABAQEBBA8EbwAAbwABbwEAAm8BAwgHUQgHc2l6ZS10MAAAB3NpemUtdDEAAQdzaXplLXQyAAIHc2l6ZS10MwADB2dyb3ctdDAABAdncm93LXQxAAUHZ3Jvdy10MgAGB2dyb3ctdDMABwpFCAUA/BAACwUA/BABCwUA/BACCwUA/BADCwoA0G8gAPwPABoLCgDQbyAA/A8BGgsKANBvIAD8DwIaCwoA0G8gAPwPAxoL +invalid invalid table_size.wast:70 AGFzbQEAAAABBAFgAAADAgEABAQBbwABCgcBBQD8EAAL +invalid invalid table_size.wast:79 AGFzbQEAAAABBQFgAAF9AwIBAAQEAW8AAQoHAQUA/BAACw== +valid valid token.wast:15 AGFzbQEAAAABBAFgAAADAgEACgUBAwABCw== +valid valid token.wast:18 AGFzbQEAAAABBAFgAAADAgEACgYBBAABAQs= +valid valid token.wast:30 AGFzbQEAAAABBAFgAAADAgEACgcBBQAMAAEL +valid valid token.wast:33 AGFzbQEAAAABBAFgAAADAgEABAQBcAABCQcBAEEACwEACgQBAgAL +valid valid token.wast:47 AGFzbQEAAAABBAFgAAACEgEIc3BlY3Rlc3QFcHJpbnQAAA== +valid valid token.wast:54 AGFzbQEAAAABBAFgAAADAgEACgQBAgAL +valid valid token.wast:70 AGFzbQEAAAABBAFgAAADAgEACgYBBAAMAAs= +valid valid token.wast:74 AGFzbQEAAAALBAEBAWE= +valid valid token.wast:82 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEADgEAAAsL +valid valid token.wast:112 AGFzbQEAAAABBAFgAAADAgEACgwBCgACQEEADgAACws= +valid valid token.wast:142 AGFzbQEAAAALBQEBAiBh +valid valid token.wast:152 AGFzbQEAAAALBQEBAmEg +valid valid token.wast:162 AGFzbQEAAAALBgEBA2EgYg== +valid valid token.wast:172 AGFzbQEAAAALCQEBBu+Ymu+SqQ== +valid valid token.wast:182 AGFzbQEAAAALCgEBByDvmJrvkqk= +valid valid token.wast:192 AGFzbQEAAAALCgEBB++Ymu+SqSA= +valid valid token.wast:202 AGFzbQEAAAALBQEBAmFi +valid valid token.wast:232 AGFzbQEAAAALDwEBDO+Ymu+Sqe+Ymu+SqQ== +valid valid token.wast:242 AGFzbQEAAAALEAEBDe+Ymu+SqSDvmJrvkqk= +valid valid traps.wast:5 AGFzbQEAAAABCwJgAn9/AGACfn4AAwUEAAABAQdNBBBub19kY2UuaTMyLmRpdl9zAAAQbm9fZGNlLmkzMi5kaXZfdQABEG5vX2RjZS5pNjQuZGl2X3MAAhBub19kY2UuaTY0LmRpdl91AAMKJQQIACAAIAFtGgsIACAAIAFuGgsIACAAIAF/GgsIACAAIAGAGgs= +valid valid traps.wast:23 AGFzbQEAAAABCwJgAn9/AGACfn4AAwUEAAABAQdNBBBub19kY2UuaTMyLnJlbV9zAAAQbm9fZGNlLmkzMi5yZW1fdQABEG5vX2RjZS5pNjQucmVtX3MAAhBub19kY2UuaTY0LnJlbV91AAMKJQQIACAAIAFvGgsIACAAIAFwGgsIACAAIAGBGgsIACAAIAGCGgs= +valid valid traps.wast:39 AGFzbQEAAAABCQJgAX0AYAF8AAMJCAAAAQEAAAEBB8kBCBZub19kY2UuaTMyLnRydW5jX2YzMl9zAAAWbm9fZGNlLmkzMi50cnVuY19mMzJfdQABFm5vX2RjZS5pMzIudHJ1bmNfZjY0X3MAAhZub19kY2UuaTMyLnRydW5jX2Y2NF91AAMWbm9fZGNlLmk2NC50cnVuY19mMzJfcwAEFm5vX2RjZS5pNjQudHJ1bmNfZjMyX3UABRZub19kY2UuaTY0LnRydW5jX2Y2NF9zAAYWbm9fZGNlLmk2NC50cnVuY19mNjRfdQAHCjkIBgAgAKgaCwYAIACpGgsGACAAqhoLBgAgAKsaCwYAIACuGgsGACAArxoLBgAgALAaCwYAIACxGgs= +valid valid traps.wast:59 AGFzbQEAAAABBQFgAX8AAw8OAAAAAAAAAAAAAAAAAAAFAwEAAQehAg4Pbm9fZGNlLmkzMi5sb2FkAAATbm9fZGNlLmkzMi5sb2FkMTZfcwABE25vX2RjZS5pMzIubG9hZDE2X3UAAhJub19kY2UuaTMyLmxvYWQ4X3MAAxJub19kY2UuaTMyLmxvYWQ4X3UABA9ub19kY2UuaTY0LmxvYWQABRNub19kY2UuaTY0LmxvYWQzMl9zAAYTbm9fZGNlLmk2NC5sb2FkMzJfdQAHE25vX2RjZS5pNjQubG9hZDE2X3MACBNub19kY2UuaTY0LmxvYWQxNl91AAkSbm9fZGNlLmk2NC5sb2FkOF9zAAoSbm9fZGNlLmk2NC5sb2FkOF91AAsPbm9fZGNlLmYzMi5sb2FkAAwPbm9fZGNlLmY2NC5sb2FkAA0Kfw4IACAAKAIAGgsIACAALgEAGgsIACAALwEAGgsIACAALAAAGgsIACAALQAAGgsIACAAKQMAGgsIACAANAIAGgsIACAANQIAGgsIACAAMgEAGgsIACAAMwEAGgsIACAAMAAAGgsIACAAMQAAGgsIACAAKgIAGgsIACAAKwMAGgs= +valid valid type.wast:3 AGFzbQEAAAABiQEXYAAAYAAAYAF/AGABfwBgAAF/YAF/AX9gAX8Bf2ACfXwAYAACfn1gAn9+An18YAJ9fABgAn18AGACfXwAYAJ9fABgAAJ+fWACf34CfXxgAn9+An18YAZ9fH98f38AYAAFfn59fX9gBH9/fn8EfXx8f2ADfXx/AGAAA35+fWAFf39+f38EfXx8fw== +valid valid unreachable.wast:3 AGFzbQEAAAABIAdgA39/fwBgAABgAAF/YAABfmAAAX1gAAF8YAJ/fwF/Az08AQACAwQFAgIBAgICAQICAgIBAgIBAgIBAgICAgMCBgYGBgYCAQEBAQEBAQEEBAQDAQEBAQQCAwICAgICBAUBcAEBAQUDAQABBgkBfQFDAAAAAAsHjAg6CHR5cGUtaTMyAAIIdHlwZS1pNjQAAwh0eXBlLWYzMgAECHR5cGUtZjY0AAUNYXMtZnVuYy1maXJzdAAGC2FzLWZ1bmMtbWlkAAcMYXMtZnVuYy1sYXN0AAgNYXMtZnVuYy12YWx1ZQAJDmFzLWJsb2NrLWZpcnN0AAoMYXMtYmxvY2stbWlkAAsNYXMtYmxvY2stbGFzdAAMDmFzLWJsb2NrLXZhbHVlAA0OYXMtYmxvY2stYnJva2UADg1hcy1sb29wLWZpcnN0AA8LYXMtbG9vcC1taWQAEAxhcy1sb29wLWxhc3QAEQ1hcy1sb29wLWJyb2tlABILYXMtYnItdmFsdWUAEw1hcy1icl9pZi1jb25kABQOYXMtYnJfaWYtdmFsdWUAFRNhcy1icl9pZi12YWx1ZS1jb25kABYRYXMtYnJfdGFibGUtaW5kZXgAFxFhcy1icl90YWJsZS12YWx1ZQAYE2FzLWJyX3RhYmxlLXZhbHVlLTIAGRdhcy1icl90YWJsZS12YWx1ZS1pbmRleAAaG2FzLWJyX3RhYmxlLXZhbHVlLWFuZC1pbmRleAAbD2FzLXJldHVybi12YWx1ZQAcCmFzLWlmLWNvbmQAHQphcy1pZi10aGVuAB4KYXMtaWYtZWxzZQAfEmFzLWlmLXRoZW4tbm8tZWxzZQAgD2FzLXNlbGVjdC1maXJzdAAhEGFzLXNlbGVjdC1zZWNvbmQAIg5hcy1zZWxlY3QtY29uZAAjDWFzLWNhbGwtZmlyc3QAJAthcy1jYWxsLW1pZAAlDGFzLWNhbGwtbGFzdAAmFWFzLWNhbGxfaW5kaXJlY3QtZnVuYwAnFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAKBRhcy1jYWxsX2luZGlyZWN0LW1pZAApFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAqEmFzLWxvY2FsLnNldC12YWx1ZQArEmFzLWxvY2FsLnRlZS12YWx1ZQAsE2FzLWdsb2JhbC5zZXQtdmFsdWUALQ9hcy1sb2FkLWFkZHJlc3MALhBhcy1sb2FkTi1hZGRyZXNzAC8QYXMtc3RvcmUtYWRkcmVzcwAwDmFzLXN0b3JlLXZhbHVlADERYXMtc3RvcmVOLWFkZHJlc3MAMg9hcy1zdG9yZU4tdmFsdWUAMxBhcy11bmFyeS1vcGVyYW5kADQOYXMtYmluYXJ5LWxlZnQANQ9hcy1iaW5hcnktcmlnaHQANg9hcy10ZXN0LW9wZXJhbmQANw9hcy1jb21wYXJlLWxlZnQAOBBhcy1jb21wYXJlLXJpZ2h0ADkSYXMtY29udmVydC1vcGVyYW5kADoTYXMtbWVtb3J5Lmdyb3ctc2l6ZQA7CQcBAEEACwEBCrUEPAIACwIACwMAAAsDAAALAwAACwMAAAsFAABBfwsHABAAAEF/CwUAEAAACwUAEAAACwgAAn8AQQILCwoAAn8QAABBAgsLCQACQAEQAAALCwkAAn8BEAAACwsMAAJ/EABBAQwAAAsLCAADfwBBAgsLCgADfxAAAEECCwsJAANAARAAAAsLDwACfwN/EABBAQwBAAsLCwgAAn8ADAALCwgAAkAADQALCw0AAn8AQQENABpBBwsLDQACf0EGAA0AGkEHCwsLAAJAAA4CAAAACwsPAAJ/AEEBDgIAAABBBwsLDwACfwJ/AEEBDgEAAQsLCw4AAn9BBgAOAQAAQQcLCwwAAn8ADgEAAEEICwsEAAAPCwsAAAR/QQAFQQELCwsAIAAEfwAFIAELCwsAIAAEfyABBQALCwoAIAAEQAALIAELCAAAIAAgARsLCAAgAAAgARsLCABBAEEBABsLCQAAQQJBAxABCwkAQQEAQQMQAQsJAEEBQQIAEAELDAAAQQFBAkEDEQAACwwAQQAAQQJBAxEAAAsMAEEAQQEAQQMRAAALDABBAEEBQQIAEQAACwcBAX0AIQALBwEBfQAiAAsFAAAkAAsGAAAqAgALBgAAMAAACw8AAEQAAAAAAAAcQDkDAAsIAEECADcDAAsIAABBBzoAAAsIAEECAD0BAAsEAACMCwYAAEEKagsGAEIKAH0LBAAARQsNAABEAAAAAAAAJEBlCwkAQwAAIEEAXAsEAACnCwUAAEAACw== +invalid invalid unreached-invalid.wast:4 AGFzbQEAAAABBAFgAAADAgEACggBBgAAIAAaCw== +invalid invalid unreached-invalid.wast:8 AGFzbQEAAAABBAFgAAADAgEACggBBgAAIwAaCw== +invalid invalid unreached-invalid.wast:12 AGFzbQEAAAABBAFgAAADAgEACgcBBQAAEAEL +invalid invalid unreached-invalid.wast:16 AGFzbQEAAAABBAFgAAADAgEACgcBBQAADAEL +invalid invalid unreached-invalid.wast:21 AGFzbQEAAAABBAFgAAADAgEACgkBBwAAQQBQGgs= +invalid invalid unreached-invalid.wast:27 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAAEIAQQAbCw== +invalid invalid unreached-invalid.wast:33 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAEIAQQAbQQBBABsL +invalid invalid unreached-invalid.wast:42 AGFzbQEAAAABBAFgAAADAgEACgcBBQAAQQAL +invalid invalid unreached-invalid.wast:46 AGFzbQEAAAABBAFgAAADAgEACgYBBAAARQs= +invalid invalid unreached-invalid.wast:50 AGFzbQEAAAABBAFgAAADAgEACggBBgAAQQBqCw== +invalid invalid unreached-invalid.wast:56 AGFzbQEAAAABBAFgAAADAgEACgYBBAAAGws= +invalid invalid unreached-invalid.wast:60 AGFzbQEAAAABBAFgAAADAgEACggBBgAAQQAbCw== +invalid invalid unreached-invalid.wast:64 AGFzbQEAAAABBAFgAAADAgEACgoBCAAAQQBBABsL +invalid invalid unreached-invalid.wast:71 AGFzbQEAAAABBAFgAAADAgEACg8BDQACQAwAAkABRRoLCws= +invalid invalid unreached-invalid.wast:77 AGFzbQEAAAABBAFgAAADAgEAChABDgACQAwAQwAAgD9FGgsL +invalid invalid unreached-invalid.wast:83 AGFzbQEAAAABBAFgAAADAgEAChABDgACQAwAAkBBAVsaCwsL +invalid invalid unreached-invalid.wast:89 AGFzbQEAAAABBAFgAAADAgEAChIBEAACQAwAQQFDAAAAAFsaCws= +invalid invalid unreached-invalid.wast:95 AGFzbQEAAAABBAFgAAADAgEACgsBCQACQAwAQQELCw== +invalid invalid unreached-invalid.wast:101 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9BAQwAQwAAAAALCw== +invalid invalid unreached-invalid.wast:107 AGFzbQEAAAABBAFgAAADAgEACg4BDAACQANADAFBAQsLCw== +invalid invalid unreached-invalid.wast:113 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AA39BAQwBQwAAAAALCw== +invalid invalid unreached-invalid.wast:119 AGFzbQEAAAABBAFgAAADAgEACggBBgAMAEEBCw== +invalid invalid unreached-invalid.wast:125 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAQQEMAEMAAAAACw== +invalid invalid unreached-invalid.wast:132 AGFzbQEAAAABBAFgAAADAgEACgsBCQAPAkABRRoLCw== +invalid invalid unreached-invalid.wast:138 AGFzbQEAAAABBAFgAAADAgEACgwBCgAPQwAAgD9FGgs= +invalid invalid unreached-invalid.wast:144 AGFzbQEAAAABBAFgAAADAgEACgwBCgAPAkBBAVsaCws= +invalid invalid unreached-invalid.wast:150 AGFzbQEAAAABBAFgAAADAgEACg4BDAAPQQFDAAAAAFsaCw== +invalid invalid unreached-invalid.wast:156 AGFzbQEAAAABBAFgAAADAgEACgoBCAACQA9BAQsL +invalid invalid unreached-invalid.wast:162 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn9BAUEAD0MAAAAACws= +invalid invalid unreached-invalid.wast:168 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQANAD0EBCwsL +invalid invalid unreached-invalid.wast:174 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AA39BAQ9DAAAAAAsL +invalid invalid unreached-invalid.wast:180 AGFzbQEAAAABBAFgAAADAgEACgcBBQAPQQEL +invalid invalid unreached-invalid.wast:186 AGFzbQEAAAABBQFgAAF/AwIBAAoMAQoAQQEPQwAAAAAL +invalid invalid unreached-invalid.wast:193 AGFzbQEAAAABBAFgAAADAgEACgsBCQAAAkABRRoLCw== +invalid invalid unreached-invalid.wast:199 AGFzbQEAAAABBAFgAAADAgEACgsBCQAAA0ABRRoLCw== +invalid invalid unreached-invalid.wast:205 AGFzbQEAAAABBAFgAAADAgEACgoBCAAAA38BRQsL +invalid invalid unreached-invalid.wast:211 AGFzbQEAAAABBAFgAAADAgEACgwBCgAAQwAAgD9FGgs= +invalid invalid unreached-invalid.wast:217 AGFzbQEAAAABBAFgAAADAgEACgwBCgAAAkBBAVsaCws= +invalid invalid unreached-invalid.wast:223 AGFzbQEAAAABBAFgAAADAgEACg4BDAAAQQFDAAAAAFsaCw== +invalid invalid unreached-invalid.wast:229 AGFzbQEAAAABBAFgAAADAgEACgoBCAACQABBAQsL +invalid invalid unreached-invalid.wast:235 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAn9BAQBDAAAAAAsL +invalid invalid unreached-invalid.wast:241 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQANAAEEBCwsL +invalid invalid unreached-invalid.wast:247 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAA38AQwAAAAALCw== +invalid invalid unreached-invalid.wast:253 AGFzbQEAAAABBAFgAAADAgEACgcBBQAAQQEL +invalid invalid unreached-invalid.wast:259 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAAEMAAAAACw== +invalid invalid unreached-invalid.wast:265 AGFzbQEAAAABBAFgAAADAgEACg0BCwAAQQAEQAFFGgsL +invalid invalid unreached-invalid.wast:271 AGFzbQEAAAABBAFgAAADAgEACg8BDQAAQQAEQAEFAUUaCws= +invalid invalid unreached-invalid.wast:277 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAARAAAUBRRoLCw== +invalid invalid unreached-invalid.wast:284 AGFzbQEAAAABBAFgAAADAgEACg4BDAACQAALAkABRRoLCw== +invalid invalid unreached-invalid.wast:290 AGFzbQEAAAABBAFgAAADAgEACg8BDQACQAALQwAAgD9FGgs= +invalid invalid unreached-invalid.wast:296 AGFzbQEAAAABBAFgAAADAgEACg8BDQACQAALAkBBAVsaCws= +invalid invalid unreached-invalid.wast:302 AGFzbQEAAAABBAFgAAADAgEAChEBDwACQAALQQFDAAAAAFsaCw== +invalid invalid unreached-invalid.wast:308 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQAJAAAtBAQsL +invalid invalid unreached-invalid.wast:314 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAn9BAQJAAAtDAAAAAAsL +invalid invalid unreached-invalid.wast:321 AGFzbQEAAAABBAFgAAADAgEAChABDgACQANAAkAAC0EBCwsL +invalid invalid unreached-invalid.wast:327 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AA38CQAALQwAAAAALCw== +invalid invalid unreached-invalid.wast:334 AGFzbQEAAAABBAFgAAADAgEACgoBCAACQAALQQEL +invalid invalid unreached-invalid.wast:340 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAkAAC0MAAAAACw== +invalid invalid unreached-invalid.wast:348 AGFzbQEAAAABBAFgAAADAgEACg8BDQADQAwACwJAAUUaCws= +invalid invalid unreached-invalid.wast:354 AGFzbQEAAAABBAFgAAADAgEAChABDgADQAwAC0MAAIA/RRoL +invalid invalid unreached-invalid.wast:360 AGFzbQEAAAABBAFgAAADAgEAChABDgADQAwACwJAQQFbGgsL +invalid invalid unreached-invalid.wast:366 AGFzbQEAAAABBAFgAAADAgEAChIBEAADQAwAC0EBQwAAAABbGgs= +invalid invalid unreached-invalid.wast:372 AGFzbQEAAAABBAFgAAADAgEACg4BDAACQANADAALQQELCw== +invalid invalid unreached-invalid.wast:378 AGFzbQEAAAABBQFgAAF/AwIBAAoTAREAAn9BAQNADAALQwAAAAALCw== +invalid invalid unreached-invalid.wast:384 AGFzbQEAAAABBAFgAAADAgEAChEBDwACQANAA0AMAAtBAQsLCw== +invalid invalid unreached-invalid.wast:390 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AA38DQAwAC0MAAAAACws= +invalid invalid unreached-invalid.wast:396 AGFzbQEAAAABBAFgAAADAgEACgsBCQADQAwAC0EBCw== +invalid invalid unreached-invalid.wast:402 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAA0AMAAtDAAAAAAs= +invalid invalid unreached-invalid.wast:409 AGFzbQEAAAABBAFgAAADAgEACgwBCgBBAARAAUUaCws= +invalid invalid unreached-invalid.wast:415 AGFzbQEAAAABBAFgAAADAgEAChABDgBBAARAQwAAgD9FGgsL +invalid invalid unreached-invalid.wast:421 AGFzbQEAAAABBAFgAAADAgEACg0BCwBBAARAQQFbGgsL +invalid invalid unreached-invalid.wast:427 AGFzbQEAAAABBAFgAAADAgEAChIBEABBAARAQQFDAAAAAFsaCws= +invalid invalid unreached-invalid.wast:433 AGFzbQEAAAABBAFgAAADAgEACgsBCQBBAARAQQELCw== +invalid invalid unreached-invalid.wast:439 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAQQAEf0MAAAAACws= +invalid invalid unreached-invalid.wast:445 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAARAAkBBAQsLCw== +invalid invalid unreached-invalid.wast:451 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AQQAEfwJ/QwAAAAALCws= +invalid invalid unreached-invalid.wast:457 AGFzbQEAAAABBAFgAAADAgEACg4BDABBAARAA0BBAQsLCw== +invalid invalid unreached-invalid.wast:463 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AQQAEfwN/QwAAAAALCws= +invalid invalid unreached-invalid.wast:470 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AQQEPRAAAAAAAAPA/Dws= +invalid invalid unreached-invalid.wast:477 AGFzbQEAAAABBQFgAAF/AwIBAAoWARQAAn9BAQwARAAAAAAAAPA/DAALCw== +invalid invalid unreached-invalid.wast:484 AGFzbQEAAAABBAFgAAADAgEACg8BDQACQABDAAAAAA0ACws= +invalid invalid unreached-invalid.wast:490 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn8CQABBAEEADQELCws= +invalid invalid unreached-invalid.wast:498 AGFzbQEAAAABBQFgAAF/AwIBAAoUARIAAn8CfQBBAEEADQELGkEACws= +invalid invalid unreached-invalid.wast:507 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn8AQQBBAA0AQQALCw== +invalid invalid unreached-invalid.wast:515 AGFzbQEAAAABBAFgAAADAgEAChABDgACQABDAACAPw4AAAsL +invalid invalid unreached-invalid.wast:521 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAn8AQwAAAABBAQ4AAAsL +invalid invalid unreached-invalid.wast:527 AGFzbQEAAAABBAFgAAADAgEAChMBEQACQAJ9AEEBDgIAAQALGgsL +invalid invalid unreached-invalid.wast:540 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEDAkAACwsL +invalid invalid unreached-invalid.wast:546 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAAkACQAALCws= +invalid invalid unreached-invalid.wast:552 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAn5CAAJAAAsLCw== +invalid invalid unreached-invalid.wast:558 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAkBBAwJAQgEACwtBCQs= +invalid invalid unreached-invalid.wast:565 AGFzbQEAAAABBAFgAAADAgEACg4BDAACQEEDAkAMAQsLCw== +invalid invalid unreached-invalid.wast:571 AGFzbQEAAAABBQFgAAF/AwIBAAoOAQwAAn8CQEEADAELCws= +invalid invalid unreached-invalid.wast:577 AGFzbQEAAAABBQFgAAF/AwIBAAoQAQ4AAn9CAAJAQQAMAQsLCw== +invalid invalid unreached-invalid.wast:584 AGFzbQEAAAABBAFgAAADAgEAChEBDwACQAJAQQMCQAwCCwsLCw== +invalid invalid unreached-invalid.wast:590 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn8CQAJAQQAMAgsLCws= +invalid invalid unreached-invalid.wast:596 AGFzbQEAAAABBQFgAAF/AwIBAAoTAREAAn8CfkIAAkBBAAwCCwsLCw== +invalid invalid unreached-invalid.wast:604 AGFzbQEAAAABBQFgAAF/AwIBAAoSARAAAkBBAwJAQgEMAQsLQQkL +invalid invalid unreached-invalid.wast:611 AGFzbQEAAAABBAFgAAADAgEACg0BCwACQEEDAkAPCwsL +invalid invalid unreached-invalid.wast:617 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAAkACQEEADwsLCw== +invalid invalid unreached-invalid.wast:623 AGFzbQEAAAABBQFgAAF/AwIBAAoPAQ0AAn5CAAJAQQAPCwsL +invalid invalid unreached-invalid.wast:629 AGFzbQEAAAABBQFgAAF/AwIBAAoTAREAAkBBAwJAQgFBAA8LC0EJCw== +invalid invalid unreached-invalid.wast:637 AGFzbQEAAAABBAFgAAADAgEACg0BCwADQEEDAkAACwsL +invalid invalid unreached-invalid.wast:643 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAA0ACQAALCws= +invalid invalid unreached-invalid.wast:649 AGFzbQEAAAABBQFgAAF/AwIBAAoNAQsAA35CAAJAAAsLCw== +invalid invalid unreached-invalid.wast:656 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAA0ABDAALCw== +invalid invalid unreached-invalid.wast:662 AGFzbQEAAAABBQFgAAF/AwIBAAoLAQkAA0BBAAwACws= +invalid invalid unreached-invalid.wast:669 AGFzbQEAAAABBAFgAAADAgEACgkBBwEBfwAiAAs= +invalid invalid unreached-invalid.wast:676 AGFzbQEAAAABBQFgAAF/AwIBAAoRAQ8AAn8CQABBAA0BC0EACws= +invalid invalid unreached-invalid.wast:687 AGFzbQEAAAABBQFgAAF+AwIBAAoIAQYAAA0ArQs= +invalid invalid unreached-invalid.wast:699 AGFzbQEAAAABBAFgAAADAgEACg0BCwAAQQFCAUEBGxoL +invalid invalid unreached-invalid.wast:704 AGFzbQEAAAABBAFgAAADAgEACg0BCwAAQgFBAUEBGxoL +invalid invalid unreached-invalid.wast:710 AGFzbQEAAAABBAFgAAADAgEACg0BCwAAQQFBAUIBGxoL +invalid invalid unreached-invalid.wast:715 AGFzbQEAAAABBAFgAAADAgEACgsBCQAAQQFCARsaCw== +invalid invalid unreached-invalid.wast:720 AGFzbQEAAAABBAFgAAADAgEACgkBBwAAQgEbGgs= +invalid invalid unreached-invalid.wast:726 AGFzbQEAAAABBQFgAAF/AwIBAAoKAQgAAEIBQQEbCw== +invalid invalid unreached-invalid.wast:738 AGFzbQEAAAABBgFgAX8BbwMCAQAKFgEUAAJvAn/QbyAADgIAAQALGtBvCws= +valid valid unreached-valid.wast:1 AGFzbQEAAAABEQRgAX8Bf2AAAGAAAX9gAAF+AwgHAAABAgMBAQeXAQcQc2VsZWN0LXRyYXAtbGVmdAAAEXNlbGVjdC10cmFwLXJpZ2h0AAEQc2VsZWN0LXVucmVhY2hlZAACGXNlbGVjdF91bnJlYWNoZWRfcmVzdWx0XzEAAxlzZWxlY3RfdW5yZWFjaGVkX3Jlc3VsdF8yAAQPdW5yZWFjaGFibGUtbnVtAAUPdW5yZWFjaGFibGUtcmVmAAYKUgcIAABBACAAGwsIAEEAACAAGwsgAAAbAEEAGwBBAEEAGwBBAEEAQQAbAEMAAAAAQQAbAAsFAAAbagsJAABCAEEAG3wLBgAAG0UaCwYAABvRGgs= +valid valid unreached-valid.wast:49 AGFzbQEAAAABBAFgAAADAgEABw8BC21lZXQtYm90dG9tAAAKHQEbAAJ8An0AQQEOAgABAQsaRAAAAAAAAAAACxoL +valid valid unwind.wast:3 AGFzbQEAAAABCAJgAABgAAF/AzIxAAABAAEAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQeUCjEaZnVuYy11bndpbmQtYnktdW5yZWFjaGFibGUAABFmdW5jLXVud2luZC1ieS1icgABF2Z1bmMtdW53aW5kLWJ5LWJyLXZhbHVlAAIUZnVuYy11bndpbmQtYnktYnJfaWYAAxpmdW5jLXVud2luZC1ieS1icl9pZi12YWx1ZQAEF2Z1bmMtdW53aW5kLWJ5LWJyX3RhYmxlAAUdZnVuYy11bndpbmQtYnktYnJfdGFibGUtdmFsdWUABhVmdW5jLXVud2luZC1ieS1yZXR1cm4ABxtibG9jay11bndpbmQtYnktdW5yZWFjaGFibGUACBJibG9jay11bndpbmQtYnktYnIACRhibG9jay11bndpbmQtYnktYnItdmFsdWUAChVibG9jay11bndpbmQtYnktYnJfaWYACxtibG9jay11bndpbmQtYnktYnJfaWYtdmFsdWUADBhibG9jay11bndpbmQtYnktYnJfdGFibGUADR5ibG9jay11bndpbmQtYnktYnJfdGFibGUtdmFsdWUADhZibG9jay11bndpbmQtYnktcmV0dXJuAA8iYmxvY2stbmVzdGVkLXVud2luZC1ieS11bnJlYWNoYWJsZQAQGWJsb2NrLW5lc3RlZC11bndpbmQtYnktYnIAER9ibG9jay1uZXN0ZWQtdW53aW5kLWJ5LWJyLXZhbHVlABIcYmxvY2stbmVzdGVkLXVud2luZC1ieS1icl9pZgATImJsb2NrLW5lc3RlZC11bndpbmQtYnktYnJfaWYtdmFsdWUAFB9ibG9jay1uZXN0ZWQtdW53aW5kLWJ5LWJyX3RhYmxlABUlYmxvY2stbmVzdGVkLXVud2luZC1ieS1icl90YWJsZS12YWx1ZQAWHWJsb2NrLW5lc3RlZC11bndpbmQtYnktcmV0dXJuABcXdW5hcnktYWZ0ZXItdW5yZWFjaGFibGUAGA51bmFyeS1hZnRlci1icgAZEXVuYXJ5LWFmdGVyLWJyX2lmABoUdW5hcnktYWZ0ZXItYnJfdGFibGUAGxJ1bmFyeS1hZnRlci1yZXR1cm4AHBhiaW5hcnktYWZ0ZXItdW5yZWFjaGFibGUAHQ9iaW5hcnktYWZ0ZXItYnIAHhJiaW5hcnktYWZ0ZXItYnJfaWYAHxViaW5hcnktYWZ0ZXItYnJfdGFibGUAIBNiaW5hcnktYWZ0ZXItcmV0dXJuACEYc2VsZWN0LWFmdGVyLXVucmVhY2hhYmxlACIPc2VsZWN0LWFmdGVyLWJyACMSc2VsZWN0LWFmdGVyLWJyX2lmACQVc2VsZWN0LWFmdGVyLWJyX3RhYmxlACUTc2VsZWN0LWFmdGVyLXJldHVybgAmHWJsb2NrLXZhbHVlLWFmdGVyLXVucmVhY2hhYmxlACcUYmxvY2stdmFsdWUtYWZ0ZXItYnIAKBdibG9jay12YWx1ZS1hZnRlci1icl9pZgApGmJsb2NrLXZhbHVlLWFmdGVyLWJyX3RhYmxlACoYYmxvY2stdmFsdWUtYWZ0ZXItcmV0dXJuACscbG9vcC12YWx1ZS1hZnRlci11bnJlYWNoYWJsZQAsE2xvb3AtdmFsdWUtYWZ0ZXItYnIALRZsb29wLXZhbHVlLWFmdGVyLWJyX2lmAC4ZbG9vcC12YWx1ZS1hZnRlci1icl90YWJsZQAvF2xvb3AtdmFsdWUtYWZ0ZXItcmV0dXJuADAKvAYxBwBBA0IBAAsIAEEDQgEMAAsKAEEDQgFBCQwACwwAQQNCAUEBDQAaGgsOAEEDQgFBCUEBDQAaGgsLAEEDQgFBAA4AAAsNAEEDQgFBCUEADgAACwkAQQNCAUEJDwsKAAJAQQNCAQALCw0AAkBBA0IBDAALQQkLDQACf0EDQgFBCQwACwsRAAJAQQNCAUEBDQAaGgtBCQsRAAJ/QQNCAUEJQQENABoaCwsQAAJAQQNCAUEADgAAC0EJCxAAAn9BA0IBQQlBAA4AAAsLDAACf0EDQgFBCQ8LCw0AAn9BAwJAQgEACwsLEQACQEEDAkBCAQwBCxoLQQkLEAACf0EDAkBCAUEJDAELCwsUAAJAQQMCQEIBQQENARoLGgtBCQsUAAJ/QQMCQEIBQQlBAQ0BGhoLCwsUAAJAQQMCQEIBQQEOAAELGgtBCQsTAAJ/QQMCQEIBQQlBAQ4AAQsLCw8AAn9BAwJAQgFBCQ8LCwsJAEMAAAAAAFALDwACf0MAAAAAQQkMAFALCw8AAn9CAEEJQQENABpQCwsTAAJ/QwAAAABBCUEADgEAAFALCwsAQwAAAABBCQ9QCxIAQwAAAABEAAAAAAAA8D8AUQsYAAJ/QwAAAABEAAAAAAAA8D9BCQwAUQsLEQACf0IAQgFBCUEBDQAaUQsLGwACf0MAAAAARAAAAAAAAPA/QQlBAA4AAFELCxQAQwAAAABEAAAAAAAA8D9BCQ9RCxQAQwAAAABEAAAAAAAA8D9CAAAbCxoAAn9DAAAAAEQAAAAAAADwP0IAQQkMABsLCxMAAn9BAEEBQQBBCUEBDQAaGwsLHQACf0MAAAAARAAAAAAAAPA/QgBBCUEADgAAGwsLFgBDAAAAAEQAAAAAAADwP0IBQQkPGwsLAAJ/QwAAAAAACwsOAAJ/QwAAAABBCQwACwsOAAJ/QQBBCUEBDQAaCwsSAAJ/QwAAAABBCUEADgEAAAsLDQACf0MAAAAAQQkPCwsLAAN/QwAAAAAACwsRAAJ/A39DAAAAAEEJDAELCwsRAAJ/A39BAEEJQQENARoLCwsVAAJ/A39DAAAAAEEJQQAOAQEBCwsLDQADf0MAAAAAQQkPCws= +malformed invalid utf8-custom-section-id.wast:7 AGFzbQEAAAAAAgGA +malformed invalid utf8-custom-section-id.wast:17 AGFzbQEAAAAAAgGP +malformed invalid utf8-custom-section-id.wast:27 AGFzbQEAAAAAAgGQ +malformed invalid utf8-custom-section-id.wast:37 AGFzbQEAAAAAAgGf +malformed invalid utf8-custom-section-id.wast:47 AGFzbQEAAAAAAgGg +malformed invalid utf8-custom-section-id.wast:57 AGFzbQEAAAAAAgG/ +malformed invalid utf8-custom-section-id.wast:69 AGFzbQEAAAAABAPCgIA= +malformed invalid utf8-custom-section-id.wast:79 AGFzbQEAAAAAAgHC +malformed invalid utf8-custom-section-id.wast:89 AGFzbQEAAAAAAwLCLg== +malformed invalid utf8-custom-section-id.wast:101 AGFzbQEAAAAAAwLAgA== +malformed invalid utf8-custom-section-id.wast:111 AGFzbQEAAAAAAwLAvw== +malformed invalid utf8-custom-section-id.wast:121 AGFzbQEAAAAAAwLBgA== +malformed invalid utf8-custom-section-id.wast:131 AGFzbQEAAAAAAwLBvw== +malformed invalid utf8-custom-section-id.wast:141 AGFzbQEAAAAAAwLCAA== +malformed invalid utf8-custom-section-id.wast:151 AGFzbQEAAAAAAwLCfw== +malformed invalid utf8-custom-section-id.wast:161 AGFzbQEAAAAAAwLCwA== +malformed invalid utf8-custom-section-id.wast:171 AGFzbQEAAAAAAwLC/Q== +malformed invalid utf8-custom-section-id.wast:181 AGFzbQEAAAAAAwLfAA== +malformed invalid utf8-custom-section-id.wast:191 AGFzbQEAAAAAAwLffw== +malformed invalid utf8-custom-section-id.wast:201 AGFzbQEAAAAAAwLfwA== +malformed invalid utf8-custom-section-id.wast:211 AGFzbQEAAAAAAwLf/Q== +malformed invalid utf8-custom-section-id.wast:223 AGFzbQEAAAAABQThgICA +malformed invalid utf8-custom-section-id.wast:233 AGFzbQEAAAAAAwLhgA== +malformed invalid utf8-custom-section-id.wast:243 AGFzbQEAAAAABAPhgC4= +malformed invalid utf8-custom-section-id.wast:253 AGFzbQEAAAAAAgHh +malformed invalid utf8-custom-section-id.wast:263 AGFzbQEAAAAAAwLhLg== +malformed invalid utf8-custom-section-id.wast:275 AGFzbQEAAAAABAPgAKA= +malformed invalid utf8-custom-section-id.wast:285 AGFzbQEAAAAABAPgf6A= +malformed invalid utf8-custom-section-id.wast:295 AGFzbQEAAAAABAPggIA= +malformed invalid utf8-custom-section-id.wast:305 AGFzbQEAAAAABAPggKA= +malformed invalid utf8-custom-section-id.wast:315 AGFzbQEAAAAABAPgn6A= +malformed invalid utf8-custom-section-id.wast:325 AGFzbQEAAAAABAPgn78= +malformed invalid utf8-custom-section-id.wast:335 AGFzbQEAAAAABAPgwKA= +malformed invalid utf8-custom-section-id.wast:345 AGFzbQEAAAAABAPg/aA= +malformed invalid utf8-custom-section-id.wast:355 AGFzbQEAAAAABAPhAIA= +malformed invalid utf8-custom-section-id.wast:365 AGFzbQEAAAAABAPhf4A= +malformed invalid utf8-custom-section-id.wast:375 AGFzbQEAAAAABAPhwIA= +malformed invalid utf8-custom-section-id.wast:385 AGFzbQEAAAAABAPh/YA= +malformed invalid utf8-custom-section-id.wast:395 AGFzbQEAAAAABAPsAIA= +malformed invalid utf8-custom-section-id.wast:405 AGFzbQEAAAAABAPsf4A= +malformed invalid utf8-custom-section-id.wast:415 AGFzbQEAAAAABAPswIA= +malformed invalid utf8-custom-section-id.wast:425 AGFzbQEAAAAABAPs/YA= +malformed invalid utf8-custom-section-id.wast:435 AGFzbQEAAAAABAPtAIA= +malformed invalid utf8-custom-section-id.wast:445 AGFzbQEAAAAABAPtf4A= +malformed invalid utf8-custom-section-id.wast:455 AGFzbQEAAAAABAPtoIA= +malformed invalid utf8-custom-section-id.wast:465 AGFzbQEAAAAABAPtoL8= +malformed invalid utf8-custom-section-id.wast:475 AGFzbQEAAAAABAPtv4A= +malformed invalid utf8-custom-section-id.wast:485 AGFzbQEAAAAABAPtv78= +malformed invalid utf8-custom-section-id.wast:495 AGFzbQEAAAAABAPtwIA= +malformed invalid utf8-custom-section-id.wast:505 AGFzbQEAAAAABAPt/YA= +malformed invalid utf8-custom-section-id.wast:515 AGFzbQEAAAAABAPuAIA= +malformed invalid utf8-custom-section-id.wast:525 AGFzbQEAAAAABAPuf4A= +malformed invalid utf8-custom-section-id.wast:535 AGFzbQEAAAAABAPuwIA= +malformed invalid utf8-custom-section-id.wast:545 AGFzbQEAAAAABAPu/YA= +malformed invalid utf8-custom-section-id.wast:555 AGFzbQEAAAAABAPvAIA= +malformed invalid utf8-custom-section-id.wast:565 AGFzbQEAAAAABAPvf4A= +malformed invalid utf8-custom-section-id.wast:575 AGFzbQEAAAAABAPvwIA= +malformed invalid utf8-custom-section-id.wast:585 AGFzbQEAAAAABAPv/YA= +malformed invalid utf8-custom-section-id.wast:597 AGFzbQEAAAAABAPgoAA= +malformed invalid utf8-custom-section-id.wast:607 AGFzbQEAAAAABAPgoH8= +malformed invalid utf8-custom-section-id.wast:617 AGFzbQEAAAAABAPgoMA= +malformed invalid utf8-custom-section-id.wast:627 AGFzbQEAAAAABAPgoP0= +malformed invalid utf8-custom-section-id.wast:637 AGFzbQEAAAAABAPhgAA= +malformed invalid utf8-custom-section-id.wast:647 AGFzbQEAAAAABAPhgH8= +malformed invalid utf8-custom-section-id.wast:657 AGFzbQEAAAAABAPhgMA= +malformed invalid utf8-custom-section-id.wast:667 AGFzbQEAAAAABAPhgP0= +malformed invalid utf8-custom-section-id.wast:677 AGFzbQEAAAAABAPsgAA= +malformed invalid utf8-custom-section-id.wast:687 AGFzbQEAAAAABAPsgH8= +malformed invalid utf8-custom-section-id.wast:697 AGFzbQEAAAAABAPsgMA= +malformed invalid utf8-custom-section-id.wast:707 AGFzbQEAAAAABAPsgP0= +malformed invalid utf8-custom-section-id.wast:717 AGFzbQEAAAAABAPtgAA= +malformed invalid utf8-custom-section-id.wast:727 AGFzbQEAAAAABAPtgH8= +malformed invalid utf8-custom-section-id.wast:737 AGFzbQEAAAAABAPtgMA= +malformed invalid utf8-custom-section-id.wast:747 AGFzbQEAAAAABAPtgP0= +malformed invalid utf8-custom-section-id.wast:757 AGFzbQEAAAAABAPugAA= +malformed invalid utf8-custom-section-id.wast:767 AGFzbQEAAAAABAPugH8= +malformed invalid utf8-custom-section-id.wast:777 AGFzbQEAAAAABAPugMA= +malformed invalid utf8-custom-section-id.wast:787 AGFzbQEAAAAABAPugP0= +malformed invalid utf8-custom-section-id.wast:797 AGFzbQEAAAAABAPvgAA= +malformed invalid utf8-custom-section-id.wast:807 AGFzbQEAAAAABAPvgH8= +malformed invalid utf8-custom-section-id.wast:817 AGFzbQEAAAAABAPvgMA= +malformed invalid utf8-custom-section-id.wast:827 AGFzbQEAAAAABAPvgP0= +malformed invalid utf8-custom-section-id.wast:839 AGFzbQEAAAAABgXxgICAgA== +malformed invalid utf8-custom-section-id.wast:849 AGFzbQEAAAAABAPxgIA= +malformed invalid utf8-custom-section-id.wast:859 AGFzbQEAAAAABQTxgIAj +malformed invalid utf8-custom-section-id.wast:869 AGFzbQEAAAAAAwLxgA== +malformed invalid utf8-custom-section-id.wast:879 AGFzbQEAAAAABAPxgCM= +malformed invalid utf8-custom-section-id.wast:889 AGFzbQEAAAAAAgHx +malformed invalid utf8-custom-section-id.wast:899 AGFzbQEAAAAAAwLxIw== +malformed invalid utf8-custom-section-id.wast:911 AGFzbQEAAAAABQTwAJCQ +malformed invalid utf8-custom-section-id.wast:921 AGFzbQEAAAAABQTwf5CQ +malformed invalid utf8-custom-section-id.wast:931 AGFzbQEAAAAABQTwgICA +malformed invalid utf8-custom-section-id.wast:941 AGFzbQEAAAAABQTwgJCQ +malformed invalid utf8-custom-section-id.wast:951 AGFzbQEAAAAABQTwj5CQ +malformed invalid utf8-custom-section-id.wast:961 AGFzbQEAAAAABQTwj7+/ +malformed invalid utf8-custom-section-id.wast:971 AGFzbQEAAAAABQTwwJCQ +malformed invalid utf8-custom-section-id.wast:981 AGFzbQEAAAAABQTw/ZCQ +malformed invalid utf8-custom-section-id.wast:991 AGFzbQEAAAAABQTxAICA +malformed invalid utf8-custom-section-id.wast:1001 AGFzbQEAAAAABQTxf4CA +malformed invalid utf8-custom-section-id.wast:1011 AGFzbQEAAAAABQTxwICA +malformed invalid utf8-custom-section-id.wast:1021 AGFzbQEAAAAABQTx/YCA +malformed invalid utf8-custom-section-id.wast:1031 AGFzbQEAAAAABQTzAICA +malformed invalid utf8-custom-section-id.wast:1041 AGFzbQEAAAAABQTzf4CA +malformed invalid utf8-custom-section-id.wast:1051 AGFzbQEAAAAABQTzwICA +malformed invalid utf8-custom-section-id.wast:1061 AGFzbQEAAAAABQTz/YCA +malformed invalid utf8-custom-section-id.wast:1071 AGFzbQEAAAAABQT0AICA +malformed invalid utf8-custom-section-id.wast:1081 AGFzbQEAAAAABQT0f4CA +malformed invalid utf8-custom-section-id.wast:1091 AGFzbQEAAAAABQT0kICA +malformed invalid utf8-custom-section-id.wast:1101 AGFzbQEAAAAABQT0v4CA +malformed invalid utf8-custom-section-id.wast:1111 AGFzbQEAAAAABQT0wICA +malformed invalid utf8-custom-section-id.wast:1121 AGFzbQEAAAAABQT0/YCA +malformed invalid utf8-custom-section-id.wast:1131 AGFzbQEAAAAABQT1gICA +malformed invalid utf8-custom-section-id.wast:1141 AGFzbQEAAAAABQT3gICA +malformed invalid utf8-custom-section-id.wast:1151 AGFzbQEAAAAABQT3v7+/ +malformed invalid utf8-custom-section-id.wast:1163 AGFzbQEAAAAABQTwkACQ +malformed invalid utf8-custom-section-id.wast:1173 AGFzbQEAAAAABQTwkH+Q +malformed invalid utf8-custom-section-id.wast:1183 AGFzbQEAAAAABQTwkMCQ +malformed invalid utf8-custom-section-id.wast:1193 AGFzbQEAAAAABQTwkP2Q +malformed invalid utf8-custom-section-id.wast:1203 AGFzbQEAAAAABQTxgACA +malformed invalid utf8-custom-section-id.wast:1213 AGFzbQEAAAAABQTxgH+A +malformed invalid utf8-custom-section-id.wast:1223 AGFzbQEAAAAABQTxgMCA +malformed invalid utf8-custom-section-id.wast:1233 AGFzbQEAAAAABQTxgP2A +malformed invalid utf8-custom-section-id.wast:1243 AGFzbQEAAAAABQTzgACA +malformed invalid utf8-custom-section-id.wast:1253 AGFzbQEAAAAABQTzgH+A +malformed invalid utf8-custom-section-id.wast:1263 AGFzbQEAAAAABQTzgMCA +malformed invalid utf8-custom-section-id.wast:1273 AGFzbQEAAAAABQTzgP2A +malformed invalid utf8-custom-section-id.wast:1283 AGFzbQEAAAAABQT0gACA +malformed invalid utf8-custom-section-id.wast:1293 AGFzbQEAAAAABQT0gH+A +malformed invalid utf8-custom-section-id.wast:1303 AGFzbQEAAAAABQT0gMCA +malformed invalid utf8-custom-section-id.wast:1313 AGFzbQEAAAAABQT0gP2A +malformed invalid utf8-custom-section-id.wast:1325 AGFzbQEAAAAABQTwkJAA +malformed invalid utf8-custom-section-id.wast:1335 AGFzbQEAAAAABQTwkJB/ +malformed invalid utf8-custom-section-id.wast:1345 AGFzbQEAAAAABQTwkJDA +malformed invalid utf8-custom-section-id.wast:1355 AGFzbQEAAAAABQTwkJD9 +malformed invalid utf8-custom-section-id.wast:1365 AGFzbQEAAAAABQTxgIAA +malformed invalid utf8-custom-section-id.wast:1375 AGFzbQEAAAAABQTxgIB/ +malformed invalid utf8-custom-section-id.wast:1385 AGFzbQEAAAAABQTxgIDA +malformed invalid utf8-custom-section-id.wast:1395 AGFzbQEAAAAABQTxgID9 +malformed invalid utf8-custom-section-id.wast:1405 AGFzbQEAAAAABQTzgIAA +malformed invalid utf8-custom-section-id.wast:1415 AGFzbQEAAAAABQTzgIB/ +malformed invalid utf8-custom-section-id.wast:1425 AGFzbQEAAAAABQTzgIDA +malformed invalid utf8-custom-section-id.wast:1435 AGFzbQEAAAAABQTzgID9 +malformed invalid utf8-custom-section-id.wast:1445 AGFzbQEAAAAABQT0gIAA +malformed invalid utf8-custom-section-id.wast:1455 AGFzbQEAAAAABQT0gIB/ +malformed invalid utf8-custom-section-id.wast:1465 AGFzbQEAAAAABQT0gIDA +malformed invalid utf8-custom-section-id.wast:1475 AGFzbQEAAAAABQT0gID9 +malformed invalid utf8-custom-section-id.wast:1487 AGFzbQEAAAAABwb4gICAgIA= +malformed invalid utf8-custom-section-id.wast:1497 AGFzbQEAAAAABQT4gICA +malformed invalid utf8-custom-section-id.wast:1507 AGFzbQEAAAAABgX4gICAIw== +malformed invalid utf8-custom-section-id.wast:1517 AGFzbQEAAAAABAP4gIA= +malformed invalid utf8-custom-section-id.wast:1527 AGFzbQEAAAAABQT4gIAj +malformed invalid utf8-custom-section-id.wast:1537 AGFzbQEAAAAAAwL4gA== +malformed invalid utf8-custom-section-id.wast:1547 AGFzbQEAAAAABAP4gCM= +malformed invalid utf8-custom-section-id.wast:1557 AGFzbQEAAAAAAgH4 +malformed invalid utf8-custom-section-id.wast:1567 AGFzbQEAAAAAAwL4Iw== +malformed invalid utf8-custom-section-id.wast:1579 AGFzbQEAAAAABgX4gICAgA== +malformed invalid utf8-custom-section-id.wast:1589 AGFzbQEAAAAABgX7v7+/vw== +malformed invalid utf8-custom-section-id.wast:1601 AGFzbQEAAAAACAf8gICAgICA +malformed invalid utf8-custom-section-id.wast:1611 AGFzbQEAAAAABgX8gICAgA== +malformed invalid utf8-custom-section-id.wast:1621 AGFzbQEAAAAABwb8gICAgCM= +malformed invalid utf8-custom-section-id.wast:1631 AGFzbQEAAAAABQT8gICA +malformed invalid utf8-custom-section-id.wast:1641 AGFzbQEAAAAABgX8gICAIw== +malformed invalid utf8-custom-section-id.wast:1651 AGFzbQEAAAAABAP8gIA= +malformed invalid utf8-custom-section-id.wast:1661 AGFzbQEAAAAABQT8gIAj +malformed invalid utf8-custom-section-id.wast:1671 AGFzbQEAAAAAAwL8gA== +malformed invalid utf8-custom-section-id.wast:1681 AGFzbQEAAAAABAP8gCM= +malformed invalid utf8-custom-section-id.wast:1691 AGFzbQEAAAAAAgH8 +malformed invalid utf8-custom-section-id.wast:1701 AGFzbQEAAAAAAwL8Iw== +malformed invalid utf8-custom-section-id.wast:1713 AGFzbQEAAAAABwb8gICAgIA= +malformed invalid utf8-custom-section-id.wast:1723 AGFzbQEAAAAABwb9v7+/v78= +malformed invalid utf8-custom-section-id.wast:1735 AGFzbQEAAAAAAgH+ +malformed invalid utf8-custom-section-id.wast:1745 AGFzbQEAAAAAAgH/ +malformed invalid utf8-custom-section-id.wast:1755 AGFzbQEAAAAAAwL+/w== +malformed invalid utf8-custom-section-id.wast:1765 AGFzbQEAAAAABQQAAP7/ +malformed invalid utf8-custom-section-id.wast:1775 AGFzbQEAAAAAAwL//g== +malformed invalid utf8-custom-section-id.wast:1785 AGFzbQEAAAAABQT//gAA +malformed invalid utf8-import-field.wast:7 AGFzbQEAAAACCwEBgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:22 AGFzbQEAAAACCwEBjwR0ZXN0A38A +malformed invalid utf8-import-field.wast:37 AGFzbQEAAAACCwEBkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:52 AGFzbQEAAAACCwEBnwR0ZXN0A38A +malformed invalid utf8-import-field.wast:67 AGFzbQEAAAACCwEBoAR0ZXN0A38A +malformed invalid utf8-import-field.wast:82 AGFzbQEAAAACCwEBvwR0ZXN0A38A +malformed invalid utf8-import-field.wast:99 AGFzbQEAAAACDQEDwoCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:114 AGFzbQEAAAACCwEBwgR0ZXN0A38A +malformed invalid utf8-import-field.wast:129 AGFzbQEAAAACDAECwi4EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:146 AGFzbQEAAAACDAECwIAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:161 AGFzbQEAAAACDAECwL8EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:176 AGFzbQEAAAACDAECwYAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:191 AGFzbQEAAAACDAECwb8EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:206 AGFzbQEAAAACDAECwgAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:221 AGFzbQEAAAACDAECwn8EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:236 AGFzbQEAAAACDAECwsAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:251 AGFzbQEAAAACDAECwv0EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:266 AGFzbQEAAAACDAEC3wAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:281 AGFzbQEAAAACDAEC338EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:296 AGFzbQEAAAACDAEC38AEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:311 AGFzbQEAAAACDAEC3/0EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:328 AGFzbQEAAAACDgEE4YCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:343 AGFzbQEAAAACDAEC4YAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:358 AGFzbQEAAAACDQED4YAuBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:373 AGFzbQEAAAACCwEB4QR0ZXN0A38A +malformed invalid utf8-import-field.wast:388 AGFzbQEAAAACDAEC4S4EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:405 AGFzbQEAAAACDQED4ACgBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:420 AGFzbQEAAAACDQED4H+gBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:435 AGFzbQEAAAACDQED4ICABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:450 AGFzbQEAAAACDQED4ICgBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:465 AGFzbQEAAAACDQED4J+gBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:480 AGFzbQEAAAACDQED4J+/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:495 AGFzbQEAAAACDQED4MCgBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:510 AGFzbQEAAAACDQED4P2gBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:525 AGFzbQEAAAACDQED4QCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:540 AGFzbQEAAAACDQED4X+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:555 AGFzbQEAAAACDQED4cCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:570 AGFzbQEAAAACDQED4f2ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:585 AGFzbQEAAAACDQED7ACABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:600 AGFzbQEAAAACDQED7H+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:615 AGFzbQEAAAACDQED7MCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:630 AGFzbQEAAAACDQED7P2ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:645 AGFzbQEAAAACDQED7QCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:660 AGFzbQEAAAACDQED7X+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:675 AGFzbQEAAAACDQED7aCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:690 AGFzbQEAAAACDQED7aC/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:705 AGFzbQEAAAACDQED7b+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:720 AGFzbQEAAAACDQED7b+/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:735 AGFzbQEAAAACDQED7cCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:750 AGFzbQEAAAACDQED7f2ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:765 AGFzbQEAAAACDQED7gCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:780 AGFzbQEAAAACDQED7n+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:795 AGFzbQEAAAACDQED7sCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:810 AGFzbQEAAAACDQED7v2ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:825 AGFzbQEAAAACDQED7wCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:840 AGFzbQEAAAACDQED73+ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:855 AGFzbQEAAAACDQED78CABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:870 AGFzbQEAAAACDQED7/2ABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:887 AGFzbQEAAAACDQED4KAABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:902 AGFzbQEAAAACDQED4KB/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:917 AGFzbQEAAAACDQED4KDABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:932 AGFzbQEAAAACDQED4KD9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:947 AGFzbQEAAAACDQED4YAABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:962 AGFzbQEAAAACDQED4YB/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:977 AGFzbQEAAAACDQED4YDABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:992 AGFzbQEAAAACDQED4YD9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1007 AGFzbQEAAAACDQED7IAABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1022 AGFzbQEAAAACDQED7IB/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1037 AGFzbQEAAAACDQED7IDABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1052 AGFzbQEAAAACDQED7ID9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1067 AGFzbQEAAAACDQED7YAABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1082 AGFzbQEAAAACDQED7YB/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1097 AGFzbQEAAAACDQED7YDABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1112 AGFzbQEAAAACDQED7YD9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1127 AGFzbQEAAAACDQED7oAABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1142 AGFzbQEAAAACDQED7oB/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1157 AGFzbQEAAAACDQED7oDABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1172 AGFzbQEAAAACDQED7oD9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1187 AGFzbQEAAAACDQED74AABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1202 AGFzbQEAAAACDQED74B/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1217 AGFzbQEAAAACDQED74DABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1232 AGFzbQEAAAACDQED74D9BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1249 AGFzbQEAAAACDwEF8YCAgIAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:1264 AGFzbQEAAAACDQED8YCABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1279 AGFzbQEAAAACDgEE8YCAIwR0ZXN0A38A +malformed invalid utf8-import-field.wast:1294 AGFzbQEAAAACDAEC8YAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:1309 AGFzbQEAAAACDQED8YAjBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:1324 AGFzbQEAAAACCwEB8QR0ZXN0A38A +malformed invalid utf8-import-field.wast:1339 AGFzbQEAAAACDAEC8SMEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:1356 AGFzbQEAAAACDgEE8ACQkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1371 AGFzbQEAAAACDgEE8H+QkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1386 AGFzbQEAAAACDgEE8ICAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1401 AGFzbQEAAAACDgEE8ICQkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1416 AGFzbQEAAAACDgEE8I+QkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1431 AGFzbQEAAAACDgEE8I+/vwR0ZXN0A38A +malformed invalid utf8-import-field.wast:1446 AGFzbQEAAAACDgEE8MCQkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1461 AGFzbQEAAAACDgEE8P2QkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1476 AGFzbQEAAAACDgEE8QCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1491 AGFzbQEAAAACDgEE8X+AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1506 AGFzbQEAAAACDgEE8cCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1521 AGFzbQEAAAACDgEE8f2AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1536 AGFzbQEAAAACDgEE8wCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1551 AGFzbQEAAAACDgEE83+AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1566 AGFzbQEAAAACDgEE88CAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1581 AGFzbQEAAAACDgEE8/2AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1596 AGFzbQEAAAACDgEE9ACAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1611 AGFzbQEAAAACDgEE9H+AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1626 AGFzbQEAAAACDgEE9JCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1641 AGFzbQEAAAACDgEE9L+AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1656 AGFzbQEAAAACDgEE9MCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1671 AGFzbQEAAAACDgEE9P2AgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1686 AGFzbQEAAAACDgEE9YCAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1701 AGFzbQEAAAACDgEE94CAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1716 AGFzbQEAAAACDgEE97+/vwR0ZXN0A38A +malformed invalid utf8-import-field.wast:1733 AGFzbQEAAAACDgEE8JAAkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1748 AGFzbQEAAAACDgEE8JB/kAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1763 AGFzbQEAAAACDgEE8JDAkAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1778 AGFzbQEAAAACDgEE8JD9kAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1793 AGFzbQEAAAACDgEE8YAAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1808 AGFzbQEAAAACDgEE8YB/gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1823 AGFzbQEAAAACDgEE8YDAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1838 AGFzbQEAAAACDgEE8YD9gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1853 AGFzbQEAAAACDgEE84AAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1868 AGFzbQEAAAACDgEE84B/gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1883 AGFzbQEAAAACDgEE84DAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1898 AGFzbQEAAAACDgEE84D9gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1913 AGFzbQEAAAACDgEE9IAAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1928 AGFzbQEAAAACDgEE9IB/gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1943 AGFzbQEAAAACDgEE9IDAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1958 AGFzbQEAAAACDgEE9ID9gAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1975 AGFzbQEAAAACDgEE8JCQAAR0ZXN0A38A +malformed invalid utf8-import-field.wast:1990 AGFzbQEAAAACDgEE8JCQfwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2005 AGFzbQEAAAACDgEE8JCQwAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2020 AGFzbQEAAAACDgEE8JCQ/QR0ZXN0A38A +malformed invalid utf8-import-field.wast:2035 AGFzbQEAAAACDgEE8YCAAAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2050 AGFzbQEAAAACDgEE8YCAfwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2065 AGFzbQEAAAACDgEE8YCAwAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2080 AGFzbQEAAAACDgEE8YCA/QR0ZXN0A38A +malformed invalid utf8-import-field.wast:2095 AGFzbQEAAAACDgEE84CAAAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2110 AGFzbQEAAAACDgEE84CAfwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2125 AGFzbQEAAAACDgEE84CAwAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2140 AGFzbQEAAAACDgEE84CA/QR0ZXN0A38A +malformed invalid utf8-import-field.wast:2155 AGFzbQEAAAACDgEE9ICAAAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2170 AGFzbQEAAAACDgEE9ICAfwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2185 AGFzbQEAAAACDgEE9ICAwAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2200 AGFzbQEAAAACDgEE9ICA/QR0ZXN0A38A +malformed invalid utf8-import-field.wast:2217 AGFzbQEAAAACEAEG+ICAgICABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2232 AGFzbQEAAAACDgEE+ICAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2247 AGFzbQEAAAACDwEF+ICAgCMEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2262 AGFzbQEAAAACDQED+ICABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2277 AGFzbQEAAAACDgEE+ICAIwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2292 AGFzbQEAAAACDAEC+IAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2307 AGFzbQEAAAACDQED+IAjBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2322 AGFzbQEAAAACCwEB+AR0ZXN0A38A +malformed invalid utf8-import-field.wast:2337 AGFzbQEAAAACDAEC+CMEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2354 AGFzbQEAAAACDwEF+ICAgIAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2369 AGFzbQEAAAACDwEF+7+/v78EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2386 AGFzbQEAAAACEQEH/ICAgICAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2401 AGFzbQEAAAACDwEF/ICAgIAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2416 AGFzbQEAAAACEAEG/ICAgIAjBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2431 AGFzbQEAAAACDgEE/ICAgAR0ZXN0A38A +malformed invalid utf8-import-field.wast:2446 AGFzbQEAAAACDwEF/ICAgCMEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2461 AGFzbQEAAAACDQED/ICABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2476 AGFzbQEAAAACDgEE/ICAIwR0ZXN0A38A +malformed invalid utf8-import-field.wast:2491 AGFzbQEAAAACDAEC/IAEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2506 AGFzbQEAAAACDQED/IAjBHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2521 AGFzbQEAAAACCwEB/AR0ZXN0A38A +malformed invalid utf8-import-field.wast:2536 AGFzbQEAAAACDAEC/CMEdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2553 AGFzbQEAAAACEAEG/ICAgICABHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2568 AGFzbQEAAAACEAEG/b+/v7+/BHRlc3QDfwA= +malformed invalid utf8-import-field.wast:2585 AGFzbQEAAAACCwEB/gR0ZXN0A38A +malformed invalid utf8-import-field.wast:2600 AGFzbQEAAAACCwEB/wR0ZXN0A38A +malformed invalid utf8-import-field.wast:2615 AGFzbQEAAAACDAEC/v8EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2630 AGFzbQEAAAACDgEEAAD+/wR0ZXN0A38A +malformed invalid utf8-import-field.wast:2645 AGFzbQEAAAACDAEC//4EdGVzdAN/AA== +malformed invalid utf8-import-field.wast:2660 AGFzbQEAAAACDgEE//4AAAR0ZXN0A38A +malformed invalid utf8-import-module.wast:7 AGFzbQEAAAACCwEEdGVzdAGAA38A +malformed invalid utf8-import-module.wast:22 AGFzbQEAAAACCwEEdGVzdAGPA38A +malformed invalid utf8-import-module.wast:37 AGFzbQEAAAACCwEEdGVzdAGQA38A +malformed invalid utf8-import-module.wast:52 AGFzbQEAAAACCwEEdGVzdAGfA38A +malformed invalid utf8-import-module.wast:67 AGFzbQEAAAACCwEEdGVzdAGgA38A +malformed invalid utf8-import-module.wast:82 AGFzbQEAAAACCwEEdGVzdAG/A38A +malformed invalid utf8-import-module.wast:99 AGFzbQEAAAACDQEEdGVzdAPCgIADfwA= +malformed invalid utf8-import-module.wast:114 AGFzbQEAAAACCwEEdGVzdAHCA38A +malformed invalid utf8-import-module.wast:129 AGFzbQEAAAACDAEEdGVzdALCLgN/AA== +malformed invalid utf8-import-module.wast:146 AGFzbQEAAAACDAEEdGVzdALAgAN/AA== +malformed invalid utf8-import-module.wast:161 AGFzbQEAAAACDAEEdGVzdALAvwN/AA== +malformed invalid utf8-import-module.wast:176 AGFzbQEAAAACDAEEdGVzdALBgAN/AA== +malformed invalid utf8-import-module.wast:191 AGFzbQEAAAACDAEEdGVzdALBvwN/AA== +malformed invalid utf8-import-module.wast:206 AGFzbQEAAAACDAEEdGVzdALCAAN/AA== +malformed invalid utf8-import-module.wast:221 AGFzbQEAAAACDAEEdGVzdALCfwN/AA== +malformed invalid utf8-import-module.wast:236 AGFzbQEAAAACDAEEdGVzdALCwAN/AA== +malformed invalid utf8-import-module.wast:251 AGFzbQEAAAACDAEEdGVzdALC/QN/AA== +malformed invalid utf8-import-module.wast:266 AGFzbQEAAAACDAEEdGVzdALfAAN/AA== +malformed invalid utf8-import-module.wast:281 AGFzbQEAAAACDAEEdGVzdALffwN/AA== +malformed invalid utf8-import-module.wast:296 AGFzbQEAAAACDAEEdGVzdALfwAN/AA== +malformed invalid utf8-import-module.wast:311 AGFzbQEAAAACDAEEdGVzdALf/QN/AA== +malformed invalid utf8-import-module.wast:328 AGFzbQEAAAACDgEEdGVzdAThgICAA38A +malformed invalid utf8-import-module.wast:343 AGFzbQEAAAACDAEEdGVzdALhgAN/AA== +malformed invalid utf8-import-module.wast:358 AGFzbQEAAAACDQEEdGVzdAPhgC4DfwA= +malformed invalid utf8-import-module.wast:373 AGFzbQEAAAACCwEEdGVzdAHhA38A +malformed invalid utf8-import-module.wast:388 AGFzbQEAAAACDAEEdGVzdALhLgN/AA== +malformed invalid utf8-import-module.wast:405 AGFzbQEAAAACDQEEdGVzdAPgAKADfwA= +malformed invalid utf8-import-module.wast:420 AGFzbQEAAAACDQEEdGVzdAPgf6ADfwA= +malformed invalid utf8-import-module.wast:435 AGFzbQEAAAACDQEEdGVzdAPggIADfwA= +malformed invalid utf8-import-module.wast:450 AGFzbQEAAAACDQEEdGVzdAPggKADfwA= +malformed invalid utf8-import-module.wast:465 AGFzbQEAAAACDQEEdGVzdAPgn6ADfwA= +malformed invalid utf8-import-module.wast:480 AGFzbQEAAAACDQEEdGVzdAPgn78DfwA= +malformed invalid utf8-import-module.wast:495 AGFzbQEAAAACDQEEdGVzdAPgwKADfwA= +malformed invalid utf8-import-module.wast:510 AGFzbQEAAAACDQEEdGVzdAPg/aADfwA= +malformed invalid utf8-import-module.wast:525 AGFzbQEAAAACDQEEdGVzdAPhAIADfwA= +malformed invalid utf8-import-module.wast:540 AGFzbQEAAAACDQEEdGVzdAPhf4ADfwA= +malformed invalid utf8-import-module.wast:555 AGFzbQEAAAACDQEEdGVzdAPhwIADfwA= +malformed invalid utf8-import-module.wast:570 AGFzbQEAAAACDQEEdGVzdAPh/YADfwA= +malformed invalid utf8-import-module.wast:585 AGFzbQEAAAACDQEEdGVzdAPsAIADfwA= +malformed invalid utf8-import-module.wast:600 AGFzbQEAAAACDQEEdGVzdAPsf4ADfwA= +malformed invalid utf8-import-module.wast:615 AGFzbQEAAAACDQEEdGVzdAPswIADfwA= +malformed invalid utf8-import-module.wast:630 AGFzbQEAAAACDQEEdGVzdAPs/YADfwA= +malformed invalid utf8-import-module.wast:645 AGFzbQEAAAACDQEEdGVzdAPtAIADfwA= +malformed invalid utf8-import-module.wast:660 AGFzbQEAAAACDQEEdGVzdAPtf4ADfwA= +malformed invalid utf8-import-module.wast:675 AGFzbQEAAAACDQEEdGVzdAPtoIADfwA= +malformed invalid utf8-import-module.wast:690 AGFzbQEAAAACDQEEdGVzdAPtoL8DfwA= +malformed invalid utf8-import-module.wast:705 AGFzbQEAAAACDQEEdGVzdAPtv4ADfwA= +malformed invalid utf8-import-module.wast:720 AGFzbQEAAAACDQEEdGVzdAPtv78DfwA= +malformed invalid utf8-import-module.wast:735 AGFzbQEAAAACDQEEdGVzdAPtwIADfwA= +malformed invalid utf8-import-module.wast:750 AGFzbQEAAAACDQEEdGVzdAPt/YADfwA= +malformed invalid utf8-import-module.wast:765 AGFzbQEAAAACDQEEdGVzdAPuAIADfwA= +malformed invalid utf8-import-module.wast:780 AGFzbQEAAAACDQEEdGVzdAPuf4ADfwA= +malformed invalid utf8-import-module.wast:795 AGFzbQEAAAACDQEEdGVzdAPuwIADfwA= +malformed invalid utf8-import-module.wast:810 AGFzbQEAAAACDQEEdGVzdAPu/YADfwA= +malformed invalid utf8-import-module.wast:825 AGFzbQEAAAACDQEEdGVzdAPvAIADfwA= +malformed invalid utf8-import-module.wast:840 AGFzbQEAAAACDQEEdGVzdAPvf4ADfwA= +malformed invalid utf8-import-module.wast:855 AGFzbQEAAAACDQEEdGVzdAPvwIADfwA= +malformed invalid utf8-import-module.wast:870 AGFzbQEAAAACDQEEdGVzdAPv/YADfwA= +malformed invalid utf8-import-module.wast:887 AGFzbQEAAAACDQEEdGVzdAPgoAADfwA= +malformed invalid utf8-import-module.wast:902 AGFzbQEAAAACDQEEdGVzdAPgoH8DfwA= +malformed invalid utf8-import-module.wast:917 AGFzbQEAAAACDQEEdGVzdAPgoMADfwA= +malformed invalid utf8-import-module.wast:932 AGFzbQEAAAACDQEEdGVzdAPgoP0DfwA= +malformed invalid utf8-import-module.wast:947 AGFzbQEAAAACDQEEdGVzdAPhgAADfwA= +malformed invalid utf8-import-module.wast:962 AGFzbQEAAAACDQEEdGVzdAPhgH8DfwA= +malformed invalid utf8-import-module.wast:977 AGFzbQEAAAACDQEEdGVzdAPhgMADfwA= +malformed invalid utf8-import-module.wast:992 AGFzbQEAAAACDQEEdGVzdAPhgP0DfwA= +malformed invalid utf8-import-module.wast:1007 AGFzbQEAAAACDQEEdGVzdAPsgAADfwA= +malformed invalid utf8-import-module.wast:1022 AGFzbQEAAAACDQEEdGVzdAPsgH8DfwA= +malformed invalid utf8-import-module.wast:1037 AGFzbQEAAAACDQEEdGVzdAPsgMADfwA= +malformed invalid utf8-import-module.wast:1052 AGFzbQEAAAACDQEEdGVzdAPsgP0DfwA= +malformed invalid utf8-import-module.wast:1067 AGFzbQEAAAACDQEEdGVzdAPtgAADfwA= +malformed invalid utf8-import-module.wast:1082 AGFzbQEAAAACDQEEdGVzdAPtgH8DfwA= +malformed invalid utf8-import-module.wast:1097 AGFzbQEAAAACDQEEdGVzdAPtgMADfwA= +malformed invalid utf8-import-module.wast:1112 AGFzbQEAAAACDQEEdGVzdAPtgP0DfwA= +malformed invalid utf8-import-module.wast:1127 AGFzbQEAAAACDQEEdGVzdAPugAADfwA= +malformed invalid utf8-import-module.wast:1142 AGFzbQEAAAACDQEEdGVzdAPugH8DfwA= +malformed invalid utf8-import-module.wast:1157 AGFzbQEAAAACDQEEdGVzdAPugMADfwA= +malformed invalid utf8-import-module.wast:1172 AGFzbQEAAAACDQEEdGVzdAPugP0DfwA= +malformed invalid utf8-import-module.wast:1187 AGFzbQEAAAACDQEEdGVzdAPvgAADfwA= +malformed invalid utf8-import-module.wast:1202 AGFzbQEAAAACDQEEdGVzdAPvgH8DfwA= +malformed invalid utf8-import-module.wast:1217 AGFzbQEAAAACDQEEdGVzdAPvgMADfwA= +malformed invalid utf8-import-module.wast:1232 AGFzbQEAAAACDQEEdGVzdAPvgP0DfwA= +malformed invalid utf8-import-module.wast:1249 AGFzbQEAAAACDwEEdGVzdAXxgICAgAN/AA== +malformed invalid utf8-import-module.wast:1264 AGFzbQEAAAACDQEEdGVzdAPxgIADfwA= +malformed invalid utf8-import-module.wast:1279 AGFzbQEAAAACDgEEdGVzdATxgIAjA38A +malformed invalid utf8-import-module.wast:1294 AGFzbQEAAAACDAEEdGVzdALxgAN/AA== +malformed invalid utf8-import-module.wast:1309 AGFzbQEAAAACDQEEdGVzdAPxgCMDfwA= +malformed invalid utf8-import-module.wast:1324 AGFzbQEAAAACCwEEdGVzdAHxA38A +malformed invalid utf8-import-module.wast:1339 AGFzbQEAAAACDAEEdGVzdALxIwN/AA== +malformed invalid utf8-import-module.wast:1356 AGFzbQEAAAACDgEEdGVzdATwAJCQA38A +malformed invalid utf8-import-module.wast:1371 AGFzbQEAAAACDgEEdGVzdATwf5CQA38A +malformed invalid utf8-import-module.wast:1386 AGFzbQEAAAACDgEEdGVzdATwgICAA38A +malformed invalid utf8-import-module.wast:1401 AGFzbQEAAAACDgEEdGVzdATwgJCQA38A +malformed invalid utf8-import-module.wast:1416 AGFzbQEAAAACDgEEdGVzdATwj5CQA38A +malformed invalid utf8-import-module.wast:1431 AGFzbQEAAAACDgEEdGVzdATwj7+/A38A +malformed invalid utf8-import-module.wast:1446 AGFzbQEAAAACDgEEdGVzdATwwJCQA38A +malformed invalid utf8-import-module.wast:1461 AGFzbQEAAAACDgEEdGVzdATw/ZCQA38A +malformed invalid utf8-import-module.wast:1476 AGFzbQEAAAACDgEEdGVzdATxAICAA38A +malformed invalid utf8-import-module.wast:1491 AGFzbQEAAAACDgEEdGVzdATxf4CAA38A +malformed invalid utf8-import-module.wast:1506 AGFzbQEAAAACDgEEdGVzdATxwICAA38A +malformed invalid utf8-import-module.wast:1521 AGFzbQEAAAACDgEEdGVzdATx/YCAA38A +malformed invalid utf8-import-module.wast:1536 AGFzbQEAAAACDgEEdGVzdATzAICAA38A +malformed invalid utf8-import-module.wast:1551 AGFzbQEAAAACDgEEdGVzdATzf4CAA38A +malformed invalid utf8-import-module.wast:1566 AGFzbQEAAAACDgEEdGVzdATzwICAA38A +malformed invalid utf8-import-module.wast:1581 AGFzbQEAAAACDgEEdGVzdATz/YCAA38A +malformed invalid utf8-import-module.wast:1596 AGFzbQEAAAACDgEEdGVzdAT0AICAA38A +malformed invalid utf8-import-module.wast:1611 AGFzbQEAAAACDgEEdGVzdAT0f4CAA38A +malformed invalid utf8-import-module.wast:1626 AGFzbQEAAAACDgEEdGVzdAT0kICAA38A +malformed invalid utf8-import-module.wast:1641 AGFzbQEAAAACDgEEdGVzdAT0v4CAA38A +malformed invalid utf8-import-module.wast:1656 AGFzbQEAAAACDgEEdGVzdAT0wICAA38A +malformed invalid utf8-import-module.wast:1671 AGFzbQEAAAACDgEEdGVzdAT0/YCAA38A +malformed invalid utf8-import-module.wast:1686 AGFzbQEAAAACDgEEdGVzdAT1gICAA38A +malformed invalid utf8-import-module.wast:1701 AGFzbQEAAAACDgEEdGVzdAT3gICAA38A +malformed invalid utf8-import-module.wast:1716 AGFzbQEAAAACDgEEdGVzdAT3v7+/A38A +malformed invalid utf8-import-module.wast:1733 AGFzbQEAAAACDgEEdGVzdATwkACQA38A +malformed invalid utf8-import-module.wast:1748 AGFzbQEAAAACDgEEdGVzdATwkH+QA38A +malformed invalid utf8-import-module.wast:1763 AGFzbQEAAAACDgEEdGVzdATwkMCQA38A +malformed invalid utf8-import-module.wast:1778 AGFzbQEAAAACDgEEdGVzdATwkP2QA38A +malformed invalid utf8-import-module.wast:1793 AGFzbQEAAAACDgEEdGVzdATxgACAA38A +malformed invalid utf8-import-module.wast:1808 AGFzbQEAAAACDgEEdGVzdATxgH+AA38A +malformed invalid utf8-import-module.wast:1823 AGFzbQEAAAACDgEEdGVzdATxgMCAA38A +malformed invalid utf8-import-module.wast:1838 AGFzbQEAAAACDgEEdGVzdATxgP2AA38A +malformed invalid utf8-import-module.wast:1853 AGFzbQEAAAACDgEEdGVzdATzgACAA38A +malformed invalid utf8-import-module.wast:1868 AGFzbQEAAAACDgEEdGVzdATzgH+AA38A +malformed invalid utf8-import-module.wast:1883 AGFzbQEAAAACDgEEdGVzdATzgMCAA38A +malformed invalid utf8-import-module.wast:1898 AGFzbQEAAAACDgEEdGVzdATzgP2AA38A +malformed invalid utf8-import-module.wast:1913 AGFzbQEAAAACDgEEdGVzdAT0gACAA38A +malformed invalid utf8-import-module.wast:1928 AGFzbQEAAAACDgEEdGVzdAT0gH+AA38A +malformed invalid utf8-import-module.wast:1943 AGFzbQEAAAACDgEEdGVzdAT0gMCAA38A +malformed invalid utf8-import-module.wast:1958 AGFzbQEAAAACDgEEdGVzdAT0gP2AA38A +malformed invalid utf8-import-module.wast:1975 AGFzbQEAAAACDgEEdGVzdATwkJAAA38A +malformed invalid utf8-import-module.wast:1990 AGFzbQEAAAACDgEEdGVzdATwkJB/A38A +malformed invalid utf8-import-module.wast:2005 AGFzbQEAAAACDgEEdGVzdATwkJDAA38A +malformed invalid utf8-import-module.wast:2020 AGFzbQEAAAACDgEEdGVzdATwkJD9A38A +malformed invalid utf8-import-module.wast:2035 AGFzbQEAAAACDgEEdGVzdATxgIAAA38A +malformed invalid utf8-import-module.wast:2050 AGFzbQEAAAACDgEEdGVzdATxgIB/A38A +malformed invalid utf8-import-module.wast:2065 AGFzbQEAAAACDgEEdGVzdATxgIDAA38A +malformed invalid utf8-import-module.wast:2080 AGFzbQEAAAACDgEEdGVzdATxgID9A38A +malformed invalid utf8-import-module.wast:2095 AGFzbQEAAAACDgEEdGVzdATzgIAAA38A +malformed invalid utf8-import-module.wast:2110 AGFzbQEAAAACDgEEdGVzdATzgIB/A38A +malformed invalid utf8-import-module.wast:2125 AGFzbQEAAAACDgEEdGVzdATzgIDAA38A +malformed invalid utf8-import-module.wast:2140 AGFzbQEAAAACDgEEdGVzdATzgID9A38A +malformed invalid utf8-import-module.wast:2155 AGFzbQEAAAACDgEEdGVzdAT0gIAAA38A +malformed invalid utf8-import-module.wast:2170 AGFzbQEAAAACDgEEdGVzdAT0gIB/A38A +malformed invalid utf8-import-module.wast:2185 AGFzbQEAAAACDgEEdGVzdAT0gIDAA38A +malformed invalid utf8-import-module.wast:2200 AGFzbQEAAAACDgEEdGVzdAT0gID9A38A +malformed invalid utf8-import-module.wast:2217 AGFzbQEAAAACEAEEdGVzdAb4gICAgIADfwA= +malformed invalid utf8-import-module.wast:2232 AGFzbQEAAAACDgEEdGVzdAT4gICAA38A +malformed invalid utf8-import-module.wast:2247 AGFzbQEAAAACDwEEdGVzdAX4gICAIwN/AA== +malformed invalid utf8-import-module.wast:2262 AGFzbQEAAAACDQEEdGVzdAP4gIADfwA= +malformed invalid utf8-import-module.wast:2277 AGFzbQEAAAACDgEEdGVzdAT4gIAjA38A +malformed invalid utf8-import-module.wast:2292 AGFzbQEAAAACDAEEdGVzdAL4gAN/AA== +malformed invalid utf8-import-module.wast:2307 AGFzbQEAAAACDQEEdGVzdAP4gCMDfwA= +malformed invalid utf8-import-module.wast:2322 AGFzbQEAAAACCwEEdGVzdAH4A38A +malformed invalid utf8-import-module.wast:2337 AGFzbQEAAAACDAEEdGVzdAL4IwN/AA== +malformed invalid utf8-import-module.wast:2354 AGFzbQEAAAACDwEEdGVzdAX4gICAgAN/AA== +malformed invalid utf8-import-module.wast:2369 AGFzbQEAAAACDwEEdGVzdAX7v7+/vwN/AA== +malformed invalid utf8-import-module.wast:2386 AGFzbQEAAAACEQEEdGVzdAf8gICAgICAA38A +malformed invalid utf8-import-module.wast:2401 AGFzbQEAAAACDwEEdGVzdAX8gICAgAN/AA== +malformed invalid utf8-import-module.wast:2416 AGFzbQEAAAACEAEEdGVzdAb8gICAgCMDfwA= +malformed invalid utf8-import-module.wast:2431 AGFzbQEAAAACDgEEdGVzdAT8gICAA38A +malformed invalid utf8-import-module.wast:2446 AGFzbQEAAAACDwEEdGVzdAX8gICAIwN/AA== +malformed invalid utf8-import-module.wast:2461 AGFzbQEAAAACDQEEdGVzdAP8gIADfwA= +malformed invalid utf8-import-module.wast:2476 AGFzbQEAAAACDgEEdGVzdAT8gIAjA38A +malformed invalid utf8-import-module.wast:2491 AGFzbQEAAAACDAEEdGVzdAL8gAN/AA== +malformed invalid utf8-import-module.wast:2506 AGFzbQEAAAACDQEEdGVzdAP8gCMDfwA= +malformed invalid utf8-import-module.wast:2521 AGFzbQEAAAACCwEEdGVzdAH8A38A +malformed invalid utf8-import-module.wast:2536 AGFzbQEAAAACDAEEdGVzdAL8IwN/AA== +malformed invalid utf8-import-module.wast:2553 AGFzbQEAAAACEAEEdGVzdAb8gICAgIADfwA= +malformed invalid utf8-import-module.wast:2568 AGFzbQEAAAACEAEEdGVzdAb9v7+/v78DfwA= +malformed invalid utf8-import-module.wast:2585 AGFzbQEAAAACCwEEdGVzdAH+A38A +malformed invalid utf8-import-module.wast:2600 AGFzbQEAAAACCwEEdGVzdAH/A38A +malformed invalid utf8-import-module.wast:2615 AGFzbQEAAAACDAEEdGVzdAL+/wN/AA== +malformed invalid utf8-import-module.wast:2630 AGFzbQEAAAACDgEEdGVzdAQAAP7/A38A +malformed invalid utf8-import-module.wast:2645 AGFzbQEAAAACDAEEdGVzdAL//gN/AA== +malformed invalid utf8-import-module.wast:2660 AGFzbQEAAAACDgEEdGVzdAT//gAAA38A +valid valid extended-const/global.wast:3 AGFzbQEAAAABNw1gAn9/AX9gAAF/YAABfmAAAW9gAX8AYAF+AGABbwBgAAF9YAABfGABfQBgAXwAYAAAYAF/AX8CLwIIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAhzcGVjdGVzdApnbG9iYWxfaTY0A34AAzc2AQIDAwECAQIBAgECBAUGBwgHCAkKCwEBAQEBAQEBAQEBAQEAAQEBCwsBAQwBAQsBDAwBAQEBBAUBcAEBAQUDAQABBoIBEX8AQX4LfQBDAABAwAt8AEQAAAAAAAAQwAt+AEJ7C38BQXQLfQFDAABQwQt8AUQAAAAAAAAswAt+AUJxC38AIwALfgAjAQt/AEEUQQJsQQJrQQRqC34AQhRCAn5CAn1CBXwLfwAjAEEqagt+ACMBQip8C28A0G8LbwHQbwtwANBwCwfVBTMFZ2V0LWEAAAVnZXQtYgABBWdldC1yAAIGZ2V0LW1yAAMFZ2V0LXgABAVnZXQteQAFBmdldC16MQAGBmdldC16MgAHBmdldC16MwAIBmdldC16NAAJBmdldC16NQAKBmdldC16NgALBXNldC14AAwFc2V0LXkADQZzZXQtbXIADgVnZXQtMwAPBWdldC00ABAFZ2V0LTcAEQVnZXQtOAASBXNldC03ABMFc2V0LTgAFA9hcy1zZWxlY3QtZmlyc3QAFg1hcy1zZWxlY3QtbWlkABcOYXMtc2VsZWN0LWxhc3QAGA1hcy1sb29wLWZpcnN0ABkLYXMtbG9vcC1taWQAGgxhcy1sb29wLWxhc3QAGw9hcy1pZi1jb25kaXRpb24AHAphcy1pZi10aGVuAB0KYXMtaWYtZWxzZQAeDmFzLWJyX2lmLWZpcnN0AB8NYXMtYnJfaWYtbGFzdAAgEWFzLWJyX3RhYmxlLWZpcnN0ACEQYXMtYnJfdGFibGUtbGFzdAAiFmFzLWNhbGxfaW5kaXJlY3QtZmlyc3QAJBRhcy1jYWxsX2luZGlyZWN0LW1pZAAlFWFzLWNhbGxfaW5kaXJlY3QtbGFzdAAmDmFzLXN0b3JlLWZpcnN0ACcNYXMtc3RvcmUtbGFzdAAoD2FzLWxvYWQtb3BlcmFuZAApFGFzLW1lbW9yeS5ncm93LXZhbHVlACoNYXMtY2FsbC12YWx1ZQAsD2FzLXJldHVybi12YWx1ZQAtD2FzLWRyb3Atb3BlcmFuZAAuC2FzLWJyLXZhbHVlAC8SYXMtbG9jYWwuc2V0LXZhbHVlADASYXMtbG9jYWwudGVlLXZhbHVlADETYXMtZ2xvYmFsLnNldC12YWx1ZQAyEGFzLXVuYXJ5LW9wZXJhbmQAMxFhcy1iaW5hcnktb3BlcmFuZAA0EmFzLWNvbXBhcmUtb3BlcmFuZAA1CQcBAEEACwEjCsQDNgQAIwILBAAjBQsEACMQCwQAIxELBAAjBgsEACMJCwQAIwoLBAAjCwsEACMMCwQAIw0LBAAjDgsEACMPCwYAIAAkBgsGACAAJAkLBgAgACQRCwQAIwMLBAAjBAsEACMHCwQAIwgLBgAgACQHCwYAIAAkCAsCAAsJACMGQQJBAxsLCQBBAiMGQQMbCwkAQQJBAyMGGwsLAAN/IwYQFRAVCwsLAAN/EBUjBhAVCwsLAAN/EBUQFSMGCwsQACMGBH8QFUECBRAVQQMLCwwAQQEEfyMGBUECCwsMAEEABH9BAgUjBgsLDgACfyMGQQINAEEDDwsLDgACf0ECIwYNAEEDDwsLDQACfyMGQQIOAQAACwsNAAJ/QQIjBg4BAAALCwQAIAALDgACfyMGQQJBABEAAAsLDgACf0ECIwZBABEAAAsLDgACf0ECQQAjBhEAAAsLCQAjBkEBNgIACwkAQQAjBjYCAAsHACMGKAIACwYAIwZAAAsEACAACwYAIwYQKwsFACMGDwsFACMGGgsJAAJ/IwYMAAsLCAAjBiEAIAALBgAjBiIACwgAIwYkBiMGCwUAIwZFCwcAIwYjBmwLBwAjAEEBSws= +malformed invalid extended-const/global.wast:391 AGFzbQEAAAACmICAgAABCHNwZWN0ZXN0Cmdsb2JhbF9pMzIDfwI= +malformed invalid extended-const/global.wast:421 AGFzbQEAAAAGhoCAgAABfwJBAAs= +valid valid extended-const/data.wast:5 AGFzbQEAAAAFAwEAAQujARgAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmMAQQALAABBAQsEYWJjZABBAAsAAEEACwNhYmM= +valid valid extended-const/data.wast:179 AGFzbQEAAAAFAwEAAQsJAQBBAEEqagsA +valid valid extended-const/data.wast:184 AGFzbQEAAAAFAwEAAQsJAQBBKkEAawsA +valid valid extended-const/data.wast:189 AGFzbQEAAAAFAwEAAQsJAQBBAUECbAsA +valid valid extended-const/data.wast:196 AGFzbQEAAAACGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAUDAQABCw8BAEECIwBBAWtBAmpsCwA= +invalid invalid extended-const/elem.wast:536 AGFzbQEAAAABBQFgAAF/AwIBAAQEAXAAAQkJAQRBAAsBEAALCgYBBABBCQs= +valid valid extended-const/elem.wast:705 AGFzbQEAAAABCgJgAAF/YAF/AX8DAwIAAQQEAXAACgcRAQ1jYWxsX2luX3RhYmxlAAEJCgEAQQFBAmoLAQAKDgIEAEEqCwcAIAARAAAL +valid valid extended-const/elem.wast:716 AGFzbQEAAAABCgJgAAF/YAF/AX8DAwIAAQQEAXAACgcRAQ1jYWxsX2luX3RhYmxlAAEJCgEAQQJBAWsLAQAKDgIEAEEqCwcAIAARAAAL +valid valid extended-const/elem.wast:727 AGFzbQEAAAABCgJgAAF/YAF/AX8DAwIAAQQEAXAACgcRAQ1jYWxsX2luX3RhYmxlAAEJCgEAQQJBAmwLAQAKDgIEAEEqCwcAIAARAAAL +valid valid extended-const/elem.wast:740 AGFzbQEAAAABCgJgAAF/YAF/AX8CGAEIc3BlY3Rlc3QKZ2xvYmFsX2kzMgN/AAMDAgABBAQBcAAKBxEBDWNhbGxfaW5fdGFibGUAAQkRAQBBAiMAQZkFa0ECamwLAQAKDgIEAEEqCwcAIAARAAAL diff --git a/packages/compiler/test/wasm-spec.test.ts b/packages/compiler/test/wasm-spec.test.ts new file mode 100644 index 000000000..fe935e418 --- /dev/null +++ b/packages/compiler/test/wasm-spec.test.ts @@ -0,0 +1,168 @@ +/* The WebAssembly decoder (src/wasm/binary.ts) against the specification's + * test suite, against V8 on mutations of those modules, and on the inline + * modules of real packages in this workspace. V8 (the Node running the + * test) is the oracle: scriptc must accept exactly the modules Node + * accepts, within the translatable feature level. */ +import { globSync, readFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, test } from "vitest"; +import { analyzeWasm } from "../src/wasm/binary.js"; +import { decodeBase64 } from "../src/wasm/discover.js"; + +/** V8's verdict (the compiler's type world declares no WebAssembly value). */ +const v8Validate = (bytes: Uint8Array): boolean => + ( + globalThis as unknown as { WebAssembly: { validate(bytes: Uint8Array): boolean } } + ).WebAssembly.validate(bytes); + +interface SpecCase { + suite: string; + v8: string; + where: string; + bytes: Uint8Array; +} + +const cases: SpecCase[] = readFileSync(join(import.meta.dirname, "wasm-spec-cases.txt"), "utf8") + .split("\n") + .filter((line) => line !== "" && !line.startsWith("#")) + .map((line) => { + const [suite, v8, where, b64] = line.split(" "); + return { + suite: suite!, + v8: v8!, + where: where!, + bytes: new Uint8Array(Buffer.from(b64!, "base64")), + }; + }); + +const accepted = (status: string): boolean => status === "valid" || status === "unsupported"; + +describe("WebAssembly spec test suite", () => { + test("covers the 2.0 core suite and extended constant expressions", () => { + expect(cases.length).toBeGreaterThan(3000); + const extended = cases.filter((c) => c.where.startsWith("extended-const/")); + expect(extended.length).toBeGreaterThan(10); + expect( + extended.filter((c) => analyzeWasm(c.bytes).features.includes("extended-const")).length, + ).toBeGreaterThan(5); + }); + + test("every module gets V8's verdict and needs no other proposal", () => { + const wrong: string[] = []; + for (const c of cases) { + const s = analyzeWasm(c.bytes); + const v8 = v8Validate(c.bytes); + if ((v8 ? "valid" : "invalid") !== c.v8) wrong.push(`${c.where}: V8 changed its verdict`); + // Multiple memories are the one proposal outside the translatable set + // that 2.0 tests exercise (as invalid; V8 accepts them). + const allowed = s.status !== "unsupported" || s.unsupported.join() === "multi-memory"; + if (accepted(s.status) !== v8 || !allowed) { + wrong.push(`${c.where}: ${s.status} ${s.error ?? ""} (V8 ${v8 ? "accepts" : "rejects"})`); + } + } + expect(wrong).toEqual([]); + }); + + test("differs from the 2.0 suite only where WebAssembly 3.0 and V8 relaxed it", () => { + // Multiple memories became valid, and memory.size/grow's reserved byte + // a memory index, so a long LEB128 zero is accepted (multi-memory); + // global initializers and segment offsets may read defined immutable + // globals (GC proposal). + const relaxed = cases.filter((c) => c.suite !== "valid" && c.v8 === "valid"); + expect(relaxed.length).toBeGreaterThan(0); + for (const c of relaxed) { + expect(c.where).toMatch( + /^(?:extended-const\/)?(?:binary|data|elem|global|imports|memory)\.wast:\d+$/, + ); + } + expect(relaxed.length).toBeLessThan(30); + }); +}); + +describe("mutations of the suite's valid modules", () => { + test("never disagree with V8 (deterministic sample)", () => { + const seeds = cases.filter((c) => c.v8 === "valid").map((c) => c.bytes); + let state = 0x9e3779b9; + const random = (n: number): number => { + state ^= state << 13; + state >>>= 0; + state ^= state >>> 17; + state ^= state << 5; + state >>>= 0; + return state % n; + }; + const disagreements: string[] = []; + for (let i = 0; i < 8000; i++) { + const seed = seeds[random(seeds.length)]!; + const at = 8 + random(Math.max(1, seed.length - 8)); + let bytes: Uint8Array; + switch (random(4)) { + case 0: + bytes = Uint8Array.from(seed); + bytes[at] = bytes[at]! ^ (1 << random(8)); + break; + case 1: + bytes = Uint8Array.from(seed); + bytes[at] = random(256); + break; + case 2: + bytes = new Uint8Array([...seed.subarray(0, at), ...seed.subarray(at + 1)]); + break; + default: + bytes = new Uint8Array([...seed.subarray(0, at), random(256), ...seed.subarray(at)]); + } + const s = analyzeWasm(bytes); + if (s.status === "unsupported") continue; + if (accepted(s.status) !== v8Validate(bytes)) { + disagreements.push( + `${s.status} ${s.error ?? ""}: ${Buffer.from(bytes).toString("base64")}`, + ); + } + } + expect(disagreements).toEqual([]); + }); +}); + +describe("modules inlined by packages in this workspace", () => { + // Lockfile-pinned installs: undici's llhttp (with and without SIMD) and + // es-module-lexer, both inlined as base64 string literals. + const root = join(import.meta.dirname, "../../.."); + const inline = (pattern: string): Uint8Array[] => + globSync(join(root, pattern)) + .sort() + .flatMap((file) => + [...readFileSync(file, "utf8").matchAll(/AGFzbQ[A-Za-z0-9+/=]*/g)].map((m) => + decodeBase64(m[0])!, + ), + ); + + test("undici's llhttp: the scalar module translates, the SIMD one needs SIMD", () => { + const scalar = inline( + "node_modules/.pnpm/undici@7.*/node_modules/undici/lib/llhttp/llhttp-wasm.js", + ); + const simd = inline( + "node_modules/.pnpm/undici@7.*/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js", + ); + expect(scalar.length).toBeGreaterThan(0); + expect(simd.length).toBeGreaterThan(0); + for (const bytes of scalar) { + expect(analyzeWasm(bytes)).toMatchObject({ status: "valid", importModules: ["env"] }); + expect(v8Validate(bytes)).toBe(true); + } + for (const bytes of simd) { + expect(analyzeWasm(bytes)).toMatchObject({ status: "unsupported", unsupported: ["simd"] }); + expect(v8Validate(bytes)).toBe(true); + } + }); + + test("es-module-lexer's module is plain MVP", () => { + const modules = inline( + "node_modules/.pnpm/es-module-lexer@1.*/node_modules/es-module-lexer/dist/lexer.js", + ); + expect(modules.length).toBeGreaterThan(0); + for (const bytes of modules) { + expect(analyzeWasm(bytes)).toMatchObject({ status: "valid", imports: 0 }); + expect(v8Validate(bytes)).toBe(true); + } + }); +}); diff --git a/packages/runtime/src/scr_array.c b/packages/runtime/src/scr_array.c index ef64be56d..4ef24e906 100644 --- a/packages/runtime/src/scr_array.c +++ b/packages/runtime/src/scr_array.c @@ -1179,7 +1179,7 @@ static void scr_arr_destroy(void *object) { #ifdef SCR_RC_AUDIT scr_live_arrays--; #endif - scr_weak_dispose(a); + scr_weak_dispose_inline(a); scr_mem_free(a); } } diff --git a/packages/runtime/src/scr_async.c b/packages/runtime/src/scr_async.c index 48f3a5329..f630ee5f9 100644 --- a/packages/runtime/src/scr_async.c +++ b/packages/runtime/src/scr_async.c @@ -4890,6 +4890,8 @@ struct ScrGen { /* The never-started teardown: drops the packed (already-retained) * arguments the spawn wrapper built. Emitted per generator function. */ void (*drop_args)(void *); + /* scr_gen_set_unstarted_return's hook; NULL for most generators. */ + void (*unstarted_return)(void *); bool is_async; void (*settle_async)(ScrGen *, ScrPromise *); ScrAsyncGenRequest *requests_head; @@ -5449,6 +5451,8 @@ void scr_gen_resume(ScrGen *g) { } } +void scr_gen_set_unstarted_return(ScrGen *g, void (*hook)(void *)) { g->unstarted_return = hook; } + void scr_gen_close(ScrGen *g) { scr_gen_slot_reset(&g->ret); scr_gen_resume_return(g); @@ -5483,13 +5487,16 @@ void scr_gen_resume_return(ScrGen *g) { return; case SCR_GEN_UNSTARTED: /* The body never runs: tear the fiber down cleanly (drop the packed - * arguments) and complete with the parked value. */ + * arguments) and complete with the parked value. The generator is + * done before the hook runs, so a resume from inside it answers done; + * an exception the hook raises stays pending for the caller. */ + g->state = SCR_GEN_DONE; + if (g->unstarted_return != NULL) g->unstarted_return(g->fiber->argpack); if (g->drop_args != NULL) g->drop_args(g->fiber->argpack); else free(g->fiber->argpack); scr_fiber_destroy(g->fiber); g->fiber = NULL; scr_fibers_live--; - g->state = SCR_GEN_DONE; scr_gen_ret_to_out(g); return; default: diff --git a/packages/runtime/src/scr_blob.c b/packages/runtime/src/scr_blob.c index 5c4f9ba68..817a85e2d 100644 --- a/packages/runtime/src/scr_blob.c +++ b/packages/runtime/src/scr_blob.c @@ -44,7 +44,7 @@ static void *scr_blob_retain_v(void *h) { static void scr_blob_release_v(void *h) { ScrBlob *b = h; if (--b->rc) return; - scr_weak_dispose(b); + scr_weak_dispose_inline(b); scr_blob_store_release(b->store); free(b->parts); scr_str_release(b->type); diff --git a/packages/runtime/src/scr_bytes.c b/packages/runtime/src/scr_bytes.c index 28258a29c..d33f32a97 100644 --- a/packages/runtime/src/scr_bytes.c +++ b/packages/runtime/src/scr_bytes.c @@ -296,7 +296,7 @@ ScrBytes *scr_bytes_as_buffer(ScrBytes *bytes) { void scr_bytes_release(ScrBytes *b) { if (!b || b->rc == SIZE_MAX) return; /* NULL: an uninitialized `let` local */ if (--b->rc == 0) { - scr_weak_dispose(b); + scr_weak_dispose_inline(b); if (b->backing) { scr_bytes_release(b->backing); /* a view: data points into the owner */ } else if (b->shared) { diff --git a/packages/runtime/src/scr_dyn.h b/packages/runtime/src/scr_dyn.h index 667ceced0..24f3578c3 100644 --- a/packages/runtime/src/scr_dyn.h +++ b/packages/runtime/src/scr_dyn.h @@ -174,6 +174,17 @@ typedef enum { SCR_DYNH_COUNT, } ScrDynHandleTag; +/* Every per-tag table (scr_dynh_ops in scr_json.c, the message clone hooks + * in scr_message.c) is sized by this fixed capacity, never by + * SCR_DYNH_COUNT. Appending a tag for a link-gated unit therefore changes + * no always-linked storage or code: a program that never boxes the new + * handle links byte-identical objects. Raising the capacity is a + * program-wide layout change; do it in a change of its own, measured as + * neutral, and only when the enum outgrows it. */ +#define SCR_DYNH_CAPACITY 128 +_Static_assert(SCR_DYNH_COUNT <= SCR_DYNH_CAPACITY, + "ScrDynHandleTag outgrew SCR_DYNH_CAPACITY: raise it in its own change"); + typedef struct ScrDyn ScrDyn; typedef struct ScrBytes ScrBytes; /* full definition below (C11 repeat) */ typedef struct ScrClosure ScrClosure; /* full definition below (C11 repeat) */ @@ -1162,7 +1173,25 @@ typedef struct ScrDynHandleOps { * lookup): +1 value, or NULL when the class has no member for `key` * (the read answers undefined). NULL hook = no symbol-keyed members. */ ScrDyn *(*symbol_get)(void *h, const ScrDyn *key); + /* Cross-thread structured clone (postMessage, workerData); NULL = + * DataCloneError. See ScrDynHandleTransfer. */ + const struct ScrDynHandleTransfer *transfer; } ScrDynHandleOps; + +/* How a handle crosses threads, supplied by the handle's owning unit so the + * message encoder (scr_message.c) needs no reference to gated units and no + * per-tag registry. share runs on the sending thread: it answers a payload + * that any thread may use, +1, or NULL when this handle cannot be cloned + * (with an exception pending, or DataCloneError is thrown). adopt runs on + * the receiving thread and answers a fresh box over the payload (+1; the + * message keeps its payload reference). drop releases the payload when the + * message is freed, whether or not it was delivered. All three must be + * callable from any thread. */ +typedef struct ScrDynHandleTransfer { + void *(*share)(void *h); + ScrDyn *(*adopt)(void *payload); + void (*drop)(void *payload); +} ScrDynHandleTransfer; ScrDyn *scr_dyn_native_handle_iterator(ScrDyn *source, unsigned selection); /* ── promises in the checked-dynamic tree (SCR_DYN_PROMISE) ──────────────────────────── diff --git a/packages/runtime/src/scr_events.c b/packages/runtime/src/scr_events.c index 670ea10d6..54eb87a0d 100644 --- a/packages/runtime/src/scr_events.c +++ b/packages/runtime/src/scr_events.c @@ -1061,7 +1061,7 @@ static void scr_stdio_cleanup(void) { scr_stdio_write_hook = NULL; for (int i = 0; i < 3; i++) { ScrStdio *stream = &scr_stdio_streams[i]; - scr_weak_dispose(stream); + scr_weak_dispose_inline(stream); scr_dyn_release(stream->write); stream->write = NULL; scr_dyn_release(stream->write_error); diff --git a/packages/runtime/src/scr_exception.c b/packages/runtime/src/scr_exception.c index fb152e078..3a79cf85b 100644 --- a/packages/runtime/src/scr_exception.c +++ b/packages/runtime/src/scr_exception.c @@ -389,6 +389,17 @@ void scr_exc_suppressed_forget(const void *error_object) { } } +void scr_exc_keep_first(ScrCaught *first) { + if (first->kind == SCR_EXC_GENRET) { + scr_caught_release(first); + return; + } + ScrCaught *dropped = scr_exc_take(); + if (dropped) scr_caught_release(dropped); + scr_rethrow(first); + scr_caught_release(first); +} + void scr_exc_suppress(ScrCaught *suppressed) { if (suppressed->kind == SCR_EXC_GENRET) { /* A generator .return() is a return completion, not a thrown error. diff --git a/packages/runtime/src/scr_exception.h b/packages/runtime/src/scr_exception.h index 80fb98957..3c8261561 100644 --- a/packages/runtime/src/scr_exception.h +++ b/packages/runtime/src/scr_exception.h @@ -84,6 +84,10 @@ typedef struct ScrExcCell { ScrTraceFn trace_fn; ScrStackFrame *stack; /* execution state; never moves with an exception */ } ScrExcCell; +/* Executables push and pop source frames inline (emitter.ts, stack-trace + * mode) at this offset on 64-bit targets. */ +_Static_assert(sizeof(void *) != 8 || offsetof(ScrExcCell, stack) == 56, + "ScrExcCell.stack moved: update the emitter's inline frame push"); /* Runtime-internal (fiber machinery in scr_async.c) — never emitted. */ ScrExcCell *scr_exc_swap_cell(ScrExcCell *cell); /* NULL = main's cell */ @@ -172,6 +176,10 @@ void scr_caught_trace_v(void *c, ScrTraceVisit visit, void *ctx); * when scr_json.c builds its dyn view, and scr_exc_suppressed_forget * releases them. */ void scr_exc_suppress(ScrCaught *suppressed); +/* An iterator close that threw while `first` was propagating: the close's + * error is dropped and `first` is raised again (consumed). A generator + * .return() in flight is replaced by the close's error instead. */ +void scr_exc_keep_first(ScrCaught *first); bool scr_exc_suppressed_values(const void *error_object, const ScrCaught **error, const ScrCaught **suppressed); void scr_exc_suppressed_forget(const void *error_object); diff --git a/packages/runtime/src/scr_fetch.c b/packages/runtime/src/scr_fetch.c index f586b96f8..eff2ae6bc 100644 --- a/packages/runtime/src/scr_fetch.c +++ b/packages/runtime/src/scr_fetch.c @@ -2522,7 +2522,7 @@ static SfResponse *sf_response_retain(SfResponse *r) { static void sf_response_release(SfResponse *r) { if (!r || --r->rc > 0) return; - scr_weak_dispose(r); + scr_weak_dispose_inline(r); sf_stream_release(r->body); sf_headers_release(r->headers); scr_str_release(r->url); @@ -4760,7 +4760,7 @@ static void *sf_request_retain_v(void *ptr) { static void sf_request_release_v(void *ptr) { SfRequest *r = ptr; if (--r->rc) return; - scr_weak_dispose(r); + scr_weak_dispose_inline(r); sf_response_release(r->payload); scr_str_release(r->url); scr_str_release(r->method); scr_str_release(r->redirect); sf_signal_release(r->signal); free(r); diff --git a/packages/runtime/src/scr_generator.h b/packages/runtime/src/scr_generator.h index 2c2c0e953..f0ecb9d85 100644 --- a/packages/runtime/src/scr_generator.h +++ b/packages/runtime/src/scr_generator.h @@ -60,6 +60,9 @@ void scr_gen_coro_finish(ScrFiber *self); ScrGen *scr_async_gen_new(void (*entry)(ScrFiber *, void *), void *argpack, void (*drop_args)(void *), void (*settle)(ScrGen *, ScrPromise *)); +/* Runs when return() reaches the generator before its first resume, with + * the packed arguments still alive: an iterator helper closes its source. */ +void scr_gen_set_unstarted_return(ScrGen *g, void (*hook)(void *)); ScrGen *scr_gen_retain(ScrGen *g); void scr_gen_release(ScrGen *g); /* NULL-tolerant */ void *scr_gen_retain_v(void *g); diff --git a/packages/runtime/src/scr_json.c b/packages/runtime/src/scr_json.c index b23e78241..81da2bc66 100644 --- a/packages/runtime/src/scr_json.c +++ b/packages/runtime/src/scr_json.c @@ -212,6 +212,8 @@ static void scr_jb_dispose(ScrJsonBuf *b) { scr_jb_init(b); } +void scr_jb_abandon(ScrJsonBuf *b) { scr_jb_dispose(b); } + void scr_jb_putc(ScrJsonBuf *b, char c) { scr_jb_grow(b, 1); b->data[b->len++] = c; @@ -3649,7 +3651,7 @@ ScrDyn *scr_dyn_bind(ScrDyn *target, ScrDyn *const *args, size_t argc) { * always-linked core never references gated units. A missing tag at use * is an internal error: emitted programs install a unit's ops whenever * they can box its handles. */ -static SCR_TL const ScrDynHandleOps *scr_dynh_ops[SCR_DYNH_COUNT]; +static SCR_TL const ScrDynHandleOps *scr_dynh_ops[SCR_DYNH_CAPACITY]; /* BroadcastChannel's EventTarget table (scr_et_broadcast_install). */ SCR_TL const ScrEtBroadcastOps *scr_et_broadcast_ops = NULL; @@ -13045,63 +13047,13 @@ double scr_buffer_byte_length_dyn(ScrDyn *value, ScrStr *encoding) { return 0; } -/* Radix digit generation follows V8's DoubleToRadixStringView algorithm. - * Copyright 2012 the V8 project authors. BSD license in - * ../vendor/v8-number-radix/LICENSE. The decimal path retains Ryū. */ +/* toString(radix) with any radix value: undefined means 10, anything else + * converts with ToNumber (which can run program code) first. */ ScrStr *scr_num_to_string_radix(double value, const ScrDyn *argument) { double requested = 10; if (argument && argument->kind != SCR_DYN_UNDEF && !scr_dyn_number_coerce_js(argument, &requested)) return NULL; - requested = isnan(requested) ? 0 : trunc(requested); - if (requested < 2 || requested > 36 || !isfinite(requested)) { - static const char message[] = "toString() radix argument must be between 2 and 36"; - scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1); - return NULL; - } - int radix = (int)requested; - if (radix == 10 || !isfinite(value) || value == 0) return scr_f64_to_scrstr(value); - static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - char buffer[2200]; - const size_t middle = sizeof buffer / 2; - size_t begin = middle, end = middle; - bool negative = value < 0; - value = fabs(value); - double integer = floor(value), fraction = value - integer; - double tolerance = 0.5 * (nextafter(value, INFINITY) - value); - if (tolerance <= 0) tolerance = nextafter(0, INFINITY); - if (fraction >= tolerance) { - buffer[end++] = '.'; - do { - fraction *= radix; - tolerance *= radix; - int digit = (int)fraction; - buffer[end++] = digits[digit]; - fraction -= digit; - if ((fraction > 0.5 || (fraction == 0.5 && (digit & 1))) && fraction + tolerance > 1) { - for (;;) { - end--; - if (end == middle) { integer += 1; break; } - char last = buffer[end]; - digit = last > '9' ? last - 'a' + 10 : last - '0'; - if (digit + 1 < radix) { buffer[end++] = digits[digit + 1]; break; } - } - break; - } - } while (fraction >= tolerance); - } - /* V8's Double::Exponent is the unbiased exponent minus 52. Beyond - * that precision boundary, trailing digits are unrepresented zeros. */ - while (integer / radix >= 0x1p53) { - integer /= radix; - buffer[--begin] = '0'; - } - do { - double remainder = fmod(integer, radix); - buffer[--begin] = digits[(int)remainder]; - integer = (integer - remainder) / radix; - } while (integer > 0); - if (negative) buffer[--begin] = '-'; - return scr_str_new(buffer + begin, end - begin); + return scr_num_to_string_radix_f64(value, requested); } ScrDyn *scr_caught_to_dyn(const ScrCaught *c) { diff --git a/packages/runtime/src/scr_json.h b/packages/runtime/src/scr_json.h index 8a353f40a..e3077703e 100644 --- a/packages/runtime/src/scr_json.h +++ b/packages/runtime/src/scr_json.h @@ -119,6 +119,8 @@ _Static_assert(offsetof(ScrJsonBuf, data) == 0 && offsetof(ScrJsonBuf, len) == s "LLVM backend expects ScrJsonBuf to start with { data, len, cap }"); void scr_jb_init(ScrJsonBuf *b); +/* Release a buffer's text without finishing it (error paths). */ +void scr_jb_abandon(ScrJsonBuf *b); /* Append a borrowed byte span verbatim, including embedded NUL bytes. */ void scr_jb_write(ScrJsonBuf *b, const char *s, size_t n); /* scr_jb_write for text that holds no lone surrogate (fixed text, JSON diff --git a/packages/runtime/src/scr_lib.c b/packages/runtime/src/scr_lib.c index fd51e9c78..bda75a58d 100644 --- a/packages/runtime/src/scr_lib.c +++ b/packages/runtime/src/scr_lib.c @@ -10716,6 +10716,64 @@ ScrStr *scr_num_to_fixed0(double x) { * the receiver's non-finite arm, as ECMA-262 requires. Invalid precision * raises V8's catchable RangeError text; otherwise the result is +1. The * exact-binary-value digits come from scr_f64_to_fixed (scr_number.c). */ +/* Number.prototype.toString(radix) with a number radix, which + * ToIntegerOrInfinity truncates (NaN to 0). Radix digit generation follows + * V8's DoubleToRadixStringView algorithm. Copyright 2012 the V8 project + * authors. BSD license in ../vendor/v8-number-radix/LICENSE. The decimal + * path retains Ryū. */ +ScrStr *scr_num_to_string_radix_f64(double value, double requested) { + requested = isnan(requested) ? 0 : trunc(requested); + if (requested < 2 || requested > 36 || !isfinite(requested)) { + static const char message[] = "toString() radix argument must be between 2 and 36"; + scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1); + return NULL; + } + int radix = (int)requested; + if (radix == 10 || !isfinite(value) || value == 0) return scr_f64_to_scrstr(value); + static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + char buffer[2200]; + const size_t middle = sizeof buffer / 2; + size_t begin = middle, end = middle; + bool negative = value < 0; + value = fabs(value); + double integer = floor(value), fraction = value - integer; + double tolerance = 0.5 * (nextafter(value, INFINITY) - value); + if (tolerance <= 0) tolerance = nextafter(0, INFINITY); + if (fraction >= tolerance) { + buffer[end++] = '.'; + do { + fraction *= radix; + tolerance *= radix; + int digit = (int)fraction; + buffer[end++] = digits[digit]; + fraction -= digit; + if ((fraction > 0.5 || (fraction == 0.5 && (digit & 1))) && fraction + tolerance > 1) { + for (;;) { + end--; + if (end == middle) { integer += 1; break; } + char last = buffer[end]; + digit = last > '9' ? last - 'a' + 10 : last - '0'; + if (digit + 1 < radix) { buffer[end++] = digits[digit + 1]; break; } + } + break; + } + } while (fraction >= tolerance); + } + /* V8's Double::Exponent is the unbiased exponent minus 52. Beyond + * that precision boundary, trailing digits are unrepresented zeros. */ + while (integer / radix >= 0x1p53) { + integer /= radix; + buffer[--begin] = '0'; + } + do { + double remainder = fmod(integer, radix); + buffer[--begin] = digits[(int)remainder]; + integer = (integer - remainder) / radix; + } while (integer > 0); + if (negative) buffer[--begin] = '-'; + return scr_str_new(buffer + begin, end - begin); +} + ScrStr *scr_num_to_fixed(double x, double fraction_digits) { double fd = isnan(fraction_digits) ? 0 : trunc(fraction_digits); if (!(fd >= 0 && fd <= 100)) { diff --git a/packages/runtime/src/scr_map.c b/packages/runtime/src/scr_map.c index 14181968c..28922296e 100644 --- a/packages/runtime/src/scr_map.c +++ b/packages/runtime/src/scr_map.c @@ -697,7 +697,7 @@ static void scr_map_trace(void *o, ScrTraceVisit visit, void *ctx) { static void scr_map_gcfree(void *o) { ScrMap *m = (ScrMap *)o; bool keys = m->traced & SCR_MAP_TRACED_KEY, vals = m->traced & SCR_MAP_TRACED_VAL; - scr_weak_dispose(m); + scr_weak_dispose_inline(m); for (size_t e = 0; e < m->nentries; e++) { if (!m->entries[e].hash) continue; if (!keys) scr_map_release_key(m, m->entries[e].key); @@ -752,7 +752,7 @@ ScrMap *scr_map_retain(ScrMap *m) { static void scr_map_destroy(void *object) { ScrMap *m = object; - scr_weak_dispose(m); + scr_weak_dispose_inline(m); for (size_t e = 0; e < m->nentries; e++) { if (!m->entries[e].hash) continue; scr_map_release_key(m, m->entries[e].key); diff --git a/packages/runtime/src/scr_message.c b/packages/runtime/src/scr_message.c index 82428a6fe..7c969a2e3 100644 --- a/packages/runtime/src/scr_message.c +++ b/packages/runtime/src/scr_message.c @@ -23,6 +23,8 @@ typedef enum { SCR_MESSAGE_TYPED_REF, /* A transferred MessagePort: its channel end (+1), the side in number. */ SCR_MESSAGE_PORT, + /* A native handle cloned through its unit's ScrDynHandleTransfer. */ + SCR_MESSAGE_HANDLE, } ScrMessageKind; const ScrMessagePortOps *scr_message_port_ops = NULL; @@ -49,6 +51,9 @@ typedef struct { bool data_view; ScrDyn *published; /* SCR_MESSAGE_PUBLISHED: immortal root, owns nothing */ ScrChannel *channel; /* SCR_MESSAGE_PORT */ + /* SCR_MESSAGE_HANDLE: the owning unit's hooks and its payload (+1). */ + const ScrDynHandleTransfer *transfer; + void *payload; /* SCR_MESSAGE_TYPED_REF: the capsule's process-wide adapters and type key * (vtables, adapters and type keys are shared by every thread). */ struct { @@ -389,7 +394,20 @@ static size_t scr_message_value(ScrMessageEncoder *encoder, const ScrDyn *input) break; } bool buffer = scr_buffer_storage_is(value); - if (value->kind == SCR_DYN_HANDLE && !buffer) goto unsupported; + if (value->kind == SCR_DYN_HANDLE && !buffer) { + const ScrDynHandleTransfer *transfer = scr_dyn_handle_ops_of(value)->transfer; + if (!transfer) goto unsupported; + void *payload = transfer->share(value->v.handle.ptr); + if (!payload) { + if (scr_exc_pending()) return SIZE_MAX; + goto unsupported; + } + node = &encoder->message->nodes[id]; + node->kind = SCR_MESSAGE_HANDLE; + node->transfer = transfer; + node->payload = payload; + break; + } const ScrBytes *bytes = buffer ? value->v.handle.ptr : value->v.bytes; size_t storage = scr_message_storage(encoder, bytes); /* Adding the storage node can reallocate the node array. */ @@ -765,6 +783,7 @@ ScrDyn *scr_message_decode(const ScrMessage *message) { case SCR_MESSAGE_PORT: values[i] = scr_message_port_ops->adopt(node->channel, (int)node->number); break; + case SCR_MESSAGE_HANDLE: values[i] = node->transfer->adopt(node->payload); break; } if (!values[i] || scr_exc_pending()) goto done; } @@ -820,6 +839,7 @@ void scr_message_free(ScrMessage *message) { free(node->data); scr_shared_release(node->shared); if (node->kind == SCR_MESSAGE_PORT) scr_message_port_ops->release(node->channel); + if (node->kind == SCR_MESSAGE_HANDLE) node->transfer->drop(node->payload); } free(message->nodes); free(message); diff --git a/packages/runtime/src/scr_message.test.c b/packages/runtime/src/scr_message.test.c index 4e8aa7d62..0c6bd7ae3 100644 --- a/packages/runtime/src/scr_message.test.c +++ b/packages/runtime/src/scr_message.test.c @@ -172,6 +172,115 @@ static void check_documents(void) { scr_message_free(message); } +/* A link-gated unit's handle crosses threads through the transfer hooks in + * its ops: share on the sender, adopt on the receiver, drop with the + * message. The test borrows the last capacity slot, which no unit uses, so + * it also proves that slots past SCR_DYNH_COUNT work. */ +#define TRANSFER_TAG ((ScrDynHandleTag)(SCR_DYNH_CAPACITY - 1)) +typedef struct { + _Atomic size_t rc; + int value; +} TransferBox; +static _Atomic int transfer_shares, transfer_adopts, transfer_drops; +static void *transfer_retain(void *h) { + ((TransferBox *)h)->rc++; + return h; +} +static void transfer_release(void *h) { + if (--((TransferBox *)h)->rc == 0) free(h); +} +static void *transfer_share(void *h) { + TransferBox *source = h; + if (source->value < 0) return NULL; + transfer_shares++; + TransferBox *copy = malloc(sizeof *copy); + copy->rc = 1; + copy->value = source->value; + return copy; +} +static ScrDyn *transfer_adopt(void *payload) { + transfer_adopts++; + return scr_dyn_new_handle(payload, TRANSFER_TAG); +} +static void transfer_drop(void *payload) { + transfer_drops++; + transfer_release(payload); +} +static const ScrDynHandleTransfer transfer_hooks = {transfer_share, transfer_adopt, transfer_drop}; +static const ScrDynHandleOps transfer_ops = { + .cls = "Transferable", + .retain = transfer_retain, + .release = transfer_release, + .transfer = &transfer_hooks, +}; +static const ScrDynHandleOps opaque_ops = { + .cls = "Opaque", + .retain = transfer_retain, + .release = transfer_release, +}; + +static void *receive_handles(void *data) { + scr_context_enter(1); + scr_init(); + scr_lib_init(0, NULL); + scr_dyn_handle_install(TRANSFER_TAG, &transfer_ops); + ScrDyn *root = scr_message_decode(data); + assert(root && !scr_exc_pending()); + ScrDyn *first = scr_dyn_obj_get(root, "first", 5); + assert(first->kind == SCR_DYN_HANDLE && first->v.handle.tag == TRANSFER_TAG); + assert(((TransferBox *)first->v.handle.ptr)->value == 7); + /* One handle reached twice decodes to one box. */ + assert(first == scr_dyn_obj_get(root, "again", 5)); + assert(transfer_adopts == 1); + scr_dyn_release(root); + scr_collect_cycles(); + scr_context_cleanup(); + return NULL; +} + +static ScrDyn *transfer_handle(int value, const ScrDynHandleOps *ops) { + scr_dyn_handle_install(TRANSFER_TAG, ops); + TransferBox *box = malloc(sizeof *box); + box->rc = 1; + box->value = value; + ScrDyn *handle = scr_dyn_new_handle(box, TRANSFER_TAG); + transfer_release(box); + return handle; +} + +static void check_handle_transfer(void) { + ScrDyn *root = scr_dyn_new_obj(); + ScrDyn *handle = transfer_handle(7, &transfer_ops); + scr_dyn_obj_set(root, "first", 5, scr_dyn_retain(handle)); + scr_dyn_obj_set(root, "again", 5, handle); + ScrMessage *message = scr_message_encode(root); + assert(message && !scr_exc_pending()); + assert(transfer_shares == 1); + scr_dyn_release(root); + pthread_t receiver; + assert(pthread_create(&receiver, NULL, receive_handles, message) == 0); + assert(pthread_join(receiver, NULL) == 0); + assert(transfer_drops == 0); + scr_message_free(message); + assert(transfer_drops == 1); + + /* A handle whose unit declines (share answers NULL) and a handle with no + * transfer hooks both throw DataCloneError, releasing what was shared. */ + root = scr_dyn_new_arr(); + scr_dyn_arr_push(root, transfer_handle(1, &transfer_ops)); + scr_dyn_arr_push(root, transfer_handle(-1, &transfer_ops)); + assert(!scr_message_encode(root) && scr_exc_pending()); + scr_exc_clear(); + assert(transfer_shares == 2 && transfer_drops == 2); + scr_dyn_release(root); + root = transfer_handle(3, &opaque_ops); + assert(!scr_message_encode(root) && scr_exc_pending()); + scr_exc_clear(); + assert(transfer_shares == 2); + scr_dyn_release(root); + scr_collect_cycles(); +} + int main(void) { scr_init(); scr_lib_init(0, NULL); @@ -188,6 +297,8 @@ int main(void) { check_getters(); check_rejection(); check_documents(); + check_handle_transfer(); scr_context_cleanup(); puts("message graphs preserve identity, sparse values, byte aliases and getter order"); + puts("native handles cross threads through their transfer hooks"); } diff --git a/packages/runtime/src/scr_message.test.ts b/packages/runtime/src/scr_message.test.ts index b2364a5d8..56b35f1ac 100644 --- a/packages/runtime/src/scr_message.test.ts +++ b/packages/runtime/src/scr_message.test.ts @@ -34,7 +34,8 @@ test.skipIf(process.platform === "win32")( env: { ...process.env, UBSAN_OPTIONS: "halt_on_error=1" }, }); expect(result.stdout).toBe( - "message graphs preserve identity, sparse values, byte aliases and getter order\n", + "message graphs preserve identity, sparse values, byte aliases and getter order\n" + + "native handles cross threads through their transfer hooks\n", ); expect(result.stderr).toBe(""); } finally { diff --git a/packages/runtime/src/scr_number.h b/packages/runtime/src/scr_number.h index 84db27075..f980daeb5 100644 --- a/packages/runtime/src/scr_number.h +++ b/packages/runtime/src/scr_number.h @@ -73,6 +73,7 @@ bool scr_num_is_safe_integer(double x); ScrStr *scr_num_to_exponential(double x); ScrStr *scr_num_to_fixed0(double x); ScrStr *scr_num_to_fixed(double x, double fraction_digits); +ScrStr *scr_num_to_string_radix_f64(double value, double radix); /* Object.is over two numbers — the spec's SameValue on doubles: NaN * equals NaN, +0 differs from -0, everything else is ==. Never throws. */ diff --git a/packages/runtime/src/scr_rc.h b/packages/runtime/src/scr_rc.h index d6e1f8e88..ad9babd9e 100644 --- a/packages/runtime/src/scr_rc.h +++ b/packages/runtime/src/scr_rc.h @@ -423,8 +423,15 @@ static inline void *scr_cyc_alloc_inline(size_t size, ScrCycType *type) { scr_cyc_live++; return h + 1; } -static inline void scr_cyc_free_inline(void *obj) { +/* scr_weak_dispose's NULL test inline, for the runtime's hot frees: the + * hook stays NULL unless the program creates a weak collection or keeps a + * checked record's source, so the free costs one predictable branch, not a + * call. */ +static inline void scr_weak_dispose_inline(void *obj) { if (scr_weak_dispose_hook) scr_weak_dispose_hook(obj); +} +static inline void scr_cyc_free_inline(void *obj) { + scr_weak_dispose_inline(obj); scr_cyc_live--; if (scr_cyc_gen(scr_cyc_hdr(obj)) == SCR_CYC_OLD) scr_cyc_old_freed++; scr_mem_free(scr_cyc_hdr(obj)); diff --git a/packages/runtime/src/scr_regex.c b/packages/runtime/src/scr_regex.c index b24261a4d..a2e591b0e 100644 --- a/packages/runtime/src/scr_regex.c +++ b/packages/runtime/src/scr_regex.c @@ -1358,7 +1358,129 @@ ScrStr *scr_regex_replace_callback(ScrStr *s, ScrRegex *re, ScrDyn *callback, bo for (size_t i = 0; i < count; i++) scr_dyn_release(matches[i].arguments); free(matches); if (scr_exc_pending()) { - free(output.data); + scr_jb_abandon(&output); + scr_regex_input_dispose(&input); + return NULL; + } + scr_regex_put_span(&output, &input, next, len); + scr_regex_input_dispose(&input); + return scr_jb_finish(&output); +} + +/* One call of a typed replacer (scr_regex_replace_fn's contract): string + * arguments are passed +1 (the closure ABI's owned parameters), the offset + * as a number, and the result is the closure's +1 string. */ +static ScrStr *scr_regex_call_replacer(ScrClosure *f, uint32_t arity, int ncap, + ScrStr *const *caps, double offset, ScrStr *subject) { + void *p[4] = { NULL, NULL, NULL, NULL }; + for (uint32_t i = 0; i < arity && i < 4; i++) { + if ((int)i < ncap) { + if (!caps[i]) scr_trap("scriptc: internal error: typed replacer capture is unset\n"); + p[i] = scr_str_retain(caps[i]); + } else if ((int)i == ncap + 1) { + p[i] = scr_str_retain(subject); + } + } + void *fn = f->fn; + typedef ScrStr *R; + switch (arity) { + case 0: return ((R (*)(ScrClosure *))fn)(f); + case 1: return ((R (*)(ScrClosure *, void *))fn)(f, p[0]); + case 2: + if (ncap == 1) return ((R (*)(ScrClosure *, void *, double))fn)(f, p[0], offset); + return ((R (*)(ScrClosure *, void *, void *))fn)(f, p[0], p[1]); + case 3: + if (ncap == 1) return ((R (*)(ScrClosure *, void *, double, void *))fn)(f, p[0], offset, p[2]); + if (ncap == 2) return ((R (*)(ScrClosure *, void *, void *, double))fn)(f, p[0], p[1], offset); + return ((R (*)(ScrClosure *, void *, void *, void *))fn)(f, p[0], p[1], p[2]); + case 4: + if (ncap == 2) + return ((R (*)(ScrClosure *, void *, void *, double, void *))fn)(f, p[0], p[1], offset, p[3]); + if (ncap == 3) + return ((R (*)(ScrClosure *, void *, void *, void *, double))fn)(f, p[0], p[1], p[2], offset); + if (ncap >= 4) + return ((R (*)(ScrClosure *, void *, void *, void *, void *))fn)(f, p[0], p[1], p[2], p[3]); + break; + default: break; + } + scr_trap("scriptc: internal error: typed replacer signature\n"); +} + +/* scr_regex_replace_callback's algorithm for a typed replacer: the matches + * are collected first, keeping only the captures the replacer reads, then + * the replacer runs once per match in order. */ +ScrStr *scr_regex_replace_fn(ScrStr *s, ScrRegex *re, ScrClosure *f, uint32_t arity, bool all) { + uint8_t *bc = scr_regex_bc(re); + int flags = lre_get_flags(bc); + bool global = (flags & LRE_FLAG_GLOBAL) != 0; + if (all && !global) { + static const char message[] = "String.prototype.replaceAll called with a non-global RegExp argument"; + scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1); + return NULL; + } + bool sticky = (flags & LRE_FLAG_STICKY) != 0; + bool unicode = (flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0; + int capture_count = lre_get_capture_count(bc); + size_t keep = arity < (uint32_t)capture_count ? arity : (size_t)capture_count; + ScrRegexInput input; + scr_regex_input_init(&input, re, bc, s); + int len = input.len; + struct { int start, end; } *matches = NULL; + ScrStr **caps = NULL; + size_t count = 0, capacity = 0; + if (global) re->last_index = 0; + int position = sticky ? scr_regex_start(re, len) : 0; + if (position < 0) position = len + 1; + if (sticky && !global) re->last_index = 0; + while (position <= len && scr_exec(&input, bc, position) == 1) { + uint8_t **capture = input.capture; + int start = scr_capture_index(&input, capture[0]); + int end = scr_capture_index(&input, capture[1]); + if (sticky && !global) re->last_index = end; + if (count == capacity) { + size_t next = capacity ? capacity * 2 : 8; + if (next < capacity || next > SIZE_MAX / sizeof(*matches) / (keep + 1)) scr_regex_oom(); + void *grown = realloc(matches, next * sizeof(*matches)); + if (!grown) scr_regex_oom(); + matches = grown; + if (keep) { + grown = realloc(caps, next * keep * sizeof(*caps)); + if (!grown) scr_regex_oom(); + caps = grown; + } + capacity = next; + } + for (size_t group = 0; group < keep; group++) { + const uint8_t *cs = capture[group * 2], *ce = capture[group * 2 + 1]; + caps[count * keep + group] = + cs && ce ? scr_regex_span(&input, scr_capture_index(&input, cs), scr_capture_index(&input, ce)) + : NULL; + } + matches[count].start = start; + matches[count].end = end; + count++; + if (!global) break; + position = start == end ? scr_advance(&input, end, unicode) : end; + } + ScrJsonBuf output; + scr_jb_init(&output); + int next = 0; + scr_dyn_this_push_dyn(NULL); + for (size_t i = 0; i < count; i++) { + ScrStr *replacement = scr_regex_call_replacer(f, arity, capture_count, caps + i * keep, + (double)matches[i].start, s); + if (scr_exc_pending()) break; + scr_regex_put_span(&output, &input, next, matches[i].start); + scr_jb_put_str(&output, replacement); + scr_str_release(replacement); + next = matches[i].end; + } + scr_dyn_this_pop(); + for (size_t i = 0; i < count * keep; i++) scr_str_release(caps[i]); + free(caps); + free(matches); + if (scr_exc_pending()) { + scr_jb_abandon(&output); scr_regex_input_dispose(&input); return NULL; } diff --git a/packages/runtime/src/scr_regex.h b/packages/runtime/src/scr_regex.h index e34e877de..014e5aa83 100644 --- a/packages/runtime/src/scr_regex.h +++ b/packages/runtime/src/scr_regex.h @@ -80,6 +80,16 @@ ScrStr *scr_regex_flags(ScrRegex *re); /* +1 */ ScrStr *scr_regex_to_string(ScrRegex *re); /* +1 */ /* replace: first match without /g, every match with it. */ ScrStr *scr_regex_replace(ScrStr *s, ScrRegex *re, ScrStr *rep); +/* replace/replaceAll with a typed replacer closure of `arity` (at most 4) + * parameters returning a string. Parameter i receives what Node passes at + * position i: the match and captures (strings) below the capture count n, + * the match offset (a number) at n, the subject (a string) at n + 1. The + * compiler admits a closure only when every position it declares is one of + * those with the declared kind, and every capture it reads is set in every + * match (scr_regex_replace_callback handles the rest). Borrows all. */ +struct ScrClosure; +ScrStr *scr_regex_replace_fn(ScrStr *s, ScrRegex *re, struct ScrClosure *f, uint32_t arity, + bool all); /* replaceAll: throws Node's TypeError when /g is missing (may-throw). */ ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep); /* split: captured substrings are interleaved with the split pieces; diff --git a/tests/corpus/5908-iterator-helper-objects.ts b/tests/corpus/5908-iterator-helper-objects.ts new file mode 100644 index 000000000..5e57b9ddf --- /dev/null +++ b/tests/corpus/5908-iterator-helper-objects.ts @@ -0,0 +1,214 @@ +// Iterator helpers over generators, stored array iterators and Map/Set +// iterators: chains that end in a consuming method, helper objects driven +// by next(), for...of, spreads, Array.from and yield*, and the points at +// which a helper closes its source (runs its return()). +const log: string[] = []; +function* count(label: string, n: number): Generator { + try { + for (let i = 1; i <= n; i++) { + log.push(`${label}${i}`); + yield i; + } + } finally { + log.push(`${label}:closed`); + } +} +function flush(what: unknown): void { + console.log(what, "|", log.join(" ")); + log.length = 0; +} + +// Consuming methods over generator chains. +flush(count("a", 5).map((x) => x * 10).filter((x) => x !== 20).toArray()); +flush(count("b", 4).reduce((acc, x) => acc + x)); +flush(count("c", 4).reduce((acc, x, i) => acc + x * i, 100)); +flush(count("d", 5).some((x) => x === 2)); +flush(count("e", 5).every((x) => x < 3)); +flush(count("f", 5).find((x) => x > 3) ?? -1); +flush(count("g", 2).find((x) => x > 3) ?? -1); +let each = ""; +count("h", 3).forEach((x, i) => { + each += `${x}@${i} `; +}); +flush(each.trim()); + +// take, drop and their budgets. +flush(count("i", 9).drop(2).take(3).toArray()); +flush(count("j", 3).take(Infinity).toArray()); +flush([count("k", 4).take(2.9).toArray(), count("l", 4).drop(1.5).toArray()]); +for (const budget of [-1, NaN, -0.5]) { + try { + console.log(count("m", 1).take(budget).toArray()); + } catch (e) { + console.log((e as Error).name, (e as Error).message); + } +} +try { + count("n", 0).reduce((a, b) => a + b); +} catch (e) { + console.log((e as Error).name, (e as Error).message); +} +flush("budgets"); + +// An invalid budget closes a started source before the RangeError. +const invalid = count("bad", 3); +invalid.next(); +try { + invalid.take(-1); +} catch (e) { + log.push((e as Error).message); +} +flush(invalid.next().done); + +// A started source closes through take(0) without another pull. +const started = count("o", 3); +started.next(); +flush([started.take(0).toArray(), started.next().done]); + +// Helper objects step lazily, one source value per delivered value. +const h = count("p", 4) + .map((x) => x * 2) + .filter((x) => x !== 4); +log.push("made"); +console.log(h.next(), h.next()); +console.log(h.next(), h.next()); +flush("next"); +const words = count("q", 3).map((x, i) => "w".repeat(x) + i); +flush([...words]); +flush(Array.from(count("r", 3).drop(1))); +function* wrap(): Generator { + yield 0; + yield* count("s", 2).map((x) => -x); + yield 9; +} +flush([...wrap()]); +function sum(it: Iterator): number { + let total = 0; + for (let r = it.next(); !r.done; r = it.next()) total += r.value; + return total; +} +flush(sum(count("t", 4).filter((x) => x % 2 === 0))); + +// next() from inside the helper's own callback. +const self: IteratorObject = count("re", 2).map((x) => { + if (x === 2) { + try { + self.next(); + } catch (e) { + log.push(`${(e as Error).name}: ${(e as Error).message}`); + } + } + return x; +}); +flush(self.toArray()); + +// Leaving a for...of over a helper closes the helper and its source. +for (const x of count("u", 9).map((v) => v * v)) { + if (x > 4) break; + log.push(`got${x}`); +} +flush("break"); +try { + count("v", 3).forEach((x) => { + if (x === 2) throw new Error("callback threw"); + }); +} catch (e) { + log.push((e as Error).message); +} +flush("throw"); +function* failing(): Generator { + try { + yield 1; + throw new Error("source threw"); + } finally { + log.push("failing:finally"); + } +} +try { + failing().map((x) => x).toArray(); +} catch (e) { + log.push((e as Error).message); +} +flush("source"); +// When closing the source throws while another error propagates, the +// first error is the one that reaches the caller. +function* closeThrows(): Generator { + try { + yield 1; + } finally { + log.push("closeThrows:finally"); + throw new Error("close threw"); + } +} +try { + closeThrows() + .map((x): number => { + if (x > 0) throw new Error("callback threw"); + return x; + }) + .toArray(); +} catch (e) { + log.push((e as Error).message); +} +try { + for (const x of closeThrows().filter(() => true)) throw new Error(`body threw at ${x}`); +} catch (e) { + log.push((e as Error).message); +} +try { + for (const x of closeThrows()) throw new Error(`plain loop threw at ${x}`); +} catch (e) { + log.push((e as Error).message); +} +flush("close errors"); + +// flatMap over arrays and generators; take stops mid-way through an inner +// generator and closes it before the outer source. +flush(count("w", 2).flatMap((x) => [x, -x]).toArray()); +flush(count("x", 3).flatMap((x) => count(`y${x}-`, 2)).take(3).toArray()); + +// Map and Set iterators, observed live. +const set = new Set([1, 2, 3]); +console.log( + set + .values() + .map((x) => { + if (x === 1) set.add(4); + if (x === 2) set.delete(3); + return x * 100; + }) + .toArray(), +); +const map = new Map([ + ["a", 1], + ["b", 2], + ["c", 3], +]); +const pairs = map.entries().filter(([, v]) => v !== 2); +map.set("d", 4); +console.log([...pairs].map(([k, v]) => k + v).join(",")); +console.log(map.keys().map((k) => k.toUpperCase()).toArray(), map.values().reduce((a, b) => a + b, 0)); +console.log(set.keys().some((x) => x > 3), set.entries().find(([k]) => k === 2)?.[1]); + +// Array iterators as helper sources. +const nums = [5, 6, 7]; +const doubled = nums.values().map((x) => x * 2); +nums.push(8); +console.log([...doubled], nums.keys().filter((i) => i > 0).toArray(), [...nums.entries().drop(2)]); + +// Records and strings flow through the stages by reference. +interface Item { + name: string; + qty: number; +} +const items: Item[] = [ + { name: "pen", qty: 3 }, + { name: "ink", qty: 0 }, + { name: "pad", qty: 7 }, +]; +function* stock(): Generator { + yield* items; +} +const inStock = stock().filter((it) => it.qty > 0); +console.log(inStock.next().value === items[0], stock().find((it) => it.name === "pad")?.qty); +console.log(stock().map((it) => `${it.name}x${it.qty}`).toArray().join(" ")); diff --git a/tests/corpus/5909-iterator-helper-objects-js.js b/tests/corpus/5909-iterator-helper-objects-js.js new file mode 100644 index 000000000..759cc2321 --- /dev/null +++ b/tests/corpus/5909-iterator-helper-objects-js.js @@ -0,0 +1,58 @@ +// Iterator helper objects in JavaScript: inferred callback parameters, +// return() on a helper (before its first next(), mid-way and after +// completion), and chains over Map/Set iterators. +const log = []; +function* count(label, n) { + try { + for (let i = 1; i <= n; i++) { + log.push(label + i); + yield i; + } + } finally { + log.push(label + ":closed"); + } +} +function flush(what) { + console.log(what, "|", log.join(" ")); + log.length = 0; +} + +flush(count("a", 4).map((x) => x + 0.5).toArray()); +flush(count("b", 6).filter((x) => x % 2 === 1).map((x, i) => x * 10 + i).take(2).toArray()); +flush(count("c", 3).reduce((acc, x) => acc + x, "")); + +// return() before the first next() closes a source that has started. +const started = count("d", 3); +started.next(); +const mapped = started.map((x) => x * 2); +flush([mapped.return(), started.next()]); +// ... and leaves an unstarted source without running its body. +const fresh = count("e", 3); +const filtered = fresh.filter(() => true); +flush([filtered.return(), fresh.next(), filtered.next()]); +// return() at a yield closes the source; later calls report done. +const stepping = count("f", 5).take(4); +flush([stepping.next(), stepping.return(), stepping.next(), stepping.return()]); +// A chain of helpers closes through to the source. +const chained = count("g", 5); +chained.next(); +const chain = chained.map((x) => x).filter(() => true).take(3); +flush([chain.return(), chained.next()]); + +// Map and Set iterators. +const scores = new Map([ + ["ann", 3], + ["bob", 9], + ["cy", 5], +]); +console.log(scores.entries().filter(([, v]) => v > 4).map(([k]) => k).toArray()); +console.log(scores.values().every((v) => v > 2), scores.keys().find((k) => k.length === 2)); +const tags = new Set(["x", "y", "z"]); +const upper = tags.values().map((t) => t.toUpperCase()); +tags.add("w"); +console.log([...upper], tags.keys().drop(3).toArray()); +for (const t of tags.values().flatMap((t) => [t, t + t])) { + if (t === "yy") break; + log.push(t); +} +flush("flat"); diff --git a/tests/corpus/5997-frame-records-in-record-unions.ts b/tests/corpus/5997-frame-records-in-record-unions.ts new file mode 100644 index 000000000..c066c3edb --- /dev/null +++ b/tests/corpus/5997-frame-records-in-record-unions.ts @@ -0,0 +1,88 @@ +// Records that are arms of a union of records and also live in frame +// storage. An arm of such a union carries a hidden shape word before its +// fields, so every field address has to skip it: the reference fields a +// frame record owns are read, overwritten and released through the same +// slots as heap records of the shape. The same shapes also flow through +// the union, are compared by identity and are serialized. +interface Ident { + kind: "ident"; + name: string; + tags: string[]; +} +interface Call { + kind: "call"; + callee: string; + args: Ident[]; +} +type Node = Ident | Call; + +const words = ["alpha", "beta", "gamma", "delta", "epsilon"]; +function word(i: number): string { + return words[i % words.length]! + i; +} + +function describe(node: Node): string { + switch (node.kind) { + case "ident": + return `${node.name}[${node.tags.join(",")}]`; + case "call": + return `${node.callee}(${node.args.map((a) => a.name).join(", ")})`; + } +} +function weight(node: Node): number { + return node.kind === "ident" ? node.name.length + node.tags.length : node.args.length * 10; +} + +// Heap values of the union: the arms are tagged shapes. +const nodes: Node[] = []; +for (let i = 0; i < 6; i++) { + const id: Ident = { kind: "ident", name: word(i), tags: [word(i + 1)] }; + nodes.push(i % 2 === 0 ? id : { kind: "call", callee: word(i + 2), args: [id, id] }); +} +console.log(nodes.map(describe).join(" | ")); + +// Frame records of the arms that only flow into field reads. +let total = 0; +let log = ""; +for (let i = 0; i < 10; i++) { + const w = word(i); + const id: Ident = { kind: "ident", name: w + "!", tags: [w, word(i + 3)] }; + total += id.name.length + id.tags.length + id.tags[1]!.length; + const call: Call = { kind: "call", callee: w.toUpperCase(), args: [] }; + total += call.callee.length + call.args.length; + log += id.kind[0]! + call.kind[0]! + id.name[0]!; +} +console.log(total, log); + +// A reassigned frame binding: each new value is built apart and copied over +// the slot, and the replaced reference fields are released. +let cur: Ident = { kind: "ident", name: word(0), tags: [] }; +for (let i = 1; i < 8; i++) { + cur = { kind: "ident", name: cur.name.slice(0, 3) + word(i), tags: [...cur.tags, cur.name] }; + if (i % 3 === 0) cur = { kind: "ident", name: cur.tags[0] ?? "none", tags: cur.tags.slice(1) }; +} +console.log(cur.name, cur.tags.length, cur.tags.join("+")); + +// Field writes into a frame record's reference slots. +for (let i = 0; i < 4; i++) { + const id: Ident = { kind: "ident", name: word(i), tags: [word(i)] }; + id.name = id.name + "/" + i; + id.tags = [id.name, ...id.tags]; + id.tags.push(word(i + 7)); + console.log(id.name, id.tags.join(" ")); +} + +// Through the union: describe and weigh by union, keep identity, and +// serialize the arms and the union values. +const a: Ident = { kind: "ident", name: "x", tags: ["t1", "t2"] }; +const b: Call = { kind: "call", callee: "f", args: [a] }; +const asNode: Node = a; +const picked: Node = weight(b) > weight(a) ? b : a; +console.log(describe(asNode), describe(b), weight(asNode), weight(picked)); +console.log(asNode === a, picked === b, b.args[0] === a, (picked as Call).args[0] === asNode); +a.tags.push("t3"); +console.log(describe(asNode), describe(picked)); +console.log(JSON.stringify(a), JSON.stringify(picked)); +console.log(JSON.stringify(nodes.slice(0, 2))); +const mixed: Node[] = [a, b, nodes[1]!]; +console.log(mixed.filter((n) => n.kind === "ident").length, mixed.indexOf(asNode), mixed.indexOf(b)); diff --git a/tests/corpus/6051-generic-class-factory-results.ts b/tests/corpus/6051-generic-class-factory-results.ts new file mode 100644 index 000000000..542619946 --- /dev/null +++ b/tests/corpus/6051-generic-class-factory-results.ts @@ -0,0 +1,111 @@ +// Classes extending the result of a generic class factory, and the +// factory's class values and instances: each instantiation of the factory +// has its own class, as each call does in Node. +function base(initial: T) { + return class { + value: T = initial; + read(): T { + return this.value; + } + describe(): string { + return `value=${String(this.value)}`; + } + }; +} + +class Counter extends base(42) { + bump(): number { + this.value += 1; + return this.value; + } +} +const counter = new Counter(); +console.log(counter.value, counter.bump(), counter.read(), counter.describe()); + +class Label extends base("hello") { + shout(): string { + return this.read().toUpperCase(); + } + describe(): string { + return `label ${super.describe()}`; + } +} +const label = new Label(); +console.log(label.shout(), label.describe(), label.value.length); + +const NumberBox = base(7); +const box = new NumberBox(); +console.log(box.read() * 2, box instanceof NumberBox, counter instanceof NumberBox); +console.log(base(1) === base(1), typeof NumberBox); +console.log(Counter.name, Label.name, counter instanceof Counter); + +function pair(first: A, second: B) { + return class { + first: A = first; + second: B = second; + swap(): [B, A] { + return [this.second, this.first]; + } + }; +} +class Entry extends pair("id", 3) { + label: string; + constructor(label: string) { + super(); + this.label = label; + } + render(): string { + const [n, s] = this.swap(); + return `${this.label}:${s}:${n * 10}`; + } +} +console.log(new Entry("row").render(), new Entry("col").first); + +interface Shape { + name: string; + size: number; +} +function model(defaults: S) { + return class { + data: S; + constructor(data?: S) { + this.data = data ?? defaults; + } + get(): S { + return this.data; + } + }; +} +class ShapeModel extends model({ name: "square", size: 2 }) { + area(): number { + return this.data.size * this.data.size; + } +} +const square = new ShapeModel(); +const big = new ShapeModel({ name: "big", size: 5 }); +console.log(square.get().name, square.area(), big.get().name, big.area()); + +function tagged(tag: string, payload: T) { + class Tagged { + tag = tag; + payload = payload; + toString(): string { + return `${this.tag}(${String(this.payload)})`; + } + } + return new Tagged(); +} +const first = tagged("a", 1); +const second = tagged("b", true); +console.log(first.toString(), second.toString(), first.payload + 1, second.payload === true); + +const arrowFactory = (initial: T) => + class { + item: T = initial; + }; +class FromArrow extends arrowFactory("arrow") {} +function wrap(value: U): U { + const Made = base(value); + return new Made().read(); +} +console.log(new FromArrow().item, wrap("w"), wrap(9), wrap([1, 2])); diff --git a/tests/corpus/6110-cjs-speculative-wrapper-fences.cjs b/tests/corpus/6110-cjs-speculative-wrapper-fences.cjs index 1b3546518..fbb1a65fc 100644 --- a/tests/corpus/6110-cjs-speculative-wrapper-fences.cjs +++ b/tests/corpus/6110-cjs-speculative-wrapper-fences.cjs @@ -1,12 +1,12 @@ -// @deferred-fences: 9 +// @deferred-fences: 1 // Function expressions lowered speculatively — the `.call(this)` and // `.apply` receivers of CommonJS wrappers, and a computed class base — keep -// every statement of their bodies. A statement with no static lowering -// (here `module.exports` read as a value) compiles to its runtime fence -// instead of vanishing; these never run, so the binary matches Node. -// Coverage counts the three fenced statements nine times: each lowering of -// a wrapper body counts its statements, and the `.call` and `.apply` -// wrapper bodies are each lowered four times. +// every statement of their bodies. The wrappers' `root === module.exports` +// and `typeof module.exports` compile; a statement with no static lowering +// (here `module.exports` passed as a value in the class base) compiles to +// its runtime fence instead of vanishing. It never runs, so the binary +// matches Node. Coverage counts that one fenced statement once: the class +// base's body is lowered once. const verbose = process.argv.length > 99; (function () { var root = this; diff --git a/tests/corpus/6150-cjs-inline-require/fallback.js b/tests/corpus/6150-cjs-inline-require/fallback.js new file mode 100644 index 000000000..d89da1a00 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/fallback.js @@ -0,0 +1,6 @@ +const preferred = undefined; +module.exports = + preferred || + function fallback() { + return "fallback"; + }; diff --git a/tests/corpus/6150-cjs-inline-require/inner.js b/tests/corpus/6150-cjs-inline-require/inner.js new file mode 100644 index 000000000..7aa065c1e --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/inner.js @@ -0,0 +1,4 @@ +console.log("inner: evaluated"); +exports.inner = function () { + return "inner"; +}; diff --git a/tests/corpus/6150-cjs-inline-require/late.js b/tests/corpus/6150-cjs-inline-require/late.js new file mode 100644 index 000000000..a28525b26 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/late.js @@ -0,0 +1,2 @@ +console.log("late: evaluated"); +exports.value = "late value"; diff --git a/tests/corpus/6150-cjs-inline-require/lib.js b/tests/corpus/6150-cjs-inline-require/lib.js new file mode 100644 index 000000000..94a5872a4 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/lib.js @@ -0,0 +1,6 @@ +console.log("lib: evaluated"); +exports.f = function (x) { + return x * 10; +}; +exports.n = 7; +exports.counter = { hits: 0 }; diff --git a/tests/corpus/6150-cjs-inline-require/main.js b/tests/corpus/6150-cjs-inline-require/main.js new file mode 100644 index 000000000..0ebc20d36 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/main.js @@ -0,0 +1,55 @@ +// Inline require() of program modules: each call evaluates its module at +// exactly that position (or answers from the cache), and the value is the +// module's exports, read statically. +console.log("main: start"); +const f = require("./lib.js").f; +console.log("main: first inline require done", f(1)); +console.log("main: cached", require("./lib.js").n, require("./lib.js").f(2)); +exports.viaInline = require("./lib.js").f; +console.log("main: exported member", exports.viaInline(3), exports.viaInline === f); + +// Mutation through an inline read is visible to every requirer. +require("./lib.js").counter.hits++; +const lib = require("./lib.js"); +console.log("main: shared counter", lib.counter.hits, require("./lib.js").counter === lib.counter); + +// A whole-export function called directly off the require. +const debug = require("./make-logger.js")("app"); +console.log(debug("ready")); + +// Construction through a whole-export class and through a member class. +const p = new (require("./point.js"))(1, 2); +console.log("point", p.x + p.y); +const q = new (require("./shapes.js").Square)(3); +console.log("square", q.area()); + +// Lazy inline require: the module loads at the first call, once. +function late() { + return require("./late.js").value; +} +console.log("main: before late"); +console.log("late", late(), late()); + +// Member calls off an inline require of a table module. +console.log("table member", require("./table.js").twice(4), require("./table.js").label); + +// Table entries holding inline requires. +const table = { verify: require("./verify.js"), sign: require("./lib.js").f }; +console.log("table", table.verify("tok"), table.sign(4)); + +// Re-exports: module.exports = require(...) and through a binding. +const a = require("./reexport-inline.js"); +const b = require("./reexport-binding.js"); +console.log("reexports", a.inner(), b.inner(), a.inner === b.inner); + +// Single computed values as the whole export. +const T = require("./type-error.js"); +try { + throw new T("bad input"); +} catch (e) { + console.log(e instanceof TypeError, String(e)); +} +const pick = require("./pick.js"); +console.log("pick", pick(5), typeof require("./fallback.js"), require("./fallback.js")()); +const reg = require("./registry.js"); +console.log("registry", reg.size(), reg.add("x"), reg.size(), require("./registry.js") === reg); diff --git a/tests/corpus/6150-cjs-inline-require/make-logger.js b/tests/corpus/6150-cjs-inline-require/make-logger.js new file mode 100644 index 000000000..f698b54a7 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/make-logger.js @@ -0,0 +1,6 @@ +console.log("make-logger: evaluated"); +module.exports = function (ns) { + return function (msg) { + return ns + ": " + msg; + }; +}; diff --git a/tests/corpus/6150-cjs-inline-require/package.json b/tests/corpus/6150-cjs-inline-require/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6150-cjs-inline-require/pick.js b/tests/corpus/6150-cjs-inline-require/pick.js new file mode 100644 index 000000000..aadc1eb8e --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/pick.js @@ -0,0 +1,7 @@ +function double(x) { + return x * 2; +} +function triple(x) { + return x * 3; +} +module.exports = process.env.SCRIPTC_CORPUS_NEVER_SET ? triple : double; diff --git a/tests/corpus/6150-cjs-inline-require/point.js b/tests/corpus/6150-cjs-inline-require/point.js new file mode 100644 index 000000000..0f002800c --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/point.js @@ -0,0 +1,6 @@ +module.exports = class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } +}; diff --git a/tests/corpus/6150-cjs-inline-require/reexport-binding.js b/tests/corpus/6150-cjs-inline-require/reexport-binding.js new file mode 100644 index 000000000..e8307cc65 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/reexport-binding.js @@ -0,0 +1,3 @@ +const inner = require("./inner.js"); +console.log("reexport-binding: evaluated"); +module.exports = inner; diff --git a/tests/corpus/6150-cjs-inline-require/reexport-inline.js b/tests/corpus/6150-cjs-inline-require/reexport-inline.js new file mode 100644 index 000000000..26b6d44ea --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/reexport-inline.js @@ -0,0 +1,2 @@ +console.log("reexport-inline: evaluated"); +module.exports = require("./inner.js"); diff --git a/tests/corpus/6150-cjs-inline-require/registry.js b/tests/corpus/6150-cjs-inline-require/registry.js new file mode 100644 index 000000000..e34b1015f --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/registry.js @@ -0,0 +1,13 @@ +class Registry { + constructor() { + this.items = []; + } + add(item) { + this.items.push(item); + return this.items.length; + } + size() { + return this.items.length; + } +} +module.exports = new Registry(); diff --git a/tests/corpus/6150-cjs-inline-require/shapes.js b/tests/corpus/6150-cjs-inline-require/shapes.js new file mode 100644 index 000000000..4dd410384 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/shapes.js @@ -0,0 +1,9 @@ +class Square { + constructor(side) { + this.side = side; + } + area() { + return this.side * this.side; + } +} +exports.Square = Square; diff --git a/tests/corpus/6150-cjs-inline-require/table.js b/tests/corpus/6150-cjs-inline-require/table.js new file mode 100644 index 000000000..ce8f1e364 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/table.js @@ -0,0 +1,4 @@ +function twice(x) { + return x * 2; +} +module.exports = { twice, label: "table" }; diff --git a/tests/corpus/6150-cjs-inline-require/type-error.js b/tests/corpus/6150-cjs-inline-require/type-error.js new file mode 100644 index 000000000..483613b44 --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/type-error.js @@ -0,0 +1 @@ +module.exports = TypeError; diff --git a/tests/corpus/6150-cjs-inline-require/verify.js b/tests/corpus/6150-cjs-inline-require/verify.js new file mode 100644 index 000000000..7adb1f64a --- /dev/null +++ b/tests/corpus/6150-cjs-inline-require/verify.js @@ -0,0 +1,4 @@ +console.log("verify: evaluated"); +module.exports = function verify(token) { + return "verified " + token; +}; diff --git a/tests/corpus/6151-cjs-export-chains/chain.js b/tests/corpus/6151-cjs-export-chains/chain.js new file mode 100644 index 000000000..533e35ba8 --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/chain.js @@ -0,0 +1,10 @@ +let evaluations = 0; +function make() { + evaluations++; + return function () { + return "shared"; + }; +} +exports.a = exports.b = make(); +module.exports.c = exports.d = module.exports.e = 5; +exports.evaluations = evaluations; diff --git a/tests/corpus/6151-cjs-export-chains/constants.js b/tests/corpus/6151-cjs-export-chains/constants.js new file mode 100644 index 000000000..7a67f9f21 --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/constants.js @@ -0,0 +1 @@ +exports.VERSION = "1.2.3"; diff --git a/tests/corpus/6151-cjs-export-chains/main.js b/tests/corpus/6151-cjs-export-chains/main.js new file mode 100644 index 000000000..394c5e3d2 --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/main.js @@ -0,0 +1,9 @@ +// Chained member exports share one value, evaluated once; a fresh +// `exports = module.exports = {}` at the top of a module is a no-op reset. +const chain = require("./chain.js"); +console.log(chain.a(), chain.b(), chain.a === chain.b, chain.evaluations); +console.log(chain.c, chain.d, chain.e); +const re = require("./re.js"); +console.log(re.src.length, re.t.FULL, re.tokens.join(",")); +const sem = require("./sem.js"); +console.log(sem.src.join(" "), sem.re.join(","), sem.count()); diff --git a/tests/corpus/6151-cjs-export-chains/package.json b/tests/corpus/6151-cjs-export-chains/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6151-cjs-export-chains/re.js b/tests/corpus/6151-cjs-export-chains/re.js new file mode 100644 index 000000000..8839b5cb4 --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/re.js @@ -0,0 +1,15 @@ +'use strict' +const constants = require("./constants.js"); +exports = module.exports = {} +const src = []; +const t = {}; +exports.src = src; +exports.t = t; +exports.tokens = []; +function createToken(name, value) { + t[name] = src.length; + src.push(value); + exports.tokens.push(name); +} +createToken("FULL", "^" + constants.VERSION + "$"); +createToken("LOOSE", "v?" + constants.VERSION); diff --git a/tests/corpus/6151-cjs-export-chains/sem.js b/tests/corpus/6151-cjs-export-chains/sem.js new file mode 100644 index 000000000..f12b5b25f --- /dev/null +++ b/tests/corpus/6151-cjs-export-chains/sem.js @@ -0,0 +1,16 @@ +'use strict' +// semver's internal/re.js shape: export members assigned in value position. +exports = module.exports = {} +const re = exports.re = [] +const src = exports.src = [] +const t = exports.t = {} +let R = 0 +const createToken = (name, value) => { + const index = R++ + t[name] = index + src[index] = value + re[index] = value.length +} +exports.count = () => R +createToken('MAIN', 'x.y.z') +createToken('LOOSE', 'v?x') diff --git a/tests/corpus/6152-cjs-tsc-interop/fn.js b/tests/corpus/6152-cjs-tsc-interop/fn.js new file mode 100644 index 000000000..09b227f5b --- /dev/null +++ b/tests/corpus/6152-cjs-tsc-interop/fn.js @@ -0,0 +1,3 @@ +module.exports = function square(x) { + return x * x; +}; diff --git a/tests/corpus/6152-cjs-tsc-interop/main.js b/tests/corpus/6152-cjs-tsc-interop/main.js new file mode 100644 index 000000000..0924dce35 --- /dev/null +++ b/tests/corpus/6152-cjs-tsc-interop/main.js @@ -0,0 +1,17 @@ +"use strict"; +// tsc's CommonJS output: interop helpers over require(), the void 0 +// preamble, and the (0, x.default)() call spelling. +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.run = void 0; +console.log("main: start"); +const plain_1 = __importDefault(require("./plain.js")); +const stamped_1 = __importDefault(require("./stamped.js")); +const fn_1 = __importDefault(require("./fn.js")); +function run() { + return [plain_1.default.greet("a"), (0, stamped_1.default)("b"), stamped_1.helper(), (0, fn_1.default)(2)].join(" "); +} +exports.run = run; +console.log(run(), plain_1.default.count, typeof fn_1.default); diff --git a/tests/corpus/6152-cjs-tsc-interop/package.json b/tests/corpus/6152-cjs-tsc-interop/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6152-cjs-tsc-interop/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6152-cjs-tsc-interop/plain.js b/tests/corpus/6152-cjs-tsc-interop/plain.js new file mode 100644 index 000000000..60e6732ab --- /dev/null +++ b/tests/corpus/6152-cjs-tsc-interop/plain.js @@ -0,0 +1,5 @@ +console.log("plain: evaluated"); +exports.greet = function (who) { + return "hello " + who; +}; +exports.count = 3; diff --git a/tests/corpus/6152-cjs-tsc-interop/stamped.js b/tests/corpus/6152-cjs-tsc-interop/stamped.js new file mode 100644 index 000000000..9e844af05 --- /dev/null +++ b/tests/corpus/6152-cjs-tsc-interop/stamped.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.helper = exports.default = void 0; +console.log("stamped: evaluated"); +function greet(who) { + return "stamped " + who; +} +exports.default = greet; +function helper() { + return "helper"; +} +exports.helper = helper; diff --git a/tests/corpus/6153-cjs-exports-object/lib.js b/tests/corpus/6153-cjs-exports-object/lib.js new file mode 100644 index 000000000..4f69bfca2 --- /dev/null +++ b/tests/corpus/6153-cjs-exports-object/lib.js @@ -0,0 +1,13 @@ +exports.lookup = function (ext) { + return "application/" + ext; +}; +exports.contentType = function (ext) { + return exports.lookup(ext) + "; charset=utf-8"; +}; +exports.describe = function () { + return module.exports.lookup("xml"); +}; +// A later reassignment is what member calls see from then on. +exports.lookup = function (ext) { + return "text/" + ext; +}; diff --git a/tests/corpus/6153-cjs-exports-object/main.js b/tests/corpus/6153-cjs-exports-object/main.js new file mode 100644 index 000000000..39cf61c6c --- /dev/null +++ b/tests/corpus/6153-cjs-exports-object/main.js @@ -0,0 +1,19 @@ +// A module's own exports object, used inside the module: identity +// comparisons (the UMD self-test), typeof and truthiness, and member calls. +const lib = require("./lib.js"); +(function () { + var root = this; + console.log("wrapper", root === module.exports, root === exports, typeof root); +}).call(this); +function check() { + return [exports === module.exports, typeof exports, typeof module.exports, !exports].join(" "); +} +console.log(check(), module.exports ? "truthy" : "falsy"); +console.log(lib.contentType("json"), lib.describe()); +exports.answer = function () { + return 42; +}; +function ask() { + return module.exports.answer() + exports.answer(); +} +console.log(exports.answer(), ask()); diff --git a/tests/corpus/6153-cjs-exports-object/package.json b/tests/corpus/6153-cjs-exports-object/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6153-cjs-exports-object/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6154-cjs-require-nested-destructure/constants.js b/tests/corpus/6154-cjs-require-nested-destructure/constants.js new file mode 100644 index 000000000..6a53c5d81 --- /dev/null +++ b/tests/corpus/6154-cjs-require-nested-destructure/constants.js @@ -0,0 +1,8 @@ +exports.MAX_LENGTH = 1024; +exports.SEP = "/"; +exports.helper = function (x) { + return x * 3; +}; +exports.bump = function () { + exports.MAX_LENGTH = 2048; +}; diff --git a/tests/corpus/6154-cjs-require-nested-destructure/errors.js b/tests/corpus/6154-cjs-require-nested-destructure/errors.js new file mode 100644 index 000000000..bdddfec3f --- /dev/null +++ b/tests/corpus/6154-cjs-require-nested-destructure/errors.js @@ -0,0 +1,12 @@ +console.log("errors: evaluated"); +const codes = { + ERR_ONE: { code: "ERR_ONE" }, + ERR_TWO: { code: "ERR_TWO" }, +}; +class AbortError extends Error { + constructor() { + super("aborted"); + this.name = "AbortError"; + } +} +module.exports = { codes, AbortError, version: "4.0" }; diff --git a/tests/corpus/6154-cjs-require-nested-destructure/main.js b/tests/corpus/6154-cjs-require-nested-destructure/main.js new file mode 100644 index 000000000..d928d5a27 --- /dev/null +++ b/tests/corpus/6154-cjs-require-nested-destructure/main.js @@ -0,0 +1,14 @@ +// Nested patterns under a named export of a program module destructure +// that export's value at the require (a snapshot), while plain keys stay +// live bindings to the export. +console.log("main: start"); +const { codes: { ERR_ONE, ERR_TWO }, AbortError, version } = require("./errors.js"); +console.log(ERR_ONE.code, ERR_TWO.code, new AbortError().name, version); +const errors = require("./errors.js"); +errors.codes.ERR_ONE = { code: "replaced" }; +console.log(ERR_ONE.code, errors.codes.ERR_ONE.code); +// Destructuring a module BINDING snapshots its exports the same way. +const constants = require("./constants.js"); +const { MAX_LENGTH, SEP: sep, helper } = constants; +constants.bump(); +console.log(MAX_LENGTH, constants.MAX_LENGTH, sep, helper(2)); diff --git a/tests/corpus/6154-cjs-require-nested-destructure/package.json b/tests/corpus/6154-cjs-require-nested-destructure/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6154-cjs-require-nested-destructure/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6155-cjs-export-table-methods/lib.js b/tests/corpus/6155-cjs-export-table-methods/lib.js new file mode 100644 index 000000000..d8aa56495 --- /dev/null +++ b/tests/corpus/6155-cjs-export-table-methods/lib.js @@ -0,0 +1,20 @@ +console.log("lib: start"); +const WIN = { SEP: "\\" }; +const POSIX = { SEP: "/" }; +function describe() { + return "table"; +} +module.exports = { + scale(x) { + return x * 10; + }, + chars(win32) { + return win32 === true ? WIN.SEP : POSIX.SEP; + }, + get label() { + return describe(); + }, + ...require("./more.js"), + k: (console.log("lib: k entry"), 1), +}; +console.log("lib: end"); diff --git a/tests/corpus/6155-cjs-export-table-methods/main.js b/tests/corpus/6155-cjs-export-table-methods/main.js new file mode 100644 index 000000000..b2ce150d0 --- /dev/null +++ b/tests/corpus/6155-cjs-export-table-methods/main.js @@ -0,0 +1,5 @@ +// Export tables with method entries, accessors and spreads of required +// modules: the spread evaluates its module at its place in the table. +console.log("main: start"); +const m = require("./lib.js"); +console.log(m.scale(2), m.chars(true), m.chars(false), m.label, m.extra(), m.k); diff --git a/tests/corpus/6155-cjs-export-table-methods/more.js b/tests/corpus/6155-cjs-export-table-methods/more.js new file mode 100644 index 000000000..4051ce311 --- /dev/null +++ b/tests/corpus/6155-cjs-export-table-methods/more.js @@ -0,0 +1,4 @@ +console.log("more: evaluated"); +exports.extra = function () { + return "more"; +}; diff --git a/tests/corpus/6155-cjs-export-table-methods/package.json b/tests/corpus/6155-cjs-export-table-methods/package.json new file mode 100644 index 000000000..a3c15a7a6 --- /dev/null +++ b/tests/corpus/6155-cjs-export-table-methods/package.json @@ -0,0 +1 @@ +{ "type": "commonjs" } diff --git a/tests/corpus/6156-cjs-function-members-from-ts/consumer.cjs b/tests/corpus/6156-cjs-function-members-from-ts/consumer.cjs new file mode 100644 index 000000000..12299e189 --- /dev/null +++ b/tests/corpus/6156-cjs-function-members-from-ts/consumer.cjs @@ -0,0 +1,4 @@ +const status = require("./status.cjs"); +exports.describe = function (code) { + return code + " " + status.message[code]; +}; diff --git a/tests/corpus/6156-cjs-function-members-from-ts/main.ts b/tests/corpus/6156-cjs-function-members-from-ts/main.ts new file mode 100644 index 000000000..070d576ff --- /dev/null +++ b/tests/corpus/6156-cjs-function-members-from-ts/main.ts @@ -0,0 +1,9 @@ +// A CommonJS module exporting a function that carries its own members +// (statuses' `status.message = codes; module.exports = status`), read from +// TypeScript through the default import: calls, member reads, member calls. +import status from "./status.cjs"; +import { describe } from "./consumer.cjs"; + +console.log(status(404), status.message[200], status.codes.length, status.isOk(200)); +console.log(status.redirect[301] === true, status.redirect[302]); +console.log(describe(500)); diff --git a/tests/corpus/6156-cjs-function-members-from-ts/package.json b/tests/corpus/6156-cjs-function-members-from-ts/package.json new file mode 100644 index 000000000..5ffd9800b --- /dev/null +++ b/tests/corpus/6156-cjs-function-members-from-ts/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/tests/corpus/6156-cjs-function-members-from-ts/status.cjs b/tests/corpus/6156-cjs-function-members-from-ts/status.cjs new file mode 100644 index 000000000..7a06d9ab1 --- /dev/null +++ b/tests/corpus/6156-cjs-function-members-from-ts/status.cjs @@ -0,0 +1,10 @@ +function status(code) { + return code + 1; +} +status.message = { 200: "OK", 404: "Not Found", 500: "Internal Server Error" }; +status.codes = [200, 404, 500]; +status.redirect = { 301: true, 302: true }; +status.isOk = function (code) { + return code === 200; +}; +module.exports = status; diff --git a/tests/corpus/6160-number-radix-typed.ts b/tests/corpus/6160-number-radix-typed.ts new file mode 100644 index 000000000..4e11e06b2 --- /dev/null +++ b/tests/corpus/6160-number-radix-typed.ts @@ -0,0 +1,36 @@ +// Number.prototype.toString(radix) with a number-typed radix takes the +// typed entry point: ToIntegerOrInfinity truncates the radix (NaN to 0), +// out-of-range radixes throw the same RangeError, and the argument is +// evaluated once, before formatting. An optional radix keeps the generic +// conversion, where undefined means 10. +const radixes = [2, 2.9, 7, 10, 16, 16.5, 35.99, 36]; +const values = [0, -0, 1, -1, 255, -255.5, 0.1, 1 / 3, 2 ** 53, -(2 ** 60), 1e21, 123.456, NaN, Infinity, -Infinity]; +for (const radix of radixes) { + const row: string[] = []; + for (const value of values) row.push(value.toString(radix)); + console.log(radix, row.join(" ")); +} + +let calls = 0; +function nextRadix(): number { + calls++; + return 8 + calls; +} +console.log((1234).toString(nextRadix()), (1234).toString(nextRadix()), calls); + +for (const bad of [-0, 0.5, 1, 1.99, 36.5, 37, -2, NaN, Infinity, -Infinity]) { + try { + console.log((42).toString(bad)); + } catch (error) { + console.log(String(bad), error instanceof RangeError, (error as Error).message); + } +} + +function maybeRadix(i: number): number | undefined { + return i % 2 === 0 ? undefined : 2 + i; +} +for (let i = 0; i < 4; i++) console.log((255).toString(maybeRadix(i))); + +let total = 0; +for (let i = 0; i < 2000; i++) total += (i * 7919).toString(2 + (i % 35)).length; +console.log(total); diff --git a/tests/corpus/6161-dispose-observer-gates.ts b/tests/corpus/6161-dispose-observer-gates.ts new file mode 100644 index 000000000..aa53c9c85 --- /dev/null +++ b/tests/corpus/6161-dispose-observer-gates.ts @@ -0,0 +1,47 @@ +// A program without weak collections still keeps the undeclared keys of +// checked records, and forgets them when the record is freed: a record +// built later at the same address (the allocator reuses freed blocks of +// its size) serializes only its own fields. Class instances and records +// of shapes that never keep a source free without the dispose hook. +interface Row { + id: number; + name: string; +} +class Point { + x: number; + y: number; + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +function parsedRows(round: number): Row[] { + const text = + `[{"id":${round},"extra":"kept-${round}","name":"a"},` + + `{"name":"b","id":${round + 1}},` + + `{"id":${round + 2},"name":"c","tags":[${round}]}]`; + return JSON.parse(text) as Row[]; +} + +let checksum = 0; +for (let round = 0; round < 3; round++) { + const rows = parsedRows(round); + console.log(JSON.stringify(rows)); + // Drop the parsed rows, then build fresh rows of the same shape. + rows.length = 0; + const fresh: Row[] = []; + for (let i = 0; i < 64; i++) fresh.push({ id: i, name: "n" + i }); + const text = JSON.stringify(fresh); + checksum += text.length; + console.log(text.includes("extra"), text.includes("tags"), Object.keys(fresh[0]!).join(",")); +} +console.log(checksum); + +let sum = 0; +for (let i = 0; i < 10000; i++) { + const p = new Point(i, -i); + const r = { a: p.x, b: [p.y] }; + sum += r.a + r.b[0]!; +} +console.log(sum); diff --git a/tests/corpus/6162-dispose-observer-weak-keys.ts b/tests/corpus/6162-dispose-observer-weak-keys.ts new file mode 100644 index 000000000..f9c5738fa --- /dev/null +++ b/tests/corpus/6162-dispose-observer-weak-keys.ts @@ -0,0 +1,41 @@ +// With a weak collection in the program, every object type's free tells +// the collection to forget the key: objects built later at a freed key's +// address (the allocator reuses blocks of the same size) are not members. +class Node { + id: number; + constructor(id: number) { + this.id = id; + } +} +interface Tag { + label: string; +} + +const seenNodes = new WeakSet(); +const seenTags = new WeakSet(); +const seenArrays = new WeakMap(); +for (let i = 0; i < 64; i++) { + seenNodes.add(new Node(i)); + seenTags.add({ label: "t" + i }); + seenArrays.set([i], "a" + i); +} +let hits = 0; +for (let i = 0; i < 64; i++) { + if (seenNodes.has(new Node(i))) hits++; + if (seenTags.has({ label: "t" + i })) hits++; + if (seenArrays.has([i])) hits++; +} +console.log("stale hits", hits); + +const kept = new Node(1); +const tag: Tag = { label: "kept" }; +seenNodes.add(kept); +seenTags.add(tag); +console.log(seenNodes.has(kept), seenTags.has(tag)); +seenNodes.delete(kept); +console.log(seenNodes.has(kept), seenTags.has(tag)); + +// Checked records with undeclared keys in the same program. +const parsed = JSON.parse('{"label":"x","more":1}') as Tag; +seenTags.add(parsed); +console.log(JSON.stringify(parsed), seenTags.has(parsed)); diff --git a/tests/corpus/6163-dispose-observer-workers.ts b/tests/corpus/6163-dispose-observer-workers.ts new file mode 100644 index 000000000..aa5781752 --- /dev/null +++ b/tests/corpus/6163-dispose-observer-workers.ts @@ -0,0 +1,43 @@ +import { Worker, isMainThread, parentPort } from "node:worker_threads"; + +// Each script thread has its own dispose hook: a worker that keeps checked +// record sources and weak keys serializes and forgets them on its own, +// while the main thread runs the same code without sharing its state. +interface Row { + id: number; + name: string; +} +class Key { + id: number; + constructor(id: number) { + this.id = id; + } +} + +function run(who: string, base: number): string[] { + const out: string[] = []; + const text = `[{"id":${base},"extra":"${who}","name":"a"},{"name":"b","id":${base + 1}}]`; + const rows = JSON.parse(text) as Row[]; + out.push(JSON.stringify(rows)); + rows.length = 0; + const fresh: Row[] = []; + for (let i = 0; i < 32; i++) fresh.push({ id: base + i, name: who }); + out.push(String(JSON.stringify(fresh).includes("extra"))); + const seen = new WeakSet(); + for (let i = 0; i < 32; i++) seen.add(new Key(i)); + let stale = 0; + for (let i = 0; i < 32; i++) if (seen.has(new Key(i))) stale++; + out.push(`${who} stale ${stale}`); + return out; +} + +if (isMainThread) { + for (const line of run("main", 0)) console.log(line); + const worker = new Worker(new URL(import.meta.url)); + worker.on("message", (lines: string[]) => { + for (const line of lines) console.log(line); + }); + worker.on("exit", (code) => console.log("worker exit", code)); +} else { + parentPort!.postMessage(run("worker", 100)); +} diff --git a/tests/corpus/6164-regex-replace-typed-callback.ts b/tests/corpus/6164-regex-replace-typed-callback.ts new file mode 100644 index 000000000..8945235cd --- /dev/null +++ b/tests/corpus/6164-regex-replace-typed-callback.ts @@ -0,0 +1,67 @@ +// String replace/replaceAll with typed function replacers. Callbacks whose +// every parameter receives its declared kind in each match (the match, the +// captures every match sets, the offset, the subject) are called through +// the closure directly; the rest keep the generic path. Both must match +// Node: all matches are collected before the first call, calls run in +// order with the offset in UTF-16 code units, and a throw stops the +// replacement. +const entities: Record = { "&": "&", "<": "<", ">": ">", '"': """ }; +const escapeHtml = (text: string): string => text.replace(/[&<>"]/g, (c) => entities[c] ?? c); +console.log(escapeHtml('a & "c"'), escapeHtml("plain")); +console.log("hello world".replace(/o/, (m) => m.toUpperCase())); +console.log("hello world".replaceAll(/o/g, (m) => `[${m}]`)); +console.log("abc".replace(/x/g, () => "never")); + +console.log("a-b-c".replace(/-/g, (m: string, offset: number) => `${m}${offset}`)); +console.log("ab".replace(/b/, (m: string, offset: number, input: string) => `${m}@${offset}/${input}`)); +console.log("id-12 id-345".replace(/(\d+)/g, (_m: string, digits: string) => String(Number(digits) * 2))); +console.log("k1=v1;k2=v2".replace(/(\w+)=(\w+)/g, (_m: string, k: string, v: string) => `${v}=${k}`)); +console.log("x1y22".replace(/(\d)+/g, (m: string, last: string, at: number) => `<${m}:${last}:${at}>`)); +console.log("a=1".replace(/(\w)=(\d)/, (m: string, k: string, v: string, at: number) => `${m}|${k}|${v}|${at}`)); +console.log("ab ab".replace(/(?a)(b)/g, (m: string, a: string, b: string, at: number, all: string) => `${b}${a}${at}${all.length}`)); + +// Offsets count UTF-16 code units; empty matches advance by code points under /u. +console.log("héllo wörld 😀!".replace(/o/g, (m: string, at: number) => `${m}${at}`)); +console.log("😀a".replace(/(?:)/gu, (m: string, at: number) => `[${at}]`)); +console.log("😀a".replace(/(?:)/g, (m: string, at: number) => `[${at}]`)); + +// Captures that some match leaves unset keep the generic path. +console.log("ab".replace(/(a)|(b)/g, (m: string, a?: string, b?: string) => `${m}:${a}:${b};`)); +console.log("ab".replace(/(x)?b/, (m: string, x?: string) => `${m}:${x}`)); +const dynamicPattern = /(\d)/g; +console.log("1-2".replace(dynamicPattern, (m: string, d: string) => d + d)); + +// The callback runs after every match is collected: it can reuse the regex. +const word = /\w+/g; +console.log("one two three".replace(word, (m: string) => `${m.length}${word.lastIndex}`), word.lastIndex); +const sticky = /a/y; +sticky.lastIndex = 1; +console.log("baaa".replace(sticky, (m: string) => m.toUpperCase()), sticky.lastIndex); + +let calls = 0; +try { + "a1b2c3".replace(/\d/g, (m: string) => { + calls++; + if (m === "2") throw new Error("stop at " + m); + return "#"; + }); +} catch (error) { + console.log((error as Error).message, calls); +} +try { + "a1b2".replace(/(\d)|z/g, (m: string, d?: string) => { + if (d === "2") throw new Error("generic stop at " + d); + return "#" + m; + }); +} catch (error) { + console.log((error as Error).message); +} +try { + "aaa".replaceAll(/a/, (m: string) => m); +} catch (error) { + console.log(error instanceof TypeError, (error as Error).message); +} + +let total = 0; +for (let i = 0; i < 3000; i++) total += escapeHtml(`<${i}> & "${i}"`).length; +console.log(total); diff --git a/tests/corpus/6165-regex-replace-callback-throws.ts b/tests/corpus/6165-regex-replace-callback-throws.ts new file mode 100644 index 000000000..57cb8af18 --- /dev/null +++ b/tests/corpus/6165-regex-replace-callback-throws.ts @@ -0,0 +1,26 @@ +// A replace callback that throws after earlier matches were replaced: the +// partial result is discarded and the exception propagates, with the +// callbacks that ran counted exactly as in Node. +let calls = 0; +function replacer(m: string, digit?: string): string { + calls++; + if (digit === "3") throw new RangeError("stop at " + m); + return "<" + m + ">"; +} +for (const subject of ["a1b2c3d4", "x3", "no digits"]) { + calls = 0; + try { + console.log(subject.replace(/(\d)|z/g, replacer), calls); + } catch (error) { + console.log(error instanceof RangeError, (error as Error).message, calls); + } +} +const parts: string[] = []; +for (let i = 0; i < 50; i++) { + try { + parts.push(("k" + i + "-3").replace(/(\d)/g, replacer)); + } catch { + parts.push("thrown"); + } +} +console.log(parts.filter((p) => p === "thrown").length, calls); diff --git a/tests/corpus/6170-flight-dev-stacks-dead.ts b/tests/corpus/6170-flight-dev-stacks-dead.ts new file mode 100644 index 000000000..bddf70f6a --- /dev/null +++ b/tests/corpus/6170-flight-dev-stacks-dead.ts @@ -0,0 +1,173 @@ +// React Flight's production server as compiled from its sources: the V8 +// structured-stack parser (ReactFlightStackConfigV8) is development-only and +// is referenced only after the production `throw` stubs, so a production +// render never parses a stack. Statements after an abrupt statement never +// run: they may use APIs with no static lowering (Error.prepareStackTrace, +// CallSite) and must not make the program keep stack frames. +// V8's structured stack API, declared here as React's Flow build declares +// it (the program's own types, not Node's). +interface CallSite { + getTypeName(): string | null; + getMethodName(): string | null; + getFunctionName(): string | null; + getScriptNameOrSourceURL(): string | null; + getEvalOrigin(): string | undefined; + getLineNumber(): number | null; + getColumnNumber(): number | null; + isNative(): boolean; + isAsync(): boolean; + isConstructor(): boolean; + isToplevel(): boolean; + isEval(): boolean; + toString(): string; +} +declare global { + interface ErrorConstructor { + prepareStackTrace?: (error: Error, structuredStackTrace: CallSite[]) => string; + } +} +type ReactStackTrace = Array<[string, string, number, number, number, number, boolean]>; + +let framesToSkip: number = 0; +let collectedStackTrace: null | ReactStackTrace = null; +const identifierRegExp = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; + +function getMethodCallName(callSite: CallSite): string { + const typeName = callSite.getTypeName(); + const methodName = callSite.getMethodName(); + const functionName = callSite.getFunctionName(); + let result = ''; + if (functionName) { + if (typeName && identifierRegExp.test(functionName) && functionName !== typeName) { + result += typeName + '.'; + } + result += functionName; + if (methodName && functionName !== methodName && !functionName.endsWith('.' + methodName) && !functionName.endsWith(' ' + methodName)) { + result += ' [as ' + methodName + ']'; + } + } else { + if (typeName) { + result += typeName + '.'; + } + result += methodName ? methodName : ''; + } + return result; +} + +function collectStackTracePrivate(error: Error, structuredStackTrace: CallSite[]): string { + const result: ReactStackTrace = []; + for (let i = framesToSkip; i < structuredStackTrace.length; i++) { + const callSite = structuredStackTrace[i]; + let name = callSite.getFunctionName() || ''; + if (name.includes('react_stack_bottom_frame')) { + break; + } else if (callSite.isNative()) { + result.push([name, '', 0, 0, 0, 0, callSite.isAsync()]); + } else { + if (callSite.isConstructor()) { + name = 'new ' + name; + } else if (!callSite.isToplevel()) { + name = getMethodCallName(callSite); + } + if (name === '') { + name = ''; + } + let filename = callSite.getScriptNameOrSourceURL() || ''; + if (filename === '') { + filename = ''; + if (callSite.isEval()) { + const origin = callSite.getEvalOrigin(); + if (origin) { + filename = origin.toString() + ', '; + } + } + } + const line = callSite.getLineNumber() || 0; + const col = callSite.getColumnNumber() || 0; + result.push([name, filename, line, col, 0, 0, callSite.isAsync()]); + } + } + collectedStackTrace = result; + return ''; +} + +function collectStackTrace(error: Error, structuredStackTrace: CallSite[]): string { + collectStackTracePrivate(error, structuredStackTrace); + const name = error.name || 'Error'; + const message = error.message || ''; + let stack = name + ': ' + message; + for (let i = 0; i < structuredStackTrace.length; i++) { + stack += '\n at ' + structuredStackTrace[i].toString(); + } + return stack; +} + +function parseStackTrace(error: Error, skipFrames: number): ReactStackTrace { + collectedStackTrace = null; + framesToSkip = skipFrames; + const previousPrepare = Error.prepareStackTrace; + Error.prepareStackTrace = collectStackTrace; + let stack; + try { + stack = String(error.stack); + } finally { + Error.prepareStackTrace = previousPrepare; + } + if (collectedStackTrace !== null) { + const result = collectedStackTrace; + collectedStackTrace = null; + return result; + } + return stack.split('\n').length > 0 ? [] : []; +} + +function renderDebugModel(value: any): any { + if (value !== null && typeof value === 'object' && value._debugStack != null) { + return parseStackTrace(value._debugStack, 1); + } + return value; +} + +function emitOutlinedDebugModelChunk(model: any): string { + throw new Error('emitOutlinedDebugModel should never be called in production mode. This is a bug in React.'); + function replacer(this: any, parentPropertyName: string, value: any): any { + return renderDebugModel(this[parentPropertyName]); + } + const json: string = JSON.stringify(model, replacer); + return json; +} + +function outlineComponentInfo(componentInfo: any): string { + throw new Error('outlineComponentInfo should never be called in production mode. This is a bug in React.'); + const counter = { objectLimit: 10 }; + if (componentInfo.debugStack != null) { + counter.objectLimit += parseStackTrace(componentInfo.debugStack, 1).length; + } + return emitOutlinedDebugModelChunk(componentInfo) + counter.objectLimit; +} + +// The production render: elements become `id:json` rows. +type Element = { type: string; props: { [key: string]: string }; children: Element[] }; +function el(type: string, props: { [key: string]: string }, children: Element[]): Element { + return { type, props, children }; +} +function renderModel(node: Element): string { + const children = node.children.map(renderModel); + return '["$","' + node.type + '",null,' + JSON.stringify(node.props).slice(0, -1) + (children.length > 0 ? (Object.keys(node.props).length > 0 ? ',' : '') + '"children":[' + children.join(',') + ']' : '') + '}]'; +} +const rows: string[] = []; +const items: Element[] = []; +for (let i = 0; i < 3; i++) items.push(el('li', { key: 'k' + i }, [])); +rows.push('0:' + renderModel(el('main', {}, [el('ul', { className: 'list' }, items)]))); +console.log(rows.join('\n')); + +// The production stubs themselves run and throw; their DEV bodies never do. +for (const stub of [() => outlineComponentInfo({ debugStack: new Error('owner') }), () => emitOutlinedDebugModelChunk({})]) { + try { + stub(); + } catch (error) { + console.log((error as Error).message); + } +} + +export {}; diff --git a/tests/corpus/6171-error-stack-capture-sites.ts b/tests/corpus/6171-error-stack-capture-sites.ts new file mode 100644 index 000000000..1a8c8494d --- /dev/null +++ b/tests/corpus/6171-error-stack-capture-sites.ts @@ -0,0 +1,79 @@ +// Stack captures keep the frames of every function active when the Error is +// created: callers of constructors and closures, recursion, and errors a +// runtime operation creates and a local catch takes. Leaf functions and +// accessors that cannot create an Error run in between. Captures record +// frames when the Error is created and format them on the first `.stack` +// read. +let lastCaught: Error | null = null; + +function parseNumber(text: string): number { + try { + return JSON.parse(text) as number; + } catch (error) { + lastCaught = error as Error; + return -1; + } +} + +class Failure { + readonly error: Error; + constructor(reason: string) { + this.error = new Error(reason); + } +} +function buildFailure(reason: string): Failure { + return new Failure(reason); +} + +class Counter { + count: number = 0; + get next(): number { + return ++this.count; + } +} + +function leaf(n: number): number { + return n * 2 + 1; +} +function sumLeaves(n: number): number { + let total = 0; + for (let i = 0; i < n; i++) total += leaf(i); + return total; +} +function viaClosure(make: () => Error): Error { + return make(); +} +function recurse(n: number): Error { + return n === 0 ? new Error('deep') : recurse(n - 1); +} +function hasFrame(error: Error, name: string): boolean { + return error.stack!.split('\n').some((line) => line.includes(' ' + name + ' ') || line.endsWith(' ' + name)); +} + +const counter = new Counter(); +console.log(parseNumber('12'), parseNumber('{'), counter.next, counter.next, sumLeaves(4)); +const caught = lastCaught!; +console.log(caught.name, caught.stack!.startsWith('SyntaxError: '), hasFrame(caught, 'parseNumber')); + +const constructed = buildFailure('in constructor').error; +console.log(constructed.stack!.split('\n')[0], hasFrame(constructed, 'buildFailure')); + +const closure = viaClosure(() => new Error('in closure')); +console.log(closure.stack!.split('\n')[0], hasFrame(closure, 'viaClosure')); + +// Frames are recorded at creation: a later limit and later calls do not +// change them, and the first read fixes the text. +Error.stackTraceLimit = 3; +const deep = recurse(10); +Error.stackTraceLimit = 10; +sumLeaves(100); +const first = deep.stack!; +console.log(first.split('\n').length, hasFrame(deep, 'recurse'), first === deep.stack); +deep.message = 'changed'; +console.log(deep.stack === first); + +// An Error created with the limit at zero has no frames. +Error.stackTraceLimit = 0; +const bare = recurse(2); +Error.stackTraceLimit = 10; +console.log(JSON.stringify(bare.stack)); diff --git a/tests/corpus/6172-unreachable-statements.ts b/tests/corpus/6172-unreachable-statements.ts new file mode 100644 index 000000000..53704f694 --- /dev/null +++ b/tests/corpus/6172-unreachable-statements.ts @@ -0,0 +1,85 @@ +// Statements after return, throw, break or continue never run, while the +// declarations among them keep their hoisting: a later function declaration +// is callable from above, a later `var` reads undefined, and a later +// `let`/`const` stays in its temporal dead zone. +function hoistedCall(): number { + return twice(21); + console.log('never'); + function twice(n: number): number { + return n * 2; + } +} + +function hoistedVar(): string { + const before = typeof late; + return before; + var late: string | undefined = 'assigned'; + console.log(late); +} + +function deadZone(): string { + const read = (): number => counted; + try { + return String(read()); + } catch (error) { + return (error as Error).name + ': ' + (error as Error).message; + } + const counted = 1; +} + +function closureReference(): number { + const call = (): number => helper(); + return call(); + function helper(): number { + return 7; + } +} + +function loops(): string { + const seen: string[] = []; + for (let i = 0; i < 4; i++) { + if (i === 1) { + seen.push('skip'); + continue; + seen.push('never'); + } + if (i === 3) { + seen.push('stop'); + break; + seen.push('never'); + } + seen.push('i' + i); + } + return seen.join(','); +} + +function cases(n: number): string { + switch (n) { + case 0: + return 'zero'; + console.log('never'); + case 1: + n += 10; + case 2: + return 'fell to ' + n; + default: + throw new RangeError('n=' + n); + console.log('never'); + } +} + +function stub(): string { + throw new Error('stub'); + const unused = [1, 2, 3].map((x) => x * 2); + return unused.join(); +} + +console.log(hoistedCall(), hoistedVar(), deadZone(), closureReference(), loops()); +console.log(cases(0), cases(1), cases(2)); +for (const run of [() => cases(5), stub]) { + try { + run(); + } catch (error) { + console.log((error as Error).name, (error as Error).message); + } +} diff --git a/tests/corpus/6180-interface-overload-events.ts b/tests/corpus/6180-interface-overload-events.ts new file mode 100644 index 000000000..d76a118bc --- /dev/null +++ b/tests/corpus/6180-interface-overload-events.ts @@ -0,0 +1,95 @@ +// An interface method with literal-discriminated overloads (the event +// registry shape: on("x", (e: X) => R)) holds ONE function at runtime, as +// JavaScript does. Each call site resolves its overload statically; handlers +// whose types differ per overload cross into the stored function as checked +// function values, and the implementation receives them in its own +// callback type. Events keep their identity across that boundary. +export {}; + +interface SaveEvent { + type: "save"; + path: string; + cancel: boolean; +} +interface LoadEvent { + type: "load"; + path: string; +} +interface Context { + cwd: string; +} +interface Api { + on(event: "save", handler: (e: SaveEvent, ctx: Context) => void): () => void; + on(event: "load", handler: (e: LoadEvent, ctx: Context) => boolean): () => void; + on(event: "tick", handler: (n: number) => void): () => void; + name: string; +} + +let nextId = 0; +const saves: { id: number; h: (e: SaveEvent, ctx: Context) => void }[] = []; +const loads: { id: number; h: (e: LoadEvent, ctx: Context) => boolean }[] = []; +const ticks: { id: number; h: (n: number) => void }[] = []; + +function createApi(name: string): Api { + return { + name, + on(event: "save" | "load" | "tick", handler: any): () => void { + const id = ++nextId; + const count = + event === "save" + ? saves.push({ id, h: handler }) + : event === "load" + ? loads.push({ id, h: handler }) + : ticks.push({ id, h: handler }); + console.log(`${name}: registered ${event} #${id} (${count})`); + return () => { + if (event === "save") saves.splice(saves.findIndex((x) => x.id === id), 1); + else if (event === "load") loads.splice(loads.findIndex((x) => x.id === id), 1); + else ticks.splice(ticks.findIndex((x) => x.id === id), 1); + console.log(`${name}: removed ${event} #${id}`); + }; + }, + }; +} + +// An extension sees only the interface. +function extension(pi: Api): () => void { + pi.on("save", (e, ctx) => { + e.cancel = e.path.endsWith(".lock"); + console.log(`save ${ctx.cwd}/${e.path}`); + }); + pi.on("load", (e) => e.path.length > 3); + return pi.on("tick", (n) => console.log("tick", n * 2, pi.name)); +} + +const api = createApi("main"); +const stopTicks = extension(api); +const ctx: Context = { cwd: "/work" }; +for (const path of ["a.txt", "b.lock"]) { + const ev: SaveEvent = { type: "save", path, cancel: false }; + for (const { h } of saves) h(ev, ctx); + console.log(path, "cancelled:", ev.cancel); +} +for (const { h } of loads) console.log(h({ type: "load", path: "ab" }, ctx), h({ type: "load", path: "abcd" }, ctx)); +for (const { h } of ticks) h(21); +stopTicks(); +console.log("ticks left", ticks.length); + +// A named handler value converts the same way as a lambda. +function onTick(n: number): void { + console.log("named tick", n); +} +const off = api.on("tick", onTick); +for (const { h } of ticks) h(7); +off(); + +// A handler that throws propagates through the boundary unchanged. +api.on("load", (e) => { + if (e.path === "") throw new Error("empty path"); + return true; +}); +try { + for (const { h } of loads) h({ type: "load", path: "" }, ctx); +} catch (err) { + console.log("caught", (err as Error).message); +} diff --git a/tests/corpus/6181-interface-overload-arity.ts b/tests/corpus/6181-interface-overload-arity.ts new file mode 100644 index 000000000..ae4dc5192 --- /dev/null +++ b/tests/corpus/6181-interface-overload-arity.ts @@ -0,0 +1,56 @@ +// Arity overloads on interface and type-literal members: positions some +// overloads omit are optional in the stored function, so one implementation +// with optional parameters serves every overload, and a call omitting a +// trailing argument passes undefined exactly as Node does. +export {}; + +interface Formatter { + label(): string; + label(prefix: string): string; + label(prefix: string, width: number): string; +} +const formatter: Formatter = { + label(prefix?: string, width?: number): string { + const text = prefix ?? "none"; + return width === undefined ? text : text.padEnd(width, ".") + "|"; + }, +}; +console.log(formatter.label()); +console.log(formatter.label("p")); +console.log(formatter.label("q", 6)); + +// Overloads spelled as call signatures of a type-literal member. +type Logger = { + log: { + (message: string): void; + (level: number, message: string): void; + }; + lines: string[]; +}; +const lines: string[] = []; +const logger: Logger = { + lines, + log: (a: string | number, b?: string) => { + lines.push(typeof a === "number" ? `[${a}] ${b}` : a); + }, +}; +logger.log("plain"); +logger.log(2, "leveled"); +console.log(logger.lines.join("; ")); + +// A single-signature method with an optional parameter fills its slot the +// same way. +interface Greeter { + greet(name?: string): string; +} +const greeter: Greeter = { + greet(name?: string): string { + return `hello ${name ?? "stranger"}`; + }, +}; +console.log(greeter.greet(), greeter.greet("ada")); + +// Arguments are evaluated once, left to right, before the call. +let n = 0; +const next = (): string => `#${++n}`; +console.log(formatter.label(next(), 4 + n), n); diff --git a/tests/corpus/6182-interface-overload-types.ts b/tests/corpus/6182-interface-overload-types.ts new file mode 100644 index 000000000..17ce95d17 --- /dev/null +++ b/tests/corpus/6182-interface-overload-types.ts @@ -0,0 +1,61 @@ +// Type overloads with one shared implementation: the stored function takes +// the join of the overload parameter types (a scalar union here) and each +// call converts its result back to the resolved overload's type. Records, +// generic overloads, and implementations typed with unions or `any` share +// the same slot. +export {}; + +interface Converter { + conv(x: number): string; + conv(x: string): number; + conv(x: boolean): boolean; +} +const converter: Converter = { + conv(x: number | string | boolean): any { + return typeof x === "number" ? `n${x}` : typeof x === "string" ? x.length : !x; + }, +}; +const s: string = converter.conv(12); +const len: number = converter.conv("abcd"); +const flipped: boolean = converter.conv(false); +console.log(s.toUpperCase(), len + 1, flipped); + +interface Point { + x: number; + y: number; +} +interface Named { + name: string; +} +interface Factory { + make(kind: "point", a: number, b: number): Point; + make(kind: "named", a: string): Named; +} +const factory: Factory = { + make(kind: string, a: number | string, b?: number): any { + return kind === "point" ? { x: a, y: b } : { name: a }; + }, +}; +const p = factory.make("point", 3, 4); +const named = factory.make("named", "zed"); +console.log(Math.hypot(p.x, p.y), named.name.length, p, named); + +// Generic overloads erase their own type parameters to `unknown`. +interface Store { + get(key: "names", fallback: string[]): string[]; + get(key: "count"): number; + at(items: T[], i: number): T; + at(items: string, i: number): string; +} +const data: Record = { names: ["a", "b"], count: 3 }; +const store: Store = { + get(key: string, fallback?: unknown): any { + return data[key] ?? fallback; + }, + at(items: any, i: number): any { + return items[i]; + }, +}; +console.log(store.get("names", []).join("|"), store.get("count") * 2); +console.log(store.at([10, 20, 30], 1) + 1, store.at("xyz", 2).toUpperCase()); + diff --git a/tests/corpus/6183-interface-overload-flow.ts b/tests/corpus/6183-interface-overload-flow.ts new file mode 100644 index 000000000..d2f3151dc --- /dev/null +++ b/tests/corpus/6183-interface-overload-flow.ts @@ -0,0 +1,89 @@ +// Values of an interface with an overloaded member flow like any record: +// through arrays, factory callbacks, and function results. A class that +// implements the interface dispatches to its own overloaded method. +export {}; + +interface Bus { + emit(kind: "num", value: number): void; + emit(kind: "text", value: string): void; + label: string; +} +type Plugin = (bus: Bus) => void; + +const log: string[] = []; +function makeBus(label: string): Bus { + return { + label, + emit(kind: "num" | "text", value: number | string): void { + log.push(`${label}:${kind}:${typeof value}:${value}`); + }, + }; +} +const plugins: Plugin[] = [ + (bus) => bus.emit("num", 1), + (bus) => { + bus.emit("text", "two"); + bus.emit("num", bus.label.length + 2); + }, +]; +const buses: Bus[] = [makeBus("x"), makeBus("yy")]; +for (const bus of buses) for (const plugin of plugins) plugin(bus); +console.log(log.join("\n")); +console.log(typeof buses[1]!.emit, JSON.stringify(buses[0])); + +interface Picker { + pick(kind: "s"): string; + pick(kind: "n"): number; +} +class Impl implements Picker { + private readonly base: number; + constructor(base: number) { + this.base = base; + } + pick(kind: "s"): string; + pick(kind: "n"): number; + pick(kind: "s" | "n"): string | number { + return kind === "s" ? `str${this.base}` : this.base * 7; + } +} +function use(p: Picker): string { + return `${p.pick("s").length}/${p.pick("n") + 1}`; +} +console.log(use(new Impl(1)), use(new Impl(10))); +const literal: Picker = { + pick(kind: "s" | "n"): any { + return kind === "s" ? "literal" : -1; + }, +}; +console.log(use(literal)); + +// Receivers of every shape resolve the overload the same way: a union of +// records sharing the member, an optional chain, and a call result. +interface Measure { + kind: "len"; + of(x: number): string; + of(x: string): number; +} +interface Sign { + kind: "sign"; + of(x: number): string; + of(x: string): number; +} +const measure: Measure = { + kind: "len", + of(x: number | string): any { + return typeof x === "number" ? `#${x}` : x.length; + }, +}; +const sign: Sign = { + kind: "sign", + of(x: number | string): any { + return typeof x === "number" ? (x < 0 ? "-" : "+") : -x.length; + }, +}; +for (const m of [measure, sign] as (Measure | Sign)[]) console.log(m.kind, m.of(-4).length, m.of("xyz") + 1); +const maybe: Measure | undefined = buses.length > 5 ? undefined : measure; +const none: Measure | undefined = buses.length > 5 ? measure : undefined; +console.log(maybe?.of(5), maybe?.of("abc"), none?.of(1), none?.of("q")); +const pickMeasure = (): Measure => measure; +console.log(pickMeasure().of(7).toUpperCase()); diff --git a/tests/corpus/6230-optional-chain-unchecked-receivers.ts b/tests/corpus/6230-optional-chain-unchecked-receivers.ts new file mode 100644 index 000000000..b80f6134a --- /dev/null +++ b/tests/corpus/6230-optional-chain-unchecked-receivers.ts @@ -0,0 +1,98 @@ +// An optional chain short-circuits EVERY later step when its guarded +// receiver is nullish, even when the checker calls that receiver present: +// an array read past the end or a missing index-signature key is undefined +// at runtime, so `choices[0]?.delta.content` must not read `.content` from +// undefined (the streaming SSE shape). Covers property, element, call, +// non-null-assertion, and nested tails, plus the forms that must still throw. +type Delta = { content?: string; parts: number[] }; +type Choice = { + delta: Delta; + pick(): { c: string }; + maybe?: () => { c: string }; +}; + +const none: Choice[] = []; +const some: Choice[] = [ + { delta: { content: "hi", parts: [7, 8] }, pick: () => ({ c: "picked" }) }, + { delta: { parts: [] }, pick: () => ({ c: "second" }), maybe: () => ({ c: "maybe" }) }, +]; + +// Property tails. +console.log("prop", none[0]?.delta.content, some[0]?.delta.content, some[1]?.delta.content); +console.log("prop ===", none[0]?.delta.content === undefined); +console.log("prop ??", none[0]?.delta.content ?? "none", some[0]?.delta.content ?? "none"); +console.log("prop len", none[0]?.delta.parts.length, some[0]?.delta.parts.length); + +// Element tails, with lazy index side effects on the short-circuit. +let evals = 0; +function at(i: number): number { + evals++; + return i; +} +console.log("elem", none[0]?.delta.parts[at(0)], "evals", evals); +console.log("elem", some[0]?.delta.parts[at(1)], "evals", evals); +console.log("elem ?.[]", none?.[0]?.delta.parts[0], some?.[0]?.delta.parts[0]); + +// Call tails: method call results and optional calls inside the chain. +console.log("call", none[0]?.pick().c, some[0]?.pick().c); +console.log("call ?.()", none[0]?.maybe?.().c, some[0]?.maybe?.().c, some[1]?.maybe?.().c); +let pushed = 0; +function sideEffect(): number { + pushed++; + return 1; +} +none[0]?.delta.parts.push(sideEffect()); +some[1]?.delta.parts.push(sideEffect()); +console.log("call args", pushed, some[1]!.delta.parts.length); + +// A non-null assertion stays inside the chain (`a?.b!.c` is one chain). +console.log("assert", none[0]?.delta!.content, some[0]?.delta!.content); +console.log("assert ===", none[0]?.delta!.parts.length === undefined); + +// Index-signature records: a missing key is undefined. +const byId: { [id: string]: Choice } = { a: some[0]! }; +console.log("index", byId["zz"]?.delta.content, byId["a"]?.delta.content); +console.log("index dot", byId.zz?.delta.parts.length, byId.a?.delta.parts.length); + +// Nested receivers and nested guards. +const grid: Choice[][] = [[], some]; +console.log("nested", grid[0]?.[0]?.delta.content, grid[1]?.[0]?.delta.content); +console.log("nested", grid[5]?.[0].delta.content, grid[1]?.[1]?.delta.content); + +// Optional members holding arrays. +const holder: { list?: Choice[] } = {}; +const full: { list?: Choice[] } = { list: some }; +console.log("member", holder.list?.[0].delta.content, full.list?.[0].delta.content); + +// Strings and conditions. +const words: string[] = []; +const padded = [" ab "]; +console.log("string", words[0]?.trim().length, padded[0]?.trim().length); +console.log("typeof", typeof none[0]?.delta.content, typeof some[0]?.delta.content); +if (none[0]?.delta.content) console.log("unreachable"); +else console.log("cond ok"); +console.log(`template ${none[0]?.delta.content} ${some[0]?.delta.content}`); + +// Typed JSON.parse results: an empty choices array short-circuits too. +type Chunk = { choices: { delta: Delta }[] }; +const streamChunk = JSON.parse('{"choices":[]}') as Chunk; +console.log("json", streamChunk.choices[0]?.delta.content ?? "(no delta)"); +const textChunk = JSON.parse('{"choices":[{"delta":{"content":"tok","parts":[]}}]}') as Chunk; +console.log("json", textChunk.choices[0]?.delta.content ?? "(no delta)"); + +// A PRESENT receiver followed by a missing step still throws: the guard +// covers only the receiver it tests. +function message(f: () => unknown): string { + try { + f(); + return "no throw"; + } catch (e) { + return (e as Error).message; + } +} +console.log("throws", message(() => some?.[5].delta)); +console.log("throws", message(() => none[0].delta)); +// Parentheses end the chain: the outer read sees undefined. +const loose = JSON.parse("{}"); +console.log("parens", message(() => (loose.missing?.deep).deeper)); +console.log("no parens", message(() => loose.missing?.deep.deeper)); diff --git a/tests/corpus/error-js-accessor-name-message.js b/tests/corpus/error-js-accessor-name-message.js new file mode 100644 index 000000000..77b8668fa --- /dev/null +++ b/tests/corpus/error-js-accessor-name-message.js @@ -0,0 +1,45 @@ +// A JavaScript Error subclass that overrides name and message with accessor +// pairs, as quickjs-wasi's JSException does. Writing `.name` or `.message` +// on an ordinary Error builds the Error property dispatchers, whose branch +// for this class calls the JavaScript setters with an untyped value. +class GuestException extends Error { + #name; + #message; + constructor(name, message) { + super(); + this.#name = name; + this.#message = message; + } + get name() { + return this.#name; + } + set name(v) { + this.#name = v; + } + get message() { + return this.#message; + } + set message(v) { + this.#message = `[${v}]`; + } +} + +const guest = new GuestException("GuestError", "boom"); +console.log(guest.name, guest.message, String(guest)); +guest.name = "Renamed"; +guest.message = "changed"; +console.log(guest.name, guest.message, String(guest)); + +const plain = new Error("plain"); +plain.name = "PlainName"; +plain.message = "plain message"; +console.log(plain.name, plain.message, String(plain)); + +/** @type {Error[]} */ +const errors = [plain, guest, new TypeError("bad")]; +for (const err of errors) console.log(String(err)); +try { + throw guest; +} catch (caught) { + console.log(caught instanceof GuestException, caught instanceof Error, String(caught)); +} diff --git a/tests/corpus/webassembly-feature-probe.js b/tests/corpus/webassembly-feature-probe.js new file mode 100644 index 000000000..7a164fd90 --- /dev/null +++ b/tests/corpus/webassembly-feature-probe.js @@ -0,0 +1,16 @@ +// @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). +function supportsWasm() { + return typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function"; +} + +async function instantiate(bytes, imports) { + const { instance } = await WebAssembly.instantiate(bytes, imports); + return instance.exports; +} + +const backend = process.argv.includes("--wasm") ? instantiate : null; +console.log("supports wasm:", supportsWasm()); +console.log("backend:", backend === null ? "javascript" : "wasm"); diff --git a/tests/corpus/webassembly-type-mentions.ts b/tests/corpus/webassembly-type-mentions.ts new file mode 100644 index 000000000..fbaec710e --- /dev/null +++ b/tests/corpus/webassembly-type-mentions.ts @@ -0,0 +1,22 @@ +// Declarations that mention the WebAssembly API's types compile: the types +// have the checked-dynamic representation, and only a reached use of the +// API itself is refused. typeof needs no value and folds to Node's answer. +interface LoaderOptions { + wasm?: BufferSource | WebAssembly.Module; + imports?: WebAssembly.Imports; + memory?: WebAssembly.Memory; +} + +function describe(name: string, options: LoaderOptions): string { + const parts = [name]; + parts.push(options.wasm === undefined ? "no module" : "module given"); + parts.push(options.imports === undefined ? "no imports" : "imports given"); + return parts.join(", "); +} + +console.log(describe("empty", {})); +console.log(describe("bytes", { wasm: new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0]) })); +console.log(typeof WebAssembly, typeof globalThis.WebAssembly); +console.log(typeof WebAssembly.compile, typeof WebAssembly.instantiate, typeof WebAssembly.validate); +console.log(typeof WebAssembly.Module, typeof WebAssembly.Instance, typeof WebAssembly.Memory); +console.log(typeof WebAssembly.RuntimeError, typeof WebAssembly.CompileError); diff --git a/tests/coverage-fixtures/wasm/add.wasm b/tests/coverage-fixtures/wasm/add.wasm new file mode 100644 index 000000000..357f72da7 Binary files /dev/null and b/tests/coverage-fixtures/wasm/add.wasm differ diff --git a/tests/coverage-fixtures/wasm/build/generated.wasm b/tests/coverage-fixtures/wasm/build/generated.wasm new file mode 100644 index 000000000..3697e05bc Binary files /dev/null and b/tests/coverage-fixtures/wasm/build/generated.wasm differ diff --git a/tests/coverage-fixtures/wasm/glue.js b/tests/coverage-fixtures/wasm/glue.js new file mode 100644 index 000000000..631560632 --- /dev/null +++ b/tests/coverage-fixtures/wasm/glue.js @@ -0,0 +1,18 @@ +import { existsSync } from "node:fs"; + +// (module (func (export "answer") (result i32) i32.const 42)), inlined the +// way undici inlines llhttp. +const ANSWER = "AGFzbQEAAAABBQFgAAF/AwIBAAcKAQZhbnN3ZXIAAAoGAQQAQSoL"; + +export function hasModule() { + return existsSync(new URL("./add.wasm", import.meta.url).pathname); +} + +export function inlineModule() { + return ANSWER; +} + +export async function instantiate(bytes) { + const { instance } = await WebAssembly.instantiate(bytes, {}); + return instance.exports; +} diff --git a/tests/coverage-fixtures/wasm/main.ts b/tests/coverage-fixtures/wasm/main.ts new file mode 100644 index 000000000..a2d80b6b3 --- /dev/null +++ b/tests/coverage-fixtures/wasm/main.ts @@ -0,0 +1,9 @@ +// 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"; +import { describeModule } from "wasm-fixture-pkg"; + +console.log(hasModule(), inlineModule().length, describeModule()); diff --git a/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.d.ts b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.d.ts new file mode 100644 index 000000000..2de8deed5 --- /dev/null +++ b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.d.ts @@ -0,0 +1 @@ +export declare function describeModule(path?: string): string; diff --git a/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.js b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.js new file mode 100644 index 000000000..ecb29cd32 --- /dev/null +++ b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/index.js @@ -0,0 +1,6 @@ +// Loads lib/core.wasm from a path computed at run time, so only the +// package scan finds the module. +export function describeModule(path) { + const where = path ?? "lib/core.wasm"; + return typeof WebAssembly === "object" ? `wasm at ${where}` : "no wasm"; +} diff --git a/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm new file mode 100644 index 000000000..dd711f095 Binary files /dev/null and b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm differ diff --git a/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/package.json b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/package.json new file mode 100644 index 000000000..af753b539 --- /dev/null +++ b/tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/package.json @@ -0,0 +1,7 @@ +{ + "name": "wasm-fixture-pkg", + "version": "1.0.0", + "type": "module", + "main": "index.js", + "types": "index.d.ts" +} diff --git a/tests/coverage-fixtures/wasm/package.json b/tests/coverage-fixtures/wasm/package.json new file mode 100644 index 000000000..a68fcd213 --- /dev/null +++ b/tests/coverage-fixtures/wasm/package.json @@ -0,0 +1,8 @@ +{ + "name": "wasm-coverage-fixture", + "private": true, + "type": "module", + "scriptc": { + "wasm": ["build/generated.wasm"] + } +} diff --git a/tests/diagnostics/collection-iterator-helpers.ts b/tests/diagnostics/collection-iterator-helpers.ts index 9d264ec51..127b5c64b 100644 --- a/tests/diagnostics/collection-iterator-helpers.ts +++ b/tests/diagnostics/collection-iterator-helpers.ts @@ -1,10 +1,9 @@ -// Stored collection cursors support next/iteration, but helper methods are -// refused explicitly instead of dispatching to array helpers at runtime. -const map = new Map(); -const values = map.values(); -values.map(value => value + 1); -map.keys().toArray(); -const set = new Set(); -set.values().filter(value => value > 0); -set.entries().take(1); +// Iterator helpers lower over Map/Set iterators, generators and array +// iterators. These helper forms are refused explicitly. +const set = new Set([1, 2]); +// flatMap callbacks return arrays or generators. +set.values().flatMap((value) => new Set([value, value + 1])); +// return() on a helper object. +const mapped = set.values().map((value) => value * 2); +mapped.return!(); // Each helper call must produce a diagnostic. diff --git a/tests/diagnostics/local-class-boundaries.ts b/tests/diagnostics/local-class-boundaries.ts index 5b509931d..a82dfb869 100644 --- a/tests/diagnostics/local-class-boundaries.ts +++ b/tests/diagnostics/local-class-boundaries.ts @@ -7,8 +7,4 @@ privateBrand(); selfName(); derived(); generic(); -function genericFactory(value: T) { - return class Stored { read(): T { return value; } }; -} -genericFactory(7); // End of unsupported local-class forms. diff --git a/tests/diagnostics/overloaded-members.ts b/tests/diagnostics/overloaded-members.ts new file mode 100644 index 000000000..07ffa9b63 --- /dev/null +++ b/tests/diagnostics/overloaded-members.ts @@ -0,0 +1,25 @@ +// Overloaded interface members compile as one stored function whose type +// joins the overloads; calls resolve per site. Two fences remain: reading +// the member as a VALUE (its type is still the overload set), and a set +// whose overloads do not join (here, a rest parameter beside a fixed one). +interface Api { + on(event: "a", handler: (x: number) => void): void; + on(event: "b", handler: (x: string) => void): void; +} +const api: Api = { + on(event: string, handler: (x: any) => void): void { + handler(event === "a" ? 1 : "one"); + }, +}; +api.on("a", (x) => console.log(x + 1)); +const detached = api.on; +console.log(typeof detached); + +interface Emitter { + emit(event: "many", ...values: number[]): void; + emit(event: "one", value: string): void; +} +function fire(e: Emitter): void { + e.emit("many", 1, 2); +} +console.log(typeof fire); diff --git a/tests/diagnostics/webassembly-fences.ts b/tests/diagnostics/webassembly-fences.ts new file mode 100644 index 000000000..56b2991de --- /dev/null +++ b/tests/diagnostics/webassembly-fences.ts @@ -0,0 +1,30 @@ +// 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)); + 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); +} + +// 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])); diff --git a/tests/fixtures/npm-static/deep-packages-cli.ts b/tests/fixtures/npm-static/deep-packages-cli.ts new file mode 100644 index 000000000..9b10fdf46 --- /dev/null +++ b/tests/fixtures/npm-static/deep-packages-cli.ts @@ -0,0 +1,3 @@ +import { depth } from "hop-1"; + +console.log(depth()); diff --git a/tests/fixtures/npm-static/dup-install-cli.ts b/tests/fixtures/npm-static/dup-install-cli.ts new file mode 100644 index 000000000..346be854d --- /dev/null +++ b/tests/fixtures/npm-static/dup-install-cli.ts @@ -0,0 +1,4 @@ +import { left } from "dup-left"; +import { right } from "dup-right"; + +console.log(left(), left(), right(), left()); diff --git a/tests/fixtures/npm-static/node_modules/dup-left/index.d.ts b/tests/fixtures/npm-static/node_modules/dup-left/index.d.ts new file mode 100644 index 000000000..f3363e894 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-left/index.d.ts @@ -0,0 +1 @@ +export declare function left(): number; diff --git a/tests/fixtures/npm-static/node_modules/dup-left/index.js b/tests/fixtures/npm-static/node_modules/dup-left/index.js new file mode 100644 index 000000000..ef32a8a0a --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-left/index.js @@ -0,0 +1,5 @@ +const leaf = require("dup-leaf"); +function left() { + return leaf.tick(); +} +exports.left = left; diff --git a/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/index.js b/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/index.js new file mode 100644 index 000000000..9246c7839 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/index.js @@ -0,0 +1,6 @@ +let calls = 0; +function tick() { + calls += 1; + return calls; +} +exports.tick = tick; diff --git a/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/package.json b/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/package.json new file mode 100644 index 000000000..f01a0c08f --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-left/node_modules/dup-leaf/package.json @@ -0,0 +1,5 @@ +{ + "name": "dup-leaf", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/dup-left/package.json b/tests/fixtures/npm-static/node_modules/dup-left/package.json new file mode 100644 index 000000000..feab6391f --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-left/package.json @@ -0,0 +1,5 @@ +{ + "name": "dup-left", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/dup-right/index.d.ts b/tests/fixtures/npm-static/node_modules/dup-right/index.d.ts new file mode 100644 index 000000000..51ed905a7 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-right/index.d.ts @@ -0,0 +1 @@ +export declare function right(): number; diff --git a/tests/fixtures/npm-static/node_modules/dup-right/index.js b/tests/fixtures/npm-static/node_modules/dup-right/index.js new file mode 100644 index 000000000..d0bba85ad --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-right/index.js @@ -0,0 +1,5 @@ +const leaf = require("dup-leaf"); +function right() { + return leaf.tick(); +} +exports.right = right; diff --git a/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/index.js b/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/index.js new file mode 100644 index 000000000..9246c7839 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/index.js @@ -0,0 +1,6 @@ +let calls = 0; +function tick() { + calls += 1; + return calls; +} +exports.tick = tick; diff --git a/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/package.json b/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/package.json new file mode 100644 index 000000000..f01a0c08f --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-right/node_modules/dup-leaf/package.json @@ -0,0 +1,5 @@ +{ + "name": "dup-leaf", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/dup-right/package.json b/tests/fixtures/npm-static/node_modules/dup-right/package.json new file mode 100644 index 000000000..9889f0261 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/dup-right/package.json @@ -0,0 +1,5 @@ +{ + "name": "dup-right", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-1/index.d.ts b/tests/fixtures/npm-static/node_modules/hop-1/index.d.ts new file mode 100644 index 000000000..4d0af9c97 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-1/index.d.ts @@ -0,0 +1 @@ +export declare function depth(): number; diff --git a/tests/fixtures/npm-static/node_modules/hop-1/index.js b/tests/fixtures/npm-static/node_modules/hop-1/index.js new file mode 100644 index 000000000..57fdb622e --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-1/index.js @@ -0,0 +1,5 @@ +const next = require("hop-2"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-1/package.json b/tests/fixtures/npm-static/node_modules/hop-1/package.json new file mode 100644 index 000000000..9dda7b293 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-1/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-1", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-10/index.js b/tests/fixtures/npm-static/node_modules/hop-10/index.js new file mode 100644 index 000000000..2fa002968 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-10/index.js @@ -0,0 +1,5 @@ +const next = require("hop-11"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-10/package.json b/tests/fixtures/npm-static/node_modules/hop-10/package.json new file mode 100644 index 000000000..624842847 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-10/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-10", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-11/index.js b/tests/fixtures/npm-static/node_modules/hop-11/index.js new file mode 100644 index 000000000..3af42d043 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-11/index.js @@ -0,0 +1,4 @@ +function depth() { + return 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-11/package.json b/tests/fixtures/npm-static/node_modules/hop-11/package.json new file mode 100644 index 000000000..258cf14d9 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-11/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-11", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-2/index.js b/tests/fixtures/npm-static/node_modules/hop-2/index.js new file mode 100644 index 000000000..d21c4aa70 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-2/index.js @@ -0,0 +1,5 @@ +const next = require("hop-3"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-2/package.json b/tests/fixtures/npm-static/node_modules/hop-2/package.json new file mode 100644 index 000000000..268f49b69 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-2/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-2", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-3/index.js b/tests/fixtures/npm-static/node_modules/hop-3/index.js new file mode 100644 index 000000000..83e9c2655 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-3/index.js @@ -0,0 +1,5 @@ +const next = require("hop-4"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-3/package.json b/tests/fixtures/npm-static/node_modules/hop-3/package.json new file mode 100644 index 000000000..68d73b9be --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-3/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-3", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-4/index.js b/tests/fixtures/npm-static/node_modules/hop-4/index.js new file mode 100644 index 000000000..e6af833de --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-4/index.js @@ -0,0 +1,5 @@ +const next = require("hop-5"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-4/package.json b/tests/fixtures/npm-static/node_modules/hop-4/package.json new file mode 100644 index 000000000..35987d11b --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-4/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-4", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-5/index.js b/tests/fixtures/npm-static/node_modules/hop-5/index.js new file mode 100644 index 000000000..e91733984 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-5/index.js @@ -0,0 +1,5 @@ +const next = require("hop-6"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-5/package.json b/tests/fixtures/npm-static/node_modules/hop-5/package.json new file mode 100644 index 000000000..45ee8a1bf --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-5/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-5", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-6/index.js b/tests/fixtures/npm-static/node_modules/hop-6/index.js new file mode 100644 index 000000000..c55749fc8 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-6/index.js @@ -0,0 +1,5 @@ +const next = require("hop-7"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-6/package.json b/tests/fixtures/npm-static/node_modules/hop-6/package.json new file mode 100644 index 000000000..e663924bd --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-6/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-6", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-7/index.js b/tests/fixtures/npm-static/node_modules/hop-7/index.js new file mode 100644 index 000000000..7438cec8d --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-7/index.js @@ -0,0 +1,5 @@ +const next = require("hop-8"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-7/package.json b/tests/fixtures/npm-static/node_modules/hop-7/package.json new file mode 100644 index 000000000..751f50e6c --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-7/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-7", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-8/index.js b/tests/fixtures/npm-static/node_modules/hop-8/index.js new file mode 100644 index 000000000..f60c54f01 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-8/index.js @@ -0,0 +1,5 @@ +const next = require("hop-9"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-8/package.json b/tests/fixtures/npm-static/node_modules/hop-8/package.json new file mode 100644 index 000000000..df486ce40 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-8/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-8", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/hop-9/index.js b/tests/fixtures/npm-static/node_modules/hop-9/index.js new file mode 100644 index 000000000..36861384c --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-9/index.js @@ -0,0 +1,5 @@ +const next = require("hop-10"); +function depth() { + return next.depth() + 1; +} +exports.depth = depth; diff --git a/tests/fixtures/npm-static/node_modules/hop-9/package.json b/tests/fixtures/npm-static/node_modules/hop-9/package.json new file mode 100644 index 000000000..5a6ffeb84 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/hop-9/package.json @@ -0,0 +1,5 @@ +{ + "name": "hop-9", + "version": "1.0.0", + "main": "index.js" +} diff --git a/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/build.js b/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/build.js new file mode 100644 index 000000000..a155b52d4 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/build.js @@ -0,0 +1,3 @@ +export default function build() { + return "node build"; +} diff --git a/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/index.js b/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/index.js new file mode 100644 index 000000000..1f79b2f93 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/split-node-types/dist-node/index.js @@ -0,0 +1,2 @@ +export { default as build } from "./build.js"; +export const NIL = "node"; diff --git a/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.d.ts b/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.d.ts new file mode 100644 index 000000000..47272b882 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.d.ts @@ -0,0 +1,2 @@ +export declare function build(): string; +export declare const NIL: string; diff --git a/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.js b/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.js new file mode 100644 index 000000000..308044e34 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/split-node-types/dist/index.js @@ -0,0 +1,4 @@ +export function build() { + return "browser build"; +} +export const NIL = "browser"; diff --git a/tests/fixtures/npm-static/node_modules/split-node-types/package.json b/tests/fixtures/npm-static/node_modules/split-node-types/package.json new file mode 100644 index 000000000..aaa29cebc --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/split-node-types/package.json @@ -0,0 +1,16 @@ +{ + "name": "split-node-types", + "version": "1.0.0", + "type": "module", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "node": { + "types": "./dist/index.d.ts", + "default": "./dist-node/index.js" + }, + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + } +} diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/index.js b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/index.js new file mode 100644 index 000000000..aacc3bcce --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/index.js @@ -0,0 +1,6 @@ +"use strict"; +const domain = require("./src/domain.js"); +function getDomain(host) { + return domain.lastTwo(host); +} +exports.getDomain = getDomain; diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/src/domain.js b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/src/domain.js new file mode 100644 index 000000000..98b461afa --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/cjs/src/domain.js @@ -0,0 +1,5 @@ +"use strict"; +function lastTwo(host) { + return host.split(".").slice(-2).join("."); +} +exports.lastTwo = lastTwo; diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/dist/types/index.d.ts b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/types/index.d.ts new file mode 100644 index 000000000..dac3eccb0 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/dist/types/index.d.ts @@ -0,0 +1 @@ +export declare function getDomain(host: string): string; diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/index.ts b/tests/fixtures/npm-static/node_modules/ts-root-source/index.ts new file mode 100644 index 000000000..de03041f8 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/index.ts @@ -0,0 +1 @@ +export { getDomain } from "./src/domain"; diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/package.json b/tests/fixtures/npm-static/node_modules/ts-root-source/package.json new file mode 100644 index 000000000..edfff933b --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/package.json @@ -0,0 +1,7 @@ +{ + "name": "ts-root-source", + "version": "1.0.0", + "main": "dist/cjs/index.js", + "module": "dist/es6/index.js", + "types": "dist/types/index.d.ts" +} diff --git a/tests/fixtures/npm-static/node_modules/ts-root-source/src/domain.ts b/tests/fixtures/npm-static/node_modules/ts-root-source/src/domain.ts new file mode 100644 index 000000000..fe1e5eb18 --- /dev/null +++ b/tests/fixtures/npm-static/node_modules/ts-root-source/src/domain.ts @@ -0,0 +1,3 @@ +export function getDomain(host: string): string { + return "TypeScript source: " + host; +} diff --git a/tests/fixtures/npm-static/split-node-types-cli.ts b/tests/fixtures/npm-static/split-node-types-cli.ts new file mode 100644 index 000000000..ecfac96ba --- /dev/null +++ b/tests/fixtures/npm-static/split-node-types-cli.ts @@ -0,0 +1,3 @@ +import { build, NIL } from "split-node-types"; + +console.log(build(), NIL); diff --git a/tests/fixtures/npm-static/ts-root-source-cli.ts b/tests/fixtures/npm-static/ts-root-source-cli.ts new file mode 100644 index 000000000..3741b48e5 --- /dev/null +++ b/tests/fixtures/npm-static/ts-root-source-cli.ts @@ -0,0 +1,3 @@ +import { getDomain } from "ts-root-source"; + +console.log(getDomain("a.b.github.io")); diff --git a/tests/harness/__snapshots__/collection-iterator-helpers.ts.txt b/tests/harness/__snapshots__/collection-iterator-helpers.ts.txt index b6996b3c1..87470b621 100644 --- a/tests/harness/__snapshots__/collection-iterator-helpers.ts.txt +++ b/tests/harness/__snapshots__/collection-iterator-helpers.ts.txt @@ -1,35 +1,17 @@ -collection-iterator-helpers.ts:5:1 - error SC2020: 'collection iterator .map()' is part of the standard library types but has no scriptc lowering yet +collection-iterator-helpers.ts:5:22 - error SC2020: '.flatMap over a callback returning 'Set'' is part of the standard library types but has no scriptc lowering yet - 4 | const values = map.values(); - 5 | values.map(value => value + 1); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 6 | map.keys().toArray(); + 4 | // flatMap callbacks return arrays or generators. + 5 | set.values().flatMap((value) => new Set([value, value + 1])); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 6 | // return() on a helper object. - hint: stored Map/Set iterators support .next() and iteration; iterator helper methods have no lowering + hint: callbacks returning an array or a generator are the supported forms -collection-iterator-helpers.ts:6:1 - error SC2020: 'collection iterator .toArray()' is part of the standard library types but has no scriptc lowering yet +collection-iterator-helpers.ts:8:1 - error SC2020: 'IteratorObject.return' is part of the standard library types but has no scriptc lowering yet - 5 | values.map(value => value + 1); - 6 | map.keys().toArray(); - | ^~~~~~~~~~~~~~~~~~~~ - 7 | const set = new Set(); + 7 | const mapped = set.values().map((value) => value * 2); + 8 | mapped.return!(); + | ^~~~~~~~~~~~~ + 9 | // Each helper call must produce a diagnostic. - hint: stored Map/Set iterators support .next() and iteration; iterator helper methods have no lowering - -collection-iterator-helpers.ts:8:1 - error SC2020: 'collection iterator .filter()' is part of the standard library types but has no scriptc lowering yet - - 7 | const set = new Set(); - 8 | set.values().filter(value => value > 0); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 9 | set.entries().take(1); - - hint: stored Map/Set iterators support .next() and iteration; iterator helper methods have no lowering - -collection-iterator-helpers.ts:9:1 - error SC2020: 'collection iterator .take()' is part of the standard library types but has no scriptc lowering yet - - 8 | set.values().filter(value => value > 0); - 9 | set.entries().take(1); - | ^~~~~~~~~~~~~~~~~~~~~ - 10 | // Each helper call must produce a diagnostic. - - hint: stored Map/Set iterators support .next() and iteration; iterator helper methods have no lowering \ No newline at end of file + hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations) \ No newline at end of file diff --git a/tests/harness/__snapshots__/coverage-wasm.txt b/tests/harness/__snapshots__/coverage-wasm.txt new file mode 100644 index 000000000..5b5bea36a --- /dev/null +++ b/tests/harness/__snapshots__/coverage-wasm.txt @@ -0,0 +1,31 @@ +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) + + npm package compilation: + wasm-fixture-pkg static + + WebAssembly modules: (found at build time; none compile to native code yet) + 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/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 + tests/coverage-fixtures/wasm/build/generated.wasm 43 bytes uses simd + 1 function, 0 imports, 0 exports + 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 diff --git a/tests/harness/__snapshots__/es2025-fences.ts.txt b/tests/harness/__snapshots__/es2025-fences.ts.txt index e2dc5f40f..d7eda27b6 100644 --- a/tests/harness/__snapshots__/es2025-fences.ts.txt +++ b/tests/harness/__snapshots__/es2025-fences.ts.txt @@ -43,15 +43,6 @@ es2025-fences.ts:22:16 - error SC2020: 'Atomics.waitAsync' is part of the standa hint: use integer load, store, exchange, compareExchange, add, sub, and, or, xor, wait or notify -es2025-fences.ts:25:7 - error SC2020: 'IteratorObject' is part of the standard library types but has no scriptc lowering yet - - 24 | // First-class iterator objects. - 25 | const it = Iterator.from([1, 2, 3].values()); - | ^~ - 26 | - - hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations) - es2025-fences.ts:25:12 - error SC2020: 'Iterator.from' is part of the standard library types but has no scriptc lowering yet 24 | // First-class iterator objects. @@ -59,7 +50,7 @@ es2025-fences.ts:25:12 - error SC2020: 'Iterator.from' is part of the standard l | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | - hint: first-class iterator objects have no lowering — iterator helpers compile as one chain on an array iterator, consumed in place: arr.values().map(f).take(n).toArray() + hint: iterator helpers apply directly to generators and to array, Map and Set iterators: arr.values().map(f).take(n).toArray() es2025-fences.ts:28:27 - error SC2020: 'Promise.try over a callback of type '(a: number, b?: number | undefined) => number' with 1 argument' is part of the standard library types but has no scriptc lowering yet diff --git a/tests/harness/__snapshots__/local-class-boundaries.ts.txt b/tests/harness/__snapshots__/local-class-boundaries.ts.txt index e3e27ad95..04dbc336c 100644 --- a/tests/harness/__snapshots__/local-class-boundaries.ts.txt +++ b/tests/harness/__snapshots__/local-class-boundaries.ts.txt @@ -16,11 +16,4 @@ local-class-boundaries.ts:5:29 - error SC1090: function-local classes with stati 4 | function derived() { return class extends Base {}; } 5 | function generic() { return class { read(value: T): T { return value; } }; } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 6 | privateBrand(); - -local-class-boundaries.ts:13:1 - error SC2001: values of type 'typeof Stored' cannot be compiled yet (supported: number, string, boolean, arrays, Maps, Sets, RegExp, read-only Date values, functions, classes, records, unions of those, and 'unknown') - - 12 | } - 13 | genericFactory(7); - | ^~~~~~~~~~~~~~~~~~~~~~~~~ - 14 | // End of unsupported local-class forms. \ No newline at end of file + 6 | privateBrand(); \ No newline at end of file diff --git a/tests/harness/__snapshots__/overloaded-members.ts.txt b/tests/harness/__snapshots__/overloaded-members.ts.txt new file mode 100644 index 000000000..17e608785 --- /dev/null +++ b/tests/harness/__snapshots__/overloaded-members.ts.txt @@ -0,0 +1,35 @@ +overloaded-members.ts:15:7 - error SC2007: values of type '{ (event: "a", handler: (x: number) => void): void; (event: "b", handler: (x: string) => void): void; }' cannot be compiled: the type declares multiple call signatures (overloads), and a compiled function value is always one concrete signature + + 14 | api.on("a", (x) => console.log(x + 1)); + 15 | const detached = api.on; + | ^~~~~~~~ + 16 | console.log(typeof detached); + + hint: annotate the slot with the ONE signature the program actually calls (e.g. '(x: number) => string'), or wrap the overloaded function in a single-signature arrow + +overloaded-members.ts:16:20 - error SC2004: uses of 'detached' inherit the blocker on its declaration + + 15 | const detached = api.on; + 16 | console.log(typeof detached); + | ^~~~~~~~ + 17 | + + hint: the declaration of 'detached' did not compile — fix the diagnostic reported there and these sites clear with it + +overloaded-members.ts:22:15 - error SC2009: values of type 'Emitter' cannot be compiled: the record shape is supported, but its member 'emit' is an overload set, and its overload 'emit(event: "many", ...values: number[]): void' has a rest parameter (an overload set stores one fixed-arity function) + + 21 | } + 22 | function fire(e: Emitter): void { + | ^ + 23 | e.emit("many", 1, 2); + + 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') + +overloaded-members.ts:25:20 - error SC2004: uses of 'fire' inherit the blocker on its declaration + + 24 | } + 25 | console.log(typeof fire); + | ^~~~ + 26 | + + hint: the declaration of 'fire' did not compile — fix the diagnostic reported there and these sites clear with it \ No newline at end of file diff --git a/tests/harness/__snapshots__/string-iterator-helpers.ts.txt b/tests/harness/__snapshots__/string-iterator-helpers.ts.txt index 4d9d1ad8d..ef768934e 100644 --- a/tests/harness/__snapshots__/string-iterator-helpers.ts.txt +++ b/tests/harness/__snapshots__/string-iterator-helpers.ts.txt @@ -1,12 +1,3 @@ -string-iterator-helpers.ts:3:7 - error SC2020: 'IteratorObject' is part of the standard library types but has no scriptc lowering yet - - 2 | // refused instead of failing at run time. - 3 | const upper = "abc"[Symbol.iterator]().map((c) => c.toUpperCase()); - | ^~~~~ - 4 | - - hint: the type checker sees the full standard library, but only the supported surface compiles (https://scriptc.dev/limitations) - string-iterator-helpers.ts:3:15 - error SC2020: 'StringIterator.map' is part of the standard library types but has no scriptc lowering yet 2 | // refused instead of failing at run time. @@ -14,4 +5,4 @@ string-iterator-helpers.ts:3:15 - error SC2020: 'StringIterator.map' is part of | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | - hint: iterator helpers lower on chains from arr.values() or arr.entries() that end in a terminal (toArray, forEach, reduce, some, every, find) — spread the string first: [...s].values() \ No newline at end of file + hint: iterator helpers lower on generators and on array, Map and Set iterators — spread the string first: [...s].values() \ No newline at end of file diff --git a/tests/harness/__snapshots__/webassembly-fences.ts.txt b/tests/harness/__snapshots__/webassembly-fences.ts.txt new file mode 100644 index 000000000..da38a2c57 --- /dev/null +++ b/tests/harness/__snapshots__/webassembly-fences.ts.txt @@ -0,0 +1,98 @@ +webassembly-fences.ts:10:15 - error SC2020: 'WebAssembly.validate' is not supported yet: scriptc does not compile WebAssembly modules to native code yet + + 9 | async function load(options: LoaderOptions, bytes: Uint8Array): Promise { + 10 | console.log(WebAssembly.validate(bytes)); + | ^~~~~~~~~~~~~~~~~~~~ + 11 | const module = await WebAssembly.compile(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:11:24 - error SC2020: 'WebAssembly.compile' is not supported yet: scriptc does not compile WebAssembly modules to native code yet + + 10 | console.log(WebAssembly.validate(bytes)); + 11 | const module = await WebAssembly.compile(bytes); + | ^~~~~~~~~~~~~~~~~~~ + 12 | const { instance } = await WebAssembly.instantiate(bytes, options.imports); + + 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:12:30 - error SC2020: 'WebAssembly.instantiate' is not supported yet: scriptc does not compile WebAssembly modules to native code yet + + 11 | const module = await WebAssembly.compile(bytes); + 12 | const { instance } = await WebAssembly.instantiate(bytes, options.imports); + | ^~~~~~~~~~~~~~~~~~~~~~~ + 13 | console.log(instance instanceof WebAssembly.Instance, module); + + 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 diff --git a/tests/harness/corpus-costs.json b/tests/harness/corpus-costs.json index 18147374d..a6222ef3d 100644 --- a/tests/harness/corpus-costs.json +++ b/tests/harness/corpus-costs.json @@ -2132,6 +2132,8 @@ "5905-array-from-async-generator.ts": 2750, "5906-array-from-async-generator-js.js": 2950, "5907-regex-groups-match-rows.ts": 3150, + "5908-iterator-helper-objects.ts": 6350, + "5909-iterator-helper-objects-js.js": 4850, "5910-set-prototype-of-primitive-object-kinds.ts": 2719, "5911-dyn-class-to-primitive.ts": 2850, "5912-dyn-class-conversion-methods.ts": 3251, @@ -2211,6 +2213,7 @@ "6042-regex-match-object-destructuring.ts": 3393, "6043-string-index-narrowed-union.ts": 2983, "605-closures-forward-capture-tdz.ts": 3277, + "6051-generic-class-factory-results.ts": 4363, "6100-record-get-or-create.ts": 3771, "6101-record-get-or-create-unchecked/main.ts": 2107, "6103-typeof-builtin-bindings.cjs": 2202, @@ -2224,6 +2227,13 @@ "6143-cjs-require-json/main.js": 3245, "6144-cjs-require-builtin-nested/main.js": 2181, "6145-cjs-require-cycle/main.js": 3507, + "6150-cjs-inline-require/main.js": 4200, + "6151-cjs-export-chains/main.js": 3000, + "6152-cjs-tsc-interop/main.js": 2600, + "6153-cjs-exports-object/main.js": 2400, + "6154-cjs-require-nested-destructure/main.js": 2800, + "6155-cjs-export-table-methods/main.js": 2600, + "6156-cjs-function-members-from-ts/main.ts": 3000, "700-classes-basic.ts": 2530, "701-classes-composition.ts": 2357, "702-classes-this-capture.ts": 2140, @@ -5172,6 +5182,8 @@ "5905-array-from-async-generator.ts": 3500, "5906-array-from-async-generator-js.js": 3750, "5907-regex-groups-match-rows.ts": 3750, + "5908-iterator-helper-objects.ts": 5950, + "5909-iterator-helper-objects-js.js": 3750, "5910-set-prototype-of-primitive-object-kinds.ts": 5033, "5911-dyn-class-to-primitive.ts": 4732, "5912-dyn-class-conversion-methods.ts": 4424, @@ -5251,6 +5263,7 @@ "6042-regex-match-object-destructuring.ts": 3091, "6043-string-index-narrowed-union.ts": 3627, "605-closures-forward-capture-tdz.ts": 4638, + "6051-generic-class-factory-results.ts": 46581, "6100-record-get-or-create.ts": 3173, "6101-record-get-or-create-unchecked/main.ts": 3228, "6103-typeof-builtin-bindings.cjs": 1796, @@ -5264,6 +5277,13 @@ "6143-cjs-require-json/main.js": 3050, "6144-cjs-require-builtin-nested/main.js": 3329, "6145-cjs-require-cycle/main.js": 4761, + "6150-cjs-inline-require/main.js": 9600, + "6151-cjs-export-chains/main.js": 7000, + "6152-cjs-tsc-interop/main.js": 6000, + "6153-cjs-exports-object/main.js": 5600, + "6154-cjs-require-nested-destructure/main.js": 6400, + "6155-cjs-export-table-methods/main.js": 6000, + "6156-cjs-function-members-from-ts/main.ts": 7000, "700-classes-basic.ts": 2674, "701-classes-composition.ts": 2606, "702-classes-this-capture.ts": 2403, diff --git a/tests/harness/coverage.test.ts b/tests/harness/coverage.test.ts index 420651418..f1347bf23 100644 --- a/tests/harness/coverage.test.ts +++ b/tests/harness/coverage.test.ts @@ -43,6 +43,36 @@ 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. + await expect(report(fixture("wasm/main.ts"))).toMatchFileSnapshot( + "__snapshots__/coverage-wasm.txt", + ); + const { coverage } = analyze(fixture("wasm/main.ts"), { wasm: [fixture("wasm/add.wasm")] }); + const modules = coverage.wasmModules ?? []; + expect( + modules.map((m) => [ + m.path?.replace(repoRoot + "/", "") ?? "inline", + m.status, + m.unsupported, + m.sources.map((s) => s.kind), + ]), + ).toEqual([ + ["inline", "valid", [], ["inline"]], + ["tests/coverage-fixtures/wasm/add.wasm", "valid", [], ["path", "config"]], + [ + "tests/coverage-fixtures/wasm/node_modules/wasm-fixture-pkg/lib/core.wasm", + "invalid", + [], + ["package"], + ], + ["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]); +}); + test("divergences report as warnings, never as blockers", async () => { const { coverage } = analyze(fixture("divergences.ts")); expect(coverage.diagnostics).toEqual([]); diff --git a/tests/harness/deadstrip.test.ts b/tests/harness/deadstrip.test.ts index 7db7ec404..1baa92ac9 100644 --- a/tests/harness/deadstrip.test.ts +++ b/tests/harness/deadstrip.test.ts @@ -1,5 +1,6 @@ /* Reachability's build contract — scriptc-only, deliberately NOT - * differential: + * differential (tests/corpus/6170-flight-dev-stacks-dead pins statement-level + * reachability differentially; here its emitted LLVM is grepped): * * - The dead-strip side (a program importing a module whose UNUSED exports * hold rejected constructs must build and run) is covered differentially @@ -49,6 +50,36 @@ test("unreached bodies leave no trace in the emitted LLVM", async () => { } }); +test("statements after an abrupt statement leave no trace and no stack frames", async () => { + const outDir = join(cacheDir, `deadstrip-abrupt${sanitize ? "-san" : ""}`); + const result = await compile(join(repoRoot, "tests/corpus/6170-flight-dev-stacks-dead.ts"), { + outPath: join(outDir, "program"), + outDir, + sanitize, + backend: "llvm", + }); + if (!result.ok) { + throw new Error(result.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n")); + } + const c = readFileSync(result.llvmPath, "utf8"); + for (const reached of ["outlineComponentInfo", "emitOutlinedDebugModelChunk", "renderModel"]) { + expect(c, `expected reached '${reached}' in the emitted LLVM`).toContain(reached); + } + // The development-only stack parser is referenced only after the + // production stubs' throw: none of it is emitted, and the program keeps + // no source frames (its only stack read never runs). + for (const gone of [ + "parseStackTrace", + "collectStackTrace", + "getMethodCallName", + "renderDebugModel", + ]) { + expect(c, `unreached '${gone}' must leave no trace in the emitted LLVM`).not.toContain(gone); + } + expect(c).not.toContain("source_frame"); + expect(c).not.toContain("scr_stack_enter"); +}); + /** Compiles an in-repo fixture and returns its diagnostics codes+messages. * Deliberately NO backend pin: every program here fails during lowering, * before any backend runs — the default is irrelevant by construction, and diff --git a/tests/harness/errors.test.ts b/tests/harness/errors.test.ts index 51f04d310..564d53bc3 100644 --- a/tests/harness/errors.test.ts +++ b/tests/harness/errors.test.ts @@ -972,7 +972,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () `(function () { var root = this; console.log("before"); - console.log(root === module.exports); + console.log(root === eval("this")); console.log("after"); }).call(this); `, @@ -983,7 +983,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () "speculative-apply", `(function () { console.log("before"); - console.log(typeof module.exports); + console.log(typeof eval("1")); }).apply(null, []); `, "before\n", @@ -994,7 +994,7 @@ describe("refused statements in speculatively lowered JavaScript functions", () `class Base {} class Derived extends (function () { console.log("before"); - console.log(typeof module.exports); + console.log(typeof eval("1")); return Base; })() {} console.log(typeof Derived); @@ -1008,8 +1008,88 @@ console.log(typeof Derived); expect(r.stdout).toBe(stdout); expect(r.stderr).toMatch( new RegExp( - `^Uncaught Error: 'module\\.exports' is part of the standard library types but has no scriptc lowering yet \\[SC2020 at .*${name}\\.cjs:${line}\\]\\n$`, + `^Uncaught Error: values of type '\\(x: string\\) => any' cannot be compiled: .* \\[SC2009 at .*${name}\\.cjs:${line}\\]\\n$`, ), ); }); }); + +// CommonJS forms around the module's exports that keep a refusal name the +// construct itself (they used to report an unlowerable `require` value, a +// "binding form with no lowering", or the ES-module `module` message). +describe("CommonJS export-object and inline require refusals", () => { + test.each([ + [ + "exports-as-argument", + `exports.x = 1; +function keys(o) { + return Object.keys(o); +} +console.log("before"); +console.log(keys(exports)); +`, + {}, + "before\n", + 6, + "'exports' as a value other than a member access, comparison, typeof or truthiness test \\(the compiled exports are a static table, not an object: read exports\\.\\)", + ], + [ + "exports-rebinding", + `console.log("before"); +exports = module.exports = function hash(x) { + return x; +}; +exports.extra = 1; +`, + {}, + "before\n", + 2, + "rebinding 'exports' \\(exports = module\\.exports = value\\)", + ], + [ + "require-computed", + `const name = "./lib.cjs"; +console.log("before"); +console.log(require(name).x); +`, + { "lib.cjs": "exports.x = 1;\n" }, + "before\n", + 3, + "require\\(\\) with a computed specifier", + ], + [ + "exports-call-reads-this", + `exports.timeouts = function (n) { + return this.scale * n; +}; +exports.scale = 2; +console.log("before"); +console.log(exports.timeouts(3)); +`, + {}, + "before\n", + 6, + "calling 'exports\\.timeouts' through the module's exports object when the function may read 'this'", + ], + [ + "require-table-as-value", + `function count(o) { + return Object.keys(o).length; +} +console.log("before"); +console.log(count(require("./lib.cjs"))); +`, + { "lib.cjs": "exports.x = 1;\n" }, + "before\n", + 5, + "the exports object of '\\./lib\\.cjs' as a value", + ], + ] as const)("%s", async (name, source, extra, stdout, line, message) => { + const r = await compileAndRun(name, source, "cjs", extra); + expect(r.exitCode).toBe(1); + expect(r.stdout).toBe(stdout); + expect(r.stderr).toMatch( + new RegExp(`^Uncaught Error: ${message}.*\\[SC1090 at .*${name}\\.cjs:${line}\\]\\n$`), + ); + }); +}); diff --git a/tests/harness/npm-static.test.ts b/tests/harness/npm-static.test.ts index ba716076c..356d2fa6d 100644 --- a/tests/harness/npm-static.test.ts +++ b/tests/harness/npm-static.test.ts @@ -69,7 +69,7 @@ async function buildStatic(entry: string, npmStatic: string[] | "auto"): Promise const hash = createHash("sha256"); const inputs = [ entry, - ...globSync(join(pilotRoot, "**/node_modules/**/*.{js,mjs,cjs,json,d.ts}")).sort(), + ...globSync(join(pilotRoot, "**/node_modules/**/*.{js,mjs,cjs,json,ts}")).sort(), ...globSync( join(fixturesRoot, "commander-calc/node_modules/**/*.{js,mjs,cjs,json,d.ts}"), ).sort(), @@ -1061,6 +1061,40 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => { expect(nativeRes.exitCode).toBe(nodeRes.exitCode); }, 180_000); + // The two resolvers must answer one file for every opted-in edge. Each + // shape below once left the runtime file outside tsgo's program (SC2013 + // "did not join the type-checked program"): uuid's node condition with + // declarations in another tree, tldts's package-root TypeScript source + // beside `main`, express's same-version copies of one package (tsgo's + // package-id redirect), and get-intrinsic's dependency chain deeper than + // maxNodeModuleJsDepth. + test.each([ + ["split-node-types-cli.ts", ["split-node-types"]], + ["ts-root-source-cli.ts", ["ts-root-source"]], + ["dup-install-cli.ts", ["dup-left", "dup-right", "dup-leaf"]], + ["deep-packages-cli.ts", Array.from({ length: 11 }, (_, i) => `hop-${i + 1}`)], + ])( + "%s joins the type-checked program and matches Node", + async (name, pkgs) => { + const entry = join(pilotRoot, name); + const { coverage } = analyze(entry, { npmStatic: pkgs }); + expect(coverage.npmStatic.map((p) => [p.package, p.status]).sort()).toEqual( + pkgs.map((p) => [p, "static"]).sort(), + ); + expect(coverage.preflightFailed).toBe(false); + expect(coverage.diagnostics).toHaveLength(0); + const binary = await buildStatic(entry, pkgs); + const [nodeRes, nativeRes] = await Promise.all([ + runBinary("node", [entry]), + runBinary(binary, []), + ]); + expect(nativeRes.stdout).toEqual(nodeRes.stdout); + expect(comparableStderr(nativeRes.stderr)).toEqual(nodeRes.stderr); + expect(nativeRes.exitCode).toBe(nodeRes.exitCode); + }, + 180_000, + ); + test("recursive inferred JavaScript results retain their promised ABI", async () => { const entry = join(pilotRoot, "recursive-result-cli.ts"); const binary = await buildStatic(entry, ["recursive-result"]); diff --git a/tests/harness/npm.test.ts b/tests/harness/npm.test.ts index a6cdee2b5..136a58fcd 100644 --- a/tests/harness/npm.test.ts +++ b/tests/harness/npm.test.ts @@ -43,15 +43,15 @@ const KNOWN: Record = { "cjs-lexer-invisible": { build: "SC2013" }, "commander-calc": { run: "SC1090", argvs: [["--help"]] }, "commander-calc-async": { run: "SC1090", argvs: [["--help"]] }, - "create-require": { run: "SC2009" }, - "dotfolder": { run: "SC2009" }, + "create-require": { run: "SC1090" }, + "dotfolder": { run: "SC1090" }, "dual-package-kinds": { build: "SC2013" }, "dynamic-import": { build: "SC2012" }, "dynamic-import-local": { build: "SC2012" }, "esbuild-require": { build: "SC2013" }, "esm-missing-default": { build: "SC1090" }, "esm-missing-export": { build: "SC1090" }, - "fetch-destructure": { build: "SC1090" }, + "fetch-destructure": { run: "SC1031" }, "fs-shims": { run: "SC2020" }, "hoisted-workspace": { build: "SC2013" }, "import-refusal": { build: "SC2020" }, @@ -65,7 +65,7 @@ const KNOWN: Record = { "misc-shims": { build: "SC2013" }, "namespace": { build: "SC1013" }, "node24-async-events": { run: "SC2020" }, - "node24-commonjs-metadata": { run: "SC1090" }, + "node24-commonjs-metadata": { run: "SC2020" }, "node24-crypto-kdf": { run: "SC2020" }, "node24-deep-equality": { run: "SC2020" }, "node24-diagnostics-async": { run: "SC1090" },