diff --git a/workloads/sqlite3-wasm/build.log b/workloads/sqlite3-wasm/build.log index c32b2204..085ca3e3 100644 --- a/workloads/sqlite3-wasm/build.log +++ b/workloads/sqlite3-wasm/build.log @@ -1,8 +1,8 @@ -Built on 2025-01-21T15:10:24Z +Built on 2026-10-28T21:51:11Z Toolchain versions -emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.73 (ac676d5e437525d15df5fd46bc2c208ec6d376a3) -wasm-strip 1.0.34 +emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 6.0.13 (e13ee988ce3d87a738dd8f3661d02223308c412a) +wasm-strip 1.0.36 Getting sources from https://sqlite.org/2025/sqlite-src-3480000.zip diff --git a/workloads/sqlite3-wasm/build.sh b/workloads/sqlite3-wasm/build.sh index 27c61423..2cc8acb0 100755 --- a/workloads/sqlite3-wasm/build.sh +++ b/workloads/sqlite3-wasm/build.sh @@ -25,9 +25,15 @@ unzip "$SQLITE_SRC_FILE" # Paths and information in make output could be sensitive, so don't save in log. echo "Building..." | tee -a "$BUILD_LOG" pushd sqlite-src-*/ +# SQLite 3.48.0's JS glue predates Emscripten 4.0's async MODULARIZE factory, +# see the patch description. Drop the patch when updating to SQLite >= 3.49.0. +patch -p1 -i ../emscripten-4-post-load-init.patch ./configure cd ext/wasm -make dist +# Emscripten 6.0.2 removed `wasmBinary` from the default INCOMING_MODULE_JS_API +# list, and setting the list replaces the default, so name every Module property +# that benchmark.js and the speedtest1 glue code pass in. +EMCC_CFLAGS="-sINCOMING_MODULE_JS_API=wasmBinary,print,printErr,preRun,postRun,noInitialRun" make dist popd echo "Copying files from sqlite-src-*/ext/wasm/ into build/" | tee -a "$BUILD_LOG" diff --git a/workloads/sqlite3-wasm/build/jswasm/speedtest1.js b/workloads/sqlite3-wasm/build/jswasm/speedtest1.js index 3d592baf..d505be51 100644 --- a/workloads/sqlite3-wasm/build/jswasm/speedtest1.js +++ b/workloads/sqlite3-wasm/build/jswasm/speedtest1.js @@ -28,19 +28,25 @@ ** ** SQLITE_VERSION "3.48.0" ** SQLITE_VERSION_NUMBER 3048000 -** SQLITE_SOURCE_ID "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010" +** SQLITE_SOURCE_ID "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e8alt1" ** -** Using the Emscripten SDK version 3.1.73. +** Using the Emscripten SDK version 6.0.13. */ +// This code implements the `-sMODULARIZE` settings by taking the generated +// JS program code (INNER_JS_CODE) and wrapping it in a factory function. +// Single threaded MINIMAL_RUNTIME programs do not need access to +// document.currentScript, so a simple export declaration is enough. var sqlite3InitModule = (() => { - var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined; - - return ( -function(moduleArg = {}) { - var moduleRtn; - + // When MODULARIZE this JS may be executed later, + // after document.currentScript is gone, so we save it. + // In EXPORT_ES6 mode we can just use 'import.meta.url'. + var _scriptName = globalThis.document?.currentScript?.src; + return async function(moduleArg = {}) { + var Module = moduleArg; // include: shell.js +// include: minimum_runtime_check.js +// end include: minimum_runtime_check.js // The Module object: Our interface to the outside world. We import // and export values on it. There are various ways Module can be used: // 1. Not defined. We create it here @@ -54,26 +60,18 @@ function(moduleArg = {}) { // after the generated code, you will need to define var Module = {}; // before the code. Then that object will be used in the code, and you // can continue to use Module afterwards as well. -var Module = moduleArg; - -// Set up the promise that indicates the Module is initialized -var readyPromiseResolve, readyPromiseReject; -var readyPromise = new Promise((resolve, reject) => { - readyPromiseResolve = resolve; - readyPromiseReject = reject; -}); // Determine the runtime environment we are in. You can customize this by // setting the ENVIRONMENT setting at compile time (see settings.js). -var ENVIRONMENT_IS_WEB = true; -var ENVIRONMENT_IS_WORKER = false; -var ENVIRONMENT_IS_NODE = false; -var ENVIRONMENT_IS_SHELL = false; +const ENVIRONMENT_IS_WEB = true; +const ENVIRONMENT_IS_WORKER = false; +const ENVIRONMENT_IS_NODE = false; +const ENVIRONMENT_IS_SHELL = false; // --pre-jses are emitted after the Module integration code, so that they can // refer to Module (if they choose; they can also define Module) -// include: /usr/local/google/home/dlehmann/JetStream/sqlite3/sqlite-src-3480000/ext/wasm/bld/pre-js.speedtest1-vanilla.js +// include: ./bld/pre-js.speedtest1-vanilla.js /** BEGIN FILE: api/pre-js.js @@ -132,17 +130,10 @@ Module['locateFile'] = function(path, prefix) { /* END FILE: api/pre-js.js, noting that the build process may add a line after this one to change the above .uri to a build-specific one. */ -// end include: /usr/local/google/home/dlehmann/JetStream/sqlite3/sqlite-src-3480000/ext/wasm/bld/pre-js.speedtest1-vanilla.js +// end include: ./bld/pre-js.speedtest1-vanilla.js -// Sometimes an existing Module object exists with properties -// meant to overwrite the default module functionality. Here -// we collect those properties and reapply _after_ we configure -// the current environment's defaults to avoid having to be so -// defensive during initialization. -var moduleOverrides = Object.assign({}, Module); - -var arguments_ = []; +var programArgs = []; var thisProgram = './this.program'; var quit_ = (status, toThrow) => { throw toThrow; @@ -151,9 +142,6 @@ var quit_ = (status, toThrow) => { // `/` should be present at the end if `scriptDirectory` is not empty var scriptDirectory = ''; function locateFile(path) { - if (Module['locateFile']) { - return Module['locateFile'](path, scriptDirectory); - } return scriptDirectory + path; } @@ -164,38 +152,21 @@ var readAsync, readBinary; // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and // ENVIRONMENT_IS_NODE. if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { - if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled - scriptDirectory = self.location.href; - } else if (typeof document != 'undefined' && document.currentScript) { // web - scriptDirectory = document.currentScript.src; - } - // When MODULARIZE, this JS may be executed later, after document.currentScript - // is gone, so we saved it, and we use it here instead of any other info. - if (_scriptName) { - scriptDirectory = _scriptName; - } - // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. - // otherwise, slice off the final part of the url to find the script directory. - // if scriptDirectory does not contain a slash, lastIndexOf will return -1, - // and scriptDirectory will correctly be replaced with an empty string. - // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), - // they are removed because they could contain a slash. - if (scriptDirectory.startsWith('blob:')) { - scriptDirectory = ''; - } else { - scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1); + try { + scriptDirectory = new URL('.', _scriptName).href; // includes trailing slash + } catch { + // Must be a `blob:` or `data:` URL (e.g. `blob:http://site.com/etc/etc`), we cannot + // infer anything from them. } { // include: web_or_worker_shell_read.js -readAsync = (url) => { - return fetch(url, { credentials: 'same-origin' }) - .then((response) => { - if (response.ok) { - return response.arrayBuffer(); - } - return Promise.reject(new Error(response.status + ' : ' + response.url)); - }) +readAsync = async (url) => { + var response = await fetch(url, { credentials: 'same-origin' }); + if (response.ok) { + return response.arrayBuffer(); + } + throw new Error(response.status + ' : ' + response.url); }; // end include: web_or_worker_shell_read.js } @@ -203,25 +174,9 @@ readAsync = (url) => { { } -var out = Module['print'] || console.log.bind(console); -var err = Module['printErr'] || console.error.bind(console); - -// Merge back in the overrides -Object.assign(Module, moduleOverrides); -// Free the object hierarchy contained in the overrides, this lets the GC -// reclaim data used. -moduleOverrides = null; - -// Emit code to handle expected values on the Module object. This applies Module.x -// to the proper local x. This has two benefits: first, we only emit it if it is -// expected to arrive, and second, by using a local everywhere else that can be -// minified. +var out = console.log.bind(console); +var err = console.error.bind(console); -if (Module['arguments']) arguments_ = Module['arguments']; - -if (Module['thisProgram']) thisProgram = Module['thisProgram']; - -// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message // end include: shell.js // include: preamble.js @@ -235,12 +190,10 @@ if (Module['thisProgram']) thisProgram = Module['thisProgram']; // 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 -var wasmBinary = Module['wasmBinary']; +var wasmBinary; // Wasm globals -var wasmMemory; - //======================================== // Runtime essentials //======================================== @@ -250,7 +203,7 @@ var wasmMemory; 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 +// NOTE: This is also used as the process return code in shell environments // but only when noExitRuntime is false. var EXITSTATUS; @@ -268,161 +221,100 @@ function assert(condition, text) { } } -// 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, -/* 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, -/** @type {!Float64Array} */ - HEAPF64; - -// include: runtime_shared.js -function updateMemoryViews() { - var b = wasmMemory.buffer; - Module['HEAP8'] = HEAP8 = new Int8Array(b); - Module['HEAP16'] = HEAP16 = new Int16Array(b); - Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); - Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); - Module['HEAP32'] = HEAP32 = new Int32Array(b); - Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); - Module['HEAPF32'] = HEAPF32 = new Float32Array(b); - Module['HEAPF64'] = HEAPF64 = new Float64Array(b); - Module['HEAP64'] = HEAP64 = new BigInt64Array(b); - Module['HEAPU64'] = HEAPU64 = new BigUint64Array(b); -} - -// end include: runtime_shared.js -// include: runtime_stack_check.js -// end include: runtime_stack_check.js -var __ATPRERUN__ = []; // functions called before the runtime is initialized -var __ATINIT__ = []; // functions called during startup -var __ATEXIT__ = []; // functions called during shutdown -var __ATPOSTRUN__ = []; // functions called after the main() is called - -var runtimeInitialized = 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 initRuntime() { - runtimeInitialized = true; +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); - -if (!Module['noFSInit'] && !FS.initialized) - FS.init(); -FS.ignorePermissions = false; +// include: runtime_common.js +// include: runtime_exceptions.js +// Base Emscripten EH error class +class EmscriptenEH {} -TTY.init(); - callRuntimeCallbacks(__ATINIT__); -} +class EmscriptenSjLj extends EmscriptenEH {} -function postRun() { +// end include: runtime_exceptions.js +// include: runtime_debug.js +// end include: runtime_debug.js +// Memory management - if (Module['postRun']) { - if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; - while (Module['postRun'].length) { - addOnPostRun(Module['postRun'].shift()); - } - } +var runtimeInitialized = false; - callRuntimeCallbacks(__ATPOSTRUN__); -} -function addOnPreRun(cb) { - __ATPRERUN__.unshift(cb); -} -function addOnInit(cb) { - __ATINIT__.unshift(cb); +// When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm +// memory to ArrayBuffer requires some additional logic. +function getMemoryBuffer() { + return wasmMemory.buffer; } -function addOnExit(cb) { +function updateMemoryViews() { + // If we already have a heap that is resizeable/growable buffer we don't + // need to do anything in updateMemoryViews. + if (HEAP8?.buffer?.resizable) return; + var b = getMemoryBuffer(); + HEAP8 = new Int8Array(b); + HEAP16 = new Int16Array(b); + HEAPU8 = new Uint8Array(b); + + HEAP32 = new Int32Array(b); + HEAPU32 = new Uint32Array(b); + HEAPF32 = new Float32Array(b); + HEAPF64 = new Float64Array(b); + HEAP64 = new BigInt64Array(b); + HEAPU64 = new BigUint64Array(b); } -function addOnPostRun(cb) { - __ATPOSTRUN__.unshift(cb); +// include: memoryprofiler.js +// end include: memoryprofiler.js +// end include: runtime_common.js +function preRun() { + var preRun = Module['preRun']; + if (preRun) { + if (typeof preRun === 'function') preRun = [preRun]; + onPreRuns.push(...preRun); + } + // Begin ATPRERUNS hooks + callRuntimeCallbacks(onPreRuns); + // End ATPRERUNS hooks } -// include: runtime_math.js -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc - -// end 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 +function initRuntime() { + runtimeInitialized = true; -function getUniqueRunDependency(id) { - return id; -} + // Begin ATINITS hooks + if (!Module['noFSInit'] && !FS.initialized) FS.init(); +TTY.init(); + // End ATINITS hooks -function addRunDependency(id) { - runDependencies++; + wasmExports['__wasm_call_ctors'](); - Module['monitorRunDependencies']?.(runDependencies); + // Begin ATPOSTCTORS hooks + FS.ignorePermissions = false; + // End ATPOSTCTORS hooks } -function removeRunDependency(id) { - runDependencies--; - - Module['monitorRunDependencies']?.(runDependencies); +function postRun() { - if (runDependencies == 0) { - if (runDependencyWatcher !== null) { - clearInterval(runDependencyWatcher); - runDependencyWatcher = null; - } - if (dependenciesFulfilled) { - var callback = dependenciesFulfilled; - dependenciesFulfilled = null; - callback(); // can add another dependenciesFulfilled - } + var postRun = Module['postRun']; + if (postRun) { + if (typeof postRun === 'function') postRun = [postRun]; + onPostRuns.push(...postRun); } + + // Begin ATPOSTRUNS hooks + callRuntimeCallbacks(onPostRuns); + // End ATPOSTRUNS hooks } -/** @param {string|number=} what */ +/** + * @param {string|number=} what + */ function abort(what) { - Module['onAbort']?.(what); - what = 'Aborted(' + what + ')'; + what = `Aborted(${what})`; // TODO(sbc): Should we remove printing and leave it up to whoever // catches the exception? err(what); @@ -439,51 +331,15 @@ function abort(what) { // 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. - /** @suppress {checkTypes} */ - var e = new WebAssembly.RuntimeError(what); - - readyPromiseReject(e); - // 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; + throw new WebAssembly.RuntimeError(what); } -// include: memoryprofiler.js -// end include: memoryprofiler.js -// include: URIUtils.js -// Prefix of data URIs emitted by SINGLE_FILE and related options. -var dataURIPrefix = 'data:application/octet-stream;base64,'; - -/** - * Indicates whether filename is a base64 data URI. - * @noinline - */ -var isDataURI = (filename) => filename.startsWith(dataURIPrefix); +var wasmBinaryFile; -/** - * Indicates whether filename is delivered via file protocol (as opposed to http/https) - * @noinline - */ -var isFileURI = (filename) => filename.startsWith('file://'); -// end include: URIUtils.js -// include: runtime_exceptions.js -// end include: runtime_exceptions.js function findWasmBinary() { - var f = 'speedtest1.wasm'; - if (!isDataURI(f)) { - return locateFile(f); - } - return f; + return locateFile('speedtest1.wasm'); } -var wasmBinaryFile; - function getBinarySync(file) { if (file == wasmBinaryFile && wasmBinary) { return new Uint8Array(wasmBinary); @@ -491,93 +347,81 @@ function getBinarySync(file) { if (readBinary) { return readBinary(file); } + // Throwing a plain string here, even though it not normally advisable since + // this gets turning into an `abort` in instantiateArrayBuffer. throw 'both async and sync fetching of the wasm failed'; } -function getBinaryPromise(binaryFile) { +async function getWasmBinary(binaryFile) { // If we don't have the binary yet, load it asynchronously using readAsync. - if (!wasmBinary - ) { + if (!wasmBinary) { // Fetch the binary using readAsync - return readAsync(binaryFile).then( - (response) => new Uint8Array(/** @type{!ArrayBuffer} */(response)), - // Fall back to getBinarySync if readAsync fails - () => getBinarySync(binaryFile) - ); + try { + var response = await readAsync(binaryFile); + return new Uint8Array(response); + } catch { + // Fall back to getBinarySync below; + } } // Otherwise, getBinarySync should be able to get it synchronously - return Promise.resolve().then(() => getBinarySync(binaryFile)); + return getBinarySync(binaryFile); } -function instantiateArrayBuffer(binaryFile, imports, receiver) { - return getBinaryPromise(binaryFile).then((binary) => { - return WebAssembly.instantiate(binary, imports); - }).then(receiver, (reason) => { +async function instantiateArrayBuffer(binaryFile, imports) { + try { + var binary = await getWasmBinary(binaryFile); + var instance = await WebAssembly.instantiate(binary, imports); + return instance; + } catch (reason) { err(`failed to asynchronously prepare wasm: ${reason}`); abort(reason); - }); + } } -function instantiateAsync(binary, binaryFile, imports, callback) { - if (!binary && - typeof WebAssembly.instantiateStreaming == 'function' && - !isDataURI(binaryFile) && - typeof fetch == 'function') { - return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { - // Suppress closure warning here since the upstream definition for - // instantiateStreaming only allows Promise 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); - - return result.then( - callback, - 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); - }); - }); +async function instantiateAsync(binary, binaryFile, imports) { + if (!binary + ) { + try { + var response = fetch(binaryFile, { credentials: 'same-origin' }); + var instantiationResult = await WebAssembly.instantiateStreaming(response, imports); + return instantiationResult; + } catch (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'); + // fall back of instantiateArrayBuffer below + }; } - return instantiateArrayBuffer(binaryFile, imports, callback); + return instantiateArrayBuffer(binaryFile, imports); } function getWasmImports() { // prepare imports - return { + var imports = { 'env': wasmImports, 'wasi_snapshot_preview1': wasmImports, - } + }; + return imports; } // Create the wasm instance. // Receives the wasm imports, returns the exports. -function createWasm() { +async function createWasm() { // 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) { + function receiveInstance(instance) { wasmExports = instance.exports; - + assignWasmExports(wasmExports); - wasmMemory = wasmExports['memory']; - Module['wasmMemory'] = wasmMemory; updateMemoryViews(); - addOnInit(wasmExports['__wasm_call_ctors']); - - removeRunDependency('wasm-instantiate'); return wasmExports; } - // wait for the pthread pool (if any) - addRunDependency('wasm-instantiate'); // Prefer streaming instantiation if available. function receiveInstantiationResult(result) { @@ -585,39 +429,21 @@ function createWasm() { // receiveInstance() will swap in the exports (to Module.asm) so they can be called // 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']); + return receiveInstance(result['instance']); } var info = getWasmImports(); - // 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 instantiation fails, reject the module ready promise. - readyPromiseReject(e); - } - } - wasmBinaryFile ??= findWasmBinary(); - - // If instantiation fails, reject the module ready promise. - instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject); - return {}; // no exports yet; we'll fill them in later + var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info); + var exports = receiveInstantiationResult(result); + return exports; } -// include: runtime_debug.js -// end include: runtime_debug.js -// === Body === // end include: preamble.js +// Begin JS library code + class ExitStatus { name = 'ExitStatus'; @@ -627,130 +453,69 @@ function createWasm() { } } + /** @type {!Int8Array} */ + var HEAP8; + var callRuntimeCallbacks = (callbacks) => { while (callbacks.length > 0) { // Pass the module as the first argument. callbacks.shift()(Module); } }; + var onPostRuns = []; + var addOnPostRun = (cb) => onPostRuns.push(cb); - - /** - * @param {number} ptr - * @param {string} type - */ - function getValue(ptr, type = 'i8') { - if (type.endsWith('*')) type = '*'; - switch (type) { - case 'i1': return HEAP8[ptr]; - case 'i8': return HEAP8[ptr]; - case 'i16': return HEAP16[((ptr)>>1)]; - case 'i32': return HEAP32[((ptr)>>2)]; - case 'i64': return HEAP64[((ptr)>>3)]; - case 'float': return HEAPF32[((ptr)>>2)]; - case 'double': return HEAPF64[((ptr)>>3)]; - case '*': return HEAPU32[((ptr)>>2)]; - default: abort(`invalid type for getValue: ${type}`); - } - } - - var noExitRuntime = Module['noExitRuntime'] || true; + var onPreRuns = []; + var addOnPreRun = (cb) => onPreRuns.push(cb); - - /** - * @param {number} ptr - * @param {number} value - * @param {string} type - */ - function setValue(ptr, value, type = 'i8') { - if (type.endsWith('*')) type = '*'; - switch (type) { - case 'i1': HEAP8[ptr] = value; break; - case 'i8': HEAP8[ptr] = value; break; - case 'i16': HEAP16[((ptr)>>1)] = value; break; - case 'i32': HEAP32[((ptr)>>2)] = value; break; - case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break; - case 'float': HEAPF32[((ptr)>>2)] = value; break; - case 'double': HEAPF64[((ptr)>>3)] = value; break; - case '*': HEAPU32[((ptr)>>2)] = value; break; - default: abort(`invalid type for setValue: ${type}`); - } - } var stackRestore = (val) => __emscripten_stack_restore(val); var stackSave = () => _emscripten_stack_get_current(); - var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder() : undefined; + + + var UTF8Decoder = new TextDecoder(); + /** - * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given - * array that contains uint8 values, returns a copy of that string as a - * Javascript String object. - * heapOrArray is either a regular array, or a JavaScript typed array view. - * @param {number=} idx - * @param {number=} maxBytesToRead - * @return {string} - */ - var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead = NaN) => { - var endIdx = idx + maxBytesToRead; - var endPtr = idx; + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @param {boolean=} ignoreNul + * @return {number} + */ + var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { + var maxIdx = idx + maxBytesToRead; + if (ignoreNul) return maxIdx; // TextDecoder needs to know the byte length in advance, it doesn't stop on - // null terminator by itself. Also, use the length info to avoid running tiny - // strings through TextDecoder, since .subarray() allocates garbage. - // (As a tiny code save trick, compare endPtr against endIdx using a negation, - // so that undefined/NaN means Infinity) - while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; - - if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { - return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); - } - var str = ''; - // If building with TextDecoder, we have already computed the string length - // above, so test loop end condition against that - while (idx < endPtr) { - // For UTF8 byte structure, see: - // http://en.wikipedia.org/wiki/UTF-8#Description - // https://www.ietf.org/rfc/rfc2279.txt - // https://tools.ietf.org/html/rfc3629 - var u0 = heapOrArray[idx++]; - if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } - var u1 = heapOrArray[idx++] & 63; - if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } - var u2 = heapOrArray[idx++] & 63; - if ((u0 & 0xF0) == 0xE0) { - u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; - } else { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); - } - - if (u0 < 0x10000) { - str += String.fromCharCode(u0); - } else { - var ch = u0 - 0x10000; - str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); - } - } - return str; + // null terminator by itself. + // As a tiny code save trick, compare idx against maxIdx using a negation, + // so that maxBytesToRead=undefined/NaN means Infinity. + while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx; + return idx; }; + /** @type {!Uint8Array} */ + var HEAPU8; + /** - * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the - * emscripten HEAP, returns a copy of that string as a Javascript String object. - * - * @param {number} ptr - * @param {number=} maxBytesToRead - An optional length that specifies the - * maximum number of bytes to read. You can omit this parameter to scan the - * string until the first 0 byte. If maxBytesToRead is passed, and the string - * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the - * string will cut short at that byte index (i.e. maxBytesToRead will not - * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing - * frequent uses of UTF8ToString() with and without maxBytesToRead may throw - * JS JIT optimizations off, so it is worth to consider consistently using one - * @return {string} - */ - var UTF8ToString = (ptr, maxBytesToRead) => { - return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index. + * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character. + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => { + if (!ptr) return ''; + var end = findStringEnd(HEAPU8, ptr, maxBytesToRead, ignoreNul); + return UTF8Decoder.decode(HEAPU8.subarray(ptr, end)); }; var ___assert_fail = (condition, filename, line, func) => abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); @@ -786,7 +551,7 @@ function createWasm() { }, normalize:(path) => { var isAbsolute = PATH.isAbs(path), - trailingSlash = path.substr(-1) === '/'; + trailingSlash = path.slice(-1) === '/'; // Normalize the path path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/'); if (!path && !isAbsolute) { @@ -807,93 +572,96 @@ function createWasm() { } if (dir) { // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); + dir = dir.slice(0, -1); } return root + dir; }, - basename:(path) => { - // EMSCRIPTEN return '/'' for '/', not an empty string - if (path === '/') return '/'; - path = PATH.normalize(path); - path = path.replace(/\/$/, ""); - var lastSlash = path.lastIndexOf('/'); - if (lastSlash === -1) return path; - return path.substr(lastSlash+1); - }, - join:(...paths) => PATH.normalize(paths.join('/')), - join2:(l, r) => PATH.normalize(l + '/' + r), + basename:(path) => path && path.match(/([^\/]+|\/)\/*$/)[1], +join:(...paths) => PATH.normalize(paths.join('/')), +join2:(l, r) => PATH.normalize(l + '/' + r), +}; + +var initRandomFill = () => { + + return (view) => (crypto.getRandomValues(view), 0); }; - - var initRandomFill = () => { - if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') { - // for modern web browsers - return (view) => crypto.getRandomValues(view); - } else - // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096 - abort('initRandomDevice'); - }; - var randomFill = (view) => { - // Lazily init on the first invocation. - return (randomFill = initRandomFill())(view); - }; - - - - var PATH_FS = { - resolve:(...args) => { - var resolvedPath = '', - resolvedAbsolute = false; - for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? args[i] : FS.cwd(); - // Skip empty and invalid entries - if (typeof path != 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - return ''; // an invalid portion invalidates the whole thing - } - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = PATH.isAbs(path); - } - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - }, - relative:(from, to) => { - from = PATH_FS.resolve(from).substr(1); - to = PATH_FS.resolve(to).substr(1); - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } +var randomFill = (view) => (randomFill = initRandomFill())(view); + + + +var PATH_FS = { +resolve:(...args) => { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? args[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; // an invalid portion invalidates the whole thing } - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, +relative:(from, to) => { + from = PATH_FS.resolve(from).slice(1); + to = PATH_FS.resolve(to).slice(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; } - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - return outputParts.join('/'); - }, - }; + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }, +}; + + + + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number=} idx + * @param {number=} maxBytesToRead + * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character. + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => { + var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul); + return UTF8Decoder.decode(heapOrArray.buffer ? heapOrArray.subarray(idx, endPtr) : new Uint8Array(heapOrArray.slice(idx, endPtr))); + }; var FS_stdin_getChar_buffer = []; @@ -927,18 +695,10 @@ function createWasm() { var startIdx = outIdx; var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. for (var i = 0; i < str.length; ++i) { - // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code - // unit, not a Unicode code point of the character! So decode - // UTF16->UTF32->UTF8. - // See http://unicode.org/faq/utf_bom.html#utf16-3 // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description // and https://www.ietf.org/rfc/rfc2279.txt // and https://tools.ietf.org/html/rfc3629 - var u = str.charCodeAt(i); // possibly a lead surrogate - if (u >= 0xD800 && u <= 0xDFFF) { - var u1 = str.charCodeAt(++i); - u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); - } + var u = str.codePointAt(i); if (u <= 0x7F) { if (outIdx >= endIdx) break; heap[outIdx++] = u; @@ -957,6 +717,9 @@ function createWasm() { heap[outIdx++] = 0x80 | ((u >> 12) & 63); heap[outIdx++] = 0x80 | ((u >> 6) & 63); heap[outIdx++] = 0x80 | (u & 63); + // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. + // We need to manually skip over the second code unit for correct iteration. + i++; } } // Null-terminate the pointer to the buffer. @@ -964,18 +727,17 @@ function createWasm() { return outIdx - startIdx; }; /** @type {function(string, boolean=, number=)} */ - 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; - } + var 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; + }; var FS_stdin_getChar = () => { if (!FS_stdin_getChar_buffer.length) { var result = null; - if (typeof window != 'undefined' && - typeof window.prompt == 'function') { + if (globalThis.window?.prompt) { // Browser. result = window.prompt('Input: '); // returns null on cancel if (result !== null) { @@ -1045,15 +807,18 @@ function createWasm() { } catch (e) { throw new FS.ErrnoError(29); } - if (result === undefined && bytesRead === 0) { + if (result === undefined && !bytesRead) { throw new FS.ErrnoError(6); } if (result === null || result === undefined) break; bytesRead++; buffer[offset+i] = result; + // We currently only support canonical mode (ICANON), where + // read(2) returns as soon as a line delimiter is read. + if (result === 10) break; } if (bytesRead) { - stream.node.timestamp = Date.now(); + stream.node.atime = Date.now(); } return bytesRead; }, @@ -1069,7 +834,7 @@ function createWasm() { throw new FS.ErrnoError(29); } if (length) { - stream.node.timestamp = Date.now(); + stream.node.mtime = stream.node.ctime = Date.now(); } return i; }, @@ -1087,7 +852,7 @@ function createWasm() { } }, fsync(tty) { - if (tty.output && tty.output.length > 0) { + if (tty.output?.length > 0) { out(UTF8ArrayToString(tty.output)); tty.output = []; } @@ -1124,7 +889,7 @@ function createWasm() { } }, fsync(tty) { - if (tty.output && tty.output.length > 0) { + if (tty.output?.length > 0) { err(UTF8ArrayToString(tty.output)); tty.output = []; } @@ -1133,9 +898,7 @@ function createWasm() { }; - var zeroMemory = (address, size) => { - HEAPU8.fill(0, address, address + size); - }; + var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size); var alignMemory = (size, alignment) => { return Math.ceil(size / alignment) * alignment; @@ -1146,14 +909,15 @@ function createWasm() { if (ptr) zeroMemory(ptr, size); return ptr; }; + var MEMFS = { ops_table:null, mount(mount) { return MEMFS.createNode(null, '/', 16895, 0); }, - createNode(parent, name, mode, dev) { + createNode(parent, name, mode, dev = undefined) { if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { - // no supported + // not supported throw new FS.ErrnoError(63); } MEMFS.ops_table ||= { @@ -1182,7 +946,6 @@ function createWasm() { llseek: MEMFS.stream_ops.llseek, read: MEMFS.stream_ops.read, write: MEMFS.stream_ops.write, - allocate: MEMFS.stream_ops.allocate, mmap: MEMFS.stream_ops.mmap, msync: MEMFS.stream_ops.msync } @@ -1211,11 +974,14 @@ function createWasm() { } else if (FS.isFile(node.mode)) { node.node_ops = MEMFS.ops_table.file.node; node.stream_ops = MEMFS.ops_table.file.stream; - node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. - // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred - // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size - // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. - node.contents = null; + // The actual number of bytes used in the typed array, as opposed to + // contents.length which gives the whole capacity. + node.usedBytes = 0; + // The byte data of the file is stored in a typed array. + // Note: typed arrays are not resizable like normal JS arrays are, so + // there is a small penalty involved for appending file writes that + // continuously grow a file similar to std::vector capacity vs used. + node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0); } else if (FS.isLink(node.mode)) { node.node_ops = MEMFS.ops_table.link.node; node.stream_ops = MEMFS.ops_table.link.stream; @@ -1223,45 +989,38 @@ function createWasm() { node.node_ops = MEMFS.ops_table.chrdev.node; node.stream_ops = MEMFS.ops_table.chrdev.stream; } - node.timestamp = Date.now(); + node.atime = node.mtime = node.ctime = Date.now(); // add the new node to the parent if (parent) { parent.contents[name] = node; - parent.timestamp = node.timestamp; + parent.atime = parent.mtime = parent.ctime = node.atime; } return node; }, getFileDataAsTypedArray(node) { - if (!node.contents) return new Uint8Array(0); - if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. - return new Uint8Array(node.contents); + return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. }, expandFileStorage(node, newCapacity) { - var prevCapacity = node.contents ? node.contents.length : 0; + var prevCapacity = node.contents.length; if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. - // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. - // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to - // avoid overshooting the allocation cap by a very large margin. - var CAPACITY_DOUBLING_MAX = 1024 * 1024; + // Don't expand strictly to the given requested limit if it's only a very + // small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for + // large sizes, do a much more conservative size*1.125 increase to avoid + // overshooting the allocation cap by a very large margin. + const CAPACITY_DOUBLING_MAX = 1024 * 1024; newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); - if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. - var oldContents = node.contents; + if (prevCapacity) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = MEMFS.getFileDataAsTypedArray(node); node.contents = new Uint8Array(newCapacity); // Allocate new storage. - if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + node.contents.set(oldContents); }, resizeFileStorage(node, newSize) { if (node.usedBytes == newSize) return; - if (newSize == 0) { - node.contents = null; // Fully decommit when requesting a resize to zero. - node.usedBytes = 0; - } else { - var oldContents = node.contents; - node.contents = new Uint8Array(newSize); // Allocate new storage. - if (oldContents) { - node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. - } - node.usedBytes = newSize; - } + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); // Allocate new storage. + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + node.usedBytes = newSize; }, node_ops:{ getattr(node) { @@ -1283,9 +1042,9 @@ function createWasm() { } else { attr.size = 0; } - attr.atime = new Date(node.timestamp); - attr.mtime = new Date(node.timestamp); - attr.ctime = new Date(node.timestamp); + attr.atime = new Date(node.atime); + attr.mtime = new Date(node.mtime); + attr.ctime = new Date(node.ctime); // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), // but this is not required by the standard. attr.blksize = 4096; @@ -1293,46 +1052,48 @@ function createWasm() { return attr; }, setattr(node, attr) { - if (attr.mode !== undefined) { - node.mode = attr.mode; - } - if (attr.timestamp !== undefined) { - node.timestamp = attr.timestamp; + for (const key of ['mode', 'atime', 'mtime', 'ctime']) { + if (attr[key] != null) { + node[key] = attr[key]; + } } if (attr.size !== undefined) { MEMFS.resizeFileStorage(node, attr.size); } }, lookup(parent, name) { + // This error may happen quite a bit. To avoid overhead we reuse it (and + // suffer a lack of stack info). + if (!MEMFS.doesNotExistError) { + MEMFS.doesNotExistError = new FS.ErrnoError(44); + /** @suppress {checkTypes} */ + MEMFS.doesNotExistError.stack = ''; + } throw MEMFS.doesNotExistError; }, - mknod(parent, name, mode, dev) { + mknod(parent, name, mode, dev = undefined) { return MEMFS.createNode(parent, name, mode, dev); }, rename(old_node, new_dir, new_name) { - // if we're overwriting a directory at new_name, make sure it's empty. - if (FS.isDir(old_node.mode)) { - var new_node; - try { - new_node = FS.lookupNode(new_dir, new_name); - } catch (e) { - } - if (new_node) { - for (var i in new_node.contents) { - throw new FS.ErrnoError(55); - } + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) {} + if (new_node && FS.isDir(old_node.mode)) { + // if we're overwriting a directory at new_name, make sure it's empty. + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); } } // do the internal rewiring delete old_node.parent.contents[old_node.name]; - old_node.parent.timestamp = Date.now() - old_node.name = new_name; new_dir.contents[new_name] = old_node; - new_dir.timestamp = old_node.parent.timestamp; + old_node.name = new_name; + new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now(); }, unlink(parent, name) { delete parent.contents[name]; - parent.timestamp = Date.now(); + parent.ctime = parent.mtime = Date.now(); }, rmdir(parent, name) { var node = FS.lookupNode(parent, name); @@ -1340,14 +1101,10 @@ function createWasm() { throw new FS.ErrnoError(55); } delete parent.contents[name]; - parent.timestamp = Date.now(); + parent.ctime = parent.mtime = Date.now(); }, readdir(node) { - var entries = ['.', '..']; - for (var key of Object.keys(node.contents)) { - entries.push(key); - } - return entries; + return ['.', '..', ...Object.keys(node.contents)]; }, symlink(parent, newname, oldpath) { var node = MEMFS.createNode(parent, newname, 0o777 | 40960, 0); @@ -1366,52 +1123,34 @@ function createWasm() { var contents = stream.node.contents; if (position >= stream.node.usedBytes) return 0; var size = Math.min(stream.node.usedBytes - position, length); - if (size > 8 && contents.subarray) { // non-trivial, and typed array - buffer.set(contents.subarray(position, position + size), offset); - } else { - for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; - } + buffer.set(contents.subarray(position, position + size), offset); return size; }, write(stream, buffer, offset, length, position, canOwn) { // If the buffer is located in main memory (HEAP), and if // memory can grow, we can't hold on to references of the // memory buffer, as they may get invalidated. That means we - // need to do copy its contents. + // need to copy its contents. if (buffer.buffer === HEAP8.buffer) { canOwn = false; } if (!length) return 0; var node = stream.node; - node.timestamp = Date.now(); - - if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? - if (canOwn) { - node.contents = buffer.subarray(offset, offset + length); - node.usedBytes = length; - return length; - } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. - node.contents = buffer.slice(offset, offset + length); - node.usedBytes = length; - return length; - } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? - node.contents.set(buffer.subarray(offset, offset + length), position); - return length; - } - } + node.mtime = node.ctime = Date.now(); - // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. - MEMFS.expandFileStorage(node, position+length); - if (node.contents.subarray && buffer.subarray) { + if (canOwn) { + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + } else if (!node.usedBytes && !position) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + } else { + MEMFS.expandFileStorage(node, position+length); // Use typed array write which is available. node.contents.set(buffer.subarray(offset, offset + length), position); - } else { - for (var i = 0; i < length; i++) { - node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. - } + node.usedBytes = Math.max(node.usedBytes, position + length); } - node.usedBytes = Math.max(node.usedBytes, position + length); return length; }, llseek(stream, offset, whence) { @@ -1428,10 +1167,6 @@ function createWasm() { } return position; }, - allocate(stream, offset, length) { - MEMFS.expandFileStorage(stream.node, offset + length); - stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); - }, mmap(stream, length, position, prot, flags) { if (!FS.isFile(stream.node.mode)) { throw new FS.ErrnoError(43); @@ -1440,7 +1175,7 @@ function createWasm() { var allocated; var contents = stream.node.contents; // Only make a new copy when MAP_PRIVATE is specified. - if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) { + if (!(flags & 2) && contents.buffer === HEAP8.buffer) { // We can't emulate MAP_SHARED when the file is not backed by the // buffer we're mapping to (e.g. the HEAP buffer). allocated = false; @@ -1473,76 +1208,8 @@ function createWasm() { }, }; - /** @param {boolean=} noRunDep */ - var asyncLoad = (url, onload, onerror, noRunDep) => { - var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ''; - readAsync(url).then( - (arrayBuffer) => { - onload(new Uint8Array(arrayBuffer)); - if (dep) removeRunDependency(dep); - }, - (err) => { - if (onerror) { - onerror(); - } else { - throw `Loading data file "${url}" failed.`; - } - } - ); - if (dep) addRunDependency(dep); - }; - - - var FS_createDataFile = (parent, name, fileData, canRead, canWrite, canOwn) => { - FS.createDataFile(parent, name, fileData, canRead, canWrite, canOwn); - }; - - var preloadPlugins = Module['preloadPlugins'] || []; - var FS_handledByPreloadPlugin = (byteArray, fullname, finish, onerror) => { - // Ensure plugins are ready. - if (typeof Browser != 'undefined') Browser.init(); - - var handled = false; - preloadPlugins.forEach((plugin) => { - if (handled) return; - if (plugin['canHandle'](fullname)) { - plugin['handle'](byteArray, fullname, finish, onerror); - handled = true; - } - }); - return handled; - }; - var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { - // TODO we should allow people to just pass in a complete filename instead - // of parent and name being that we just join them anyways - var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; - var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname - function processData(byteArray) { - function finish(byteArray) { - preFinish?.(); - if (!dontCreateFile) { - FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); - } - onload?.(); - removeRunDependency(dep); - } - if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => { - onerror?.(); - removeRunDependency(dep); - })) { - return; - } - finish(byteArray); - } - addRunDependency(dep); - if (typeof url == 'string') { - asyncLoad(url, processData, onerror); - } else { - processData(url); - } - }; - var FS_modeStringToFlags = (str) => { + if (typeof str !== 'string') return str; var flagModes = { 'r': 0, 'r+': 2, @@ -1552,12 +1219,22 @@ function createWasm() { 'a+': 1024 | 64 | 2, }; var flags = flagModes[str]; - if (typeof flags == 'undefined') { + if (typeof flags === 'undefined') { throw new Error(`Unknown file open mode: ${str}`); } return flags; }; + var FS_fileDataToTypedArray = (data) => { + if (typeof data === 'string') { + data = intArrayFromString(data, true); + } + if (!data.subarray) { + data = new Uint8Array(data); + } + return data; + }; + var FS_getMode = (canRead, canWrite) => { var mode = 0; if (canRead) mode |= 292 | 73; @@ -1566,6 +1243,81 @@ function createWasm() { }; + var asyncLoad = async (url) => { + var arrayBuffer = await readAsync(url); + return new Uint8Array(arrayBuffer); + }; + + + var FS_createDataFile = (...args) => FS.createDataFile(...args); + + var getUniqueRunDependency = (id) => { + return id; + }; + + var dependenciesPromise = null; + var resolveRunDependencies = async () => dependenciesPromise; + var runDependencies = 0; + + + var dependenciesPromiseResolve = null; + var removeRunDependency = (id) => { + runDependencies--; + + if (!runDependencies) { + dependenciesPromiseResolve(); + } + }; + + + var addRunDependency = (id) => { + if (!runDependencies) { + dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve); + } + runDependencies++; + + }; + + + var preloadPlugins = []; + var FS_handledByPreloadPlugin = async (byteArray, fullname) => { + // Ensure plugins are ready. + if (typeof Browser !== 'undefined') Browser.init(); + + for (var plugin of preloadPlugins) { + if (plugin['canHandle'](fullname)) { + return plugin['handle'](byteArray, fullname); + } + } + // If no plugin handled this file then return the original/unmodified + // byteArray. + return byteArray; + }; + var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => { + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname + addRunDependency(dep); + + try { + var byteArray = url; + if (typeof url === 'string') { + byteArray = await asyncLoad(url); + } + + byteArray = await FS_handledByPreloadPlugin(byteArray, fullname); + preFinish?.(); + if (!dontCreateFile) { + FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + } finally { + removeRunDependency(dep); + } + }; + var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { + FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror); + }; var FS = { root:null, @@ -1574,10 +1326,11 @@ function createWasm() { }, streams:[], nextInode:1, - nameTable:null, + nameTable:[], currentPath:"/", initialized:false, ignorePermissions:true, + syncFSRequests:0, ErrnoError:class { name = 'ErrnoError'; // We set the `name` property to be able to identify `FS.ErrnoError` @@ -1590,10 +1343,6 @@ function createWasm() { this.errno = errno; } }, - filesystems:null, - syncFSRequests:0, - readFiles:{ - }, FSStream:class { shared = {}; get object() { @@ -1640,6 +1389,7 @@ function createWasm() { this.name = name; this.mode = mode; this.rdev = rdev; + this.atime = this.mtime = this.ctime = Date.now(); } get read() { return (this.mode & this.readMode) === this.readMode; @@ -1659,65 +1409,128 @@ function createWasm() { get isDevice() { return FS.isChrdev(this.mode); } + // The per-inode readiness wait-queue. The node carries a Set of listener + // entries {cb}; producers (SOCKFS, PIPEFS) call notifyListeners on a + // readiness transition, and poll()/epoll consume it. It lives on the node + // (not the fd) so dup'd fds share one queue. Only nodes that derive real + // readiness (sockets, pipes, and an epoll's own node) ever use this - + // always-ready types (regular files, ttys) never register or notify. + addListener(cb, exclusive = false) { + var entry = {cb, exclusive}; + var listeners = (this.listeners ??= new Set()); + listeners.add(entry); + return {listeners, entry}; + } + notifyListeners(flags) { + // Iterates the set without copying, which is safe ONLY under a + // load-bearing contract that every internal listener must honour: + // 1. A listener must not run user code synchronously (a poll waiter only + // resolves a Promise; an epoll registration only re-lists + + // re-notifies; the epoll callback only schedules a tick). User code + // runs on a later tick, never inside this loop. + // 2. A listener may delete entries only from ITS OWN waiter, never from + // a sibling node's set that may be mid-iteration. (Deleting an entry + // of the set being iterated here is fine - a Set tolerates removal of + // a not-yet-visited entry mid-iteration; mutating a *different* node's + // set is fine because that set is not being iterated.) + // Violating either gives silently skipped wakeups that are near-impossible + // to reproduce. Any new producer/listener must preserve it. + if (!this.listeners) return; + // Fire every non-exclusive listener. Among EPOLLEXCLUSIVE registrations + // (one fd watched by several epolls) wake only one, rotating round-robin + // per node, to avoid a thundering herd. (Only epoll registrations are ever + // exclusive; poll waiters and a node's own consumers are not.) + var excl; + for (var entry of this.listeners) { + if (entry.exclusive) (excl ||= []).push(entry); + else entry.cb(flags); + } + if (excl) { + var i = (this.exclTurn || 0) % excl.length; + this.exclTurn = i + 1; + excl[i].cb(flags); + } + } }, lookupPath(path, opts = {}) { - path = PATH_FS.resolve(path); - - if (!path) return { path: '', node: null }; - - var defaults = { - follow_mount: true, - recurse_count: 0 - }; - opts = Object.assign(defaults, opts) + if (!path) { + throw new FS.ErrnoError(44); + } + opts.follow_mount ??= true - if (opts.recurse_count > 8) { // max recursive lookup of 8 - throw new FS.ErrnoError(32); + if (!PATH.isAbs(path)) { + path = FS.cwd() + '/' + path; } - // split the absolute path - var parts = path.split('/').filter((p) => !!p); + // limit max consecutive symlinks to SYMLOOP_MAX. + linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) { + // split the absolute path + var parts = path.split('/').filter((p) => !!p); - // start at the root - var current = FS.root; - var current_path = '/'; + // start at the root + var current = FS.root; + var current_path = '/'; - for (var i = 0; i < parts.length; i++) { - var islast = (i === parts.length-1); - if (islast && opts.parent) { - // stop resolving - break; - } + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } - current = FS.lookupNode(current, parts[i]); - current_path = PATH.join2(current_path, parts[i]); + if (parts[i] === '.') { + continue; + } - // jump to the mount's root node if this is a mountpoint - if (FS.isMountpoint(current)) { - if (!islast || (islast && opts.follow_mount)) { - current = current.mounted.root; + if (parts[i] === '..') { + current_path = PATH.dirname(current_path); + if (FS.isRoot(current)) { + path = current_path + '/' + parts.slice(i + 1).join('/'); + // We're making progress here, don't let many consecutive ..'s + // lead to ELOOP + nlinks--; + continue linkloop; + } else { + current = current.parent; + } + continue; } - } - // by default, lookupPath will not follow a symlink if it is the final path component. - // setting opts.follow = true will override this behavior. - if (!islast || opts.follow) { - var count = 0; - while (FS.isLink(current.mode)) { - var link = FS.readlink(current_path); - current_path = PATH_FS.resolve(PATH.dirname(current_path), link); + current_path = PATH.join2(current_path, parts[i]); + try { + current = FS.lookupNode(current, parts[i]); + } catch (e) { + // if noent_okay is true, suppress a ENOENT in the last component + // and return an object with an undefined node. This is needed for + // resolving symlinks in the path when creating a file. + if ((e?.errno === 44) && islast && opts.noent_okay) { + return { path: current_path }; + } + throw e; + } - var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 }); - current = lookup.node; + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) { + current = current.mounted.root; + } - if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). - throw new FS.ErrnoError(32); + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (FS.isLink(current.mode) && (!islast || opts.follow)) { + if (!current.node_ops.readlink) { + throw new FS.ErrnoError(52); + } + var link = current.node_ops.readlink(current); + if (!PATH.isAbs(link)) { + link = PATH.dirname(current_path) + '/' + link; } + path = link + '/' + parts.slice(i + 1).join('/'); + continue linkloop; } } + return { path: current_path, node: current }; } - - return { path: current_path, node: current }; + throw new FS.ErrnoError(32); }, getPath(node) { var path; @@ -1774,7 +1587,7 @@ function createWasm() { // if we failed to find it in the cache, call into the VFS return FS.lookup(parent, name); }, - createNode(parent, name, mode, rdev) { + createNode(parent, name, mode, rdev = undefined) { var node = new FS.FSNode(parent, name, mode, rdev); FS.hashAddNode(node); @@ -1825,9 +1638,11 @@ function createWasm() { // return 0 if any user, group or owner bits are set. if (perms.includes('r') && !(node.mode & 292)) { return 2; - } else if (perms.includes('w') && !(node.mode & 146)) { + } + if (perms.includes('w') && !(node.mode & 146)) { return 2; - } else if (perms.includes('x') && !(node.mode & 73)) { + } + if (perms.includes('x') && !(node.mode & 73)) { return 2; } return 0; @@ -1840,6 +1655,9 @@ function createWasm() { return 0; }, mayCreate(dir, name) { + if (!FS.isDir(dir.mode)) { + return 54; + } try { var node = FS.lookupNode(dir, name); return 20; @@ -1865,10 +1683,8 @@ function createWasm() { if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { return 10; } - } else { - if (FS.isDir(node.mode)) { - return 31; - } + } else if (FS.isDir(node.mode)) { + return 31; } return 0; }, @@ -1878,13 +1694,22 @@ function createWasm() { } if (FS.isLink(node.mode)) { return 32; - } else if (FS.isDir(node.mode)) { - if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write - (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only) + } + var mode = FS.flagsToPermissionString(flags); + if (FS.isDir(node.mode)) { + // opening for write + // TODO: check for O_SEARCH? (== search for dir only) + if (mode !== 'r' || (flags & (512 | 64))) { return 31; } } - return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + return FS.nodePermissions(node, mode); + }, + checkOpExists(op, err) { + if (!op) { + throw new FS.ErrnoError(err); + } + return op; }, MAX_OPEN_FDS:4096, nextfd() { @@ -1922,6 +1747,20 @@ function createWasm() { stream.stream_ops?.dup?.(stream); return stream; }, + doSetAttr(stream, node, attr) { + var setattr = stream?.stream_ops.setattr; + var arg = setattr ? stream : node; + setattr ??= node.node_ops.setattr; + FS.checkOpExists(setattr, 63) + try { + setattr(arg, attr); + } catch (e) { + if (e instanceof RangeError) { + throw new FS.ErrnoError(22); + } + throw e; + } + }, chrdev_stream_ops:{ open(stream) { var device = FS.getDevice(stream.node.rdev); @@ -1956,7 +1795,7 @@ function createWasm() { return mounts; }, syncfs(populate, callback) { - if (typeof populate == 'function') { + if (typeof populate === 'function') { callback = populate; populate = false; } @@ -1989,12 +1828,13 @@ function createWasm() { }; // sync all mounts - mounts.forEach((mount) => { - if (!mount.type.syncfs) { - return done(null); + for (var mount of mounts) { + if (mount.type.syncfs) { + mount.type.syncfs(mount, populate, done); + } else { + done(null); } - mount.type.syncfs(mount, populate, done); - }); + } }, mount(type, opts, mountpoint) { var root = mountpoint === '/'; @@ -2056,9 +1896,7 @@ function createWasm() { var mount = node.mounted; var mounts = FS.getMounts(mount); - Object.keys(FS.nameTable).forEach((hash) => { - var current = FS.nameTable[hash]; - + for (var [hash, current] of Object.entries(FS.nameTable)) { while (current) { var next = current.name_next; @@ -2068,7 +1906,7 @@ function createWasm() { current = next; } - }); + } // no longer a mountpoint node.mounted = null; @@ -2084,9 +1922,12 @@ function createWasm() { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); - if (!name || name === '.' || name === '..') { + if (!name) { throw new FS.ErrnoError(28); } + if (name === '.' || name === '..') { + throw new FS.ErrnoError(20); + } var errCode = FS.mayCreate(parent, name); if (errCode) { throw new FS.ErrnoError(errCode); @@ -2097,15 +1938,24 @@ function createWasm() { return parent.node_ops.mknod(parent, name, mode, dev); }, statfs(path) { - + return FS.statfsNode(FS.lookupPath(path, {follow: true}).node); + }, + statfsStream(stream) { + // We keep a separate statfsStream function because noderawfs overrides + // it. In noderawfs, stream.node is sometimes null. Instead, we need to + // look at stream.path. + return FS.statfsNode(stream.node); + }, + statfsNode(node) { // NOTE: None of the defaults here are true. We're just returning safe and - // sane values. + // sane values. Currently nodefs and rawfs replace these defaults, + // other file systems leave them alone. var rtn = { bsize: 4096, frsize: 4096, - blocks: 1e6, - bfree: 5e5, - bavail: 5e5, + blocks: 1_000_000, + bfree: 500_000, + bavail: 500_000, files: FS.nextInode, ffree: FS.nextInode - 1, fsid: 42, @@ -2113,9 +1963,8 @@ function createWasm() { namelen: 255, }; - var parent = FS.lookupPath(path, {follow: true}).node; - if (parent?.node_ops.statfs) { - Object.assign(rtn, parent.node_ops.statfs(parent.mount.opts.root)); + if (node.node_ops.statfs) { + Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root)); } return rtn; }, @@ -2129,12 +1978,13 @@ function createWasm() { mode |= 16384; return FS.mknod(path, mode, 0); }, - mkdirTree(path, mode) { + mkdirTree(path, mode = 0o777) { var dirs = path.split('/'); var d = ''; - for (var i = 0; i < dirs.length; ++i) { - if (!dirs[i]) continue; - d += '/' + dirs[i]; + for (var dir of dirs) { + if (!dir) continue; + if (d || PATH.isAbs(path)) d += '/'; + d += dir; try { FS.mkdir(d, mode); } catch(e) { @@ -2142,8 +1992,8 @@ function createWasm() { } } }, - mkdev(path, mode, dev) { - if (typeof dev == 'undefined') { + mkdev(path, mode, dev = undefined) { + if (typeof dev === 'undefined') { dev = mode; mode = 0o666; } @@ -2169,6 +2019,25 @@ function createWasm() { } return parent.node_ops.symlink(parent, newname, oldpath); }, + link(oldpath, newpath, flags) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + // Hardlinks are only supported by filesystem backends that provide a + // `link` node op (e.g. NODERAWFS backed by the host). NODEFS omits it: + // a host hardlink cannot be confined to the mount root. + if (!parent.node_ops.link) { + throw new FS.ErrnoError(34); + } + return parent.node_ops.link(parent, newname, oldpath, flags); + }, rename(old_path, new_path) { var old_dirname = PATH.dirname(old_path); var new_dirname = PATH.dirname(new_path); @@ -2243,6 +2112,11 @@ function createWasm() { // do the underlying fs rename try { old_dir.node_ops.rename(old_node, new_dir, new_name); + // The replaced node is stale now. Evict it only after the rename + // succeeded: backends like NODEFS report node.id as st_ino. + if (new_node) { + FS.hashRemoveNode(new_node); + } // update old node (we do this here to avoid each backend // needing to) old_node.parent = new_dir; @@ -2275,10 +2149,8 @@ function createWasm() { readdir(path) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; - if (!node.node_ops.readdir) { - throw new FS.ErrnoError(54); - } - return node.node_ops.readdir(node); + var readdir = FS.checkOpExists(node.node_ops.readdir, 54); + return readdir(node); }, unlink(path) { var lookup = FS.lookupPath(path, { parent: true }); @@ -2315,80 +2187,73 @@ function createWasm() { } return link.node_ops.readlink(link); }, - stat(path, dontFollow) { + stat(path, dontFollow = false) { var lookup = FS.lookupPath(path, { follow: !dontFollow }); var node = lookup.node; - if (!node) { - throw new FS.ErrnoError(44); - } - if (!node.node_ops.getattr) { - throw new FS.ErrnoError(63); - } - return node.node_ops.getattr(node); + var getattr = FS.checkOpExists(node.node_ops.getattr, 63); + return getattr(node); + }, + fstat(fd) { + var stream = FS.getStreamChecked(fd); + var node = stream.node; + var getattr = stream.stream_ops.getattr; + var arg = getattr ? stream : node; + getattr ??= node.node_ops.getattr; + FS.checkOpExists(getattr, 63) + return getattr(arg); }, lstat(path) { return FS.stat(path, true); }, - chmod(path, mode, dontFollow) { + doChmod(stream, node, mode, dontFollow = false) { + FS.doSetAttr(stream, node, { + mode: (mode & 4095) | (node.mode & ~4095), + ctime: Date.now(), + dontFollow + }); + }, + chmod(path, mode, dontFollow = false) { var node; - if (typeof path == 'string') { + if (typeof path === 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } - node.node_ops.setattr(node, { - mode: (mode & 4095) | (node.mode & ~4095), - timestamp: Date.now() - }); + FS.doChmod(null, node, mode, dontFollow); }, lchmod(path, mode) { FS.chmod(path, mode, true); }, fchmod(fd, mode) { var stream = FS.getStreamChecked(fd); - FS.chmod(stream.node, mode); + FS.doChmod(stream, stream.node, mode, false); + }, + doChown(stream, node, dontFollow = false) { + FS.doSetAttr(stream, node, { + timestamp: Date.now(), + dontFollow + // we ignore the uid / gid for now + }); }, - chown(path, uid, gid, dontFollow) { + chown(path, uid, gid, dontFollow = false) { var node; - if (typeof path == 'string') { + if (typeof path === 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } - node.node_ops.setattr(node, { - timestamp: Date.now() - // we ignore the uid / gid for now - }); + FS.doChown(null, node, dontFollow); }, lchown(path, uid, gid) { FS.chown(path, uid, gid, true); }, fchown(fd, uid, gid) { var stream = FS.getStreamChecked(fd); - FS.chown(stream.node, uid, gid); + FS.doChown(stream, stream.node, false); }, - truncate(path, len) { - if (len < 0) { - throw new FS.ErrnoError(28); - } - var node; - if (typeof path == 'string') { - var lookup = FS.lookupPath(path, { follow: true }); - node = lookup.node; - } else { - node = path; - } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } + doTruncate(stream, node, len) { if (FS.isDir(node.mode)) { throw new FS.ErrnoError(31); } @@ -2399,48 +2264,64 @@ function createWasm() { if (errCode) { throw new FS.ErrnoError(errCode); } - node.node_ops.setattr(node, { + FS.doSetAttr(stream, node, { size: len, timestamp: Date.now() }); }, + truncate(path, len) { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path === 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + FS.doTruncate(null, node, len); + }, ftruncate(fd, len) { var stream = FS.getStreamChecked(fd); - if ((stream.flags & 2097155) === 0) { + if (len < 0 || (stream.flags & 2097155) === 0) { throw new FS.ErrnoError(28); } - FS.truncate(stream.node, len); + FS.doTruncate(stream, stream.node, len); }, - utime(path, atime, mtime) { - var lookup = FS.lookupPath(path, { follow: true }); - var node = lookup.node; - node.node_ops.setattr(node, { - timestamp: Math.max(atime, mtime) + utime(path, atime, mtime, dontFollow = false) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + FS.doSetAttr(null, lookup.node, { + atime: atime, + mtime: mtime, + dontFollow }); }, open(path, flags, mode = 0o666) { - if (path === "") { + if (path === '') { throw new FS.ErrnoError(44); } - flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; + flags = FS_modeStringToFlags(flags); if ((flags & 64)) { mode = (mode & 4095) | 32768; } else { mode = 0; } var node; - if (typeof path == 'object') { + var isDirPath; + if (typeof path === 'object') { node = path; } else { - path = PATH.normalize(path); - try { - var lookup = FS.lookupPath(path, { - follow: !(flags & 131072) - }); - node = lookup.node; - } catch (e) { - // ignore - } + isDirPath = path.endsWith('/'); + // noent_okay makes it so that if the final component of the path + // doesn't exist, lookupPath returns `node: undefined`. `path` will be + // updated to point to the target of all symlinks. + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072), + noent_okay: true + }); + node = lookup.node; + path = lookup.path; } // perhaps we need to create the node var created = false; @@ -2450,9 +2331,14 @@ function createWasm() { if ((flags & 128)) { throw new FS.ErrnoError(20); } + } else if (isDirPath) { + throw new FS.ErrnoError(31); } else { // node doesn't exist, try to create it - node = FS.mknod(path, mode, 0); + // Ignore the permission bits here to ensure we can `open` this new + // file below. We use chmod below to apply the permissions once the + // file is open. + node = FS.mknod(path, mode | 0o777, 0); created = true; } } @@ -2499,10 +2385,8 @@ function createWasm() { if (stream.stream_ops.open) { stream.stream_ops.open(stream); } - if (Module['logReadFiles'] && !(flags & 1)) { - if (!(path in FS.readFiles)) { - FS.readFiles[path] = 1; - } + if (created) { + FS.chmod(node, mode & 0o777); } return stream; }, @@ -2511,6 +2395,11 @@ function createWasm() { throw new FS.ErrnoError(8); } if (stream.getdents) stream.getdents = null; // free readdir state + // The fd is going away: wake anything waiting on it (poll/epoll) with + // POLLNVAL so a blocking wait unblocks and an epoll registration is evicted + // on its next derive. Only sockets/pipes/epoll ever carry a wait-queue, so + // for every other stream (incl. nodeless noderawfs stdio) this is a no-op. + stream.node?.notifyListeners(32); try { if (stream.stream_ops.close) { stream.stream_ops.close(stream); @@ -2539,7 +2428,7 @@ function createWasm() { stream.ungotten = []; return stream.position; }, - read(stream, buffer, offset, length, position) { + read(stream, buffer, offset, length, position = undefined) { if (length < 0 || position < 0) { throw new FS.ErrnoError(28); } @@ -2555,7 +2444,7 @@ function createWasm() { if (!stream.stream_ops.read) { throw new FS.ErrnoError(28); } - var seeking = typeof position != 'undefined'; + var seeking = typeof position !== 'undefined'; if (!seeking) { position = stream.position; } else if (!stream.seekable) { @@ -2565,7 +2454,7 @@ function createWasm() { if (!seeking) stream.position += bytesRead; return bytesRead; }, - write(stream, buffer, offset, length, position, canOwn) { + write(stream, buffer, offset, length, position = undefined, canOwn = undefined) { if (length < 0 || position < 0) { throw new FS.ErrnoError(28); } @@ -2585,7 +2474,7 @@ function createWasm() { // seek to the end before writing in append mode FS.llseek(stream, 0, 2); } - var seeking = typeof position != 'undefined'; + var seeking = typeof position !== 'undefined'; if (!seeking) { position = stream.position; } else if (!stream.seekable) { @@ -2595,24 +2484,6 @@ function createWasm() { if (!seeking) stream.position += bytesWritten; return bytesWritten; }, - allocate(stream, offset, length) { - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if (offset < 0 || length <= 0) { - throw new FS.ErrnoError(28); - } - if ((stream.flags & 2097155) === 0) { - throw new FS.ErrnoError(8); - } - if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { - throw new FS.ErrnoError(43); - } - if (!stream.stream_ops.allocate) { - throw new FS.ErrnoError(138); - } - stream.stream_ops.allocate(stream, offset, length); - }, mmap(stream, length, position, prot, flags) { // User requests writing to file (prot & PROT_WRITE != 0). // Checking if we have permissions to write to the file unless @@ -2620,8 +2491,8 @@ function createWasm() { // to write to file opened in read-only mode with MAP_PRIVATE flag, // as all modifications will be visible only in the memory of // the current process. - if ((prot & 2) !== 0 - && (flags & 2) === 0 + if ((prot & 2) + && !(flags & 2) && (stream.flags & 2097155) !== 2) { throw new FS.ErrnoError(2); } @@ -2649,37 +2520,27 @@ function createWasm() { return stream.stream_ops.ioctl(stream, cmd, arg); }, readFile(path, opts = {}) { - opts.flags = opts.flags || 0; - opts.encoding = opts.encoding || 'binary'; + opts.flags ??= 0; + opts.encoding ??= 'binary'; if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { - throw new Error(`Invalid encoding type "${opts.encoding}"`); + abort(`Invalid encoding type "${opts.encoding}"`); } - var ret; var stream = FS.open(path, opts.flags); var stat = FS.stat(path); var length = stat.size; var buf = new Uint8Array(length); FS.read(stream, buf, 0, length, 0); if (opts.encoding === 'utf8') { - ret = UTF8ArrayToString(buf); - } else if (opts.encoding === 'binary') { - ret = buf; + buf = UTF8ArrayToString(buf); } FS.close(stream); - return ret; + return buf; }, writeFile(path, data, opts = {}) { - opts.flags = opts.flags || 577; + opts.flags ??= 577; var stream = FS.open(path, opts.flags, opts.mode); - if (typeof data == 'string') { - var buf = new Uint8Array(lengthBytesUTF8(data)+1); - var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); - FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); - } else if (ArrayBuffer.isView(data)) { - FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); - } else { - throw new Error('Unsupported data type'); - } + data = FS_fileDataToTypedArray(data); + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); FS.close(stream); }, cwd:() => FS.currentPath, @@ -2723,8 +2584,9 @@ function createWasm() { // use a buffer to avoid overhead of individual crypto calls per byte var randomBuffer = new Uint8Array(1024), randomLeft = 0; var randomByte = () => { - if (randomLeft === 0) { - randomLeft = randomFill(randomBuffer).byteLength; + if (!randomLeft) { + randomFill(randomBuffer); + randomLeft = randomBuffer.byteLength; } return randomBuffer[--randomLeft]; }; @@ -2744,6 +2606,9 @@ function createWasm() { FS.mount({ mount() { var node = FS.createNode(proc_self, 'fd', 16895, 73); + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek, + }; node.node_ops = { lookup(parent, name) { var fd = +name; @@ -2752,9 +2617,15 @@ function createWasm() { parent: null, mount: { mountpoint: 'fake' }, node_ops: { readlink: () => stream.path }, + id: fd + 1, }; ret.parent = ret; // make it look like a simple root node return ret; + }, + readdir() { + return Array.from(FS.streams.entries()) + .filter(([k, v]) => v) + .map(([k, v]) => k.toString()); } }; return node; @@ -2792,25 +2663,18 @@ function createWasm() { var stderr = FS.open('/dev/stderr', 1); }, staticInit() { - FS.nameTable = new Array(4096); + FS.nameTable.length = 4096; FS.mount(MEMFS, {}, '/'); FS.createDefaultDirectories(); FS.createDefaultDevices(); FS.createSpecialDirectories(); - - FS.filesystems = { - 'MEMFS': MEMFS, - }; }, - init(input, output, error) { + init(input = undefined, output = undefined, error = undefined) { FS.initialized = true; // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here - input ??= Module['stdin']; - output ??= Module['stdout']; - error ??= Module['stderr']; FS.createStandardStreams(input, output, error); }, @@ -2818,22 +2682,13 @@ function createWasm() { FS.initialized = false; // force-flush all streams, so we get musl std streams printed out // close all of our streams - for (var i = 0; i < FS.streams.length; i++) { - var stream = FS.streams[i]; - if (!stream) { - continue; + for (var stream of FS.streams) { + if (stream) { + FS.close(stream); } - FS.close(stream); - } - }, - findObject(path, dontResolveLastLink) { - var ret = FS.analyzePath(path, dontResolveLastLink); - if (!ret.exists) { - return null; } - return ret.object; }, - analyzePath(path, dontResolveLastLink) { + analyzePath(path, dontResolveLastLink = false) { // operate from within the context of the symlink's target try { var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); @@ -2861,8 +2716,8 @@ function createWasm() { }; return ret; }, - createPath(parent, path, canRead, canWrite) { - parent = typeof parent == 'string' ? parent : FS.getPath(parent); + createPath(parent, path, canRead = undefined, canWrite = undefined) { + parent = typeof parent === 'string' ? parent : FS.getPath(parent); var parts = path.split('/').reverse(); while (parts.length) { var part = parts.pop(); @@ -2871,31 +2726,27 @@ function createWasm() { try { FS.mkdir(current); } catch (e) { - // ignore EEXIST + if (e.errno != 20) throw e; } parent = current; } return current; }, - createFile(parent, name, properties, canRead, canWrite) { - var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + createFile(parent, name, properties, canRead = undefined, canWrite = undefined) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS_getMode(canRead, canWrite); return FS.create(path, mode); }, - createDataFile(parent, name, data, canRead, canWrite, canOwn) { + createDataFile(parent, name, data = undefined, canRead = undefined, canWrite = undefined, canOwn = undefined) { var path = name; if (parent) { - parent = typeof parent == 'string' ? parent : FS.getPath(parent); + parent = typeof parent === 'string' ? parent : FS.getPath(parent); path = name ? PATH.join2(parent, name) : parent; } var mode = FS_getMode(canRead, canWrite); var node = FS.create(path, mode); if (data) { - if (typeof data == 'string') { - var arr = new Array(data.length); - for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); - data = arr; - } + data = FS_fileDataToTypedArray(data); // make sure we can write to the file FS.chmod(node, mode | 146); var stream = FS.open(node, 577); @@ -2904,8 +2755,8 @@ function createWasm() { FS.chmod(node, mode); } }, - createDevice(parent, name, input, output) { - var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + createDevice(parent, name, input = undefined, output = undefined) { + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS_getMode(!!input, !!output); FS.createDevice.major ??= 64; var dev = FS.makedev(FS.createDevice.major++, 0); @@ -2930,7 +2781,7 @@ function createWasm() { } catch (e) { throw new FS.ErrnoError(29); } - if (result === undefined && bytesRead === 0) { + if (result === undefined && !bytesRead) { throw new FS.ErrnoError(6); } if (result === null || result === undefined) break; @@ -2938,7 +2789,7 @@ function createWasm() { buffer[offset+i] = result; } if (bytesRead) { - stream.node.timestamp = Date.now(); + stream.node.atime = Date.now(); } return bytesRead; }, @@ -2951,7 +2802,7 @@ function createWasm() { } } if (length) { - stream.node.timestamp = Date.now(); + stream.node.mtime = stream.node.ctime = Date.now(); } return i; } @@ -2960,18 +2811,17 @@ function createWasm() { }, forceLoadFile(obj) { if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; - if (typeof XMLHttpRequest != 'undefined') { - throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + if (globalThis.XMLHttpRequest) { + abort('Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.'); } else { // Command-line. try { obj.contents = readBinary(obj.url); - obj.usedBytes = obj.contents.length; } catch (e) { throw new FS.ErrnoError(29); } } }, - createLazyFile(parent, name, url, canRead, canWrite) { + createLazyFile(parent, name, url, canRead = undefined, canWrite = undefined) { // Lazy chunked Uint8Array (implements get and length from Uint8Array). // Actual getting is abstracted away for eventual reuse. class LazyUint8Array { @@ -2993,11 +2843,11 @@ function createWasm() { var xhr = new XMLHttpRequest(); xhr.open('HEAD', url, false); xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - var datalength = Number(xhr.getResponseHeader("Content-length")); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`); + var datalength = Number(xhr.getResponseHeader('Content-length')); var header; - var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; - var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + var hasByteServing = (header = xhr.getResponseHeader('Accept-Ranges')) && header === 'bytes'; + var usesGzip = (header = xhr.getResponseHeader('Content-Encoding')) && header === 'gzip'; var chunkSize = 1024*1024; // Chunk size in bytes @@ -3005,13 +2855,13 @@ function createWasm() { // Function to get a range from the remote URL. var doXHR = (from, to) => { - if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); - if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`); + if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`); // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); - if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + if (datalength !== chunkSize) xhr.setRequestHeader('Range', `bytes=${from}-${to}`); // Some hints to the browser that we want binary data. xhr.responseType = 'arraybuffer'; @@ -3020,21 +2870,21 @@ function createWasm() { } xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`); if (xhr.response !== undefined) { return new Uint8Array(/** @type{Array} */(xhr.response || [])); } - return intArrayFromString(xhr.responseText || '', true); + return intArrayFromString(xhr.responseText ?? '', true); }; var lazyArray = this; lazyArray.setDataGetter((chunkNum) => { var start = chunkNum * chunkSize; var end = (chunkNum+1) * chunkSize - 1; // including this byte end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block - if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + if (typeof lazyArray.chunks[chunkNum] === 'undefined') { lazyArray.chunks[chunkNum] = doXHR(start, end); } - if (typeof lazyArray.chunks[chunkNum] == 'undefined') throw new Error('doXHR failed!'); + if (typeof lazyArray.chunks[chunkNum] === 'undefined') abort('doXHR failed!'); return lazyArray.chunks[chunkNum]; }); @@ -3043,7 +2893,7 @@ function createWasm() { chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file datalength = this.getter(0).length; chunkSize = datalength; - out("LazyFiles on gzip forces download of the whole file when length is accessed"); + out('LazyFiles on gzip forces download of the whole file when length is accessed'); } this._length = datalength; @@ -3064,8 +2914,8 @@ function createWasm() { } } - if (typeof XMLHttpRequest != 'undefined') { - if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + if (globalThis.XMLHttpRequest) { + if (!ENVIRONMENT_IS_WORKER) abort('Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'); var lazyArray = new LazyUint8Array(); var properties = { isDevice: false, contents: lazyArray }; } else { @@ -3090,14 +2940,12 @@ function createWasm() { }); // override each stream op with one that tries to force load the lazy file first var stream_ops = {}; - var keys = Object.keys(node.stream_ops); - keys.forEach((key) => { - var fn = node.stream_ops[key]; + for (const [key, fn] of Object.entries(node.stream_ops)) { stream_ops[key] = (...args) => { FS.forceLoadFile(node); return fn(...args); }; - }); + } function writeChunks(stream, buffer, offset, length, position) { var contents = stream.node.contents; if (position >= contents.length) @@ -3134,9 +2982,19 @@ function createWasm() { }, }; + + + /** @type {!Int32Array} */ + var HEAP32; + + /** @type {!Uint32Array} */ + var HEAPU32; + + /** not-@type {!BigInt64Array} */ + var HEAP64; var SYSCALLS = { - DEFAULT_POLLMASK:5, - calculateAt(dirfd, path, allowEmpty) { + currentUmask:18, + calculateAt(dirfd, path, allowEmpty = false) { if (PATH.isAbs(path)) { return path; } @@ -3154,16 +3012,15 @@ function createWasm() { } return dir; } - return PATH.join2(dir, path); + return dir + '/' + path; }, - doStat(func, path, buf) { - var stat = func(path); - HEAP32[((buf)>>2)] = stat.dev; - HEAP32[(((buf)+(4))>>2)] = stat.mode; + writeStat(buf, stat) { + HEAPU32[((buf)>>2)] = stat.dev; + HEAPU32[(((buf)+(4))>>2)] = stat.mode; HEAPU32[(((buf)+(8))>>2)] = stat.nlink; - HEAP32[(((buf)+(12))>>2)] = stat.uid; - HEAP32[(((buf)+(16))>>2)] = stat.gid; - HEAP32[(((buf)+(20))>>2)] = stat.rdev; + HEAPU32[(((buf)+(12))>>2)] = stat.uid; + HEAPU32[(((buf)+(16))>>2)] = stat.gid; + HEAPU32[(((buf)+(20))>>2)] = stat.rdev; HEAP64[(((buf)+(24))>>3)] = BigInt(stat.size); HEAP32[(((buf)+(32))>>2)] = 4096; HEAP32[(((buf)+(36))>>2)] = stat.blocks; @@ -3179,6 +3036,18 @@ function createWasm() { HEAP64[(((buf)+(88))>>3)] = BigInt(stat.ino); return 0; }, + writeStatFs(buf, stats) { + HEAPU32[(((buf)+(4))>>2)] = stats.bsize; + HEAPU32[(((buf)+(60))>>2)] = stats.bsize; + HEAP64[(((buf)+(8))>>3)] = BigInt(stats.blocks); + HEAP64[(((buf)+(16))>>3)] = BigInt(stats.bfree); + HEAP64[(((buf)+(24))>>3)] = BigInt(stats.bavail); + HEAP64[(((buf)+(32))>>3)] = BigInt(stats.files); + HEAP64[(((buf)+(40))>>3)] = BigInt(stats.ffree); + HEAPU32[(((buf)+(48))>>2)] = stats.fsid; + HEAPU32[(((buf)+(64))>>2)] = stats.flags; // ST_NOSUID + HEAPU32[(((buf)+(56))>>2)] = stats.namelen; + }, doMsync(addr, stream, len, flags, offset) { if (!FS.isFile(stream.node.mode)) { throw new FS.ErrnoError(43); @@ -3187,7 +3056,7 @@ function createWasm() { // MAP_PRIVATE calls need not to be synced back to underlying fs return 0; } - var buffer = HEAPU8.slice(addr, addr + len); + var buffer = HEAPU8.subarray(addr, addr + len); FS.msync(stream, buffer, offset, len, flags); }, getStreamFromFD(fd) { @@ -3207,10 +3076,11 @@ function createWasm() { FS.chmod(path, mode); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_faccessat(dirfd, path, amode, flags) { try { @@ -3235,10 +3105,11 @@ function createWasm() { } return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_fchmod(fd, mode) { try { @@ -3246,10 +3117,11 @@ function createWasm() { FS.fchmod(fd, mode); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_fchown32(fd, owner, group) { try { @@ -3257,12 +3129,12 @@ function createWasm() { FS.fchown(fd, owner, group); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + - /** @suppress {duplicate } */ var syscallGetVarargI = () => { // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; @@ -3272,6 +3144,9 @@ function createWasm() { var syscallGetVarargP = syscallGetVarargI; + + /** @type {!Int16Array} */ + var HEAP16; function ___syscall_fcntl64(fd, cmd, varargs) { SYSCALLS.varargs = varargs; try { @@ -3297,7 +3172,8 @@ function createWasm() { return stream.flags; case 4: { var arg = syscallGetVarargI(); - stream.flags |= arg; + var mask = 289792; + stream.flags = (stream.flags & ~mask) | (arg & mask); return 0; } case 12: { @@ -3309,25 +3185,30 @@ function createWasm() { } case 13: case 14: - return 0; // Pretend that the locking is successful. + // Pretend that the locking is successful. These are process-level locks, + // and Emscripten programs are a single process. If we supported linking a + // filesystem between programs, we'd need to do more here. + // See https://github.com/emscripten-core/emscripten/issues/23697 + return 0; } return -28; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_fstat64(fd, buf) { try { - var stream = SYSCALLS.getStreamFromFD(fd); - return SYSCALLS.doStat(FS.stat, stream.path, buf); + return SYSCALLS.writeStat(buf, FS.fstat(fd)); } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + var INT53_MAX = 9007199254740992; @@ -3336,39 +3217,46 @@ function createWasm() { function ___syscall_ftruncate64(fd, length) { length = bigintToI53Checked(length); - + try { - if (isNaN(length)) return 61; + if (isNaN(length)) return -22; FS.ftruncate(fd, length); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } ; } + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); }; function ___syscall_getcwd(buf, size) { try { - if (size === 0) return -28; + if (!size) return -28; var cwd = FS.cwd(); var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1; if (size < cwdLengthInBytes) return -68; stringToUTF8(cwd, buf, size); return cwdLengthInBytes; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + + + var ___syscall_geteuid32 = () => 0; + + + function ___syscall_ioctl(fd, op, varargs) { SYSCALLS.varargs = varargs; try { @@ -3429,6 +3317,7 @@ function createWasm() { if (!stream.tty) return -59; return -28; // not supported } + case 21537: case 21531: { var argp = syscallGetVarargP(); return FS.ioctl(stream, op, argp); @@ -3459,38 +3348,38 @@ function createWasm() { default: return -28; // not supported } } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_lstat64(path, buf) { try { path = SYSCALLS.getStr(path); - return SYSCALLS.doStat(FS.lstat, path, buf); + return SYSCALLS.writeStat(buf, FS.lstat(path)); } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_mkdirat(dirfd, path, mode) { try { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); - // remove a trailing slash, if one - /a/b/ has basename of '', but - // we want to create b in the context of this function - path = PATH.normalize(path); - if (path[path.length-1] === '/') path = path.substr(0, path.length-1); - FS.mkdir(path, mode, 0); + mode &= ~SYSCALLS.currentUmask; + FS.mkdir(path, mode); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_newfstatat(dirfd, path, buf, flags) { try { @@ -3500,12 +3389,13 @@ function createWasm() { var allowEmpty = flags & 4096; flags = flags & (~6400); path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); - return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf); + return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path)); } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_openat(dirfd, path, flags, varargs) { @@ -3515,15 +3405,20 @@ function createWasm() { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); var mode = varargs ? syscallGetVarargI() : 0; + if (flags & 64) { + mode &= ~SYSCALLS.currentUmask; + } return FS.open(path, flags, mode).fd; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + + function ___syscall_readlinkat(dirfd, path, buf, bufsize) { try { @@ -3540,10 +3435,11 @@ function createWasm() { HEAP8[buf+len] = endChar; return len; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_rmdir(path) { try { @@ -3552,48 +3448,54 @@ function createWasm() { FS.rmdir(path); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_stat64(path, buf) { try { path = SYSCALLS.getStr(path); - return SYSCALLS.doStat(FS.stat, path, buf); + return SYSCALLS.writeStat(buf, FS.stat(path)); } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + function ___syscall_unlinkat(dirfd, path, flags) { try { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); - if (flags === 0) { + if (!flags) { FS.unlink(path); } else if (flags === 512) { FS.rmdir(path); } else { - abort('Invalid flags passed to unlinkat'); + return -28; } return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } + + var readI53FromI64 = (ptr) => { return HEAPU32[((ptr)>>2)] + HEAP32[(((ptr)+(4))>>2)] * 4294967296; }; + function ___syscall_utimensat(dirfd, path, times, flags) { try { + var nofollow = flags & 256; path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path, true); var now = Date.now(), atime, mtime; @@ -3601,41 +3503,32 @@ function createWasm() { atime = now; mtime = now; } else { - var seconds = readI53FromI64(times); - var nanoseconds = HEAP32[(((times)+(8))>>2)]; - if (nanoseconds == 1073741823) { - atime = now; - } else if (nanoseconds == 1073741822) { - atime = -1; - } else { - atime = (seconds*1000) + (nanoseconds/(1000*1000)); - } - times += 16; - seconds = readI53FromI64(times); - nanoseconds = HEAP32[(((times)+(8))>>2)]; - if (nanoseconds == 1073741823) { - mtime = now; - } else if (nanoseconds == 1073741822) { - mtime = -1; - } else { - mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + function readTimespec(ptr) { + var tv_nsec = HEAP32[(((ptr)+(8))>>2)]; + if (tv_nsec == 1073741823) { + return now; + } + if (tv_nsec == 1073741822) { + return null; + } + var tv_sec = readI53FromI64(ptr); + return (tv_sec*1000) + Math.floor(tv_nsec/(1000*1000)); } + atime = readTimespec(times); + mtime = readTimespec(times + 16); } - // -1 here means UTIME_OMIT was passed. FS.utime tables the max of these - // two values and sets the timestamp to that single value. If both were - // set to UTIME_OMIT then we can skip the call completely. - if (mtime != -1 || atime != -1) { - FS.utime(path, atime, mtime); + // null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then + // we can skip the call completely. + if ((mtime ?? atime) !== null) { + FS.utime(path, atime, mtime, nofollow); } return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } } - - var nowIsMonotonic = 1; - var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; + var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0); @@ -3650,11 +3543,15 @@ function createWasm() { return yday; }; + function __localtime_js(time, tmPtr) { time = bigintToI53Checked(time); - + var date = new Date(time*1000); + if (isNaN(date.getTime())) { + return 1; + } HEAP32[((tmPtr)>>2)] = date.getSeconds(); HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); @@ -3673,6 +3570,7 @@ function createWasm() { var winterOffset = start.getTimezoneOffset(); var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0; HEAP32[(((tmPtr)+(32))>>2)] = dst; + return 0; ; } @@ -3681,13 +3579,14 @@ function createWasm() { + + function __mmap_js(len, prot, flags, fd, offset, allocated, addr) { offset = bigintToI53Checked(offset); - + try { - if (isNaN(offset)) return 61; var stream = SYSCALLS.getStreamFromFD(fd); var res = FS.mmap(stream, len, offset, prot, flags); var ptr = res.ptr; @@ -3695,7 +3594,7 @@ function createWasm() { HEAPU32[((addr)>>2)] = ptr; return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } ; @@ -3705,7 +3604,7 @@ function createWasm() { function __munmap_js(addr, len, prot, flags, fd, offset) { offset = bigintToI53Checked(offset); - + try { var stream = SYSCALLS.getStreamFromFD(fd); @@ -3713,12 +3612,14 @@ function createWasm() { SYSCALLS.doMsync(addr, stream, len, flags, offset); } } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } ; } + + var __tzset_js = (timezone, daylight, std_name, dst_name) => { // TODO: Use (malleable) environment variables instead of system settings. var currentYear = new Date().getFullYear(); @@ -3747,11 +3648,11 @@ function createWasm() { var extractZone = (timezoneOffset) => { // Why inverse sign? // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset - var sign = timezoneOffset >= 0 ? "-" : "+"; + var sign = timezoneOffset >= 0 ? '-' : '+'; var absOffset = Math.abs(timezoneOffset) - var hours = String(Math.floor(absOffset / 60)).padStart(2, "0"); - var minutes = String(absOffset % 60).padStart(2, "0"); + var hours = String(Math.floor(absOffset / 60)).padStart(2, '0'); + var minutes = String(absOffset % 60).padStart(2, '0'); return `UTC${sign}${hours}${minutes}`; } @@ -3768,10 +3669,44 @@ function createWasm() { } }; + var _emscripten_get_now = () => performance.now(); + var _emscripten_date_now = () => Date.now(); + + var nowIsMonotonic = 1; + + var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3; + + + function _clock_time_get(clk_id, ignored_precision, ptime) { + ignored_precision = bigintToI53Checked(ignored_precision); + + + if (!checkWasiClock(clk_id)) { + return 28; + } + var now; + // all wasi clocks but realtime are monotonic + if (clk_id === 0) { + now = _emscripten_date_now(); + } else if (nowIsMonotonic) { + now = _emscripten_get_now(); + } else { + return 52; + } + // "now" is in ms, and wasi times are in ns. + var nsec = Math.round(now * 1_000_000); + HEAP64[((ptime)>>3)] = BigInt(nsec); + return 0; + ; + } + - var _emscripten_get_now = () => performance.now(); + var abortOnCannotGrowMemory = (requestedSize) => { + abort('OOM'); + }; + var getHeapMax = () => // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side @@ -3780,13 +3715,9 @@ function createWasm() { 2147483648; - var abortOnCannotGrowMemory = (requestedSize) => { - abort('OOM'); - }; - var growMemory = (size) => { - var b = wasmMemory.buffer; - var pages = ((size - b.byteLength + 65535) / 65536) | 0; + var oldHeapSize = wasmMemory.buffer.byteLength; + var pages = ((size - oldHeapSize + 65535) / 65536) | 0; try { // round size grow request up to wasm page size (fixed 64KB per spec) wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size @@ -3794,9 +3725,10 @@ function createWasm() { return 1 /*success*/; } catch(e) { } - // implicit 0 return to save code size (caller will cast "undefined" into 0 + // implicit 0 return to save code size (caller will cast 'undefined' into 0 // anyhow) }; + var _emscripten_resize_heap = (requestedSize) => { var oldSize = HEAPU8.length; // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. @@ -3850,12 +3782,11 @@ function createWasm() { var ENV = { }; - var getExecutableName = () => thisProgram || './this.program'; + var getExecutableName = () => thisProgram; var getEnvStrings = () => { if (!getEnvStrings.strings) { // Default values. - // Browser language detection #8751 - var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; + var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8'; var env = { 'USER': 'web_user', 'LOGNAME': 'web_user', @@ -3882,45 +3813,41 @@ function createWasm() { return getEnvStrings.strings; }; - var stringToAscii = (str, buffer) => { - for (var i = 0; i < str.length; ++i) { - HEAP8[buffer++] = str.charCodeAt(i); - } - // Null-terminate the string - HEAP8[buffer] = 0; - }; + var _environ_get = (__environ, environ_buf) => { var bufSize = 0; - getEnvStrings().forEach((string, i) => { + var envp = 0; + for (var string of getEnvStrings()) { var ptr = environ_buf + bufSize; - HEAPU32[(((__environ)+(i*4))>>2)] = ptr; - stringToAscii(string, ptr); - bufSize += string.length + 1; - }); + HEAPU32[(((__environ)+(envp))>>2)] = ptr; + bufSize += stringToUTF8(string, ptr, Infinity) + 1; + envp += 4; + } return 0; }; + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { var strings = getEnvStrings(); HEAPU32[((penviron_count)>>2)] = strings.length; var bufSize = 0; - strings.forEach((string) => bufSize += string.length + 1); + for (var string of strings) { + bufSize += lengthBytesUTF8(string) + 1; + } HEAPU32[((penviron_buf_size)>>2)] = bufSize; return 0; }; - var runtimeKeepaliveCounter = 0; - var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + var keepRuntimeAlive = () => true; var _proc_exit = (code) => { EXITSTATUS = code; if (!keepRuntimeAlive()) { - Module['onExit']?.(code); ABORT = true; } quit_(code, new ExitStatus(code)); }; - /** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => { EXITSTATUS = status; @@ -3936,11 +3863,15 @@ function createWasm() { FS.close(stream); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } } + + + + function _fd_fdstat_get(fd, pbuf) { try { @@ -3962,11 +3893,13 @@ function createWasm() { HEAP64[(((pbuf)+(16))>>3)] = BigInt(rightsInheriting); return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } } + + /** @param {number=} offset */ var doReadv = (stream, iov, iovcnt, offset) => { var ret = 0; @@ -3974,17 +3907,29 @@ function createWasm() { var ptr = HEAPU32[((iov)>>2)]; var len = HEAPU32[(((iov)+(4))>>2)]; iov += 8; - var curr = FS.read(stream, HEAP8, ptr, len, offset); + try { + var curr = FS.read(stream, HEAP8, ptr, len, offset); + } catch (e) { + // On a non-blocking stream a subsequent read may would-block after we + // already gathered data. POSIX readv is a single gather-read: return + // what we have rather than failing the whole call. + if (ret > 0 && e instanceof FS.ErrnoError && + (e.errno == 6 || e.errno == 6)) { + break; + } + throw e; + } if (curr < 0) return -1; ret += curr; if (curr < len) break; // nothing more to read - if (typeof offset != 'undefined') { + if (typeof offset !== 'undefined') { offset += curr; } } return ret; }; + function _fd_read(fd, iov, iovcnt, pnum) { try { @@ -3993,26 +3938,28 @@ function createWasm() { HEAPU32[((pnum)>>2)] = num; return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } } + + function _fd_seek(fd, offset, whence, newOffset) { offset = bigintToI53Checked(offset); - + try { - if (isNaN(offset)) return 61; + if (isNaN(offset)) return 22; var stream = SYSCALLS.getStreamFromFD(fd); FS.llseek(stream, offset, whence); HEAP64[((newOffset)>>3)] = BigInt(stream.position); - if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state + if (stream.getdents && !offset && whence === 0) stream.getdents = null; // reset readdir state return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } ; @@ -4022,37 +3969,43 @@ function createWasm() { try { var stream = SYSCALLS.getStreamFromFD(fd); - if (stream.stream_ops?.fsync) { - return stream.stream_ops.fsync(stream); - } - return 0; // we can't do anything synchronously; the in-memory FS is already synced to + var rtn = stream.stream_ops?.fsync?.(stream); + return rtn; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } } + + + /** @param {number=} offset */ var doWritev = (stream, iov, iovcnt, offset) => { - var ret = 0; - for (var i = 0; i < iovcnt; i++) { + // Gather all iovecs into one contiguous buffer and issue a single + // FS.write, matching POSIX writev's single gather-write semantics (as + // __syscall_sendmsg already does). Per-iovec writes fragment a stream + // socket send into multiple segments, breaking stream byte semantics. + if (iovcnt == 1) { + // Single iovec: write directly from HEAP8, no gather buffer needed. + return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset); + } + var total = 0; + for (var i = 0, p = iov; i < iovcnt; i++, p += 8) { + total += HEAPU32[(((p)+(4))>>2)]; + } + var view = new Uint8Array(total); + var voff = 0; + for (var i = 0; i < iovcnt; i++, iov += 8) { var ptr = HEAPU32[((iov)>>2)]; var len = HEAPU32[(((iov)+(4))>>2)]; - iov += 8; - var curr = FS.write(stream, HEAP8, ptr, len, offset); - if (curr < 0) return -1; - ret += curr; - if (curr < len) { - // No more space to write. - break; - } - if (typeof offset != 'undefined') { - offset += curr; - } + view.set(HEAPU8.subarray(ptr, ptr + len), voff); + voff += len; } - return ret; + return FS.write(stream, view, 0, total, offset); }; + function _fd_write(fd, iov, iovcnt, pnum) { try { @@ -4061,22 +4014,513 @@ function createWasm() { HEAPU32[((pnum)>>2)] = num; return 0; } catch (e) { - if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + if (typeof FS === 'undefined' || !(e.name === 'ErrnoError')) throw e; return e.errno; } } + + + + + + + /** @type {!Float32Array} */ + var HEAPF32; + + /** @type {!Float64Array} */ + var HEAPF64; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP64[((ptr)>>3)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + + + + + + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break; + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + + + + + /** not-@type {!BigUint64Array} */ + var HEAPU64; + FS.createPreloadedFile = FS_createPreloadedFile; - FS.staticInit(); - // Set module methods based on EXPORTED_RUNTIME_METHODS - ; + FS.preloadFile = FS_preloadFile; + FS.staticInit();; +// End JS library code + +// include: postlibrary.js +// This file is included after the automatically-generated JS library code +// but before the wasm module is created. + +{ + + // Begin ATMODULES hooks + +if (Module['print']) out = Module['print']; +if (Module['printErr']) err = Module['printErr']; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; + // End ATMODULES hooks + + + + +} + +// Begin runtime exports + // End runtime exports + // Begin JS library exports + // End JS library exports + +// end include: postlibrary.js + + +// Imports from the Wasm binary. +var _sqlite3_vfs_find, + _sqlite3_free, + _sqlite3_finalize, + _sqlite3_exec, + _sqlite3_errmsg, + _sqlite3_strglob, + _sqlite3_prepare_v2, + _sqlite3_expanded_sql, + _sqlite3_step, + _sqlite3_column_text, + _sqlite3_column_count, + _sqlite3_column_type, + _sqlite3_column_bytes, + _sqlite3_column_blob, + _sqlite3_sql, + _sqlite3_reset, + _sqlite3_bind_int64, + _sqlite3_bind_int, + _sqlite3_bind_text, + _sqlite3_libversion_number, + _sqlite3_bind_double, + _sqlite3_malloc, + _sqlite3_libversion, + _sqlite3_sourceid, + _malloc, + _sqlite3_initialize, + _sqlite3_open_v2, + _sqlite3_file_control, + _sqlite3_create_function, + _sqlite3_db_status, + _sqlite3_status, + _free, + _sqlite3_stricmp, + _sqlite3_result_int64, + _wasm_main, + _sqlite3_status64, + _sqlite3_msize, + _sqlite3_vfs_register, + _sqlite3_vfs_unregister, + _sqlite3_malloc64, + _sqlite3_realloc, + _sqlite3_realloc64, + _sqlite3_value_text, + _sqlite3_randomness, + _sqlite3_strnicmp, + _sqlite3_uri_parameter, + _sqlite3_uri_boolean, + _sqlite3_serialize, + _sqlite3_column_int64, + _sqlite3_column_int, + _sqlite3_column_name, + _sqlite3_deserialize, + _sqlite3_clear_bindings, + _sqlite3_value_blob, + _sqlite3_value_bytes, + _sqlite3_value_double, + _sqlite3_value_int, + _sqlite3_value_int64, + _sqlite3_value_subtype, + _sqlite3_value_pointer, + _sqlite3_value_type, + _sqlite3_value_nochange, + _sqlite3_value_frombind, + _sqlite3_value_dup, + _sqlite3_value_free, + _sqlite3_result_blob, + _sqlite3_result_error_toobig, + _sqlite3_result_error_nomem, + _sqlite3_result_double, + _sqlite3_result_error, + _sqlite3_result_int, + _sqlite3_result_null, + _sqlite3_result_pointer, + _sqlite3_result_subtype, + _sqlite3_result_text, + _sqlite3_result_zeroblob, + _sqlite3_result_zeroblob64, + _sqlite3_result_error_code, + _sqlite3_user_data, + _sqlite3_context_db_handle, + _sqlite3_vtab_nochange, + _sqlite3_vtab_in_first, + _sqlite3_vtab_in_next, + _sqlite3_aggregate_context, + _sqlite3_get_auxdata, + _sqlite3_set_auxdata, + _sqlite3_data_count, + _sqlite3_column_double, + _sqlite3_column_value, + _sqlite3_column_decltype, + _sqlite3_bind_blob, + _sqlite3_bind_null, + _sqlite3_bind_pointer, + _sqlite3_bind_parameter_count, + _sqlite3_bind_parameter_name, + _sqlite3_bind_parameter_index, + _sqlite3_db_handle, + _sqlite3_stmt_readonly, + _sqlite3_stmt_isexplain, + _sqlite3_stmt_explain, + _sqlite3_stmt_busy, + _sqlite3_stmt_status, + _sqlite3_value_numeric_type, + _sqlite3_strlike, + _sqlite3_auto_extension, + _sqlite3_cancel_auto_extension, + _sqlite3_reset_auto_extension, + _sqlite3_prepare_v3, + _sqlite3_vtab_on_conflict, + _sqlite3_vtab_collation, + _sqlite3_vtab_in, + _sqlite3_vtab_rhs_value, + _sqlite3_vtab_distinct, + _sqlite3_keyword_name, + _sqlite3_keyword_count, + _sqlite3_keyword_check, + _sqlite3_complete, + _sqlite3_shutdown, + _sqlite3_last_insert_rowid, + _sqlite3_set_last_insert_rowid, + _sqlite3_changes64, + _sqlite3_changes, + _sqlite3_total_changes64, + _sqlite3_total_changes, + _sqlite3_txn_state, + _sqlite3_close_v2, + _sqlite3_busy_handler, + _sqlite3_busy_timeout, + _sqlite3_interrupt, + _sqlite3_is_interrupted, + _sqlite3_create_function_v2, + _sqlite3_overload_function, + _sqlite3_trace_v2, + _sqlite3_commit_hook, + _sqlite3_update_hook, + _sqlite3_rollback_hook, + _sqlite3_error_offset, + _sqlite3_errcode, + _sqlite3_extended_errcode, + _sqlite3_errstr, + _sqlite3_limit, + _sqlite3_open, + _sqlite3_create_collation, + _sqlite3_create_collation_v2, + _sqlite3_collation_needed, + _sqlite3_get_autocommit, + _sqlite3_table_column_metadata, + _sqlite3_extended_result_codes, + _sqlite3_uri_key, + _sqlite3_uri_int64, + _sqlite3_db_name, + _sqlite3_db_filename, + _sqlite3_db_readonly, + _sqlite3_compileoption_used, + _sqlite3_compileoption_get, + _sqlite3__wasm_pstack_ptr, + _sqlite3__wasm_pstack_restore, + _sqlite3__wasm_pstack_alloc, + _sqlite3__wasm_pstack_remaining, + _sqlite3__wasm_pstack_quota, + _sqlite3__wasm_db_error, + _sqlite3__wasm_test_struct, + _sqlite3__wasm_enum_json, + _sqlite3__wasm_vfs_unlink, + _sqlite3__wasm_db_vfs, + _sqlite3__wasm_db_reset, + _sqlite3__wasm_db_export_chunked, + _sqlite3__wasm_db_serialize, + _sqlite3__wasm_vfs_create_file, + _sqlite3__wasm_posix_create_file, + _sqlite3__wasm_kvvfsMakeKeyOnPstack, + _sqlite3__wasm_kvvfs_methods, + _sqlite3__wasm_vtab_config, + _sqlite3__wasm_db_config_ip, + _sqlite3__wasm_db_config_pii, + _sqlite3__wasm_db_config_s, + _sqlite3__wasm_config_i, + _sqlite3__wasm_config_ii, + _sqlite3__wasm_config_j, + _sqlite3__wasm_qfmt_token, + _sqlite3__wasm_init_wasmfs, + _sqlite3__wasm_test_intptr, + _sqlite3__wasm_test_voidptr, + _sqlite3__wasm_test_int64_max, + _sqlite3__wasm_test_int64_min, + _sqlite3__wasm_test_int64_times2, + _sqlite3__wasm_test_int64_minmax, + _sqlite3__wasm_test_int64ptr, + _sqlite3__wasm_test_stack_overflow, + _sqlite3__wasm_test_str_hello, + _sqlite3__wasm_SQLTester_strglob, + _realloc, + _emscripten_builtin_memalign, + _setThrew, + __emscripten_stack_restore, + __emscripten_stack_alloc, + _emscripten_stack_get_current, + memory, + __indirect_function_table, + wasmMemory; + + +function assignWasmExports(wasmExports) { + _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find']; + _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; + _sqlite3_finalize = Module['_sqlite3_finalize'] = wasmExports['sqlite3_finalize']; + _sqlite3_exec = Module['_sqlite3_exec'] = wasmExports['sqlite3_exec']; + _sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg']; + _sqlite3_strglob = Module['_sqlite3_strglob'] = wasmExports['sqlite3_strglob']; + _sqlite3_prepare_v2 = Module['_sqlite3_prepare_v2'] = wasmExports['sqlite3_prepare_v2']; + _sqlite3_expanded_sql = Module['_sqlite3_expanded_sql'] = wasmExports['sqlite3_expanded_sql']; + _sqlite3_step = Module['_sqlite3_step'] = wasmExports['sqlite3_step']; + _sqlite3_column_text = Module['_sqlite3_column_text'] = wasmExports['sqlite3_column_text']; + _sqlite3_column_count = Module['_sqlite3_column_count'] = wasmExports['sqlite3_column_count']; + _sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type']; + _sqlite3_column_bytes = Module['_sqlite3_column_bytes'] = wasmExports['sqlite3_column_bytes']; + _sqlite3_column_blob = Module['_sqlite3_column_blob'] = wasmExports['sqlite3_column_blob']; + _sqlite3_sql = Module['_sqlite3_sql'] = wasmExports['sqlite3_sql']; + _sqlite3_reset = Module['_sqlite3_reset'] = wasmExports['sqlite3_reset']; + _sqlite3_bind_int64 = Module['_sqlite3_bind_int64'] = wasmExports['sqlite3_bind_int64']; + _sqlite3_bind_int = Module['_sqlite3_bind_int'] = wasmExports['sqlite3_bind_int']; + _sqlite3_bind_text = Module['_sqlite3_bind_text'] = wasmExports['sqlite3_bind_text']; + _sqlite3_libversion_number = Module['_sqlite3_libversion_number'] = wasmExports['sqlite3_libversion_number']; + _sqlite3_bind_double = Module['_sqlite3_bind_double'] = wasmExports['sqlite3_bind_double']; + _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; + _sqlite3_libversion = Module['_sqlite3_libversion'] = wasmExports['sqlite3_libversion']; + _sqlite3_sourceid = Module['_sqlite3_sourceid'] = wasmExports['sqlite3_sourceid']; + _malloc = Module['_malloc'] = wasmExports['malloc']; + _sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize']; + _sqlite3_open_v2 = Module['_sqlite3_open_v2'] = wasmExports['sqlite3_open_v2']; + _sqlite3_file_control = Module['_sqlite3_file_control'] = wasmExports['sqlite3_file_control']; + _sqlite3_create_function = Module['_sqlite3_create_function'] = wasmExports['sqlite3_create_function']; + _sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status']; + _sqlite3_status = Module['_sqlite3_status'] = wasmExports['sqlite3_status']; + _free = Module['_free'] = wasmExports['free']; + _sqlite3_stricmp = Module['_sqlite3_stricmp'] = wasmExports['sqlite3_stricmp']; + _sqlite3_result_int64 = Module['_sqlite3_result_int64'] = wasmExports['sqlite3_result_int64']; + _wasm_main = Module['_wasm_main'] = wasmExports['wasm_main']; + _sqlite3_status64 = Module['_sqlite3_status64'] = wasmExports['sqlite3_status64']; + _sqlite3_msize = Module['_sqlite3_msize'] = wasmExports['sqlite3_msize']; + _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register']; + _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister']; + _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64']; + _sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc']; + _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64']; + _sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text']; + _sqlite3_randomness = Module['_sqlite3_randomness'] = wasmExports['sqlite3_randomness']; + _sqlite3_strnicmp = Module['_sqlite3_strnicmp'] = wasmExports['sqlite3_strnicmp']; + _sqlite3_uri_parameter = Module['_sqlite3_uri_parameter'] = wasmExports['sqlite3_uri_parameter']; + _sqlite3_uri_boolean = Module['_sqlite3_uri_boolean'] = wasmExports['sqlite3_uri_boolean']; + _sqlite3_serialize = Module['_sqlite3_serialize'] = wasmExports['sqlite3_serialize']; + _sqlite3_column_int64 = Module['_sqlite3_column_int64'] = wasmExports['sqlite3_column_int64']; + _sqlite3_column_int = Module['_sqlite3_column_int'] = wasmExports['sqlite3_column_int']; + _sqlite3_column_name = Module['_sqlite3_column_name'] = wasmExports['sqlite3_column_name']; + _sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize']; + _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings']; + _sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob']; + _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes']; + _sqlite3_value_double = Module['_sqlite3_value_double'] = wasmExports['sqlite3_value_double']; + _sqlite3_value_int = Module['_sqlite3_value_int'] = wasmExports['sqlite3_value_int']; + _sqlite3_value_int64 = Module['_sqlite3_value_int64'] = wasmExports['sqlite3_value_int64']; + _sqlite3_value_subtype = Module['_sqlite3_value_subtype'] = wasmExports['sqlite3_value_subtype']; + _sqlite3_value_pointer = Module['_sqlite3_value_pointer'] = wasmExports['sqlite3_value_pointer']; + _sqlite3_value_type = Module['_sqlite3_value_type'] = wasmExports['sqlite3_value_type']; + _sqlite3_value_nochange = Module['_sqlite3_value_nochange'] = wasmExports['sqlite3_value_nochange']; + _sqlite3_value_frombind = Module['_sqlite3_value_frombind'] = wasmExports['sqlite3_value_frombind']; + _sqlite3_value_dup = Module['_sqlite3_value_dup'] = wasmExports['sqlite3_value_dup']; + _sqlite3_value_free = Module['_sqlite3_value_free'] = wasmExports['sqlite3_value_free']; + _sqlite3_result_blob = Module['_sqlite3_result_blob'] = wasmExports['sqlite3_result_blob']; + _sqlite3_result_error_toobig = Module['_sqlite3_result_error_toobig'] = wasmExports['sqlite3_result_error_toobig']; + _sqlite3_result_error_nomem = Module['_sqlite3_result_error_nomem'] = wasmExports['sqlite3_result_error_nomem']; + _sqlite3_result_double = Module['_sqlite3_result_double'] = wasmExports['sqlite3_result_double']; + _sqlite3_result_error = Module['_sqlite3_result_error'] = wasmExports['sqlite3_result_error']; + _sqlite3_result_int = Module['_sqlite3_result_int'] = wasmExports['sqlite3_result_int']; + _sqlite3_result_null = Module['_sqlite3_result_null'] = wasmExports['sqlite3_result_null']; + _sqlite3_result_pointer = Module['_sqlite3_result_pointer'] = wasmExports['sqlite3_result_pointer']; + _sqlite3_result_subtype = Module['_sqlite3_result_subtype'] = wasmExports['sqlite3_result_subtype']; + _sqlite3_result_text = Module['_sqlite3_result_text'] = wasmExports['sqlite3_result_text']; + _sqlite3_result_zeroblob = Module['_sqlite3_result_zeroblob'] = wasmExports['sqlite3_result_zeroblob']; + _sqlite3_result_zeroblob64 = Module['_sqlite3_result_zeroblob64'] = wasmExports['sqlite3_result_zeroblob64']; + _sqlite3_result_error_code = Module['_sqlite3_result_error_code'] = wasmExports['sqlite3_result_error_code']; + _sqlite3_user_data = Module['_sqlite3_user_data'] = wasmExports['sqlite3_user_data']; + _sqlite3_context_db_handle = Module['_sqlite3_context_db_handle'] = wasmExports['sqlite3_context_db_handle']; + _sqlite3_vtab_nochange = Module['_sqlite3_vtab_nochange'] = wasmExports['sqlite3_vtab_nochange']; + _sqlite3_vtab_in_first = Module['_sqlite3_vtab_in_first'] = wasmExports['sqlite3_vtab_in_first']; + _sqlite3_vtab_in_next = Module['_sqlite3_vtab_in_next'] = wasmExports['sqlite3_vtab_in_next']; + _sqlite3_aggregate_context = Module['_sqlite3_aggregate_context'] = wasmExports['sqlite3_aggregate_context']; + _sqlite3_get_auxdata = Module['_sqlite3_get_auxdata'] = wasmExports['sqlite3_get_auxdata']; + _sqlite3_set_auxdata = Module['_sqlite3_set_auxdata'] = wasmExports['sqlite3_set_auxdata']; + _sqlite3_data_count = Module['_sqlite3_data_count'] = wasmExports['sqlite3_data_count']; + _sqlite3_column_double = Module['_sqlite3_column_double'] = wasmExports['sqlite3_column_double']; + _sqlite3_column_value = Module['_sqlite3_column_value'] = wasmExports['sqlite3_column_value']; + _sqlite3_column_decltype = Module['_sqlite3_column_decltype'] = wasmExports['sqlite3_column_decltype']; + _sqlite3_bind_blob = Module['_sqlite3_bind_blob'] = wasmExports['sqlite3_bind_blob']; + _sqlite3_bind_null = Module['_sqlite3_bind_null'] = wasmExports['sqlite3_bind_null']; + _sqlite3_bind_pointer = Module['_sqlite3_bind_pointer'] = wasmExports['sqlite3_bind_pointer']; + _sqlite3_bind_parameter_count = Module['_sqlite3_bind_parameter_count'] = wasmExports['sqlite3_bind_parameter_count']; + _sqlite3_bind_parameter_name = Module['_sqlite3_bind_parameter_name'] = wasmExports['sqlite3_bind_parameter_name']; + _sqlite3_bind_parameter_index = Module['_sqlite3_bind_parameter_index'] = wasmExports['sqlite3_bind_parameter_index']; + _sqlite3_db_handle = Module['_sqlite3_db_handle'] = wasmExports['sqlite3_db_handle']; + _sqlite3_stmt_readonly = Module['_sqlite3_stmt_readonly'] = wasmExports['sqlite3_stmt_readonly']; + _sqlite3_stmt_isexplain = Module['_sqlite3_stmt_isexplain'] = wasmExports['sqlite3_stmt_isexplain']; + _sqlite3_stmt_explain = Module['_sqlite3_stmt_explain'] = wasmExports['sqlite3_stmt_explain']; + _sqlite3_stmt_busy = Module['_sqlite3_stmt_busy'] = wasmExports['sqlite3_stmt_busy']; + _sqlite3_stmt_status = Module['_sqlite3_stmt_status'] = wasmExports['sqlite3_stmt_status']; + _sqlite3_value_numeric_type = Module['_sqlite3_value_numeric_type'] = wasmExports['sqlite3_value_numeric_type']; + _sqlite3_strlike = Module['_sqlite3_strlike'] = wasmExports['sqlite3_strlike']; + _sqlite3_auto_extension = Module['_sqlite3_auto_extension'] = wasmExports['sqlite3_auto_extension']; + _sqlite3_cancel_auto_extension = Module['_sqlite3_cancel_auto_extension'] = wasmExports['sqlite3_cancel_auto_extension']; + _sqlite3_reset_auto_extension = Module['_sqlite3_reset_auto_extension'] = wasmExports['sqlite3_reset_auto_extension']; + _sqlite3_prepare_v3 = Module['_sqlite3_prepare_v3'] = wasmExports['sqlite3_prepare_v3']; + _sqlite3_vtab_on_conflict = Module['_sqlite3_vtab_on_conflict'] = wasmExports['sqlite3_vtab_on_conflict']; + _sqlite3_vtab_collation = Module['_sqlite3_vtab_collation'] = wasmExports['sqlite3_vtab_collation']; + _sqlite3_vtab_in = Module['_sqlite3_vtab_in'] = wasmExports['sqlite3_vtab_in']; + _sqlite3_vtab_rhs_value = Module['_sqlite3_vtab_rhs_value'] = wasmExports['sqlite3_vtab_rhs_value']; + _sqlite3_vtab_distinct = Module['_sqlite3_vtab_distinct'] = wasmExports['sqlite3_vtab_distinct']; + _sqlite3_keyword_name = Module['_sqlite3_keyword_name'] = wasmExports['sqlite3_keyword_name']; + _sqlite3_keyword_count = Module['_sqlite3_keyword_count'] = wasmExports['sqlite3_keyword_count']; + _sqlite3_keyword_check = Module['_sqlite3_keyword_check'] = wasmExports['sqlite3_keyword_check']; + _sqlite3_complete = Module['_sqlite3_complete'] = wasmExports['sqlite3_complete']; + _sqlite3_shutdown = Module['_sqlite3_shutdown'] = wasmExports['sqlite3_shutdown']; + _sqlite3_last_insert_rowid = Module['_sqlite3_last_insert_rowid'] = wasmExports['sqlite3_last_insert_rowid']; + _sqlite3_set_last_insert_rowid = Module['_sqlite3_set_last_insert_rowid'] = wasmExports['sqlite3_set_last_insert_rowid']; + _sqlite3_changes64 = Module['_sqlite3_changes64'] = wasmExports['sqlite3_changes64']; + _sqlite3_changes = Module['_sqlite3_changes'] = wasmExports['sqlite3_changes']; + _sqlite3_total_changes64 = Module['_sqlite3_total_changes64'] = wasmExports['sqlite3_total_changes64']; + _sqlite3_total_changes = Module['_sqlite3_total_changes'] = wasmExports['sqlite3_total_changes']; + _sqlite3_txn_state = Module['_sqlite3_txn_state'] = wasmExports['sqlite3_txn_state']; + _sqlite3_close_v2 = Module['_sqlite3_close_v2'] = wasmExports['sqlite3_close_v2']; + _sqlite3_busy_handler = Module['_sqlite3_busy_handler'] = wasmExports['sqlite3_busy_handler']; + _sqlite3_busy_timeout = Module['_sqlite3_busy_timeout'] = wasmExports['sqlite3_busy_timeout']; + _sqlite3_interrupt = Module['_sqlite3_interrupt'] = wasmExports['sqlite3_interrupt']; + _sqlite3_is_interrupted = Module['_sqlite3_is_interrupted'] = wasmExports['sqlite3_is_interrupted']; + _sqlite3_create_function_v2 = Module['_sqlite3_create_function_v2'] = wasmExports['sqlite3_create_function_v2']; + _sqlite3_overload_function = Module['_sqlite3_overload_function'] = wasmExports['sqlite3_overload_function']; + _sqlite3_trace_v2 = Module['_sqlite3_trace_v2'] = wasmExports['sqlite3_trace_v2']; + _sqlite3_commit_hook = Module['_sqlite3_commit_hook'] = wasmExports['sqlite3_commit_hook']; + _sqlite3_update_hook = Module['_sqlite3_update_hook'] = wasmExports['sqlite3_update_hook']; + _sqlite3_rollback_hook = Module['_sqlite3_rollback_hook'] = wasmExports['sqlite3_rollback_hook']; + _sqlite3_error_offset = Module['_sqlite3_error_offset'] = wasmExports['sqlite3_error_offset']; + _sqlite3_errcode = Module['_sqlite3_errcode'] = wasmExports['sqlite3_errcode']; + _sqlite3_extended_errcode = Module['_sqlite3_extended_errcode'] = wasmExports['sqlite3_extended_errcode']; + _sqlite3_errstr = Module['_sqlite3_errstr'] = wasmExports['sqlite3_errstr']; + _sqlite3_limit = Module['_sqlite3_limit'] = wasmExports['sqlite3_limit']; + _sqlite3_open = Module['_sqlite3_open'] = wasmExports['sqlite3_open']; + _sqlite3_create_collation = Module['_sqlite3_create_collation'] = wasmExports['sqlite3_create_collation']; + _sqlite3_create_collation_v2 = Module['_sqlite3_create_collation_v2'] = wasmExports['sqlite3_create_collation_v2']; + _sqlite3_collation_needed = Module['_sqlite3_collation_needed'] = wasmExports['sqlite3_collation_needed']; + _sqlite3_get_autocommit = Module['_sqlite3_get_autocommit'] = wasmExports['sqlite3_get_autocommit']; + _sqlite3_table_column_metadata = Module['_sqlite3_table_column_metadata'] = wasmExports['sqlite3_table_column_metadata']; + _sqlite3_extended_result_codes = Module['_sqlite3_extended_result_codes'] = wasmExports['sqlite3_extended_result_codes']; + _sqlite3_uri_key = Module['_sqlite3_uri_key'] = wasmExports['sqlite3_uri_key']; + _sqlite3_uri_int64 = Module['_sqlite3_uri_int64'] = wasmExports['sqlite3_uri_int64']; + _sqlite3_db_name = Module['_sqlite3_db_name'] = wasmExports['sqlite3_db_name']; + _sqlite3_db_filename = Module['_sqlite3_db_filename'] = wasmExports['sqlite3_db_filename']; + _sqlite3_db_readonly = Module['_sqlite3_db_readonly'] = wasmExports['sqlite3_db_readonly']; + _sqlite3_compileoption_used = Module['_sqlite3_compileoption_used'] = wasmExports['sqlite3_compileoption_used']; + _sqlite3_compileoption_get = Module['_sqlite3_compileoption_get'] = wasmExports['sqlite3_compileoption_get']; + _sqlite3__wasm_pstack_ptr = Module['_sqlite3__wasm_pstack_ptr'] = wasmExports['sqlite3__wasm_pstack_ptr']; + _sqlite3__wasm_pstack_restore = Module['_sqlite3__wasm_pstack_restore'] = wasmExports['sqlite3__wasm_pstack_restore']; + _sqlite3__wasm_pstack_alloc = Module['_sqlite3__wasm_pstack_alloc'] = wasmExports['sqlite3__wasm_pstack_alloc']; + _sqlite3__wasm_pstack_remaining = Module['_sqlite3__wasm_pstack_remaining'] = wasmExports['sqlite3__wasm_pstack_remaining']; + _sqlite3__wasm_pstack_quota = Module['_sqlite3__wasm_pstack_quota'] = wasmExports['sqlite3__wasm_pstack_quota']; + _sqlite3__wasm_db_error = Module['_sqlite3__wasm_db_error'] = wasmExports['sqlite3__wasm_db_error']; + _sqlite3__wasm_test_struct = Module['_sqlite3__wasm_test_struct'] = wasmExports['sqlite3__wasm_test_struct']; + _sqlite3__wasm_enum_json = Module['_sqlite3__wasm_enum_json'] = wasmExports['sqlite3__wasm_enum_json']; + _sqlite3__wasm_vfs_unlink = Module['_sqlite3__wasm_vfs_unlink'] = wasmExports['sqlite3__wasm_vfs_unlink']; + _sqlite3__wasm_db_vfs = Module['_sqlite3__wasm_db_vfs'] = wasmExports['sqlite3__wasm_db_vfs']; + _sqlite3__wasm_db_reset = Module['_sqlite3__wasm_db_reset'] = wasmExports['sqlite3__wasm_db_reset']; + _sqlite3__wasm_db_export_chunked = Module['_sqlite3__wasm_db_export_chunked'] = wasmExports['sqlite3__wasm_db_export_chunked']; + _sqlite3__wasm_db_serialize = Module['_sqlite3__wasm_db_serialize'] = wasmExports['sqlite3__wasm_db_serialize']; + _sqlite3__wasm_vfs_create_file = Module['_sqlite3__wasm_vfs_create_file'] = wasmExports['sqlite3__wasm_vfs_create_file']; + _sqlite3__wasm_posix_create_file = Module['_sqlite3__wasm_posix_create_file'] = wasmExports['sqlite3__wasm_posix_create_file']; + _sqlite3__wasm_kvvfsMakeKeyOnPstack = Module['_sqlite3__wasm_kvvfsMakeKeyOnPstack'] = wasmExports['sqlite3__wasm_kvvfsMakeKeyOnPstack']; + _sqlite3__wasm_kvvfs_methods = Module['_sqlite3__wasm_kvvfs_methods'] = wasmExports['sqlite3__wasm_kvvfs_methods']; + _sqlite3__wasm_vtab_config = Module['_sqlite3__wasm_vtab_config'] = wasmExports['sqlite3__wasm_vtab_config']; + _sqlite3__wasm_db_config_ip = Module['_sqlite3__wasm_db_config_ip'] = wasmExports['sqlite3__wasm_db_config_ip']; + _sqlite3__wasm_db_config_pii = Module['_sqlite3__wasm_db_config_pii'] = wasmExports['sqlite3__wasm_db_config_pii']; + _sqlite3__wasm_db_config_s = Module['_sqlite3__wasm_db_config_s'] = wasmExports['sqlite3__wasm_db_config_s']; + _sqlite3__wasm_config_i = Module['_sqlite3__wasm_config_i'] = wasmExports['sqlite3__wasm_config_i']; + _sqlite3__wasm_config_ii = Module['_sqlite3__wasm_config_ii'] = wasmExports['sqlite3__wasm_config_ii']; + _sqlite3__wasm_config_j = Module['_sqlite3__wasm_config_j'] = wasmExports['sqlite3__wasm_config_j']; + _sqlite3__wasm_qfmt_token = Module['_sqlite3__wasm_qfmt_token'] = wasmExports['sqlite3__wasm_qfmt_token']; + _sqlite3__wasm_init_wasmfs = Module['_sqlite3__wasm_init_wasmfs'] = wasmExports['sqlite3__wasm_init_wasmfs']; + _sqlite3__wasm_test_intptr = Module['_sqlite3__wasm_test_intptr'] = wasmExports['sqlite3__wasm_test_intptr']; + _sqlite3__wasm_test_voidptr = Module['_sqlite3__wasm_test_voidptr'] = wasmExports['sqlite3__wasm_test_voidptr']; + _sqlite3__wasm_test_int64_max = Module['_sqlite3__wasm_test_int64_max'] = wasmExports['sqlite3__wasm_test_int64_max']; + _sqlite3__wasm_test_int64_min = Module['_sqlite3__wasm_test_int64_min'] = wasmExports['sqlite3__wasm_test_int64_min']; + _sqlite3__wasm_test_int64_times2 = Module['_sqlite3__wasm_test_int64_times2'] = wasmExports['sqlite3__wasm_test_int64_times2']; + _sqlite3__wasm_test_int64_minmax = Module['_sqlite3__wasm_test_int64_minmax'] = wasmExports['sqlite3__wasm_test_int64_minmax']; + _sqlite3__wasm_test_int64ptr = Module['_sqlite3__wasm_test_int64ptr'] = wasmExports['sqlite3__wasm_test_int64ptr']; + _sqlite3__wasm_test_stack_overflow = Module['_sqlite3__wasm_test_stack_overflow'] = wasmExports['sqlite3__wasm_test_stack_overflow']; + _sqlite3__wasm_test_str_hello = Module['_sqlite3__wasm_test_str_hello'] = wasmExports['sqlite3__wasm_test_str_hello']; + _sqlite3__wasm_SQLTester_strglob = Module['_sqlite3__wasm_SQLTester_strglob'] = wasmExports['sqlite3__wasm_SQLTester_strglob']; + _realloc = Module['_realloc'] = wasmExports['realloc']; + _emscripten_builtin_memalign = wasmExports['emscripten_builtin_memalign']; + _setThrew = wasmExports['setThrew']; + __emscripten_stack_restore = wasmExports['_emscripten_stack_restore']; + __emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc']; + _emscripten_stack_get_current = wasmExports['emscripten_stack_get_current']; + memory = wasmMemory = Module['wasmMemory'] = wasmExports['memory']; + __indirect_function_table = wasmExports['__indirect_function_table']; +} - // This error may happen quite a bit. To avoid overhead we reuse it (and - // suffer a lack of stack info). - MEMFS.doesNotExistError = new FS.ErrnoError(44); - /** @suppress {checkTypes} */ - MEMFS.doesNotExistError.stack = ''; - ; var wasmImports = { /** @export */ __assert_fail: ___assert_fail, @@ -4097,6 +4541,8 @@ var wasmImports = { /** @export */ __syscall_getcwd: ___syscall_getcwd, /** @export */ + __syscall_geteuid32: ___syscall_geteuid32, + /** @export */ __syscall_ioctl: ___syscall_ioctl, /** @export */ __syscall_lstat64: ___syscall_lstat64, @@ -4117,8 +4563,6 @@ var wasmImports = { /** @export */ __syscall_utimensat: ___syscall_utimensat, /** @export */ - _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, - /** @export */ _localtime_js: __localtime_js, /** @export */ _mmap_js: __mmap_js, @@ -4127,6 +4571,8 @@ var wasmImports = { /** @export */ _tzset_js: __tzset_js, /** @export */ + clock_time_get: _clock_time_get, + /** @export */ emscripten_date_now: _emscripten_date_now, /** @export */ emscripten_get_now: _emscripten_get_now, @@ -4151,274 +4597,36 @@ var wasmImports = { /** @export */ fd_write: _fd_write }; -var wasmExports = createWasm(); -var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports['__wasm_call_ctors'])(); -var _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = (a0) => (_sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find'])(a0); -var _sqlite3_free = Module['_sqlite3_free'] = (a0) => (_sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free'])(a0); -var _sqlite3_finalize = Module['_sqlite3_finalize'] = (a0) => (_sqlite3_finalize = Module['_sqlite3_finalize'] = wasmExports['sqlite3_finalize'])(a0); -var _sqlite3_exec = Module['_sqlite3_exec'] = (a0, a1, a2, a3, a4) => (_sqlite3_exec = Module['_sqlite3_exec'] = wasmExports['sqlite3_exec'])(a0, a1, a2, a3, a4); -var _sqlite3_errmsg = Module['_sqlite3_errmsg'] = (a0) => (_sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg'])(a0); -var _sqlite3_strglob = Module['_sqlite3_strglob'] = (a0, a1) => (_sqlite3_strglob = Module['_sqlite3_strglob'] = wasmExports['sqlite3_strglob'])(a0, a1); -var _sqlite3_prepare_v2 = Module['_sqlite3_prepare_v2'] = (a0, a1, a2, a3, a4) => (_sqlite3_prepare_v2 = Module['_sqlite3_prepare_v2'] = wasmExports['sqlite3_prepare_v2'])(a0, a1, a2, a3, a4); -var _sqlite3_expanded_sql = Module['_sqlite3_expanded_sql'] = (a0) => (_sqlite3_expanded_sql = Module['_sqlite3_expanded_sql'] = wasmExports['sqlite3_expanded_sql'])(a0); -var _sqlite3_step = Module['_sqlite3_step'] = (a0) => (_sqlite3_step = Module['_sqlite3_step'] = wasmExports['sqlite3_step'])(a0); -var _sqlite3_column_text = Module['_sqlite3_column_text'] = (a0, a1) => (_sqlite3_column_text = Module['_sqlite3_column_text'] = wasmExports['sqlite3_column_text'])(a0, a1); -var _sqlite3_column_count = Module['_sqlite3_column_count'] = (a0) => (_sqlite3_column_count = Module['_sqlite3_column_count'] = wasmExports['sqlite3_column_count'])(a0); -var _sqlite3_column_type = Module['_sqlite3_column_type'] = (a0, a1) => (_sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type'])(a0, a1); -var _sqlite3_column_bytes = Module['_sqlite3_column_bytes'] = (a0, a1) => (_sqlite3_column_bytes = Module['_sqlite3_column_bytes'] = wasmExports['sqlite3_column_bytes'])(a0, a1); -var _sqlite3_column_blob = Module['_sqlite3_column_blob'] = (a0, a1) => (_sqlite3_column_blob = Module['_sqlite3_column_blob'] = wasmExports['sqlite3_column_blob'])(a0, a1); -var _sqlite3_sql = Module['_sqlite3_sql'] = (a0) => (_sqlite3_sql = Module['_sqlite3_sql'] = wasmExports['sqlite3_sql'])(a0); -var _sqlite3_reset = Module['_sqlite3_reset'] = (a0) => (_sqlite3_reset = Module['_sqlite3_reset'] = wasmExports['sqlite3_reset'])(a0); -var _sqlite3_bind_int64 = Module['_sqlite3_bind_int64'] = (a0, a1, a2) => (_sqlite3_bind_int64 = Module['_sqlite3_bind_int64'] = wasmExports['sqlite3_bind_int64'])(a0, a1, a2); -var _sqlite3_bind_int = Module['_sqlite3_bind_int'] = (a0, a1, a2) => (_sqlite3_bind_int = Module['_sqlite3_bind_int'] = wasmExports['sqlite3_bind_int'])(a0, a1, a2); -var _sqlite3_bind_text = Module['_sqlite3_bind_text'] = (a0, a1, a2, a3, a4) => (_sqlite3_bind_text = Module['_sqlite3_bind_text'] = wasmExports['sqlite3_bind_text'])(a0, a1, a2, a3, a4); -var _sqlite3_libversion_number = Module['_sqlite3_libversion_number'] = () => (_sqlite3_libversion_number = Module['_sqlite3_libversion_number'] = wasmExports['sqlite3_libversion_number'])(); -var _sqlite3_bind_double = Module['_sqlite3_bind_double'] = (a0, a1, a2) => (_sqlite3_bind_double = Module['_sqlite3_bind_double'] = wasmExports['sqlite3_bind_double'])(a0, a1, a2); -var _sqlite3_malloc = Module['_sqlite3_malloc'] = (a0) => (_sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc'])(a0); -var _sqlite3_libversion = Module['_sqlite3_libversion'] = () => (_sqlite3_libversion = Module['_sqlite3_libversion'] = wasmExports['sqlite3_libversion'])(); -var _sqlite3_sourceid = Module['_sqlite3_sourceid'] = () => (_sqlite3_sourceid = Module['_sqlite3_sourceid'] = wasmExports['sqlite3_sourceid'])(); -var _malloc = Module['_malloc'] = (a0) => (_malloc = Module['_malloc'] = wasmExports['malloc'])(a0); -var _sqlite3_initialize = Module['_sqlite3_initialize'] = () => (_sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize'])(); -var _sqlite3_open_v2 = Module['_sqlite3_open_v2'] = (a0, a1, a2, a3) => (_sqlite3_open_v2 = Module['_sqlite3_open_v2'] = wasmExports['sqlite3_open_v2'])(a0, a1, a2, a3); -var _sqlite3_file_control = Module['_sqlite3_file_control'] = (a0, a1, a2, a3) => (_sqlite3_file_control = Module['_sqlite3_file_control'] = wasmExports['sqlite3_file_control'])(a0, a1, a2, a3); -var _sqlite3_create_function = Module['_sqlite3_create_function'] = (a0, a1, a2, a3, a4, a5, a6, a7) => (_sqlite3_create_function = Module['_sqlite3_create_function'] = wasmExports['sqlite3_create_function'])(a0, a1, a2, a3, a4, a5, a6, a7); -var _sqlite3_db_status = Module['_sqlite3_db_status'] = (a0, a1, a2, a3, a4) => (_sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status'])(a0, a1, a2, a3, a4); -var _sqlite3_status = Module['_sqlite3_status'] = (a0, a1, a2, a3) => (_sqlite3_status = Module['_sqlite3_status'] = wasmExports['sqlite3_status'])(a0, a1, a2, a3); -var _free = Module['_free'] = (a0) => (_free = Module['_free'] = wasmExports['free'])(a0); -var _sqlite3_stricmp = Module['_sqlite3_stricmp'] = (a0, a1) => (_sqlite3_stricmp = Module['_sqlite3_stricmp'] = wasmExports['sqlite3_stricmp'])(a0, a1); -var _sqlite3_result_int64 = Module['_sqlite3_result_int64'] = (a0, a1) => (_sqlite3_result_int64 = Module['_sqlite3_result_int64'] = wasmExports['sqlite3_result_int64'])(a0, a1); -var _wasm_main = Module['_wasm_main'] = (a0, a1) => (_wasm_main = Module['_wasm_main'] = wasmExports['wasm_main'])(a0, a1); -var _sqlite3_status64 = Module['_sqlite3_status64'] = (a0, a1, a2, a3) => (_sqlite3_status64 = Module['_sqlite3_status64'] = wasmExports['sqlite3_status64'])(a0, a1, a2, a3); -var _sqlite3_msize = Module['_sqlite3_msize'] = (a0) => (_sqlite3_msize = Module['_sqlite3_msize'] = wasmExports['sqlite3_msize'])(a0); -var _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = (a0, a1) => (_sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register'])(a0, a1); -var _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = (a0) => (_sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister'])(a0); -var _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = (a0) => (_sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64'])(a0); -var _sqlite3_realloc = Module['_sqlite3_realloc'] = (a0, a1) => (_sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc'])(a0, a1); -var _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = (a0, a1) => (_sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64'])(a0, a1); -var _sqlite3_value_text = Module['_sqlite3_value_text'] = (a0) => (_sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text'])(a0); -var _sqlite3_randomness = Module['_sqlite3_randomness'] = (a0, a1) => (_sqlite3_randomness = Module['_sqlite3_randomness'] = wasmExports['sqlite3_randomness'])(a0, a1); -var _sqlite3_strnicmp = Module['_sqlite3_strnicmp'] = (a0, a1, a2) => (_sqlite3_strnicmp = Module['_sqlite3_strnicmp'] = wasmExports['sqlite3_strnicmp'])(a0, a1, a2); -var _sqlite3_uri_parameter = Module['_sqlite3_uri_parameter'] = (a0, a1) => (_sqlite3_uri_parameter = Module['_sqlite3_uri_parameter'] = wasmExports['sqlite3_uri_parameter'])(a0, a1); -var _sqlite3_uri_boolean = Module['_sqlite3_uri_boolean'] = (a0, a1, a2) => (_sqlite3_uri_boolean = Module['_sqlite3_uri_boolean'] = wasmExports['sqlite3_uri_boolean'])(a0, a1, a2); -var _sqlite3_serialize = Module['_sqlite3_serialize'] = (a0, a1, a2, a3) => (_sqlite3_serialize = Module['_sqlite3_serialize'] = wasmExports['sqlite3_serialize'])(a0, a1, a2, a3); -var _sqlite3_column_int64 = Module['_sqlite3_column_int64'] = (a0, a1) => (_sqlite3_column_int64 = Module['_sqlite3_column_int64'] = wasmExports['sqlite3_column_int64'])(a0, a1); -var _sqlite3_column_int = Module['_sqlite3_column_int'] = (a0, a1) => (_sqlite3_column_int = Module['_sqlite3_column_int'] = wasmExports['sqlite3_column_int'])(a0, a1); -var _sqlite3_column_name = Module['_sqlite3_column_name'] = (a0, a1) => (_sqlite3_column_name = Module['_sqlite3_column_name'] = wasmExports['sqlite3_column_name'])(a0, a1); -var _sqlite3_deserialize = Module['_sqlite3_deserialize'] = (a0, a1, a2, a3, a4, a5) => (_sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize'])(a0, a1, a2, a3, a4, a5); -var _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = (a0) => (_sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings'])(a0); -var _sqlite3_value_blob = Module['_sqlite3_value_blob'] = (a0) => (_sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob'])(a0); -var _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = (a0) => (_sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes'])(a0); -var _sqlite3_value_double = Module['_sqlite3_value_double'] = (a0) => (_sqlite3_value_double = Module['_sqlite3_value_double'] = wasmExports['sqlite3_value_double'])(a0); -var _sqlite3_value_int = Module['_sqlite3_value_int'] = (a0) => (_sqlite3_value_int = Module['_sqlite3_value_int'] = wasmExports['sqlite3_value_int'])(a0); -var _sqlite3_value_int64 = Module['_sqlite3_value_int64'] = (a0) => (_sqlite3_value_int64 = Module['_sqlite3_value_int64'] = wasmExports['sqlite3_value_int64'])(a0); -var _sqlite3_value_subtype = Module['_sqlite3_value_subtype'] = (a0) => (_sqlite3_value_subtype = Module['_sqlite3_value_subtype'] = wasmExports['sqlite3_value_subtype'])(a0); -var _sqlite3_value_pointer = Module['_sqlite3_value_pointer'] = (a0, a1) => (_sqlite3_value_pointer = Module['_sqlite3_value_pointer'] = wasmExports['sqlite3_value_pointer'])(a0, a1); -var _sqlite3_value_type = Module['_sqlite3_value_type'] = (a0) => (_sqlite3_value_type = Module['_sqlite3_value_type'] = wasmExports['sqlite3_value_type'])(a0); -var _sqlite3_value_nochange = Module['_sqlite3_value_nochange'] = (a0) => (_sqlite3_value_nochange = Module['_sqlite3_value_nochange'] = wasmExports['sqlite3_value_nochange'])(a0); -var _sqlite3_value_frombind = Module['_sqlite3_value_frombind'] = (a0) => (_sqlite3_value_frombind = Module['_sqlite3_value_frombind'] = wasmExports['sqlite3_value_frombind'])(a0); -var _sqlite3_value_dup = Module['_sqlite3_value_dup'] = (a0) => (_sqlite3_value_dup = Module['_sqlite3_value_dup'] = wasmExports['sqlite3_value_dup'])(a0); -var _sqlite3_value_free = Module['_sqlite3_value_free'] = (a0) => (_sqlite3_value_free = Module['_sqlite3_value_free'] = wasmExports['sqlite3_value_free'])(a0); -var _sqlite3_result_blob = Module['_sqlite3_result_blob'] = (a0, a1, a2, a3) => (_sqlite3_result_blob = Module['_sqlite3_result_blob'] = wasmExports['sqlite3_result_blob'])(a0, a1, a2, a3); -var _sqlite3_result_error_toobig = Module['_sqlite3_result_error_toobig'] = (a0) => (_sqlite3_result_error_toobig = Module['_sqlite3_result_error_toobig'] = wasmExports['sqlite3_result_error_toobig'])(a0); -var _sqlite3_result_error_nomem = Module['_sqlite3_result_error_nomem'] = (a0) => (_sqlite3_result_error_nomem = Module['_sqlite3_result_error_nomem'] = wasmExports['sqlite3_result_error_nomem'])(a0); -var _sqlite3_result_double = Module['_sqlite3_result_double'] = (a0, a1) => (_sqlite3_result_double = Module['_sqlite3_result_double'] = wasmExports['sqlite3_result_double'])(a0, a1); -var _sqlite3_result_error = Module['_sqlite3_result_error'] = (a0, a1, a2) => (_sqlite3_result_error = Module['_sqlite3_result_error'] = wasmExports['sqlite3_result_error'])(a0, a1, a2); -var _sqlite3_result_int = Module['_sqlite3_result_int'] = (a0, a1) => (_sqlite3_result_int = Module['_sqlite3_result_int'] = wasmExports['sqlite3_result_int'])(a0, a1); -var _sqlite3_result_null = Module['_sqlite3_result_null'] = (a0) => (_sqlite3_result_null = Module['_sqlite3_result_null'] = wasmExports['sqlite3_result_null'])(a0); -var _sqlite3_result_pointer = Module['_sqlite3_result_pointer'] = (a0, a1, a2, a3) => (_sqlite3_result_pointer = Module['_sqlite3_result_pointer'] = wasmExports['sqlite3_result_pointer'])(a0, a1, a2, a3); -var _sqlite3_result_subtype = Module['_sqlite3_result_subtype'] = (a0, a1) => (_sqlite3_result_subtype = Module['_sqlite3_result_subtype'] = wasmExports['sqlite3_result_subtype'])(a0, a1); -var _sqlite3_result_text = Module['_sqlite3_result_text'] = (a0, a1, a2, a3) => (_sqlite3_result_text = Module['_sqlite3_result_text'] = wasmExports['sqlite3_result_text'])(a0, a1, a2, a3); -var _sqlite3_result_zeroblob = Module['_sqlite3_result_zeroblob'] = (a0, a1) => (_sqlite3_result_zeroblob = Module['_sqlite3_result_zeroblob'] = wasmExports['sqlite3_result_zeroblob'])(a0, a1); -var _sqlite3_result_zeroblob64 = Module['_sqlite3_result_zeroblob64'] = (a0, a1) => (_sqlite3_result_zeroblob64 = Module['_sqlite3_result_zeroblob64'] = wasmExports['sqlite3_result_zeroblob64'])(a0, a1); -var _sqlite3_result_error_code = Module['_sqlite3_result_error_code'] = (a0, a1) => (_sqlite3_result_error_code = Module['_sqlite3_result_error_code'] = wasmExports['sqlite3_result_error_code'])(a0, a1); -var _sqlite3_user_data = Module['_sqlite3_user_data'] = (a0) => (_sqlite3_user_data = Module['_sqlite3_user_data'] = wasmExports['sqlite3_user_data'])(a0); -var _sqlite3_context_db_handle = Module['_sqlite3_context_db_handle'] = (a0) => (_sqlite3_context_db_handle = Module['_sqlite3_context_db_handle'] = wasmExports['sqlite3_context_db_handle'])(a0); -var _sqlite3_vtab_nochange = Module['_sqlite3_vtab_nochange'] = (a0) => (_sqlite3_vtab_nochange = Module['_sqlite3_vtab_nochange'] = wasmExports['sqlite3_vtab_nochange'])(a0); -var _sqlite3_vtab_in_first = Module['_sqlite3_vtab_in_first'] = (a0, a1) => (_sqlite3_vtab_in_first = Module['_sqlite3_vtab_in_first'] = wasmExports['sqlite3_vtab_in_first'])(a0, a1); -var _sqlite3_vtab_in_next = Module['_sqlite3_vtab_in_next'] = (a0, a1) => (_sqlite3_vtab_in_next = Module['_sqlite3_vtab_in_next'] = wasmExports['sqlite3_vtab_in_next'])(a0, a1); -var _sqlite3_aggregate_context = Module['_sqlite3_aggregate_context'] = (a0, a1) => (_sqlite3_aggregate_context = Module['_sqlite3_aggregate_context'] = wasmExports['sqlite3_aggregate_context'])(a0, a1); -var _sqlite3_get_auxdata = Module['_sqlite3_get_auxdata'] = (a0, a1) => (_sqlite3_get_auxdata = Module['_sqlite3_get_auxdata'] = wasmExports['sqlite3_get_auxdata'])(a0, a1); -var _sqlite3_set_auxdata = Module['_sqlite3_set_auxdata'] = (a0, a1, a2, a3) => (_sqlite3_set_auxdata = Module['_sqlite3_set_auxdata'] = wasmExports['sqlite3_set_auxdata'])(a0, a1, a2, a3); -var _sqlite3_data_count = Module['_sqlite3_data_count'] = (a0) => (_sqlite3_data_count = Module['_sqlite3_data_count'] = wasmExports['sqlite3_data_count'])(a0); -var _sqlite3_column_double = Module['_sqlite3_column_double'] = (a0, a1) => (_sqlite3_column_double = Module['_sqlite3_column_double'] = wasmExports['sqlite3_column_double'])(a0, a1); -var _sqlite3_column_value = Module['_sqlite3_column_value'] = (a0, a1) => (_sqlite3_column_value = Module['_sqlite3_column_value'] = wasmExports['sqlite3_column_value'])(a0, a1); -var _sqlite3_column_decltype = Module['_sqlite3_column_decltype'] = (a0, a1) => (_sqlite3_column_decltype = Module['_sqlite3_column_decltype'] = wasmExports['sqlite3_column_decltype'])(a0, a1); -var _sqlite3_bind_blob = Module['_sqlite3_bind_blob'] = (a0, a1, a2, a3, a4) => (_sqlite3_bind_blob = Module['_sqlite3_bind_blob'] = wasmExports['sqlite3_bind_blob'])(a0, a1, a2, a3, a4); -var _sqlite3_bind_null = Module['_sqlite3_bind_null'] = (a0, a1) => (_sqlite3_bind_null = Module['_sqlite3_bind_null'] = wasmExports['sqlite3_bind_null'])(a0, a1); -var _sqlite3_bind_pointer = Module['_sqlite3_bind_pointer'] = (a0, a1, a2, a3, a4) => (_sqlite3_bind_pointer = Module['_sqlite3_bind_pointer'] = wasmExports['sqlite3_bind_pointer'])(a0, a1, a2, a3, a4); -var _sqlite3_bind_parameter_count = Module['_sqlite3_bind_parameter_count'] = (a0) => (_sqlite3_bind_parameter_count = Module['_sqlite3_bind_parameter_count'] = wasmExports['sqlite3_bind_parameter_count'])(a0); -var _sqlite3_bind_parameter_name = Module['_sqlite3_bind_parameter_name'] = (a0, a1) => (_sqlite3_bind_parameter_name = Module['_sqlite3_bind_parameter_name'] = wasmExports['sqlite3_bind_parameter_name'])(a0, a1); -var _sqlite3_bind_parameter_index = Module['_sqlite3_bind_parameter_index'] = (a0, a1) => (_sqlite3_bind_parameter_index = Module['_sqlite3_bind_parameter_index'] = wasmExports['sqlite3_bind_parameter_index'])(a0, a1); -var _sqlite3_db_handle = Module['_sqlite3_db_handle'] = (a0) => (_sqlite3_db_handle = Module['_sqlite3_db_handle'] = wasmExports['sqlite3_db_handle'])(a0); -var _sqlite3_stmt_readonly = Module['_sqlite3_stmt_readonly'] = (a0) => (_sqlite3_stmt_readonly = Module['_sqlite3_stmt_readonly'] = wasmExports['sqlite3_stmt_readonly'])(a0); -var _sqlite3_stmt_isexplain = Module['_sqlite3_stmt_isexplain'] = (a0) => (_sqlite3_stmt_isexplain = Module['_sqlite3_stmt_isexplain'] = wasmExports['sqlite3_stmt_isexplain'])(a0); -var _sqlite3_stmt_explain = Module['_sqlite3_stmt_explain'] = (a0, a1) => (_sqlite3_stmt_explain = Module['_sqlite3_stmt_explain'] = wasmExports['sqlite3_stmt_explain'])(a0, a1); -var _sqlite3_stmt_busy = Module['_sqlite3_stmt_busy'] = (a0) => (_sqlite3_stmt_busy = Module['_sqlite3_stmt_busy'] = wasmExports['sqlite3_stmt_busy'])(a0); -var _sqlite3_stmt_status = Module['_sqlite3_stmt_status'] = (a0, a1, a2) => (_sqlite3_stmt_status = Module['_sqlite3_stmt_status'] = wasmExports['sqlite3_stmt_status'])(a0, a1, a2); -var _sqlite3_value_numeric_type = Module['_sqlite3_value_numeric_type'] = (a0) => (_sqlite3_value_numeric_type = Module['_sqlite3_value_numeric_type'] = wasmExports['sqlite3_value_numeric_type'])(a0); -var _sqlite3_strlike = Module['_sqlite3_strlike'] = (a0, a1, a2) => (_sqlite3_strlike = Module['_sqlite3_strlike'] = wasmExports['sqlite3_strlike'])(a0, a1, a2); -var _sqlite3_auto_extension = Module['_sqlite3_auto_extension'] = (a0) => (_sqlite3_auto_extension = Module['_sqlite3_auto_extension'] = wasmExports['sqlite3_auto_extension'])(a0); -var _sqlite3_cancel_auto_extension = Module['_sqlite3_cancel_auto_extension'] = (a0) => (_sqlite3_cancel_auto_extension = Module['_sqlite3_cancel_auto_extension'] = wasmExports['sqlite3_cancel_auto_extension'])(a0); -var _sqlite3_reset_auto_extension = Module['_sqlite3_reset_auto_extension'] = () => (_sqlite3_reset_auto_extension = Module['_sqlite3_reset_auto_extension'] = wasmExports['sqlite3_reset_auto_extension'])(); -var _sqlite3_prepare_v3 = Module['_sqlite3_prepare_v3'] = (a0, a1, a2, a3, a4, a5) => (_sqlite3_prepare_v3 = Module['_sqlite3_prepare_v3'] = wasmExports['sqlite3_prepare_v3'])(a0, a1, a2, a3, a4, a5); -var _sqlite3_vtab_on_conflict = Module['_sqlite3_vtab_on_conflict'] = (a0) => (_sqlite3_vtab_on_conflict = Module['_sqlite3_vtab_on_conflict'] = wasmExports['sqlite3_vtab_on_conflict'])(a0); -var _sqlite3_vtab_collation = Module['_sqlite3_vtab_collation'] = (a0, a1) => (_sqlite3_vtab_collation = Module['_sqlite3_vtab_collation'] = wasmExports['sqlite3_vtab_collation'])(a0, a1); -var _sqlite3_vtab_in = Module['_sqlite3_vtab_in'] = (a0, a1, a2) => (_sqlite3_vtab_in = Module['_sqlite3_vtab_in'] = wasmExports['sqlite3_vtab_in'])(a0, a1, a2); -var _sqlite3_vtab_rhs_value = Module['_sqlite3_vtab_rhs_value'] = (a0, a1, a2) => (_sqlite3_vtab_rhs_value = Module['_sqlite3_vtab_rhs_value'] = wasmExports['sqlite3_vtab_rhs_value'])(a0, a1, a2); -var _sqlite3_vtab_distinct = Module['_sqlite3_vtab_distinct'] = (a0) => (_sqlite3_vtab_distinct = Module['_sqlite3_vtab_distinct'] = wasmExports['sqlite3_vtab_distinct'])(a0); -var _sqlite3_keyword_name = Module['_sqlite3_keyword_name'] = (a0, a1, a2) => (_sqlite3_keyword_name = Module['_sqlite3_keyword_name'] = wasmExports['sqlite3_keyword_name'])(a0, a1, a2); -var _sqlite3_keyword_count = Module['_sqlite3_keyword_count'] = () => (_sqlite3_keyword_count = Module['_sqlite3_keyword_count'] = wasmExports['sqlite3_keyword_count'])(); -var _sqlite3_keyword_check = Module['_sqlite3_keyword_check'] = (a0, a1) => (_sqlite3_keyword_check = Module['_sqlite3_keyword_check'] = wasmExports['sqlite3_keyword_check'])(a0, a1); -var _sqlite3_complete = Module['_sqlite3_complete'] = (a0) => (_sqlite3_complete = Module['_sqlite3_complete'] = wasmExports['sqlite3_complete'])(a0); -var _sqlite3_shutdown = Module['_sqlite3_shutdown'] = () => (_sqlite3_shutdown = Module['_sqlite3_shutdown'] = wasmExports['sqlite3_shutdown'])(); -var _sqlite3_last_insert_rowid = Module['_sqlite3_last_insert_rowid'] = (a0) => (_sqlite3_last_insert_rowid = Module['_sqlite3_last_insert_rowid'] = wasmExports['sqlite3_last_insert_rowid'])(a0); -var _sqlite3_set_last_insert_rowid = Module['_sqlite3_set_last_insert_rowid'] = (a0, a1) => (_sqlite3_set_last_insert_rowid = Module['_sqlite3_set_last_insert_rowid'] = wasmExports['sqlite3_set_last_insert_rowid'])(a0, a1); -var _sqlite3_changes64 = Module['_sqlite3_changes64'] = (a0) => (_sqlite3_changes64 = Module['_sqlite3_changes64'] = wasmExports['sqlite3_changes64'])(a0); -var _sqlite3_changes = Module['_sqlite3_changes'] = (a0) => (_sqlite3_changes = Module['_sqlite3_changes'] = wasmExports['sqlite3_changes'])(a0); -var _sqlite3_total_changes64 = Module['_sqlite3_total_changes64'] = (a0) => (_sqlite3_total_changes64 = Module['_sqlite3_total_changes64'] = wasmExports['sqlite3_total_changes64'])(a0); -var _sqlite3_total_changes = Module['_sqlite3_total_changes'] = (a0) => (_sqlite3_total_changes = Module['_sqlite3_total_changes'] = wasmExports['sqlite3_total_changes'])(a0); -var _sqlite3_txn_state = Module['_sqlite3_txn_state'] = (a0, a1) => (_sqlite3_txn_state = Module['_sqlite3_txn_state'] = wasmExports['sqlite3_txn_state'])(a0, a1); -var _sqlite3_close_v2 = Module['_sqlite3_close_v2'] = (a0) => (_sqlite3_close_v2 = Module['_sqlite3_close_v2'] = wasmExports['sqlite3_close_v2'])(a0); -var _sqlite3_busy_handler = Module['_sqlite3_busy_handler'] = (a0, a1, a2) => (_sqlite3_busy_handler = Module['_sqlite3_busy_handler'] = wasmExports['sqlite3_busy_handler'])(a0, a1, a2); -var _sqlite3_busy_timeout = Module['_sqlite3_busy_timeout'] = (a0, a1) => (_sqlite3_busy_timeout = Module['_sqlite3_busy_timeout'] = wasmExports['sqlite3_busy_timeout'])(a0, a1); -var _sqlite3_interrupt = Module['_sqlite3_interrupt'] = (a0) => (_sqlite3_interrupt = Module['_sqlite3_interrupt'] = wasmExports['sqlite3_interrupt'])(a0); -var _sqlite3_is_interrupted = Module['_sqlite3_is_interrupted'] = (a0) => (_sqlite3_is_interrupted = Module['_sqlite3_is_interrupted'] = wasmExports['sqlite3_is_interrupted'])(a0); -var _sqlite3_create_function_v2 = Module['_sqlite3_create_function_v2'] = (a0, a1, a2, a3, a4, a5, a6, a7, a8) => (_sqlite3_create_function_v2 = Module['_sqlite3_create_function_v2'] = wasmExports['sqlite3_create_function_v2'])(a0, a1, a2, a3, a4, a5, a6, a7, a8); -var _sqlite3_overload_function = Module['_sqlite3_overload_function'] = (a0, a1, a2) => (_sqlite3_overload_function = Module['_sqlite3_overload_function'] = wasmExports['sqlite3_overload_function'])(a0, a1, a2); -var _sqlite3_trace_v2 = Module['_sqlite3_trace_v2'] = (a0, a1, a2, a3) => (_sqlite3_trace_v2 = Module['_sqlite3_trace_v2'] = wasmExports['sqlite3_trace_v2'])(a0, a1, a2, a3); -var _sqlite3_commit_hook = Module['_sqlite3_commit_hook'] = (a0, a1, a2) => (_sqlite3_commit_hook = Module['_sqlite3_commit_hook'] = wasmExports['sqlite3_commit_hook'])(a0, a1, a2); -var _sqlite3_update_hook = Module['_sqlite3_update_hook'] = (a0, a1, a2) => (_sqlite3_update_hook = Module['_sqlite3_update_hook'] = wasmExports['sqlite3_update_hook'])(a0, a1, a2); -var _sqlite3_rollback_hook = Module['_sqlite3_rollback_hook'] = (a0, a1, a2) => (_sqlite3_rollback_hook = Module['_sqlite3_rollback_hook'] = wasmExports['sqlite3_rollback_hook'])(a0, a1, a2); -var _sqlite3_error_offset = Module['_sqlite3_error_offset'] = (a0) => (_sqlite3_error_offset = Module['_sqlite3_error_offset'] = wasmExports['sqlite3_error_offset'])(a0); -var _sqlite3_errcode = Module['_sqlite3_errcode'] = (a0) => (_sqlite3_errcode = Module['_sqlite3_errcode'] = wasmExports['sqlite3_errcode'])(a0); -var _sqlite3_extended_errcode = Module['_sqlite3_extended_errcode'] = (a0) => (_sqlite3_extended_errcode = Module['_sqlite3_extended_errcode'] = wasmExports['sqlite3_extended_errcode'])(a0); -var _sqlite3_errstr = Module['_sqlite3_errstr'] = (a0) => (_sqlite3_errstr = Module['_sqlite3_errstr'] = wasmExports['sqlite3_errstr'])(a0); -var _sqlite3_limit = Module['_sqlite3_limit'] = (a0, a1, a2) => (_sqlite3_limit = Module['_sqlite3_limit'] = wasmExports['sqlite3_limit'])(a0, a1, a2); -var _sqlite3_open = Module['_sqlite3_open'] = (a0, a1) => (_sqlite3_open = Module['_sqlite3_open'] = wasmExports['sqlite3_open'])(a0, a1); -var _sqlite3_create_collation = Module['_sqlite3_create_collation'] = (a0, a1, a2, a3, a4) => (_sqlite3_create_collation = Module['_sqlite3_create_collation'] = wasmExports['sqlite3_create_collation'])(a0, a1, a2, a3, a4); -var _sqlite3_create_collation_v2 = Module['_sqlite3_create_collation_v2'] = (a0, a1, a2, a3, a4, a5) => (_sqlite3_create_collation_v2 = Module['_sqlite3_create_collation_v2'] = wasmExports['sqlite3_create_collation_v2'])(a0, a1, a2, a3, a4, a5); -var _sqlite3_collation_needed = Module['_sqlite3_collation_needed'] = (a0, a1, a2) => (_sqlite3_collation_needed = Module['_sqlite3_collation_needed'] = wasmExports['sqlite3_collation_needed'])(a0, a1, a2); -var _sqlite3_get_autocommit = Module['_sqlite3_get_autocommit'] = (a0) => (_sqlite3_get_autocommit = Module['_sqlite3_get_autocommit'] = wasmExports['sqlite3_get_autocommit'])(a0); -var _sqlite3_table_column_metadata = Module['_sqlite3_table_column_metadata'] = (a0, a1, a2, a3, a4, a5, a6, a7, a8) => (_sqlite3_table_column_metadata = Module['_sqlite3_table_column_metadata'] = wasmExports['sqlite3_table_column_metadata'])(a0, a1, a2, a3, a4, a5, a6, a7, a8); -var _sqlite3_extended_result_codes = Module['_sqlite3_extended_result_codes'] = (a0, a1) => (_sqlite3_extended_result_codes = Module['_sqlite3_extended_result_codes'] = wasmExports['sqlite3_extended_result_codes'])(a0, a1); -var _sqlite3_uri_key = Module['_sqlite3_uri_key'] = (a0, a1) => (_sqlite3_uri_key = Module['_sqlite3_uri_key'] = wasmExports['sqlite3_uri_key'])(a0, a1); -var _sqlite3_uri_int64 = Module['_sqlite3_uri_int64'] = (a0, a1, a2) => (_sqlite3_uri_int64 = Module['_sqlite3_uri_int64'] = wasmExports['sqlite3_uri_int64'])(a0, a1, a2); -var _sqlite3_db_name = Module['_sqlite3_db_name'] = (a0, a1) => (_sqlite3_db_name = Module['_sqlite3_db_name'] = wasmExports['sqlite3_db_name'])(a0, a1); -var _sqlite3_db_filename = Module['_sqlite3_db_filename'] = (a0, a1) => (_sqlite3_db_filename = Module['_sqlite3_db_filename'] = wasmExports['sqlite3_db_filename'])(a0, a1); -var _sqlite3_db_readonly = Module['_sqlite3_db_readonly'] = (a0, a1) => (_sqlite3_db_readonly = Module['_sqlite3_db_readonly'] = wasmExports['sqlite3_db_readonly'])(a0, a1); -var _sqlite3_compileoption_used = Module['_sqlite3_compileoption_used'] = (a0) => (_sqlite3_compileoption_used = Module['_sqlite3_compileoption_used'] = wasmExports['sqlite3_compileoption_used'])(a0); -var _sqlite3_compileoption_get = Module['_sqlite3_compileoption_get'] = (a0) => (_sqlite3_compileoption_get = Module['_sqlite3_compileoption_get'] = wasmExports['sqlite3_compileoption_get'])(a0); -var _sqlite3__wasm_pstack_ptr = Module['_sqlite3__wasm_pstack_ptr'] = () => (_sqlite3__wasm_pstack_ptr = Module['_sqlite3__wasm_pstack_ptr'] = wasmExports['sqlite3__wasm_pstack_ptr'])(); -var _sqlite3__wasm_pstack_restore = Module['_sqlite3__wasm_pstack_restore'] = (a0) => (_sqlite3__wasm_pstack_restore = Module['_sqlite3__wasm_pstack_restore'] = wasmExports['sqlite3__wasm_pstack_restore'])(a0); -var _sqlite3__wasm_pstack_alloc = Module['_sqlite3__wasm_pstack_alloc'] = (a0) => (_sqlite3__wasm_pstack_alloc = Module['_sqlite3__wasm_pstack_alloc'] = wasmExports['sqlite3__wasm_pstack_alloc'])(a0); -var _sqlite3__wasm_pstack_remaining = Module['_sqlite3__wasm_pstack_remaining'] = () => (_sqlite3__wasm_pstack_remaining = Module['_sqlite3__wasm_pstack_remaining'] = wasmExports['sqlite3__wasm_pstack_remaining'])(); -var _sqlite3__wasm_pstack_quota = Module['_sqlite3__wasm_pstack_quota'] = () => (_sqlite3__wasm_pstack_quota = Module['_sqlite3__wasm_pstack_quota'] = wasmExports['sqlite3__wasm_pstack_quota'])(); -var _sqlite3__wasm_db_error = Module['_sqlite3__wasm_db_error'] = (a0, a1, a2) => (_sqlite3__wasm_db_error = Module['_sqlite3__wasm_db_error'] = wasmExports['sqlite3__wasm_db_error'])(a0, a1, a2); -var _sqlite3__wasm_test_struct = Module['_sqlite3__wasm_test_struct'] = (a0) => (_sqlite3__wasm_test_struct = Module['_sqlite3__wasm_test_struct'] = wasmExports['sqlite3__wasm_test_struct'])(a0); -var _sqlite3__wasm_enum_json = Module['_sqlite3__wasm_enum_json'] = () => (_sqlite3__wasm_enum_json = Module['_sqlite3__wasm_enum_json'] = wasmExports['sqlite3__wasm_enum_json'])(); -var _sqlite3__wasm_vfs_unlink = Module['_sqlite3__wasm_vfs_unlink'] = (a0, a1) => (_sqlite3__wasm_vfs_unlink = Module['_sqlite3__wasm_vfs_unlink'] = wasmExports['sqlite3__wasm_vfs_unlink'])(a0, a1); -var _sqlite3__wasm_db_vfs = Module['_sqlite3__wasm_db_vfs'] = (a0, a1) => (_sqlite3__wasm_db_vfs = Module['_sqlite3__wasm_db_vfs'] = wasmExports['sqlite3__wasm_db_vfs'])(a0, a1); -var _sqlite3__wasm_db_reset = Module['_sqlite3__wasm_db_reset'] = (a0) => (_sqlite3__wasm_db_reset = Module['_sqlite3__wasm_db_reset'] = wasmExports['sqlite3__wasm_db_reset'])(a0); -var _sqlite3__wasm_db_export_chunked = Module['_sqlite3__wasm_db_export_chunked'] = (a0, a1) => (_sqlite3__wasm_db_export_chunked = Module['_sqlite3__wasm_db_export_chunked'] = wasmExports['sqlite3__wasm_db_export_chunked'])(a0, a1); -var _sqlite3__wasm_db_serialize = Module['_sqlite3__wasm_db_serialize'] = (a0, a1, a2, a3, a4) => (_sqlite3__wasm_db_serialize = Module['_sqlite3__wasm_db_serialize'] = wasmExports['sqlite3__wasm_db_serialize'])(a0, a1, a2, a3, a4); -var _sqlite3__wasm_vfs_create_file = Module['_sqlite3__wasm_vfs_create_file'] = (a0, a1, a2, a3) => (_sqlite3__wasm_vfs_create_file = Module['_sqlite3__wasm_vfs_create_file'] = wasmExports['sqlite3__wasm_vfs_create_file'])(a0, a1, a2, a3); -var _sqlite3__wasm_posix_create_file = Module['_sqlite3__wasm_posix_create_file'] = (a0, a1, a2) => (_sqlite3__wasm_posix_create_file = Module['_sqlite3__wasm_posix_create_file'] = wasmExports['sqlite3__wasm_posix_create_file'])(a0, a1, a2); -var _sqlite3__wasm_kvvfsMakeKeyOnPstack = Module['_sqlite3__wasm_kvvfsMakeKeyOnPstack'] = (a0, a1) => (_sqlite3__wasm_kvvfsMakeKeyOnPstack = Module['_sqlite3__wasm_kvvfsMakeKeyOnPstack'] = wasmExports['sqlite3__wasm_kvvfsMakeKeyOnPstack'])(a0, a1); -var _sqlite3__wasm_kvvfs_methods = Module['_sqlite3__wasm_kvvfs_methods'] = () => (_sqlite3__wasm_kvvfs_methods = Module['_sqlite3__wasm_kvvfs_methods'] = wasmExports['sqlite3__wasm_kvvfs_methods'])(); -var _sqlite3__wasm_vtab_config = Module['_sqlite3__wasm_vtab_config'] = (a0, a1, a2) => (_sqlite3__wasm_vtab_config = Module['_sqlite3__wasm_vtab_config'] = wasmExports['sqlite3__wasm_vtab_config'])(a0, a1, a2); -var _sqlite3__wasm_db_config_ip = Module['_sqlite3__wasm_db_config_ip'] = (a0, a1, a2, a3) => (_sqlite3__wasm_db_config_ip = Module['_sqlite3__wasm_db_config_ip'] = wasmExports['sqlite3__wasm_db_config_ip'])(a0, a1, a2, a3); -var _sqlite3__wasm_db_config_pii = Module['_sqlite3__wasm_db_config_pii'] = (a0, a1, a2, a3, a4) => (_sqlite3__wasm_db_config_pii = Module['_sqlite3__wasm_db_config_pii'] = wasmExports['sqlite3__wasm_db_config_pii'])(a0, a1, a2, a3, a4); -var _sqlite3__wasm_db_config_s = Module['_sqlite3__wasm_db_config_s'] = (a0, a1, a2) => (_sqlite3__wasm_db_config_s = Module['_sqlite3__wasm_db_config_s'] = wasmExports['sqlite3__wasm_db_config_s'])(a0, a1, a2); -var _sqlite3__wasm_config_i = Module['_sqlite3__wasm_config_i'] = (a0, a1) => (_sqlite3__wasm_config_i = Module['_sqlite3__wasm_config_i'] = wasmExports['sqlite3__wasm_config_i'])(a0, a1); -var _sqlite3__wasm_config_ii = Module['_sqlite3__wasm_config_ii'] = (a0, a1, a2) => (_sqlite3__wasm_config_ii = Module['_sqlite3__wasm_config_ii'] = wasmExports['sqlite3__wasm_config_ii'])(a0, a1, a2); -var _sqlite3__wasm_config_j = Module['_sqlite3__wasm_config_j'] = (a0, a1) => (_sqlite3__wasm_config_j = Module['_sqlite3__wasm_config_j'] = wasmExports['sqlite3__wasm_config_j'])(a0, a1); -var _sqlite3__wasm_qfmt_token = Module['_sqlite3__wasm_qfmt_token'] = (a0, a1) => (_sqlite3__wasm_qfmt_token = Module['_sqlite3__wasm_qfmt_token'] = wasmExports['sqlite3__wasm_qfmt_token'])(a0, a1); -var _sqlite3__wasm_init_wasmfs = Module['_sqlite3__wasm_init_wasmfs'] = (a0) => (_sqlite3__wasm_init_wasmfs = Module['_sqlite3__wasm_init_wasmfs'] = wasmExports['sqlite3__wasm_init_wasmfs'])(a0); -var _sqlite3__wasm_test_intptr = Module['_sqlite3__wasm_test_intptr'] = (a0) => (_sqlite3__wasm_test_intptr = Module['_sqlite3__wasm_test_intptr'] = wasmExports['sqlite3__wasm_test_intptr'])(a0); -var _sqlite3__wasm_test_voidptr = Module['_sqlite3__wasm_test_voidptr'] = (a0) => (_sqlite3__wasm_test_voidptr = Module['_sqlite3__wasm_test_voidptr'] = wasmExports['sqlite3__wasm_test_voidptr'])(a0); -var _sqlite3__wasm_test_int64_max = Module['_sqlite3__wasm_test_int64_max'] = () => (_sqlite3__wasm_test_int64_max = Module['_sqlite3__wasm_test_int64_max'] = wasmExports['sqlite3__wasm_test_int64_max'])(); -var _sqlite3__wasm_test_int64_min = Module['_sqlite3__wasm_test_int64_min'] = () => (_sqlite3__wasm_test_int64_min = Module['_sqlite3__wasm_test_int64_min'] = wasmExports['sqlite3__wasm_test_int64_min'])(); -var _sqlite3__wasm_test_int64_times2 = Module['_sqlite3__wasm_test_int64_times2'] = (a0) => (_sqlite3__wasm_test_int64_times2 = Module['_sqlite3__wasm_test_int64_times2'] = wasmExports['sqlite3__wasm_test_int64_times2'])(a0); -var _sqlite3__wasm_test_int64_minmax = Module['_sqlite3__wasm_test_int64_minmax'] = (a0, a1) => (_sqlite3__wasm_test_int64_minmax = Module['_sqlite3__wasm_test_int64_minmax'] = wasmExports['sqlite3__wasm_test_int64_minmax'])(a0, a1); -var _sqlite3__wasm_test_int64ptr = Module['_sqlite3__wasm_test_int64ptr'] = (a0) => (_sqlite3__wasm_test_int64ptr = Module['_sqlite3__wasm_test_int64ptr'] = wasmExports['sqlite3__wasm_test_int64ptr'])(a0); -var _sqlite3__wasm_test_stack_overflow = Module['_sqlite3__wasm_test_stack_overflow'] = (a0) => (_sqlite3__wasm_test_stack_overflow = Module['_sqlite3__wasm_test_stack_overflow'] = wasmExports['sqlite3__wasm_test_stack_overflow'])(a0); -var _sqlite3__wasm_test_str_hello = Module['_sqlite3__wasm_test_str_hello'] = (a0) => (_sqlite3__wasm_test_str_hello = Module['_sqlite3__wasm_test_str_hello'] = wasmExports['sqlite3__wasm_test_str_hello'])(a0); -var _sqlite3__wasm_SQLTester_strglob = Module['_sqlite3__wasm_SQLTester_strglob'] = (a0, a1) => (_sqlite3__wasm_SQLTester_strglob = Module['_sqlite3__wasm_SQLTester_strglob'] = wasmExports['sqlite3__wasm_SQLTester_strglob'])(a0, a1); -var _realloc = Module['_realloc'] = (a0, a1) => (_realloc = Module['_realloc'] = wasmExports['realloc'])(a0, a1); -var _emscripten_builtin_memalign = (a0, a1) => (_emscripten_builtin_memalign = wasmExports['emscripten_builtin_memalign'])(a0, a1); -var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0); -var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0); -var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); // include: postamble.js // === Auto-generated postamble setup entry stuff === -Module['wasmMemory'] = wasmMemory; - - -var calledRun; - -dependenciesFulfilled = function runCaller() { - // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) - if (!calledRun) run(); - if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled -}; - -function run() { - - if (runDependencies > 0) { - return; - } +async function run() { preRun(); - // a preRun added a dependency, run will be called later - if (runDependencies > 0) { - return; + if (runDependencies) { + await resolveRunDependencies(); } - function doRun() { - // run may have just been called through dependencies being fulfilled just in this very frame, - // or while the async setStatus time below was happening - if (calledRun) return; - calledRun = true; - Module['calledRun'] = true; - - if (ABORT) return; + if (ABORT) return; - initRuntime(); + initRuntime(); - readyPromiseResolve(Module); - Module['onRuntimeInitialized']?.(); - - postRun(); - } - - if (Module['setStatus']) { - Module['setStatus']('Running...'); - setTimeout(() => { - setTimeout(() => Module['setStatus'](''), 1); - doRun(); - }, 1); - } else - { - doRun(); - } + postRun(); } -if (Module['preInit']) { - if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; - while (Module['preInit'].length > 0) { - Module['preInit'].pop()(); - } -} +var wasmExports; -run(); +// In modularize mode the generated code is within a factory function so we +// can use await here (since it's not top-level-await). +wasmExports = await createWasm(); +await run(); // end include: postamble.js -// include: /usr/local/google/home/dlehmann/JetStream/sqlite3/sqlite-src-3480000/ext/wasm/bld/post-js.speedtest1-vanilla.js +// include: ./bld/post-js.speedtest1-vanilla.js /* BEGIN FILE: api/post-js-header.js */ /** post-js-header.js is to be prepended to other code to create @@ -4429,8 +4637,7 @@ run(); installs will be run after the WASM module is loaded, at which point the sqlite3 JS API bits will get set up. */ -if(!Module.postRun) Module.postRun = []; -Module.postRun.push(function(Module/*the Emscripten-style module object*/){ +Module.runSQLite3PostLoadInit = function(Module/*the Emscripten-style module object*/){ 'use strict'; /* This function will contain at least the following: @@ -4481,9 +4688,9 @@ Module.postRun.push(function(Module/*the Emscripten-style module object*/){ ** ** SQLITE_VERSION "3.48.0" ** SQLITE_VERSION_NUMBER 3048000 -** SQLITE_SOURCE_ID "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010" +** SQLITE_SOURCE_ID "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e8alt1" ** -** Using the Emscripten SDK version 3.1.73. +** Using the Emscripten SDK version 6.0.13. */ /* END FILE: ./bld/sqlite3-license-version.js */ /* BEGIN FILE: api/sqlite3-api-prologue.js */ @@ -11579,7 +11786,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* END FILE: api/sqlite3-api-glue.c-pp.js */ /* BEGIN FILE: ./bld/sqlite3-api-build-version.js */ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - sqlite3.version = {"libVersion": "3.48.0", "libVersionNumber": 3048000, "sourceId": "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010","downloadVersion": 3480000}; + sqlite3.version = {"libVersion": "3.48.0", "libVersionNumber": 3048000, "sourceId": "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e8alt1","downloadVersion": 3480000}; }); /* END FILE: ./bld/sqlite3-api-build-version.js */ /* BEGIN FILE: api/sqlite3-api-oo1.c-pp.js */ @@ -17622,32 +17829,32 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build /* The current function scope was opened via post-js-header.js, which gets prepended to this at build-time. This file closes that scope. */ -})/*postRun.push(...)*/; +}/*Module.runSQLite3PostLoadInit()*/; /* END FILE: api/post-js-footer.js */ -// end include: /usr/local/google/home/dlehmann/JetStream/sqlite3/sqlite-src-3480000/ext/wasm/bld/post-js.speedtest1-vanilla.js +// end include: ./bld/post-js.speedtest1-vanilla.js // include: postamble_modularize.js // In MODULARIZE mode we wrap the generated code in a factory function // and return either the Module itself, or a promise of the module. -// -// We assign to the `moduleRtn` global here and configure closure to see -// this as and extern so it won't get minified. - -moduleRtn = readyPromise; // end include: postamble_modularize.js - return moduleRtn; -} -); + return Module; + }; })(); -if (typeof exports === 'object' && typeof module === 'object') + +// Export using a UMD style export, or ES6 exports if selected +if (typeof exports === 'object' && typeof module === 'object') { module.exports = sqlite3InitModule; -else if (typeof define === 'function' && define['amd']) + // This default export looks redundant, but it allows TS to import this + // commonjs style module. + module.exports.default = sqlite3InitModule; +} else if (typeof define === 'function' && define['amd']) define([], () => sqlite3InitModule); + /* ^^^^ ACHTUNG: blank line at the start is necessary because Emscripten will not add a newline in some cases and we need a blank line for a sed-based kludge for the ES6 build. */ @@ -17709,6 +17916,7 @@ else if (typeof define === 'function' && define['amd']) //console.warn("Using replaced sqlite3InitModule()",globalThis.location); return originalInit(...args).then((EmscriptenModule)=>{ //console.warn("sqlite3InitModule() returning sqlite3 object."); + EmscriptenModule.runSQLite3PostLoadInit(EmscriptenModule); const s = EmscriptenModule.sqlite3; s.scriptInfo = initModuleState; //console.warn("sqlite3.scriptInfo =",s.scriptInfo); diff --git a/workloads/sqlite3-wasm/build/jswasm/speedtest1.wasm b/workloads/sqlite3-wasm/build/jswasm/speedtest1.wasm index 94c755be..4e7c0595 100644 Binary files a/workloads/sqlite3-wasm/build/jswasm/speedtest1.wasm and b/workloads/sqlite3-wasm/build/jswasm/speedtest1.wasm differ diff --git a/workloads/sqlite3-wasm/emscripten-4-post-load-init.patch b/workloads/sqlite3-wasm/emscripten-4-post-load-init.patch new file mode 100644 index 00000000..cc9975b7 --- /dev/null +++ b/workloads/sqlite3-wasm/emscripten-4-post-load-init.patch @@ -0,0 +1,41 @@ +Backport of the SQLite 3.49.0 fix for building with Emscripten 4.0 or newer. + +Since Emscripten 4.0.0 (emscripten-core/emscripten#23157), the -sMODULARIZE +factory awaits the Wasm instantiation and runs Module.postRun before any +--post-js code executes. SQLite 3.48.0 registers its API setup as a +Module.postRun handler in post-js-header.js, so with Emscripten 4+ that +handler never runs and sqlite3InitModule() fails with "s is undefined". +SQLite 3.49.0 replaced the handler with Module.runSQLite3PostLoadInit(), +which extern-post-js.c-pp.js calls once the factory promise resolves. +Remove this patch when updating to SQLite 3.49.0 or newer. + +--- a/ext/wasm/api/post-js-header.js ++++ b/ext/wasm/api/post-js-header.js +@@ -7,8 +7,7 @@ + installs will be run after the WASM module is loaded, at which + point the sqlite3 JS API bits will get set up. + */ +-if(!Module.postRun) Module.postRun = []; +-Module.postRun.push(function(Module/*the Emscripten-style module object*/){ ++Module.runSQLite3PostLoadInit = function(Module/*the Emscripten-style module object*/){ + 'use strict'; + /* This function will contain at least the following: + +--- a/ext/wasm/api/post-js-footer.js ++++ b/ext/wasm/api/post-js-footer.js +@@ -1,4 +1,4 @@ + /* The current function scope was opened via post-js-header.js, which + gets prepended to this at build-time. This file closes that + scope. */ +-})/*postRun.push(...)*/; ++}/*Module.runSQLite3PostLoadInit()*/; +--- a/ext/wasm/api/extern-post-js.c-pp.js ++++ b/ext/wasm/api/extern-post-js.c-pp.js +@@ -75,6 +75,7 @@ + } + //#endif + //console.warn("sqlite3InitModule() returning sqlite3 object."); ++ EmscriptenModule.runSQLite3PostLoadInit(EmscriptenModule); + const s = EmscriptenModule.sqlite3; + s.scriptInfo = initModuleState; + //console.warn("sqlite3.scriptInfo =",s.scriptInfo);