blob: 61d0858a9e657d552b4c87de043e6f243bc53778 [file] [log] [blame] [edit]
/**
* @license
* Copyright 2010 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/
// === Preamble library stuff ===
// Documentation for the public APIs defined in this file must be updated in:
// site/source/docs/api_reference/preamble.js.rst
// A prebuilt local version of the documentation is available at:
// site/build/text/docs/api_reference/preamble.js.txt
// You can also build docs locally as HTML or other formats in site/
// An online HTML version (which may be of a different version of Emscripten)
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
#if PTHREADS
#include "runtime_pthread.js"
#endif
#if RELOCATABLE
{{{ makeModuleReceiveWithVar('dynamicLibraries', undefined, '[]', true) }}}
#endif
{{{ makeModuleReceiveWithVar('wasmBinary') }}}
#if WASM != 2 && MAYBE_WASM2JS
#if !WASM2JS
if (Module['doWasm2JS']) {
#endif
#include "wasm2js.js"
#if !WASM2JS
}
#endif
#endif
#if MAYBE_WASM2JS
if (WebAssembly.isWasm2js) {
// We don't need to actually download a wasm binary, mark it as present but
// empty.
wasmBinary = [];
}
#endif
#if ASSERTIONS && WASM == 1
if (typeof WebAssembly != 'object') {
err('no native wasm support detected');
}
#endif
#if SAFE_HEAP
#include "runtime_safe_heap.js"
#endif
#if USE_ASAN
#include "runtime_asan.js"
#endif
#if SUPPORT_BASE64_EMBEDDING || FORCE_FILESYSTEM
#include "base64Utils.js"
#endif
// Wasm globals
var wasmMemory;
#if SHARED_MEMORY
// For sending to workers.
var wasmModule;
#endif // SHARED_MEMORY
//========================================
// Runtime essentials
//========================================
// whether we are quitting the application. no code should run after this.
// set in exit() and abort()
var ABORT = false;
// set by exit() and abort(). Passed to 'onExit' handler.
// NOTE: This is also used as the process return code code in shell environments
// but only when noExitRuntime is false.
var EXITSTATUS;
#if ASSERTIONS || !STRICT
// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
// don't define it at all in release modes. This matches the behaviour of
// MINIMAL_RUNTIME.
// TODO(sbc): Make this the default even without STRICT enabled.
/** @type {function(*, string=)} */
function assert(condition, text) {
if (!condition) {
#if ASSERTIONS
abort('Assertion failed' + (text ? ': ' + text : ''));
#else
// This build was created without ASSERTIONS defined. `assert()` should not
// ever be called in this configuration but in case there are callers in
// the wild leave this simple abort() implementation here for now.
abort(text);
#endif
}
}
#endif
#if ASSERTIONS
// We used to include malloc/free by default in the past. Show a helpful error in
// builds with assertions.
#if !hasExportedSymbol('malloc')
function _malloc() {
abort('malloc() called but not included in the build - add `_malloc` to EXPORTED_FUNCTIONS');
}
#endif // malloc
#if !hasExportedSymbol('free')
function _free() {
// Show a helpful error since we used to include free by default in the past.
abort('free() called but not included in the build - add `_free` to EXPORTED_FUNCTIONS');
}
#endif // free
#endif // ASSERTIONS
// Memory management
var HEAP,
/** @type {!Int8Array} */
HEAP8,
/** @type {!Uint8Array} */
HEAPU8,
/** @type {!Int16Array} */
HEAP16,
/** @type {!Uint16Array} */
HEAPU16,
/** @type {!Int32Array} */
HEAP32,
/** @type {!Uint32Array} */
HEAPU32,
/** @type {!Float32Array} */
HEAPF32,
#if WASM_BIGINT
/* BigInt64Array type is not correctly defined in closure
/** not-@type {!BigInt64Array} */
HEAP64,
/* BigUint64Array type is not correctly defined in closure
/** not-t@type {!BigUint64Array} */
HEAPU64,
#endif
/** @type {!Float64Array} */
HEAPF64;
#if SUPPORT_BIG_ENDIAN
var HEAP_DATA_VIEW;
#endif
#include "runtime_shared.js"
#if ASSERTIONS
assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
#endif
#if ASSERTIONS
assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,
'JS engine does not provide full typed array support');
#endif
#if IMPORTED_MEMORY
// In non-standalone/normal mode, we create the memory here.
#include "runtime_init_memory.js"
#elif ASSERTIONS
// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY
assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
#endif // !IMPORTED_MEMORY && ASSERTIONS
#include "runtime_stack_check.js"
var __ATPRERUN__ = []; // functions called before the runtime is initialized
var __ATINIT__ = []; // functions called during startup
#if HAS_MAIN
var __ATMAIN__ = []; // functions called when main() is to be run
#endif
var __ATEXIT__ = []; // functions called during shutdown
var __ATPOSTRUN__ = []; // functions called after the main() is called
#if RELOCATABLE
var __RELOC_FUNCS__ = [];
#endif
var runtimeInitialized = false;
#if EXIT_RUNTIME
var runtimeExited = false;
#endif
function preRun() {
#if ASSERTIONS && PTHREADS
assert(!ENVIRONMENT_IS_PTHREAD); // PThreads reuse the runtime from the main thread.
#endif
#if expectToReceiveOnModule('preRun')
if (Module['preRun']) {
if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
while (Module['preRun'].length) {
addOnPreRun(Module['preRun'].shift());
}
}
#endif
callRuntimeCallbacks(__ATPRERUN__);
}
function initRuntime() {
#if RUNTIME_DEBUG
dbg('initRuntime');
#endif
#if ASSERTIONS
assert(!runtimeInitialized);
#endif
runtimeInitialized = true;
#if WASM_WORKERS
if (ENVIRONMENT_IS_WASM_WORKER) return _wasmWorkerInitializeRuntime();
#endif
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return;
#endif
#if STACK_OVERFLOW_CHECK
checkStackCookie();
#endif
#if STACK_OVERFLOW_CHECK >= 2
setStackLimits();
#endif
#if RELOCATABLE
callRuntimeCallbacks(__RELOC_FUNCS__);
#endif
<<< ATINITS >>>
callRuntimeCallbacks(__ATINIT__);
}
#if HAS_MAIN
function preMain() {
#if STACK_OVERFLOW_CHECK
checkStackCookie();
#endif
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
<<< ATMAINS >>>
callRuntimeCallbacks(__ATMAIN__);
}
#endif
#if EXIT_RUNTIME
function exitRuntime() {
#if RUNTIME_DEBUG
dbg('exitRuntime');
#endif
#if ASSERTIONS
assert(!runtimeExited);
#endif
#if ASYNCIFY == 1 && ASSERTIONS
// ASYNCIFY cannot be used once the runtime starts shutting down.
Asyncify.state = Asyncify.State.Disabled;
#endif
#if STACK_OVERFLOW_CHECK
checkStackCookie();
#endif
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
#if !STANDALONE_WASM
___funcs_on_exit(); // Native atexit() functions
#endif
callRuntimeCallbacks(__ATEXIT__);
<<< ATEXITS >>>
#if PTHREADS
PThread.terminateAllThreads();
#endif
runtimeExited = true;
}
#endif
function postRun() {
#if STACK_OVERFLOW_CHECK
checkStackCookie();
#endif
#if PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
#if expectToReceiveOnModule('postRun')
if (Module['postRun']) {
if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
while (Module['postRun'].length) {
addOnPostRun(Module['postRun'].shift());
}
}
#endif
callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb);
}
function addOnInit(cb) {
__ATINIT__.unshift(cb);
}
#if HAS_MAIN
function addOnPreMain(cb) {
__ATMAIN__.unshift(cb);
}
#endif
function addOnExit(cb) {
#if EXIT_RUNTIME
__ATEXIT__.unshift(cb);
#endif
}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
#include "runtime_math.js"
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
// Module.preRun (used by emcc to add file preloading).
// Note that you can add dependencies in preRun, even though
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
var runDependencyWatcher = null;
var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
#if ASSERTIONS
var runDependencyTracking = {};
#endif
function getUniqueRunDependency(id) {
#if ASSERTIONS
var orig = id;
while (1) {
if (!runDependencyTracking[id]) return id;
id = orig + Math.random();
}
#else
return id;
#endif
}
function addRunDependency(id) {
runDependencies++;
#if expectToReceiveOnModule('monitorRunDependencies')
Module['monitorRunDependencies']?.(runDependencies);
#endif
#if ASSERTIONS
if (id) {
assert(!runDependencyTracking[id]);
runDependencyTracking[id] = 1;
if (runDependencyWatcher === null && typeof setInterval != 'undefined') {
// Check for missing dependencies every few seconds
runDependencyWatcher = setInterval(() => {
if (ABORT) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
return;
}
var shown = false;
for (var dep in runDependencyTracking) {
if (!shown) {
shown = true;
err('still waiting on run dependencies:');
}
err(`dependency: ${dep}`);
}
if (shown) {
err('(end of list)');
}
}, 10000);
}
} else {
err('warning: run dependency added without ID');
}
#endif
}
function removeRunDependency(id) {
runDependencies--;
#if expectToReceiveOnModule('monitorRunDependencies')
Module['monitorRunDependencies']?.(runDependencies);
#endif
#if ASSERTIONS
if (id) {
assert(runDependencyTracking[id]);
delete runDependencyTracking[id];
} else {
err('warning: run dependency removed without ID');
}
#endif
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
}
if (dependenciesFulfilled) {
var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback(); // can add another dependenciesFulfilled
}
}
}
/** @param {string|number=} what */
function abort(what) {
#if expectToReceiveOnModule('onAbort')
Module['onAbort']?.(what);
#endif
what = 'Aborted(' + what + ')';
// TODO(sbc): Should we remove printing and leave it up to whoever
// catches the exception?
err(what);
ABORT = true;
#if ASSERTIONS == 0
what += '. Build with -sASSERTIONS for more info.';
#elif ASYNCIFY == 1
if (what.indexOf('RuntimeError: unreachable') >= 0) {
what += '. "unreachable" may be due to ASYNCIFY_STACK_SIZE not being large enough (try increasing it)';
}
#endif // ASSERTIONS
// Use a wasm runtime error, because a JS error might be seen as a foreign
// exception, which means we'd run destructors on it. We need the error to
// simply make the program stop.
// FIXME This approach does not work in Wasm EH because it currently does not assume
// all RuntimeErrors are from traps; it decides whether a RuntimeError is from
// a trap or not based on a hidden field within the object. So at the moment
// we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
// allows this in the wasm spec.
// Suppress closure compiler warning here. Closure compiler's builtin extern
// definition for WebAssembly.RuntimeError claims it takes no arguments even
// though it can.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
#if WASM_EXCEPTIONS == 1
// See above, in the meantime, we resort to wasm code for trapping.
//
// In case abort() is called before the module is initialized, wasmExports
// and its exported '__trap' function is not available, in which case we throw
// a RuntimeError.
//
// We trap instead of throwing RuntimeError to prevent infinite-looping in
// Wasm EH code (because RuntimeError is considered as a foreign exception and
// caught by 'catch_all'), but in case throwing RuntimeError is fine because
// the module has not even been instantiated, even less running.
if (runtimeInitialized) {
___trap();
}
#endif
/** @suppress {checkTypes} */
var e = new WebAssembly.RuntimeError(what);
#if MODULARIZE
readyPromiseReject(e);
#endif
// Throw the error whether or not MODULARIZE is set because abort is used
// in code paths apart from instantiation where an exception is expected
// to be thrown when abort is called.
throw e;
}
#include "memoryprofiler.js"
#if ASSERTIONS && !('$FS' in addedLibraryItems)
// show errors on likely calls to FS when it was not included
var FS = {
error() {
abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM');
},
init() { FS.error() },
createDataFile() { FS.error() },
createPreloadedFile() { FS.error() },
createLazyFile() { FS.error() },
open() { FS.error() },
mkdev() { FS.error() },
registerDevice() { FS.error() },
analyzePath() { FS.error() },
ErrnoError() { FS.error() },
};
Module['FS_createDataFile'] = FS.createDataFile;
Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
#endif
#include "URIUtils.js"
#if ASSERTIONS
function createExportWrapper(name, nargs) {
return (...args) => {
assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
#if EXIT_RUNTIME
assert(!runtimeExited, `native function \`${name}\` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)`);
#endif
var f = wasmExports[name];
assert(f, `exported native function \`${name}\` not found`);
// Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
return f(...args);
};
}
#endif
#include "runtime_exceptions.js"
#if ABORT_ON_WASM_EXCEPTIONS
// `abortWrapperDepth` counts the recursion level of the wrapper function so
// that we only handle exceptions at the top level letting the exception
// mechanics work uninterrupted at the inner level. Additionally,
// `abortWrapperDepth` is also manually incremented in callMain so that we know
// to ignore exceptions from there since they're handled by callMain directly.
var abortWrapperDepth = 0;
function makeAbortWrapper(original) {
return (...args) => {
// Don't allow this function to be called if we're aborted!
if (ABORT) {
throw 'program has already aborted!';
}
abortWrapperDepth++;
try {
return original(...args);
} catch (e) {
if (
ABORT // rethrow exception if abort() was called in the original function call above
|| abortWrapperDepth > 1 // rethrow exceptions not caught at the top level if exception catching is enabled; rethrow from exceptions from within callMain
#if SUPPORT_LONGJMP == 'emscripten' // Rethrow longjmp if enabled
#if EXCEPTION_STACK_TRACES
|| e instanceof EmscriptenSjLj // EXCEPTION_STACK_TRACES=1 will throw an instance of EmscriptenSjLj
#else
|| e === Infinity // EXCEPTION_STACK_TRACES=0 will throw Infinity
#endif // EXCEPTION_STACK_TRACES
#endif
|| e === 'unwind'
) {
throw e;
}
abort('unhandled exception: ' + [e, e.stack]);
}
finally {
abortWrapperDepth--;
}
}
}
// Instrument all the exported functions to:
// - abort if an unhandled exception occurs
// - throw an exception if someone tries to call them after the program has aborted
// See settings.ABORT_ON_WASM_EXCEPTIONS for more info.
function instrumentWasmExportsWithAbort(exports) {
// Override the exported functions with the wrappers and copy over any other symbols
var instExports = {};
for (var name in exports) {
var original = exports[name];
if (typeof original == 'function') {
instExports[name] = makeAbortWrapper(original);
} else {
instExports[name] = original;
}
}
return instExports;
}
function instrumentWasmTableWithAbort() {
// Override the wasmTable get function to return the wrappers
var realGet = wasmTable.get;
var wrapperCache = {};
wasmTable.get = (i) => {
var func = realGet.call(wasmTable, i);
var cached = wrapperCache[i];
if (!cached || cached.func !== func) {
cached = wrapperCache[i] = {
func,
wrapper: makeAbortWrapper(func)
}
}
return cached.wrapper;
};
}
#endif
function findWasmBinary() {
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE && !AUDIO_WORKLET
if (Module['locateFile']) {
#endif
var f = '{{{ WASM_BINARY_FILE }}}';
#if !SINGLE_FILE
if (!isDataURI(f)) {
return locateFile(f);
}
#endif
return f;
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE && !AUDIO_WORKLET // In single-file mode, repeating WASM_BINARY_FILE would emit the contents again. For an Audio Worklet, we cannot use `new URL()`.
}
#if ENVIRONMENT_MAY_BE_SHELL
if (ENVIRONMENT_IS_SHELL)
return '{{{ WASM_BINARY_FILE }}}';
#endif
// Use bundler-friendly `new URL(..., import.meta.url)` pattern; works in browsers too.
return new URL('{{{ WASM_BINARY_FILE }}}', import.meta.url).href;
#endif
}
var wasmBinaryFile;
function getBinarySync(file) {
if (file == wasmBinaryFile && wasmBinary) {
return new Uint8Array(wasmBinary);
}
#if SUPPORT_BASE64_EMBEDDING
var binary = tryParseAsDataURI(file);
if (binary) {
return binary;
}
#endif
if (readBinary) {
return readBinary(file);
}
#if WASM_ASYNC_COMPILATION
throw 'both async and sync fetching of the wasm failed';
#else
throw 'sync fetching of the wasm failed: you can preload it to Module["wasmBinary"] manually, or emcc.py will do that for you when generating HTML (but not JS)';
#endif
}
function getBinaryPromise(binaryFile) {
#if !SINGLE_FILE
// If we don't have the binary yet, load it asynchronously using readAsync.
if (!wasmBinary
#if SUPPORT_BASE64_EMBEDDING
|| isDataURI(binaryFile)
#endif
) {
// Fetch the binary using readAsync
return readAsync(binaryFile).then(
(response) => new Uint8Array(/** @type{!ArrayBuffer} */(response)),
// Fall back to getBinarySync if readAsync fails
() => getBinarySync(binaryFile)
);
}
#endif
// Otherwise, getBinarySync should be able to get it synchronously
return Promise.resolve().then(() => getBinarySync(binaryFile));
}
#if LOAD_SOURCE_MAP
var wasmSourceMap;
#include "source_map_support.js"
#endif
#if USE_OFFSET_CONVERTER
var wasmOffsetConverter;
#include "wasm_offset_converter.js"
#endif
#if SPLIT_MODULE
{{{ makeModuleReceiveWithVar('loadSplitModule', undefined, 'instantiateSync', true) }}}
var splitModuleProxyHandler = {
get(target, prop, receiver) {
return (...args) => {
#if ASYNCIFY == 2
throw new Error('Placeholder function "' + prop + '" should not be called when using JSPI.');
#else
err(`placeholder function called: ${prop}`);
var imports = {'primary': wasmExports};
// Replace '.wasm' suffix with '.deferred.wasm'.
var deferred = wasmBinaryFile.slice(0, -5) + '.deferred.wasm'
loadSplitModule(deferred, imports, prop);
err('instantiated deferred module, continuing');
#if RELOCATABLE
// When the table is dynamically laid out, the placeholder functions names
// are offsets from the table base. In the main module, the table base is
// always 1.
return wasmTable.get(1 + parseInt(prop))(...args);
#else
return wasmTable.get(prop)(...args);
#endif
#endif
}
}
};
#endif
#if LOAD_SOURCE_MAP
function receiveSourceMapJSON(sourceMap) {
wasmSourceMap = new WasmSourceMap(sourceMap);
{{{ runIfMainThread("removeRunDependency('source-map');") }}}
}
#endif
#if SPLIT_MODULE || !WASM_ASYNC_COMPILATION
function instantiateSync(file, info) {
var module;
var binary = getBinarySync(file);
#if NODE_CODE_CACHING
if (ENVIRONMENT_IS_NODE) {
var v8 = require('v8');
// Include the V8 version in the cache name, so that we don't try to
// load cached code from another version, which fails silently (it seems
// to load ok, but we do actually recompile the binary every time).
var cachedCodeFile = '{{{ WASM_BINARY_FILE }}}.' + v8.cachedDataVersionTag() + '.cached';
cachedCodeFile = locateFile(cachedCodeFile);
var hasCached = fs.existsSync(cachedCodeFile);
if (hasCached) {
#if RUNTIME_DEBUG
dbg('NODE_CODE_CACHING: loading module');
#endif
try {
module = v8.deserialize(fs.readFileSync(cachedCodeFile));
} catch (e) {
err(`NODE_CODE_CACHING: failed to deserialize, bad cache file? (${cachedCodeFile})`);
// Save the new compiled code when we have it.
hasCached = false;
}
}
}
module ||= new WebAssembly.Module(binary);
if (ENVIRONMENT_IS_NODE && !hasCached) {
#if RUNTIME_DEBUG
dbg('NODE_CODE_CACHING: saving module');
#endif
fs.writeFileSync(cachedCodeFile, v8.serialize(module));
}
#else // NODE_CODE_CACHING
module = new WebAssembly.Module(binary);
#endif // NODE_CODE_CACHING
var instance = new WebAssembly.Instance(module, info);
#if USE_OFFSET_CONVERTER
wasmOffsetConverter = new WasmOffsetConverter(binary, module);
#endif
#if LOAD_SOURCE_MAP
receiveSourceMapJSON(getSourceMap());
#endif
return [instance, module];
}
#endif
#if (PTHREADS || WASM_WORKERS) && (LOAD_SOURCE_MAP || USE_OFFSET_CONVERTER)
// When using postMessage to send an object, it is processed by the structured
// clone algorithm. The prototype, and hence methods, on that object is then
// lost. This function adds back the lost prototype. This does not work with
// nested objects that has prototypes, but it suffices for WasmSourceMap and
// WasmOffsetConverter.
function resetPrototype(constructor, attrs) {
var object = Object.create(constructor.prototype);
return Object.assign(object, attrs);
}
#endif
#if WASM_ASYNC_COMPILATION
function instantiateArrayBuffer(binaryFile, imports, receiver) {
#if USE_OFFSET_CONVERTER
var savedBinary;
#endif
return getBinaryPromise(binaryFile).then((binary) => {
#if USE_OFFSET_CONVERTER
savedBinary = binary;
#endif
return WebAssembly.instantiate(binary, imports);
#if USE_OFFSET_CONVERTER
}).then((instance) => {
// wasmOffsetConverter needs to be assigned before calling the receiver
// (receiveInstantiationResult). See comments below in instantiateAsync.
wasmOffsetConverter = new WasmOffsetConverter(savedBinary, instance.module);
return instance;
#endif
}).then(receiver, (reason) => {
err(`failed to asynchronously prepare wasm: ${reason}`);
#if WASM == 2
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
if (typeof location != 'undefined') {
#endif
// WebAssembly compilation failed, try running the JS fallback instead.
var search = location.search;
if (search.indexOf('_rwasm=0') < 0) {
location.href += (search ? search + '&' : '?') + '_rwasm=0';
// Return here to avoid calling abort() below. The application
// still has a chance to start successfully do we don't want to
// trigger onAbort or onExit handlers.
return;
}
#if ENVIRONMENT_MAY_BE_NODE || ENVIRONMENT_MAY_BE_SHELL
}
#endif
#endif // WASM == 2
#if ASSERTIONS
// Warn on some common problems.
if (isFileURI(wasmBinaryFile)) {
err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`);
}
#endif
abort(reason);
});
}
function instantiateAsync(binary, binaryFile, imports, callback) {
#if !SINGLE_FILE
if (!binary &&
typeof WebAssembly.instantiateStreaming == 'function' &&
!isDataURI(binaryFile) &&
#if ENVIRONMENT_MAY_BE_WEBVIEW
// Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
!isFileURI(binaryFile) &&
#endif
#if ENVIRONMENT_MAY_BE_NODE
// Avoid instantiateStreaming() on Node.js environment for now, as while
// Node.js v18.1.0 implements it, it does not have a full fetch()
// implementation yet.
//
// Reference:
// https://github.com/emscripten-core/emscripten/pull/16917
!ENVIRONMENT_IS_NODE &&
#endif
typeof fetch == 'function') {
return fetch(binaryFile, {{{ makeModuleReceiveExpr('fetchSettings', "{ credentials: 'same-origin' }") }}}).then((response) => {
// Suppress closure warning here since the upstream definition for
// instantiateStreaming only allows Promise<Repsponse> rather than
// an actual Response.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
/** @suppress {checkTypes} */
var result = WebAssembly.instantiateStreaming(response, imports);
#if USE_OFFSET_CONVERTER
// We need the wasm binary for the offset converter. Clone the response
// in order to get its arrayBuffer (cloning should be more efficient
// than doing another entire request).
// (We must clone the response now in order to use it later, as if we
// try to clone it asynchronously lower down then we will get a
// "response was already consumed" error.)
var clonedResponsePromise = response.clone().arrayBuffer();
#endif
return result.then(
#if !USE_OFFSET_CONVERTER
callback,
#else
function(instantiationResult) {
// When using the offset converter, we must interpose here. First,
// the instantiation result must arrive (if it fails, the error
// handling later down will handle it). Once it arrives, we can
// initialize the offset converter. And only then is it valid to
// call receiveInstantiationResult, as that function will use the
// offset converter (in the case of pthreads, it will create the
// pthreads and send them the offsets along with the wasm instance).
clonedResponsePromise.then((arrayBufferResult) => {
wasmOffsetConverter = new WasmOffsetConverter(new Uint8Array(arrayBufferResult), instantiationResult.module);
callback(instantiationResult);
},
(reason) => err(`failed to initialize offset-converter: ${reason}`)
);
},
#endif
function(reason) {
// We expect the most common failure cause to be a bad MIME type for the binary,
// in which case falling back to ArrayBuffer instantiation should work.
err(`wasm streaming compile failed: ${reason}`);
err('falling back to ArrayBuffer instantiation');
return instantiateArrayBuffer(binaryFile, imports, callback);
});
});
}
#endif
return instantiateArrayBuffer(binaryFile, imports, callback);
}
#endif // WASM_ASYNC_COMPILATION
function getWasmImports() {
#if PTHREADS
assignWasmImports();
#endif
#if ASYNCIFY && (ASSERTIONS || ASYNCIFY == 2)
// instrumenting imports is used in asyncify in two ways: to add assertions
// that check for proper import use, and for ASYNCIFY=2 we use them to set up
// the Promise API on the import side.
#if PTHREADS || ASYNCIFY_LAZY_LOAD_CODE
// In pthreads builds getWasmImports is called more than once but we only
// and the instrument the imports once.
if (!wasmImports.__instrumented) {
wasmImports.__instrumented = true;
Asyncify.instrumentWasmImports(wasmImports);
}
#else
Asyncify.instrumentWasmImports(wasmImports);
#endif
#endif
// prepare imports
return {
#if MINIFY_WASM_IMPORTED_MODULES
'a': wasmImports,
#else // MINIFY_WASM_IMPORTED_MODULES
'env': wasmImports,
'{{{ WASI_MODULE_NAME }}}': wasmImports,
#endif // MINIFY_WASM_IMPORTED_MODULES
#if SPLIT_MODULE
'placeholder': new Proxy({}, splitModuleProxyHandler),
#endif
#if RELOCATABLE
'GOT.mem': new Proxy(wasmImports, GOTHandler),
'GOT.func': new Proxy(wasmImports, GOTHandler),
#endif
}
}
// Create the wasm instance.
// Receives the wasm imports, returns the exports.
function createWasm() {
var info = getWasmImports();
// Load the wasm module and create an instance of using native support in the JS engine.
// handle a generated wasm instance, receiving its exports and
// performing other necessary setup
/** @param {WebAssembly.Module=} module*/
function receiveInstance(instance, module) {
wasmExports = instance.exports;
#if RELOCATABLE
wasmExports = relocateExports(wasmExports, {{{ GLOBAL_BASE }}});
#endif
#if ASYNCIFY
wasmExports = Asyncify.instrumentWasmExports(wasmExports);
#endif
#if ABORT_ON_WASM_EXCEPTIONS
wasmExports = instrumentWasmExportsWithAbort(wasmExports);
#endif
#if MAIN_MODULE
var metadata = getDylinkMetadata(module);
#if AUTOLOAD_DYLIBS
if (metadata.neededDynlibs) {
dynamicLibraries = metadata.neededDynlibs.concat(dynamicLibraries);
}
#endif
mergeLibSymbols(wasmExports, 'main')
#if '$LDSO' in addedLibraryItems
LDSO.init();
#endif
loadDylibs();
#elif RELOCATABLE
reportUndefinedSymbols();
#endif
#if MEMORY64 || CAN_ADDRESS_2GB
wasmExports = applySignatureConversions(wasmExports);
#endif
{{{ receivedSymbol('wasmExports') }}}
#if PTHREADS
#if MAIN_MODULE
registerTLSInit(wasmExports['_emscripten_tls_init'], instance.exports, metadata);
#else
registerTLSInit(wasmExports['_emscripten_tls_init']);
#endif
#endif
#if !IMPORTED_MEMORY
wasmMemory = wasmExports['memory'];
{{{ receivedSymbol('wasmMemory') }}}
#if ASSERTIONS
assert(wasmMemory, 'memory not found in wasm exports');
#endif
updateMemoryViews();
#endif
#if '$wasmTable' in addedLibraryItems && !RELOCATABLE
wasmTable = wasmExports['__indirect_function_table'];
{{{ receivedSymbol('wasmTable') }}}
#if ASSERTIONS && !PURE_WASI
assert(wasmTable, 'table not found in wasm exports');
#endif
#endif
#if hasExportedSymbol('__wasm_call_ctors')
addOnInit(wasmExports['__wasm_call_ctors']);
#endif
#if hasExportedSymbol('__wasm_apply_data_relocs')
__RELOC_FUNCS__.push(wasmExports['__wasm_apply_data_relocs']);
#endif
#if ABORT_ON_WASM_EXCEPTIONS
instrumentWasmTableWithAbort();
#endif
#if !DECLARE_ASM_MODULE_EXPORTS
// If we didn't declare the asm exports as top level enties this function
// is in charge of programmatically exporting them on the global object.
exportWasmSymbols(wasmExports);
#endif
#if PTHREADS || WASM_WORKERS
// We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
wasmModule = module;
#endif
removeRunDependency('wasm-instantiate');
return wasmExports;
}
// wait for the pthread pool (if any)
addRunDependency('wasm-instantiate');
#if LOAD_SOURCE_MAP
{{{ runIfMainThread("addRunDependency('source-map');") }}}
#endif
// Prefer streaming instantiation if available.
#if WASM_ASYNC_COMPILATION
#if ASSERTIONS
// Async compilation can be confusing when an error on the page overwrites Module
// (for example, if the order of elements is wrong, and the one defining Module is
// later), so we save Module and check it later.
var trueModule = Module;
#endif
function receiveInstantiationResult(result) {
// 'result' is a ResultObject object which has both the module and instance.
// receiveInstance() will swap in the exports (to Module.asm) so they can be called
#if ASSERTIONS
assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
trueModule = null;
#endif
#if SHARED_MEMORY || RELOCATABLE
receiveInstance(result['instance'], result['module']);
#else
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
// When the regression is fixed, can restore the above PTHREADS-enabled path.
receiveInstance(result['instance']);
#endif
}
#endif // WASM_ASYNC_COMPILATION
#if expectToReceiveOnModule('instantiateWasm')
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
// to manually instantiate the Wasm module themselves. This allows pages to
// run the instantiation parallel to any other async startup actions they are
// performing.
// Also pthreads and wasm workers initialize the wasm instance through this
// path.
if (Module['instantiateWasm']) {
try {
return Module['instantiateWasm'](info, receiveInstance);
} catch(e) {
err(`Module.instantiateWasm callback failed with error: ${e}`);
#if MODULARIZE
// If instantiation fails, reject the module ready promise.
readyPromiseReject(e);
#else
return false;
#endif
}
}
#endif
if (!wasmBinaryFile) wasmBinaryFile = findWasmBinary();
#if WASM_ASYNC_COMPILATION
#if RUNTIME_DEBUG
dbg('asynchronously preparing wasm');
#endif
#if MODULARIZE
// If instantiation fails, reject the module ready promise.
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
#else
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
#endif
#if LOAD_SOURCE_MAP
getSourceMapPromise().then(receiveSourceMapJSON);
#endif
return {}; // no exports yet; we'll fill them in later
#else
var result = instantiateSync(wasmBinaryFile, info);
#if PTHREADS || MAIN_MODULE
return receiveInstance(result[0], result[1]);
#else
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
// the above line no longer optimizes out down to the following line.
// When the regression is fixed, we can remove this if/else.
return receiveInstance(result[0]);
#endif
#endif
}
#if !WASM_BIGINT
// Globals used by JS i64 conversions (see makeSetValue)
var tempDouble;
var tempI64;
#endif
#include "runtime_debug.js"
#if RETAIN_COMPILER_SETTINGS
var compilerSettings = {{{ JSON.stringify(makeRetainedCompilerSettings()) }}} ;
function getCompilerSetting(name) {
if (!(name in compilerSettings)) return 'invalid compiler setting: ' + name;
return compilerSettings[name];
}
#endif // RETAIN_COMPILER_SETTINGS
#if MAIN_MODULE && ASYNCIFY
// With MAIN_MODULE + ASYNCIFY the normal method of placing stub functions in
// wasmImports for as-yet-undefined symbols doesn't work since ASYNCIFY then
// wraps these stub functions and we can't then replace them directly. Instead
// the stub functions call into `asyncifyStubs` which gets populated by the
// dynamic linker as symbols are loaded.
var asyncifyStubs = {};
#endif
// === Body ===