| /** | |
| * @license | |
| * Copyright 2024 The Emscripten Authors | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| #include "runtime_exceptions.js" | |
| #include "runtime_debug.js" | |
| #if STACK_OVERFLOW_CHECK | |
| #include "runtime_stack_check.js" | |
| #endif | |
| #if SAFE_HEAP | |
| #include "runtime_safe_heap.js" | |
| #endif | |
| #if USE_ASAN | |
| #include "runtime_asan.js" | |
| #endif | |
| #if SINGLE_FILE && SINGLE_FILE_BINARY_ENCODE && !WASM2JS | |
| #include "binaryDecode.js" | |
| #endif | |
| #if SHARED_MEMORY && ALLOW_MEMORY_GROWTH && GROWABLE_ARRAYBUFFERS != 2 | |
| // Support for growable heap + pthreads, where the buffer may change, so JS views | |
| // must be updated. | |
| function growMemViews() { | |
| // `updateMemoryViews` updates all the views simultaneously, so it's enough to check any of them. | |
| if (wasmMemory.buffer != HEAP8.buffer) { | |
| updateMemoryViews(); | |
| } | |
| } | |
| #endif | |
| #if (PTHREADS || WASM_WORKERS) && (ENVIRONMENT_MAY_BE_NODE && !WASM_ESM_INTEGRATION) | |
| if (ENVIRONMENT_IS_NODE && {{{ ENVIRONMENT_IS_WORKER_THREAD() }}}) { | |
| // Create as web-worker-like an environment as we can. | |
| globalThis.self = globalThis; | |
| var parentPort = worker_threads.parentPort; | |
| // Deno and Bun already have `postMessage` defined on the global scope and | |
| // deliver messages to `globalThis.onmessage`, so we must not duplicate that | |
| // behavior here if `postMessage` is already present. | |
| if (!globalThis.postMessage) { | |
| parentPort.on('message', (msg) => globalThis.onmessage?.({ data: msg })); | |
| globalThis.postMessage = (msg) => parentPort.postMessage(msg); | |
| } | |
| // Node.js Workers do not pass postMessage()s and uncaught exception events to the parent | |
| // thread necessarily in the same order where they were generated in sequential program order. | |
| // See https://github.com/nodejs/node/issues/59617 | |
| // To remedy this, capture all uncaughtExceptions in the Worker, and sequentialize those over | |
| // to the same postMessage pipe that other messages use. | |
| process.on("uncaughtException", (err) => { | |
| #if PTHREADS_DEBUG | |
| dbg(`uncaughtException on worker thread: ${err.message}`); | |
| #endif | |
| postMessage({ cmd: {{{ CMD_UNCAUGHT_EXN }}}, error: err }); | |
| // Also shut down the Worker to match the same semantics as if this uncaughtException | |
| // handler was not registered. | |
| // (n.b. this will not shut down the whole Node.js app process, but just the Worker) | |
| process.exit(1); | |
| }); | |
| } | |
| #endif // (PTHREADS || WASM_WORKERS) && (ENVIRONMENT_MAY_BE_NODE && !WASM_ESM_INTEGRATION) | |
| #if PTHREADS | |
| #include "runtime_pthread.js" | |
| #endif | |
| #if WASM_WORKERS | |
| #include "wasm_worker.js" | |
| #endif | |
| #if AUDIO_WORKLET | |
| #include "audio_worklet.js" | |
| #endif | |
| // Memory management | |
| #if SUPPORT_BIG_ENDIAN | |
| /** @type {!DataView} */ | |
| var HEAP_DATA_VIEW; | |
| #endif | |
| #if !MINIMAL_RUNTIME || ASSERTIONS || SAFE_HEAP || USE_ASAN || MODULARIZE || PTHREADS | |
| var runtimeInitialized = false; | |
| #endif | |
| #if EXIT_RUNTIME | |
| var runtimeExited = false; | |
| #endif | |
| {{{ | |
| // Helper function to export a heap symbol on the module object, | |
| // if requested. | |
| const shouldExportHeap = (x) => { | |
| let shouldExport = false; | |
| if (EXPORT_ALL) { | |
| shouldExport = true; | |
| } else if (EXPORTED_RUNTIME_METHODS.has(x)) { | |
| shouldExport = true; | |
| } | |
| return shouldExport; | |
| }; | |
| const maybeExportHeap = (x) => { | |
| if (shouldExportHeap(x) && MODULARIZE != 'instance') { | |
| return `Module['${x}'] = `; | |
| } | |
| return ''; | |
| }; | |
| const isHeapNeeded = (x) => { | |
| return shouldExportHeap(x) || addedLibraryItems['$' + x]; | |
| }; | |
| const updateHeap = (x, type) => { | |
| if (isHeapNeeded(x)) { | |
| return `${maybeExportHeap(x)}${x} = new ${type}(b);`; | |
| } | |
| return ''; | |
| }; | |
| }}} | |
| #if ALLOW_MEMORY_GROWTH | |
| // When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm | |
| // memory to ArrayBuffer requires some additional logic. | |
| function getMemoryBuffer() { | |
| #if GROWABLE_ARRAYBUFFERS == 2 | |
| return wasmMemory.toResizableBuffer(); | |
| #else | |
| #if GROWABLE_ARRAYBUFFERS == 1 | |
| #if SHARED_MEMORY && (MIN_FIREFOX_VERSION < 154) | |
| // Deserializing a growable SharedArrayBuffer was broken until Firefox 154 | |
| // See: https://bugzilla.mozilla.org/show_bug.cgi?id=2021136 | |
| var firefoxMatch = globalThis.navigator?.userAgent?.match(/Firefox\/(\d+)/); | |
| if (!firefoxMatch || Number(firefoxMatch[1]) >= 154) { | |
| #endif | |
| try { | |
| // This method may be missing or could fail with `Memory must have a maximum` | |
| var b = wasmMemory.toResizableBuffer(); | |
| #if SHARED_MEMORY | |
| growMemViews = () => {}; | |
| #endif | |
| return b; | |
| } catch {} | |
| #if SHARED_MEMORY && (MIN_FIREFOX_VERSION < 154) | |
| } | |
| #endif | |
| #endif // GROWABLE_ARRAYBUFFERS == 1 | |
| return wasmMemory.buffer; | |
| #endif // GROWABLE_ARRAYBUFFERS == 2 | |
| } | |
| #endif // ALLOW_MEMORY_GROWTH | |
| function updateMemoryViews() { | |
| #if RUNTIME_DEBUG | |
| dbg(`updateMemoryViews: first=${!HEAP8} size=${wasmMemory.buffer.byteLength}`); | |
| #endif | |
| #if ALLOW_MEMORY_GROWTH | |
| // If we already have a heap that is resizeable/growable buffer we don't | |
| // need to do anything in updateMemoryViews. | |
| #if SHARED_MEMORY | |
| if (HEAP8?.buffer?.growable) return; | |
| #else | |
| if (HEAP8?.buffer?.resizable) return; | |
| #endif | |
| var b = getMemoryBuffer(); | |
| #else | |
| #if ASSERTIONS | |
| // When memory growth is disabled this function should be called exactly once. | |
| assert(!HEAP8, 'updateMemoryViews should only be called once when ALLOW_MEMORY_GROWTH=0'); | |
| #endif | |
| var b = wasmMemory.buffer; | |
| #endif | |
| {{{ updateHeap('HEAP8', 'Int8Array') }}} | |
| {{{ updateHeap('HEAP16', 'Int16Array') }}} | |
| {{{ updateHeap('HEAPU8', 'Uint8Array') }}} | |
| {{{ updateHeap('HEAPU16', 'Uint16Array') }}} | |
| {{{ updateHeap('HEAP32', 'Int32Array') }}} | |
| {{{ updateHeap('HEAPU32', 'Uint32Array') }}} | |
| {{{ updateHeap('HEAPF32', 'Float32Array') }}} | |
| {{{ updateHeap('HEAPF64', 'Float64Array') }}} | |
| #if WASM_BIGINT | |
| {{{ updateHeap('HEAP64', 'BigInt64Array') }}} | |
| {{{ updateHeap('HEAPU64', 'BigUint64Array') }}} | |
| #endif | |
| #if SUPPORT_BIG_ENDIAN | |
| {{{ maybeExportHeap('HEAP_DATA_VIEW') }}} HEAP_DATA_VIEW = new DataView(b); | |
| LE_HEAP_UPDATE(); | |
| #endif | |
| } | |
| #if IMPORTED_MEMORY | |
| // In non-standalone/normal mode, we create the memory here. | |
| #include "runtime_init_memory.js" | |
| #endif | |
| #include "memoryprofiler.js" | |
| #if !DECLARE_ASM_MODULE_EXPORTS | |
| function exportAliases(wasmExports) { | |
| {{{ makeExportAliases() }}} | |
| } | |
| #endif |