WebAssembly: We should be able to postMessage a JSWebAssemblyModule
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Apr 2017 02:10:17 +0000 (02:10 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Apr 2017 02:10:17 +0000 (02:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170573

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch adds a callback to JSRunLoopTimer to notify
clients that a timer has been set. This is used inside
WorkerRunLoop in WebCore so that its RunLoop can perform
an iteration when it sees that a timer got set.

* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/JSRunLoopTimer.cpp:
(JSC::JSRunLoopTimer::scheduleTimer):
(JSC::JSRunLoopTimer::addTimerSetNotification):
(JSC::JSRunLoopTimer::removeTimerSetNotification):
* runtime/JSRunLoopTimer.h:
* wasm/WasmCodeBlock.cpp:
(JSC::Wasm::CodeBlock::~CodeBlock):
* wasm/WasmCodeBlock.h:
* wasm/WasmModule.cpp:
(JSC::Wasm::Module::~Module):
(JSC::Wasm::Module::signatureIndexFromFunctionIndexSpace):
(JSC::Wasm::makeValidationCallback):
(JSC::Wasm::Module::validateSync):
(JSC::Wasm::Module::validateAsync):
(JSC::Wasm::Module::validateSyncImpl): Deleted.
(JSC::Wasm::Module::makeValidationCallback): Deleted.
* wasm/WasmModule.h:
(JSC::Wasm::Module::validateSync): Deleted.
(JSC::Wasm::Module::validateAsync): Deleted.
(JSC::Wasm::Module::signatureIndexFromFunctionIndexSpace): Deleted.
(JSC::Wasm::Module::nonNullCodeBlock): Deleted.
* wasm/js/JSWebAssemblyCodeBlock.cpp:
(JSC::JSWebAssemblyCodeBlock::create):
* wasm/js/JSWebAssemblyCodeBlock.h:
(JSC::JSWebAssemblyCodeBlock::create): Deleted.
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::source):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::source): Deleted.
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyModulePrototype.cpp:

Source/WebCore:

This patch's main purpose is to implement postMessage of JSWebAssemblyModule.
The spec text describing the behavior is: https://github.com/WebAssembly/design/blob/master/JS.md#structured-clone-of-a-webassemblymodule
We only allow for JSWebAssemblyModule to be serialized in the postMessage
context. More work needs to be done to make it valid to store a module in
IndexDB.

All that is needed to serialize a JSWebAssemblyModule is grab a Ref
to its underlying Wasm::Module. So, when doing a postMessage, all we
do is grab this Ref, and then re-create the JSWebAssemblyModule from
the Wasm::Module in the new VM/global object. Because the code for
Wasm::Module is VM-independent, this is all that's needed. This turned
out nicely, because it requires little knowledge from WebCore about
what it means to clone a JSWebAssemblyModule.

The second significant part of this patch is teaching WorkerRunLoop about
the various timers inside JSC. Before, the WorkerRunLoop wouldn't always
wake up to address JSC timers. I noticed this bug when I was writing
tests to make sure that Wasm was running concurrently in different
workers. The bug is that the WorkerRunLoop's message queue has no insight
into a timer being scheduled. This effected the PromiseDeferredTimer that
Wasm uses, as well as the various GC timers that Heap uses. Now, WorkerRunLoop
will set itself up to be notified when timers are set. When a timer is
set, the WorkerRunLoop will perform an iteration to to reset its top
level MessageQueue timeout to be no longer than the next timer fire date.

Tests: storage/indexeddb/wasm-exceptions.html
       workers/wasm-hashset-many.html
       workers/wasm-hashset.html
       workers/wasm-long-compile-many.html
       workers/wasm-long-compile.html

* ForwardingHeaders/heap/GCActivityCallback.h: Added.
* ForwardingHeaders/runtime/JSRunLoopTimer.h: Added.
* ForwardingHeaders/runtime/PromiseDeferredTimer.h: Added.
* ForwardingHeaders/wasm: Added.
* ForwardingHeaders/wasm/js: Added.
* ForwardingHeaders/wasm/js/JSWebAssemblyModule.h: Added.
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
(WebCore::CloneSerializer::CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::deserialize):
(WebCore::CloneDeserializer::CloneDeserializer):
(WebCore::CloneDeserializer::readTerminal):
(WebCore::SerializedScriptValue::SerializedScriptValue):
(WebCore::SerializedScriptValue::create):
(WebCore::SerializedScriptValue::deserialize):
* bindings/js/SerializedScriptValue.h:
* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::addTimerSetNotification):
(WebCore::WorkerScriptController::removeTimerSetNotification):
* bindings/js/WorkerScriptController.h:
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):

LayoutTests:

* storage/indexeddb/resources/wasm-exceptions.js: Added.
(const._fail):
(const.isNotA.assert.isNotA):
(const):
(switch.typeof):
(Builder):
(Builder.prototype.setChecked):
(Builder.prototype.setPreamble):
(Builder.prototype._functionIndexSpaceKeyHash):
(Builder.prototype._registerFunctionToIndexSpace):
(Builder.prototype._getFunctionFromIndexSpace):
(Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.const.codeBuilder.End.switch.case.string_appeared_here.e):
(Builder.prototype._registerSectionBuilders.this.Unknown):
(prepareDatabase):
(testDatabase):
* storage/indexeddb/wasm-exceptions-expected.txt: Added.
* storage/indexeddb/wasm-exceptions.html: Added.
* workers/wasm-hashset: Added.
* workers/wasm-hashset-expected.txt: Added.
* workers/wasm-hashset-many-expected.txt: Added.
* workers/wasm-hashset-many.html: Added.
* workers/wasm-hashset.html: Added.
* workers/wasm-hashset/many-test.js: Added.
(reallyDone):
(console.log):
(console.error):
(console.assert):
(i.worker.onmessage):
(Module.print):
(Module.printErr):
(Module.canvas):
(Module.setStatus):
(Module):
(setValue):
(getValue):
(allocate):
(getMemory):
(Pointer_stringify):
(AsciiToString):
(stringToAscii):
(UTF8ArrayToString):
(UTF8ToString):
(stringToUTF8Array):
(stringToUTF8):
(lengthBytesUTF8):
(demangle):
(demangleAll):
(stackTrace):
(alignUp):
(updateGlobalBuffer):
(updateGlobalBufferViews):
(abortOnCannotGrowMemory):
(enlargeMemory):
(getTotalMemory):
(callRuntimeCallbacks):
(preRun):
(ensureInitRuntime):
(preMain):
(exitRuntime):
(postRun):
(addOnPreRun):
(addOnInit):
(addOnPreMain):
(addOnExit):
(addOnPostRun):
(intArrayFromString):
(intArrayToString):
(writeStringToMemory):
(writeArrayToMemory):
(writeAsciiToMemory):
(Math.string_appeared_here):
(addRunDependency):
(removeRunDependency):
(integrateWasmJS.asm2wasmImports.string_appeared_here):
(integrateWasmJS.lookupImport):
(integrateWasmJS.mergeMemory):
(integrateWasmJS.fixImports):
(integrateWasmJS.getBinary):
(integrateWasmJS.doJustAsm):
(integrateWasmJS.receiveInstance):
(integrateWasmJS.):
(integrateWasmJS.doNativeWasm):
(integrateWasmJS.doWasmPolyfill):
(integrateWasmJS.Module.string_appeared_here):
(integrateWasmJS):
(___setErrNo):
(__ZSt18uncaught_exceptionv):
(EXCEPTIONS.deAdjust):
(EXCEPTIONS.addRef):
(EXCEPTIONS.decRef):
(EXCEPTIONS.clearRef):
(___cxa_find_matching_catch):
(___gxx_personality_v0):
(___lock):
(_emscripten_memcpy_big):
(_gettimeofday):
(_abort):
(SYSCALLS):
(SYSCALLS.get getStr):
(SYSCALLS.get64):
(SYSCALLS.getZero):
(try.___syscall146.printChar):
(___syscall146):
(___syscall54):
(___unlock):
(___syscall6):
(invoke_ii):
(invoke_iiii):
(invoke_v):
(_malloc.Module.string_appeared_here):
(getTempRet0.Module.string_appeared_here):
(_free.Module.string_appeared_here):
(_main.Module.string_appeared_here):
(setTempRet0.Module.string_appeared_here):
(establishStackSpace.Module.string_appeared_here):
(stackSave.Module.string_appeared_here):
(_memset.Module.string_appeared_here):
(_sbrk.Module.string_appeared_here):
(_emscripten_get_global_libc.Module.string_appeared_here):
(_memcpy.Module.string_appeared_here):
(___errno_location.Module.string_appeared_here):
(setThrew.Module.string_appeared_here):
(_fflush.Module.string_appeared_here):
(stackAlloc.Module.string_appeared_here):
(stackRestore.Module.string_appeared_here):
(_llvm_bswap_i32.Module.string_appeared_here):
(runPostSets.Module.string_appeared_here):
(dynCall_ii.Module.string_appeared_here):
(dynCall_iiii.Module.string_appeared_here):
(dynCall_v.Module.string_appeared_here):
(else.applyMemoryInitializer):
(else):
(else.useRequest):
(ExitStatus):
(dependenciesFulfilled):
(Module.string_appeared_here.Module.callMain.callMain.pad):
(Module.string_appeared_here.Module.callMain):
(run.doRun):
(run):
(exit):
* workers/wasm-hashset/many-worker.js: Added.
(console.log):
(console.error):
(console.assert):
(Module.print):
(Module.printErr):
(Module.canvas):
(Module.setStatus):
(Module):
(setValue):
(getValue):
(allocate):
(getMemory):
(Pointer_stringify):
(AsciiToString):
(stringToAscii):
(UTF8ArrayToString):
(UTF8ToString):
(stringToUTF8Array):
(stringToUTF8):
(lengthBytesUTF8):
(demangle):
(demangleAll):
(stackTrace):
(alignUp):
(updateGlobalBuffer):
(updateGlobalBufferViews):
(abortOnCannotGrowMemory):
(enlargeMemory):
(getTotalMemory):
(callRuntimeCallbacks):
(preRun):
(ensureInitRuntime):
(preMain):
(exitRuntime):
(postRun):
(addOnPreRun):
(addOnInit):
(addOnPreMain):
(addOnExit):
(addOnPostRun):
(intArrayFromString):
(intArrayToString):
(writeStringToMemory):
(writeArrayToMemory):
(writeAsciiToMemory):
(Math.string_appeared_here):
(addRunDependency):
(removeRunDependency):
(integrateWasmJS.asm2wasmImports.string_appeared_here):
(integrateWasmJS.lookupImport):
(integrateWasmJS.mergeMemory):
(integrateWasmJS.fixImports):
(integrateWasmJS.getBinary):
(integrateWasmJS.doJustAsm):
(integrateWasmJS.receiveInstance):
(integrateWasmJS.doNativeWasm):
(integrateWasmJS.doWasmPolyfill):
(integrateWasmJS.Module.string_appeared_here):
(integrateWasmJS):
(___setErrNo):
(__ZSt18uncaught_exceptionv):
(EXCEPTIONS.deAdjust):
(EXCEPTIONS.addRef):
(EXCEPTIONS.decRef):
(EXCEPTIONS.clearRef):
(___cxa_find_matching_catch):
(___gxx_personality_v0):
(___lock):
(_emscripten_memcpy_big):
(_gettimeofday):
(_abort):
(SYSCALLS):
(SYSCALLS.get getStr):
(SYSCALLS.get64):
(SYSCALLS.getZero):
(try.___syscall146.printChar):
(___syscall146):
(___syscall54):
(___unlock):
(___syscall6):
(invoke_ii):
(invoke_iiii):
(invoke_v):
(_malloc.Module.string_appeared_here):
(getTempRet0.Module.string_appeared_here):
(_free.Module.string_appeared_here):
(_main.Module.string_appeared_here):
(setTempRet0.Module.string_appeared_here):
(establishStackSpace.Module.string_appeared_here):
(stackSave.Module.string_appeared_here):
(_memset.Module.string_appeared_here):
(_sbrk.Module.string_appeared_here):
(_emscripten_get_global_libc.Module.string_appeared_here):
(_memcpy.Module.string_appeared_here):
(___errno_location.Module.string_appeared_here):
(setThrew.Module.string_appeared_here):
(_fflush.Module.string_appeared_here):
(stackAlloc.Module.string_appeared_here):
(stackRestore.Module.string_appeared_here):
(_llvm_bswap_i32.Module.string_appeared_here):
(runPostSets.Module.string_appeared_here):
(dynCall_ii.Module.string_appeared_here):
(dynCall_iiii.Module.string_appeared_here):
(dynCall_v.Module.string_appeared_here):
(else.applyMemoryInitializer):
(else):
(else.useRequest):
(ExitStatus):
(dependenciesFulfilled):
(Module.string_appeared_here.Module.callMain.callMain.pad):
(Module.string_appeared_here.Module.callMain):
(run.doRun):
(run):
(exit):
* workers/wasm-hashset/test.js: Added.
(reallyDone):
(console.log):
(console.error):
(console.assert):
(Module.print):
(Module.printErr):
(Module.canvas):
(Module.setStatus):
(Module):
(setValue):
(getValue):
(allocate):
(getMemory):
(Pointer_stringify):
(AsciiToString):
(stringToAscii):
(UTF8ArrayToString):
(UTF8ToString):
(stringToUTF8Array):
(stringToUTF8):
(lengthBytesUTF8):
(demangle):
(demangleAll):
(stackTrace):
(alignUp):
(updateGlobalBuffer):
(updateGlobalBufferViews):
(abortOnCannotGrowMemory):
(enlargeMemory):
(getTotalMemory):
(callRuntimeCallbacks):
(preRun):
(ensureInitRuntime):
(preMain):
(exitRuntime):
(postRun):
(addOnPreRun):
(addOnInit):
(addOnPreMain):
(addOnExit):
(addOnPostRun):
(intArrayFromString):
(intArrayToString):
(writeStringToMemory):
(writeArrayToMemory):
(writeAsciiToMemory):
(Math.string_appeared_here):
(addRunDependency):
(removeRunDependency):
(integrateWasmJS.asm2wasmImports.string_appeared_here):
(integrateWasmJS.lookupImport):
(integrateWasmJS.mergeMemory):
(integrateWasmJS.fixImports):
(integrateWasmJS.getBinary):
(integrateWasmJS.doJustAsm):
(integrateWasmJS.receiveInstance):
(integrateWasmJS.doNativeWasm):
(integrateWasmJS.doWasmPolyfill):
(integrateWasmJS.Module.string_appeared_here):
(integrateWasmJS):
(___setErrNo):
(__ZSt18uncaught_exceptionv):
(EXCEPTIONS.deAdjust):
(EXCEPTIONS.addRef):
(EXCEPTIONS.decRef):
(EXCEPTIONS.clearRef):
(___cxa_find_matching_catch):
(___gxx_personality_v0):
(___lock):
(_emscripten_memcpy_big):
(_gettimeofday):
(_abort):
(SYSCALLS):
(SYSCALLS.get getStr):
(SYSCALLS.get64):
(SYSCALLS.getZero):
(try.___syscall146.printChar):
(___syscall146):
(___syscall54):
(___unlock):
(___syscall6):
(invoke_ii):
(invoke_iiii):
(invoke_v):
(_malloc.Module.string_appeared_here):
(getTempRet0.Module.string_appeared_here):
(_free.Module.string_appeared_here):
(_main.Module.string_appeared_here):
(setTempRet0.Module.string_appeared_here):
(establishStackSpace.Module.string_appeared_here):
(stackSave.Module.string_appeared_here):
(_memset.Module.string_appeared_here):
(_sbrk.Module.string_appeared_here):
(_emscripten_get_global_libc.Module.string_appeared_here):
(_memcpy.Module.string_appeared_here):
(___errno_location.Module.string_appeared_here):
(setThrew.Module.string_appeared_here):
(_fflush.Module.string_appeared_here):
(stackAlloc.Module.string_appeared_here):
(stackRestore.Module.string_appeared_here):
(_llvm_bswap_i32.Module.string_appeared_here):
(runPostSets.Module.string_appeared_here):
(dynCall_ii.Module.string_appeared_here):
(dynCall_iiii.Module.string_appeared_here):
(dynCall_v.Module.string_appeared_here):
(else.applyMemoryInitializer):
(else):
(else.useRequest):
(ExitStatus):
(dependenciesFulfilled):
(Module.string_appeared_here.Module.callMain.callMain.pad):
(Module.string_appeared_here.Module.callMain):
(run.doRun):
(run):
(exit):
* workers/wasm-hashset/worker.js: Added.
(console.log):
(console.error):
(console.assert):
(Module.print):
(Module.printErr):
(Module.canvas):
(Module.setStatus):
(Module):
(setValue):
(getValue):
(allocate):
(getMemory):
(Pointer_stringify):
(AsciiToString):
(stringToAscii):
(UTF8ArrayToString):
(UTF8ToString):
(stringToUTF8Array):
(stringToUTF8):
(lengthBytesUTF8):
(demangle):
(demangleAll):
(stackTrace):
(alignUp):
(updateGlobalBuffer):
(updateGlobalBufferViews):
(abortOnCannotGrowMemory):
(enlargeMemory):
(getTotalMemory):
(callRuntimeCallbacks):
(preRun):
(ensureInitRuntime):
(preMain):
(exitRuntime):
(postRun):
(addOnPreRun):
(addOnInit):
(addOnPreMain):
(addOnExit):
(addOnPostRun):
(intArrayFromString):
(intArrayToString):
(writeStringToMemory):
(writeArrayToMemory):
(writeAsciiToMemory):
(Math.string_appeared_here):
(addRunDependency):
(removeRunDependency):
(integrateWasmJS.asm2wasmImports.string_appeared_here):
(integrateWasmJS.lookupImport):
(integrateWasmJS.mergeMemory):
(integrateWasmJS.fixImports):
(integrateWasmJS.getBinary):
(integrateWasmJS.doJustAsm):
(integrateWasmJS.receiveInstance):
(integrateWasmJS.):
(integrateWasmJS.doNativeWasm):
(integrateWasmJS.doWasmPolyfill):
(integrateWasmJS.Module.string_appeared_here):
(integrateWasmJS):
(___setErrNo):
(__ZSt18uncaught_exceptionv):
(EXCEPTIONS.deAdjust):
(EXCEPTIONS.addRef):
(EXCEPTIONS.decRef):
(EXCEPTIONS.clearRef):
(___cxa_find_matching_catch):
(___gxx_personality_v0):
(___lock):
(_emscripten_memcpy_big):
(_gettimeofday):
(_abort):
(SYSCALLS):
(SYSCALLS.get getStr):
(SYSCALLS.get64):
(SYSCALLS.getZero):
(try.___syscall146.printChar):
(___syscall146):
(___syscall54):
(___unlock):
(___syscall6):
(invoke_ii):
(invoke_iiii):
(invoke_v):
(_malloc.Module.string_appeared_here):
(getTempRet0.Module.string_appeared_here):
(_free.Module.string_appeared_here):
(_main.Module.string_appeared_here):
(setTempRet0.Module.string_appeared_here):
(establishStackSpace.Module.string_appeared_here):
(stackSave.Module.string_appeared_here):
(_memset.Module.string_appeared_here):
(_sbrk.Module.string_appeared_here):
(_emscripten_get_global_libc.Module.string_appeared_here):
(_memcpy.Module.string_appeared_here):
(___errno_location.Module.string_appeared_here):
(setThrew.Module.string_appeared_here):
(_fflush.Module.string_appeared_here):
(stackAlloc.Module.string_appeared_here):
(stackRestore.Module.string_appeared_here):
(_llvm_bswap_i32.Module.string_appeared_here):
(runPostSets.Module.string_appeared_here):
(dynCall_ii.Module.string_appeared_here):
(dynCall_iiii.Module.string_appeared_here):
(dynCall_v.Module.string_appeared_here):
(else.applyMemoryInitializer):
(else):
(else.useRequest):
(ExitStatus):
(dependenciesFulfilled):
(Module.string_appeared_here.Module.callMain.callMain.pad):
(Module.string_appeared_here.Module.callMain):
(run.doRun):
(run):
(exit):
* workers/wasm-long-compile-expected.txt: Added.
* workers/wasm-long-compile-many-expected.txt: Added.
* workers/wasm-long-compile-many.html: Added.
* workers/wasm-long-compile.html: Added.
* workers/wasm-resources: Added.
* workers/wasm-resources/long-compile-many.js: Added.
(done):
(i.async.run):
(i.worker.onmessage):
* workers/wasm-resources/long-compile-worker.js: Added.
(const._fail):
(const.isNotA.assert.isNotA):
(const):
(switch.typeof):
(Builder):
(Builder.prototype.setChecked):
(Builder.prototype.setPreamble):
(Builder.prototype._functionIndexSpaceKeyHash):
(Builder.prototype._registerFunctionToIndexSpace):
(Builder.prototype._getFunctionFromIndexSpace):
(Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.const.codeBuilder.End.switch.case.string_appeared_here.e):
(Builder.prototype._registerSectionBuilders.this.Unknown):
* workers/wasm-resources/long-compile.js: Added.
(done):
(async.run):
(worker.onmessage):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215353 268f45cc-cd09-0410-ab3c-d52691b4dbfc

47 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/storage/indexeddb/resources/wasm-exceptions.js [new file with mode: 0644]
LayoutTests/storage/indexeddb/wasm-exceptions-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/wasm-exceptions.html [new file with mode: 0644]
LayoutTests/workers/wasm-hashset-expected.txt [new file with mode: 0644]
LayoutTests/workers/wasm-hashset-many-2-expected.txt [new file with mode: 0644]
LayoutTests/workers/wasm-hashset-many-2.html [new file with mode: 0644]
LayoutTests/workers/wasm-hashset-many-expected.txt [new file with mode: 0644]
LayoutTests/workers/wasm-hashset-many.html [new file with mode: 0644]
LayoutTests/workers/wasm-hashset.html [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/many-test-2.js [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/many-test.js [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/many-worker-2.js [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/test.js [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/test.wasm [new file with mode: 0644]
LayoutTests/workers/wasm-hashset/worker.js [new file with mode: 0644]
LayoutTests/workers/wasm-long-compile-expected.txt [new file with mode: 0644]
LayoutTests/workers/wasm-long-compile-many-expected.txt [new file with mode: 0644]
LayoutTests/workers/wasm-long-compile-many.html [new file with mode: 0644]
LayoutTests/workers/wasm-long-compile.html [new file with mode: 0644]
LayoutTests/workers/wasm-resources/long-compile-many.js [new file with mode: 0644]
LayoutTests/workers/wasm-resources/long-compile-worker.js [new file with mode: 0644]
LayoutTests/workers/wasm-resources/long-compile.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp
Source/JavaScriptCore/runtime/JSRunLoopTimer.h
Source/JavaScriptCore/wasm/WasmCodeBlock.cpp
Source/JavaScriptCore/wasm/WasmCodeBlock.h
Source/JavaScriptCore/wasm/WasmModule.cpp
Source/JavaScriptCore/wasm/WasmModule.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/heap/GCActivityCallback.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/runtime/JSRunLoopTimer.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/runtime/PromiseDeferredTimer.h [new file with mode: 0644]
Source/WebCore/ForwardingHeaders/wasm/js/JSWebAssemblyModule.h [new file with mode: 0644]
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/js/SerializedScriptValue.h
Source/WebCore/bindings/js/WorkerScriptController.cpp
Source/WebCore/bindings/js/WorkerScriptController.h
Source/WebCore/workers/WorkerRunLoop.cpp

index dd64ba9..1d2f6b5 100644 (file)
@@ -1,3 +1,526 @@
+2017-04-13  Saam Barati  <sbarati@apple.com>
+
+        WebAssembly: We should be able to postMessage a JSWebAssemblyModule
+        https://bugs.webkit.org/show_bug.cgi?id=170573
+
+        Reviewed by Filip Pizlo.
+
+        * storage/indexeddb/resources/wasm-exceptions.js: Added.
+        (const._fail):
+        (const.isNotA.assert.isNotA):
+        (const):
+        (switch.typeof):
+        (Builder):
+        (Builder.prototype.setChecked):
+        (Builder.prototype.setPreamble):
+        (Builder.prototype._functionIndexSpaceKeyHash):
+        (Builder.prototype._registerFunctionToIndexSpace):
+        (Builder.prototype._getFunctionFromIndexSpace):
+        (Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
+        (Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.const.codeBuilder.End.switch.case.string_appeared_here.e):
+        (Builder.prototype._registerSectionBuilders.this.Unknown):
+        (prepareDatabase):
+        (testDatabase):
+        * storage/indexeddb/wasm-exceptions-expected.txt: Added.
+        * storage/indexeddb/wasm-exceptions.html: Added.
+        * workers/wasm-hashset: Added.
+        * workers/wasm-hashset-expected.txt: Added.
+        * workers/wasm-hashset-many-expected.txt: Added.
+        * workers/wasm-hashset-many.html: Added.
+        * workers/wasm-hashset.html: Added.
+        * workers/wasm-hashset/many-test.js: Added.
+        (reallyDone):
+        (console.log):
+        (console.error):
+        (console.assert):
+        (i.worker.onmessage):
+        (Module.print):
+        (Module.printErr):
+        (Module.canvas):
+        (Module.setStatus):
+        (Module):
+        (setValue):
+        (getValue):
+        (allocate):
+        (getMemory):
+        (Pointer_stringify):
+        (AsciiToString):
+        (stringToAscii):
+        (UTF8ArrayToString):
+        (UTF8ToString):
+        (stringToUTF8Array):
+        (stringToUTF8):
+        (lengthBytesUTF8):
+        (demangle):
+        (demangleAll):
+        (stackTrace):
+        (alignUp):
+        (updateGlobalBuffer):
+        (updateGlobalBufferViews):
+        (abortOnCannotGrowMemory):
+        (enlargeMemory):
+        (getTotalMemory):
+        (callRuntimeCallbacks):
+        (preRun):
+        (ensureInitRuntime):
+        (preMain):
+        (exitRuntime):
+        (postRun):
+        (addOnPreRun):
+        (addOnInit):
+        (addOnPreMain):
+        (addOnExit):
+        (addOnPostRun):
+        (intArrayFromString):
+        (intArrayToString):
+        (writeStringToMemory):
+        (writeArrayToMemory):
+        (writeAsciiToMemory):
+        (Math.string_appeared_here):
+        (addRunDependency):
+        (removeRunDependency):
+        (integrateWasmJS.asm2wasmImports.string_appeared_here):
+        (integrateWasmJS.lookupImport):
+        (integrateWasmJS.mergeMemory):
+        (integrateWasmJS.fixImports):
+        (integrateWasmJS.getBinary):
+        (integrateWasmJS.doJustAsm):
+        (integrateWasmJS.receiveInstance):
+        (integrateWasmJS.):
+        (integrateWasmJS.doNativeWasm):
+        (integrateWasmJS.doWasmPolyfill):
+        (integrateWasmJS.Module.string_appeared_here):
+        (integrateWasmJS):
+        (___setErrNo):
+        (__ZSt18uncaught_exceptionv):
+        (EXCEPTIONS.deAdjust):
+        (EXCEPTIONS.addRef):
+        (EXCEPTIONS.decRef):
+        (EXCEPTIONS.clearRef):
+        (___cxa_find_matching_catch):
+        (___gxx_personality_v0):
+        (___lock):
+        (_emscripten_memcpy_big):
+        (_gettimeofday):
+        (_abort):
+        (SYSCALLS):
+        (SYSCALLS.get getStr):
+        (SYSCALLS.get64):
+        (SYSCALLS.getZero):
+        (try.___syscall146.printChar):
+        (___syscall146):
+        (___syscall54):
+        (___unlock):
+        (___syscall6):
+        (invoke_ii):
+        (invoke_iiii):
+        (invoke_v):
+        (_malloc.Module.string_appeared_here):
+        (getTempRet0.Module.string_appeared_here):
+        (_free.Module.string_appeared_here):
+        (_main.Module.string_appeared_here):
+        (setTempRet0.Module.string_appeared_here):
+        (establishStackSpace.Module.string_appeared_here):
+        (stackSave.Module.string_appeared_here):
+        (_memset.Module.string_appeared_here):
+        (_sbrk.Module.string_appeared_here):
+        (_emscripten_get_global_libc.Module.string_appeared_here):
+        (_memcpy.Module.string_appeared_here):
+        (___errno_location.Module.string_appeared_here):
+        (setThrew.Module.string_appeared_here):
+        (_fflush.Module.string_appeared_here):
+        (stackAlloc.Module.string_appeared_here):
+        (stackRestore.Module.string_appeared_here):
+        (_llvm_bswap_i32.Module.string_appeared_here):
+        (runPostSets.Module.string_appeared_here):
+        (dynCall_ii.Module.string_appeared_here):
+        (dynCall_iiii.Module.string_appeared_here):
+        (dynCall_v.Module.string_appeared_here):
+        (else.applyMemoryInitializer):
+        (else):
+        (else.useRequest):
+        (ExitStatus):
+        (dependenciesFulfilled):
+        (Module.string_appeared_here.Module.callMain.callMain.pad):
+        (Module.string_appeared_here.Module.callMain):
+        (run.doRun):
+        (run):
+        (exit):
+        * workers/wasm-hashset/many-worker.js: Added.
+        (console.log):
+        (console.error):
+        (console.assert):
+        (Module.print):
+        (Module.printErr):
+        (Module.canvas):
+        (Module.setStatus):
+        (Module):
+        (setValue):
+        (getValue):
+        (allocate):
+        (getMemory):
+        (Pointer_stringify):
+        (AsciiToString):
+        (stringToAscii):
+        (UTF8ArrayToString):
+        (UTF8ToString):
+        (stringToUTF8Array):
+        (stringToUTF8):
+        (lengthBytesUTF8):
+        (demangle):
+        (demangleAll):
+        (stackTrace):
+        (alignUp):
+        (updateGlobalBuffer):
+        (updateGlobalBufferViews):
+        (abortOnCannotGrowMemory):
+        (enlargeMemory):
+        (getTotalMemory):
+        (callRuntimeCallbacks):
+        (preRun):
+        (ensureInitRuntime):
+        (preMain):
+        (exitRuntime):
+        (postRun):
+        (addOnPreRun):
+        (addOnInit):
+        (addOnPreMain):
+        (addOnExit):
+        (addOnPostRun):
+        (intArrayFromString):
+        (intArrayToString):
+        (writeStringToMemory):
+        (writeArrayToMemory):
+        (writeAsciiToMemory):
+        (Math.string_appeared_here):
+        (addRunDependency):
+        (removeRunDependency):
+        (integrateWasmJS.asm2wasmImports.string_appeared_here):
+        (integrateWasmJS.lookupImport):
+        (integrateWasmJS.mergeMemory):
+        (integrateWasmJS.fixImports):
+        (integrateWasmJS.getBinary):
+        (integrateWasmJS.doJustAsm):
+        (integrateWasmJS.receiveInstance):
+        (integrateWasmJS.doNativeWasm):
+        (integrateWasmJS.doWasmPolyfill):
+        (integrateWasmJS.Module.string_appeared_here):
+        (integrateWasmJS):
+        (___setErrNo):
+        (__ZSt18uncaught_exceptionv):
+        (EXCEPTIONS.deAdjust):
+        (EXCEPTIONS.addRef):
+        (EXCEPTIONS.decRef):
+        (EXCEPTIONS.clearRef):
+        (___cxa_find_matching_catch):
+        (___gxx_personality_v0):
+        (___lock):
+        (_emscripten_memcpy_big):
+        (_gettimeofday):
+        (_abort):
+        (SYSCALLS):
+        (SYSCALLS.get getStr):
+        (SYSCALLS.get64):
+        (SYSCALLS.getZero):
+        (try.___syscall146.printChar):
+        (___syscall146):
+        (___syscall54):
+        (___unlock):
+        (___syscall6):
+        (invoke_ii):
+        (invoke_iiii):
+        (invoke_v):
+        (_malloc.Module.string_appeared_here):
+        (getTempRet0.Module.string_appeared_here):
+        (_free.Module.string_appeared_here):
+        (_main.Module.string_appeared_here):
+        (setTempRet0.Module.string_appeared_here):
+        (establishStackSpace.Module.string_appeared_here):
+        (stackSave.Module.string_appeared_here):
+        (_memset.Module.string_appeared_here):
+        (_sbrk.Module.string_appeared_here):
+        (_emscripten_get_global_libc.Module.string_appeared_here):
+        (_memcpy.Module.string_appeared_here):
+        (___errno_location.Module.string_appeared_here):
+        (setThrew.Module.string_appeared_here):
+        (_fflush.Module.string_appeared_here):
+        (stackAlloc.Module.string_appeared_here):
+        (stackRestore.Module.string_appeared_here):
+        (_llvm_bswap_i32.Module.string_appeared_here):
+        (runPostSets.Module.string_appeared_here):
+        (dynCall_ii.Module.string_appeared_here):
+        (dynCall_iiii.Module.string_appeared_here):
+        (dynCall_v.Module.string_appeared_here):
+        (else.applyMemoryInitializer):
+        (else):
+        (else.useRequest):
+        (ExitStatus):
+        (dependenciesFulfilled):
+        (Module.string_appeared_here.Module.callMain.callMain.pad):
+        (Module.string_appeared_here.Module.callMain):
+        (run.doRun):
+        (run):
+        (exit):
+        * workers/wasm-hashset/test.js: Added.
+        (reallyDone):
+        (console.log):
+        (console.error):
+        (console.assert):
+        (Module.print):
+        (Module.printErr):
+        (Module.canvas):
+        (Module.setStatus):
+        (Module):
+        (setValue):
+        (getValue):
+        (allocate):
+        (getMemory):
+        (Pointer_stringify):
+        (AsciiToString):
+        (stringToAscii):
+        (UTF8ArrayToString):
+        (UTF8ToString):
+        (stringToUTF8Array):
+        (stringToUTF8):
+        (lengthBytesUTF8):
+        (demangle):
+        (demangleAll):
+        (stackTrace):
+        (alignUp):
+        (updateGlobalBuffer):
+        (updateGlobalBufferViews):
+        (abortOnCannotGrowMemory):
+        (enlargeMemory):
+        (getTotalMemory):
+        (callRuntimeCallbacks):
+        (preRun):
+        (ensureInitRuntime):
+        (preMain):
+        (exitRuntime):
+        (postRun):
+        (addOnPreRun):
+        (addOnInit):
+        (addOnPreMain):
+        (addOnExit):
+        (addOnPostRun):
+        (intArrayFromString):
+        (intArrayToString):
+        (writeStringToMemory):
+        (writeArrayToMemory):
+        (writeAsciiToMemory):
+        (Math.string_appeared_here):
+        (addRunDependency):
+        (removeRunDependency):
+        (integrateWasmJS.asm2wasmImports.string_appeared_here):
+        (integrateWasmJS.lookupImport):
+        (integrateWasmJS.mergeMemory):
+        (integrateWasmJS.fixImports):
+        (integrateWasmJS.getBinary):
+        (integrateWasmJS.doJustAsm):
+        (integrateWasmJS.receiveInstance):
+        (integrateWasmJS.doNativeWasm):
+        (integrateWasmJS.doWasmPolyfill):
+        (integrateWasmJS.Module.string_appeared_here):
+        (integrateWasmJS):
+        (___setErrNo):
+        (__ZSt18uncaught_exceptionv):
+        (EXCEPTIONS.deAdjust):
+        (EXCEPTIONS.addRef):
+        (EXCEPTIONS.decRef):
+        (EXCEPTIONS.clearRef):
+        (___cxa_find_matching_catch):
+        (___gxx_personality_v0):
+        (___lock):
+        (_emscripten_memcpy_big):
+        (_gettimeofday):
+        (_abort):
+        (SYSCALLS):
+        (SYSCALLS.get getStr):
+        (SYSCALLS.get64):
+        (SYSCALLS.getZero):
+        (try.___syscall146.printChar):
+        (___syscall146):
+        (___syscall54):
+        (___unlock):
+        (___syscall6):
+        (invoke_ii):
+        (invoke_iiii):
+        (invoke_v):
+        (_malloc.Module.string_appeared_here):
+        (getTempRet0.Module.string_appeared_here):
+        (_free.Module.string_appeared_here):
+        (_main.Module.string_appeared_here):
+        (setTempRet0.Module.string_appeared_here):
+        (establishStackSpace.Module.string_appeared_here):
+        (stackSave.Module.string_appeared_here):
+        (_memset.Module.string_appeared_here):
+        (_sbrk.Module.string_appeared_here):
+        (_emscripten_get_global_libc.Module.string_appeared_here):
+        (_memcpy.Module.string_appeared_here):
+        (___errno_location.Module.string_appeared_here):
+        (setThrew.Module.string_appeared_here):
+        (_fflush.Module.string_appeared_here):
+        (stackAlloc.Module.string_appeared_here):
+        (stackRestore.Module.string_appeared_here):
+        (_llvm_bswap_i32.Module.string_appeared_here):
+        (runPostSets.Module.string_appeared_here):
+        (dynCall_ii.Module.string_appeared_here):
+        (dynCall_iiii.Module.string_appeared_here):
+        (dynCall_v.Module.string_appeared_here):
+        (else.applyMemoryInitializer):
+        (else):
+        (else.useRequest):
+        (ExitStatus):
+        (dependenciesFulfilled):
+        (Module.string_appeared_here.Module.callMain.callMain.pad):
+        (Module.string_appeared_here.Module.callMain):
+        (run.doRun):
+        (run):
+        (exit):
+        * workers/wasm-hashset/worker.js: Added.
+        (console.log):
+        (console.error):
+        (console.assert):
+        (Module.print):
+        (Module.printErr):
+        (Module.canvas):
+        (Module.setStatus):
+        (Module):
+        (setValue):
+        (getValue):
+        (allocate):
+        (getMemory):
+        (Pointer_stringify):
+        (AsciiToString):
+        (stringToAscii):
+        (UTF8ArrayToString):
+        (UTF8ToString):
+        (stringToUTF8Array):
+        (stringToUTF8):
+        (lengthBytesUTF8):
+        (demangle):
+        (demangleAll):
+        (stackTrace):
+        (alignUp):
+        (updateGlobalBuffer):
+        (updateGlobalBufferViews):
+        (abortOnCannotGrowMemory):
+        (enlargeMemory):
+        (getTotalMemory):
+        (callRuntimeCallbacks):
+        (preRun):
+        (ensureInitRuntime):
+        (preMain):
+        (exitRuntime):
+        (postRun):
+        (addOnPreRun):
+        (addOnInit):
+        (addOnPreMain):
+        (addOnExit):
+        (addOnPostRun):
+        (intArrayFromString):
+        (intArrayToString):
+        (writeStringToMemory):
+        (writeArrayToMemory):
+        (writeAsciiToMemory):
+        (Math.string_appeared_here):
+        (addRunDependency):
+        (removeRunDependency):
+        (integrateWasmJS.asm2wasmImports.string_appeared_here):
+        (integrateWasmJS.lookupImport):
+        (integrateWasmJS.mergeMemory):
+        (integrateWasmJS.fixImports):
+        (integrateWasmJS.getBinary):
+        (integrateWasmJS.doJustAsm):
+        (integrateWasmJS.receiveInstance):
+        (integrateWasmJS.):
+        (integrateWasmJS.doNativeWasm):
+        (integrateWasmJS.doWasmPolyfill):
+        (integrateWasmJS.Module.string_appeared_here):
+        (integrateWasmJS):
+        (___setErrNo):
+        (__ZSt18uncaught_exceptionv):
+        (EXCEPTIONS.deAdjust):
+        (EXCEPTIONS.addRef):
+        (EXCEPTIONS.decRef):
+        (EXCEPTIONS.clearRef):
+        (___cxa_find_matching_catch):
+        (___gxx_personality_v0):
+        (___lock):
+        (_emscripten_memcpy_big):
+        (_gettimeofday):
+        (_abort):
+        (SYSCALLS):
+        (SYSCALLS.get getStr):
+        (SYSCALLS.get64):
+        (SYSCALLS.getZero):
+        (try.___syscall146.printChar):
+        (___syscall146):
+        (___syscall54):
+        (___unlock):
+        (___syscall6):
+        (invoke_ii):
+        (invoke_iiii):
+        (invoke_v):
+        (_malloc.Module.string_appeared_here):
+        (getTempRet0.Module.string_appeared_here):
+        (_free.Module.string_appeared_here):
+        (_main.Module.string_appeared_here):
+        (setTempRet0.Module.string_appeared_here):
+        (establishStackSpace.Module.string_appeared_here):
+        (stackSave.Module.string_appeared_here):
+        (_memset.Module.string_appeared_here):
+        (_sbrk.Module.string_appeared_here):
+        (_emscripten_get_global_libc.Module.string_appeared_here):
+        (_memcpy.Module.string_appeared_here):
+        (___errno_location.Module.string_appeared_here):
+        (setThrew.Module.string_appeared_here):
+        (_fflush.Module.string_appeared_here):
+        (stackAlloc.Module.string_appeared_here):
+        (stackRestore.Module.string_appeared_here):
+        (_llvm_bswap_i32.Module.string_appeared_here):
+        (runPostSets.Module.string_appeared_here):
+        (dynCall_ii.Module.string_appeared_here):
+        (dynCall_iiii.Module.string_appeared_here):
+        (dynCall_v.Module.string_appeared_here):
+        (else.applyMemoryInitializer):
+        (else):
+        (else.useRequest):
+        (ExitStatus):
+        (dependenciesFulfilled):
+        (Module.string_appeared_here.Module.callMain.callMain.pad):
+        (Module.string_appeared_here.Module.callMain):
+        (run.doRun):
+        (run):
+        (exit):
+        * workers/wasm-long-compile-expected.txt: Added.
+        * workers/wasm-long-compile-many-expected.txt: Added.
+        * workers/wasm-long-compile-many.html: Added.
+        * workers/wasm-long-compile.html: Added.
+        * workers/wasm-resources: Added.
+        * workers/wasm-resources/long-compile-many.js: Added.
+        (done):
+        (i.async.run):
+        (i.worker.onmessage):
+        * workers/wasm-resources/long-compile-worker.js: Added.
+        (const._fail):
+        (const.isNotA.assert.isNotA):
+        (const):
+        (switch.typeof):
+        (Builder):
+        (Builder.prototype.setChecked):
+        (Builder.prototype.setPreamble):
+        (Builder.prototype._functionIndexSpaceKeyHash):
+        (Builder.prototype._registerFunctionToIndexSpace):
+        (Builder.prototype._getFunctionFromIndexSpace):
+        (Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
+        (Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.const.codeBuilder.End.switch.case.string_appeared_here.e):
+        (Builder.prototype._registerSectionBuilders.this.Unknown):
+        * workers/wasm-resources/long-compile.js: Added.
+        (done):
+        (async.run):
+        (worker.onmessage):
+
 2017-04-13  Dean Jackson  <dino@apple.com>
 
         Large negative animation-delays may not work depending on machine uptime
index 7b14e29..8291a9d 100644 (file)
@@ -981,6 +981,13 @@ webkit.org/b/159370 [ Debug ] fast/history/page-cache-destroy-document.html [ Sk
 # This test is just way too slow.
 workers/bomb-with-v8.html [ Skip ]
 
+# These tests are slow by design.
+workers/wasm-hashset-many.html [ Slow ]
+workers/wasm-hashset-many-2.html [ Slow ]
+workers/wasm-hashset.html [ Slow ]
+workers/wasm-long-compile-many.html [ Slow ]
+workers/wasm-long-compile.html [ Slow ]
+
 # WebCryptoAPI tests that take too long to complete
 imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/hkdf.worker.html [ Skip ]
 imported/w3c/web-platform-tests/WebCryptoAPI/derive_bits_keys/pbkdf2.worker.html [ Slow ]
diff --git a/LayoutTests/storage/indexeddb/resources/wasm-exceptions.js b/LayoutTests/storage/indexeddb/resources/wasm-exceptions.js
new file mode 100644 (file)
index 0000000..4812a97
--- /dev/null
@@ -0,0 +1,1848 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const _fail = (msg, extra) => {
+    throw new Error(msg + (extra ? ": " + extra : ""));
+};
+
+const assert = {};
+
+const isNotA = assert.isNotA = (v, t, msg) => {
+    if (typeof v === t)
+        _fail(`Shouldn't be ${t}`, msg);
+};
+
+const isA = assert.isA = (v, t, msg) => {
+    if (typeof v !== t)
+        _fail(`Should be ${t}, got ${typeof(v)}`, msg);
+};
+
+const isNotUndef = assert.isNotUndef = (v, msg) => isNotA(v, "undefined", msg);
+assert.isUndef = (v, msg) => isA(v, "undefined", msg);
+assert.notObject = (v, msg) => isNotA(v, "object", msg);
+const isObject = assert.isObject = (v, msg) => isA(v, "object", msg);
+assert.notString = (v, msg) => isNotA(v, "string", msg);
+assert.isString = (v, msg) => isA(v, "string", msg);
+assert.notNumber = (v, msg) => isNotA(v, "number", msg);
+assert.isNumber = (v, msg) => isA(v, "number", msg);
+assert.notFunction = (v, msg) => isNotA(v, "function", msg);
+assert.isFunction = (v, msg) => isA(v, "function", msg);
+
+assert.hasObjectProperty = (o, p, msg) => {
+    isObject(o, msg);
+    isNotUndef(o[p], msg, `expected object to have property ${p}`);
+};
+
+assert.isArray = (v, msg) => {
+    if (!Array.isArray(v))
+        _fail(`Expected an array, got ${typeof(v)}`, msg);
+};
+
+assert.isNotArray = (v, msg) => {
+    if (Array.isArray(v))
+        _fail(`Expected to not be an array`, msg);
+};
+
+assert.truthy = (v, msg) => {
+    if (!v)
+        _fail(`Expected truthy`, msg);
+};
+
+assert.falsy = (v, msg) => {
+    if (v)
+        _fail(`Expected falsy`, msg);
+};
+
+assert.eq = (lhs, rhs, msg) => {
+    if (typeof lhs !== typeof rhs)
+        _fail(`Not the same: "${lhs}" and "${rhs}"`, msg);
+    if (Array.isArray(lhs) && Array.isArray(rhs) && (lhs.length === rhs.length)) {
+        for (let i = 0; i !== lhs.length; ++i)
+            eq(lhs[i], rhs[i], msg);
+    } else if (lhs !== rhs) {
+        if (typeof lhs === "number" && isNaN(lhs) && isNaN(rhs))
+            return;
+        _fail(`Not the same: "${lhs}" and "${rhs}"`, msg);
+    } else {
+        if (typeof lhs === "number" && (1.0 / lhs !== 1.0 / rhs)) // Distinguish -0.0 from 0.0.
+            _fail(`Not the same: "${lhs}" and "${rhs}"`, msg);
+    }
+};
+
+const canonicalizeI32 = (number) => {
+    if (Math.round(number) === number && number >= 2 ** 31)
+        number = number - 2 ** 32;
+    return number;
+}
+
+assert.eqI32 = (lhs, rhs, msg) => {
+    return eq(canonicalizeI32(lhs), canonicalizeI32(rhs), msg);
+};
+
+assert.ge = (lhs, rhs, msg) => {
+    isNotUndef(lhs);
+    isNotUndef(rhs);
+    if (!(lhs >= rhs))
+        _fail(`Expected: "${lhs}" < "${rhs}"`, msg);
+};
+
+assert.le = (lhs, rhs, msg) => {
+    isNotUndef(lhs);
+    isNotUndef(rhs);
+    if (!(lhs <= rhs))
+        _fail(`Expected: "${lhs}" > "${rhs}"`, msg);
+};
+
+const _throws = (func, type, message, ...args) => {
+    try {
+        func(...args);
+    } catch (e) {
+        if (e instanceof type) {
+            if (e.message === message)
+                return e;
+            // Ignore source information at the end of the error message if the
+            // expected message didn't specify that information. Sometimes it
+            // changes, or it's tricky to get just right.
+            const evaluatingIndex = e.message.indexOf(" (evaluating '");
+            if (evaluatingIndex !== -1) {
+                const cleanMessage = e.message.substring(0, evaluatingIndex);
+                if (cleanMessage === message)
+                    return e;
+            }
+        }
+        _fail(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`);
+    }
+    _fail(`Expected to throw a ${type.name} with message "${message}"`);
+};
+
+const _instanceof = (obj, type, msg) => {
+    if (!(obj instanceof type))
+        _fail(`Expected a ${typeof(type)}, got ${typeof obj}`);
+};
+
+// Use underscore names to avoid clashing with builtin names.
+assert.throws = _throws;
+assert.instanceof = _instanceof;
+
+const asyncTestImpl = (promise, thenFunc, catchFunc) => {
+    asyncTestStart(1);
+    promise.then(thenFunc).catch(catchFunc);
+};
+
+const printExn = (e) => {
+    print("Failed: ", e);
+    print(e.stack);
+};
+
+assert.asyncTest = (promise) => asyncTestImpl(promise, asyncTestPassed, printExn);
+assert.asyncTestEq = (promise, expected) => {
+    const thenCheck = (value) => {
+        if (value === expected)
+            return asyncTestPassed();
+        print("Failed: got ", value, " but expected ", expected);
+
+    }
+    asyncTestImpl(promise, thenCheck, printExn);
+};
+
+const WASM_JSON = `
+{
+    "comments": ["This file describes the WebAssembly ISA.",
+                 "Scripts in this folder auto-generate C++ code for JavaScriptCore as well as the testing DSL which WebKit's WebAssembly tests use."
+                ],
+    "preamble": [
+        { "name": "magic number", "type": "uint32", "value": 1836278016, "description": "NULL character followed by 'asm'" },
+        { "name": "version",      "type": "uint32", "value":          1, "description": "Version number" }
+    ],
+    "type" : {
+        "i32":     { "type": "varint7", "value":  -1, "b3type": "B3::Int32" },
+        "i64":     { "type": "varint7", "value":  -2, "b3type": "B3::Int64" },
+        "f32":     { "type": "varint7", "value":  -3, "b3type": "B3::Float" },
+        "f64":     { "type": "varint7", "value":  -4, "b3type": "B3::Double" },
+        "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" },
+        "func":    { "type": "varint7", "value": -32, "b3type": "B3::Void" },
+        "void":    { "type": "varint7", "value": -64, "b3type": "B3::Void" }
+    },
+    "value_type": ["i32", "i64", "f32", "f64"],
+    "block_type": ["i32", "i64", "f32", "f64", "void"],
+    "elem_type": ["anyfunc"],
+    "external_kind": {
+        "Function": { "type": "uint8", "value": 0 },
+        "Table":    { "type": "uint8", "value": 1 },
+        "Memory":   { "type": "uint8", "value": 2 },
+        "Global":   { "type": "uint8", "value": 3 }
+    },
+    "section" : {
+        "Type":     { "type": "varuint7", "value":  1, "description": "Function signature declarations" },
+        "Import":   { "type": "varuint7", "value":  2, "description": "Import declarations" },
+        "Function": { "type": "varuint7", "value":  3, "description": "Function declarations" },
+        "Table":    { "type": "varuint7", "value":  4, "description": "Indirect function table and other tables" },
+        "Memory":   { "type": "varuint7", "value":  5, "description": "Memory attributes" },
+        "Global":   { "type": "varuint7", "value":  6, "description": "Global declarations" },
+        "Export":   { "type": "varuint7", "value":  7, "description": "Exports" },
+        "Start":    { "type": "varuint7", "value":  8, "description": "Start function declaration" },
+        "Element":  { "type": "varuint7", "value":  9, "description": "Elements section" },
+        "Code":     { "type": "varuint7", "value": 10, "description": "Function bodies (code)" },
+        "Data":     { "type": "varuint7", "value": 11, "description": "Data segments" }
+    },
+    "opcode": {
+        "unreachable":         { "category": "control",    "value":   0, "return": [],           "parameter": [],                      "immediate": [],                                                                                         "description": "trap immediately" },
+        "block":               { "category": "control",    "value":   2, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a sequence of expressions, yielding 0 or 1 values" },
+        "loop":                { "category": "control",    "value":   3, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a block which can also form control flow loops" },
+        "if":                  { "category": "control",    "value":   4, "return": ["control"],  "parameter": ["bool"],                "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin if expression" },
+        "else":                { "category": "control",    "value":   5, "return": ["control"],  "parameter": [],                      "immediate": [],                                                                                         "description": "begin else expression of if" },
+        "select":              { "category": "control",    "value":  27, "return": ["prev"],     "parameter": ["any", "prev", "bool"], "immediate": [],                                                                                         "description": "select one of two values based on condition" },
+        "br":                  { "category": "control",    "value":  12, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "break that targets an outer nested block" },
+        "br_if":               { "category": "control",    "value":  13, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "conditional break that targets an outer nested block" },
+        "br_table":            { "category": "control",    "value":  14, "return": [],           "parameter": [],                      "immediate": [{"name": "target_count",   "type": "varuint32",                                            "description": "number of entries in the target_table"},
+                                                                                                                                                     {"name": "target_table",   "type": "varuint32*",                                           "description": "target entries that indicate an outer block or loop to which to break"},
+                                                                                                                                                     {"name": "default_target", "type": "varuint32",                                            "description": "an outer block or loop to which to break in the default case"}],
+                                                                                                                                                                                                                                                "description": "branch table control flow construct" },
+        "return":              { "category": "control",    "value":  15, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "return zero or one value from this function" },
+        "drop":                { "category": "control",    "value":  26, "return": [],           "parameter": ["any"],                  "immediate": [],                                                                                         "description": "ignore value" },
+        "nop":                 { "category": "control",    "value":   1, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "no operation" },
+        "end":                 { "category": "control",    "value":  11, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
+        "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
+        "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
+        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "double"}],                                             "description": "a constant value interpreted as f64" },
+        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "float"}],                                             "description": "a constant value interpreted as f32" },
+        "get_local":           { "category": "special",    "value":  32, "return": ["any"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
+        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
+        "tee_local":           { "category": "special",    "value":  34, "return": ["any"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
+        "get_global":          { "category": "special",    "value":  35, "return": ["any"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
+        "set_global":          { "category": "special",    "value":  36, "return": [],         "parameter": ["any"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
+        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
+        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "reserved",     "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
+        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_s":        { "category": "memory",     "value":  46, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_u":        { "category": "memory",     "value":  47, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_s":         { "category": "memory",     "value":  48, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_u":         { "category": "memory",     "value":  49, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_s":        { "category": "memory",     "value":  50, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_u":        { "category": "memory",     "value":  51, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_s":        { "category": "memory",     "value":  52, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_u":        { "category": "memory",     "value":  53, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load":            { "category": "memory",     "value":  40, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load":            { "category": "memory",     "value":  41, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f32.load":            { "category": "memory",     "value":  42, "return": ["f32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f64.load":            { "category": "memory",     "value":  43, "return": ["f64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.store8":          { "category": "memory",     "value":  58, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store16":         { "category": "memory",     "value":  59, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store8":          { "category": "memory",     "value":  60, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store16":         { "category": "memory",     "value":  61, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store32":         { "category": "memory",     "value":  62, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store":           { "category": "memory",     "value":  54, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store":           { "category": "memory",     "value":  55, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f32.store":           { "category": "memory",     "value":  56, "return": [],           "parameter": ["addr", "f32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f64.store":           { "category": "memory",     "value":  57, "return": [],           "parameter": ["addr", "f64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "current_memory":      { "category": "operation",  "value":  63, "return": ["size"],     "parameter": [],                       "immediate": [{"name": "flags", "type": "varuint32"}],                                                                                         "description": "query the size of memory" },
+        "grow_memory":         { "category": "operation",  "value":  64, "return": ["size"],     "parameter": ["size"],                 "immediate": [{"name": "flags", "type": "varuint32"}],                                                                                         "description": "grow the size of memory" },
+        "i32.add":             { "category": "arithmetic", "value": 106, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Add"          },
+        "i32.sub":             { "category": "arithmetic", "value": 107, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
+        "i32.mul":             { "category": "arithmetic", "value": 108, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
+        "i32.div_s":           { "category": "arithmetic", "value": 109, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.div_u":           { "category": "arithmetic", "value": 110, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.rem_s":           { "category": "arithmetic", "value": 111, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.rem_u":           { "category": "arithmetic", "value": 112, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.and":             { "category": "arithmetic", "value": 113, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
+        "i32.or":              { "category": "arithmetic", "value": 114, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
+        "i32.xor":             { "category": "arithmetic", "value": 115, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
+        "i32.shl":             { "category": "arithmetic", "value": 116, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Shl"          },
+        "i32.shr_u":           { "category": "arithmetic", "value": 118, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "ZShr"         },
+        "i32.shr_s":           { "category": "arithmetic", "value": 117, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "SShr"         },
+        "i32.rotr":            { "category": "arithmetic", "value": 120, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotR"         },
+        "i32.rotl":            { "category": "arithmetic", "value": 119, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotL"         },
+        "i32.eq":              { "category": "comparison", "value":  70, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Equal"        },
+        "i32.ne":              { "category": "comparison", "value":  71, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "NotEqual"     },
+        "i32.lt_s":            { "category": "comparison", "value":  72, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessThan"     },
+        "i32.le_s":            { "category": "comparison", "value":  76, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessEqual"    },
+        "i32.lt_u":            { "category": "comparison", "value":  73, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Below"        },
+        "i32.le_u":            { "category": "comparison", "value":  77, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i32.gt_s":            { "category": "comparison", "value":  74, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i32.ge_s":            { "category": "comparison", "value":  78, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.gt_u":            { "category": "comparison", "value":  75, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Above"        },
+        "i32.ge_u":            { "category": "comparison", "value":  79, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i32.clz":             { "category": "arithmetic", "value": 103, "return": ["i32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "Clz"          },
+        "i32.ctz":             { "category": "arithmetic", "value": 104, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.popcnt":          { "category": "arithmetic", "value": 105, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.eqz":             { "category": "comparison", "value":  69, "return": ["bool"],     "parameter": ["i32"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
+        "i64.add":             { "category": "arithmetic", "value": 124, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Add"          },
+        "i64.sub":             { "category": "arithmetic", "value": 125, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
+        "i64.mul":             { "category": "arithmetic", "value": 126, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
+        "i64.div_s":           { "category": "arithmetic", "value": 127, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.div_u":           { "category": "arithmetic", "value": 128, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.rem_s":           { "category": "arithmetic", "value": 129, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.rem_u":           { "category": "arithmetic", "value": 130, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.and":             { "category": "arithmetic", "value": 131, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
+        "i64.or":              { "category": "arithmetic", "value": 132, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
+        "i64.xor":             { "category": "arithmetic", "value": 133, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
+        "i64.shl":             { "category": "arithmetic", "value": 134, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Shl(@0, Trunc(@1))" },
+        "i64.shr_u":           { "category": "arithmetic", "value": 136, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "ZShr(@0, Trunc(@1))" },
+        "i64.shr_s":           { "category": "arithmetic", "value": 135, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "SShr(@0, Trunc(@1))" },
+        "i64.rotr":            { "category": "arithmetic", "value": 138, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotR(@0, Trunc(@1))" },
+        "i64.rotl":            { "category": "arithmetic", "value": 137, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotL(@0, Trunc(@1))" },
+        "i64.eq":              { "category": "comparison", "value":  81, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Equal"        },
+        "i64.ne":              { "category": "comparison", "value":  82, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "NotEqual"     },
+        "i64.lt_s":            { "category": "comparison", "value":  83, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessThan"     },
+        "i64.le_s":            { "category": "comparison", "value":  87, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessEqual"    },
+        "i64.lt_u":            { "category": "comparison", "value":  84, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Below"        },
+        "i64.le_u":            { "category": "comparison", "value":  88, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i64.gt_s":            { "category": "comparison", "value":  85, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i64.ge_s":            { "category": "comparison", "value":  89, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i64.gt_u":            { "category": "comparison", "value":  86, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Above"        },
+        "i64.ge_u":            { "category": "comparison", "value":  90, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i64.clz":             { "category": "arithmetic", "value": 121, "return": ["i64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Clz"          },
+        "i64.ctz":             { "category": "arithmetic", "value": 122, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.popcnt":          { "category": "arithmetic", "value": 123, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.eqz":             { "category": "comparison", "value":  80, "return": ["bool"],     "parameter": ["i64"],                  "immediate": [], "b3op": "Equal(i64(0), @0)" },
+        "f32.add":             { "category": "arithmetic", "value": 146, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
+        "f32.sub":             { "category": "arithmetic", "value": 147, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
+        "f32.mul":             { "category": "arithmetic", "value": 148, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
+        "f32.div":             { "category": "arithmetic", "value": 149, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
+        "f32.min":             { "category": "arithmetic", "value": 150, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(Equal(@0, @1), BitOr(@0, @1), Select(LessThan(@0, @1), @0, @1))" },
+        "f32.max":             { "category": "arithmetic", "value": 151, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(Equal(@0, @1), BitAnd(@0, @1), Select(LessThan(@0, @1), @1, @0))" },
+        "f32.abs":             { "category": "arithmetic", "value": 139, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
+        "f32.neg":             { "category": "arithmetic", "value": 140, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Neg"          },
+        "f32.copysign":        { "category": "arithmetic", "value": 152, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "BitwiseCast(BitOr(BitAnd(BitwiseCast(@1), i32(0x80000000)), BitAnd(BitwiseCast(@0), i32(0x7fffffff))))" },
+        "f32.ceil":            { "category": "arithmetic", "value": 141, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
+        "f32.floor":           { "category": "arithmetic", "value": 142, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
+        "f32.trunc":           { "category": "arithmetic", "value": 143, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.nearest":         { "category": "arithmetic", "value": 144, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.sqrt":            { "category": "arithmetic", "value": 145, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f32.eq":              { "category": "comparison", "value":  91, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
+        "f32.ne":              { "category": "comparison", "value":  92, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
+        "f32.lt":              { "category": "comparison", "value":  93, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
+        "f32.le":              { "category": "comparison", "value":  95, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
+        "f32.gt":              { "category": "comparison", "value":  94, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f32.ge":              { "category": "comparison", "value":  96, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "f64.add":             { "category": "arithmetic", "value": 160, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
+        "f64.sub":             { "category": "arithmetic", "value": 161, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
+        "f64.mul":             { "category": "arithmetic", "value": 162, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
+        "f64.div":             { "category": "arithmetic", "value": 163, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
+        "f64.min":             { "category": "arithmetic", "value": 164, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(Equal(@0, @1), BitOr(@0, @1), Select(LessThan(@0, @1), @0, @1))" },
+        "f64.max":             { "category": "arithmetic", "value": 165, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(Equal(@0, @1), BitAnd(@0, @1), Select(LessThan(@0, @1), @1, @0))" },
+        "f64.abs":             { "category": "arithmetic", "value": 153, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
+        "f64.neg":             { "category": "arithmetic", "value": 154, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Neg"          },
+        "f64.copysign":        { "category": "arithmetic", "value": 166, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "BitwiseCast(BitOr(BitAnd(BitwiseCast(@1), i64(0x8000000000000000)), BitAnd(BitwiseCast(@0), i64(0x7fffffffffffffff))))" },
+        "f64.ceil":            { "category": "arithmetic", "value": 155, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
+        "f64.floor":           { "category": "arithmetic", "value": 156, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
+        "f64.trunc":           { "category": "arithmetic", "value": 157, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.nearest":         { "category": "arithmetic", "value": 158, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.sqrt":            { "category": "arithmetic", "value": 159, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f64.eq":              { "category": "comparison", "value":  97, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
+        "f64.ne":              { "category": "comparison", "value":  98, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
+        "f64.lt":              { "category": "comparison", "value":  99, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
+        "f64.le":              { "category": "comparison", "value": 101, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
+        "f64.gt":              { "category": "comparison", "value": 100, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f64.ge":              { "category": "comparison", "value": 102, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.trunc_s/f32":     { "category": "conversion", "value": 168, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_s/f64":     { "category": "conversion", "value": 170, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.trunc_u/f32":     { "category": "conversion", "value": 169, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_u/f64":     { "category": "conversion", "value": 171, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.wrap/i64":        { "category": "conversion", "value": 167, "return": ["i32"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Trunc"        },
+        "i64.trunc_s/f32":     { "category": "conversion", "value": 174, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_s/f64":     { "category": "conversion", "value": 176, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.trunc_u/f32":     { "category": "conversion", "value": 175, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_u/f64":     { "category": "conversion", "value": 177, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.extend_s/i32":    { "category": "conversion", "value": 172, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
+        "i64.extend_u/i32":    { "category": "conversion", "value": 173, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
+        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF"         },
+        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToF(ZExt32(@0))" },
+        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToF"         },
+        "f32.convert_u/i64":   { "category": "conversion", "value": 181, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.demote/f64":      { "category": "conversion", "value": 182, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
+        "f32.reinterpret/i32": { "category": "conversion", "value": 190, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD"         },
+        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "IToD(ZExt32(@0))" },
+        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "IToD"         },
+        "f64.convert_u/i64":   { "category": "conversion", "value": 186, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.promote/f32":     { "category": "conversion", "value": 187, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
+        "f64.reinterpret/i64": { "category": "conversion", "value": 191, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i32.reinterpret/f32": { "category": "conversion", "value": 188, "return": ["i32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i64.reinterpret/f64": { "category": "conversion", "value": 189, "return": ["i64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "BitwiseCast"  }
+    }
+}
+`;
+
+
+const _environment =
+    ((typeof process === "object" && typeof require === "function") ? "node"
+     : (typeof window === "object" ? "web"
+        : (typeof importScripts === "function" ? "worker"
+           : "shell")));
+
+let _global = (typeof global !== 'object' || !global || global.Math !== Math || global.Array !== Array)
+    ? ((typeof self !== 'undefined') ? self
+       : (typeof window !== 'undefined') ? window
+       : (typeof global !== 'undefined') ? global
+       : Function('return this')())
+    : global;
+
+const _eval = x => eval.call(null, x);
+
+const _read = filename => {
+    switch (_environment) {
+    case "node":   return read(filename);
+    case "web":    // fallthrough
+    case "worker": let xhr = new XMLHttpRequest(); xhr.open("GET", filename, /*async=*/false); return xhr.responseText;
+    case "shell":  return read(filename);
+    }
+}
+
+const _load = filename => {
+    switch (_environment) {
+    case "node":   // fallthrough
+    case "web":    // fallthrough
+    case "shell":  return _eval(_read(filename));
+    case "worker": return importScripts(filename);
+    }
+}
+
+const _json = filename => {
+    assert.eq(filename, "wasm.json");
+    return JSON.parse(WASM_JSON);
+
+    switch (_environment) {
+    case "node":   // fallthrough
+    case "shell":  return JSON.parse(_read(filename));
+    case "web":    // fallthrough
+    case "worker": let xhr = new XMLHttpRequest(); xhr.overrideMimeType("application/json"); xhr.open("GET", filename, /*async=*/false); return xhr.response;
+    }
+}
+
+const _dump = (what, name, pad = '    ') => {
+    const value = v => {
+        try { return `"${v}"`; }
+        catch (e) { return `Error: "${e.message}"`; }
+    };
+    let s = `${pad}${name} ${typeof what}: ${value(what)}`;
+    for (let p in what) {
+        s += `\n${pad}${pad}${p}: ${value(what[p])} ${typeof v}`;
+        s += '\n' + _dump(what[p], p, pad + pad);
+    }
+    return s;
+};
+
+// Use underscore names to avoid clashing with builtin names.
+const utilities = {
+    dump : _dump,
+    eval : _eval,
+    read : _read,
+    load : _load,
+    json : _json,
+    global : _global
+};
+
+
+const _mapValues = from => {
+    let values = {};
+    for (const key in from)
+        values[key] = from[key].value;
+    return values;
+};
+
+
+const WASM = {};
+{
+    const description = WASM.description = utilities.json("wasm.json");
+    const type = WASM.type = Object.keys(description.type);
+    const _typeSet = new Set(type);
+    WASM.isValidType = v => _typeSet.has(v);
+    WASM.typeValue = _mapValues(description.type);
+    const _valueTypeSet = new Set(description.value_type);
+    WASM.isValidValueType = v => _valueTypeSet.has(v);
+    const _blockTypeSet = new Set(description.block_type);
+    WASM.isValidBlockType = v => _blockTypeSet.has(v);
+    WASM.externalKindValue = _mapValues(description.external_kind);
+    const sections = WASM.sections = Object.keys(description.section);
+    WASM.sectionEncodingType = description.section[sections[0]].type;
+}
+
+
+// LowLevelBinary.js
+const _initialAllocationSize = 1024;
+const _growAllocationSize = allocated => allocated * 2;
+
+
+const varuint32Min = 0;
+const varint7Min = -0b1000000;
+const varint7Max = 0b111111;
+const varuint7Max = 0b1111111;
+const varuint32Max = ((((1 << 31) >>> 0) - 1) * 2) + 1;
+const varint32Min = -((1 << 31) >>> 0);
+const varint32Max = ((1 << 31) - 1) >>> 0;
+const varBitsMax = 5;
+
+const _getterRangeCheck = (llb, at, size) => {
+    if (0 > at || at + size > llb._used)
+        throw new RangeError(`[${at}, ${at + size}) is out of buffer range [0, ${llb._used})`);
+};
+
+const _hexdump = (buf, size) => {
+    let s = "";
+    const width = 16;
+    const base = 16;
+    for (let row = 0; row * width < size; ++row) {
+        const address = (row * width).toString(base);
+        s += "0".repeat(8 - address.length) + address;
+        let chars = "";
+        for (let col = 0; col !== width; ++col) {
+            const idx = row * width + col;
+            if (idx < size) {
+                const byte = buf[idx];
+                const bytestr = byte.toString(base);
+                s += " " + (bytestr.length === 1 ? "0" + bytestr : bytestr);
+                chars += 0x20 <= byte && byte < 0x7F ? String.fromCharCode(byte) : "ยท";
+            } else {
+                s += "   ";
+                chars += " ";
+            }
+        }
+        s+= "  |" + chars + "|\n";
+    }
+    return s;
+};
+
+class LowLevelBinary {
+    constructor() {
+        this._buf = new Uint8Array(_initialAllocationSize);
+        this._used = 0;
+    }
+
+    newPatchable(type) { return new PatchableLowLevelBinary(type, this); }
+
+    // Utilities.
+    get() { return this._buf; }
+    trim() { this._buf = this._buf.slice(0, this._used); }
+
+    hexdump() { return _hexdump(this._buf, this._used); }
+    _maybeGrow(bytes) {
+        const allocated = this._buf.length;
+        if (allocated - this._used < bytes) {
+            let buf = new Uint8Array(_growAllocationSize(allocated));
+            buf.set(this._buf);
+            this._buf = buf;
+        }
+    }
+    _push8(v) { this._buf[this._used] = v & 0xFF; this._used += 1; }
+
+    // Data types.
+    uint8(v) {
+        if ((v & 0xFF) >>> 0 !== v)
+            throw new RangeError(`Invalid uint8 ${v}`);
+        this._maybeGrow(1);
+        this._push8(v);
+    }
+    uint16(v) {
+        if ((v & 0xFFFF) >>> 0 !== v)
+            throw new RangeError(`Invalid uint16 ${v}`);
+        this._maybeGrow(2);
+        this._push8(v);
+        this._push8(v >>> 8);
+    }
+    uint24(v) {
+        if ((v & 0xFFFFFF) >>> 0 !== v)
+            throw new RangeError(`Invalid uint24 ${v}`);
+        this._maybeGrow(3);
+        this._push8(v);
+        this._push8(v >>> 8);
+        this._push8(v >>> 16);
+    }
+    uint32(v) {
+        if ((v & 0xFFFFFFFF) >>> 0 !== v)
+            throw new RangeError(`Invalid uint32 ${v}`);
+        this._maybeGrow(4);
+        this._push8(v);
+        this._push8(v >>> 8);
+        this._push8(v >>> 16);
+        this._push8(v >>> 24);
+    }
+    float(v) {
+        if (isNaN(v))
+            throw new RangeError("unimplemented, NaNs");
+        // Unfortunately, we cannot just view the actual buffer as a Float32Array since it needs to be 4 byte aligned
+        let buffer = new ArrayBuffer(4);
+        let floatView = new Float32Array(buffer);
+        let int8View = new Uint8Array(buffer);
+        floatView[0] = v;
+        for (let byte of int8View)
+            this._push8(byte);
+    }
+
+    double(v) {
+        if (isNaN(v))
+            throw new RangeError("unimplemented, NaNs");
+        // Unfortunately, we cannot just view the actual buffer as a Float64Array since it needs to be 4 byte aligned
+        let buffer = new ArrayBuffer(8);
+        let floatView = new Float64Array(buffer);
+        let int8View = new Uint8Array(buffer);
+        floatView[0] = v;
+        for (let byte of int8View)
+            this._push8(byte);
+    }
+
+    varuint32(v) {
+        assert.isNumber(v);
+        if (v < varuint32Min || varuint32Max < v)
+            throw new RangeError(`Invalid varuint32 ${v} range is [${varuint32Min}, ${varuint32Max}]`);
+        while (v >= 0x80) {
+            this.uint8(0x80 | (v & 0x7F));
+            v >>>= 7;
+        }
+        this.uint8(v);
+    }
+    varint32(v) {
+        assert.isNumber(v);
+        if (v < varint32Min || varint32Max < v)
+            throw new RangeError(`Invalid varint32 ${v} range is [${varint32Min}, ${varint32Max}]`);
+        do {
+            const b = v & 0x7F;
+            v >>= 7;
+            if ((v === 0 && ((b & 0x40) === 0)) || (v === -1 && ((b & 0x40) === 0x40))) {
+                this.uint8(b & 0x7F);
+                break;
+            }
+            this.uint8(0x80 | b);
+        } while (true);
+    }
+    varuint64(v) {
+        assert.isNumber(v);
+        if (v < varuint32Min || varuint32Max < v)
+            throw new RangeError(`unimplemented: varuint64 larger than 32-bit`);
+        this.varuint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
+    }
+    varint64(v) {
+        assert.isNumber(v);
+        if (v < varint32Min || varint32Max < v)
+            throw new RangeError(`unimplemented: varint64 larger than 32-bit`);
+        this.varint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
+    }
+    varuint1(v) {
+        if (v !== 0 && v !== 1)
+            throw new RangeError(`Invalid varuint1 ${v} range is [0, 1]`);
+        this.varuint32(v);
+    }
+    varint7(v) {
+        if (v < varint7Min || varint7Max < v)
+            throw new RangeError(`Invalid varint7 ${v} range is [${varint7Min}, ${varint7Max}]`);
+        this.varint32(v);
+    }
+    varuint7(v) {
+        if (v < varuint32Min || varuint7Max < v)
+            throw new RangeError(`Invalid varuint7 ${v} range is [${varuint32Min}, ${varuint7Max}]`);
+        this.varuint32(v);
+    }
+    block_type(v) {
+        if (!WASM.isValidBlockType(v))
+            throw new Error(`Invalid block type ${v}`);
+        this.varint7(WASM.typeValue[v]);
+    }
+    string(str) {
+        let patch = this.newPatchable("varuint32");
+        for (const char of str) {
+            // Encode UTF-8 2003 code points.
+            const code = char.codePointAt();
+            if (code <= 0x007F) {
+                const utf8 = code;
+                patch.uint8(utf8);
+            } else if (code <= 0x07FF) {
+                const utf8 = 0x80C0 | ((code & 0x7C0) >> 6) | ((code & 0x3F) << 8);
+                patch.uint16(utf8);
+            } else if (code <= 0xFFFF) {
+                const utf8 = 0x8080E0 | ((code & 0xF000) >> 12) | ((code & 0xFC0) << 2) | ((code & 0x3F) << 16);
+                patch.uint24(utf8);
+            } else if (code <= 0x10FFFF) {
+                const utf8 = (0x808080F0 | ((code & 0x1C0000) >> 18) | ((code & 0x3F000) >> 4) | ((code & 0xFC0) << 10) | ((code & 0x3F) << 24)) >>> 0;
+                patch.uint32(utf8);
+            } else
+                throw new Error(`Unexpectedly large UTF-8 character code point '${char}' 0x${code.toString(16)}`);
+        }
+        patch.apply();
+    }
+
+    // Getters.
+    getSize() { return this._used; }
+    getUint8(at) {
+        _getterRangeCheck(this, at, 1);
+        return this._buf[at];
+    }
+    getUint16(at) {
+        _getterRangeCheck(this, at, 2);
+        return this._buf[at] | (this._buf[at + 1] << 8);
+    }
+    getUint24(at) {
+        _getterRangeCheck(this, at, 3);
+        return this._buf[at] | (this._buf[at + 1] << 8) | (this._buf[at + 2] << 16);
+    }
+    getUint32(at) {
+        _getterRangeCheck(this, at, 4);
+        return (this._buf[at] | (this._buf[at + 1] << 8) | (this._buf[at + 2] << 16) | (this._buf[at + 3] << 24)) >>> 0;
+    }
+    getVaruint32(at) {
+        let v = 0;
+        let shift = 0;
+        let byte = 0;
+        do {
+            byte = this.getUint8(at++);
+            ++read;
+            v = (v | ((byte & 0x7F) << shift) >>> 0) >>> 0;
+            shift += 7;
+        } while ((byte & 0x80) !== 0);
+        if (shift - 7 > 32) throw new RangeError(`Shifting too much at ${at}`);
+        if ((shift == 35) && ((byte & 0xF0) != 0)) throw new Error(`Unexpected non-significant varuint32 bits in last byte 0x${byte.toString(16)}`);
+        return { value: v, next: at };
+    }
+    getVarint32(at) {
+        let v = 0;
+        let shift = 0;
+        let byte = 0;
+        do {
+            byte = this.getUint8(at++);
+            v = (v | ((byte & 0x7F) << shift) >>> 0) >>> 0;
+            shift += 7;
+        } while ((byte & 0x80) !== 0);
+        if (shift - 7 > 32) throw new RangeError(`Shifting too much at ${at}`);
+        if ((shift == 35) && (((byte << 26) >> 30) != ((byte << 25) >> 31))) throw new Error(`Unexpected non-significant varint32 bits in last byte 0x${byte.toString(16)}`);
+        if ((byte & 0x40) === 0x40) {
+            const sext = shift < 32 ? 32 - shift : 0;
+            v = (v << sext) >> sext;
+        }
+        return { value: v, next: at };
+    }
+    getVaruint1(at) {
+        const res = this.getVaruint32(at);
+        if (res.value !== 0 && res.value !== 1) throw new Error(`Expected a varuint1, got value ${res.value}`);
+        return res;
+    }
+    getVaruint7(at) {
+        const res = this.getVaruint32(at);
+        if (res.value > varuint7Max) throw new Error(`Expected a varuint7, got value ${res.value}`);
+        return res;
+    }
+    getString(at) {
+        const size = this.getVaruint32(at);
+        const last = size.next + size.value;
+        let i = size.next;
+        let str = "";
+        while (i < last) {
+            // Decode UTF-8 2003 code points.
+            const peek = this.getUint8(i);
+            let code;
+            if ((peek & 0x80) === 0x0) {
+                const utf8 = this.getUint8(i);
+                assert.eq(utf8 & 0x80, 0x00);
+                i += 1;
+                code = utf8;
+            } else if ((peek & 0xE0) === 0xC0) {
+                const utf8 = this.getUint16(i);
+                assert.eq(utf8 & 0xC0E0, 0x80C0);
+                i += 2;
+                code = ((utf8 & 0x1F) << 6) | ((utf8 & 0x3F00) >> 8);
+            } else if ((peek & 0xF0) === 0xE0) {
+                const utf8 = this.getUint24(i);
+                assert.eq(utf8 & 0xC0C0F0, 0x8080E0);
+                i += 3;
+                code = ((utf8 & 0xF) << 12) | ((utf8 & 0x3F00) >> 2) | ((utf8 & 0x3F0000) >> 16);
+            } else if ((peek & 0xF8) === 0xF0) {
+                const utf8 = this.getUint32(i);
+                assert.eq((utf8 & 0xC0C0C0F8) | 0, 0x808080F0 | 0);
+                i += 4;
+                code = ((utf8 & 0x7) << 18) | ((utf8 & 0x3F00) << 4) | ((utf8 & 0x3F0000) >> 10) | ((utf8 & 0x3F000000) >> 24);
+            } else
+                throw new Error(`Unexpectedly large UTF-8 initial byte 0x${peek.toString(16)}`);
+            str += String.fromCodePoint(code);
+        }
+        if (i !== last)
+            throw new Error(`String decoding read up to ${i}, expected ${last}, UTF-8 decoding was too greedy`);
+        return str;
+    }
+};
+
+class PatchableLowLevelBinary extends LowLevelBinary {
+    constructor(type, lowLevelBinary) {
+        super();
+        this.type = type;
+        this.target = lowLevelBinary;
+        this._buffered_bytes = 0;
+    }
+    _push8(v) { ++this._buffered_bytes; super._push8(v); }
+    apply() {
+        this.target[this.type](this._buffered_bytes);
+        for (let i = 0; i < this._buffered_bytes; ++i)
+            this.target.uint8(this._buf[i]);
+    }
+};
+
+LowLevelBinary.varuint32Min = 0;
+LowLevelBinary.varint7Min = -0b1000000;
+LowLevelBinary.varint7Max = 0b111111;
+LowLevelBinary.varuint7Max = 0b1111111;
+LowLevelBinary.varuint32Max = ((((1 << 31) >>> 0) - 1) * 2) + 1;
+LowLevelBinary.varint32Min = -((1 << 31) >>> 0);
+LowLevelBinary.varint32Max = ((1 << 31) - 1) >>> 0;
+LowLevelBinary.varBitsMax = 5;
+
+
+// Builder_WebAssemblyBinary.js
+const BuildWebAssembly = {};
+{
+    const put = (bin, type, value) => bin[type](value);
+
+    const putResizableLimits = (bin, initial, maximum) => {
+        assert.truthy(typeof initial === "number", "We expect 'initial' to be an integer");
+        let hasMaximum = 0;
+        if (typeof maximum === "number") {
+            hasMaximum = 1;
+        } else {
+            assert.truthy(typeof maximum === "undefined", "We expect 'maximum' to be an integer if it's defined");
+        }
+
+        put(bin, "varuint1", hasMaximum);
+        put(bin, "varuint32", initial);
+        if (hasMaximum)
+            put(bin, "varuint32", maximum);
+    };
+
+    const putTable = (bin, {initial, maximum, element}) => {
+        assert.truthy(WASM.isValidType(element), "We expect 'element' to be a valid type. It was: " + element);
+        put(bin, "varint7", WASM.typeValue[element]);
+
+        putResizableLimits(bin, initial, maximum);
+    };
+
+    const valueType = WASM.description.type.i32.type
+
+    const putGlobalType = (bin, global) => {
+        put(bin, valueType, WASM.typeValue[global.type]);
+        put(bin, "varuint1", global.mutability);
+    };
+
+    const putOp = (bin, op) => {
+        put(bin, "uint8", op.value);
+        if (op.arguments.length !== 0)
+            throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
+
+        switch (op.name) {
+        default:
+            for (let i = 0; i < op.immediates.length; ++i) {
+                const type = WASM.description.opcode[op.name].immediate[i].type
+                if (!bin[type])
+                    throw new TypeError(`Unknown type: ${type} in op: ${op.name}`);
+                put(bin, type, op.immediates[i]);
+            }
+            break;
+        case "i32.const": {
+            assert.eq(op.immediates.length, 1);
+            let imm = op.immediates[0];
+            // Do a static cast to make large int32s signed.
+            if (imm >= 2 ** 31)
+                imm = imm - (2 ** 32);
+            put(bin, "varint32", imm);
+            break;
+        }
+        case "br_table":
+            put(bin, "varuint32", op.immediates.length - 1);
+            for (let imm of op.immediates)
+                put(bin, "varuint32", imm);
+            break;
+        }
+    };
+
+    const putInitExpr = (bin, expr) => {
+        putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [expr.initValue], arguments: [] });
+        putOp(bin, { value: WASM.description.opcode.end.value, name: "end", immediates: [], arguments: [] });
+    };
+
+    const emitters = {
+        Type: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const entry of section.data) {
+                put(bin, "varint7", WASM.typeValue["func"]);
+                put(bin, "varuint32", entry.params.length);
+                for (const param of entry.params)
+                    put(bin, "varint7", WASM.typeValue[param]);
+                if (entry.ret === "void")
+                    put(bin, "varuint1", 0);
+                else {
+                    put(bin, "varuint1", 1);
+                    put(bin, "varint7", WASM.typeValue[entry.ret]);
+                }
+            }
+        },
+        Import: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const entry of section.data) {
+                put(bin, "string", entry.module);
+                put(bin, "string", entry.field);
+                put(bin, "uint8", WASM.externalKindValue[entry.kind]);
+                switch (entry.kind) {
+                default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
+                case "Function": {
+                    put(bin, "varuint32", entry.type);
+                    break;
+                }
+                case "Table": {
+                    putTable(bin, entry.tableDescription);
+                    break;
+                }
+                case "Memory": {
+                    let {initial, maximum} = entry.memoryDescription;
+                    putResizableLimits(bin, initial, maximum);
+                    break;
+                };
+                case "Global":
+                    putGlobalType(bin, entry.globalDescription);
+                    break;
+                }
+            }
+        },
+
+        Function: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const signature of section.data)
+                put(bin, "varuint32", signature);
+        },
+
+        Table: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const {tableDescription} of section.data) {
+                putTable(bin, tableDescription);
+            }
+        },
+
+        Memory: (section, bin) => {
+            // Flags, currently can only be [0,1]
+            put(bin, "varuint1", section.data.length);
+            for (const memory of section.data) {
+                put(bin, "varuint32", memory.max ? 1 : 0);
+                put(bin, "varuint32", memory.initial);
+                if (memory.max)
+                    put(bin, "varuint32", memory.max);
+            }
+        },
+
+        Global: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const global of section.data) {
+                putGlobalType(bin, global);
+                putInitExpr(bin, global)
+            }
+        },
+
+        Export: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const entry of section.data) {
+                put(bin, "string", entry.field);
+                put(bin, "uint8", WASM.externalKindValue[entry.kind]);
+                switch (entry.kind) {
+                case "Global":
+                case "Function":
+                case "Memory":
+                case "Table":
+                    put(bin, "varuint32", entry.index);
+                    break;
+                default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
+                }
+            }
+        },
+        Start: (section, bin) => {
+            put(bin, "varuint32", section.data[0]);
+        },
+        Element: (section, bin) => {
+            const data = section.data;
+            put(bin, "varuint32", data.length);
+            for (const {tableIndex, offset, functionIndices} of data) {
+                put(bin, "varuint32", tableIndex);
+
+                let initExpr;
+                if (typeof offset === "number")
+                    initExpr = {op: "i32.const", initValue: offset};
+                else
+                    initExpr = offset;
+                putInitExpr(bin, initExpr);
+
+                put(bin, "varuint32", functionIndices.length);
+                for (const functionIndex of functionIndices)
+                    put(bin, "varuint32", functionIndex);
+            }
+        },
+
+        Code: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const func of section.data) {
+                let funcBin = bin.newPatchable("varuint32");
+                const localCount = func.locals.length - func.parameterCount;
+                put(funcBin, "varuint32", localCount);
+                for (let i = func.parameterCount; i < func.locals.length; ++i) {
+                    put(funcBin, "varuint32", 1);
+                    put(funcBin, "varint7", WASM.typeValue[func.locals[i]]);
+                }
+
+                for (const op of func.code)
+                    putOp(funcBin, op);
+
+                funcBin.apply();
+            }
+        },
+
+        Data: (section, bin) => {
+            put(bin, "varuint32", section.data.length);
+            for (const datum of section.data) {
+                put(bin, "varuint32", datum.index);
+                // FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
+                // For now we only handle i32.const as offset.
+                put(bin, "uint8", WASM.description.opcode["i32.const"].value);
+                put(bin, WASM.description.opcode["i32.const"].immediate[0].type, datum.offset);
+                put(bin, "uint8", WASM.description.opcode["end"].value);
+                put(bin, "varuint32", datum.data.length);
+                for (const byte of datum.data)
+                    put(bin, "uint8", byte);
+            }
+        },
+    };
+
+    BuildWebAssembly.Binary = (preamble, sections) => {
+        let wasmBin = new LowLevelBinary();
+        for (const p of WASM.description.preamble)
+            put(wasmBin, p.type, preamble[p.name]);
+        for (const section of sections) {
+            put(wasmBin, WASM.sectionEncodingType, section.id);
+            let sectionBin = wasmBin.newPatchable("varuint32");
+            const emitter = emitters[section.name];
+            if (emitter)
+                emitter(section, sectionBin);
+            else {
+                // Unknown section.
+                put(sectionBin, "string", section.name);
+                for (const byte of section.data)
+                    put(sectionBin, "uint8", byte);
+            }
+            sectionBin.apply();
+        }
+        wasmBin.trim();
+        return wasmBin;
+    };
+}
+
+
+const LLB = LowLevelBinary;
+
+const _toJavaScriptName = name => {
+    const camelCase = name.replace(/([^a-z0-9].)/g, c => c[1].toUpperCase());
+    const CamelCase = camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
+    return CamelCase;
+};
+
+const _isValidValue = (value, type) => {
+    switch (type) {
+    // We allow both signed and unsigned numbers.
+    case "i32": return Math.round(value) === value && LLB.varint32Min <= value && value <= LLB.varuint32Max;
+    case "i64": return true; // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
+    case "f32": return typeof(value) === "number" && isFinite(value);
+    case "f64": return typeof(value) === "number" && isFinite(value);
+    default: throw new Error(`Implementation problem: unknown type ${type}`);
+    }
+};
+const _unknownSectionId = 0;
+
+const _normalizeFunctionSignature = (params, ret) => {
+    assert.isArray(params);
+    for (const p of params)
+        assert.truthy(WASM.isValidValueType(p), `Type parameter ${p} needs a valid value type`);
+    if (typeof(ret) === "undefined")
+        ret = "void";
+    assert.isNotArray(ret, `Multiple return values not supported by WebAssembly yet`);
+    assert.truthy(WASM.isValidBlockType(ret), `Type return ${ret} must be valid block type`);
+    return [params, ret];
+};
+
+const _errorHandlingProxyFor = builder => builder["__isProxy"] ? builder : new Proxy(builder, {
+    get: (target, property, receiver) => {
+        if (property === "__isProxy")
+            return true;
+        if (target[property] === undefined)
+            throw new Error(`WebAssembly builder received unknown property '${property}'`);
+        return target[property];
+    }
+});
+
+const _maybeRegisterType = (builder, type) => {
+    const typeSection = builder._getSection("Type");
+    if (typeof(type) === "number") {
+        // Type numbers already refer to the type section, no need to register them.
+        if (builder._checked) {
+            assert.isNotUndef(typeSection, `Can not use type ${type} if a type section is not present`);
+            assert.isNotUndef(typeSection.data[type], `Type ${type} does not exist in type section`);
+        }
+        return type;
+    }
+    assert.hasObjectProperty(type, "params", `Expected type to be a number or object with 'params' and optionally 'ret' fields`);
+    const [params, ret] = _normalizeFunctionSignature(type.params, type.ret);
+    assert.isNotUndef(typeSection, `Can not add type if a type section is not present`);
+    // Try reusing an equivalent type from the type section.
+    types:
+    for (let i = 0; i !== typeSection.data.length; ++i) {
+        const t = typeSection.data[i];
+        if (t.ret === ret && params.length === t.params.length) {
+            for (let j = 0; j !== t.params.length; ++j) {
+                if (params[j] !== t.params[j])
+                    continue types;
+            }
+            type = i;
+            break;
+        }
+    }
+    if (typeof(type) !== "number") {
+        // Couldn't reuse a pre-existing type, register this type in the type section.
+        typeSection.data.push({ params: params, ret: ret });
+        type = typeSection.data.length - 1;
+    }
+    return type;
+};
+
+const _importFunctionContinuation = (builder, section, nextBuilder) => {
+    return (module, field, type) => {
+        assert.isString(module, `Import function module should be a string, got "${module}"`);
+        assert.isString(field, `Import function field should be a string, got "${field}"`);
+        const typeSection = builder._getSection("Type");
+        type = _maybeRegisterType(builder, type);
+        section.data.push({ field: field, type: type, kind: "Function", module: module });
+        // Imports also count in the function index space. Map them as objects to avoid clashing with Code functions' names.
+        builder._registerFunctionToIndexSpace({ module: module, field: field });
+        return _errorHandlingProxyFor(nextBuilder);
+    };
+};
+
+const _importMemoryContinuation = (builder, section, nextBuilder) => {
+    return (module, field, {initial, maximum}) => {
+        assert.isString(module, `Import Memory module should be a string, got "${module}"`);
+        assert.isString(field, `Import Memory field should be a string, got "${field}"`);
+        section.data.push({module, field, kind: "Memory", memoryDescription: {initial, maximum}});
+        return _errorHandlingProxyFor(nextBuilder);
+    };
+};
+
+const _importTableContinuation = (builder, section, nextBuilder) => {
+    return (module, field, {initial, maximum, element}) => {
+        assert.isString(module, `Import Table module should be a string, got "${module}"`);
+        assert.isString(field, `Import Table field should be a string, got "${field}"`);
+        section.data.push({module, field, kind: "Table", tableDescription: {initial, maximum, element}});
+        return _errorHandlingProxyFor(nextBuilder);
+    };
+};
+
+const _exportFunctionContinuation = (builder, section, nextBuilder) => {
+    return (field, index, type) => {
+        assert.isString(field, `Export function field should be a string, got "${field}"`);
+        const typeSection = builder._getSection("Type");
+        if (typeof(type) !== "undefined") {
+            // Exports can leave the type unspecified, letting the Code builder patch them up later.
+            type = _maybeRegisterType(builder, type);
+        }
+
+        // We can't check much about "index" here because the Code section succeeds the Export section. More work is done at Code().End() time.
+        switch (typeof(index)) {
+        case "string": break; // Assume it's a function name which will be revealed in the Code section.
+        case "number": break; // Assume it's a number in the "function index space".
+        case "object":
+            // Re-exporting an import.
+            assert.hasObjectProperty(index, "module", `Re-exporting "${field}" from an import`);
+            assert.hasObjectProperty(index, "field", `Re-exporting "${field}" from an import`);
+            break;
+        case "undefined":
+            // Assume it's the same as the field (i.e. it's not being renamed).
+            index = field;
+            break;
+        default: throw new Error(`Export section's index must be a string or a number, got ${index}`);
+        }
+
+        const correspondingImport = builder._getFunctionFromIndexSpace(index);
+        const importSection = builder._getSection("Import");
+        if (typeof(index) === "object") {
+            // Re-exporting an import using its module+field name.
+            assert.isNotUndef(correspondingImport, `Re-exporting "${field}" couldn't find import from module "${index.module}" field "${index.field}"`);
+            index = correspondingImport;
+            if (typeof(type) === "undefined")
+                type = importSection.data[index].type;
+            if (builder._checked)
+                assert.eq(type, importSection.data[index].type, `Re-exporting import "${importSection.data[index].field}" as "${field}" has mismatching type`);
+        } else if (typeof(correspondingImport) !== "undefined") {
+            // Re-exporting an import using its index.
+            let exportedImport;
+            for (const i of importSection.data) {
+                if (i.module === correspondingImport.module && i.field === correspondingImport.field) {
+                    exportedImport = i;
+                    break;
+                }
+            }
+            if (typeof(type) === "undefined")
+                type = exportedImport.type;
+            if (builder._checked)
+                assert.eq(type, exportedImport.type, `Re-exporting import "${exportedImport.field}" as "${field}" has mismatching type`);
+        }
+        section.data.push({ field: field, type: type, kind: "Function", index: index });
+        return _errorHandlingProxyFor(nextBuilder);
+    };
+};
+
+const _normalizeMutability = (mutability) => {
+    if (mutability === "mutable")
+        return 1;
+    else if (mutability === "immutable")
+        return 0;
+    else
+        throw new Error(`mutability should be either "mutable" or "immutable", but got ${mutability}`);
+};
+
+const _exportGlobalContinuation = (builder, section, nextBuilder) => {
+    return (field, index) => {
+        assert.isNumber(index, `Global exports only support number indices right now`);
+        section.data.push({ field, kind: "Global", index });
+        return _errorHandlingProxyFor(nextBuilder);
+    }
+};
+
+const _exportMemoryContinuation = (builder, section, nextBuilder) => {
+    return (field, index) => {
+        assert.isNumber(index, `Memory exports only support number indices`);
+        section.data.push({field, kind: "Memory", index});
+        return _errorHandlingProxyFor(nextBuilder);
+    }
+};
+
+const _exportTableContinuation = (builder, section, nextBuilder) => {
+    return (field, index) => {
+        assert.isNumber(index, `Table exports only support number indices`);
+        section.data.push({field, kind: "Table", index});
+        return _errorHandlingProxyFor(nextBuilder);
+    }
+};
+
+const _importGlobalContinuation = (builder, section, nextBuilder) => {
+    return () => {
+        const globalBuilder = {
+            End: () => nextBuilder
+        };
+        for (let op of WASM.description.value_type) {
+            globalBuilder[_toJavaScriptName(op)] = (module, field, mutability) => {
+                assert.isString(module, `Import global module should be a string, got "${module}"`);
+                assert.isString(field, `Import global field should be a string, got "${field}"`);
+                assert.isString(mutability, `Import global mutability should be a string, got "${mutability}"`);
+                section.data.push({ globalDescription: { type: op, mutability: _normalizeMutability(mutability) }, module, field, kind: "Global" });
+                return _errorHandlingProxyFor(globalBuilder);
+            };
+        }
+        return _errorHandlingProxyFor(globalBuilder);
+    };
+};
+
+const _checkStackArgs = (op, param) => {
+    for (let expect of param) {
+        if (WASM.isValidType(expect)) {
+            // FIXME implement stack checks for arguments. https://bugs.webkit.org/show_bug.cgi?id=163421
+        } else {
+            // Handle our own meta-types.
+            switch (expect) {
+            case "addr": break; // FIXME implement addr. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "any": break; // FIXME implement any. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "bool": break; // FIXME implement bool. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "call": break; // FIXME implement call stack argument checks based on function signature. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "global": break; // FIXME implement global. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "local": break; // FIXME implement local. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "prev": break; // FIXME implement prev, checking for whetever the previous value was. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "size": break; // FIXME implement size. https://bugs.webkit.org/show_bug.cgi?id=163421
+            default: throw new Error(`Implementation problem: unhandled meta-type "${expect}" on "${op}"`);
+            }
+        }
+    }
+}
+
+const _checkStackReturn = (op, ret) => {
+    for (let expect of ret) {
+        if (WASM.isValidType(expect)) {
+            // FIXME implement stack checks for return. https://bugs.webkit.org/show_bug.cgi?id=163421
+        } else {
+            // Handle our own meta-types.
+            switch (expect) {
+            case "any": break;
+            case "bool": break; // FIXME implement bool. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "call": break; // FIXME implement call stack return check based on function signature. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "control": break; // FIXME implement control. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "global": break; // FIXME implement global. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "local": break; // FIXME implement local. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "prev": break; // FIXME implement prev, checking for whetever the parameter type was. https://bugs.webkit.org/show_bug.cgi?id=163421
+            case "size": break; // FIXME implement size. https://bugs.webkit.org/show_bug.cgi?id=163421
+            default: throw new Error(`Implementation problem: unhandled meta-type "${expect}" on "${op}"`);
+            }
+        }
+    }
+};
+
+const _checkImms = (op, imms, expectedImms, ret) => {
+    const minExpectedImms = expectedImms.filter(i => i.type.slice(-1) !== '*').length;
+    if (minExpectedImms !== expectedImms.length)
+        assert.ge(imms.length, minExpectedImms, `"${op}" expects at least ${minExpectedImms} immediate${minExpectedImms !== 1 ? 's' : ''}, got ${imms.length}`);
+    else
+         assert.eq(imms.length, minExpectedImms, `"${op}" expects exactly ${minExpectedImms} immediate${minExpectedImms !== 1 ? 's' : ''}, got ${imms.length}`);
+    for (let idx = 0; idx !== expectedImms.length; ++idx) {
+        const got = imms[idx];
+        const expect = expectedImms[idx];
+        switch (expect.name) {
+        case "function_index":
+            assert.truthy(_isValidValue(got, "i32") && got >= 0, `Invalid value on ${op}: got "${got}", expected non-negative i32`);
+            // FIXME check function indices. https://bugs.webkit.org/show_bug.cgi?id=163421
+            break;
+        case "local_index": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "global_index": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "type_index": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "value":
+            assert.truthy(_isValidValue(got, ret[0]), `Invalid value on ${op}: got "${got}", expected ${ret[0]}`);
+            break;
+        case "flags": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "offset": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+            // Control:
+        case "default_target": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "relative_depth": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "sig":
+            assert.truthy(WASM.isValidBlockType(imms[idx]), `Invalid block type on ${op}: "${imms[idx]}"`);
+            break;
+        case "target_count": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "target_table": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "reserved": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        default: throw new Error(`Implementation problem: unhandled immediate "${expect.name}" on "${op}"`);
+        }
+    }
+};
+
+const _createFunctionBuilder = (func, builder, previousBuilder) => {
+    let functionBuilder = {};
+    for (const op in WASM.description.opcode) {
+        const name = _toJavaScriptName(op);
+        const value = WASM.description.opcode[op].value;
+        const ret = WASM.description.opcode[op]["return"];
+        const param = WASM.description.opcode[op].parameter;
+        const imm = WASM.description.opcode[op].immediate;
+
+        const checkStackArgs = builder._checked ? _checkStackArgs : () => {};
+        const checkStackReturn = builder._checked ? _checkStackReturn : () => {};
+        const checkImms = builder._checked ? _checkImms : () => {};
+
+        functionBuilder[name] = (...args) => {
+            let nextBuilder;
+            switch (name) {
+            default:
+                nextBuilder = functionBuilder;
+                break;
+            case "End":
+                nextBuilder = previousBuilder;
+                break;
+            case "Block":
+            case "Loop":
+            case "If":
+                nextBuilder = _createFunctionBuilder(func, builder, functionBuilder);
+                break;
+            }
+
+            // Passing a function as the argument is a way to nest blocks lexically.
+            const continuation = args[args.length - 1];
+            const hasContinuation = typeof(continuation) === "function";
+            const imms = hasContinuation ? args.slice(0, -1) : args; // FIXME: allow passing in stack values, as-if code were a stack machine. Just check for a builder to this function, and drop. https://bugs.webkit.org/show_bug.cgi?id=163422
+            checkImms(op, imms, imm, ret);
+            checkStackArgs(op, param);
+            checkStackReturn(op, ret);
+            const stackArgs = []; // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
+            func.code.push({ name: op, value: value, arguments: stackArgs, immediates: imms });
+            if (hasContinuation)
+                return _errorHandlingProxyFor(continuation(nextBuilder).End());
+            return _errorHandlingProxyFor(nextBuilder);
+        };
+    };
+
+    return _errorHandlingProxyFor(functionBuilder);
+}
+
+const _createFunction = (section, builder, previousBuilder) => {
+    return (...args) => {
+        const nameOffset = (typeof(args[0]) === "string") >>> 0;
+        const functionName = nameOffset ? args[0] : undefined;
+        let signature = args[0 + nameOffset];
+        const locals = args[1 + nameOffset] === undefined ? [] : args[1 + nameOffset];
+        for (const local of locals)
+            assert.truthy(WASM.isValidValueType(local), `Type of local: ${local} needs to be a valid value type`);
+
+        if (typeof(signature) === "undefined")
+            signature = { params: [] };
+
+        let type;
+        let params;
+        if (typeof signature === "object") {
+            assert.hasObjectProperty(signature, "params", `Expect function signature to be an object with a "params" field, got "${signature}"`);
+            let ret;
+            ([params, ret] = _normalizeFunctionSignature(signature.params, signature.ret));
+            signature = {params, ret};
+            type = _maybeRegisterType(builder, signature);
+        } else {
+            assert.truthy(typeof signature === "number");
+            const typeSection = builder._getSection("Type");
+            assert.truthy(!!typeSection);
+            // FIXME: we should allow indices that exceed this to be able to
+            // test JSCs validator is correct. https://bugs.webkit.org/show_bug.cgi?id=165786
+            assert.truthy(signature < typeSection.data.length);
+            type = signature;
+            signature = typeSection.data[signature];
+            assert.hasObjectProperty(signature, "params", `Expect function signature to be an object with a "params" field, got "${signature}"`);
+            params = signature.params;
+        }
+
+        const func = {
+            name: functionName,
+            type,
+            signature: signature,
+            locals: params.concat(locals), // Parameters are the first locals.
+            parameterCount: params.length,
+            code: []
+        };
+
+        const functionSection = builder._getSection("Function");
+        if (functionSection)
+            functionSection.data.push(func.type);
+
+        section.data.push(func);
+        builder._registerFunctionToIndexSpace(functionName);
+
+        return _createFunctionBuilder(func, builder, previousBuilder);
+    }
+};
+
+class Builder {
+    constructor() {
+        this.setChecked(true);
+        let preamble = {};
+        for (const p of WASM.description.preamble)
+            preamble[p.name] = p.value;
+        this.setPreamble(preamble);
+        this._sections = [];
+        this._functionIndexSpace = new Map();
+        this._functionIndexSpaceCount = 0;
+        this._registerSectionBuilders();
+    }
+    setChecked(checked) {
+        this._checked = checked;
+        return this;
+    }
+    setPreamble(p) {
+        this._preamble = Object.assign(this._preamble || {}, p);
+        return this;
+    }
+    _functionIndexSpaceKeyHash(obj) {
+        // We don't need a full hash, just something that has a defined order for Map. Objects we insert aren't nested.
+        if (typeof(obj) !== 'object')
+            return obj;
+        const keys = Object.keys(obj).sort();
+        let entries = [];
+        for (let k in keys)
+            entries.push([k, obj[k]]);
+        return JSON.stringify(entries);
+    }
+    _registerFunctionToIndexSpace(name) {
+        if (typeof(name) === "undefined") {
+            // Registering a nameless function still adds it to the function index space. Register it as something that can't normally be registered.
+            name = {};
+        }
+        const value = this._functionIndexSpaceCount++;
+        // Collisions are fine: we'll simply count the function and forget the previous one.
+        this._functionIndexSpace.set(this._functionIndexSpaceKeyHash(name), value);
+        // Map it both ways, the number space is distinct from the name space.
+        this._functionIndexSpace.set(this._functionIndexSpaceKeyHash(value), name);
+    }
+    _getFunctionFromIndexSpace(name) {
+        return this._functionIndexSpace.get(this._functionIndexSpaceKeyHash(name));
+    }
+    _registerSectionBuilders() {
+        for (const section in WASM.description.section) {
+            switch (section) {
+            case "Type":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const builder = this;
+                    const typeBuilder = {
+                        End: () => builder,
+                        Func: (params, ret) => {
+                            [params, ret] = _normalizeFunctionSignature(params, ret);
+                            s.data.push({ params: params, ret: ret });
+                            return _errorHandlingProxyFor(typeBuilder);
+                        },
+                    };
+                    return _errorHandlingProxyFor(typeBuilder);
+                };
+                break;
+
+            case "Import":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const importBuilder = {
+                        End: () => this,
+                    };
+                    importBuilder.Global = _importGlobalContinuation(this, s, importBuilder);
+                    importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
+                    importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
+                    importBuilder.Table = _importTableContinuation(this, s, importBuilder);
+                    return _errorHandlingProxyFor(importBuilder);
+                };
+                break;
+
+            case "Function":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const functionBuilder = {
+                        End: () => this
+                        // FIXME: add ability to add this with whatever.
+                    };
+                    return _errorHandlingProxyFor(functionBuilder);
+                };
+                break;
+
+            case "Table":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const tableBuilder = {
+                        End: () => this,
+                        Table: ({initial, maximum, element}) => {
+                            s.data.push({tableDescription: {initial, maximum, element}});
+                            return _errorHandlingProxyFor(tableBuilder);
+                        }
+                    };
+                    return _errorHandlingProxyFor(tableBuilder);
+                };
+                break;
+
+            case "Memory":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const memoryBuilder = {
+                        End: () => this,
+                        InitialMaxPages: (initial, max) => {
+                            s.data.push({ initial, max });
+                            return _errorHandlingProxyFor(memoryBuilder);
+                        }
+                    };
+                    return _errorHandlingProxyFor(memoryBuilder);
+                };
+                break;
+
+            case "Global":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const globalBuilder = {
+                        End: () => this,
+                        GetGlobal: (type, initValue, mutability) => {
+                            s.data.push({ type, op: "get_global", mutability: _normalizeMutability(mutability), initValue });
+                            return _errorHandlingProxyFor(globalBuilder);
+                        }
+                    };
+                    for (let op of WASM.description.value_type) {
+                        globalBuilder[_toJavaScriptName(op)] = (initValue, mutability) => {
+                            s.data.push({ type: op, op: op + ".const", mutability: _normalizeMutability(mutability), initValue });
+                            return _errorHandlingProxyFor(globalBuilder);
+                        };
+                    }
+                    return _errorHandlingProxyFor(globalBuilder);
+                };
+                break;
+
+            case "Export":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const exportBuilder = {
+                        End: () => this,
+                    };
+                    exportBuilder.Global = _exportGlobalContinuation(this, s, exportBuilder);
+                    exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
+                    exportBuilder.Memory = _exportMemoryContinuation(this, s, exportBuilder);
+                    exportBuilder.Table = _exportTableContinuation(this, s, exportBuilder);
+                    return _errorHandlingProxyFor(exportBuilder);
+                };
+                break;
+
+            case "Start":
+                this[section] = function(functionIndexOrName) {
+                    const s = this._addSection(section);
+                    const startBuilder = {
+                        End: () => this,
+                    };
+                    if (typeof(functionIndexOrName) !== "number" && typeof(functionIndexOrName) !== "string")
+                        throw new Error(`Start section's function index  must either be a number or a string`);
+                    s.data.push(functionIndexOrName);
+                    return _errorHandlingProxyFor(startBuilder);
+                };
+                break;
+
+            case "Element":
+                this[section] = function(...args) {
+                    if (args.length !== 0)
+                        throw new Error("You're doing it wrong. This element does not take arguments. You must chain the call with another Element()");
+
+                    const s = this._addSection(section);
+                    const elementBuilder = {
+                        End: () => this,
+                        Element: ({tableIndex = 0, offset, functionIndices}) => {
+                            s.data.push({tableIndex, offset, functionIndices});
+                            return _errorHandlingProxyFor(elementBuilder);
+                        }
+                    };
+
+                    return _errorHandlingProxyFor(elementBuilder);
+                };
+                break;
+
+            case "Code":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const builder = this;
+                    const codeBuilder =  {
+                        End: () => {
+                            // We now have enough information to remap the export section's "type" and "index" according to the Code section we are currently ending.
+                            const typeSection = builder._getSection("Type");
+                            const importSection = builder._getSection("Import");
+                            const exportSection = builder._getSection("Export");
+                            const startSection = builder._getSection("Start");
+                            const codeSection = s;
+                            if (exportSection) {
+                                for (const e of exportSection.data) {
+                                    if (e.kind !== "Function" || typeof(e.type) !== "undefined")
+                                        continue;
+                                    switch (typeof(e.index)) {
+                                    default: throw new Error(`Unexpected export index "${e.index}"`);
+                                    case "string": {
+                                        const index = builder._getFunctionFromIndexSpace(e.index);
+                                        assert.isNumber(index, `Export section contains undefined function "${e.index}"`);
+                                        e.index = index;
+                                    } // Fallthrough.
+                                    case "number": {
+                                        const index = builder._getFunctionFromIndexSpace(e.index);
+                                        if (builder._checked)
+                                            assert.isNotUndef(index, `Export "${e.field}" does not correspond to a defined value in the function index space`);
+                                    } break;
+                                    case "undefined":
+                                        throw new Error(`Unimplemented: Function().End() with undefined export index`); // FIXME
+                                    }
+                                    if (typeof(e.type) === "undefined") {
+                                        // This must be a function export from the Code section (re-exports were handled earlier).
+                                        let functionIndexSpaceOffset = 0;
+                                        if (importSection) {
+                                            for (const {kind} of importSection.data) {
+                                                if (kind === "Function")
+                                                    ++functionIndexSpaceOffset;
+                                            }
+                                        }
+                                        const functionIndex = e.index - functionIndexSpaceOffset;
+                                        e.type = codeSection.data[functionIndex].type;
+                                    }
+                                }
+                            }
+                            if (startSection) {
+                                const start = startSection.data[0];
+                                let mapped = builder._getFunctionFromIndexSpace(start);
+                                if (!builder._checked) {
+                                    if (typeof(mapped) === "undefined")
+                                        mapped = start; // In unchecked mode, simply use what was provided if it's nonsensical.
+                                    assert.isA(start, "number"); // It can't be too nonsensical, otherwise we can't create a binary.
+                                    startSection.data[0] = start;
+                                } else {
+                                    if (typeof(mapped) === "undefined")
+                                        throw new Error(`Start section refers to non-existant function '${start}'`);
+                                    if (typeof(start) === "string" || typeof(start) === "object")
+                                        startSection.data[0] = mapped;
+                                    // FIXME in checked mode, test that the type is acceptable for start function. We probably want _registerFunctionToIndexSpace to also register types per index. https://bugs.webkit.org/show_bug.cgi?id=165658
+                                }
+                            }
+                            return _errorHandlingProxyFor(builder);
+                        },
+
+                    };
+                    codeBuilder.Function = _createFunction(s, builder, codeBuilder);
+                    return _errorHandlingProxyFor(codeBuilder);
+                };
+                break;
+
+            case "Data":
+                this[section] = function() {
+                    const s = this._addSection(section);
+                    const dataBuilder = {
+                        End: () => this,
+                        Segment: data => {
+                            assert.isArray(data);
+                            for (const datum of data) {
+                                assert.isNumber(datum);
+                                assert.ge(datum, 0);
+                                assert.le(datum, 0xff);
+                            }
+                            s.data.push({ data: data, index: 0, offset: 0 });
+                            let thisSegment = s.data[s.data.length - 1];
+                            const segmentBuilder = {
+                                End: () => dataBuilder,
+                                Index: index => {
+                                    assert.eq(index, 0); // Linear memory index must be zero in MVP.
+                                    thisSegment.index = index;
+                                    return _errorHandlingProxyFor(segmentBuilder);
+                                },
+                                Offset: offset => {
+                                    // FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
+                                    assert.isNumber(offset);
+                                    thisSegment.offset = offset;
+                                    return _errorHandlingProxyFor(segmentBuilder);
+                                },
+                            };
+                            return _errorHandlingProxyFor(segmentBuilder);
+                        },
+                    };
+                    return _errorHandlingProxyFor(dataBuilder);
+                };
+                break;
+
+            default:
+                this[section] = () => { throw new Error(`Unknown section type "${section}"`); };
+                break;
+            }
+        }
+
+        this.Unknown = function(name) {
+            const s = this._addSection(name);
+            const builder = this;
+            const unknownBuilder =  {
+                End: () => builder,
+                Byte: b => {
+                    assert.eq(b & 0xFF, b, `Unknown section expected byte, got: "${b}"`);
+                    s.data.push(b);
+                    return _errorHandlingProxyFor(unknownBuilder);
+                }
+            };
+            return _errorHandlingProxyFor(unknownBuilder);
+        };
+    }
+    _addSection(nameOrNumber, extraObject) {
+        const name = typeof(nameOrNumber) === "string" ? nameOrNumber : "";
+        const number = typeof(nameOrNumber) === "number" ? nameOrNumber : (WASM.description.section[name] ? WASM.description.section[name].value : _unknownSectionId);
+        if (this._checked) {
+            // Check uniqueness.
+            for (const s of this._sections)
+                if (number !== _unknownSectionId)
+                    assert.falsy(s.name === name && s.id === number, `Cannot have two sections with the same name "${name}" and ID ${number}`);
+            // Check ordering.
+            if ((number !== _unknownSectionId) && (this._sections.length !== 0)) {
+                for (let i = this._sections.length - 1; i >= 0; --i) {
+                    if (this._sections[i].id === _unknownSectionId)
+                        continue;
+                    assert.le(this._sections[i].id, number, `Bad section ordering: "${this._sections[i].name}" cannot precede "${name}"`);
+                    break;
+                }
+            }
+        }
+        const s = Object.assign({ name: name, id: number, data: [] }, extraObject || {});
+        this._sections.push(s);
+        return s;
+    }
+    _getSection(nameOrNumber) {
+        switch (typeof(nameOrNumber)) {
+        default: throw new Error(`Implementation problem: can not get section "${nameOrNumber}"`);
+        case "string":
+            for (const s of this._sections)
+                if (s.name === nameOrNumber)
+                    return s;
+            return undefined;
+        case "number":
+            for (const s of this._sections)
+                if (s.id === nameOrNumber)
+                    return s;
+            return undefined;
+        }
+    }
+    optimize() {
+        // FIXME Add more optimizations. https://bugs.webkit.org/show_bug.cgi?id=163424
+        return this;
+    }
+    json() {
+        const obj = {
+            preamble: this._preamble,
+            section: this._sections
+        };
+        // JSON.stringify serializes -0.0 as 0.0.
+        const replacer = (key, value) => {
+            if (value === 0.0 && 1.0 / value === -Infinity)
+                return "NEGATIVE_ZERO";
+            return value;
+        };
+        return JSON.stringify(obj, replacer);
+    }
+    AsmJS() {
+        "use asm"; // For speed.
+        // FIXME Create an asm.js equivalent string which can be eval'd. https://bugs.webkit.org/show_bug.cgi?id=163425
+        throw new Error("asm.js not implemented yet");
+    }
+    WebAssembly() { return BuildWebAssembly.Binary(this._preamble, this._sections); }
+};
+
+
+// ------ end builder
+
+if (this.importScripts) {
+    importScripts('../../../resources/js-test.js');
+    importScripts('shared.js');
+}
+
+description("Test that expected exceptions are thrown when storing a Wasm Module into a DB.");
+
+indexedDBTest(prepareDatabase, testDatabase);
+function prepareDatabase()
+{
+    db = event.target.result;
+
+    evalAndLog("store = db.createObjectStore('store')");
+
+    let builder = new Builder();
+    builder = builder.Type().End()
+        .Function().End()
+        .Export().Function("f1").End()
+        .Code()
+            .Function("f1", { params: ["i32"], ret: "i32" })
+                .GetLocal(0)
+                .GetLocal(0)
+                .I32Add();
+
+    const count = 2;
+    for (let i = 0; i < count; i++) {
+        builder = builder.GetLocal(0).I32Add();
+    }
+    builder = builder.Return().End().End();
+
+    module = new WebAssembly.Module(builder.WebAssembly().get());
+    evalAndExpectException("store.add(module, 'key')", "DOMException.DATA_CLONE_ERR");
+}
+
+function testDatabase()
+{
+    finishJSTest();
+}
diff --git a/LayoutTests/storage/indexeddb/wasm-exceptions-expected.txt b/LayoutTests/storage/indexeddb/wasm-exceptions-expected.txt
new file mode 100644 (file)
index 0000000..2b96b02
--- /dev/null
@@ -0,0 +1,18 @@
+Test that expected exceptions are thrown when storing a Wasm Module into a DB.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+store = db.createObjectStore('store')
+Expecting exception from store.add(module, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Exception message: Failed to store record in an IDBObjectStore: An object could not be cloned.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/wasm-exceptions.html b/LayoutTests/storage/indexeddb/wasm-exceptions.html
new file mode 100644 (file)
index 0000000..02190d9
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<script src="resources/wasm-exceptions.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/workers/wasm-hashset-expected.txt b/LayoutTests/workers/wasm-hashset-expected.txt
new file mode 100644 (file)
index 0000000..99f58e0
--- /dev/null
@@ -0,0 +1,8 @@
+CONSOLE MESSAGE: line 98: about to start worker
+CONSOLE MESSAGE: line 107: Byte length of response: 52733
+CONSOLE MESSAGE: line 111: Got the wasm module from worker
+CONSOLE MESSAGE: line 8: Finished running
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/workers/wasm-hashset-many-2-expected.txt b/LayoutTests/workers/wasm-hashset-many-2-expected.txt
new file mode 100644 (file)
index 0000000..288334f
--- /dev/null
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: line 24: Got module in main test. Posting to all workers.
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 36: Worker finished
+CONSOLE MESSAGE: line 8: Finished running
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/workers/wasm-hashset-many-2.html b/LayoutTests/workers/wasm-hashset-many-2.html
new file mode 100644 (file)
index 0000000..05b4008
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+</script>
+<script src="./wasm-hashset/many-test-2.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/workers/wasm-hashset-many-expected.txt b/LayoutTests/workers/wasm-hashset-many-expected.txt
new file mode 100644 (file)
index 0000000..c42c66d
--- /dev/null
@@ -0,0 +1,21 @@
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 27: Worker finished
+CONSOLE MESSAGE: line 8: Finished running
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/workers/wasm-hashset-many.html b/LayoutTests/workers/wasm-hashset-many.html
new file mode 100644 (file)
index 0000000..f4c5fa2
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+</script>
+<script src="./wasm-hashset/many-test.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/workers/wasm-hashset.html b/LayoutTests/workers/wasm-hashset.html
new file mode 100644 (file)
index 0000000..803e3b9
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+</script>
+<script src="./wasm-hashset/test.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/workers/wasm-hashset/many-test-2.js b/LayoutTests/workers/wasm-hashset/many-test-2.js
new file mode 100644 (file)
index 0000000..179e9a5
--- /dev/null
@@ -0,0 +1,2020 @@
+"use strict";
+
+const __numWorkers = 16;
+let __count = 0;
+function reallyDone() {
+    if (++__count === __numWorkers) {
+        if (window.testRunner) {
+            __realPrint("Finished running");
+            testRunner.notifyDone();
+        }
+    }
+}
+
+let __realPrint = console.log.bind(console);
+console = {
+    log: function() {},
+    error: function() {},
+    assert: function(){},
+};
+
+let __workers = [];
+
+function postModuleToWorkers(module) {
+    __realPrint("Got module in main test. Posting to all workers.");
+    for (let worker of __workers)
+        worker.postMessage(module);
+}
+
+for (let i = 0; i < __numWorkers; ++i) {
+    let worker = new Worker("./wasm-hashset/many-worker-2.js");
+    worker.onmessage = (e) => {
+        if (e.data !== "done") {
+            throw new Error("Bad!");
+        }
+
+        __realPrint("Worker finished");
+        reallyDone();
+    }
+    __workers.push(worker);
+};
+
+
+      var Module = {
+        preRun: [],
+        postRun: [],
+        print: (function() {
+            return function(){};
+          var element = document.getElementById('output');
+          if (element) element.value = ''; // clear browser cache
+          return function(text) {
+            if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+            // These replacements are necessary if you render to raw HTML
+            //text = text.replace(/&/g, "&amp;");
+            //text = text.replace(/</g, "&lt;");
+            //text = text.replace(/>/g, "&gt;");
+            //text = text.replace('\n', '<br>', 'g');
+            console.log(text);
+            if (element) {
+              element.value += text + "\n";
+              element.scrollTop = element.scrollHeight; // focus on bottom
+            }
+          };
+        })(),
+        printErr: function(text) {
+          if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+          if (0) { // XXX disabled for safety typeof dump == 'function') {
+            dump(text + '\n'); // fast, straight to the real console
+          } else {
+            console.error(text);
+          }
+        },
+        canvas: (function() {
+            return;
+          var canvas = document.getElementById('canvas');
+
+          // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+          // application robust, you may want to override this behavior before shipping!
+          // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+          canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+          return canvas;
+        })(),
+        setStatus: function(text) {
+            console.log("Status: ", text);
+            return;
+
+          if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+          if (text === Module.setStatus.text) return;
+          var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+          var now = Date.now();
+          if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
+          if (m) {
+            text = m[1];
+            progressElement.value = parseInt(m[2])*100;
+            progressElement.max = parseInt(m[4])*100;
+            progressElement.hidden = false;
+            spinnerElement.hidden = false;
+          } else {
+            progressElement.value = null;
+            progressElement.max = null;
+            progressElement.hidden = true;
+            if (!text) spinnerElement.style.display = 'none';
+          }
+          statusElement.innerHTML = text;
+        },
+        totalDependencies: 0,
+        monitorRunDependencies: function(left) {
+          this.totalDependencies = Math.max(this.totalDependencies, left);
+          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+        }
+      };
+      Module.setStatus('Downloading...');
+
+          var xhr = new XMLHttpRequest();
+          xhr.open('GET', './wasm-hashset/test.wasm', true);
+          xhr.responseType = 'arraybuffer';
+          xhr.onload = function() {
+            Module.wasmBinary = xhr.response;
+if (!Module) Module = (typeof Module !== "undefined" ? Module : null) || {};
+var moduleOverrides = {};
+for (var key in Module) {
+ if (Module.hasOwnProperty(key)) {
+  moduleOverrides[key] = Module[key];
+ }
+}
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+if (Module["ENVIRONMENT"]) {
+ if (Module["ENVIRONMENT"] === "WEB") {
+  ENVIRONMENT_IS_WEB = true;
+ } else if (Module["ENVIRONMENT"] === "WORKER") {
+  ENVIRONMENT_IS_WORKER = true;
+ } else if (Module["ENVIRONMENT"] === "NODE") {
+  ENVIRONMENT_IS_NODE = true;
+ } else if (Module["ENVIRONMENT"] === "SHELL") {
+  ENVIRONMENT_IS_SHELL = true;
+ } else {
+  throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");
+ }
+} else {
+ ENVIRONMENT_IS_WEB = typeof window === "object";
+ ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
+ ENVIRONMENT_IS_NODE = typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+}
+if (ENVIRONMENT_IS_NODE) {
+ if (!Module["print"]) Module["print"] = console.log;
+ if (!Module["printErr"]) Module["printErr"] = console.warn;
+ var nodeFS;
+ var nodePath;
+ Module["read"] = function read(filename, binary) {
+  if (!nodeFS) nodeFS = require("fs");
+  if (!nodePath) nodePath = require("path");
+  filename = nodePath["normalize"](filename);
+  var ret = nodeFS["readFileSync"](filename);
+  return binary ? ret : ret.toString();
+ };
+ Module["readBinary"] = function readBinary(filename) {
+  var ret = Module["read"](filename, true);
+  if (!ret.buffer) {
+   ret = new Uint8Array(ret);
+  }
+  assert(ret.buffer);
+  return ret;
+ };
+ Module["load"] = function load(f) {
+  globalEval(read(f));
+ };
+ if (!Module["thisProgram"]) {
+  if (process["argv"].length > 1) {
+   Module["thisProgram"] = process["argv"][1].replace(/\\/g, "/");
+  } else {
+   Module["thisProgram"] = "unknown-program";
+  }
+ }
+ Module["arguments"] = process["argv"].slice(2);
+ if (typeof module !== "undefined") {
+  module["exports"] = Module;
+ }
+ process["on"]("uncaughtException", (function(ex) {
+  if (!(ex instanceof ExitStatus)) {
+   throw ex;
+  }
+ }));
+ Module["inspect"] = (function() {
+  return "[Emscripten Module object]";
+ });
+} else if (ENVIRONMENT_IS_SHELL) {
+ if (!Module["print"]) Module["print"] = print;
+ if (typeof printErr != "undefined") Module["printErr"] = printErr;
+ if (typeof read != "undefined") {
+  Module["read"] = read;
+ } else {
+  Module["read"] = function read() {
+   throw "no read() available";
+  };
+ }
+ Module["readBinary"] = function readBinary(f) {
+  if (typeof readbuffer === "function") {
+   return new Uint8Array(readbuffer(f));
+  }
+  var data = read(f, "binary");
+  assert(typeof data === "object");
+  return data;
+ };
+ if (typeof scriptArgs != "undefined") {
+  Module["arguments"] = scriptArgs;
+ } else if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module["read"] = function read(url) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, false);
+  xhr.send(null);
+  return xhr.responseText;
+ };
+ Module["readAsync"] = function readAsync(url, onload, onerror) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, true);
+  xhr.responseType = "arraybuffer";
+  xhr.onload = function xhr_onload() {
+   if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
+    onload(xhr.response);
+   } else {
+    onerror();
+   }
+  };
+  xhr.onerror = onerror;
+  xhr.send(null);
+ };
+ if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+ if (typeof console !== "undefined") {
+  if (!Module["print"]) Module["print"] = function print(x) {
+   console.log(x);
+  };
+  if (!Module["printErr"]) Module["printErr"] = function printErr(x) {
+   console.warn(x);
+  };
+ } else {
+  var TRY_USE_DUMP = false;
+  if (!Module["print"]) Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function(x) {
+   dump(x);
+  }) : (function(x) {});
+ }
+ if (ENVIRONMENT_IS_WORKER) {
+  Module["load"] = importScripts;
+ }
+ if (typeof Module["setWindowTitle"] === "undefined") {
+  Module["setWindowTitle"] = (function(title) {
+   document.title = title;
+  });
+ }
+} else {
+ throw "Unknown runtime environment. Where are we?";
+}
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module["load"] && Module["read"]) {
+ Module["load"] = function load(f) {
+  globalEval(Module["read"](f));
+ };
+}
+if (!Module["print"]) {
+ Module["print"] = (function() {});
+}
+if (!Module["printErr"]) {
+ Module["printErr"] = Module["print"];
+}
+if (!Module["arguments"]) {
+ Module["arguments"] = [];
+}
+if (!Module["thisProgram"]) {
+ Module["thisProgram"] = "./this.program";
+}
+Module.print = Module["print"];
+Module.printErr = Module["printErr"];
+Module["preRun"] = [];
+Module["postRun"] = [];
+for (var key in moduleOverrides) {
+ if (moduleOverrides.hasOwnProperty(key)) {
+  Module[key] = moduleOverrides[key];
+ }
+}
+moduleOverrides = undefined;
+var Runtime = {
+ setTempRet0: (function(value) {
+  tempRet0 = value;
+  return value;
+ }),
+ getTempRet0: (function() {
+  return tempRet0;
+ }),
+ stackSave: (function() {
+  return STACKTOP;
+ }),
+ stackRestore: (function(stackTop) {
+  STACKTOP = stackTop;
+ }),
+ getNativeTypeSize: (function(type) {
+  switch (type) {
+  case "i1":
+  case "i8":
+   return 1;
+  case "i16":
+   return 2;
+  case "i32":
+   return 4;
+  case "i64":
+   return 8;
+  case "float":
+   return 4;
+  case "double":
+   return 8;
+  default:
+   {
+    if (type[type.length - 1] === "*") {
+     return Runtime.QUANTUM_SIZE;
+    } else if (type[0] === "i") {
+     var bits = parseInt(type.substr(1));
+     assert(bits % 8 === 0);
+     return bits / 8;
+    } else {
+     return 0;
+    }
+   }
+  }
+ }),
+ getNativeFieldSize: (function(type) {
+  return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
+ }),
+ STACK_ALIGN: 16,
+ prepVararg: (function(ptr, type) {
+  if (type === "double" || type === "i64") {
+   if (ptr & 7) {
+    assert((ptr & 7) === 4);
+    ptr += 4;
+   }
+  } else {
+   assert((ptr & 3) === 0);
+  }
+  return ptr;
+ }),
+ getAlignSize: (function(type, size, vararg) {
+  if (!vararg && (type == "i64" || type == "double")) return 8;
+  if (!type) return Math.min(size, 8);
+  return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
+ }),
+ dynCall: (function(sig, ptr, args) {
+  if (args && args.length) {
+   return Module["dynCall_" + sig].apply(null, [ ptr ].concat(args));
+  } else {
+   return Module["dynCall_" + sig].call(null, ptr);
+  }
+ }),
+ functionPointers: [],
+ addFunction: (function(func) {
+  for (var i = 0; i < Runtime.functionPointers.length; i++) {
+   if (!Runtime.functionPointers[i]) {
+    Runtime.functionPointers[i] = func;
+    return 2 * (1 + i);
+   }
+  }
+  throw "Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";
+ }),
+ removeFunction: (function(index) {
+  Runtime.functionPointers[(index - 2) / 2] = null;
+ }),
+ warnOnce: (function(text) {
+  if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+  if (!Runtime.warnOnce.shown[text]) {
+   Runtime.warnOnce.shown[text] = 1;
+   Module.printErr(text);
+  }
+ }),
+ funcWrappers: {},
+ getFuncWrapper: (function(func, sig) {
+  assert(sig);
+  if (!Runtime.funcWrappers[sig]) {
+   Runtime.funcWrappers[sig] = {};
+  }
+  var sigCache = Runtime.funcWrappers[sig];
+  if (!sigCache[func]) {
+   if (sig.length === 1) {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func);
+    };
+   } else if (sig.length === 2) {
+    sigCache[func] = function dynCall_wrapper(arg) {
+     return Runtime.dynCall(sig, func, [ arg ]);
+    };
+   } else {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func, Array.prototype.slice.call(arguments));
+    };
+   }
+  }
+  return sigCache[func];
+ }),
+ getCompilerSetting: (function(name) {
+  throw "You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";
+ }),
+ stackAlloc: (function(size) {
+  var ret = STACKTOP;
+  STACKTOP = STACKTOP + size | 0;
+  STACKTOP = STACKTOP + 15 & -16;
+  return ret;
+ }),
+ staticAlloc: (function(size) {
+  var ret = STATICTOP;
+  STATICTOP = STATICTOP + size | 0;
+  STATICTOP = STATICTOP + 15 & -16;
+  return ret;
+ }),
+ dynamicAlloc: (function(size) {
+  var ret = HEAP32[DYNAMICTOP_PTR >> 2];
+  var end = (ret + size + 15 | 0) & -16;
+  HEAP32[DYNAMICTOP_PTR >> 2] = end;
+  if (end >= TOTAL_MEMORY) {
+   var success = enlargeMemory();
+   if (!success) {
+    HEAP32[DYNAMICTOP_PTR >> 2] = ret;
+    return 0;
+   }
+  }
+  return ret;
+ }),
+ alignMemory: (function(size, quantum) {
+  var ret = size = Math.ceil(size / (quantum ? quantum : 16)) * (quantum ? quantum : 16);
+  return ret;
+ }),
+ makeBigInt: (function(low, high, unsigned) {
+  var ret = unsigned ? +(low >>> 0) + +(high >>> 0) * 4294967296 : +(low >>> 0) + +(high | 0) * 4294967296;
+  return ret;
+ }),
+ GLOBAL_BASE: 1024,
+ QUANTUM_SIZE: 4,
+ __dummy__: 0
+};
+Module["Runtime"] = Runtime;
+var ABORT = 0;
+var EXITSTATUS = 0;
+function assert(condition, text) {
+ if (!condition) {
+  abort("Assertion failed: " + text);
+ }
+}
+function getCFunc(ident) {
+ var func = Module["_" + ident];
+ if (!func) {
+  try {
+   func = eval("_" + ident);
+  } catch (e) {}
+ }
+ assert(func, "Cannot call unknown function " + ident + " (perhaps LLVM optimizations or closure removed it?)");
+ return func;
+}
+var cwrap, ccall;
+((function() {
+ var JSfuncs = {
+  "stackSave": (function() {
+   Runtime.stackSave();
+  }),
+  "stackRestore": (function() {
+   Runtime.stackRestore();
+  }),
+  "arrayToC": (function(arr) {
+   var ret = Runtime.stackAlloc(arr.length);
+   writeArrayToMemory(arr, ret);
+   return ret;
+  }),
+  "stringToC": (function(str) {
+   var ret = 0;
+   if (str !== null && str !== undefined && str !== 0) {
+    var len = (str.length << 2) + 1;
+    ret = Runtime.stackAlloc(len);
+    stringToUTF8(str, ret, len);
+   }
+   return ret;
+  })
+ };
+ var toC = {
+  "string": JSfuncs["stringToC"],
+  "array": JSfuncs["arrayToC"]
+ };
+ ccall = function ccallFunc(ident, returnType, argTypes, args, opts) {
+  var func = getCFunc(ident);
+  var cArgs = [];
+  var stack = 0;
+  if (args) {
+   for (var i = 0; i < args.length; i++) {
+    var converter = toC[argTypes[i]];
+    if (converter) {
+     if (stack === 0) stack = Runtime.stackSave();
+     cArgs[i] = converter(args[i]);
+    } else {
+     cArgs[i] = args[i];
+    }
+   }
+  }
+  var ret = func.apply(null, cArgs);
+  if (returnType === "string") ret = Pointer_stringify(ret);
+  if (stack !== 0) {
+   if (opts && opts.async) {
+    EmterpreterAsync.asyncFinalizers.push((function() {
+     Runtime.stackRestore(stack);
+    }));
+    return;
+   }
+   Runtime.stackRestore(stack);
+  }
+  return ret;
+ };
+ var sourceRegex = /^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
+ function parseJSFunc(jsfunc) {
+  var parsed = jsfunc.toString().match(sourceRegex).slice(1);
+  return {
+   arguments: parsed[0],
+   body: parsed[1],
+   returnValue: parsed[2]
+  };
+ }
+ var JSsource = null;
+ function ensureJSsource() {
+  if (!JSsource) {
+   JSsource = {};
+   for (var fun in JSfuncs) {
+    if (JSfuncs.hasOwnProperty(fun)) {
+     JSsource[fun] = parseJSFunc(JSfuncs[fun]);
+    }
+   }
+  }
+ }
+ cwrap = function cwrap(ident, returnType, argTypes) {
+  argTypes = argTypes || [];
+  var cfunc = getCFunc(ident);
+  var numericArgs = argTypes.every((function(type) {
+   return type === "number";
+  }));
+  var numericRet = returnType !== "string";
+  if (numericRet && numericArgs) {
+   return cfunc;
+  }
+  var argNames = argTypes.map((function(x, i) {
+   return "$" + i;
+  }));
+  var funcstr = "(function(" + argNames.join(",") + ") {";
+  var nargs = argTypes.length;
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += "var stack = " + JSsource["stackSave"].body + ";";
+   for (var i = 0; i < nargs; i++) {
+    var arg = argNames[i], type = argTypes[i];
+    if (type === "number") continue;
+    var convertCode = JSsource[type + "ToC"];
+    funcstr += "var " + convertCode.arguments + " = " + arg + ";";
+    funcstr += convertCode.body + ";";
+    funcstr += arg + "=(" + convertCode.returnValue + ");";
+   }
+  }
+  var cfuncname = parseJSFunc((function() {
+   return cfunc;
+  })).returnValue;
+  funcstr += "var ret = " + cfuncname + "(" + argNames.join(",") + ");";
+  if (!numericRet) {
+   var strgfy = parseJSFunc((function() {
+    return Pointer_stringify;
+   })).returnValue;
+   funcstr += "ret = " + strgfy + "(ret);";
+  }
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += JSsource["stackRestore"].body.replace("()", "(stack)") + ";";
+  }
+  funcstr += "return ret})";
+  return eval(funcstr);
+ };
+}))();
+Module["ccall"] = ccall;
+Module["cwrap"] = cwrap;
+function setValue(ptr, value, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i8":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i16":
+  HEAP16[ptr >> 1] = value;
+  break;
+ case "i32":
+  HEAP32[ptr >> 2] = value;
+  break;
+ case "i64":
+  tempI64 = [ value >>> 0, (tempDouble = value, +Math_abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
+  break;
+ case "float":
+  HEAPF32[ptr >> 2] = value;
+  break;
+ case "double":
+  HEAPF64[ptr >> 3] = value;
+  break;
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+}
+Module["setValue"] = setValue;
+function getValue(ptr, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  return HEAP8[ptr >> 0];
+ case "i8":
+  return HEAP8[ptr >> 0];
+ case "i16":
+  return HEAP16[ptr >> 1];
+ case "i32":
+  return HEAP32[ptr >> 2];
+ case "i64":
+  return HEAP32[ptr >> 2];
+ case "float":
+  return HEAPF32[ptr >> 2];
+ case "double":
+  return HEAPF64[ptr >> 3];
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+ return null;
+}
+Module["getValue"] = getValue;
+var ALLOC_NORMAL = 0;
+var ALLOC_STACK = 1;
+var ALLOC_STATIC = 2;
+var ALLOC_DYNAMIC = 3;
+var ALLOC_NONE = 4;
+Module["ALLOC_NORMAL"] = ALLOC_NORMAL;
+Module["ALLOC_STACK"] = ALLOC_STACK;
+Module["ALLOC_STATIC"] = ALLOC_STATIC;
+Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC;
+Module["ALLOC_NONE"] = ALLOC_NONE;
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === "number") {
+  zeroinit = true;
+  size = slab;
+ } else {
+  zeroinit = false;
+  size = slab.length;
+ }
+ var singleType = typeof types === "string" ? types : null;
+ var ret;
+ if (allocator == ALLOC_NONE) {
+  ret = ptr;
+ } else {
+  ret = [ typeof _malloc === "function" ? _malloc : Runtime.staticAlloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc ][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+ if (zeroinit) {
+  var ptr = ret, stop;
+  assert((ret & 3) == 0);
+  stop = ret + (size & ~3);
+  for (; ptr < stop; ptr += 4) {
+   HEAP32[ptr >> 2] = 0;
+  }
+  stop = ret + size;
+  while (ptr < stop) {
+   HEAP8[ptr++ >> 0] = 0;
+  }
+  return ret;
+ }
+ if (singleType === "i8") {
+  if (slab.subarray || slab.slice) {
+   HEAPU8.set(slab, ret);
+  } else {
+   HEAPU8.set(new Uint8Array(slab), ret);
+  }
+  return ret;
+ }
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+  var curr = slab[i];
+  if (typeof curr === "function") {
+   curr = Runtime.getFunctionIndex(curr);
+  }
+  type = singleType || types[i];
+  if (type === 0) {
+   i++;
+   continue;
+  }
+  if (type == "i64") type = "i32";
+  setValue(ret + i, curr, type);
+  if (previousType !== type) {
+   typeSize = Runtime.getNativeTypeSize(type);
+   previousType = type;
+  }
+  i += typeSize;
+ }
+ return ret;
+}
+Module["allocate"] = allocate;
+function getMemory(size) {
+ if (!staticSealed) return Runtime.staticAlloc(size);
+ if (!runtimeInitialized) return Runtime.dynamicAlloc(size);
+ return _malloc(size);
+}
+Module["getMemory"] = getMemory;
+function Pointer_stringify(ptr, length) {
+ if (length === 0 || !ptr) return "";
+ var hasUtf = 0;
+ var t;
+ var i = 0;
+ while (1) {
+  t = HEAPU8[ptr + i >> 0];
+  hasUtf |= t;
+  if (t == 0 && !length) break;
+  i++;
+  if (length && i == length) break;
+ }
+ if (!length) length = i;
+ var ret = "";
+ if (hasUtf < 128) {
+  var MAX_CHUNK = 1024;
+  var curr;
+  while (length > 0) {
+   curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+   ret = ret ? ret + curr : curr;
+   ptr += MAX_CHUNK;
+   length -= MAX_CHUNK;
+  }
+  return ret;
+ }
+ return Module["UTF8ToString"](ptr);
+}
+Module["Pointer_stringify"] = Pointer_stringify;
+function AsciiToString(ptr) {
+ var str = "";
+ while (1) {
+  var ch = HEAP8[ptr++ >> 0];
+  if (!ch) return str;
+  str += String.fromCharCode(ch);
+ }
+}
+Module["AsciiToString"] = AsciiToString;
+function stringToAscii(str, outPtr) {
+ return writeAsciiToMemory(str, outPtr, false);
+}
+Module["stringToAscii"] = stringToAscii;
+var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;
+function UTF8ArrayToString(u8Array, idx) {
+ var endPtr = idx;
+ while (u8Array[endPtr]) ++endPtr;
+ if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
+  return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
+ } else {
+  var u0, u1, u2, u3, u4, u5;
+  var str = "";
+  while (1) {
+   u0 = u8Array[idx++];
+   if (!u0) return str;
+   if (!(u0 & 128)) {
+    str += String.fromCharCode(u0);
+    continue;
+   }
+   u1 = u8Array[idx++] & 63;
+   if ((u0 & 224) == 192) {
+    str += String.fromCharCode((u0 & 31) << 6 | u1);
+    continue;
+   }
+   u2 = u8Array[idx++] & 63;
+   if ((u0 & 240) == 224) {
+    u0 = (u0 & 15) << 12 | u1 << 6 | u2;
+   } else {
+    u3 = u8Array[idx++] & 63;
+    if ((u0 & 248) == 240) {
+     u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3;
+    } else {
+     u4 = u8Array[idx++] & 63;
+     if ((u0 & 252) == 248) {
+      u0 = (u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4;
+     } else {
+      u5 = u8Array[idx++] & 63;
+      u0 = (u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | u5;
+     }
+    }
+   }
+   if (u0 < 65536) {
+    str += String.fromCharCode(u0);
+   } else {
+    var ch = u0 - 65536;
+    str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
+   }
+  }
+ }
+}
+Module["UTF8ArrayToString"] = UTF8ArrayToString;
+function UTF8ToString(ptr) {
+ return UTF8ArrayToString(HEAPU8, ptr);
+}
+Module["UTF8ToString"] = UTF8ToString;
+function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   if (outIdx >= endIdx) break;
+   outU8Array[outIdx++] = u;
+  } else if (u <= 2047) {
+   if (outIdx + 1 >= endIdx) break;
+   outU8Array[outIdx++] = 192 | u >> 6;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 65535) {
+   if (outIdx + 2 >= endIdx) break;
+   outU8Array[outIdx++] = 224 | u >> 12;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 2097151) {
+   if (outIdx + 3 >= endIdx) break;
+   outU8Array[outIdx++] = 240 | u >> 18;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 67108863) {
+   if (outIdx + 4 >= endIdx) break;
+   outU8Array[outIdx++] = 248 | u >> 24;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else {
+   if (outIdx + 5 >= endIdx) break;
+   outU8Array[outIdx++] = 252 | u >> 30;
+   outU8Array[outIdx++] = 128 | u >> 24 & 63;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  }
+ }
+ outU8Array[outIdx] = 0;
+ return outIdx - startIdx;
+}
+Module["stringToUTF8Array"] = stringToUTF8Array;
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+}
+Module["stringToUTF8"] = stringToUTF8;
+function lengthBytesUTF8(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   ++len;
+  } else if (u <= 2047) {
+   len += 2;
+  } else if (u <= 65535) {
+   len += 3;
+  } else if (u <= 2097151) {
+   len += 4;
+  } else if (u <= 67108863) {
+   len += 5;
+  } else {
+   len += 6;
+  }
+ }
+ return len;
+}
+Module["lengthBytesUTF8"] = lengthBytesUTF8;
+var UTF16Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le") : undefined;
+function demangle(func) {
+ var __cxa_demangle_func = Module["___cxa_demangle"] || Module["__cxa_demangle"];
+ if (__cxa_demangle_func) {
+  try {
+   var s = func.substr(1);
+   var len = lengthBytesUTF8(s) + 1;
+   var buf = _malloc(len);
+   stringToUTF8(s, buf, len);
+   var status = _malloc(4);
+   var ret = __cxa_demangle_func(buf, 0, 0, status);
+   if (getValue(status, "i32") === 0 && ret) {
+    return Pointer_stringify(ret);
+   }
+  } catch (e) {} finally {
+   if (buf) _free(buf);
+   if (status) _free(status);
+   if (ret) _free(ret);
+  }
+  return func;
+ }
+ Runtime.warnOnce("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");
+ return func;
+}
+function demangleAll(text) {
+ var regex = /__Z[\w\d_]+/g;
+ return text.replace(regex, (function(x) {
+  var y = demangle(x);
+  return x === y ? x : x + " [" + y + "]";
+ }));
+}
+function jsStackTrace() {
+ var err = new Error;
+ if (!err.stack) {
+  try {
+   throw new Error(0);
+  } catch (e) {
+   err = e;
+  }
+  if (!err.stack) {
+   return "(no stack trace available)";
+  }
+ }
+ return err.stack.toString();
+}
+function stackTrace() {
+ var js = jsStackTrace();
+ if (Module["extraStackTrace"]) js += "\n" + Module["extraStackTrace"]();
+ return demangleAll(js);
+}
+Module["stackTrace"] = stackTrace;
+var WASM_PAGE_SIZE = 65536;
+var ASMJS_PAGE_SIZE = 16777216;
+function alignUp(x, multiple) {
+ if (x % multiple > 0) {
+  x += multiple - x % multiple;
+ }
+ return x;
+}
+var HEAP;
+var buffer;
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+function updateGlobalBuffer(buf) {
+ Module["buffer"] = buffer = buf;
+}
+function updateGlobalBufferViews() {
+ Module["HEAP8"] = HEAP8 = new Int8Array(buffer);
+ Module["HEAP16"] = HEAP16 = new Int16Array(buffer);
+ Module["HEAP32"] = HEAP32 = new Int32Array(buffer);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(buffer);
+ Module["HEAPU16"] = HEAPU16 = new Uint16Array(buffer);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(buffer);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(buffer);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(buffer);
+}
+var STATIC_BASE, STATICTOP, staticSealed;
+var STACK_BASE, STACKTOP, STACK_MAX;
+var DYNAMIC_BASE, DYNAMICTOP_PTR;
+STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
+staticSealed = false;
+function abortOnCannotGrowMemory() {
+ abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value " + TOTAL_MEMORY + ", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ");
+}
+function enlargeMemory() {
+ abortOnCannotGrowMemory();
+}
+var TOTAL_STACK = Module["TOTAL_STACK"] || 5242880;
+var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 629145600;
+if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was " + TOTAL_MEMORY + "! (TOTAL_STACK=" + TOTAL_STACK + ")");
+if (Module["buffer"]) {
+ buffer = Module["buffer"];
+} else {
+ if (typeof WebAssembly === "object" && typeof WebAssembly.Memory === "function") {
+  Module["wasmMemory"] = new WebAssembly.Memory({
+   initial: TOTAL_MEMORY / WASM_PAGE_SIZE,
+   maximum: TOTAL_MEMORY / WASM_PAGE_SIZE
+  });
+  buffer = Module["wasmMemory"].buffer;
+ } else {
+  buffer = new ArrayBuffer(TOTAL_MEMORY);
+ }
+}
+updateGlobalBufferViews();
+function getTotalMemory() {
+ return TOTAL_MEMORY;
+}
+HEAP32[0] = 1668509029;
+HEAP16[1] = 25459;
+if (HEAPU8[2] !== 115 || HEAPU8[3] !== 99) throw "Runtime error: expected the system to be little-endian!";
+Module["HEAP"] = HEAP;
+Module["buffer"] = buffer;
+Module["HEAP8"] = HEAP8;
+Module["HEAP16"] = HEAP16;
+Module["HEAP32"] = HEAP32;
+Module["HEAPU8"] = HEAPU8;
+Module["HEAPU16"] = HEAPU16;
+Module["HEAPU32"] = HEAPU32;
+Module["HEAPF32"] = HEAPF32;
+Module["HEAPF64"] = HEAPF64;
+function callRuntimeCallbacks(callbacks) {
+ while (callbacks.length > 0) {
+  var callback = callbacks.shift();
+  if (typeof callback == "function") {
+   callback();
+   continue;
+  }
+  var func = callback.func;
+  if (typeof func === "number") {
+   if (callback.arg === undefined) {
+    Module["dynCall_v"](func);
+   } else {
+    Module["dynCall_vi"](func, callback.arg);
+   }
+  } else {
+   func(callback.arg === undefined ? null : callback.arg);
+  }
+ }
+}
+var __ATPRERUN__ = [];
+var __ATINIT__ = [];
+var __ATMAIN__ = [];
+var __ATEXIT__ = [];
+var __ATPOSTRUN__ = [];
+var runtimeInitialized = false;
+var runtimeExited = false;
+function preRun() {
+ if (Module["preRun"]) {
+  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+  while (Module["preRun"].length) {
+   addOnPreRun(Module["preRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+function ensureInitRuntime() {
+ if (runtimeInitialized) return;
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
+function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
+ runtimeExited = true;
+}
+function postRun() {
+ if (Module["postRun"]) {
+  if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+  while (Module["postRun"].length) {
+   addOnPostRun(Module["postRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+Module["addOnPreRun"] = addOnPreRun;
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+Module["addOnInit"] = addOnInit;
+function addOnPreMain(cb) {
+ __ATMAIN__.unshift(cb);
+}
+Module["addOnPreMain"] = addOnPreMain;
+function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
+}
+Module["addOnExit"] = addOnExit;
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+Module["addOnPostRun"] = addOnPostRun;
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+Module["intArrayFromString"] = intArrayFromString;
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+  var chr = array[i];
+  if (chr > 255) {
+   chr &= 255;
+  }
+  ret.push(String.fromCharCode(chr));
+ }
+ return ret.join("");
+}
+Module["intArrayToString"] = intArrayToString;
+function writeStringToMemory(string, buffer, dontAddNull) {
+ Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");
+ var lastChar, end;
+ if (dontAddNull) {
+  end = buffer + lengthBytesUTF8(string);
+  lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar;
+}
+Module["writeStringToMemory"] = writeStringToMemory;
+function writeArrayToMemory(array, buffer) {
+ HEAP8.set(array, buffer);
+}
+Module["writeArrayToMemory"] = writeArrayToMemory;
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+  HEAP8[buffer++ >> 0] = str.charCodeAt(i);
+ }
+ if (!dontAddNull) HEAP8[buffer >> 0] = 0;
+}
+Module["writeAsciiToMemory"] = writeAsciiToMemory;
+if (!Math["imul"] || Math["imul"](4294967295, 5) !== -5) Math["imul"] = function imul(a, b) {
+ var ah = a >>> 16;
+ var al = a & 65535;
+ var bh = b >>> 16;
+ var bl = b & 65535;
+ return al * bl + (ah * bl + al * bh << 16) | 0;
+};
+Math.imul = Math["imul"];
+if (!Math["fround"]) {
+ var froundBuffer = new Float32Array(1);
+ Math["fround"] = (function(x) {
+  froundBuffer[0] = x;
+  return froundBuffer[0];
+ });
+}
+Math.fround = Math["fround"];
+if (!Math["clz32"]) Math["clz32"] = (function(x) {
+ x = x >>> 0;
+ for (var i = 0; i < 32; i++) {
+  if (x & 1 << 31 - i) return i;
+ }
+ return 32;
+});
+Math.clz32 = Math["clz32"];
+if (!Math["trunc"]) Math["trunc"] = (function(x) {
+ return x < 0 ? Math.ceil(x) : Math.floor(x);
+});
+Math.trunc = Math["trunc"];
+var Math_abs = Math.abs;
+var Math_cos = Math.cos;
+var Math_sin = Math.sin;
+var Math_tan = Math.tan;
+var Math_acos = Math.acos;
+var Math_asin = Math.asin;
+var Math_atan = Math.atan;
+var Math_atan2 = Math.atan2;
+var Math_exp = Math.exp;
+var Math_log = Math.log;
+var Math_sqrt = Math.sqrt;
+var Math_ceil = Math.ceil;
+var Math_floor = Math.floor;
+var Math_pow = Math.pow;
+var Math_imul = Math.imul;
+var Math_fround = Math.fround;
+var Math_round = Math.round;
+var Math_min = Math.min;
+var Math_clz32 = Math.clz32;
+var Math_trunc = Math.trunc;
+var runDependencies = 0;
+var runDependencyWatcher = null;
+var dependenciesFulfilled = null;
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+}
+Module["addRunDependency"] = addRunDependency;
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+ if (runDependencies == 0) {
+  if (runDependencyWatcher !== null) {
+   clearInterval(runDependencyWatcher);
+   runDependencyWatcher = null;
+  }
+  if (dependenciesFulfilled) {
+   var callback = dependenciesFulfilled;
+   dependenciesFulfilled = null;
+   callback();
+  }
+ }
+}
+Module["removeRunDependency"] = removeRunDependency;
+Module["preloadedImages"] = {};
+Module["preloadedAudios"] = {};
+var memoryInitializer = null;
+function integrateWasmJS(Module) {
+ var method = Module["wasmJSMethod"] || "native-wasm";
+ Module["wasmJSMethod"] = method;
+ var wasmTextFile = Module["wasmTextFile"] || "js-output.wast";
+ var wasmBinaryFile = Module["wasmBinaryFile"] || "js-output.wasm";
+ var asmjsCodeFile = Module["asmjsCodeFile"] || "js-output.temp.asm.js";
+ var wasmPageSize = 64 * 1024;
+ var asm2wasmImports = {
+  "f64-rem": (function(x, y) {
+   return x % y;
+  }),
+  "f64-to-int": (function(x) {
+   return x | 0;
+  }),
+  "i32s-div": (function(x, y) {
+   return (x | 0) / (y | 0) | 0;
+  }),
+  "i32u-div": (function(x, y) {
+   return (x >>> 0) / (y >>> 0) >>> 0;
+  }),
+  "i32s-rem": (function(x, y) {
+   return (x | 0) % (y | 0) | 0;
+  }),
+  "i32u-rem": (function(x, y) {
+   return (x >>> 0) % (y >>> 0) >>> 0;
+  }),
+  "debugger": (function() {
+   debugger;
+  })
+ };
+ var info = {
+  "global": null,
+  "env": null,
+  "asm2wasm": asm2wasmImports,
+  "parent": Module
+ };
+ var exports = null;
+ function lookupImport(mod, base) {
+  var lookup = info;
+  if (mod.indexOf(".") < 0) {
+   lookup = (lookup || {})[mod];
+  } else {
+   var parts = mod.split(".");
+   lookup = (lookup || {})[parts[0]];
+   lookup = (lookup || {})[parts[1]];
+  }
+  if (base) {
+   lookup = (lookup || {})[base];
+  }
+  if (lookup === undefined) {
+   abort("bad lookupImport to (" + mod + ")." + base);
+  }
+  return lookup;
+ }
+ function mergeMemory(newBuffer) {
+  var oldBuffer = Module["buffer"];
+  if (newBuffer.byteLength < oldBuffer.byteLength) {
+   Module["printErr"]("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");
+  }
+  var oldView = new Int8Array(oldBuffer);
+  var newView = new Int8Array(newBuffer);
+  if (!memoryInitializer) {
+   oldView.set(newView.subarray(Module["STATIC_BASE"], Module["STATIC_BASE"] + Module["STATIC_BUMP"]), Module["STATIC_BASE"]);
+  }
+  newView.set(oldView);
+  updateGlobalBuffer(newBuffer);
+  updateGlobalBufferViews();
+ }
+ var WasmTypes = {
+  none: 0,
+  i32: 1,
+  i64: 2,
+  f32: 3,
+  f64: 4
+ };
+ function fixImports(imports) {
+  if (!0) return imports;
+  var ret = {};
+  for (var i in imports) {
+   var fixed = i;
+   if (fixed[0] == "_") fixed = fixed.substr(1);
+   ret[fixed] = imports[i];
+  }
+  return ret;
+ }
+ function getBinary() {
+  var binary;
+  if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+   binary = Module["wasmBinary"];
+   assert(binary, "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)");
+   binary = new Uint8Array(binary);
+  } else {
+   binary = Module["readBinary"](wasmBinaryFile);
+  }
+  return binary;
+ }
+ function doJustAsm(global, env, providedBuffer) {
+  if (typeof Module["asm"] !== "function" || Module["asm"] === methodHandler) {
+   if (!Module["asmPreload"]) {
+    eval(Module["read"](asmjsCodeFile));
+   } else {
+    Module["asm"] = Module["asmPreload"];
+   }
+  }
+  if (typeof Module["asm"] !== "function") {
+   Module["printErr"]("asm evalling did not set the module properly");
+   return false;
+  }
+  return Module["asm"](global, env, providedBuffer);
+ }
+ function doNativeWasm(global, env, providedBuffer) {
+  if (typeof WebAssembly !== "object") {
+   Module["printErr"]("no native wasm support detected");
+   return false;
+  }
+  if (!(Module["wasmMemory"] instanceof WebAssembly.Memory)) {
+   Module["printErr"]("no native wasm Memory in use");
+   return false;
+  }
+  env["memory"] = Module["wasmMemory"];
+  info["global"] = {
+   "NaN": NaN,
+   "Infinity": Infinity
+  };
+  info["global.Math"] = global.Math;
+  info["env"] = env;
+  function receiveInstance(instance) {
+   exports = instance.exports;
+   if (exports.memory) mergeMemory(exports.memory);
+   Module["asm"] = exports;
+   Module["usingWasm"] = true;
+  }
+  Module["printErr"]("asynchronously preparing wasm");
+  addRunDependency("wasm-instantiate");
+  WebAssembly.compile(getBinary()).then(function(module) {
+    postModuleToWorkers(module); 
+  });
+  return {};
+  var instance;
+  try {
+   instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info);
+  } catch (e) {
+   Module["printErr"]("failed to compile wasm module: " + e);
+   if (e.toString().indexOf("imported Memory with incompatible size") >= 0) {
+    Module["printErr"]("Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).");
+   }
+   return false;
+  }
+  receiveInstance(instance);
+  return exports;
+ }
+ function doWasmPolyfill(global, env, providedBuffer, method) {
+  if (typeof WasmJS !== "function") {
+   Module["printErr"]("WasmJS not detected - polyfill not bundled?");
+   return false;
+  }
+  var wasmJS = WasmJS({});
+  wasmJS["outside"] = Module;
+  wasmJS["info"] = info;
+  wasmJS["lookupImport"] = lookupImport;
+  assert(providedBuffer === Module["buffer"]);
+  info.global = global;
+  info.env = env;
+  assert(providedBuffer === Module["buffer"]);
+  env["memory"] = providedBuffer;
+  assert(env["memory"] instanceof ArrayBuffer);
+  wasmJS["providedTotalMemory"] = Module["buffer"].byteLength;
+  var code;
+  if (method === "interpret-binary") {
+   code = getBinary();
+  } else {
+   code = Module["read"](method == "interpret-asm2wasm" ? asmjsCodeFile : wasmTextFile);
+  }
+  var temp;
+  if (method == "interpret-asm2wasm") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_asm2wasm"](temp);
+  } else if (method === "interpret-s-expr") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_s_expr2wasm"](temp);
+  } else if (method === "interpret-binary") {
+   temp = wasmJS["_malloc"](code.length);
+   wasmJS["HEAPU8"].set(code, temp);
+   wasmJS["_load_binary2wasm"](temp, code.length);
+  } else {
+   throw "what? " + method;
+  }
+  wasmJS["_free"](temp);
+  wasmJS["_instantiate"](temp);
+  if (Module["newBuffer"]) {
+   mergeMemory(Module["newBuffer"]);
+   Module["newBuffer"] = null;
+  }
+  exports = wasmJS["asmExports"];
+  return exports;
+ }
+ Module["asmPreload"] = Module["asm"];
+ Module["reallocBuffer"] = (function(size) {
+  var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE;
+  size = alignUp(size, PAGE_MULTIPLE);
+  var old = Module["buffer"];
+  var oldSize = old.byteLength;
+  if (Module["usingWasm"]) {
+   try {
+    var result = Module["wasmMemory"].grow((size - oldSize) / wasmPageSize);
+    if (result !== (-1 | 0)) {
+     return Module["buffer"] = Module["wasmMemory"].buffer;
+    } else {
+     return null;
+    }
+   } catch (e) {
+    return null;
+   }
+  } else {
+   exports["__growWasmMemory"]((size - oldSize) / wasmPageSize);
+   return Module["buffer"] !== old ? Module["buffer"] : null;
+  }
+ });
+ Module["asm"] = (function(global, env, providedBuffer) {
+  global = fixImports(global);
+  env = fixImports(env);
+  if (!env["table"]) {
+   var TABLE_SIZE = Module["wasmTableSize"];
+   if (TABLE_SIZE === undefined) TABLE_SIZE = 1024;
+   var MAX_TABLE_SIZE = Module["wasmMaxTableSize"];
+   if (typeof WebAssembly === "object" && typeof WebAssembly.Table === "function") {
+    if (MAX_TABLE_SIZE !== undefined) {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      maximum: MAX_TABLE_SIZE,
+      element: "anyfunc"
+     });
+    } else {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      element: "anyfunc"
+     });
+    }
+   } else {
+    env["table"] = new Array(TABLE_SIZE);
+   }
+   Module["wasmTable"] = env["table"];
+  }
+  if (!env["memoryBase"]) {
+   env["memoryBase"] = Module["STATIC_BASE"];
+  }
+  if (!env["tableBase"]) {
+   env["tableBase"] = 0;
+  }
+  var exports;
+  var methods = method.split(",");
+  for (var i = 0; i < methods.length; i++) {
+   var curr = methods[i];
+   Module["printErr"]("trying binaryen method: " + curr);
+   if (curr === "native-wasm") {
+    if (exports = doNativeWasm(global, env, providedBuffer)) break;
+   } else if (curr === "asmjs") {
+    if (exports = doJustAsm(global, env, providedBuffer)) break;
+   } else if (curr === "interpret-asm2wasm" || curr === "interpret-s-expr" || curr === "interpret-binary") {
+    if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break;
+   } else {
+    throw "bad method: " + curr;
+   }
+  }
+  if (!exports) throw "no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods";
+  Module["printErr"]("binaryen method succeeded.");
+  return exports;
+ });
+ var methodHandler = Module["asm"];
+}
+integrateWasmJS(Module);
+var ASM_CONSTS = [];
+STATIC_BASE = 1024;
+STATICTOP = STATIC_BASE + 5184;
+__ATINIT__.push();
+memoryInitializer = Module["wasmJSMethod"].indexOf("asmjs") >= 0 || Module["wasmJSMethod"].indexOf("interpret-asm2wasm") >= 0 ? "js-output.html.mem" : null;
+var STATIC_BUMP = 5184;
+Module["STATIC_BASE"] = STATIC_BASE;
+Module["STATIC_BUMP"] = STATIC_BUMP;
+var tempDoublePtr = STATICTOP;
+STATICTOP += 16;
+Module["_memset"] = _memset;
+function _pthread_cleanup_push(routine, arg) {
+ __ATEXIT__.push((function() {
+  Module["dynCall_vi"](routine, arg);
+ }));
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _pthread_cleanup_pop() {
+ assert(_pthread_cleanup_push.level == __ATEXIT__.length, "cannot pop if something else added meanwhile!");
+ __ATEXIT__.pop();
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _abort() {
+ Module["abort"]();
+}
+function ___lock() {}
+function ___unlock() {}
+var SYSCALLS = {
+ varargs: 0,
+ get: (function(varargs) {
+  SYSCALLS.varargs += 4;
+  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
+  return ret;
+ }),
+ getStr: (function() {
+  var ret = Pointer_stringify(SYSCALLS.get());
+  return ret;
+ }),
+ get64: (function() {
+  var low = SYSCALLS.get(), high = SYSCALLS.get();
+  if (low >= 0) assert(high === 0); else assert(high === -1);
+  return low;
+ }),
+ getZero: (function() {
+  assert(SYSCALLS.get() === 0);
+ })
+};
+function ___syscall6(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD();
+  FS.close(stream);
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___setErrNo(value) {
+ if (Module["___errno_location"]) HEAP32[Module["___errno_location"]() >> 2] = value;
+ return value;
+}
+Module["_sbrk"] = _sbrk;
+function _gettimeofday(ptr) {
+ var now = Date.now();
+ HEAP32[ptr >> 2] = now / 1e3 | 0;
+ HEAP32[ptr + 4 >> 2] = now % 1e3 * 1e3 | 0;
+ return 0;
+}
+function __ZSt18uncaught_exceptionv() {
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+}
+var EXCEPTIONS = {
+ last: 0,
+ caught: [],
+ infos: {},
+ deAdjust: (function(adjusted) {
+  if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
+  for (var ptr in EXCEPTIONS.infos) {
+   var info = EXCEPTIONS.infos[ptr];
+   if (info.adjusted === adjusted) {
+    return ptr;
+   }
+  }
+  return adjusted;
+ }),
+ addRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount++;
+ }),
+ decRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  assert(info.refcount > 0);
+  info.refcount--;
+  if (info.refcount === 0 && !info.rethrown) {
+   if (info.destructor) {
+    Module["dynCall_vi"](info.destructor, ptr);
+   }
+   delete EXCEPTIONS.infos[ptr];
+   ___cxa_free_exception(ptr);
+  }
+ }),
+ clearRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount = 0;
+ })
+};
+function ___resumeException(ptr) {
+ if (!EXCEPTIONS.last) {
+  EXCEPTIONS.last = ptr;
+ }
+ throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
+}
+function ___cxa_find_matching_catch() {
+ var thrown = EXCEPTIONS.last;
+ if (!thrown) {
+  return (Runtime.setTempRet0(0), 0) | 0;
+ }
+ var info = EXCEPTIONS.infos[thrown];
+ var throwntype = info.type;
+ if (!throwntype) {
+  return (Runtime.setTempRet0(0), thrown) | 0;
+ }
+ var typeArray = Array.prototype.slice.call(arguments);
+ var pointer = Module["___cxa_is_pointer_type"](throwntype);
+ if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4);
+ HEAP32[___cxa_find_matching_catch.buffer >> 2] = thrown;
+ thrown = ___cxa_find_matching_catch.buffer;
+ for (var i = 0; i < typeArray.length; i++) {
+  if (typeArray[i] && Module["___cxa_can_catch"](typeArray[i], throwntype, thrown)) {
+   thrown = HEAP32[thrown >> 2];
+   info.adjusted = thrown;
+   return (Runtime.setTempRet0(typeArray[i]), thrown) | 0;
+  }
+ }
+ thrown = HEAP32[thrown >> 2];
+ return (Runtime.setTempRet0(throwntype), thrown) | 0;
+}
+function ___gxx_personality_v0() {}
+function _emscripten_memcpy_big(dest, src, num) {
+ HEAPU8.set(HEAPU8.subarray(src, src + num), dest);
+ return dest;
+}
+Module["_memcpy"] = _memcpy;
+Module["_pthread_self"] = _pthread_self;
+function ___syscall140(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
+  var offset = offset_low;
+  assert(offset_high === 0);
+  FS.llseek(stream, offset, whence);
+  HEAP32[result >> 2] = stream.position;
+  if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall146(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
+  var ret = 0;
+  if (!___syscall146.buffer) {
+   ___syscall146.buffers = [ null, [], [] ];
+   ___syscall146.printChar = (function(stream, curr) {
+    var buffer = ___syscall146.buffers[stream];
+    assert(buffer);
+    if (curr === 0 || curr === 10) {
+     (stream === 1 ? Module["print"] : Module["printErr"])(UTF8ArrayToString(buffer, 0));
+     buffer.length = 0;
+    } else {
+     buffer.push(curr);
+    }
+   });
+  }
+  for (var i = 0; i < iovcnt; i++) {
+   var ptr = HEAP32[iov + i * 8 >> 2];
+   var len = HEAP32[iov + (i * 8 + 4) >> 2];
+   for (var j = 0; j < len; j++) {
+    ___syscall146.printChar(stream, HEAPU8[ptr + j]);
+   }
+   ret += len;
+  }
+  return ret;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall54(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+__ATEXIT__.push((function() {
+ var fflush = Module["_fflush"];
+ if (fflush) fflush(0);
+ var printChar = ___syscall146.printChar;
+ if (!printChar) return;
+ var buffers = ___syscall146.buffers;
+ if (buffers[1].length) printChar(1, 10);
+ if (buffers[2].length) printChar(2, 10);
+}));
+DYNAMICTOP_PTR = allocate(1, "i32", ALLOC_STATIC);
+STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);
+STACK_MAX = STACK_BASE + TOTAL_STACK;
+DYNAMIC_BASE = Runtime.alignMemory(STACK_MAX);
+HEAP32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE;
+staticSealed = true;
+Module["wasmTableSize"] = 9;
+Module["wasmMaxTableSize"] = 9;
+function invoke_ii(index, a1) {
+ try {
+  return Module["dynCall_ii"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_iiii(index, a1, a2, a3) {
+ try {
+  return Module["dynCall_iiii"](index, a1, a2, a3);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_vi(index, a1) {
+ try {
+  Module["dynCall_vi"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_v(index) {
+ try {
+  Module["dynCall_v"](index);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+Module.asmGlobalArg = {
+ "Math": Math,
+ "Int8Array": Int8Array,
+ "Int16Array": Int16Array,
+ "Int32Array": Int32Array,
+ "Uint8Array": Uint8Array,
+ "Uint16Array": Uint16Array,
+ "Uint32Array": Uint32Array,
+ "Float32Array": Float32Array,
+ "Float64Array": Float64Array,
+ "NaN": NaN,
+ "Infinity": Infinity
+};
+Module.asmLibraryArg = {
+ "abort": abort,
+ "assert": assert,
+ "enlargeMemory": enlargeMemory,
+ "getTotalMemory": getTotalMemory,
+ "abortOnCannotGrowMemory": abortOnCannotGrowMemory,
+ "invoke_ii": invoke_ii,
+ "invoke_iiii": invoke_iiii,
+ "invoke_vi": invoke_vi,
+ "invoke_v": invoke_v,
+ "_pthread_cleanup_pop": _pthread_cleanup_pop,
+ "___syscall146": ___syscall146,
+ "___lock": ___lock,
+ "___syscall6": ___syscall6,
+ "_pthread_cleanup_push": _pthread_cleanup_push,
+ "_abort": _abort,
+ "___unlock": ___unlock,
+ "_gettimeofday": _gettimeofday,
+ "___setErrNo": ___setErrNo,
+ "_emscripten_memcpy_big": _emscripten_memcpy_big,
+ "___syscall54": ___syscall54,
+ "___syscall140": ___syscall140,
+ "___resumeException": ___resumeException,
+ "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv,
+ "___gxx_personality_v0": ___gxx_personality_v0,
+ "___cxa_find_matching_catch": ___cxa_find_matching_catch,
+ "DYNAMICTOP_PTR": DYNAMICTOP_PTR,
+ "tempDoublePtr": tempDoublePtr,
+ "ABORT": ABORT,
+ "STACKTOP": STACKTOP,
+ "STACK_MAX": STACK_MAX
+};
+var asm = Module["asm"](Module.asmGlobalArg, Module.asmLibraryArg, buffer);
+Module["asm"] = asm;
+var _malloc = Module["_malloc"] = (function() {
+ return Module["asm"]["_malloc"].apply(null, arguments);
+});
+var getTempRet0 = Module["getTempRet0"] = (function() {
+ return Module["asm"]["getTempRet0"].apply(null, arguments);
+});
+var _free = Module["_free"] = (function() {
+ return Module["asm"]["_free"].apply(null, arguments);
+});
+var _main = Module["_main"] = (function() {
+ let r = Module["asm"]["_main"].apply(null, arguments);
+ postMessage("done");
+ return r;
+});
+var setTempRet0 = Module["setTempRet0"] = (function() {
+ return Module["asm"]["setTempRet0"].apply(null, arguments);
+});
+var establishStackSpace = Module["establishStackSpace"] = (function() {
+ return Module["asm"]["establishStackSpace"].apply(null, arguments);
+});
+var _pthread_self = Module["_pthread_self"] = (function() {
+ return Module["asm"]["_pthread_self"].apply(null, arguments);
+});
+var stackSave = Module["stackSave"] = (function() {
+ return Module["asm"]["stackSave"].apply(null, arguments);
+});
+var _memset = Module["_memset"] = (function() {
+ return Module["asm"]["_memset"].apply(null, arguments);
+});
+var _sbrk = Module["_sbrk"] = (function() {
+ return Module["asm"]["_sbrk"].apply(null, arguments);
+});
+var stackRestore = Module["stackRestore"] = (function() {
+ return Module["asm"]["stackRestore"].apply(null, arguments);
+});
+var _memcpy = Module["_memcpy"] = (function() {
+ return Module["asm"]["_memcpy"].apply(null, arguments);
+});
+var stackAlloc = Module["stackAlloc"] = (function() {
+ return Module["asm"]["stackAlloc"].apply(null, arguments);
+});
+var setThrew = Module["setThrew"] = (function() {
+ return Module["asm"]["setThrew"].apply(null, arguments);
+});
+var _fflush = Module["_fflush"] = (function() {
+ return Module["asm"]["_fflush"].apply(null, arguments);
+});
+var ___errno_location = Module["___errno_location"] = (function() {
+ return Module["asm"]["___errno_location"].apply(null, arguments);
+});
+var runPostSets = Module["runPostSets"] = (function() {
+ return Module["asm"]["runPostSets"].apply(null, arguments);
+});
+var dynCall_ii = Module["dynCall_ii"] = (function() {
+ return Module["asm"]["dynCall_ii"].apply(null, arguments);
+});
+var dynCall_iiii = Module["dynCall_iiii"] = (function() {
+ return Module["asm"]["dynCall_iiii"].apply(null, arguments);
+});
+var dynCall_vi = Module["dynCall_vi"] = (function() {
+ return Module["asm"]["dynCall_vi"].apply(null, arguments);
+});
+var dynCall_v = Module["dynCall_v"] = (function() {
+ return Module["asm"]["dynCall_v"].apply(null, arguments);
+});
+Runtime.stackAlloc = Module["stackAlloc"];
+Runtime.stackSave = Module["stackSave"];
+Runtime.stackRestore = Module["stackRestore"];
+Runtime.establishStackSpace = Module["establishStackSpace"];
+Runtime.setTempRet0 = Module["setTempRet0"];
+Runtime.getTempRet0 = Module["getTempRet0"];
+Module["asm"] = asm;
+if (memoryInitializer) {
+ if (typeof Module["locateFile"] === "function") {
+  memoryInitializer = Module["locateFile"](memoryInitializer);
+ } else if (Module["memoryInitializerPrefixURL"]) {
+  memoryInitializer = Module["memoryInitializerPrefixURL"] + memoryInitializer;
+ }
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+  var data = Module["readBinary"](memoryInitializer);
+  HEAPU8.set(data, Runtime.GLOBAL_BASE);
+ } else {
+  addRunDependency("memory initializer");
+  var applyMemoryInitializer = (function(data) {
+   if (data.byteLength) data = new Uint8Array(data);
+   HEAPU8.set(data, Runtime.GLOBAL_BASE);
+   if (Module["memoryInitializerRequest"]) delete Module["memoryInitializerRequest"].response;
+   removeRunDependency("memory initializer");
+  });
+  function doBrowserLoad() {
+   Module["readAsync"](memoryInitializer, applyMemoryInitializer, (function() {
+    throw "could not load memory initializer " + memoryInitializer;
+   }));
+  }
+  if (Module["memoryInitializerRequest"]) {
+   function useRequest() {
+    var request = Module["memoryInitializerRequest"];
+    if (request.status !== 200 && request.status !== 0) {
+     console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: " + request.status + ", retrying " + memoryInitializer);
+     doBrowserLoad();
+     return;
+    }
+    applyMemoryInitializer(request.response);
+   }
+   if (Module["memoryInitializerRequest"].response) {
+    setTimeout(useRequest, 0);
+   } else {
+    Module["memoryInitializerRequest"].addEventListener("load", useRequest);
+   }
+  } else {
+   doBrowserLoad();
+  }
+ }
+}
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+}
+ExitStatus.prototype = new Error;
+ExitStatus.prototype.constructor = ExitStatus;
+var initialStackTop;
+var preloadStartTime = null;
+var calledMain = false;
+dependenciesFulfilled = function runCaller() {
+ if (!Module["calledRun"]) run();
+ if (!Module["calledRun"]) dependenciesFulfilled = runCaller;
+};
+Module["callMain"] = Module.callMain = function callMain(args) {
+ args = args || [];
+ ensureInitRuntime();
+ var argc = args.length + 1;
+ function pad() {
+  for (var i = 0; i < 4 - 1; i++) {
+   argv.push(0);
+  }
+ }
+ var argv = [ allocate(intArrayFromString(Module["thisProgram"]), "i8", ALLOC_NORMAL) ];
+ pad();
+ for (var i = 0; i < argc - 1; i = i + 1) {
+  argv.push(allocate(intArrayFromString(args[i]), "i8", ALLOC_NORMAL));
+  pad();
+ }
+ argv.push(0);
+ argv = allocate(argv, "i32", ALLOC_NORMAL);
+ try {
+  var ret = Module["_main"](argc, argv, 0);
+  exit(ret, true);
+ } catch (e) {
+  if (e instanceof ExitStatus) {
+   return;
+  } else if (e == "SimulateInfiniteLoop") {
+   Module["noExitRuntime"] = true;
+   return;
+  } else {
+   if (e && typeof e === "object" && e.stack) Module.printErr("exception thrown: " + [ e, e.stack ]);
+   throw e;
+  }
+ } finally {
+  calledMain = true;
+ }
+};
+function run(args) {
+ args = args || Module["arguments"];
+ if (preloadStartTime === null) preloadStartTime = Date.now();
+ if (runDependencies > 0) {
+  return;
+ }
+ preRun();
+ if (runDependencies > 0) return;
+ if (Module["calledRun"]) return;
+ function doRun() {
+  if (Module["calledRun"]) return;
+  Module["calledRun"] = true;
+  if (ABORT) return;
+  ensureInitRuntime();
+  preMain();
+  if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
+  if (Module["_main"] && shouldRunNow) Module["callMain"](args);
+  postRun();
+ }
+ if (Module["setStatus"]) {
+  Module["setStatus"]("Running...");
+  setTimeout((function() {
+   setTimeout((function() {
+    Module["setStatus"]("");
+   }), 1);
+   doRun();
+  }), 1);
+ } else {
+  doRun();
+ }
+}
+Module["run"] = Module.run = run;
+function exit(status, implicit) {
+ if (implicit && Module["noExitRuntime"]) {
+  return;
+ }
+ if (Module["noExitRuntime"]) {} else {
+  ABORT = true;
+  EXITSTATUS = status;
+  STACKTOP = initialStackTop;
+  exitRuntime();
+  if (Module["onExit"]) Module["onExit"](status);
+ }
+ if (ENVIRONMENT_IS_NODE) {
+  process["exit"](status);
+ } else if (ENVIRONMENT_IS_SHELL && typeof quit === "function") {
+  quit(status);
+ }
+ throw new ExitStatus(status);
+}
+Module["exit"] = Module.exit = exit;
+var abortDecorators = [];
+function abort(what) {
+ if (what !== undefined) {
+  Module.print(what);
+  Module.printErr(what);
+  what = JSON.stringify(what);
+ } else {
+  what = "";
+ }
+ ABORT = true;
+ EXITSTATUS = 1;
+ var extra = "\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";
+ var output = "abort(" + what + ") at " + stackTrace() + extra;
+ if (abortDecorators) {
+  abortDecorators.forEach((function(decorator) {
+   output = decorator(output, what);
+  }));
+ }
+ throw output;
+}
+Module["abort"] = Module.abort = abort;
+if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+  Module["preInit"].pop()();
+ }
+}
+var shouldRunNow = true;
+if (Module["noInitialRun"]) {
+ shouldRunNow = false;
+}
+run();
+
+
+
+
+          };
+          xhr.send(null);
+
diff --git a/LayoutTests/workers/wasm-hashset/many-test.js b/LayoutTests/workers/wasm-hashset/many-test.js
new file mode 100644 (file)
index 0000000..d02ba06
--- /dev/null
@@ -0,0 +1,1961 @@
+"use strict";
+
+const __numWorkers = 16;
+let __count = 0;
+function reallyDone() {
+    if (++__count === (__numWorkers * 2)) {
+        if (window.testRunner) {
+            __realPrint("Finished running");
+            testRunner.notifyDone();
+        }
+    }
+}
+
+let __realPrint = console.log.bind(console);
+console = {
+    log: function() {},
+    error: function() {},
+    assert: function(){},
+};
+
+let __workers = [];
+
+for (let i = 0; i < __numWorkers; ++i) {
+    let worker = new Worker("./wasm-hashset/worker.js");
+    worker.onmessage = (e) => {
+        if (e.data === "done") {
+            __realPrint("Worker finished")
+            reallyDone();
+            return;
+        }
+        if (typeof e.data === "string") {
+            return;
+        }
+
+      var Module = {
+        preRun: [],
+        postRun: [],
+        print: function(){},
+        printErr: function(text) { },
+        canvas: null,
+        setStatus: function(text) {
+            return;
+        },
+        totalDependencies: 0,
+        monitorRunDependencies: function(left) {
+          this.totalDependencies = Math.max(this.totalDependencies, left);
+          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+        }
+      };
+      Module.setStatus('Downloading...');
+
+    let ___wasmModule = e.data;
+    if (!(___wasmModule instanceof WebAssembly.Module))
+        __realPrint("Not instanceof module! Bad!");
+    console.log(`Main script message at: ${Date.now()}`);
+
+    Module.wasmBinary = ___wasmModule;
+if (!Module) Module = (typeof Module !== "undefined" ? Module : null) || {};
+var moduleOverrides = {};
+for (var key in Module) {
+ if (Module.hasOwnProperty(key)) {
+  moduleOverrides[key] = Module[key];
+ }
+}
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+if (Module["ENVIRONMENT"]) {
+ if (Module["ENVIRONMENT"] === "WEB") {
+  ENVIRONMENT_IS_WEB = true;
+ } else if (Module["ENVIRONMENT"] === "WORKER") {
+  ENVIRONMENT_IS_WORKER = true;
+ } else if (Module["ENVIRONMENT"] === "NODE") {
+  ENVIRONMENT_IS_NODE = true;
+ } else if (Module["ENVIRONMENT"] === "SHELL") {
+  ENVIRONMENT_IS_SHELL = true;
+ } else {
+  throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");
+ }
+} else {
+ ENVIRONMENT_IS_WEB = typeof window === "object";
+ ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
+ ENVIRONMENT_IS_NODE = typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+}
+if (ENVIRONMENT_IS_NODE) {
+ if (!Module["print"]) Module["print"] = console.log;
+ if (!Module["printErr"]) Module["printErr"] = console.warn;
+ var nodeFS;
+ var nodePath;
+ Module["read"] = function read(filename, binary) {
+  if (!nodeFS) nodeFS = require("fs");
+  if (!nodePath) nodePath = require("path");
+  filename = nodePath["normalize"](filename);
+  var ret = nodeFS["readFileSync"](filename);
+  return binary ? ret : ret.toString();
+ };
+ Module["readBinary"] = function readBinary(filename) {
+  var ret = Module["read"](filename, true);
+  if (!ret.buffer) {
+   ret = new Uint8Array(ret);
+  }
+  assert(ret.buffer);
+  return ret;
+ };
+ Module["load"] = function load(f) {
+  globalEval(read(f));
+ };
+ if (!Module["thisProgram"]) {
+  if (process["argv"].length > 1) {
+   Module["thisProgram"] = process["argv"][1].replace(/\\/g, "/");
+  } else {
+   Module["thisProgram"] = "unknown-program";
+  }
+ }
+ Module["arguments"] = process["argv"].slice(2);
+ if (typeof module !== "undefined") {
+  module["exports"] = Module;
+ }
+ process["on"]("uncaughtException", (function(ex) {
+  if (!(ex instanceof ExitStatus)) {
+   throw ex;
+  }
+ }));
+ Module["inspect"] = (function() {
+  return "[Emscripten Module object]";
+ });
+} else if (ENVIRONMENT_IS_SHELL) {
+ if (!Module["print"]) Module["print"] = print;
+ if (typeof printErr != "undefined") Module["printErr"] = printErr;
+ if (typeof read != "undefined") {
+  Module["read"] = read;
+ } else {
+  Module["read"] = function read() {
+   throw "no read() available";
+  };
+ }
+ Module["readBinary"] = function readBinary(f) {
+  if (typeof readbuffer === "function") {
+   return new Uint8Array(readbuffer(f));
+  }
+  var data = read(f, "binary");
+  assert(typeof data === "object");
+  return data;
+ };
+ if (typeof scriptArgs != "undefined") {
+  Module["arguments"] = scriptArgs;
+ } else if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module["read"] = function read(url) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, false);
+  xhr.send(null);
+  return xhr.responseText;
+ };
+ Module["readAsync"] = function readAsync(url, onload, onerror) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, true);
+  xhr.responseType = "arraybuffer";
+  xhr.onload = function xhr_onload() {
+   if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
+    onload(xhr.response);
+   } else {
+    onerror();
+   }
+  };
+  xhr.onerror = onerror;
+  xhr.send(null);
+ };
+ if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+ if (typeof console !== "undefined") {
+  if (!Module["print"]) Module["print"] = function print(x) {
+   console.log(x);
+  };
+  if (!Module["printErr"]) Module["printErr"] = function printErr(x) {
+   console.warn(x);
+  };
+ } else {
+  var TRY_USE_DUMP = false;
+  if (!Module["print"]) Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function(x) {
+   dump(x);
+  }) : (function(x) {});
+ }
+ if (ENVIRONMENT_IS_WORKER) {
+  Module["load"] = importScripts;
+ }
+ if (typeof Module["setWindowTitle"] === "undefined") {
+  Module["setWindowTitle"] = (function(title) {
+   document.title = title;
+  });
+ }
+} else {
+ throw "Unknown runtime environment. Where are we?";
+}
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module["load"] && Module["read"]) {
+ Module["load"] = function load(f) {
+  globalEval(Module["read"](f));
+ };
+}
+if (!Module["print"]) {
+ Module["print"] = (function() {});
+}
+if (!Module["printErr"]) {
+ Module["printErr"] = Module["print"];
+}
+if (!Module["arguments"]) {
+ Module["arguments"] = [];
+}
+if (!Module["thisProgram"]) {
+ Module["thisProgram"] = "./this.program";
+}
+Module.print = Module["print"];
+Module.printErr = Module["printErr"];
+Module["preRun"] = [];
+Module["postRun"] = [];
+for (var key in moduleOverrides) {
+ if (moduleOverrides.hasOwnProperty(key)) {
+  Module[key] = moduleOverrides[key];
+ }
+}
+moduleOverrides = undefined;
+var Runtime = {
+ setTempRet0: (function(value) {
+  tempRet0 = value;
+  return value;
+ }),
+ getTempRet0: (function() {
+  return tempRet0;
+ }),
+ stackSave: (function() {
+  return STACKTOP;
+ }),
+ stackRestore: (function(stackTop) {
+  STACKTOP = stackTop;
+ }),
+ getNativeTypeSize: (function(type) {
+  switch (type) {
+  case "i1":
+  case "i8":
+   return 1;
+  case "i16":
+   return 2;
+  case "i32":
+   return 4;
+  case "i64":
+   return 8;
+  case "float":
+   return 4;
+  case "double":
+   return 8;
+  default:
+   {
+    if (type[type.length - 1] === "*") {
+     return Runtime.QUANTUM_SIZE;
+    } else if (type[0] === "i") {
+     var bits = parseInt(type.substr(1));
+     assert(bits % 8 === 0);
+     return bits / 8;
+    } else {
+     return 0;
+    }
+   }
+  }
+ }),
+ getNativeFieldSize: (function(type) {
+  return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
+ }),
+ STACK_ALIGN: 16,
+ prepVararg: (function(ptr, type) {
+  if (type === "double" || type === "i64") {
+   if (ptr & 7) {
+    assert((ptr & 7) === 4);
+    ptr += 4;
+   }
+  } else {
+   assert((ptr & 3) === 0);
+  }
+  return ptr;
+ }),
+ getAlignSize: (function(type, size, vararg) {
+  if (!vararg && (type == "i64" || type == "double")) return 8;
+  if (!type) return Math.min(size, 8);
+  return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
+ }),
+ dynCall: (function(sig, ptr, args) {
+  if (args && args.length) {
+   return Module["dynCall_" + sig].apply(null, [ ptr ].concat(args));
+  } else {
+   return Module["dynCall_" + sig].call(null, ptr);
+  }
+ }),
+ functionPointers: [],
+ addFunction: (function(func) {
+  for (var i = 0; i < Runtime.functionPointers.length; i++) {
+   if (!Runtime.functionPointers[i]) {
+    Runtime.functionPointers[i] = func;
+    return 2 * (1 + i);
+   }
+  }
+  throw "Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";
+ }),
+ removeFunction: (function(index) {
+  Runtime.functionPointers[(index - 2) / 2] = null;
+ }),
+ warnOnce: (function(text) {
+  if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+  if (!Runtime.warnOnce.shown[text]) {
+   Runtime.warnOnce.shown[text] = 1;
+   Module.printErr(text);
+  }
+ }),
+ funcWrappers: {},
+ getFuncWrapper: (function(func, sig) {
+  assert(sig);
+  if (!Runtime.funcWrappers[sig]) {
+   Runtime.funcWrappers[sig] = {};
+  }
+  var sigCache = Runtime.funcWrappers[sig];
+  if (!sigCache[func]) {
+   if (sig.length === 1) {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func);
+    };
+   } else if (sig.length === 2) {
+    sigCache[func] = function dynCall_wrapper(arg) {
+     return Runtime.dynCall(sig, func, [ arg ]);
+    };
+   } else {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func, Array.prototype.slice.call(arguments));
+    };
+   }
+  }
+  return sigCache[func];
+ }),
+ getCompilerSetting: (function(name) {
+  throw "You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";
+ }),
+ stackAlloc: (function(size) {
+  var ret = STACKTOP;
+  STACKTOP = STACKTOP + size | 0;
+  STACKTOP = STACKTOP + 15 & -16;
+  return ret;
+ }),
+ staticAlloc: (function(size) {
+  var ret = STATICTOP;
+  STATICTOP = STATICTOP + size | 0;
+  STATICTOP = STATICTOP + 15 & -16;
+  return ret;
+ }),
+ dynamicAlloc: (function(size) {
+  var ret = HEAP32[DYNAMICTOP_PTR >> 2];
+  var end = (ret + size + 15 | 0) & -16;
+  HEAP32[DYNAMICTOP_PTR >> 2] = end;
+  if (end >= TOTAL_MEMORY) {
+   var success = enlargeMemory();
+   if (!success) {
+    HEAP32[DYNAMICTOP_PTR >> 2] = ret;
+    return 0;
+   }
+  }
+  return ret;
+ }),
+ alignMemory: (function(size, quantum) {
+  var ret = size = Math.ceil(size / (quantum ? quantum : 16)) * (quantum ? quantum : 16);
+  return ret;
+ }),
+ makeBigInt: (function(low, high, unsigned) {
+  var ret = unsigned ? +(low >>> 0) + +(high >>> 0) * 4294967296 : +(low >>> 0) + +(high | 0) * 4294967296;
+  return ret;
+ }),
+ GLOBAL_BASE: 1024,
+ QUANTUM_SIZE: 4,
+ __dummy__: 0
+};
+Module["Runtime"] = Runtime;
+var ABORT = 0;
+var EXITSTATUS = 0;
+function assert(condition, text) {
+ if (!condition) {
+  abort("Assertion failed: " + text);
+ }
+}
+function getCFunc(ident) {
+ var func = Module["_" + ident];
+ if (!func) {
+  try {
+   func = eval("_" + ident);
+  } catch (e) {}
+ }
+ assert(func, "Cannot call unknown function " + ident + " (perhaps LLVM optimizations or closure removed it?)");
+ return func;
+}
+var cwrap, ccall;
+((function() {
+ var JSfuncs = {
+  "stackSave": (function() {
+   Runtime.stackSave();
+  }),
+  "stackRestore": (function() {
+   Runtime.stackRestore();
+  }),
+  "arrayToC": (function(arr) {
+   var ret = Runtime.stackAlloc(arr.length);
+   writeArrayToMemory(arr, ret);
+   return ret;
+  }),
+  "stringToC": (function(str) {
+   var ret = 0;
+   if (str !== null && str !== undefined && str !== 0) {
+    var len = (str.length << 2) + 1;
+    ret = Runtime.stackAlloc(len);
+    stringToUTF8(str, ret, len);
+   }
+   return ret;
+  })
+ };
+ var toC = {
+  "string": JSfuncs["stringToC"],
+  "array": JSfuncs["arrayToC"]
+ };
+ ccall = function ccallFunc(ident, returnType, argTypes, args, opts) {
+  var func = getCFunc(ident);
+  var cArgs = [];
+  var stack = 0;
+  if (args) {
+   for (var i = 0; i < args.length; i++) {
+    var converter = toC[argTypes[i]];
+    if (converter) {
+     if (stack === 0) stack = Runtime.stackSave();
+     cArgs[i] = converter(args[i]);
+    } else {
+     cArgs[i] = args[i];
+    }
+   }
+  }
+  var ret = func.apply(null, cArgs);
+  if (returnType === "string") ret = Pointer_stringify(ret);
+  if (stack !== 0) {
+   if (opts && opts.async) {
+    EmterpreterAsync.asyncFinalizers.push((function() {
+     Runtime.stackRestore(stack);
+    }));
+    return;
+   }
+   Runtime.stackRestore(stack);
+  }
+  return ret;
+ };
+ var sourceRegex = /^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
+ function parseJSFunc(jsfunc) {
+  var parsed = jsfunc.toString().match(sourceRegex).slice(1);
+  return {
+   arguments: parsed[0],
+   body: parsed[1],
+   returnValue: parsed[2]
+  };
+ }
+ var JSsource = null;
+ function ensureJSsource() {
+  if (!JSsource) {
+   JSsource = {};
+   for (var fun in JSfuncs) {
+    if (JSfuncs.hasOwnProperty(fun)) {
+     JSsource[fun] = parseJSFunc(JSfuncs[fun]);
+    }
+   }
+  }
+ }
+ cwrap = function cwrap(ident, returnType, argTypes) {
+  argTypes = argTypes || [];
+  var cfunc = getCFunc(ident);
+  var numericArgs = argTypes.every((function(type) {
+   return type === "number";
+  }));
+  var numericRet = returnType !== "string";
+  if (numericRet && numericArgs) {
+   return cfunc;
+  }
+  var argNames = argTypes.map((function(x, i) {
+   return "$" + i;
+  }));
+  var funcstr = "(function(" + argNames.join(",") + ") {";
+  var nargs = argTypes.length;
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += "var stack = " + JSsource["stackSave"].body + ";";
+   for (var i = 0; i < nargs; i++) {
+    var arg = argNames[i], type = argTypes[i];
+    if (type === "number") continue;
+    var convertCode = JSsource[type + "ToC"];
+    funcstr += "var " + convertCode.arguments + " = " + arg + ";";
+    funcstr += convertCode.body + ";";
+    funcstr += arg + "=(" + convertCode.returnValue + ");";
+   }
+  }
+  var cfuncname = parseJSFunc((function() {
+   return cfunc;
+  })).returnValue;
+  funcstr += "var ret = " + cfuncname + "(" + argNames.join(",") + ");";
+  if (!numericRet) {
+   var strgfy = parseJSFunc((function() {
+    return Pointer_stringify;
+   })).returnValue;
+   funcstr += "ret = " + strgfy + "(ret);";
+  }
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += JSsource["stackRestore"].body.replace("()", "(stack)") + ";";
+  }
+  funcstr += "return ret})";
+  return eval(funcstr);
+ };
+}))();
+Module["ccall"] = ccall;
+Module["cwrap"] = cwrap;
+function setValue(ptr, value, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i8":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i16":
+  HEAP16[ptr >> 1] = value;
+  break;
+ case "i32":
+  HEAP32[ptr >> 2] = value;
+  break;
+ case "i64":
+  tempI64 = [ value >>> 0, (tempDouble = value, +Math_abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
+  break;
+ case "float":
+  HEAPF32[ptr >> 2] = value;
+  break;
+ case "double":
+  HEAPF64[ptr >> 3] = value;
+  break;
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+}
+Module["setValue"] = setValue;
+function getValue(ptr, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  return HEAP8[ptr >> 0];
+ case "i8":
+  return HEAP8[ptr >> 0];
+ case "i16":
+  return HEAP16[ptr >> 1];
+ case "i32":
+  return HEAP32[ptr >> 2];
+ case "i64":
+  return HEAP32[ptr >> 2];
+ case "float":
+  return HEAPF32[ptr >> 2];
+ case "double":
+  return HEAPF64[ptr >> 3];
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+ return null;
+}
+Module["getValue"] = getValue;
+var ALLOC_NORMAL = 0;
+var ALLOC_STACK = 1;
+var ALLOC_STATIC = 2;
+var ALLOC_DYNAMIC = 3;
+var ALLOC_NONE = 4;
+Module["ALLOC_NORMAL"] = ALLOC_NORMAL;
+Module["ALLOC_STACK"] = ALLOC_STACK;
+Module["ALLOC_STATIC"] = ALLOC_STATIC;
+Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC;
+Module["ALLOC_NONE"] = ALLOC_NONE;
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === "number") {
+  zeroinit = true;
+  size = slab;
+ } else {
+  zeroinit = false;
+  size = slab.length;
+ }
+ var singleType = typeof types === "string" ? types : null;
+ var ret;
+ if (allocator == ALLOC_NONE) {
+  ret = ptr;
+ } else {
+  ret = [ typeof _malloc === "function" ? _malloc : Runtime.staticAlloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc ][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+ if (zeroinit) {
+  var ptr = ret, stop;
+  assert((ret & 3) == 0);
+  stop = ret + (size & ~3);
+  for (; ptr < stop; ptr += 4) {
+   HEAP32[ptr >> 2] = 0;
+  }
+  stop = ret + size;
+  while (ptr < stop) {
+   HEAP8[ptr++ >> 0] = 0;
+  }
+  return ret;
+ }
+ if (singleType === "i8") {
+  if (slab.subarray || slab.slice) {
+   HEAPU8.set(slab, ret);
+  } else {
+   HEAPU8.set(new Uint8Array(slab), ret);
+  }
+  return ret;
+ }
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+  var curr = slab[i];
+  if (typeof curr === "function") {
+   curr = Runtime.getFunctionIndex(curr);
+  }
+  type = singleType || types[i];
+  if (type === 0) {
+   i++;
+   continue;
+  }
+  if (type == "i64") type = "i32";
+  setValue(ret + i, curr, type);
+  if (previousType !== type) {
+   typeSize = Runtime.getNativeTypeSize(type);
+   previousType = type;
+  }
+  i += typeSize;
+ }
+ return ret;
+}
+Module["allocate"] = allocate;
+function getMemory(size) {
+ if (!staticSealed) return Runtime.staticAlloc(size);
+ if (!runtimeInitialized) return Runtime.dynamicAlloc(size);
+ return _malloc(size);
+}
+Module["getMemory"] = getMemory;
+function Pointer_stringify(ptr, length) {
+ if (length === 0 || !ptr) return "";
+ var hasUtf = 0;
+ var t;
+ var i = 0;
+ while (1) {
+  t = HEAPU8[ptr + i >> 0];
+  hasUtf |= t;
+  if (t == 0 && !length) break;
+  i++;
+  if (length && i == length) break;
+ }
+ if (!length) length = i;
+ var ret = "";
+ if (hasUtf < 128) {
+  var MAX_CHUNK = 1024;
+  var curr;
+  while (length > 0) {
+   curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+   ret = ret ? ret + curr : curr;
+   ptr += MAX_CHUNK;
+   length -= MAX_CHUNK;
+  }
+  return ret;
+ }
+ return Module["UTF8ToString"](ptr);
+}
+Module["Pointer_stringify"] = Pointer_stringify;
+function AsciiToString(ptr) {
+ var str = "";
+ while (1) {
+  var ch = HEAP8[ptr++ >> 0];
+  if (!ch) return str;
+  str += String.fromCharCode(ch);
+ }
+}
+Module["AsciiToString"] = AsciiToString;
+function stringToAscii(str, outPtr) {
+ return writeAsciiToMemory(str, outPtr, false);
+}
+Module["stringToAscii"] = stringToAscii;
+var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;
+function UTF8ArrayToString(u8Array, idx) {
+ var endPtr = idx;
+ while (u8Array[endPtr]) ++endPtr;
+ if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
+  return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
+ } else {
+  var u0, u1, u2, u3, u4, u5;
+  var str = "";
+  while (1) {
+   u0 = u8Array[idx++];
+   if (!u0) return str;
+   if (!(u0 & 128)) {
+    str += String.fromCharCode(u0);
+    continue;
+   }
+   u1 = u8Array[idx++] & 63;
+   if ((u0 & 224) == 192) {
+    str += String.fromCharCode((u0 & 31) << 6 | u1);
+    continue;
+   }
+   u2 = u8Array[idx++] & 63;
+   if ((u0 & 240) == 224) {
+    u0 = (u0 & 15) << 12 | u1 << 6 | u2;
+   } else {
+    u3 = u8Array[idx++] & 63;
+    if ((u0 & 248) == 240) {
+     u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3;
+    } else {
+     u4 = u8Array[idx++] & 63;
+     if ((u0 & 252) == 248) {
+      u0 = (u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4;
+     } else {
+      u5 = u8Array[idx++] & 63;
+      u0 = (u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | u5;
+     }
+    }
+   }
+   if (u0 < 65536) {
+    str += String.fromCharCode(u0);
+   } else {
+    var ch = u0 - 65536;
+    str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
+   }
+  }
+ }
+}
+Module["UTF8ArrayToString"] = UTF8ArrayToString;
+function UTF8ToString(ptr) {
+ return UTF8ArrayToString(HEAPU8, ptr);
+}
+Module["UTF8ToString"] = UTF8ToString;
+function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   if (outIdx >= endIdx) break;
+   outU8Array[outIdx++] = u;
+  } else if (u <= 2047) {
+   if (outIdx + 1 >= endIdx) break;
+   outU8Array[outIdx++] = 192 | u >> 6;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 65535) {
+   if (outIdx + 2 >= endIdx) break;
+   outU8Array[outIdx++] = 224 | u >> 12;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 2097151) {
+   if (outIdx + 3 >= endIdx) break;
+   outU8Array[outIdx++] = 240 | u >> 18;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 67108863) {
+   if (outIdx + 4 >= endIdx) break;
+   outU8Array[outIdx++] = 248 | u >> 24;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else {
+   if (outIdx + 5 >= endIdx) break;
+   outU8Array[outIdx++] = 252 | u >> 30;
+   outU8Array[outIdx++] = 128 | u >> 24 & 63;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  }
+ }
+ outU8Array[outIdx] = 0;
+ return outIdx - startIdx;
+}
+Module["stringToUTF8Array"] = stringToUTF8Array;
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+}
+Module["stringToUTF8"] = stringToUTF8;
+function lengthBytesUTF8(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   ++len;
+  } else if (u <= 2047) {
+   len += 2;
+  } else if (u <= 65535) {
+   len += 3;
+  } else if (u <= 2097151) {
+   len += 4;
+  } else if (u <= 67108863) {
+   len += 5;
+  } else {
+   len += 6;
+  }
+ }
+ return len;
+}
+Module["lengthBytesUTF8"] = lengthBytesUTF8;
+var UTF16Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le") : undefined;
+function demangle(func) {
+ var __cxa_demangle_func = Module["___cxa_demangle"] || Module["__cxa_demangle"];
+ if (__cxa_demangle_func) {
+  try {
+   var s = func.substr(1);
+   var len = lengthBytesUTF8(s) + 1;
+   var buf = _malloc(len);
+   stringToUTF8(s, buf, len);
+   var status = _malloc(4);
+   var ret = __cxa_demangle_func(buf, 0, 0, status);
+   if (getValue(status, "i32") === 0 && ret) {
+    return Pointer_stringify(ret);
+   }
+  } catch (e) {} finally {
+   if (buf) _free(buf);
+   if (status) _free(status);
+   if (ret) _free(ret);
+  }
+  return func;
+ }
+ Runtime.warnOnce("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");
+ return func;
+}
+function demangleAll(text) {
+ var regex = /__Z[\w\d_]+/g;
+ return text.replace(regex, (function(x) {
+  var y = demangle(x);
+  return x === y ? x : x + " [" + y + "]";
+ }));
+}
+function jsStackTrace() {
+ var err = new Error;
+ if (!err.stack) {
+  try {
+   throw new Error(0);
+  } catch (e) {
+   err = e;
+  }
+  if (!err.stack) {
+   return "(no stack trace available)";
+  }
+ }
+ return err.stack.toString();
+}
+function stackTrace() {
+ var js = jsStackTrace();
+ if (Module["extraStackTrace"]) js += "\n" + Module["extraStackTrace"]();
+ return demangleAll(js);
+}
+Module["stackTrace"] = stackTrace;
+var WASM_PAGE_SIZE = 65536;
+var ASMJS_PAGE_SIZE = 16777216;
+function alignUp(x, multiple) {
+ if (x % multiple > 0) {
+  x += multiple - x % multiple;
+ }
+ return x;
+}
+var HEAP;
+var buffer;
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+function updateGlobalBuffer(buf) {
+ Module["buffer"] = buffer = buf;
+}
+function updateGlobalBufferViews() {
+ Module["HEAP8"] = HEAP8 = new Int8Array(buffer);
+ Module["HEAP16"] = HEAP16 = new Int16Array(buffer);
+ Module["HEAP32"] = HEAP32 = new Int32Array(buffer);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(buffer);
+ Module["HEAPU16"] = HEAPU16 = new Uint16Array(buffer);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(buffer);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(buffer);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(buffer);
+}
+var STATIC_BASE, STATICTOP, staticSealed;
+var STACK_BASE, STACKTOP, STACK_MAX;
+var DYNAMIC_BASE, DYNAMICTOP_PTR;
+STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
+staticSealed = false;
+function abortOnCannotGrowMemory() {
+ abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value " + TOTAL_MEMORY + ", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ");
+}
+function enlargeMemory() {
+ abortOnCannotGrowMemory();
+}
+var TOTAL_STACK = Module["TOTAL_STACK"] || 5242880;
+var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 629145600;
+if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was " + TOTAL_MEMORY + "! (TOTAL_STACK=" + TOTAL_STACK + ")");
+if (Module["buffer"]) {
+ buffer = Module["buffer"];
+} else {
+ if (typeof WebAssembly === "object" && typeof WebAssembly.Memory === "function") {
+  Module["wasmMemory"] = new WebAssembly.Memory({
+   initial: TOTAL_MEMORY / WASM_PAGE_SIZE,
+   maximum: TOTAL_MEMORY / WASM_PAGE_SIZE
+  });
+  buffer = Module["wasmMemory"].buffer;
+ } else {
+  buffer = new ArrayBuffer(TOTAL_MEMORY);
+ }
+}
+updateGlobalBufferViews();
+function getTotalMemory() {
+ return TOTAL_MEMORY;
+}
+HEAP32[0] = 1668509029;
+HEAP16[1] = 25459;
+if (HEAPU8[2] !== 115 || HEAPU8[3] !== 99) throw "Runtime error: expected the system to be little-endian!";
+Module["HEAP"] = HEAP;
+Module["buffer"] = buffer;
+Module["HEAP8"] = HEAP8;
+Module["HEAP16"] = HEAP16;
+Module["HEAP32"] = HEAP32;
+Module["HEAPU8"] = HEAPU8;
+Module["HEAPU16"] = HEAPU16;
+Module["HEAPU32"] = HEAPU32;
+Module["HEAPF32"] = HEAPF32;
+Module["HEAPF64"] = HEAPF64;
+function callRuntimeCallbacks(callbacks) {
+ while (callbacks.length > 0) {
+  var callback = callbacks.shift();
+  if (typeof callback == "function") {
+   callback();
+   continue;
+  }
+  var func = callback.func;
+  if (typeof func === "number") {
+   if (callback.arg === undefined) {
+    Module["dynCall_v"](func);
+   } else {
+    Module["dynCall_vi"](func, callback.arg);
+   }
+  } else {
+   func(callback.arg === undefined ? null : callback.arg);
+  }
+ }
+}
+var __ATPRERUN__ = [];
+var __ATINIT__ = [];
+var __ATMAIN__ = [];
+var __ATEXIT__ = [];
+var __ATPOSTRUN__ = [];
+var runtimeInitialized = false;
+var runtimeExited = false;
+function preRun() {
+ if (Module["preRun"]) {
+  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+  while (Module["preRun"].length) {
+   addOnPreRun(Module["preRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+function ensureInitRuntime() {
+ if (runtimeInitialized) return;
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
+function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
+ runtimeExited = true;
+}
+function postRun() {
+ if (Module["postRun"]) {
+  if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+  while (Module["postRun"].length) {
+   addOnPostRun(Module["postRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+Module["addOnPreRun"] = addOnPreRun;
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+Module["addOnInit"] = addOnInit;
+function addOnPreMain(cb) {
+ __ATMAIN__.unshift(cb);
+}
+Module["addOnPreMain"] = addOnPreMain;
+function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
+}
+Module["addOnExit"] = addOnExit;
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+Module["addOnPostRun"] = addOnPostRun;
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+Module["intArrayFromString"] = intArrayFromString;
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+  var chr = array[i];
+  if (chr > 255) {
+   chr &= 255;
+  }
+  ret.push(String.fromCharCode(chr));
+ }
+ return ret.join("");
+}
+Module["intArrayToString"] = intArrayToString;
+function writeStringToMemory(string, buffer, dontAddNull) {
+ Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");
+ var lastChar, end;
+ if (dontAddNull) {
+  end = buffer + lengthBytesUTF8(string);
+  lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar;
+}
+Module["writeStringToMemory"] = writeStringToMemory;
+function writeArrayToMemory(array, buffer) {
+ HEAP8.set(array, buffer);
+}
+Module["writeArrayToMemory"] = writeArrayToMemory;
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+  HEAP8[buffer++ >> 0] = str.charCodeAt(i);
+ }
+ if (!dontAddNull) HEAP8[buffer >> 0] = 0;
+}
+Module["writeAsciiToMemory"] = writeAsciiToMemory;
+if (!Math["imul"] || Math["imul"](4294967295, 5) !== -5) Math["imul"] = function imul(a, b) {
+ var ah = a >>> 16;
+ var al = a & 65535;
+ var bh = b >>> 16;
+ var bl = b & 65535;
+ return al * bl + (ah * bl + al * bh << 16) | 0;
+};
+Math.imul = Math["imul"];
+if (!Math["fround"]) {
+ var froundBuffer = new Float32Array(1);
+ Math["fround"] = (function(x) {
+  froundBuffer[0] = x;
+  return froundBuffer[0];
+ });
+}
+Math.fround = Math["fround"];
+if (!Math["clz32"]) Math["clz32"] = (function(x) {
+ x = x >>> 0;
+ for (var i = 0; i < 32; i++) {
+  if (x & 1 << 31 - i) return i;
+ }
+ return 32;
+});
+Math.clz32 = Math["clz32"];
+if (!Math["trunc"]) Math["trunc"] = (function(x) {
+ return x < 0 ? Math.ceil(x) : Math.floor(x);
+});
+Math.trunc = Math["trunc"];
+var Math_abs = Math.abs;
+var Math_cos = Math.cos;
+var Math_sin = Math.sin;
+var Math_tan = Math.tan;
+var Math_acos = Math.acos;
+var Math_asin = Math.asin;
+var Math_atan = Math.atan;
+var Math_atan2 = Math.atan2;
+var Math_exp = Math.exp;
+var Math_log = Math.log;
+var Math_sqrt = Math.sqrt;
+var Math_ceil = Math.ceil;
+var Math_floor = Math.floor;
+var Math_pow = Math.pow;
+var Math_imul = Math.imul;
+var Math_fround = Math.fround;
+var Math_round = Math.round;
+var Math_min = Math.min;
+var Math_clz32 = Math.clz32;
+var Math_trunc = Math.trunc;
+var runDependencies = 0;
+var runDependencyWatcher = null;
+var dependenciesFulfilled = null;
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+}
+Module["addRunDependency"] = addRunDependency;
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+ if (runDependencies == 0) {
+  if (runDependencyWatcher !== null) {
+   clearInterval(runDependencyWatcher);
+   runDependencyWatcher = null;
+  }
+  if (dependenciesFulfilled) {
+   var callback = dependenciesFulfilled;
+   dependenciesFulfilled = null;
+   callback();
+  }
+ }
+}
+Module["removeRunDependency"] = removeRunDependency;
+Module["preloadedImages"] = {};
+Module["preloadedAudios"] = {};
+var memoryInitializer = null;
+function integrateWasmJS(Module) {
+ var method = Module["wasmJSMethod"] || "native-wasm";
+ Module["wasmJSMethod"] = method;
+ var wasmTextFile = Module["wasmTextFile"] || "js-output.wast";
+ var wasmBinaryFile = Module["wasmBinaryFile"] || "js-output.wasm";
+ var asmjsCodeFile = Module["asmjsCodeFile"] || "js-output.temp.asm.js";
+ var wasmPageSize = 64 * 1024;
+ var asm2wasmImports = {
+  "f64-rem": (function(x, y) {
+   return x % y;
+  }),
+  "f64-to-int": (function(x) {
+   return x | 0;
+  }),
+  "i32s-div": (function(x, y) {
+   return (x | 0) / (y | 0) | 0;
+  }),
+  "i32u-div": (function(x, y) {
+   return (x >>> 0) / (y >>> 0) >>> 0;
+  }),
+  "i32s-rem": (function(x, y) {
+   return (x | 0) % (y | 0) | 0;
+  }),
+  "i32u-rem": (function(x, y) {
+   return (x >>> 0) % (y >>> 0) >>> 0;
+  }),
+  "debugger": (function() {
+   debugger;
+  })
+ };
+ var info = {
+  "global": null,
+  "env": null,
+  "asm2wasm": asm2wasmImports,
+  "parent": Module
+ };
+ var exports = null;
+ function lookupImport(mod, base) {
+  var lookup = info;
+  if (mod.indexOf(".") < 0) {
+   lookup = (lookup || {})[mod];
+  } else {
+   var parts = mod.split(".");
+   lookup = (lookup || {})[parts[0]];
+   lookup = (lookup || {})[parts[1]];
+  }
+  if (base) {
+   lookup = (lookup || {})[base];
+  }
+  if (lookup === undefined) {
+   abort("bad lookupImport to (" + mod + ")." + base);
+  }
+  return lookup;
+ }
+ function mergeMemory(newBuffer) {
+  var oldBuffer = Module["buffer"];
+  if (newBuffer.byteLength < oldBuffer.byteLength) {
+   Module["printErr"]("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");
+  }
+  var oldView = new Int8Array(oldBuffer);
+  var newView = new Int8Array(newBuffer);
+  if (!memoryInitializer) {
+   oldView.set(newView.subarray(Module["STATIC_BASE"], Module["STATIC_BASE"] + Module["STATIC_BUMP"]), Module["STATIC_BASE"]);
+  }
+  newView.set(oldView);
+  updateGlobalBuffer(newBuffer);
+  updateGlobalBufferViews();
+ }
+ var WasmTypes = {
+  none: 0,
+  i32: 1,
+  i64: 2,
+  f32: 3,
+  f64: 4
+ };
+ function fixImports(imports) {
+  if (!0) return imports;
+  var ret = {};
+  for (var i in imports) {
+   var fixed = i;
+   if (fixed[0] == "_") fixed = fixed.substr(1);
+   ret[fixed] = imports[i];
+  }
+  return ret;
+ }
+ function getBinary() {
+  var binary;
+  if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+   binary = Module["wasmBinary"];
+   assert(binary, "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)");
+   binary = new Uint8Array(binary);
+  } else {
+   binary = Module["readBinary"](wasmBinaryFile);
+  }
+  return binary;
+ }
+ function doJustAsm(global, env, providedBuffer) {
+  if (typeof Module["asm"] !== "function" || Module["asm"] === methodHandler) {
+   if (!Module["asmPreload"]) {
+    eval(Module["read"](asmjsCodeFile));
+   } else {
+    Module["asm"] = Module["asmPreload"];
+   }
+  }
+  if (typeof Module["asm"] !== "function") {
+   Module["printErr"]("asm evalling did not set the module properly");
+   return false;
+  }
+  return Module["asm"](global, env, providedBuffer);
+ }
+ function doNativeWasm(global, env, providedBuffer) {
+  if (typeof WebAssembly !== "object") {
+   Module["printErr"]("no native wasm support detected");
+   return false;
+  }
+  if (!(Module["wasmMemory"] instanceof WebAssembly.Memory)) {
+   Module["printErr"]("no native wasm Memory in use");
+   return false;
+  }
+  env["memory"] = Module["wasmMemory"];
+  info["global"] = {
+   "NaN": NaN,
+   "Infinity": Infinity
+  };
+  info["global.Math"] = global.Math;
+  info["env"] = env;
+  function receiveInstance(instance) {
+   exports = instance.exports;
+   if (exports.memory) mergeMemory(exports.memory);
+   Module["asm"] = exports;
+   Module["usingWasm"] = true;
+  }
+  Module["printErr"]("asynchronously preparing wasm");
+  addRunDependency("wasm-instantiate");
+  let __start = Date.now();
+  WebAssembly.instantiate(___wasmModule, info).then((function(instance) {
+   receiveInstance(instance);
+   removeRunDependency("wasm-instantiate");
+  })).catch((function(reason) {
+   __realPrint("not instantiated, error: ", reason);
+   Module["printErr"]("failed to asynchronously prepare wasm:\n  " + reason);
+  }));
+  return {};
+  var instance;
+  try {
+   instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info);
+  } catch (e) {
+   Module["printErr"]("failed to compile wasm module: " + e);
+   if (e.toString().indexOf("imported Memory with incompatible size") >= 0) {
+    Module["printErr"]("Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).");
+   }
+   return false;
+  }
+  receiveInstance(instance);
+  return exports;
+ }
+ function doWasmPolyfill(global, env, providedBuffer, method) {
+  if (typeof WasmJS !== "function") {
+   Module["printErr"]("WasmJS not detected - polyfill not bundled?");
+   return false;
+  }
+  var wasmJS = WasmJS({});
+  wasmJS["outside"] = Module;
+  wasmJS["info"] = info;
+  wasmJS["lookupImport"] = lookupImport;
+  assert(providedBuffer === Module["buffer"]);
+  info.global = global;
+  info.env = env;
+  assert(providedBuffer === Module["buffer"]);
+  env["memory"] = providedBuffer;
+  assert(env["memory"] instanceof ArrayBuffer);
+  wasmJS["providedTotalMemory"] = Module["buffer"].byteLength;
+  var code;
+  if (method === "interpret-binary") {
+   code = getBinary();
+  } else {
+   code = Module["read"](method == "interpret-asm2wasm" ? asmjsCodeFile : wasmTextFile);
+  }
+  var temp;
+  if (method == "interpret-asm2wasm") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_asm2wasm"](temp);
+  } else if (method === "interpret-s-expr") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_s_expr2wasm"](temp);
+  } else if (method === "interpret-binary") {
+   temp = wasmJS["_malloc"](code.length);
+   wasmJS["HEAPU8"].set(code, temp);
+   wasmJS["_load_binary2wasm"](temp, code.length);
+  } else {
+   throw "what? " + method;
+  }
+  wasmJS["_free"](temp);
+  wasmJS["_instantiate"](temp);
+  if (Module["newBuffer"]) {
+   mergeMemory(Module["newBuffer"]);
+   Module["newBuffer"] = null;
+  }
+  exports = wasmJS["asmExports"];
+  return exports;
+ }
+ Module["asmPreload"] = Module["asm"];
+ Module["reallocBuffer"] = (function(size) {
+  var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE;
+  size = alignUp(size, PAGE_MULTIPLE);
+  var old = Module["buffer"];
+  var oldSize = old.byteLength;
+  if (Module["usingWasm"]) {
+   try {
+    var result = Module["wasmMemory"].grow((size - oldSize) / wasmPageSize);
+    if (result !== (-1 | 0)) {
+     return Module["buffer"] = Module["wasmMemory"].buffer;
+    } else {
+     return null;
+    }
+   } catch (e) {
+    return null;
+   }
+  } else {
+   exports["__growWasmMemory"]((size - oldSize) / wasmPageSize);
+   return Module["buffer"] !== old ? Module["buffer"] : null;
+  }
+ });
+ Module["asm"] = (function(global, env, providedBuffer) {
+  global = fixImports(global);
+  env = fixImports(env);
+  if (!env["table"]) {
+   var TABLE_SIZE = Module["wasmTableSize"];
+   if (TABLE_SIZE === undefined) TABLE_SIZE = 1024;
+   var MAX_TABLE_SIZE = Module["wasmMaxTableSize"];
+   if (typeof WebAssembly === "object" && typeof WebAssembly.Table === "function") {
+    if (MAX_TABLE_SIZE !== undefined) {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      maximum: MAX_TABLE_SIZE,
+      element: "anyfunc"
+     });
+    } else {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      element: "anyfunc"
+     });
+    }
+   } else {
+    env["table"] = new Array(TABLE_SIZE);
+   }
+   Module["wasmTable"] = env["table"];
+  }
+  if (!env["memoryBase"]) {
+   env["memoryBase"] = Module["STATIC_BASE"];
+  }
+  if (!env["tableBase"]) {
+   env["tableBase"] = 0;
+  }
+  var exports;
+  var methods = method.split(",");
+  for (var i = 0; i < methods.length; i++) {
+   var curr = methods[i];
+   Module["printErr"]("trying binaryen method: " + curr);
+   if (curr === "native-wasm") {
+    if (exports = doNativeWasm(global, env, providedBuffer)) break;
+   } else if (curr === "asmjs") {
+    if (exports = doJustAsm(global, env, providedBuffer)) break;
+   } else if (curr === "interpret-asm2wasm" || curr === "interpret-s-expr" || curr === "interpret-binary") {
+    if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break;
+   } else {
+    throw "bad method: " + curr;
+   }
+  }
+  if (!exports) throw "no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods";
+  Module["printErr"]("binaryen method succeeded.");
+  return exports;
+ });
+ var methodHandler = Module["asm"];
+}
+integrateWasmJS(Module);
+var ASM_CONSTS = [];
+STATIC_BASE = 1024;
+STATICTOP = STATIC_BASE + 5184;
+__ATINIT__.push();
+memoryInitializer = Module["wasmJSMethod"].indexOf("asmjs") >= 0 || Module["wasmJSMethod"].indexOf("interpret-asm2wasm") >= 0 ? "js-output.html.mem" : null;
+var STATIC_BUMP = 5184;
+Module["STATIC_BASE"] = STATIC_BASE;
+Module["STATIC_BUMP"] = STATIC_BUMP;
+var tempDoublePtr = STATICTOP;
+STATICTOP += 16;
+Module["_memset"] = _memset;
+function _pthread_cleanup_push(routine, arg) {
+ __ATEXIT__.push((function() {
+  Module["dynCall_vi"](routine, arg);
+ }));
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _pthread_cleanup_pop() {
+ assert(_pthread_cleanup_push.level == __ATEXIT__.length, "cannot pop if something else added meanwhile!");
+ __ATEXIT__.pop();
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _abort() {
+ Module["abort"]();
+}
+function ___lock() {}
+function ___unlock() {}
+var SYSCALLS = {
+ varargs: 0,
+ get: (function(varargs) {
+  SYSCALLS.varargs += 4;
+  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
+  return ret;
+ }),
+ getStr: (function() {
+  var ret = Pointer_stringify(SYSCALLS.get());
+  return ret;
+ }),
+ get64: (function() {
+  var low = SYSCALLS.get(), high = SYSCALLS.get();
+  if (low >= 0) assert(high === 0); else assert(high === -1);
+  return low;
+ }),
+ getZero: (function() {
+  assert(SYSCALLS.get() === 0);
+ })
+};
+function ___syscall6(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD();
+  FS.close(stream);
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___setErrNo(value) {
+ if (Module["___errno_location"]) HEAP32[Module["___errno_location"]() >> 2] = value;
+ return value;
+}
+Module["_sbrk"] = _sbrk;
+function _gettimeofday(ptr) {
+ var now = Date.now();
+ HEAP32[ptr >> 2] = now / 1e3 | 0;
+ HEAP32[ptr + 4 >> 2] = now % 1e3 * 1e3 | 0;
+ return 0;
+}
+function __ZSt18uncaught_exceptionv() {
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+}
+var EXCEPTIONS = {
+ last: 0,
+ caught: [],
+ infos: {},
+ deAdjust: (function(adjusted) {
+  if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
+  for (var ptr in EXCEPTIONS.infos) {
+   var info = EXCEPTIONS.infos[ptr];
+   if (info.adjusted === adjusted) {
+    return ptr;
+   }
+  }
+  return adjusted;
+ }),
+ addRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount++;
+ }),
+ decRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  assert(info.refcount > 0);
+  info.refcount--;
+  if (info.refcount === 0 && !info.rethrown) {
+   if (info.destructor) {
+    Module["dynCall_vi"](info.destructor, ptr);
+   }
+   delete EXCEPTIONS.infos[ptr];
+   ___cxa_free_exception(ptr);
+  }
+ }),
+ clearRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount = 0;
+ })
+};
+function ___resumeException(ptr) {
+ if (!EXCEPTIONS.last) {
+  EXCEPTIONS.last = ptr;
+ }
+ throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
+}
+function ___cxa_find_matching_catch() {
+ var thrown = EXCEPTIONS.last;
+ if (!thrown) {
+  return (Runtime.setTempRet0(0), 0) | 0;
+ }
+ var info = EXCEPTIONS.infos[thrown];
+ var throwntype = info.type;
+ if (!throwntype) {
+  return (Runtime.setTempRet0(0), thrown) | 0;
+ }
+ var typeArray = Array.prototype.slice.call(arguments);
+ var pointer = Module["___cxa_is_pointer_type"](throwntype);
+ if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4);
+ HEAP32[___cxa_find_matching_catch.buffer >> 2] = thrown;
+ thrown = ___cxa_find_matching_catch.buffer;
+ for (var i = 0; i < typeArray.length; i++) {
+  if (typeArray[i] && Module["___cxa_can_catch"](typeArray[i], throwntype, thrown)) {
+   thrown = HEAP32[thrown >> 2];
+   info.adjusted = thrown;
+   return (Runtime.setTempRet0(typeArray[i]), thrown) | 0;
+  }
+ }
+ thrown = HEAP32[thrown >> 2];
+ return (Runtime.setTempRet0(throwntype), thrown) | 0;
+}
+function ___gxx_personality_v0() {}
+function _emscripten_memcpy_big(dest, src, num) {
+ HEAPU8.set(HEAPU8.subarray(src, src + num), dest);
+ return dest;
+}
+Module["_memcpy"] = _memcpy;
+Module["_pthread_self"] = _pthread_self;
+function ___syscall140(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
+  var offset = offset_low;
+  assert(offset_high === 0);
+  FS.llseek(stream, offset, whence);
+  HEAP32[result >> 2] = stream.position;
+  if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall146(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
+  var ret = 0;
+  if (!___syscall146.buffer) {
+   ___syscall146.buffers = [ null, [], [] ];
+   ___syscall146.printChar = (function(stream, curr) {
+    var buffer = ___syscall146.buffers[stream];
+    assert(buffer);
+    if (curr === 0 || curr === 10) {
+     (stream === 1 ? Module["print"] : Module["printErr"])(UTF8ArrayToString(buffer, 0));
+     buffer.length = 0;
+    } else {
+     buffer.push(curr);
+    }
+   });
+  }
+  for (var i = 0; i < iovcnt; i++) {
+   var ptr = HEAP32[iov + i * 8 >> 2];
+   var len = HEAP32[iov + (i * 8 + 4) >> 2];
+   for (var j = 0; j < len; j++) {
+    ___syscall146.printChar(stream, HEAPU8[ptr + j]);
+   }
+   ret += len;
+  }
+  return ret;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall54(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+__ATEXIT__.push((function() {
+ var fflush = Module["_fflush"];
+ if (fflush) fflush(0);
+ var printChar = ___syscall146.printChar;
+ if (!printChar) return;
+ var buffers = ___syscall146.buffers;
+ if (buffers[1].length) printChar(1, 10);
+ if (buffers[2].length) printChar(2, 10);
+}));
+DYNAMICTOP_PTR = allocate(1, "i32", ALLOC_STATIC);
+STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);
+STACK_MAX = STACK_BASE + TOTAL_STACK;
+DYNAMIC_BASE = Runtime.alignMemory(STACK_MAX);
+HEAP32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE;
+staticSealed = true;
+Module["wasmTableSize"] = 9;
+Module["wasmMaxTableSize"] = 9;
+function invoke_ii(index, a1) {
+ try {
+  return Module["dynCall_ii"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_iiii(index, a1, a2, a3) {
+ try {
+  return Module["dynCall_iiii"](index, a1, a2, a3);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_vi(index, a1) {
+ try {
+  Module["dynCall_vi"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_v(index) {
+ try {
+  Module["dynCall_v"](index);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+Module.asmGlobalArg = {
+ "Math": Math,
+ "Int8Array": Int8Array,
+ "Int16Array": Int16Array,
+ "Int32Array": Int32Array,
+ "Uint8Array": Uint8Array,
+ "Uint16Array": Uint16Array,
+ "Uint32Array": Uint32Array,
+ "Float32Array": Float32Array,
+ "Float64Array": Float64Array,
+ "NaN": NaN,
+ "Infinity": Infinity
+};
+Module.asmLibraryArg = {
+ "abort": abort,
+ "assert": assert,
+ "enlargeMemory": enlargeMemory,
+ "getTotalMemory": getTotalMemory,
+ "abortOnCannotGrowMemory": abortOnCannotGrowMemory,
+ "invoke_ii": invoke_ii,
+ "invoke_iiii": invoke_iiii,
+ "invoke_vi": invoke_vi,
+ "invoke_v": invoke_v,
+ "_pthread_cleanup_pop": _pthread_cleanup_pop,
+ "___syscall146": ___syscall146,
+ "___lock": ___lock,
+ "___syscall6": ___syscall6,
+ "_pthread_cleanup_push": _pthread_cleanup_push,
+ "_abort": _abort,
+ "___unlock": ___unlock,
+ "_gettimeofday": _gettimeofday,
+ "___setErrNo": ___setErrNo,
+ "_emscripten_memcpy_big": _emscripten_memcpy_big,
+ "___syscall54": ___syscall54,
+ "___syscall140": ___syscall140,
+ "___resumeException": ___resumeException,
+ "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv,
+ "___gxx_personality_v0": ___gxx_personality_v0,
+ "___cxa_find_matching_catch": ___cxa_find_matching_catch,
+ "DYNAMICTOP_PTR": DYNAMICTOP_PTR,
+ "tempDoublePtr": tempDoublePtr,
+ "ABORT": ABORT,
+ "STACKTOP": STACKTOP,
+ "STACK_MAX": STACK_MAX
+};
+var asm = Module["asm"](Module.asmGlobalArg, Module.asmLibraryArg, buffer);
+Module["asm"] = asm;
+var _malloc = Module["_malloc"] = (function() {
+ return Module["asm"]["_malloc"].apply(null, arguments);
+});
+var getTempRet0 = Module["getTempRet0"] = (function() {
+ return Module["asm"]["getTempRet0"].apply(null, arguments);
+});
+var _free = Module["_free"] = (function() {
+ return Module["asm"]["_free"].apply(null, arguments);
+});
+var _main = Module["_main"] = (function() {
+ let r = Module["asm"]["_main"].apply(null, arguments);
+ reallyDone();
+ return r;
+});
+var setTempRet0 = Module["setTempRet0"] = (function() {
+ return Module["asm"]["setTempRet0"].apply(null, arguments);
+});
+var establishStackSpace = Module["establishStackSpace"] = (function() {
+ return Module["asm"]["establishStackSpace"].apply(null, arguments);
+});
+var _pthread_self = Module["_pthread_self"] = (function() {
+ return Module["asm"]["_pthread_self"].apply(null, arguments);
+});
+var stackSave = Module["stackSave"] = (function() {
+ return Module["asm"]["stackSave"].apply(null, arguments);
+});
+var _memset = Module["_memset"] = (function() {
+ return Module["asm"]["_memset"].apply(null, arguments);
+});
+var _sbrk = Module["_sbrk"] = (function() {
+ return Module["asm"]["_sbrk"].apply(null, arguments);
+});
+var stackRestore = Module["stackRestore"] = (function() {
+ return Module["asm"]["stackRestore"].apply(null, arguments);
+});
+var _memcpy = Module["_memcpy"] = (function() {
+ return Module["asm"]["_memcpy"].apply(null, arguments);
+});
+var stackAlloc = Module["stackAlloc"] = (function() {
+ return Module["asm"]["stackAlloc"].apply(null, arguments);
+});
+var setThrew = Module["setThrew"] = (function() {
+ return Module["asm"]["setThrew"].apply(null, arguments);
+});
+var _fflush = Module["_fflush"] = (function() {
+ return Module["asm"]["_fflush"].apply(null, arguments);
+});
+var ___errno_location = Module["___errno_location"] = (function() {
+ return Module["asm"]["___errno_location"].apply(null, arguments);
+});
+var runPostSets = Module["runPostSets"] = (function() {
+ return Module["asm"]["runPostSets"].apply(null, arguments);
+});
+var dynCall_ii = Module["dynCall_ii"] = (function() {
+ return Module["asm"]["dynCall_ii"].apply(null, arguments);
+});
+var dynCall_iiii = Module["dynCall_iiii"] = (function() {
+ return Module["asm"]["dynCall_iiii"].apply(null, arguments);
+});
+var dynCall_vi = Module["dynCall_vi"] = (function() {
+ return Module["asm"]["dynCall_vi"].apply(null, arguments);
+});
+var dynCall_v = Module["dynCall_v"] = (function() {
+ return Module["asm"]["dynCall_v"].apply(null, arguments);
+});
+Runtime.stackAlloc = Module["stackAlloc"];
+Runtime.stackSave = Module["stackSave"];
+Runtime.stackRestore = Module["stackRestore"];
+Runtime.establishStackSpace = Module["establishStackSpace"];
+Runtime.setTempRet0 = Module["setTempRet0"];
+Runtime.getTempRet0 = Module["getTempRet0"];
+Module["asm"] = asm;
+if (memoryInitializer) {
+ if (typeof Module["locateFile"] === "function") {
+  memoryInitializer = Module["locateFile"](memoryInitializer);
+ } else if (Module["memoryInitializerPrefixURL"]) {
+  memoryInitializer = Module["memoryInitializerPrefixURL"] + memoryInitializer;
+ }
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+  var data = Module["readBinary"](memoryInitializer);
+  HEAPU8.set(data, Runtime.GLOBAL_BASE);
+ } else {
+  addRunDependency("memory initializer");
+  var applyMemoryInitializer = (function(data) {
+   if (data.byteLength) data = new Uint8Array(data);
+   HEAPU8.set(data, Runtime.GLOBAL_BASE);
+   if (Module["memoryInitializerRequest"]) delete Module["memoryInitializerRequest"].response;
+   removeRunDependency("memory initializer");
+  });
+  function doBrowserLoad() {
+   Module["readAsync"](memoryInitializer, applyMemoryInitializer, (function() {
+    throw "could not load memory initializer " + memoryInitializer;
+   }));
+  }
+  if (Module["memoryInitializerRequest"]) {
+   function useRequest() {
+    var request = Module["memoryInitializerRequest"];
+    if (request.status !== 200 && request.status !== 0) {
+     console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: " + request.status + ", retrying " + memoryInitializer);
+     doBrowserLoad();
+     return;
+    }
+    applyMemoryInitializer(request.response);
+   }
+   if (Module["memoryInitializerRequest"].response) {
+    setTimeout(useRequest, 0);
+   } else {
+    Module["memoryInitializerRequest"].addEventListener("load", useRequest);
+   }
+  } else {
+   doBrowserLoad();
+  }
+ }
+}
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+}
+ExitStatus.prototype = new Error;
+ExitStatus.prototype.constructor = ExitStatus;
+var initialStackTop;
+var preloadStartTime = null;
+var calledMain = false;
+dependenciesFulfilled = function runCaller() {
+ if (!Module["calledRun"]) run();
+ if (!Module["calledRun"]) dependenciesFulfilled = runCaller;
+};
+Module["callMain"] = Module.callMain = function callMain(args) {
+ args = args || [];
+ ensureInitRuntime();
+ var argc = args.length + 1;
+ function pad() {
+  for (var i = 0; i < 4 - 1; i++) {
+   argv.push(0);
+  }
+ }
+ var argv = [ allocate(intArrayFromString(Module["thisProgram"]), "i8", ALLOC_NORMAL) ];
+ pad();
+ for (var i = 0; i < argc - 1; i = i + 1) {
+  argv.push(allocate(intArrayFromString(args[i]), "i8", ALLOC_NORMAL));
+  pad();
+ }
+ argv.push(0);
+ argv = allocate(argv, "i32", ALLOC_NORMAL);
+ try {
+  var ret = Module["_main"](argc, argv, 0);
+  exit(ret, true);
+ } catch (e) {
+  if (e instanceof ExitStatus) {
+   return;
+  } else if (e == "SimulateInfiniteLoop") {
+   Module["noExitRuntime"] = true;
+   return;
+  } else {
+   if (e && typeof e === "object" && e.stack) Module.printErr("exception thrown: " + [ e, e.stack ]);
+   throw e;
+  }
+ } finally {
+  calledMain = true;
+ }
+};
+function run(args) {
+ args = args || Module["arguments"];
+ if (preloadStartTime === null) preloadStartTime = Date.now();
+ if (runDependencies > 0) {
+  return;
+ }
+ preRun();
+ if (runDependencies > 0) return;
+ if (Module["calledRun"]) return;
+ function doRun() {
+  if (Module["calledRun"]) return;
+  Module["calledRun"] = true;
+  if (ABORT) return;
+  ensureInitRuntime();
+  preMain();
+  if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
+  if (Module["_main"] && shouldRunNow) Module["callMain"](args);
+  postRun();
+ }
+ if (Module["setStatus"]) {
+  Module["setStatus"]("Running...");
+  setTimeout((function() {
+   setTimeout((function() {
+    Module["setStatus"]("");
+   }), 1);
+   doRun();
+  }), 1);
+ } else {
+  doRun();
+ }
+}
+Module["run"] = Module.run = run;
+function exit(status, implicit) {
+ if (implicit && Module["noExitRuntime"]) {
+  return;
+ }
+ if (Module["noExitRuntime"]) {} else {
+  ABORT = true;
+  EXITSTATUS = status;
+  STACKTOP = initialStackTop;
+  exitRuntime();
+  if (Module["onExit"]) Module["onExit"](status);
+ }
+ if (ENVIRONMENT_IS_NODE) {
+  process["exit"](status);
+ } else if (ENVIRONMENT_IS_SHELL && typeof quit === "function") {
+  quit(status);
+ }
+ throw new ExitStatus(status);
+}
+Module["exit"] = Module.exit = exit;
+var abortDecorators = [];
+function abort(what) {
+ if (what !== undefined) {
+  Module.print(what);
+  Module.printErr(what);
+  what = JSON.stringify(what);
+ } else {
+  what = "";
+ }
+ ABORT = true;
+ EXITSTATUS = 1;
+ var extra = "\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";
+ var output = "abort(" + what + ") at " + stackTrace() + extra;
+ if (abortDecorators) {
+  abortDecorators.forEach((function(decorator) {
+   output = decorator(output, what);
+  }));
+ }
+ throw output;
+}
+Module["abort"] = Module.abort = abort;
+if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+  Module["preInit"].pop()();
+ }
+}
+var shouldRunNow = true;
+if (Module["noInitialRun"]) {
+ shouldRunNow = false;
+}
+run();
+
+    };
+    __workers.push(worker);
+}
diff --git a/LayoutTests/workers/wasm-hashset/many-worker-2.js b/LayoutTests/workers/wasm-hashset/many-worker-2.js
new file mode 100644 (file)
index 0000000..6e7ba87
--- /dev/null
@@ -0,0 +1,1985 @@
+"use strict";
+
+console = {
+    log: function() {},
+    error: function() {},
+    assert: function(){},
+};
+
+      var Module = {
+        preRun: [],
+        postRun: [],
+        print: (function() {
+            return function(){};
+          var element = document.getElementById('output');
+          if (element) element.value = ''; // clear browser cache
+          return function(text) {
+            if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+            // These replacements are necessary if you render to raw HTML
+            //text = text.replace(/&/g, "&amp;");
+            //text = text.replace(/</g, "&lt;");
+            //text = text.replace(/>/g, "&gt;");
+            //text = text.replace('\n', '<br>', 'g');
+            console.log(text);
+            if (element) {
+              element.value += text + "\n";
+              element.scrollTop = element.scrollHeight; // focus on bottom
+            }
+          };
+        })(),
+        printErr: function(text) {
+          if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+          if (0) { // XXX disabled for safety typeof dump == 'function') {
+            dump(text + '\n'); // fast, straight to the real console
+          } else {
+            console.error(text);
+          }
+        },
+        canvas: (function() {
+            return;
+          var canvas = document.getElementById('canvas');
+
+          // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+          // application robust, you may want to override this behavior before shipping!
+          // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+          canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+          return canvas;
+        })(),
+        setStatus: function(text) {
+            console.log("Status: ", text);
+            return;
+
+          if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+          if (text === Module.setStatus.text) return;
+          var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+          var now = Date.now();
+          if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
+          if (m) {
+            text = m[1];
+            progressElement.value = parseInt(m[2])*100;
+            progressElement.max = parseInt(m[4])*100;
+            progressElement.hidden = false;
+            spinnerElement.hidden = false;
+          } else {
+            progressElement.value = null;
+            progressElement.max = null;
+            progressElement.hidden = true;
+            if (!text) spinnerElement.style.display = 'none';
+          }
+          statusElement.innerHTML = text;
+        },
+        totalDependencies: 0,
+        monitorRunDependencies: function(left) {
+          this.totalDependencies = Math.max(this.totalDependencies, left);
+          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+        }
+      };
+
+onmessage = function(e) {
+    let ___wasmModule = e.data;
+    if (!(___wasmModule instanceof WebAssembly.Module))
+        throw new Error("Bad")
+    console.log(`Main script message at: ${Date.now()}`);
+
+    Module.wasmBinary = ___wasmModule;
+if (!Module) Module = (typeof Module !== "undefined" ? Module : null) || {};
+var moduleOverrides = {};
+for (var key in Module) {
+ if (Module.hasOwnProperty(key)) {
+  moduleOverrides[key] = Module[key];
+ }
+}
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+if (Module["ENVIRONMENT"]) {
+ if (Module["ENVIRONMENT"] === "WEB") {
+  ENVIRONMENT_IS_WEB = true;
+ } else if (Module["ENVIRONMENT"] === "WORKER") {
+  ENVIRONMENT_IS_WORKER = true;
+ } else if (Module["ENVIRONMENT"] === "NODE") {
+  ENVIRONMENT_IS_NODE = true;
+ } else if (Module["ENVIRONMENT"] === "SHELL") {
+  ENVIRONMENT_IS_SHELL = true;
+ } else {
+  throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");
+ }
+} else {
+ ENVIRONMENT_IS_WEB = typeof window === "object";
+ ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
+ ENVIRONMENT_IS_NODE = typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+}
+if (ENVIRONMENT_IS_NODE) {
+ if (!Module["print"]) Module["print"] = console.log;
+ if (!Module["printErr"]) Module["printErr"] = console.warn;
+ var nodeFS;
+ var nodePath;
+ Module["read"] = function read(filename, binary) {
+  if (!nodeFS) nodeFS = require("fs");
+  if (!nodePath) nodePath = require("path");
+  filename = nodePath["normalize"](filename);
+  var ret = nodeFS["readFileSync"](filename);
+  return binary ? ret : ret.toString();
+ };
+ Module["readBinary"] = function readBinary(filename) {
+  var ret = Module["read"](filename, true);
+  if (!ret.buffer) {
+   ret = new Uint8Array(ret);
+  }
+  assert(ret.buffer);
+  return ret;
+ };
+ Module["load"] = function load(f) {
+  globalEval(read(f));
+ };
+ if (!Module["thisProgram"]) {
+  if (process["argv"].length > 1) {
+   Module["thisProgram"] = process["argv"][1].replace(/\\/g, "/");
+  } else {
+   Module["thisProgram"] = "unknown-program";
+  }
+ }
+ Module["arguments"] = process["argv"].slice(2);
+ if (typeof module !== "undefined") {
+  module["exports"] = Module;
+ }
+ process["on"]("uncaughtException", (function(ex) {
+  if (!(ex instanceof ExitStatus)) {
+   throw ex;
+  }
+ }));
+ Module["inspect"] = (function() {
+  return "[Emscripten Module object]";
+ });
+} else if (ENVIRONMENT_IS_SHELL) {
+ if (!Module["print"]) Module["print"] = print;
+ if (typeof printErr != "undefined") Module["printErr"] = printErr;
+ if (typeof read != "undefined") {
+  Module["read"] = read;
+ } else {
+  Module["read"] = function read() {
+   throw "no read() available";
+  };
+ }
+ Module["readBinary"] = function readBinary(f) {
+  if (typeof readbuffer === "function") {
+   return new Uint8Array(readbuffer(f));
+  }
+  var data = read(f, "binary");
+  assert(typeof data === "object");
+  return data;
+ };
+ if (typeof scriptArgs != "undefined") {
+  Module["arguments"] = scriptArgs;
+ } else if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module["read"] = function read(url) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, false);
+  xhr.send(null);
+  return xhr.responseText;
+ };
+ Module["readAsync"] = function readAsync(url, onload, onerror) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, true);
+  xhr.responseType = "arraybuffer";
+  xhr.onload = function xhr_onload() {
+   if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
+    onload(xhr.response);
+   } else {
+    onerror();
+   }
+  };
+  xhr.onerror = onerror;
+  xhr.send(null);
+ };
+ if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+ if (typeof console !== "undefined") {
+  if (!Module["print"]) Module["print"] = function print(x) {
+   console.log(x);
+  };
+  if (!Module["printErr"]) Module["printErr"] = function printErr(x) {
+   console.warn(x);
+  };
+ } else {
+  var TRY_USE_DUMP = false;
+  if (!Module["print"]) Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function(x) {
+   dump(x);
+  }) : (function(x) {});
+ }
+ if (ENVIRONMENT_IS_WORKER) {
+  Module["load"] = importScripts;
+ }
+ if (typeof Module["setWindowTitle"] === "undefined") {
+  Module["setWindowTitle"] = (function(title) {
+   document.title = title;
+  });
+ }
+} else {
+ throw "Unknown runtime environment. Where are we?";
+}
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module["load"] && Module["read"]) {
+ Module["load"] = function load(f) {
+  globalEval(Module["read"](f));
+ };
+}
+if (!Module["print"]) {
+ Module["print"] = (function() {});
+}
+if (!Module["printErr"]) {
+ Module["printErr"] = Module["print"];
+}
+if (!Module["arguments"]) {
+ Module["arguments"] = [];
+}
+if (!Module["thisProgram"]) {
+ Module["thisProgram"] = "./this.program";
+}
+Module.print = Module["print"];
+Module.printErr = Module["printErr"];
+Module["preRun"] = [];
+Module["postRun"] = [];
+for (var key in moduleOverrides) {
+ if (moduleOverrides.hasOwnProperty(key)) {
+  Module[key] = moduleOverrides[key];
+ }
+}
+moduleOverrides = undefined;
+var Runtime = {
+ setTempRet0: (function(value) {
+  tempRet0 = value;
+  return value;
+ }),
+ getTempRet0: (function() {
+  return tempRet0;
+ }),
+ stackSave: (function() {
+  return STACKTOP;
+ }),
+ stackRestore: (function(stackTop) {
+  STACKTOP = stackTop;
+ }),
+ getNativeTypeSize: (function(type) {
+  switch (type) {
+  case "i1":
+  case "i8":
+   return 1;
+  case "i16":
+   return 2;
+  case "i32":
+   return 4;
+  case "i64":
+   return 8;
+  case "float":
+   return 4;
+  case "double":
+   return 8;
+  default:
+   {
+    if (type[type.length - 1] === "*") {
+     return Runtime.QUANTUM_SIZE;
+    } else if (type[0] === "i") {
+     var bits = parseInt(type.substr(1));
+     assert(bits % 8 === 0);
+     return bits / 8;
+    } else {
+     return 0;
+    }
+   }
+  }
+ }),
+ getNativeFieldSize: (function(type) {
+  return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
+ }),
+ STACK_ALIGN: 16,
+ prepVararg: (function(ptr, type) {
+  if (type === "double" || type === "i64") {
+   if (ptr & 7) {
+    assert((ptr & 7) === 4);
+    ptr += 4;
+   }
+  } else {
+   assert((ptr & 3) === 0);
+  }
+  return ptr;
+ }),
+ getAlignSize: (function(type, size, vararg) {
+  if (!vararg && (type == "i64" || type == "double")) return 8;
+  if (!type) return Math.min(size, 8);
+  return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
+ }),
+ dynCall: (function(sig, ptr, args) {
+  if (args && args.length) {
+   return Module["dynCall_" + sig].apply(null, [ ptr ].concat(args));
+  } else {
+   return Module["dynCall_" + sig].call(null, ptr);
+  }
+ }),
+ functionPointers: [],
+ addFunction: (function(func) {
+  for (var i = 0; i < Runtime.functionPointers.length; i++) {
+   if (!Runtime.functionPointers[i]) {
+    Runtime.functionPointers[i] = func;
+    return 2 * (1 + i);
+   }
+  }
+  throw "Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";
+ }),
+ removeFunction: (function(index) {
+  Runtime.functionPointers[(index - 2) / 2] = null;
+ }),
+ warnOnce: (function(text) {
+  if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+  if (!Runtime.warnOnce.shown[text]) {
+   Runtime.warnOnce.shown[text] = 1;
+   Module.printErr(text);
+  }
+ }),
+ funcWrappers: {},
+ getFuncWrapper: (function(func, sig) {
+  assert(sig);
+  if (!Runtime.funcWrappers[sig]) {
+   Runtime.funcWrappers[sig] = {};
+  }
+  var sigCache = Runtime.funcWrappers[sig];
+  if (!sigCache[func]) {
+   if (sig.length === 1) {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func);
+    };
+   } else if (sig.length === 2) {
+    sigCache[func] = function dynCall_wrapper(arg) {
+     return Runtime.dynCall(sig, func, [ arg ]);
+    };
+   } else {
+    sigCache[func] = function dynCall_wrapper() {
+     return Runtime.dynCall(sig, func, Array.prototype.slice.call(arguments));
+    };
+   }
+  }
+  return sigCache[func];
+ }),
+ getCompilerSetting: (function(name) {
+  throw "You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";
+ }),
+ stackAlloc: (function(size) {
+  var ret = STACKTOP;
+  STACKTOP = STACKTOP + size | 0;
+  STACKTOP = STACKTOP + 15 & -16;
+  return ret;
+ }),
+ staticAlloc: (function(size) {
+  var ret = STATICTOP;
+  STATICTOP = STATICTOP + size | 0;
+  STATICTOP = STATICTOP + 15 & -16;
+  return ret;
+ }),
+ dynamicAlloc: (function(size) {
+  var ret = HEAP32[DYNAMICTOP_PTR >> 2];
+  var end = (ret + size + 15 | 0) & -16;
+  HEAP32[DYNAMICTOP_PTR >> 2] = end;
+  if (end >= TOTAL_MEMORY) {
+   var success = enlargeMemory();
+   if (!success) {
+    HEAP32[DYNAMICTOP_PTR >> 2] = ret;
+    return 0;
+   }
+  }
+  return ret;
+ }),
+ alignMemory: (function(size, quantum) {
+  var ret = size = Math.ceil(size / (quantum ? quantum : 16)) * (quantum ? quantum : 16);
+  return ret;
+ }),
+ makeBigInt: (function(low, high, unsigned) {
+  var ret = unsigned ? +(low >>> 0) + +(high >>> 0) * 4294967296 : +(low >>> 0) + +(high | 0) * 4294967296;
+  return ret;
+ }),
+ GLOBAL_BASE: 1024,
+ QUANTUM_SIZE: 4,
+ __dummy__: 0
+};
+Module["Runtime"] = Runtime;
+var ABORT = 0;
+var EXITSTATUS = 0;
+function assert(condition, text) {
+ if (!condition) {
+  abort("Assertion failed: " + text);
+ }
+}
+function getCFunc(ident) {
+ var func = Module["_" + ident];
+ if (!func) {
+  try {
+   func = eval("_" + ident);
+  } catch (e) {}
+ }
+ assert(func, "Cannot call unknown function " + ident + " (perhaps LLVM optimizations or closure removed it?)");
+ return func;
+}
+var cwrap, ccall;
+((function() {
+ var JSfuncs = {
+  "stackSave": (function() {
+   Runtime.stackSave();
+  }),
+  "stackRestore": (function() {
+   Runtime.stackRestore();
+  }),
+  "arrayToC": (function(arr) {
+   var ret = Runtime.stackAlloc(arr.length);
+   writeArrayToMemory(arr, ret);
+   return ret;
+  }),
+  "stringToC": (function(str) {
+   var ret = 0;
+   if (str !== null && str !== undefined && str !== 0) {
+    var len = (str.length << 2) + 1;
+    ret = Runtime.stackAlloc(len);
+    stringToUTF8(str, ret, len);
+   }
+   return ret;
+  })
+ };
+ var toC = {
+  "string": JSfuncs["stringToC"],
+  "array": JSfuncs["arrayToC"]
+ };
+ ccall = function ccallFunc(ident, returnType, argTypes, args, opts) {
+  var func = getCFunc(ident);
+  var cArgs = [];
+  var stack = 0;
+  if (args) {
+   for (var i = 0; i < args.length; i++) {
+    var converter = toC[argTypes[i]];
+    if (converter) {
+     if (stack === 0) stack = Runtime.stackSave();
+     cArgs[i] = converter(args[i]);
+    } else {
+     cArgs[i] = args[i];
+    }
+   }
+  }
+  var ret = func.apply(null, cArgs);
+  if (returnType === "string") ret = Pointer_stringify(ret);
+  if (stack !== 0) {
+   if (opts && opts.async) {
+    EmterpreterAsync.asyncFinalizers.push((function() {
+     Runtime.stackRestore(stack);
+    }));
+    return;
+   }
+   Runtime.stackRestore(stack);
+  }
+  return ret;
+ };
+ var sourceRegex = /^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
+ function parseJSFunc(jsfunc) {
+  var parsed = jsfunc.toString().match(sourceRegex).slice(1);
+  return {
+   arguments: parsed[0],
+   body: parsed[1],
+   returnValue: parsed[2]
+  };
+ }
+ var JSsource = null;
+ function ensureJSsource() {
+  if (!JSsource) {
+   JSsource = {};
+   for (var fun in JSfuncs) {
+    if (JSfuncs.hasOwnProperty(fun)) {
+     JSsource[fun] = parseJSFunc(JSfuncs[fun]);
+    }
+   }
+  }
+ }
+ cwrap = function cwrap(ident, returnType, argTypes) {
+  argTypes = argTypes || [];
+  var cfunc = getCFunc(ident);
+  var numericArgs = argTypes.every((function(type) {
+   return type === "number";
+  }));
+  var numericRet = returnType !== "string";
+  if (numericRet && numericArgs) {
+   return cfunc;
+  }
+  var argNames = argTypes.map((function(x, i) {
+   return "$" + i;
+  }));
+  var funcstr = "(function(" + argNames.join(",") + ") {";
+  var nargs = argTypes.length;
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += "var stack = " + JSsource["stackSave"].body + ";";
+   for (var i = 0; i < nargs; i++) {
+    var arg = argNames[i], type = argTypes[i];
+    if (type === "number") continue;
+    var convertCode = JSsource[type + "ToC"];
+    funcstr += "var " + convertCode.arguments + " = " + arg + ";";
+    funcstr += convertCode.body + ";";
+    funcstr += arg + "=(" + convertCode.returnValue + ");";
+   }
+  }
+  var cfuncname = parseJSFunc((function() {
+   return cfunc;
+  })).returnValue;
+  funcstr += "var ret = " + cfuncname + "(" + argNames.join(",") + ");";
+  if (!numericRet) {
+   var strgfy = parseJSFunc((function() {
+    return Pointer_stringify;
+   })).returnValue;
+   funcstr += "ret = " + strgfy + "(ret);";
+  }
+  if (!numericArgs) {
+   ensureJSsource();
+   funcstr += JSsource["stackRestore"].body.replace("()", "(stack)") + ";";
+  }
+  funcstr += "return ret})";
+  return eval(funcstr);
+ };
+}))();
+Module["ccall"] = ccall;
+Module["cwrap"] = cwrap;
+function setValue(ptr, value, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i8":
+  HEAP8[ptr >> 0] = value;
+  break;
+ case "i16":
+  HEAP16[ptr >> 1] = value;
+  break;
+ case "i32":
+  HEAP32[ptr >> 2] = value;
+  break;
+ case "i64":
+  tempI64 = [ value >>> 0, (tempDouble = value, +Math_abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
+  break;
+ case "float":
+  HEAPF32[ptr >> 2] = value;
+  break;
+ case "double":
+  HEAPF64[ptr >> 3] = value;
+  break;
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+}
+Module["setValue"] = setValue;
+function getValue(ptr, type, noSafe) {
+ type = type || "i8";
+ if (type.charAt(type.length - 1) === "*") type = "i32";
+ switch (type) {
+ case "i1":
+  return HEAP8[ptr >> 0];
+ case "i8":
+  return HEAP8[ptr >> 0];
+ case "i16":
+  return HEAP16[ptr >> 1];
+ case "i32":
+  return HEAP32[ptr >> 2];
+ case "i64":
+  return HEAP32[ptr >> 2];
+ case "float":
+  return HEAPF32[ptr >> 2];
+ case "double":
+  return HEAPF64[ptr >> 3];
+ default:
+  abort("invalid type for setValue: " + type);
+ }
+ return null;
+}
+Module["getValue"] = getValue;
+var ALLOC_NORMAL = 0;
+var ALLOC_STACK = 1;
+var ALLOC_STATIC = 2;
+var ALLOC_DYNAMIC = 3;
+var ALLOC_NONE = 4;
+Module["ALLOC_NORMAL"] = ALLOC_NORMAL;
+Module["ALLOC_STACK"] = ALLOC_STACK;
+Module["ALLOC_STATIC"] = ALLOC_STATIC;
+Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC;
+Module["ALLOC_NONE"] = ALLOC_NONE;
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === "number") {
+  zeroinit = true;
+  size = slab;
+ } else {
+  zeroinit = false;
+  size = slab.length;
+ }
+ var singleType = typeof types === "string" ? types : null;
+ var ret;
+ if (allocator == ALLOC_NONE) {
+  ret = ptr;
+ } else {
+  ret = [ typeof _malloc === "function" ? _malloc : Runtime.staticAlloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc ][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+ if (zeroinit) {
+  var ptr = ret, stop;
+  assert((ret & 3) == 0);
+  stop = ret + (size & ~3);
+  for (; ptr < stop; ptr += 4) {
+   HEAP32[ptr >> 2] = 0;
+  }
+  stop = ret + size;
+  while (ptr < stop) {
+   HEAP8[ptr++ >> 0] = 0;
+  }
+  return ret;
+ }
+ if (singleType === "i8") {
+  if (slab.subarray || slab.slice) {
+   HEAPU8.set(slab, ret);
+  } else {
+   HEAPU8.set(new Uint8Array(slab), ret);
+  }
+  return ret;
+ }
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+  var curr = slab[i];
+  if (typeof curr === "function") {
+   curr = Runtime.getFunctionIndex(curr);
+  }
+  type = singleType || types[i];
+  if (type === 0) {
+   i++;
+   continue;
+  }
+  if (type == "i64") type = "i32";
+  setValue(ret + i, curr, type);
+  if (previousType !== type) {
+   typeSize = Runtime.getNativeTypeSize(type);
+   previousType = type;
+  }
+  i += typeSize;
+ }
+ return ret;
+}
+Module["allocate"] = allocate;
+function getMemory(size) {
+ if (!staticSealed) return Runtime.staticAlloc(size);
+ if (!runtimeInitialized) return Runtime.dynamicAlloc(size);
+ return _malloc(size);
+}
+Module["getMemory"] = getMemory;
+function Pointer_stringify(ptr, length) {
+ if (length === 0 || !ptr) return "";
+ var hasUtf = 0;
+ var t;
+ var i = 0;
+ while (1) {
+  t = HEAPU8[ptr + i >> 0];
+  hasUtf |= t;
+  if (t == 0 && !length) break;
+  i++;
+  if (length && i == length) break;
+ }
+ if (!length) length = i;
+ var ret = "";
+ if (hasUtf < 128) {
+  var MAX_CHUNK = 1024;
+  var curr;
+  while (length > 0) {
+   curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+   ret = ret ? ret + curr : curr;
+   ptr += MAX_CHUNK;
+   length -= MAX_CHUNK;
+  }
+  return ret;
+ }
+ return Module["UTF8ToString"](ptr);
+}
+Module["Pointer_stringify"] = Pointer_stringify;
+function AsciiToString(ptr) {
+ var str = "";
+ while (1) {
+  var ch = HEAP8[ptr++ >> 0];
+  if (!ch) return str;
+  str += String.fromCharCode(ch);
+ }
+}
+Module["AsciiToString"] = AsciiToString;
+function stringToAscii(str, outPtr) {
+ return writeAsciiToMemory(str, outPtr, false);
+}
+Module["stringToAscii"] = stringToAscii;
+var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;
+function UTF8ArrayToString(u8Array, idx) {
+ var endPtr = idx;
+ while (u8Array[endPtr]) ++endPtr;
+ if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
+  return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
+ } else {
+  var u0, u1, u2, u3, u4, u5;
+  var str = "";
+  while (1) {
+   u0 = u8Array[idx++];
+   if (!u0) return str;
+   if (!(u0 & 128)) {
+    str += String.fromCharCode(u0);
+    continue;
+   }
+   u1 = u8Array[idx++] & 63;
+   if ((u0 & 224) == 192) {
+    str += String.fromCharCode((u0 & 31) << 6 | u1);
+    continue;
+   }
+   u2 = u8Array[idx++] & 63;
+   if ((u0 & 240) == 224) {
+    u0 = (u0 & 15) << 12 | u1 << 6 | u2;
+   } else {
+    u3 = u8Array[idx++] & 63;
+    if ((u0 & 248) == 240) {
+     u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3;
+    } else {
+     u4 = u8Array[idx++] & 63;
+     if ((u0 & 252) == 248) {
+      u0 = (u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4;
+     } else {
+      u5 = u8Array[idx++] & 63;
+      u0 = (u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | u5;
+     }
+    }
+   }
+   if (u0 < 65536) {
+    str += String.fromCharCode(u0);
+   } else {
+    var ch = u0 - 65536;
+    str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
+   }
+  }
+ }
+}
+Module["UTF8ArrayToString"] = UTF8ArrayToString;
+function UTF8ToString(ptr) {
+ return UTF8ArrayToString(HEAPU8, ptr);
+}
+Module["UTF8ToString"] = UTF8ToString;
+function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
+ if (!(maxBytesToWrite > 0)) return 0;
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   if (outIdx >= endIdx) break;
+   outU8Array[outIdx++] = u;
+  } else if (u <= 2047) {
+   if (outIdx + 1 >= endIdx) break;
+   outU8Array[outIdx++] = 192 | u >> 6;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 65535) {
+   if (outIdx + 2 >= endIdx) break;
+   outU8Array[outIdx++] = 224 | u >> 12;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 2097151) {
+   if (outIdx + 3 >= endIdx) break;
+   outU8Array[outIdx++] = 240 | u >> 18;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else if (u <= 67108863) {
+   if (outIdx + 4 >= endIdx) break;
+   outU8Array[outIdx++] = 248 | u >> 24;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  } else {
+   if (outIdx + 5 >= endIdx) break;
+   outU8Array[outIdx++] = 252 | u >> 30;
+   outU8Array[outIdx++] = 128 | u >> 24 & 63;
+   outU8Array[outIdx++] = 128 | u >> 18 & 63;
+   outU8Array[outIdx++] = 128 | u >> 12 & 63;
+   outU8Array[outIdx++] = 128 | u >> 6 & 63;
+   outU8Array[outIdx++] = 128 | u & 63;
+  }
+ }
+ outU8Array[outIdx] = 0;
+ return outIdx - startIdx;
+}
+Module["stringToUTF8Array"] = stringToUTF8Array;
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
+}
+Module["stringToUTF8"] = stringToUTF8;
+function lengthBytesUTF8(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+  var u = str.charCodeAt(i);
+  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
+  if (u <= 127) {
+   ++len;
+  } else if (u <= 2047) {
+   len += 2;
+  } else if (u <= 65535) {
+   len += 3;
+  } else if (u <= 2097151) {
+   len += 4;
+  } else if (u <= 67108863) {
+   len += 5;
+  } else {
+   len += 6;
+  }
+ }
+ return len;
+}
+Module["lengthBytesUTF8"] = lengthBytesUTF8;
+var UTF16Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le") : undefined;
+function demangle(func) {
+ var __cxa_demangle_func = Module["___cxa_demangle"] || Module["__cxa_demangle"];
+ if (__cxa_demangle_func) {
+  try {
+   var s = func.substr(1);
+   var len = lengthBytesUTF8(s) + 1;
+   var buf = _malloc(len);
+   stringToUTF8(s, buf, len);
+   var status = _malloc(4);
+   var ret = __cxa_demangle_func(buf, 0, 0, status);
+   if (getValue(status, "i32") === 0 && ret) {
+    return Pointer_stringify(ret);
+   }
+  } catch (e) {} finally {
+   if (buf) _free(buf);
+   if (status) _free(status);
+   if (ret) _free(ret);
+  }
+  return func;
+ }
+ Runtime.warnOnce("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");
+ return func;
+}
+function demangleAll(text) {
+ var regex = /__Z[\w\d_]+/g;
+ return text.replace(regex, (function(x) {
+  var y = demangle(x);
+  return x === y ? x : x + " [" + y + "]";
+ }));
+}
+function jsStackTrace() {
+ var err = new Error;
+ if (!err.stack) {
+  try {
+   throw new Error(0);
+  } catch (e) {
+   err = e;
+  }
+  if (!err.stack) {
+   return "(no stack trace available)";
+  }
+ }
+ return err.stack.toString();
+}
+function stackTrace() {
+ var js = jsStackTrace();
+ if (Module["extraStackTrace"]) js += "\n" + Module["extraStackTrace"]();
+ return demangleAll(js);
+}
+Module["stackTrace"] = stackTrace;
+var WASM_PAGE_SIZE = 65536;
+var ASMJS_PAGE_SIZE = 16777216;
+function alignUp(x, multiple) {
+ if (x % multiple > 0) {
+  x += multiple - x % multiple;
+ }
+ return x;
+}
+var HEAP;
+var buffer;
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+function updateGlobalBuffer(buf) {
+ Module["buffer"] = buffer = buf;
+}
+function updateGlobalBufferViews() {
+ Module["HEAP8"] = HEAP8 = new Int8Array(buffer);
+ Module["HEAP16"] = HEAP16 = new Int16Array(buffer);
+ Module["HEAP32"] = HEAP32 = new Int32Array(buffer);
+ Module["HEAPU8"] = HEAPU8 = new Uint8Array(buffer);
+ Module["HEAPU16"] = HEAPU16 = new Uint16Array(buffer);
+ Module["HEAPU32"] = HEAPU32 = new Uint32Array(buffer);
+ Module["HEAPF32"] = HEAPF32 = new Float32Array(buffer);
+ Module["HEAPF64"] = HEAPF64 = new Float64Array(buffer);
+}
+var STATIC_BASE, STATICTOP, staticSealed;
+var STACK_BASE, STACKTOP, STACK_MAX;
+var DYNAMIC_BASE, DYNAMICTOP_PTR;
+STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
+staticSealed = false;
+function abortOnCannotGrowMemory() {
+ abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value " + TOTAL_MEMORY + ", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ");
+}
+function enlargeMemory() {
+ abortOnCannotGrowMemory();
+}
+var TOTAL_STACK = Module["TOTAL_STACK"] || 5242880;
+var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 629145600;
+if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was " + TOTAL_MEMORY + "! (TOTAL_STACK=" + TOTAL_STACK + ")");
+if (Module["buffer"]) {
+ buffer = Module["buffer"];
+} else {
+ if (typeof WebAssembly === "object" && typeof WebAssembly.Memory === "function") {
+  Module["wasmMemory"] = new WebAssembly.Memory({
+   initial: TOTAL_MEMORY / WASM_PAGE_SIZE,
+   maximum: TOTAL_MEMORY / WASM_PAGE_SIZE
+  });
+  buffer = Module["wasmMemory"].buffer;
+ } else {
+  buffer = new ArrayBuffer(TOTAL_MEMORY);
+ }
+}
+updateGlobalBufferViews();
+function getTotalMemory() {
+ return TOTAL_MEMORY;
+}
+HEAP32[0] = 1668509029;
+HEAP16[1] = 25459;
+if (HEAPU8[2] !== 115 || HEAPU8[3] !== 99) throw "Runtime error: expected the system to be little-endian!";
+Module["HEAP"] = HEAP;
+Module["buffer"] = buffer;
+Module["HEAP8"] = HEAP8;
+Module["HEAP16"] = HEAP16;
+Module["HEAP32"] = HEAP32;
+Module["HEAPU8"] = HEAPU8;
+Module["HEAPU16"] = HEAPU16;
+Module["HEAPU32"] = HEAPU32;
+Module["HEAPF32"] = HEAPF32;
+Module["HEAPF64"] = HEAPF64;
+function callRuntimeCallbacks(callbacks) {
+ while (callbacks.length > 0) {
+  var callback = callbacks.shift();
+  if (typeof callback == "function") {
+   callback();
+   continue;
+  }
+  var func = callback.func;
+  if (typeof func === "number") {
+   if (callback.arg === undefined) {
+    Module["dynCall_v"](func);
+   } else {
+    Module["dynCall_vi"](func, callback.arg);
+   }
+  } else {
+   func(callback.arg === undefined ? null : callback.arg);
+  }
+ }
+}
+var __ATPRERUN__ = [];
+var __ATINIT__ = [];
+var __ATMAIN__ = [];
+var __ATEXIT__ = [];
+var __ATPOSTRUN__ = [];
+var runtimeInitialized = false;
+var runtimeExited = false;
+function preRun() {
+ if (Module["preRun"]) {
+  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
+  while (Module["preRun"].length) {
+   addOnPreRun(Module["preRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+function ensureInitRuntime() {
+ if (runtimeInitialized) return;
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
+function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
+ runtimeExited = true;
+}
+function postRun() {
+ if (Module["postRun"]) {
+  if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
+  while (Module["postRun"].length) {
+   addOnPostRun(Module["postRun"].shift());
+  }
+ }
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+Module["addOnPreRun"] = addOnPreRun;
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+Module["addOnInit"] = addOnInit;
+function addOnPreMain(cb) {
+ __ATMAIN__.unshift(cb);
+}
+Module["addOnPreMain"] = addOnPreMain;
+function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
+}
+Module["addOnExit"] = addOnExit;
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+Module["addOnPostRun"] = addOnPostRun;
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+Module["intArrayFromString"] = intArrayFromString;
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+  var chr = array[i];
+  if (chr > 255) {
+   chr &= 255;
+  }
+  ret.push(String.fromCharCode(chr));
+ }
+ return ret.join("");
+}
+Module["intArrayToString"] = intArrayToString;
+function writeStringToMemory(string, buffer, dontAddNull) {
+ Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");
+ var lastChar, end;
+ if (dontAddNull) {
+  end = buffer + lengthBytesUTF8(string);
+  lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar;
+}
+Module["writeStringToMemory"] = writeStringToMemory;
+function writeArrayToMemory(array, buffer) {
+ HEAP8.set(array, buffer);
+}
+Module["writeArrayToMemory"] = writeArrayToMemory;
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+  HEAP8[buffer++ >> 0] = str.charCodeAt(i);
+ }
+ if (!dontAddNull) HEAP8[buffer >> 0] = 0;
+}
+Module["writeAsciiToMemory"] = writeAsciiToMemory;
+if (!Math["imul"] || Math["imul"](4294967295, 5) !== -5) Math["imul"] = function imul(a, b) {
+ var ah = a >>> 16;
+ var al = a & 65535;
+ var bh = b >>> 16;
+ var bl = b & 65535;
+ return al * bl + (ah * bl + al * bh << 16) | 0;
+};
+Math.imul = Math["imul"];
+if (!Math["fround"]) {
+ var froundBuffer = new Float32Array(1);
+ Math["fround"] = (function(x) {
+  froundBuffer[0] = x;
+  return froundBuffer[0];
+ });
+}
+Math.fround = Math["fround"];
+if (!Math["clz32"]) Math["clz32"] = (function(x) {
+ x = x >>> 0;
+ for (var i = 0; i < 32; i++) {
+  if (x & 1 << 31 - i) return i;
+ }
+ return 32;
+});
+Math.clz32 = Math["clz32"];
+if (!Math["trunc"]) Math["trunc"] = (function(x) {
+ return x < 0 ? Math.ceil(x) : Math.floor(x);
+});
+Math.trunc = Math["trunc"];
+var Math_abs = Math.abs;
+var Math_cos = Math.cos;
+var Math_sin = Math.sin;
+var Math_tan = Math.tan;
+var Math_acos = Math.acos;
+var Math_asin = Math.asin;
+var Math_atan = Math.atan;
+var Math_atan2 = Math.atan2;
+var Math_exp = Math.exp;
+var Math_log = Math.log;
+var Math_sqrt = Math.sqrt;
+var Math_ceil = Math.ceil;
+var Math_floor = Math.floor;
+var Math_pow = Math.pow;
+var Math_imul = Math.imul;
+var Math_fround = Math.fround;
+var Math_round = Math.round;
+var Math_min = Math.min;
+var Math_clz32 = Math.clz32;
+var Math_trunc = Math.trunc;
+var runDependencies = 0;
+var runDependencyWatcher = null;
+var dependenciesFulfilled = null;
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+}
+Module["addRunDependency"] = addRunDependency;
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module["monitorRunDependencies"]) {
+  Module["monitorRunDependencies"](runDependencies);
+ }
+ if (runDependencies == 0) {
+  if (runDependencyWatcher !== null) {
+   clearInterval(runDependencyWatcher);
+   runDependencyWatcher = null;
+  }
+  if (dependenciesFulfilled) {
+   var callback = dependenciesFulfilled;
+   dependenciesFulfilled = null;
+   callback();
+  }
+ }
+}
+Module["removeRunDependency"] = removeRunDependency;
+Module["preloadedImages"] = {};
+Module["preloadedAudios"] = {};
+var memoryInitializer = null;
+function integrateWasmJS(Module) {
+ var method = Module["wasmJSMethod"] || "native-wasm";
+ Module["wasmJSMethod"] = method;
+ var wasmTextFile = Module["wasmTextFile"] || "js-output.wast";
+ var wasmBinaryFile = Module["wasmBinaryFile"] || "js-output.wasm";
+ var asmjsCodeFile = Module["asmjsCodeFile"] || "js-output.temp.asm.js";
+ var wasmPageSize = 64 * 1024;
+ var asm2wasmImports = {
+  "f64-rem": (function(x, y) {
+   return x % y;
+  }),
+  "f64-to-int": (function(x) {
+   return x | 0;
+  }),
+  "i32s-div": (function(x, y) {
+   return (x | 0) / (y | 0) | 0;
+  }),
+  "i32u-div": (function(x, y) {
+   return (x >>> 0) / (y >>> 0) >>> 0;
+  }),
+  "i32s-rem": (function(x, y) {
+   return (x | 0) % (y | 0) | 0;
+  }),
+  "i32u-rem": (function(x, y) {
+   return (x >>> 0) % (y >>> 0) >>> 0;
+  }),
+  "debugger": (function() {
+   debugger;
+  })
+ };
+ var info = {
+  "global": null,
+  "env": null,
+  "asm2wasm": asm2wasmImports,
+  "parent": Module
+ };
+ var exports = null;
+ function lookupImport(mod, base) {
+  var lookup = info;
+  if (mod.indexOf(".") < 0) {
+   lookup = (lookup || {})[mod];
+  } else {
+   var parts = mod.split(".");
+   lookup = (lookup || {})[parts[0]];
+   lookup = (lookup || {})[parts[1]];
+  }
+  if (base) {
+   lookup = (lookup || {})[base];
+  }
+  if (lookup === undefined) {
+   abort("bad lookupImport to (" + mod + ")." + base);
+  }
+  return lookup;
+ }
+ function mergeMemory(newBuffer) {
+  var oldBuffer = Module["buffer"];
+  if (newBuffer.byteLength < oldBuffer.byteLength) {
+   Module["printErr"]("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");
+  }
+  var oldView = new Int8Array(oldBuffer);
+  var newView = new Int8Array(newBuffer);
+  if (!memoryInitializer) {
+   oldView.set(newView.subarray(Module["STATIC_BASE"], Module["STATIC_BASE"] + Module["STATIC_BUMP"]), Module["STATIC_BASE"]);
+  }
+  newView.set(oldView);
+  updateGlobalBuffer(newBuffer);
+  updateGlobalBufferViews();
+ }
+ var WasmTypes = {
+  none: 0,
+  i32: 1,
+  i64: 2,
+  f32: 3,
+  f64: 4
+ };
+ function fixImports(imports) {
+  if (!0) return imports;
+  var ret = {};
+  for (var i in imports) {
+   var fixed = i;
+   if (fixed[0] == "_") fixed = fixed.substr(1);
+   ret[fixed] = imports[i];
+  }
+  return ret;
+ }
+ function getBinary() {
+  var binary;
+  if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+   binary = Module["wasmBinary"];
+   assert(binary, "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)");
+   binary = new Uint8Array(binary);
+  } else {
+   binary = Module["readBinary"](wasmBinaryFile);
+  }
+  return binary;
+ }
+ function doJustAsm(global, env, providedBuffer) {
+  if (typeof Module["asm"] !== "function" || Module["asm"] === methodHandler) {
+   if (!Module["asmPreload"]) {
+    eval(Module["read"](asmjsCodeFile));
+   } else {
+    Module["asm"] = Module["asmPreload"];
+   }
+  }
+  if (typeof Module["asm"] !== "function") {
+   Module["printErr"]("asm evalling did not set the module properly");
+   return false;
+  }
+  return Module["asm"](global, env, providedBuffer);
+ }
+ function doNativeWasm(global, env, providedBuffer) {
+  if (typeof WebAssembly !== "object") {
+   Module["printErr"]("no native wasm support detected");
+   return false;
+  }
+  if (!(Module["wasmMemory"] instanceof WebAssembly.Memory)) {
+   Module["printErr"]("no native wasm Memory in use");
+   return false;
+  }
+  env["memory"] = Module["wasmMemory"];
+  info["global"] = {
+   "NaN": NaN,
+   "Infinity": Infinity
+  };
+  info["global.Math"] = global.Math;
+  info["env"] = env;
+  function receiveInstance(instance) {
+   exports = instance.exports;
+   if (exports.memory) mergeMemory(exports.memory);
+   Module["asm"] = exports;
+   Module["usingWasm"] = true;
+  }
+  Module["printErr"]("asynchronously preparing wasm");
+  addRunDependency("wasm-instantiate");
+  let __start = Date.now();
+  WebAssembly.instantiate(___wasmModule, info).then((function(instance) {
+   receiveInstance(instance);
+   removeRunDependency("wasm-instantiate");
+  })).catch((function(reason) {
+   Module["printErr"]("failed to asynchronously prepare wasm:\n  " + reason);
+  }));
+  return {};
+  var instance;
+  try {
+   instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info);
+  } catch (e) {
+   Module["printErr"]("failed to compile wasm module: " + e);
+   if (e.toString().indexOf("imported Memory with incompatible size") >= 0) {
+    Module["printErr"]("Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).");
+   }
+   return false;
+  }
+  receiveInstance(instance);
+  return exports;
+ }
+ function doWasmPolyfill(global, env, providedBuffer, method) {
+  if (typeof WasmJS !== "function") {
+   Module["printErr"]("WasmJS not detected - polyfill not bundled?");
+   return false;
+  }
+  var wasmJS = WasmJS({});
+  wasmJS["outside"] = Module;
+  wasmJS["info"] = info;
+  wasmJS["lookupImport"] = lookupImport;
+  assert(providedBuffer === Module["buffer"]);
+  info.global = global;
+  info.env = env;
+  assert(providedBuffer === Module["buffer"]);
+  env["memory"] = providedBuffer;
+  assert(env["memory"] instanceof ArrayBuffer);
+  wasmJS["providedTotalMemory"] = Module["buffer"].byteLength;
+  var code;
+  if (method === "interpret-binary") {
+   code = getBinary();
+  } else {
+   code = Module["read"](method == "interpret-asm2wasm" ? asmjsCodeFile : wasmTextFile);
+  }
+  var temp;
+  if (method == "interpret-asm2wasm") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_asm2wasm"](temp);
+  } else if (method === "interpret-s-expr") {
+   temp = wasmJS["_malloc"](code.length + 1);
+   wasmJS["writeAsciiToMemory"](code, temp);
+   wasmJS["_load_s_expr2wasm"](temp);
+  } else if (method === "interpret-binary") {
+   temp = wasmJS["_malloc"](code.length);
+   wasmJS["HEAPU8"].set(code, temp);
+   wasmJS["_load_binary2wasm"](temp, code.length);
+  } else {
+   throw "what? " + method;
+  }
+  wasmJS["_free"](temp);
+  wasmJS["_instantiate"](temp);
+  if (Module["newBuffer"]) {
+   mergeMemory(Module["newBuffer"]);
+   Module["newBuffer"] = null;
+  }
+  exports = wasmJS["asmExports"];
+  return exports;
+ }
+ Module["asmPreload"] = Module["asm"];
+ Module["reallocBuffer"] = (function(size) {
+  var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE;
+  size = alignUp(size, PAGE_MULTIPLE);
+  var old = Module["buffer"];
+  var oldSize = old.byteLength;
+  if (Module["usingWasm"]) {
+   try {
+    var result = Module["wasmMemory"].grow((size - oldSize) / wasmPageSize);
+    if (result !== (-1 | 0)) {
+     return Module["buffer"] = Module["wasmMemory"].buffer;
+    } else {
+     return null;
+    }
+   } catch (e) {
+    return null;
+   }
+  } else {
+   exports["__growWasmMemory"]((size - oldSize) / wasmPageSize);
+   return Module["buffer"] !== old ? Module["buffer"] : null;
+  }
+ });
+ Module["asm"] = (function(global, env, providedBuffer) {
+  global = fixImports(global);
+  env = fixImports(env);
+  if (!env["table"]) {
+   var TABLE_SIZE = Module["wasmTableSize"];
+   if (TABLE_SIZE === undefined) TABLE_SIZE = 1024;
+   var MAX_TABLE_SIZE = Module["wasmMaxTableSize"];
+   if (typeof WebAssembly === "object" && typeof WebAssembly.Table === "function") {
+    if (MAX_TABLE_SIZE !== undefined) {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      maximum: MAX_TABLE_SIZE,
+      element: "anyfunc"
+     });
+    } else {
+     env["table"] = new WebAssembly.Table({
+      initial: TABLE_SIZE,
+      element: "anyfunc"
+     });
+    }
+   } else {
+    env["table"] = new Array(TABLE_SIZE);
+   }
+   Module["wasmTable"] = env["table"];
+  }
+  if (!env["memoryBase"]) {
+   env["memoryBase"] = Module["STATIC_BASE"];
+  }
+  if (!env["tableBase"]) {
+   env["tableBase"] = 0;
+  }
+  var exports;
+  var methods = method.split(",");
+  for (var i = 0; i < methods.length; i++) {
+   var curr = methods[i];
+   Module["printErr"]("trying binaryen method: " + curr);
+   if (curr === "native-wasm") {
+    if (exports = doNativeWasm(global, env, providedBuffer)) break;
+   } else if (curr === "asmjs") {
+    if (exports = doJustAsm(global, env, providedBuffer)) break;
+   } else if (curr === "interpret-asm2wasm" || curr === "interpret-s-expr" || curr === "interpret-binary") {
+    if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break;
+   } else {
+    throw "bad method: " + curr;
+   }
+  }
+  if (!exports) throw "no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods";
+  Module["printErr"]("binaryen method succeeded.");
+  return exports;
+ });
+ var methodHandler = Module["asm"];
+}
+integrateWasmJS(Module);
+var ASM_CONSTS = [];
+STATIC_BASE = 1024;
+STATICTOP = STATIC_BASE + 5184;
+__ATINIT__.push();
+memoryInitializer = Module["wasmJSMethod"].indexOf("asmjs") >= 0 || Module["wasmJSMethod"].indexOf("interpret-asm2wasm") >= 0 ? "js-output.html.mem" : null;
+var STATIC_BUMP = 5184;
+Module["STATIC_BASE"] = STATIC_BASE;
+Module["STATIC_BUMP"] = STATIC_BUMP;
+var tempDoublePtr = STATICTOP;
+STATICTOP += 16;
+Module["_memset"] = _memset;
+function _pthread_cleanup_push(routine, arg) {
+ __ATEXIT__.push((function() {
+  Module["dynCall_vi"](routine, arg);
+ }));
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _pthread_cleanup_pop() {
+ assert(_pthread_cleanup_push.level == __ATEXIT__.length, "cannot pop if something else added meanwhile!");
+ __ATEXIT__.pop();
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+}
+function _abort() {
+ Module["abort"]();
+}
+function ___lock() {}
+function ___unlock() {}
+var SYSCALLS = {
+ varargs: 0,
+ get: (function(varargs) {
+  SYSCALLS.varargs += 4;
+  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
+  return ret;
+ }),
+ getStr: (function() {
+  var ret = Pointer_stringify(SYSCALLS.get());
+  return ret;
+ }),
+ get64: (function() {
+  var low = SYSCALLS.get(), high = SYSCALLS.get();
+  if (low >= 0) assert(high === 0); else assert(high === -1);
+  return low;
+ }),
+ getZero: (function() {
+  assert(SYSCALLS.get() === 0);
+ })
+};
+function ___syscall6(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD();
+  FS.close(stream);
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___setErrNo(value) {
+ if (Module["___errno_location"]) HEAP32[Module["___errno_location"]() >> 2] = value;
+ return value;
+}
+Module["_sbrk"] = _sbrk;
+function _gettimeofday(ptr) {
+ var now = Date.now();
+ HEAP32[ptr >> 2] = now / 1e3 | 0;
+ HEAP32[ptr + 4 >> 2] = now % 1e3 * 1e3 | 0;
+ return 0;
+}
+function __ZSt18uncaught_exceptionv() {
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+}
+var EXCEPTIONS = {
+ last: 0,
+ caught: [],
+ infos: {},
+ deAdjust: (function(adjusted) {
+  if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
+  for (var ptr in EXCEPTIONS.infos) {
+   var info = EXCEPTIONS.infos[ptr];
+   if (info.adjusted === adjusted) {
+    return ptr;
+   }
+  }
+  return adjusted;
+ }),
+ addRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount++;
+ }),
+ decRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  assert(info.refcount > 0);
+  info.refcount--;
+  if (info.refcount === 0 && !info.rethrown) {
+   if (info.destructor) {
+    Module["dynCall_vi"](info.destructor, ptr);
+   }
+   delete EXCEPTIONS.infos[ptr];
+   ___cxa_free_exception(ptr);
+  }
+ }),
+ clearRef: (function(ptr) {
+  if (!ptr) return;
+  var info = EXCEPTIONS.infos[ptr];
+  info.refcount = 0;
+ })
+};
+function ___resumeException(ptr) {
+ if (!EXCEPTIONS.last) {
+  EXCEPTIONS.last = ptr;
+ }
+ throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
+}
+function ___cxa_find_matching_catch() {
+ var thrown = EXCEPTIONS.last;
+ if (!thrown) {
+  return (Runtime.setTempRet0(0), 0) | 0;
+ }
+ var info = EXCEPTIONS.infos[thrown];
+ var throwntype = info.type;
+ if (!throwntype) {
+  return (Runtime.setTempRet0(0), thrown) | 0;
+ }
+ var typeArray = Array.prototype.slice.call(arguments);
+ var pointer = Module["___cxa_is_pointer_type"](throwntype);
+ if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4);
+ HEAP32[___cxa_find_matching_catch.buffer >> 2] = thrown;
+ thrown = ___cxa_find_matching_catch.buffer;
+ for (var i = 0; i < typeArray.length; i++) {
+  if (typeArray[i] && Module["___cxa_can_catch"](typeArray[i], throwntype, thrown)) {
+   thrown = HEAP32[thrown >> 2];
+   info.adjusted = thrown;
+   return (Runtime.setTempRet0(typeArray[i]), thrown) | 0;
+  }
+ }
+ thrown = HEAP32[thrown >> 2];
+ return (Runtime.setTempRet0(throwntype), thrown) | 0;
+}
+function ___gxx_personality_v0() {}
+function _emscripten_memcpy_big(dest, src, num) {
+ HEAPU8.set(HEAPU8.subarray(src, src + num), dest);
+ return dest;
+}
+Module["_memcpy"] = _memcpy;
+Module["_pthread_self"] = _pthread_self;
+function ___syscall140(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
+  var offset = offset_low;
+  assert(offset_high === 0);
+  FS.llseek(stream, offset, whence);
+  HEAP32[result >> 2] = stream.position;
+  if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall146(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
+  var ret = 0;
+  if (!___syscall146.buffer) {
+   ___syscall146.buffers = [ null, [], [] ];
+   ___syscall146.printChar = (function(stream, curr) {
+    var buffer = ___syscall146.buffers[stream];
+    assert(buffer);
+    if (curr === 0 || curr === 10) {
+     (stream === 1 ? Module["print"] : Module["printErr"])(UTF8ArrayToString(buffer, 0));
+     buffer.length = 0;
+    } else {
+     buffer.push(curr);
+    }
+   });
+  }
+  for (var i = 0; i < iovcnt; i++) {
+   var ptr = HEAP32[iov + i * 8 >> 2];
+   var len = HEAP32[iov + (i * 8 + 4) >> 2];
+   for (var j = 0; j < len; j++) {
+    ___syscall146.printChar(stream, HEAPU8[ptr + j]);
+   }
+   ret += len;
+  }
+  return ret;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+function ___syscall54(which, varargs) {
+ SYSCALLS.varargs = varargs;
+ try {
+  return 0;
+ } catch (e) {
+  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
+  return -e.errno;
+ }
+}
+__ATEXIT__.push((function() {
+ var fflush = Module["_fflush"];
+ if (fflush) fflush(0);
+ var printChar = ___syscall146.printChar;
+ if (!printChar) return;
+ var buffers = ___syscall146.buffers;
+ if (buffers[1].length) printChar(1, 10);
+ if (buffers[2].length) printChar(2, 10);
+}));
+DYNAMICTOP_PTR = allocate(1, "i32", ALLOC_STATIC);
+STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);
+STACK_MAX = STACK_BASE + TOTAL_STACK;
+DYNAMIC_BASE = Runtime.alignMemory(STACK_MAX);
+HEAP32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE;
+staticSealed = true;
+Module["wasmTableSize"] = 9;
+Module["wasmMaxTableSize"] = 9;
+function invoke_ii(index, a1) {
+ try {
+  return Module["dynCall_ii"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_iiii(index, a1, a2, a3) {
+ try {
+  return Module["dynCall_iiii"](index, a1, a2, a3);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_vi(index, a1) {
+ try {
+  Module["dynCall_vi"](index, a1);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+function invoke_v(index) {
+ try {
+  Module["dynCall_v"](index);
+ } catch (e) {
+  if (typeof e !== "number" && e !== "longjmp") throw e;
+  Module["setThrew"](1, 0);
+ }
+}
+Module.asmGlobalArg = {
+ "Math": Math,
+ "Int8Array": Int8Array,
+ "Int16Array": Int16Array,
+ "Int32Array": Int32Array,
+ "Uint8Array": Uint8Array,
+ "Uint16Array": Uint16Array,
+ "Uint32Array": Uint32Array,
+ "Float32Array": Float32Array,
+ "Float64Array": Float64Array,
+ "NaN": NaN,
+ "Infinity": Infinity
+};
+Module.asmLibraryArg = {
+ "abort": abort,
+ "assert": assert,
+ "enlargeMemory": enlargeMemory,
+ "getTotalMemory": getTotalMemory,
+ "abortOnCannotGrowMemory": abortOnCannotGrowMemory,
+ "invoke_ii": invoke_ii,
+ "invoke_iiii": invoke_iiii,
+ "invoke_vi": invoke_vi,
+ "invoke_v": invoke_v,
+ "_pthread_cleanup_pop": _pthread_cleanup_pop,
+ "___syscall146": ___syscall146,
+ "___lock": ___lock,
+ "___syscall6": ___syscall6,
+ "_pthread_cleanup_push": _pthread_cleanup_push,
+ "_abort": _abort,
+ "___unlock": ___unlock,
+ "_gettimeofday": _gettimeofday,
+ "___setErrNo": ___setErrNo,
+ "_emscripten_memcpy_big": _emscripten_memcpy_big,
+ "___syscall54": ___syscall54,
+ "___syscall140": ___syscall140,
+ "___resumeException": ___resumeException,
+ "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv,
+ "___gxx_personality_v0": ___gxx_personality_v0,
+ "___cxa_find_matching_catch": ___cxa_find_matching_catch,
+ "DYNAMICTOP_PTR": DYNAMICTOP_PTR,
+ "tempDoublePtr": tempDoublePtr,
+ "ABORT": ABORT,
+ "STACKTOP": STACKTOP,
+ "STACK_MAX": STACK_MAX
+};
+var asm = Module["asm"](Module.asmGlobalArg, Module.asmLibraryArg, buffer);
+Module["asm"] = asm;
+var _malloc = Module["_malloc"] = (function() {
+ return Module["asm"]["_malloc"].apply(null, arguments);
+});
+var getTempRet0 = Module["getTempRet0"] = (function() {
+ return Module["asm"]["getTempRet0"].apply(null, arguments);
+});
+var _free = Module["_free"] = (function() {
+ return Module["asm"]["_free"].apply(null, arguments);
+});
+var _main = Module["_main"] = (function() {
+ let r = Module["asm"]["_main"].apply(null, arguments);
+ postMessage("done");
+ return r;
+});
+var setTempRet0 = Module["setTempRet0"] = (function() {
+ return Module["asm"]["setTempRet0"].apply(null, arguments);
+});
+var establishStackSpace = Module["establishStackSpace"] = (function() {
+ return Module["asm"]["establishStackSpace"].apply(null, arguments);
+});
+var _pthread_self = Module["_pthread_self"] = (function() {
+ return Module["asm"]["_pthread_self"].apply(null, arguments);
+});
+var stackSave = Module["stackSave"] = (function() {
+ return Module["asm"]["stackSave"].apply(null, arguments);
+});
+var _memset = Module["_memset"] = (function() {
+ return Module["asm"]["_memset"].apply(null, arguments);
+});
+var _sbrk = Module["_sbrk"] = (function() {
+ return Module["asm"]["_sbrk"].apply(null, arguments);
+});
+var stackRestore = Module["stackRestore"] = (function() {
+ return Module["asm"]["stackRestore"].apply(null, arguments);
+});
+var _memcpy = Module["_memcpy"] = (function() {
+ return Module["asm"]["_memcpy"].apply(null, arguments);
+});
+var stackAlloc = Module["stackAlloc"] = (function() {
+ return Module["asm"]["stackAlloc"].apply(null, arguments);
+});
+var setThrew = Module["setThrew"] = (function() {
+ return Module["asm"]["setThrew"].apply(null, arguments);
+});
+var _fflush = Module["_fflush"] = (function() {
+ return Module["asm"]["_fflush"].apply(null, arguments);
+});
+var ___errno_location = Module["___errno_location"] = (function() {
+ return Module["asm"]["___errno_location"].apply(null, arguments);
+});
+var runPostSets = Module["runPostSets"] = (function() {
+ return Module["asm"]["runPostSets"].apply(null, arguments);
+});
+var dynCall_ii = Module["dynCall_ii"] = (function() {
+ return Module["asm"]["dynCall_ii"].apply(null, arguments);
+});
+var dynCall_iiii = Module["dynCall_iiii"] = (function() {
+ return Module["asm"]["dynCall_iiii"].apply(null, arguments);
+});
+var dynCall_vi = Module["dynCall_vi"] = (function() {
+ return Module["asm"]["dynCall_vi"].apply(null, arguments);
+});
+var dynCall_v = Module["dynCall_v"] = (function() {
+ return Module["asm"]["dynCall_v"].apply(null, arguments);
+});
+Runtime.stackAlloc = Module["stackAlloc"];
+Runtime.stackSave = Module["stackSave"];
+Runtime.stackRestore = Module["stackRestore"];
+Runtime.establishStackSpace = Module["establishStackSpace"];
+Runtime.setTempRet0 = Module["setTempRet0"];
+Runtime.getTempRet0 = Module["getTempRet0"];
+Module["asm"] = asm;
+if (memoryInitializer) {
+ if (typeof Module["locateFile"] === "function") {
+  memoryInitializer = Module["locateFile"](memoryInitializer);
+ } else if (Module["memoryInitializerPrefixURL"]) {
+  memoryInitializer = Module["memoryInitializerPrefixURL"] + memoryInitializer;
+ }
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+  var data = Module["readBinary"](memoryInitializer);
+  HEAPU8.set(data, Runtime.GLOBAL_BASE);
+ } else {
+  addRunDependency("memory initializer");
+  var applyMemoryInitializer = (function(data) {
+   if (data.byteLength) data = new Uint8Array(data);
+   HEAPU8.set(data, Runtime.GLOBAL_BASE);
+   if (Module["memoryInitializerRequest"]) delete Module["memoryInitializerRequest"].response;
+   removeRunDependency("memory initializer");
+  });
+  function doBrowserLoad() {
+   Module["readAsync"](memoryInitializer, applyMemoryInitializer, (function() {
+    throw "could not load memory initializer " + memoryInitializer;
+   }));
+  }
+  if (Module["memoryInitializerRequest"]) {
+   function useRequest() {
+    var request = Module["memoryInitializerRequest"];
+    if (request.status !== 200 && request.status !== 0) {
+     console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: " + request.status + ", retrying " + memoryInitializer);
+     doBrowserLoad();
+     return;
+    }
+    applyMemoryInitializer(request.response);
+   }
+   if (Module["memoryInitializerRequest"].response) {
+    setTimeout(useRequest, 0);
+   } else {
+    Module["memoryInitializerRequest"].addEventListener("load", useRequest);
+   }
+  } else {
+   doBrowserLoad();
+  }
+ }
+}
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+}
+ExitStatus.prototype = new Error;
+ExitStatus.prototype.constructor = ExitStatus;
+var initialStackTop;
+var preloadStartTime = null;
+var calledMain = false;
+dependenciesFulfilled = function runCaller() {
+ if (!Module["calledRun"]) run();
+ if (!Module["calledRun"]) dependenciesFulfilled = runCaller;
+};
+Module["callMain"] = Module.callMain = function callMain(args) {
+ args = args || [];
+ ensureInitRuntime();
+ var argc = args.length + 1;
+ function pad() {
+  for (var i = 0; i < 4 - 1; i++) {
+   argv.push(0);
+  }
+ }
+ var argv = [ allocate(intArrayFromString(Module["thisProgram"]), "i8", ALLOC_NORMAL) ];
+ pad();
+ for (var i = 0; i < argc - 1; i = i + 1) {
+  argv.push(allocate(intArrayFromString(args[i]), "i8", ALLOC_NORMAL));
+  pad();
+ }
+ argv.push(0);
+ argv = allocate(argv, "i32", ALLOC_NORMAL);
+ try {
+  var ret = Module["_main"](argc, argv, 0);
+  exit(ret, true);
+ } catch (e) {
+  if (e instanceof ExitStatus) {
+   return;
+  } else if (e == "SimulateInfiniteLoop") {
+   Module["noExitRuntime"] = true;
+   return;
+  } else {
+   if (e && typeof e === "object" && e.stack) Module.printErr("exception thrown: " + [ e, e.stack ]);
+   throw e;
+  }
+ } finally {
+  calledMain = true;
+ }
+};
+function run(args) {
+ args = args || Module["arguments"];
+ if (preloadStartTime === null) preloadStartTime = Date.now();
+ if (runDependencies > 0) {
+  return;
+ }
+ preRun();
+ if (runDependencies > 0) return;
+ if (Module["calledRun"]) return;
+ function doRun() {
+  if (Module["calledRun"]) return;
+  Module["calledRun"] = true;
+  if (ABORT) return;
+  ensureInitRuntime();
+  preMain();
+  if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
+  if (Module["_main"] && shouldRunNow) Module["callMain"](args);
+  postRun();
+ }
+ if (Module["setStatus"]) {
+  Module["setStatus"]("Running...");
+  setTimeout((function() {
+   setTimeout((function() {
+    Module["setStatus"]("");
+   }), 1);
+   doRun();
+  }), 1);
+ } else {
+  doRun();
+ }
+}
+Module["run"] = Module.run = run;
+function exit(status, implicit) {
+ if (implicit && Module["noExitRuntime"]) {
+  return;
+ }
+ if (Module["noExitRuntime"]) {} else {
+  ABORT = true;
+  EXITSTATUS = status;
+  STACKTOP = initialStackTop;
+  exitRuntime();
+  if (Module["onExit"]) Module["onExit"](status);
+ }
+ if (ENVIRONMENT_IS_NODE) {
+  process["exit"](status);
+ } else if (ENVIRONMENT_IS_SHELL && typeof quit === "function") {
+  quit(status);
+ }
+ throw new ExitStatus(status);
+}
+Module["exit"] = Module.exit = exit;
+var abortDecorators = [];
+function abort(what) {
+ if (what !== undefined) {
+  Module.print(what);
+  Module.printErr(what);
+  what = JSON.stringify(what);
+ } else {
+  what = "";
+ }
+ ABORT = true;
+ EXITSTATUS = 1;
+ var extra = "\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";
+ var output = "abort(" + what + ") at " + stackTrace() + extra;
+ if (abortDecorators) {
+  abortDecorators.forEach((function(decorator) {
+   output = decorator(output, what);
+  }));
+ }
+ throw output;
+}
+Module["abort"] = Module.abort = abort;
+if (Module["preInit"]) {
+ if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
+ while (Module["preInit"].length > 0) {
+  Module["preInit"].pop()();
+ }
+}
+var shouldRunNow = true;
+if (Module["noInitialRun"]) {
+ shouldRunNow = false;
+}
+run();
+}
diff --git a/LayoutTests/workers/wasm-hashset/test.js b/LayoutTests/workers/wasm-hashset/test.js
new file mode 100644 (file)
index 0000000..2dde64f
--- /dev/null
@@ -0,0 +1,2020 @@
+"use strict";
+
+let __count = 0;
+function reallyDone() {
+    if (++__count === 2) {
+        console.log("Count: ", __count);
+        if (window.testRunner) {
+            __realPrint("Finished running");
+            testRunner.notifyDone();
+        }
+    }
+}
+
+let __realPrint = console.log.bind(console);
+console = {
+    log: function() {},
+    error: function() {},
+    assert: function(){},
+};
+      var Module = {
+        preRun: [],
+        postRun: [],
+        print: (function() {
+          var element = document.getElementById('output');
+          if (element) element.value = ''; // clear browser cache
+          return function(text) {
+            if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+            // These replacements are necessary if you render to raw HTML
+            //text = text.replace(/&/g, "&amp;");
+            //text = text.replace(/</g, "&lt;");
+            //text = text.replace(/>/g, "&gt;");
+            //text = text.replace('\n', '<br>', 'g');
+            console.log(text);
+            if (element) {
+              element.value += text + "\n";
+              element.scrollTop = element.scrollHeight; // focus on bottom
+            }
+          };
+        })(),
+        printErr: function(text) {
+          if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+          if (0) { // XXX disabled for safety typeof dump == 'function') {
+            dump(text + '\n'); // fast, straight to the real console
+          } else {
+            console.error(text);
+          }
+        },
+        canvas: (function() {
+            return;
+          var canvas = document.getElementById('canvas');
+
+          // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+          // application robust, you may want to override this behavior before shipping!
+          // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+          canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+          return canvas;
+        })(),
+        setStatus: function(text) {
+            console.log("Status: ", text);
+            return;
+
+          if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+          if (text === Module.setStatus.text) return;
+          var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+          var now = Date.now();
+          if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
+          if (m) {
+            text = m[1];
+            progressElement.value = parseInt(m[2])*100;
+            progressElement.max = parseInt(m[4])*100;
+            progressElement.hidden = false;
+            spinnerElement.hidden = false;
+          } else {
+            progressElement.value = null;
+            progressElement.max = null;
+            progressElement.hidden = true;
+            if (!text) spinnerElement.style.display = 'none';
+          }
+          statusElement.innerHTML = text;
+        },
+        totalDependencies: 0,
+        monitorRunDependencies: function(left) {
+          this.totalDependencies = Math.max(this.totalDependencies, left);
+          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+        }
+      };
+      Module.setStatus('Downloading...');
+      //window.onerror = function(event) {
+      //  // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
+      //  Module.setStatus('Exception thrown, see JavaScript console');
+      //  spinnerElement.style.display = 'none';
+      //  Module.setStatus = function(text) {
+      //    if (text) Module.printErr('[post-exception status] ' + text);
+      //  };
+      //};
+
+__realPrint("about to start worker");
+let worker = new Worker("./wasm-hashset/worker.js");
+worker.onmessage = function(e) {
+    console.log("on message of worker")
+    if (e.data === "done") {
+        reallyDone();
+        return;
+    }
+    if (typeof e.data === "string") {
+        __realPrint(e.data);
+        return;
+    }
+    let ___wasmModule = e.data;
+    __realPrint("Got the wasm module from worker");
+    if (!(___wasmModule instanceof WebAssembly.Module))
+        __realPrint("Not instanceof module! Bad!");
+    console.log(`Main script message at: ${Date.now()}`);
+
+    Module.wasmBinary = ___wasmModule;
+if (!Module) Module = (typeof Module !== "undefined" ? Module : null) || {};
+var moduleOverrides = {};
+for (var key in Module) {
+ if (Module.hasOwnProperty(key)) {
+  moduleOverrides[key] = Module[key];
+ }
+}
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+if (Module["ENVIRONMENT"]) {
+ if (Module["ENVIRONMENT"] === "WEB") {
+  ENVIRONMENT_IS_WEB = true;
+ } else if (Module["ENVIRONMENT"] === "WORKER") {
+  ENVIRONMENT_IS_WORKER = true;
+ } else if (Module["ENVIRONMENT"] === "NODE") {
+  ENVIRONMENT_IS_NODE = true;
+ } else if (Module["ENVIRONMENT"] === "SHELL") {
+  ENVIRONMENT_IS_SHELL = true;
+ } else {
+  throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");
+ }
+} else {
+ ENVIRONMENT_IS_WEB = typeof window === "object";
+ ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
+ ENVIRONMENT_IS_NODE = typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+}
+if (ENVIRONMENT_IS_NODE) {
+ if (!Module["print"]) Module["print"] = console.log;
+ if (!Module["printErr"]) Module["printErr"] = console.warn;
+ var nodeFS;
+ var nodePath;
+ Module["read"] = function read(filename, binary) {
+  if (!nodeFS) nodeFS = require("fs");
+  if (!nodePath) nodePath = require("path");
+  filename = nodePath["normalize"](filename);
+  var ret = nodeFS["readFileSync"](filename);
+  return binary ? ret : ret.toString();
+ };
+ Module["readBinary"] = function readBinary(filename) {
+  var ret = Module["read"](filename, true);
+  if (!ret.buffer) {
+   ret = new Uint8Array(ret);
+  }
+  assert(ret.buffer);
+  return ret;
+ };
+ Module["load"] = function load(f) {
+  globalEval(read(f));
+ };
+ if (!Module["thisProgram"]) {
+  if (process["argv"].length > 1) {
+   Module["thisProgram"] = process["argv"][1].replace(/\\/g, "/");
+  } else {
+   Module["thisProgram"] = "unknown-program";
+  }
+ }
+ Module["arguments"] = process["argv"].slice(2);
+ if (typeof module !== "undefined") {
+  module["exports"] = Module;
+ }
+ process["on"]("uncaughtException", (function(ex) {
+  if (!(ex instanceof ExitStatus)) {
+   throw ex;
+  }
+ }));
+ Module["inspect"] = (function() {
+  return "[Emscripten Module object]";
+ });
+} else if (ENVIRONMENT_IS_SHELL) {
+ if (!Module["print"]) Module["print"] = print;
+ if (typeof printErr != "undefined") Module["printErr"] = printErr;
+ if (typeof read != "undefined") {
+  Module["read"] = read;
+ } else {
+  Module["read"] = function read() {
+   throw "no read() available";
+  };
+ }
+ Module["readBinary"] = function readBinary(f) {
+  if (typeof readbuffer === "function") {
+   return new Uint8Array(readbuffer(f));
+  }
+  var data = read(f, "binary");
+  assert(typeof data === "object");
+  return data;
+ };
+ if (typeof scriptArgs != "undefined") {
+  Module["arguments"] = scriptArgs;
+ } else if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module["read"] = function read(url) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, false);
+  xhr.send(null);
+  return xhr.responseText;
+ };
+ Module["readAsync"] = function readAsync(url, onload, onerror) {
+  var xhr = new XMLHttpRequest;
+  xhr.open("GET", url, true);
+  xhr.responseType = "arraybuffer";
+  xhr.onload = function xhr_onload() {
+   if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
+    onload(xhr.response);
+   } else {
+    onerror();
+   }
+  };
+  xhr.onerror = onerror;
+  xhr.send(null);
+ };
+ if (typeof arguments != "undefined") {
+  Module["arguments"] = arguments;
+ }
+ if (typeof console !== "undefined") {
+  if (!Module["print"]) Module["print"] = function print(x) {
+   console.log(x);
+  };
+  if (!Module["printErr"]) Module["printErr"] = function printErr(x) {
+   console.warn(x);
+  };
+ } else {
+  var TRY_USE_DUMP = false;
+  if (!Module["print"]) Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function(x) {
+   dump(x);
+  }) : (function(x) {});
+ }
+ if (ENVIRONMENT_IS_WORKER) {
+  Module["load"] = importScripts;
+ }
+ if (typeof Module["setWindowTitle"] === "undefined") {
+  Module["setWindowTitle"] = (function(title) {
+   document.title = title;
+  });
+ }
+} else {
+ throw "Unknown runtime environment. Where are we?";
+}
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module["load"] && Module["read"]) {
+ Module["load"] = function load(f) {
+  globalEval(Module["read"](f));
+ };
+}
+if (!Module["print"]) {
+ Module["print"] = (function() {});
+}
+if (!Module["printErr"]) {
+ Module["printErr"] = Module["pr