Jofthomas/Everchanging-Quest
187
1/**2 * @license3 * Copyright 2015 The Emscripten Authors4 * SPDX-License-Identifier: MIT5 */6 7// Pthread Web Worker startup routine:8// This is the entry point file that is loaded first by each Web Worker9// that executes pthreads on the Emscripten application.10 11'use strict';12 13var Module = {};14 15// Thread-local guard variable for one-time init of the JS state16var initializedJS = false;17 18function assert(condition, text) {19 if (!condition) abort('Assertion failed: ' + text);20}21 22function threadPrintErr() {23 var text = Array.prototype.slice.call(arguments).join(' ');24 console.error(text);25}26function threadAlert() {27 var text = Array.prototype.slice.call(arguments).join(' ');28 postMessage({cmd: 'alert', text, threadId: Module['_pthread_self']()});29}30// We don't need out() for now, but may need to add it if we want to use it31// here. Or, if this code all moves into the main JS, that problem will go32// away. (For now, adding it here increases code size for no benefit.)33var out = () => { throw 'out() is not defined in worker.js.'; }34var err = threadPrintErr;35self.alert = threadAlert;36var dbg = threadPrintErr;37 38Module['instantiateWasm'] = (info, receiveInstance) => {39 // Instantiate from the module posted from the main thread.40 // We can just use sync instantiation in the worker.41 var module = Module['wasmModule'];42 // We don't need the module anymore; new threads will be spawned from the main thread.43 Module['wasmModule'] = null;44 var instance = new WebAssembly.Instance(module, info);45 // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,46 // the above line no longer optimizes out down to the following line.47 // When the regression is fixed, we can remove this if/else.48 return receiveInstance(instance);49}50 51// Turn unhandled rejected promises into errors so that the main thread will be52// notified about them.53self.onunhandledrejection = (e) => {54 throw e.reason || e;55};56 57function handleMessage(e) {58 try {59 if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.60 61 // Until we initialize the runtime, queue up any further incoming messages.62 let messageQueue = [];63 self.onmessage = (e) => messageQueue.push(e);64 65 // And add a callback for when the runtime is initialized.66 self.startWorker = (instance) => {67 Module = instance;68 // Notify the main thread that this thread has loaded.69 postMessage({ 'cmd': 'loaded' });70 // Process any messages that were queued before the thread was ready.71 for (let msg of messageQueue) {72 handleMessage(msg);73 }74 // Restore the real message handler.75 self.onmessage = handleMessage;76 };77 78 // Module and memory were sent from main thread79 Module['wasmModule'] = e.data.wasmModule;80 81 // Use `const` here to ensure that the variable is scoped only to82 // that iteration, allowing safe reference from a closure.83 for (const handler of e.data.handlers) {84 Module[handler] = (...args) => {85 postMessage({ cmd: 'callHandler', handler, args: args });86 }87 }88 89 Module['wasmMemory'] = e.data.wasmMemory;90 91 Module['buffer'] = Module['wasmMemory'].buffer;92 93 Module['workerID'] = e.data.workerID;94 95 Module['ENVIRONMENT_IS_PTHREAD'] = true;96 97 if (typeof e.data.urlOrBlob == 'string') {98 importScripts(e.data.urlOrBlob);99 } else {100 var objectUrl = URL.createObjectURL(e.data.urlOrBlob);101 importScripts(objectUrl);102 URL.revokeObjectURL(objectUrl);103 }104 Godot(Module);105 } else if (e.data.cmd === 'run') {106 // Pass the thread address to wasm to store it for fast access.107 Module['__emscripten_thread_init'](e.data.pthread_ptr, /*is_main=*/0, /*is_runtime=*/0, /*can_block=*/1);108 109 // Await mailbox notifications with `Atomics.waitAsync` so we can start110 // using the fast `Atomics.notify` notification path.111 Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr);112 113 assert(e.data.pthread_ptr);114 // Also call inside JS module to set up the stack frame for this pthread in JS module scope115 Module['establishStackSpace']();116 Module['PThread'].receiveObjectTransfer(e.data);117 Module['PThread'].threadInitTLS();118 119 if (!initializedJS) {120 initializedJS = true;121 }122 123 try {124 Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);125 } catch(ex) {126 if (ex != 'unwind') {127 // The pthread "crashed". Do not call `_emscripten_thread_exit` (which128 // would make this thread joinable). Instead, re-throw the exception129 // and let the top level handler propagate it back to the main thread.130 throw ex;131 }132 }133 } else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread.134 if (Module['_pthread_self']()) {135 Module['__emscripten_thread_exit'](-1);136 }137 } else if (e.data.target === 'setimmediate') {138 // no-op139 } else if (e.data.cmd === 'checkMailbox') {140 if (initializedJS) {141 Module['checkMailbox']();142 }143 } else if (e.data.cmd) {144 // The received message looks like something that should be handled by this message145 // handler, (since there is a e.data.cmd field present), but is not one of the146 // recognized commands:147 err(`worker.js received unknown command ${e.data.cmd}`);148 err(e.data);149 }150 } catch(ex) {151 err(`worker.js onmessage() captured an uncaught exception: ${ex}`);152 if (ex?.stack) err(ex.stack);153 Module['__emscripten_thread_crashed']?.();154 throw ex;155 }156};157 158self.onmessage = handleMessage;159 