Buckets:
| /** | |
| * @license | |
| * Copyright 2023 The Emscripten Authors | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| #if WASM_WORKERS | |
| #if !SHARED_MEMORY | |
| #error "Internal error! SHARED_MEMORY should be enabled when building with WASM_WORKERS" | |
| #endif | |
| #if SINGLE_FILE | |
| #error "-sSINGLE_FILE is not supported with -sWASM_WORKERS" | |
| #endif | |
| #if LINKABLE | |
| #error "-sLINKABLE is not supported with -sWASM_WORKERS" | |
| #endif | |
| #if WASM2JS && MODULARIZE | |
| #error "-sWASM=0 + -sMODULARIZE + -sWASM_WORKERS is not supported" | |
| #endif | |
| #endif // ~WASM_WORKERS | |
| {{{ | |
| const workerSupportsFutexWait = () => AUDIO_WORKLET ? "!ENVIRONMENT_IS_AUDIO_WORKLET" : '1'; | |
| const wasmWorkerJs = ` | |
| #if MINIMAL_RUNTIME | |
| #if ENVIRONMENT_MAY_BE_NODE | |
| Module['js'] || './${TARGET_JS_NAME}' | |
| #else | |
| Module['js'] | |
| #endif | |
| #else | |
| locateFile('${TARGET_JS_NAME}') | |
| #endif | |
| `; | |
| const wasmWorkerOptions = `{ | |
| #if EXPORT_ES6 | |
| 'type': 'module', | |
| #endif | |
| #if ENVIRONMENT_MAY_BE_NODE | |
| // This is the way that we signal to the node worker that it is hosting | |
| // a Wasm Worker. | |
| 'workerData': 'em-ww', | |
| #endif | |
| #if ENVIRONMENT_MAY_BE_WEB || ENVIRONMENT_MAY_BE_WORKER | |
| // This is the way that we signal to the Web Worker that it is hosting | |
| // a Wasm Worker. | |
| #if ASSERTIONS | |
| 'name': 'em-ww-' + wwID, | |
| #else | |
| 'name': 'em-ww', | |
| #endif | |
| #endif | |
| }`; | |
| }}} | |
| addToLibrary({ | |
| $_wasmWorkers: {}, | |
| // Starting up a Wasm Worker is an asynchronous operation, hence if the parent | |
| // thread performs any postMessage()-based wasm function calls to the | |
| // Worker, they must be delayed until the async startup has finished, after | |
| // which these postponed function calls can be dispatched. | |
| $_wasmWorkerDelayedMessageQueue: [], | |
| $_wasmWorkerAppendToQueue: (e) => { | |
| _wasmWorkerDelayedMessageQueue.push(e); | |
| }, | |
| // Executes a wasm function call received via a postMessage. | |
| $_wasmWorkerRunPostMessage__deps: ['$callUserCallback'], | |
| $_wasmWorkerRunPostMessage: (e) => { | |
| // '_wsc' is short for 'wasm call', trying to use an identifier name that | |
| // will never conflict with user code | |
| let data = e.data; | |
| let wasmCall = data['_wsc']; | |
| wasmCall && callUserCallback(() => getWasmTableEntry(wasmCall)(...data['x'])); | |
| }, | |
| // src/postamble_minimal.js brings this symbol in to the build, and calls this | |
| // function synchronously from main JS file at the startup of each Worker. | |
| $_wasmWorkerInitializeRuntime__deps: [ | |
| '$_wasmWorkerDelayedMessageQueue', | |
| '$_wasmWorkerRunPostMessage', | |
| '$_wasmWorkerAppendToQueue', | |
| '_emscripten_wasm_worker_initialize', | |
| #if PTHREADS | |
| '__set_thread_state', | |
| '$alignMemory', | |
| #endif | |
| ], | |
| $_wasmWorkerInitializeRuntime: () => { | |
| #if ASSERTIONS | |
| assert(wwParams); | |
| assert(wwParams.wwID); | |
| assert(wwParams.stackLowestAddress % {{{ STACK_ALIGN }}} == 0); | |
| assert(wwParams.stackSize % {{{ STACK_ALIGN }}} == 0); | |
| #endif | |
| #if RUNTIME_DEBUG | |
| dbg("wasmWorkerInitializeRuntime wwID:", wwParams.wwID); | |
| #endif | |
| #if !MINIMAL_RUNTIME && isSymbolNeeded('$noExitRuntime') | |
| // Wasm workers basically never exit their runtime | |
| noExitRuntime = 1; | |
| #endif | |
| #if STACK_OVERFLOW_CHECK >= 2 | |
| // _emscripten_wasm_worker_initialize() initializes the stack for this | |
| // Worker, but it cannot call to extern __set_stack_limits() function, or | |
| // Binaryen breaks with "Fatal: Module::addFunction: __set_stack_limits | |
| // already exists". So for now, invoke this function from JS side. TODO: | |
| // remove this in the future. Note that this call is not exactly correct, | |
| // since this limit will include the TLS slot, that will be part of the | |
| // region between wwParams.stackLowestAddress and wwParams.stackSize, so we | |
| // need to fix up the call below. | |
| ___set_stack_limits(wwParams.stackLowestAddress + wwParams.stackSize, wwParams.stackLowestAddress); | |
| #endif | |
| // Run the C side Worker initialization for stack and TLS. | |
| __emscripten_wasm_worker_initialize(wwParams.wwID, wwParams.stackLowestAddress, wwParams.stackSize); | |
| #if PTHREADS | |
| // Record the pthread configuration, and whether this Wasm Worker supports synchronous blocking in emscripten_futex_wait(). | |
| // (regular Wasm Workers do, AudioWorklets don't) | |
| ___set_thread_state(wwParams.pthreadPtr ?? 0, /*is_main_thread=*/0, /*is_runtime_thread=*/0, /*supports_wait=*/ {{{ workerSupportsFutexWait() }}}); | |
| #endif | |
| #if STACK_OVERFLOW_CHECK >= 2 | |
| // Fix up stack base. (TLS frame is created at the bottom address end of the stack) | |
| // See https://github.com/emscripten-core/emscripten/issues/16496 | |
| ___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end()); | |
| #endif | |
| #if STACK_OVERFLOW_CHECK | |
| // Write the stack cookie last, after we have set up the proper bounds and | |
| // current position of the stack. | |
| writeStackCookie(); | |
| #endif | |
| #if EMBIND | |
| // Embind must initialize itself on all threads, as it generates support JS. | |
| __embind_initialize_bindings(); | |
| #endif | |
| #if AUDIO_WORKLET | |
| // Audio Worklets do not have postMessage()ing capabilities. | |
| if (!ENVIRONMENT_IS_AUDIO_WORKLET) { | |
| #endif | |
| // The Wasm Worker runtime is now up, so we can start processing | |
| // any postMessage function calls that have been received. Drop the temp | |
| // message handler that queued any pending incoming postMessage function calls ... | |
| removeEventListener('message', _wasmWorkerAppendToQueue); | |
| // ... then flush whatever messages we may have already gotten in the queue, | |
| // and clear _wasmWorkerDelayedMessageQueue to undefined ... | |
| _wasmWorkerDelayedMessageQueue = _wasmWorkerDelayedMessageQueue.forEach(_wasmWorkerRunPostMessage); | |
| // ... and finally register the proper postMessage handler that immediately | |
| // dispatches incoming function calls without queueing them. | |
| addEventListener('message', _wasmWorkerRunPostMessage); | |
| #if AUDIO_WORKLET | |
| } | |
| #endif | |
| }, | |
| _emscripten_create_wasm_worker__deps: [ | |
| '$_wasmWorkers', | |
| '$_wasmWorkerAppendToQueue', '$_wasmWorkerRunPostMessage', | |
| #if ASSERTIONS | |
| 'emscripten_has_threading_support', | |
| #endif | |
| ], | |
| _emscripten_create_wasm_worker__postset: ` | |
| if (ENVIRONMENT_IS_WASM_WORKER | |
| // AudioWorkletGlobalScope does not contain addEventListener | |
| #if AUDIO_WORKLET | |
| && !ENVIRONMENT_IS_AUDIO_WORKLET | |
| #endif | |
| ) { | |
| _wasmWorkers[0] = globalThis; | |
| addEventListener("message", _wasmWorkerAppendToQueue); | |
| }`, | |
| _emscripten_create_wasm_worker: (wwID, stackLowestAddress, stackSize, pthreadPtr) => { | |
| #if ASSERTIONS | |
| if (!_emscripten_has_threading_support()) { | |
| err('create_wasm_worker: environment does not support SharedArrayBuffer, wasm workers are not available'); | |
| return false; | |
| } | |
| #endif | |
| let worker; | |
| #if TRUSTED_TYPES | |
| // Use Trusted Types compatible wrappers. | |
| if (globalThis.trustedTypes?.createPolicy) { | |
| var p = trustedTypes.createPolicy( | |
| 'emscripten#workerPolicy1', { createScriptURL: (ignored) => {{{ wasmWorkerJs }}}} | |
| ); | |
| worker = _wasmWorkers[wwID] = new Worker(p.createScriptURL('ignored'), {{{ wasmWorkerOptions }}}); | |
| } else | |
| #endif | |
| worker = _wasmWorkers[wwID] = new Worker({{{ wasmWorkerJs }}}, {{{ wasmWorkerOptions }}}); | |
| // Craft the Module object for the Wasm Worker scope: | |
| worker.postMessage({ | |
| // Signal with a non-zero value that this Worker will be a Wasm Worker, | |
| // and not the main browser thread. | |
| wwID, | |
| wasm: wasmModule, | |
| wasmMemory, | |
| stackLowestAddress, | |
| stackSize, | |
| #if PTHREADS | |
| pthreadPtr, | |
| #endif | |
| }); | |
| worker.onmessage = _wasmWorkerRunPostMessage; | |
| #if ENVIRONMENT_MAY_BE_NODE | |
| if (ENVIRONMENT_IS_NODE) { | |
| /** @suppress {checkTypes} */ | |
| worker.on('message', (msg) => { | |
| if (msg['cmd'] == 'uncaughtException') { | |
| // Message handler for Node.js specific out-of-order behavior: | |
| // https://github.com/nodejs/node/issues/59617 | |
| // A worker sent an uncaught exception event. Re-raise it on the main thread. | |
| err(`worker sent an error! ${msg.error.message}`); | |
| throw msg.error; | |
| } else { | |
| worker.onmessage({ data: msg }); | |
| } | |
| }); | |
| } | |
| #endif | |
| #if RUNTIME_DEBUG | |
| dbg("done _emscripten_create_wasm_worker", wwID) | |
| #endif | |
| return true; | |
| }, | |
| emscripten_terminate_wasm_worker: (id) => { | |
| #if ASSERTIONS | |
| assert(id != 0, 'emscripten_terminate_wasm_worker() cannot be called with id=0'); | |
| #endif | |
| if (_wasmWorkers[id]) { | |
| _wasmWorkers[id].terminate(); | |
| delete _wasmWorkers[id]; | |
| } | |
| }, | |
| emscripten_terminate_all_wasm_workers: () => { | |
| #if ASSERTIONS | |
| assert(!ENVIRONMENT_IS_WASM_WORKER, 'emscripten_terminate_all_wasm_workers() should only be called from the main thread'); | |
| #endif | |
| Object.values(_wasmWorkers).forEach((worker) => worker.terminate()); | |
| _wasmWorkers = {}; | |
| }, | |
| emscripten_wasm_worker_post_function_v: (id, funcPtr) => { | |
| _wasmWorkers[id].postMessage({'_wsc': funcPtr, 'x': [] }); // "WaSm Call" | |
| }, | |
| $_wasmWorkerPostFunction1__sig: 'vipd', | |
| $_wasmWorkerPostFunction1: (id, funcPtr, arg0) => { | |
| _wasmWorkers[id].postMessage({'_wsc': funcPtr, 'x': [arg0] }); // "WaSm Call" | |
| }, | |
| emscripten_wasm_worker_post_function_vi: '$_wasmWorkerPostFunction1', | |
| emscripten_wasm_worker_post_function_vd: '$_wasmWorkerPostFunction1', | |
| $_wasmWorkerPostFunction2__sig: 'vipdd', | |
| $_wasmWorkerPostFunction2: (id, funcPtr, arg0, arg1) => { | |
| _wasmWorkers[id].postMessage({'_wsc': funcPtr, 'x': [arg0, arg1] }); // "WaSm Call" | |
| }, | |
| emscripten_wasm_worker_post_function_vii: '$_wasmWorkerPostFunction2', | |
| emscripten_wasm_worker_post_function_vdd: '$_wasmWorkerPostFunction2', | |
| $_wasmWorkerPostFunction3__sig: 'vipddd', | |
| $_wasmWorkerPostFunction3: (id, funcPtr, arg0, arg1, arg2) => { | |
| _wasmWorkers[id].postMessage({'_wsc': funcPtr, 'x': [arg0, arg1, arg2] }); // "WaSm Call" | |
| }, | |
| emscripten_wasm_worker_post_function_viii: '$_wasmWorkerPostFunction3', | |
| emscripten_wasm_worker_post_function_vddd: '$_wasmWorkerPostFunction3', | |
| emscripten_wasm_worker_post_function_sig__deps: ['$readEmAsmArgs'], | |
| emscripten_wasm_worker_post_function_sig: (id, funcPtr, sigPtr, varargs) => { | |
| #if ASSERTIONS | |
| assert(id >= 0); | |
| assert(funcPtr); | |
| assert(sigPtr); | |
| assert(UTF8ToString(sigPtr)[0] != 'v', 'emscripten_wasm_worker_post_function_sig() supports only void return type'); | |
| assert(varargs); | |
| #endif | |
| _wasmWorkers[id].postMessage({'_wsc': funcPtr, 'x': readEmAsmArgs(sigPtr, varargs) }); | |
| }, | |
| emscripten_navigator_hardware_concurrency: () => { | |
| #if ENVIRONMENT_MAY_BE_NODE | |
| if (ENVIRONMENT_IS_NODE) return require('node:os').cpus().length; | |
| #endif | |
| return navigator['hardwareConcurrency']; | |
| }, | |
| emscripten_lock_async_acquire__deps: ['$polyfillWaitAsync'], | |
| emscripten_lock_async_acquire: (lock, asyncWaitFinished, userData, maxWaitMilliseconds) => { | |
| let tryAcquireLock = () => { | |
| do { | |
| var val = Atomics.compareExchange(HEAP32, {{{ getHeapOffset('lock', 'i32') }}}, 0/*zero represents lock being free*/, 1/*one represents lock being acquired*/); | |
| if (!val) return {{{ makeDynCall('vpiip', 'asyncWaitFinished') }}}(lock, 0, 0/*'ok'*/, userData); | |
| var wait = Atomics.waitAsync(HEAP32, {{{ getHeapOffset('lock', 'i32') }}}, val, maxWaitMilliseconds); | |
| } while (wait.value === 'not-equal'); | |
| #if ASSERTIONS | |
| assert(wait.async || wait.value === 'timed-out'); | |
| #endif | |
| if (wait.async) wait.value.then(tryAcquireLock); | |
| else return {{{ makeDynCall('vpiip', 'asyncWaitFinished') }}}(lock, val, 2/*'timed-out'*/, userData); | |
| }; | |
| // Asynchronously dispatch acquiring the lock so that we have uniform control flow in both | |
| // cases when the lock is acquired, and when it needs to wait. | |
| setTimeout(tryAcquireLock); | |
| }, | |
| emscripten_semaphore_async_acquire__deps: ['$polyfillWaitAsync'], | |
| emscripten_semaphore_async_acquire: (sem, num, asyncWaitFinished, userData, maxWaitMilliseconds) => { | |
| let dispatch = (idx, ret) => { | |
| setTimeout(() => { | |
| {{{ makeDynCall('viiii', 'asyncWaitFinished') }}}(sem, /*val=*/idx, /*waitResult=*/ret, userData); | |
| }, 0); | |
| }; | |
| let tryAcquireSemaphore = () => { | |
| let val = num; | |
| do { | |
| let ret = Atomics.compareExchange(HEAP32, {{{ getHeapOffset('sem', 'i32') }}}, | |
| val, /* We expect this many semaphore resources to be available*/ | |
| val - num /* Acquire 'num' of them */); | |
| if (ret == val) return dispatch(ret/*index of resource acquired*/, 0/*'ok'*/); | |
| val = ret; | |
| let wait = Atomics.waitAsync(HEAP32, {{{ getHeapOffset('sem', 'i32') }}}, ret, maxWaitMilliseconds); | |
| } while (wait.value === 'not-equal'); | |
| #if ASSERTIONS | |
| assert(wait.async || wait.value === 'timed-out'); | |
| #endif | |
| if (wait.async) wait.value.then(tryAcquireSemaphore); | |
| else dispatch(-1/*idx*/, 2/*'timed-out'*/); | |
| }; | |
| tryAcquireSemaphore(); | |
| }, | |
| #if !PTHREADS | |
| // When pthreads are used we call `__set_thread_state` immediately on worker | |
| // creation. When wasm workers is used without pthreads, we call | |
| // `__set_thread_state` lazily to save code size for programs that don't use | |
| // the threads state. | |
| __do_set_thread_state__deps: ['__set_thread_state'], | |
| __do_set_thread_state: (tb) => { | |
| ___set_thread_state( | |
| /*thread_ptr=*/0, | |
| /*is_main_thread=*/!ENVIRONMENT_IS_WORKER, | |
| /*is_runtime_thread=*/!ENVIRONMENT_IS_WASM_WORKER, | |
| /*supports_wait=*/ENVIRONMENT_IS_WORKER && {{{ workerSupportsFutexWait() }}}); | |
| }, | |
| #endif | |
| }); | |
Xet Storage Details
- Size:
- 13.5 kB
- Xet hash:
- 7c98d747d356509bfb1c1ded2e8527d3d7ba0e19e803c71752d98288f8cc8375
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.