@emnapi/wasi-threads
Advanced tools
@@ -473,2 +473,32 @@ const _WebAssembly = typeof WebAssembly !== 'undefined' | ||
| const patchedWasiInstances = new WeakMap(); | ||
| const THREAD_SPAWN_RESULT_SIZE = Int32Array.BYTES_PER_ELEMENT * 2; | ||
| const sharedArrayBufferByteLength = typeof SharedArrayBuffer === 'function' | ||
| ? Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'byteLength').get | ||
| : undefined; | ||
| function isConclusivelySharedArrayBuffer(buffer) { | ||
| if (sharedArrayBufferByteLength === undefined) | ||
| return false; | ||
| try { | ||
| sharedArrayBufferByteLength.call(buffer); | ||
| return true; | ||
| } | ||
| catch (_) { | ||
| return false; | ||
| } | ||
| } | ||
| function getThreadSpawnResultView(memory, address, wasm64) { | ||
| const offset = typeof address === 'bigint' ? Number(address) : address >>> 0; | ||
| let buffer = memory.buffer; | ||
| if (offset + THREAD_SPAWN_RESULT_SIZE > buffer.byteLength && | ||
| isConclusivelySharedArrayBuffer(buffer)) { | ||
| if (wasm64) { | ||
| memory.grow(BigInt(0)); | ||
| } | ||
| else { | ||
| memory.grow(0); | ||
| } | ||
| buffer = memory.buffer; | ||
| } | ||
| return new Int32Array(buffer, offset, 2); | ||
| } | ||
| class WASIThreads { | ||
@@ -527,3 +557,3 @@ constructor(options) { | ||
| if (isNewABI) { | ||
| const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2); | ||
| const struct = getThreadSpawnResultView(this.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 1); | ||
@@ -547,3 +577,3 @@ Atomics.store(struct, 1, EAGAIN); | ||
| const free = wasm64 ? (ptr) => { _free(BigInt(ptr)); } : _free; | ||
| const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2); | ||
| const struct = getThreadSpawnResultView(this.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 0); | ||
@@ -550,0 +580,0 @@ Atomics.store(struct, 1, 0); |
@@ -1,1 +0,1 @@ | ||
| const e="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,t="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function r(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function s(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function o(t){try{return t instanceof e.RuntimeError}catch(e){return!1}}function n(e,t){return{__emnapi__:{type:e,payload:t}}}function i(e){if(e){if(!s(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}let a=0;class d{get nextWorkerID(){return a}constructor(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;const r=null!==(t=Number(e.size))&&void 0!==t?t:0,s=Boolean(e.strict);if(!(r>0)&&s)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:s}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}init(){this._childThread||this.initMainThread()}initMainThread(){this.preparePool()}preparePool(){if(this._reuseWorker&&this._reuseWorker.size){let e=this._reuseWorker.size;for(;e--;){const e=this.allocateUnusedWorker();t&&(e.once("message",()=>{}),e.unref())}}}shouldPreloadWorkers(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0}loadWasmModuleToAllWorkers(){const e=Array(this.unusedWorkers.length);for(let r=0;r<this.unusedWorkers.length;++r){const s=this.unusedWorkers[r];t&&s.ref(),e[r]=this.loadWasmModuleToWorker(s).then(e=>(t&&s.unref(),e),e=>{throw t&&s.unref(),e})}return Promise.all(e).catch(e=>{throw this.terminateAllThreads(),e})}preloadWorkers(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])}setup(e,t){this.wasmModule=e,this.wasmMemory=t}markId(e){if(e.__emnapi_tid)return e.__emnapi_tid;const t=a+43;return a=(a+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t}returnWorkerToPool(e){var r=e.__emnapi_tid;void 0!==r&&delete this.pthreads[r],this.unusedWorkers.push(e),delete e.__emnapi_tid,t&&e.unref()}loadWasmModuleToWorker(e,r){if(e.whenLoaded)return e.whenLoaded;const s=this.printErr,o=this._beforeLoad,a=this;return e.whenLoaded=new Promise((d,h)=>{const l=r=>{if(r.__emnapi__){const s=r.__emnapi__.type,o=r.__emnapi__.payload;"loaded"===s?(e.loaded=!0,t&&!e.__emnapi_tid&&e.unref(),d(e)):"cleanup-thread"===s?o.tid in this.pthreads&&this.cleanThread(e,o.tid):"spawn-thread"===s?this.threadSpawn(o.startArg,o.errorOrTid):"terminate-all-threads"===s&&this.terminateAllThreads()}};e.onmessage=t=>{l(t.data),this.fireMessageEvent(e,t)},e.onerror=function(t){let r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(s(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{a.terminateAllThreads()}catch(e){}}else s(r);throw h(t),t},t&&(e.on("message",function(t){var r,s;null===(s=(r=e).onmessage)||void 0===s||s.call(r,{data:t})}),e.on("error",function(t){var r,s;null===(s=(r=e).onerror)||void 0===s||s.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof o&&o(e);try{e.postMessage(n("load",{wasmModule:this.wasmModule,wasmMemory:this.wasmMemory,sab:r}))}catch(e){throw i(this.wasmMemory),e}}),e.whenLoaded}allocateUnusedWorker(){const e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");const t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t}getNewWorker(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict&&!t){return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.")}const r=this.allocateUnusedWorker();this.loadWasmModuleToWorker(r,e)}return this.unusedWorkers.pop()}const r=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(r,e),this.unusedWorkers.pop()}cleanThread(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)}terminateWorker(e){var t;const r=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=e=>{if(e.data.__emnapi__){(0,this.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+r)}}}terminateAllThreads(){const e=Object.values(this.pthreads);for(let t=0;t<e.length;++t)this.terminateWorker(e[t]);for(let e=0;e<this.unusedWorkers.length;++e)this.terminateWorker(this.unusedWorkers[e]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()}addMessageEventListener(e,t){let r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),()=>{null==r||r.delete(t)}}fireMessageEvent(e,t){const r=this.messageEvents.get(e);if(!r)return;const s=this.printErr;r.forEach(e=>{try{e(t)}catch(e){s(e.stack)}})}}const h=Symbol("kIsProxy");function l(e,t){if(e[h])return e;const r=e.exports,s=function(e){const t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={};for(let s=0;s<t.length;s++){const o=t[s];r[o]=function(){const t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[o].apply(Reflect,t)}}return r}(r),o=()=>{},n=()=>0;s.get=function(e,s,i){var a;return"memory"===s?null!==(a="function"==typeof t?t():t)&&void 0!==a?a:Reflect.get(r,s,i):"_initialize"===s?s in r?o:void 0:"_start"===s?s in r?n:void 0:Reflect.get(r,s,i)},s.has=function(e,t){return"memory"===t||Reflect.has(r,t)};const i=new Proxy(Object.create(null),s);return new Proxy(e,{get:(e,t,r)=>"exports"===t?i:t===h||Reflect.get(e,t,r)})}const c=new WeakMap;function u(e,t){const r=Object.getOwnPropertySymbols(e),s=e=>t=>t.description?t.description===e:t.toString()===`Symbol(${e})`;return Array.isArray(t)?t.map(e=>r.filter(s(e))[0]):r.filter(s(t))[0]}function f(e,t,r){e&&(!function(e,t,r){const s=new Int32Array(e);if(Atomics.store(s,0,t),t>1&&r){const t=r.name,o=r.message,n=r.stack,i=(new TextEncoder).encode(t),a=(new TextEncoder).encode(o),d=(new TextEncoder).encode(n);Atomics.store(s,1,i.length),Atomics.store(s,2,a.length),Atomics.store(s,3,d.length);const h=new Uint8Array(e);h.set(i,16),h.set(a,16+i.length),h.set(d,16+i.length+a.length)}}(e.buffer,t,r),Atomics.notify(e,0))}exports.ThreadManager=d,exports.ThreadMessageHandler=class{constructor(e){const t=r(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:(e,t)=>{throw t},this.instance=void 0,this.messagesBeforeLoad=[]}instantiate(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")}handle(e){var t;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){const t=e.data.__emnapi__.type,r=e.data.__emnapi__.payload;try{"load"===t?this._load(r):"start"===t&&this.handleAfterLoad(e,()=>{this._start(r)})}catch(e){this.onError(e,t)}}}_load(e){if(void 0!==this.instance)return;let t;try{t=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}const r=t&&"then"in t?t.then:void 0;"function"==typeof r?r.call(t,t=>{this._loaded(null,t,e)},t=>{this._loaded(t,null,e)}):this._loaded(null,t,e)}_start(e){const t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){const t=new TypeError("wasi_thread_start is not exported");throw f(e.sab,2,t),t}const r=this.postMessage,s=e.tid,o=e.arg;f(e.sab,1);try{t(s,o)}catch(e){if("unwind"!==e)throw e;return}r(n("cleanup-thread",{tid:s}))}_loaded(e,t,r){if(e)throw f(r.sab,2,e),e;if(null==t){const e=new TypeError("onLoad should return an object");throw f(r.sab,2,e),e}const s=t.instance;if(!s){const e=new TypeError('onLoad should return an object which includes "instance"');throw f(r.sab,2,e),e}this.instance=s;(0,this.postMessage)(n("loaded",{}));const o=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(let e=0;e<o.length;e++){const t=o[e];this.handle({data:t})}}handleAfterLoad(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)}},exports.WASIThreads=class{constructor(s){if(!s)throw new TypeError("WASIThreads(): options is not provided");if(!s.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");c.set(this,new WeakSet);const a=s.wasi;!function(e,t){const r=c.get(e);if(r.has(t))return;const s=e,n=t.wasiImport;if(n){const e=n.proc_exit;n.proc_exit=function(t){return s.terminateAllThreads(),e.call(this,t)}}if(!s.childThread){const e=t.start;"function"==typeof e&&(t.start=function(t){try{return e.call(this,t)}catch(e){throw o(e)&&s.terminateAllThreads(),e}})}r.add(t)}(this,a),this.wasi=a,this.childThread="childThread"in s&&Boolean(s.childThread),this.PThread=void 0,"threadManager"in s?"function"==typeof s.threadManager?this.PThread=s.threadManager():this.PThread=s.threadManager:this.childThread||(this.PThread=new d(s),this.PThread.init());let h=!1;"waitThreadStart"in s&&(h="number"==typeof s.waitThreadStart?s.waitThreadStart:Boolean(s.waitThreadStart));const l=r(s);if(this.childThread&&"function"!=typeof l)throw new TypeError("options.postMessage is not a function");this.postMessage=l;const u=Boolean(s.wasm64),f=(r,s)=>{var o;const a=void 0!==s;try{i(this.wasmMemory)}catch(e){if(null===(o=this.PThread)||void 0===o||o.printErr(e.stack),a){const e=new Int32Array(this.wasmMemory.buffer,s,2);return Atomics.store(e,0,1),Atomics.store(e,1,6),Atomics.notify(e,1),1}return-6}if(!a){const e=this.wasmInstance.exports.malloc;if(!(s=u?Number(e(BigInt(8))):e(8)>>>0))return-48}const d=this.wasmInstance.exports.free,c=u?e=>{d(BigInt(e))}:d,f=new Int32Array(this.wasmMemory.buffer,s,2);if(Atomics.store(f,0,0),Atomics.store(f,1,0),this.childThread){l(n("spawn-thread",{startArg:r,errorOrTid:s})),Atomics.wait(f,1,0);const e=Atomics.load(f,0),t=Atomics.load(f,1);return a?e:(c(s),e?-t:t)}const p=h||0===h;let m,w,y;p&&(m=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(m,0,0));const _=this.PThread;try{if(w=_.getNewWorker(m),!w)throw new Error("failed to get new worker");if(y=_.markId(w),t&&w.unref(),w.postMessage(n("start",{tid:y,arg:r,sab:m})),p){if("number"==typeof h){if("timed-out"===Atomics.wait(m,0,0,h))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(m,0,0);if(Atomics.load(m,0)>1)throw function(t){var r,s;const o=new Int32Array(t);if(Atomics.load(o,0)<=1)return null;const n=Atomics.load(o,1),i=Atomics.load(o,2),a=Atomics.load(o,3),d=new Uint8Array(t),h=d.slice(16,16+n),l=d.slice(16+n,16+n+i),c=d.slice(16+n+i,16+n+i+a),u=(new TextDecoder).decode(h),f=(new TextDecoder).decode(l),p=(new TextDecoder).decode(c),m=new(null!==(r=globalThis[u])&&void 0!==r?r:"RuntimeError"===u&&null!==(s=e.RuntimeError)&&void 0!==s?s:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(m.buffer)}}catch(e){if(void 0!==w&&void 0!==y)try{_.cleanThread(w,y,!0)}catch(e){}return Atomics.store(f,0,1),Atomics.store(f,1,6),Atomics.notify(f,1),null==_||_.printErr(e.stack),a?1:(c(s),-6)}return Atomics.store(f,0,0),Atomics.store(f,1,y),Atomics.notify(f,1),p||w.whenLoaded.catch(e=>{throw delete w.whenLoaded,_.cleanThread(w,y,!0),e}),a?0:(c(s),y)};this.threadSpawn=f,this.PThread&&(this.PThread.threadSpawn=f)}getImportObject(){return{wasi:{"thread-spawn":this.threadSpawn}}}setup(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)}preloadWorkers(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])}initialize(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);const o=this.wasi;if("_start"in s&&"function"==typeof s._start)if(this.childThread){o.start(e);try{o[u(o,"kStarted")]=!1}catch(e){}}else!function(e,t){const[r,s]=u(e,["kInstance","kSetMemory"]);e[r]=t,e[s](t.exports.memory)}(o,e);else o.initialize(e);return e}start(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);return{exitCode:this.wasi.start(e),instance:e}}terminateAllThreads(){var e;this.childThread?this.postMessage(n("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()}},exports.createInstanceProxy=l,exports.isSharedArrayBuffer=s,exports.isTrapError=o; | ||
| const e="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,t="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function r(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function s(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function o(t){try{return t instanceof e.RuntimeError}catch(e){return!1}}function n(e,t){return{__emnapi__:{type:e,payload:t}}}function i(e){if(e){if(!s(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}let a=0;class h{get nextWorkerID(){return a}constructor(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;const r=null!==(t=Number(e.size))&&void 0!==t?t:0,s=Boolean(e.strict);if(!(r>0)&&s)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:s}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}init(){this._childThread||this.initMainThread()}initMainThread(){this.preparePool()}preparePool(){if(this._reuseWorker&&this._reuseWorker.size){let e=this._reuseWorker.size;for(;e--;){const e=this.allocateUnusedWorker();t&&(e.once("message",()=>{}),e.unref())}}}shouldPreloadWorkers(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0}loadWasmModuleToAllWorkers(){const e=Array(this.unusedWorkers.length);for(let r=0;r<this.unusedWorkers.length;++r){const s=this.unusedWorkers[r];t&&s.ref(),e[r]=this.loadWasmModuleToWorker(s).then(e=>(t&&s.unref(),e),e=>{throw t&&s.unref(),e})}return Promise.all(e).catch(e=>{throw this.terminateAllThreads(),e})}preloadWorkers(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])}setup(e,t){this.wasmModule=e,this.wasmMemory=t}markId(e){if(e.__emnapi_tid)return e.__emnapi_tid;const t=a+43;return a=(a+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t}returnWorkerToPool(e){var r=e.__emnapi_tid;void 0!==r&&delete this.pthreads[r],this.unusedWorkers.push(e),delete e.__emnapi_tid,t&&e.unref()}loadWasmModuleToWorker(e,r){if(e.whenLoaded)return e.whenLoaded;const s=this.printErr,o=this._beforeLoad,a=this;return e.whenLoaded=new Promise((h,d)=>{const l=r=>{if(r.__emnapi__){const s=r.__emnapi__.type,o=r.__emnapi__.payload;"loaded"===s?(e.loaded=!0,t&&!e.__emnapi_tid&&e.unref(),h(e)):"cleanup-thread"===s?o.tid in this.pthreads&&this.cleanThread(e,o.tid):"spawn-thread"===s?this.threadSpawn(o.startArg,o.errorOrTid):"terminate-all-threads"===s&&this.terminateAllThreads()}};e.onmessage=t=>{l(t.data),this.fireMessageEvent(e,t)},e.onerror=function(t){let r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(s(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{a.terminateAllThreads()}catch(e){}}else s(r);throw d(t),t},t&&(e.on("message",function(t){var r,s;null===(s=(r=e).onmessage)||void 0===s||s.call(r,{data:t})}),e.on("error",function(t){var r,s;null===(s=(r=e).onerror)||void 0===s||s.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof o&&o(e);try{e.postMessage(n("load",{wasmModule:this.wasmModule,wasmMemory:this.wasmMemory,sab:r}))}catch(e){throw i(this.wasmMemory),e}}),e.whenLoaded}allocateUnusedWorker(){const e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");const t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t}getNewWorker(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict&&!t){return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.")}const r=this.allocateUnusedWorker();this.loadWasmModuleToWorker(r,e)}return this.unusedWorkers.pop()}const r=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(r,e),this.unusedWorkers.pop()}cleanThread(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)}terminateWorker(e){var t;const r=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=e=>{if(e.data.__emnapi__){(0,this.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+r)}}}terminateAllThreads(){const e=Object.values(this.pthreads);for(let t=0;t<e.length;++t)this.terminateWorker(e[t]);for(let e=0;e<this.unusedWorkers.length;++e)this.terminateWorker(this.unusedWorkers[e]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()}addMessageEventListener(e,t){let r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),()=>{null==r||r.delete(t)}}fireMessageEvent(e,t){const r=this.messageEvents.get(e);if(!r)return;const s=this.printErr;r.forEach(e=>{try{e(t)}catch(e){s(e.stack)}})}}const d=Symbol("kIsProxy");function l(e,t){if(e[d])return e;const r=e.exports,s=function(e){const t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={};for(let s=0;s<t.length;s++){const o=t[s];r[o]=function(){const t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[o].apply(Reflect,t)}}return r}(r),o=()=>{},n=()=>0;s.get=function(e,s,i){var a;return"memory"===s?null!==(a="function"==typeof t?t():t)&&void 0!==a?a:Reflect.get(r,s,i):"_initialize"===s?s in r?o:void 0:"_start"===s?s in r?n:void 0:Reflect.get(r,s,i)},s.has=function(e,t){return"memory"===t||Reflect.has(r,t)};const i=new Proxy(Object.create(null),s);return new Proxy(e,{get:(e,t,r)=>"exports"===t?i:t===d||Reflect.get(e,t,r)})}const c=new WeakMap,u=2*Int32Array.BYTES_PER_ELEMENT,f="function"==typeof SharedArrayBuffer?Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype,"byteLength").get:void 0;function p(e,t,r){const s="bigint"==typeof t?Number(t):t>>>0;let o=e.buffer;return s+u>o.byteLength&&function(e){if(void 0===f)return!1;try{return f.call(e),!0}catch(e){return!1}}(o)&&(r?e.grow(BigInt(0)):e.grow(0),o=e.buffer),new Int32Array(o,s,2)}function m(e,t){const r=Object.getOwnPropertySymbols(e),s=e=>t=>t.description?t.description===e:t.toString()===`Symbol(${e})`;return Array.isArray(t)?t.map(e=>r.filter(s(e))[0]):r.filter(s(t))[0]}function w(e,t,r){e&&(!function(e,t,r){const s=new Int32Array(e);if(Atomics.store(s,0,t),t>1&&r){const t=r.name,o=r.message,n=r.stack,i=(new TextEncoder).encode(t),a=(new TextEncoder).encode(o),h=(new TextEncoder).encode(n);Atomics.store(s,1,i.length),Atomics.store(s,2,a.length),Atomics.store(s,3,h.length);const d=new Uint8Array(e);d.set(i,16),d.set(a,16+i.length),d.set(h,16+i.length+a.length)}}(e.buffer,t,r),Atomics.notify(e,0))}exports.ThreadManager=h,exports.ThreadMessageHandler=class{constructor(e){const t=r(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:(e,t)=>{throw t},this.instance=void 0,this.messagesBeforeLoad=[]}instantiate(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")}handle(e){var t;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){const t=e.data.__emnapi__.type,r=e.data.__emnapi__.payload;try{"load"===t?this._load(r):"start"===t&&this.handleAfterLoad(e,()=>{this._start(r)})}catch(e){this.onError(e,t)}}}_load(e){if(void 0!==this.instance)return;let t;try{t=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}const r=t&&"then"in t?t.then:void 0;"function"==typeof r?r.call(t,t=>{this._loaded(null,t,e)},t=>{this._loaded(t,null,e)}):this._loaded(null,t,e)}_start(e){const t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){const t=new TypeError("wasi_thread_start is not exported");throw w(e.sab,2,t),t}const r=this.postMessage,s=e.tid,o=e.arg;w(e.sab,1);try{t(s,o)}catch(e){if("unwind"!==e)throw e;return}r(n("cleanup-thread",{tid:s}))}_loaded(e,t,r){if(e)throw w(r.sab,2,e),e;if(null==t){const e=new TypeError("onLoad should return an object");throw w(r.sab,2,e),e}const s=t.instance;if(!s){const e=new TypeError('onLoad should return an object which includes "instance"');throw w(r.sab,2,e),e}this.instance=s;(0,this.postMessage)(n("loaded",{}));const o=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(let e=0;e<o.length;e++){const t=o[e];this.handle({data:t})}}handleAfterLoad(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)}},exports.WASIThreads=class{constructor(s){if(!s)throw new TypeError("WASIThreads(): options is not provided");if(!s.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");c.set(this,new WeakSet);const a=s.wasi;!function(e,t){const r=c.get(e);if(r.has(t))return;const s=e,n=t.wasiImport;if(n){const e=n.proc_exit;n.proc_exit=function(t){return s.terminateAllThreads(),e.call(this,t)}}if(!s.childThread){const e=t.start;"function"==typeof e&&(t.start=function(t){try{return e.call(this,t)}catch(e){throw o(e)&&s.terminateAllThreads(),e}})}r.add(t)}(this,a),this.wasi=a,this.childThread="childThread"in s&&Boolean(s.childThread),this.PThread=void 0,"threadManager"in s?"function"==typeof s.threadManager?this.PThread=s.threadManager():this.PThread=s.threadManager:this.childThread||(this.PThread=new h(s),this.PThread.init());let d=!1;"waitThreadStart"in s&&(d="number"==typeof s.waitThreadStart?s.waitThreadStart:Boolean(s.waitThreadStart));const l=r(s);if(this.childThread&&"function"!=typeof l)throw new TypeError("options.postMessage is not a function");this.postMessage=l;const u=Boolean(s.wasm64),f=(r,s)=>{var o;const a=void 0!==s;try{i(this.wasmMemory)}catch(e){if(null===(o=this.PThread)||void 0===o||o.printErr(e.stack),a){const e=p(this.wasmMemory,s,u);return Atomics.store(e,0,1),Atomics.store(e,1,6),Atomics.notify(e,1),1}return-6}if(!a){const e=this.wasmInstance.exports.malloc;if(!(s=u?Number(e(BigInt(8))):e(8)>>>0))return-48}const h=this.wasmInstance.exports.free,c=u?e=>{h(BigInt(e))}:h,f=p(this.wasmMemory,s,u);if(Atomics.store(f,0,0),Atomics.store(f,1,0),this.childThread){l(n("spawn-thread",{startArg:r,errorOrTid:s})),Atomics.wait(f,1,0);const e=Atomics.load(f,0),t=Atomics.load(f,1);return a?e:(c(s),e?-t:t)}const m=d||0===d;let w,y,_;m&&(w=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(w,0,0));const g=this.PThread;try{if(y=g.getNewWorker(w),!y)throw new Error("failed to get new worker");if(_=g.markId(y),t&&y.unref(),y.postMessage(n("start",{tid:_,arg:r,sab:w})),m){if("number"==typeof d){if("timed-out"===Atomics.wait(w,0,0,d))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(w,0,0);if(Atomics.load(w,0)>1)throw function(t){var r,s;const o=new Int32Array(t);if(Atomics.load(o,0)<=1)return null;const n=Atomics.load(o,1),i=Atomics.load(o,2),a=Atomics.load(o,3),h=new Uint8Array(t),d=h.slice(16,16+n),l=h.slice(16+n,16+n+i),c=h.slice(16+n+i,16+n+i+a),u=(new TextDecoder).decode(d),f=(new TextDecoder).decode(l),p=(new TextDecoder).decode(c),m=new(null!==(r=globalThis[u])&&void 0!==r?r:"RuntimeError"===u&&null!==(s=e.RuntimeError)&&void 0!==s?s:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(w.buffer)}}catch(e){if(void 0!==y&&void 0!==_)try{g.cleanThread(y,_,!0)}catch(e){}return Atomics.store(f,0,1),Atomics.store(f,1,6),Atomics.notify(f,1),null==g||g.printErr(e.stack),a?1:(c(s),-6)}return Atomics.store(f,0,0),Atomics.store(f,1,_),Atomics.notify(f,1),m||y.whenLoaded.catch(e=>{throw delete y.whenLoaded,g.cleanThread(y,_,!0),e}),a?0:(c(s),_)};this.threadSpawn=f,this.PThread&&(this.PThread.threadSpawn=f)}getImportObject(){return{wasi:{"thread-spawn":this.threadSpawn}}}setup(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)}preloadWorkers(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])}initialize(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);const o=this.wasi;if("_start"in s&&"function"==typeof s._start)if(this.childThread){o.start(e);try{o[m(o,"kStarted")]=!1}catch(e){}}else!function(e,t){const[r,s]=m(e,["kInstance","kSetMemory"]);e[r]=t,e[s](t.exports.memory)}(o,e);else o.initialize(e);return e}start(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);return{exitCode:this.wasi.start(e),instance:e}}terminateAllThreads(){var e;this.childThread?this.postMessage(n("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()}},exports.createInstanceProxy=l,exports.isSharedArrayBuffer=s,exports.isTrapError=o; |
@@ -501,2 +501,44 @@ var _WebAssembly = typeof WebAssembly !== 'undefined' | ||
| var patchedWasiInstances = new WeakMap(); | ||
| var THREAD_SPAWN_RESULT_SIZE = Int32Array.BYTES_PER_ELEMENT * 2; | ||
| // Intrinsic SharedArrayBuffer.prototype.byteLength getter: it reads the | ||
| // internal slot, so it is a conclusive brand check that a spoofed own | ||
| // Symbol.toStringTag (which fools Object.prototype.toString) cannot satisfy. | ||
| var sharedArrayBufferByteLength = typeof SharedArrayBuffer === 'function' | ||
| ? Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'byteLength').get | ||
| : undefined; | ||
| function isConclusivelySharedArrayBuffer(buffer) { | ||
| if (sharedArrayBufferByteLength === undefined) | ||
| return false; | ||
| try { | ||
| sharedArrayBufferByteLength.call(buffer); | ||
| return true; | ||
| } | ||
| catch (_) { | ||
| return false; | ||
| } | ||
| } | ||
| function getThreadSpawnResultView(memory, address, wasm64) { | ||
| // The result pointer arrives across the wasm ABI: an i64 (memory64) address | ||
| // is a bigint, and an upper-half i32 address is a negative Number. Normalize | ||
| // it the way malloc results are normalized elsewhere in this file. | ||
| var offset = typeof address === 'bigint' ? Number(address) : address >>> 0; | ||
| var buffer = memory.buffer; | ||
| if (offset + THREAD_SPAWN_RESULT_SIZE > buffer.byteLength && | ||
| // Only refresh shared memory. A conclusive brand check is required here: | ||
| // grow(0) detaches an *unshared* buffer (spec: even at delta 0), so a | ||
| // spoofed 'SharedArrayBuffer' tag must never be allowed to reach it. | ||
| isConclusivelySharedArrayBuffer(buffer)) { | ||
| // Another agent may have grown shared memory while this agent still sees | ||
| // the previous shorter buffer. A zero-page grow refreshes the local view | ||
| // without changing the memory size. | ||
| if (wasm64) { | ||
| memory.grow(BigInt(0)); | ||
| } | ||
| else { | ||
| memory.grow(0); | ||
| } | ||
| buffer = memory.buffer; | ||
| } | ||
| return new Int32Array(buffer, offset, 2); | ||
| } | ||
| /** @public */ | ||
@@ -557,3 +599,3 @@ var WASIThreads = /*#__PURE__*/ (function () { | ||
| if (isNewABI) { | ||
| var struct_1 = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2); | ||
| var struct_1 = getThreadSpawnResultView(_this_1.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct_1, 0, 1); | ||
@@ -577,3 +619,3 @@ Atomics.store(struct_1, 1, EAGAIN); | ||
| var free = wasm64 ? function (ptr) { _free(BigInt(ptr)); } : _free; | ||
| var struct = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2); | ||
| var struct = getThreadSpawnResultView(_this_1.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 0); | ||
@@ -580,0 +622,0 @@ Atomics.store(struct, 1, 0); |
+44
-2
@@ -506,2 +506,44 @@ (function (global, factory) { | ||
| var patchedWasiInstances = new WeakMap(); | ||
| var THREAD_SPAWN_RESULT_SIZE = Int32Array.BYTES_PER_ELEMENT * 2; | ||
| // Intrinsic SharedArrayBuffer.prototype.byteLength getter: it reads the | ||
| // internal slot, so it is a conclusive brand check that a spoofed own | ||
| // Symbol.toStringTag (which fools Object.prototype.toString) cannot satisfy. | ||
| var sharedArrayBufferByteLength = typeof SharedArrayBuffer === 'function' | ||
| ? Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'byteLength').get | ||
| : undefined; | ||
| function isConclusivelySharedArrayBuffer(buffer) { | ||
| if (sharedArrayBufferByteLength === undefined) | ||
| return false; | ||
| try { | ||
| sharedArrayBufferByteLength.call(buffer); | ||
| return true; | ||
| } | ||
| catch (_) { | ||
| return false; | ||
| } | ||
| } | ||
| function getThreadSpawnResultView(memory, address, wasm64) { | ||
| // The result pointer arrives across the wasm ABI: an i64 (memory64) address | ||
| // is a bigint, and an upper-half i32 address is a negative Number. Normalize | ||
| // it the way malloc results are normalized elsewhere in this file. | ||
| var offset = typeof address === 'bigint' ? Number(address) : address >>> 0; | ||
| var buffer = memory.buffer; | ||
| if (offset + THREAD_SPAWN_RESULT_SIZE > buffer.byteLength && | ||
| // Only refresh shared memory. A conclusive brand check is required here: | ||
| // grow(0) detaches an *unshared* buffer (spec: even at delta 0), so a | ||
| // spoofed 'SharedArrayBuffer' tag must never be allowed to reach it. | ||
| isConclusivelySharedArrayBuffer(buffer)) { | ||
| // Another agent may have grown shared memory while this agent still sees | ||
| // the previous shorter buffer. A zero-page grow refreshes the local view | ||
| // without changing the memory size. | ||
| if (wasm64) { | ||
| memory.grow(BigInt(0)); | ||
| } | ||
| else { | ||
| memory.grow(0); | ||
| } | ||
| buffer = memory.buffer; | ||
| } | ||
| return new Int32Array(buffer, offset, 2); | ||
| } | ||
| /** @public */ | ||
@@ -562,3 +604,3 @@ var WASIThreads = /*#__PURE__*/ (function () { | ||
| if (isNewABI) { | ||
| var struct_1 = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2); | ||
| var struct_1 = getThreadSpawnResultView(_this_1.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct_1, 0, 1); | ||
@@ -582,3 +624,3 @@ Atomics.store(struct_1, 1, EAGAIN); | ||
| var free = wasm64 ? function (ptr) { _free(BigInt(ptr)); } : _free; | ||
| var struct = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2); | ||
| var struct = getThreadSpawnResultView(_this_1.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 0); | ||
@@ -585,0 +627,0 @@ Atomics.store(struct, 1, 0); |
@@ -1,1 +0,1 @@ | ||
| !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).wasiThreads={})}(this,function(e){var t="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,r="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function o(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function n(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function i(e){try{return e instanceof t.RuntimeError}catch(e){return!1}}function a(e,t){return{__emnapi__:{type:e,payload:t}}}function s(e){if(e){if(!n(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}var d=0,h=function(){function e(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;var r=null!==(t=Number(e.size))&&void 0!==t?t:0,o=Boolean(e.strict);if(!(r>0)&&o)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:o}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}return Object.defineProperty(e.prototype,"nextWorkerID",{get:function(){return d},enumerable:!1,configurable:!0}),e.prototype.init=function(){this._childThread||this.initMainThread()},e.prototype.initMainThread=function(){this.preparePool()},e.prototype.preparePool=function(){if(this._reuseWorker&&this._reuseWorker.size)for(var e=this._reuseWorker.size;e--;){var t=this.allocateUnusedWorker();r&&(t.once("message",function(){}),t.unref())}},e.prototype.shouldPreloadWorkers=function(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0},e.prototype.loadWasmModuleToAllWorkers=function(){for(var e=this,t=Array(this.unusedWorkers.length),o=function(e){var o=n.unusedWorkers[e];r&&o.ref(),t[e]=n.loadWasmModuleToWorker(o).then(function(e){return r&&o.unref(),e},function(e){throw r&&o.unref(),e})},n=this,i=0;i<this.unusedWorkers.length;++i)o(i);return Promise.all(t).catch(function(t){throw e.terminateAllThreads(),t})},e.prototype.preloadWorkers=function(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])},e.prototype.setup=function(e,t){this.wasmModule=e,this.wasmMemory=t},e.prototype.markId=function(e){if(e.__emnapi_tid)return e.__emnapi_tid;var t=d+43;return d=(d+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t},e.prototype.returnWorkerToPool=function(e){var t=e.__emnapi_tid;void 0!==t&&delete this.pthreads[t],this.unusedWorkers.push(e),delete e.__emnapi_tid,r&&e.unref()},e.prototype.loadWasmModuleToWorker=function(e,t){var o=this;if(e.whenLoaded)return e.whenLoaded;var n=this.printErr,i=this._beforeLoad,d=this;return e.whenLoaded=new Promise(function(h,u){e.onmessage=function(t){!function(t){if(t.__emnapi__){var n=t.__emnapi__.type,i=t.__emnapi__.payload;"loaded"===n?(e.loaded=!0,r&&!e.__emnapi_tid&&e.unref(),h(e)):"cleanup-thread"===n?i.tid in o.pthreads&&o.cleanThread(e,i.tid):"spawn-thread"===n?o.threadSpawn(i.startArg,i.errorOrTid):"terminate-all-threads"===n&&o.terminateAllThreads()}}(t.data),o.fireMessageEvent(e,t)},e.onerror=function(t){var r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(n(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{d.terminateAllThreads()}catch(e){}}else n(r);throw u(t),t},r&&(e.on("message",function(t){var r,o;null===(o=(r=e).onmessage)||void 0===o||o.call(r,{data:t})}),e.on("error",function(t){var r,o;null===(o=(r=e).onerror)||void 0===o||o.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof i&&i(e);try{e.postMessage(a("load",{wasmModule:o.wasmModule,wasmMemory:o.wasmMemory,sab:t}))}catch(e){throw s(o.wasmMemory),e}}),e.whenLoaded},e.prototype.allocateUnusedWorker=function(){var e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");var t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t},e.prototype.getNewWorker=function(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict)if(!r)return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.");var t=this.allocateUnusedWorker();this.loadWasmModuleToWorker(t,e)}return this.unusedWorkers.pop()}var o=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(o,e),this.unusedWorkers.pop()},e.prototype.cleanThread=function(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)},e.prototype.terminateWorker=function(e){var t,r=this,o=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=function(e){e.data.__emnapi__&&(0,r.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+o)}},e.prototype.terminateAllThreads=function(){for(var e=Object.values(this.pthreads),t=0;t<e.length;++t)this.terminateWorker(e[t]);for(t=0;t<this.unusedWorkers.length;++t)this.terminateWorker(this.unusedWorkers[t]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()},e.prototype.addMessageEventListener=function(e,t){var r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),function(){null==r||r.delete(t)}},e.prototype.fireMessageEvent=function(e,t){var r=this.messageEvents.get(e);if(r){var o=this.printErr;r.forEach(function(e){try{e(t)}catch(e){o(e.stack)}})}},e}(),u=Symbol("kIsProxy");function l(e,t){if(e[u])return e;var r=e.exports,o=function(e){for(var t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={},o=function(o){var n=t[o];r[n]=function(){var t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[n].apply(Reflect,t)}},n=0;n<t.length;n++)o(n);return r}(r),n=function(){},i=function(){return 0};o.get=function(e,o,a){var s;return"memory"===o?null!==(s="function"==typeof t?t():t)&&void 0!==s?s:Reflect.get(r,o,a):"_initialize"===o?o in r?n:void 0:"_start"===o?o in r?i:void 0:Reflect.get(r,o,a)},o.has=function(e,t){return"memory"===t||Reflect.has(r,t)};var a=new Proxy(Object.create(null),o);return new Proxy(e,{get:function(e,t,r){return"exports"===t?a:t===u||Reflect.get(e,t,r)}})}var c=new WeakMap,f=function(){function e(e){var n=this;if(!e)throw new TypeError("WASIThreads(): options is not provided");if(!e.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");c.set(this,new WeakSet);var d=e.wasi;!function(e,t){var r=c.get(e);if(r.has(t))return;var o=e,n=t.wasiImport;if(n){var a=n.proc_exit;n.proc_exit=function(e){return o.terminateAllThreads(),a.call(this,e)}}if(!o.childThread){var s=t.start;"function"==typeof s&&(t.start=function(e){try{return s.call(this,e)}catch(e){throw i(e)&&o.terminateAllThreads(),e}})}r.add(t)}(this,d),this.wasi=d,this.childThread="childThread"in e&&Boolean(e.childThread),this.PThread=void 0,"threadManager"in e?"function"==typeof e.threadManager?this.PThread=e.threadManager():this.PThread=e.threadManager:this.childThread||(this.PThread=new h(e),this.PThread.init());var u=!1;"waitThreadStart"in e&&(u="number"==typeof e.waitThreadStart?e.waitThreadStart:Boolean(e.waitThreadStart));var l=o(e);if(this.childThread&&"function"!=typeof l)throw new TypeError("options.postMessage is not a function");this.postMessage=l;var f=Boolean(e.wasm64),p=function(e,o){var i,d=void 0!==o;try{s(n.wasmMemory)}catch(e){if(null===(i=n.PThread)||void 0===i||i.printErr(e.stack),d){var h=new Int32Array(n.wasmMemory.buffer,o,2);return Atomics.store(h,0,1),Atomics.store(h,1,6),Atomics.notify(h,1),1}return-6}if(!d){var c=n.wasmInstance.exports.malloc;if(!(o=f?Number(c(BigInt(8))):c(8)>>>0))return-48}var p=n.wasmInstance.exports.free,m=f?function(e){p(BigInt(e))}:p,y=new Int32Array(n.wasmMemory.buffer,o,2);if(Atomics.store(y,0,0),Atomics.store(y,1,0),n.childThread){l(a("spawn-thread",{startArg:e,errorOrTid:o})),Atomics.wait(y,1,0);var v=Atomics.load(y,0),w=Atomics.load(y,1);return d?v:(m(o),v?-w:w)}var _,g,T,k=u||0===u;k&&(_=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(_,0,0));var W=n.PThread;try{if(!(g=W.getNewWorker(_)))throw new Error("failed to get new worker");if(T=W.markId(g),r&&g.unref(),g.postMessage(a("start",{tid:T,arg:e,sab:_})),k){if("number"==typeof u){if("timed-out"===Atomics.wait(_,0,0,u))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(_,0,0);if(Atomics.load(_,0)>1)throw function(e){var r,o,n=new Int32Array(e);if(Atomics.load(n,0)<=1)return null;var i=Atomics.load(n,1),a=Atomics.load(n,2),s=Atomics.load(n,3),d=new Uint8Array(e),h=d.slice(16,16+i),u=d.slice(16+i,16+i+a),l=d.slice(16+i+a,16+i+a+s),c=(new TextDecoder).decode(h),f=(new TextDecoder).decode(u),p=(new TextDecoder).decode(l),m=new(null!==(r=globalThis[c])&&void 0!==r?r:"RuntimeError"===c&&null!==(o=t.RuntimeError)&&void 0!==o?o:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(_.buffer)}}catch(e){if(void 0!==g&&void 0!==T)try{W.cleanThread(g,T,!0)}catch(e){}return Atomics.store(y,0,1),Atomics.store(y,1,6),Atomics.notify(y,1),null==W||W.printErr(e.stack),d?1:(m(o),-6)}return Atomics.store(y,0,0),Atomics.store(y,1,T),Atomics.notify(y,1),k||g.whenLoaded.catch(function(e){throw delete g.whenLoaded,W.cleanThread(g,T,!0),e}),d?0:(m(o),T)};this.threadSpawn=p,this.PThread&&(this.PThread.threadSpawn=p)}return e.prototype.getImportObject=function(){return{wasi:{"thread-spawn":this.threadSpawn}}},e.prototype.setup=function(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)},e.prototype.preloadWorkers=function(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])},e.prototype.initialize=function(e,t,r){var o=e.exports;null!=r||(r=o.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);var n=this.wasi;if("_start"in o&&"function"==typeof o._start)if(this.childThread){n.start(e);try{n[p(n,"kStarted")]=!1}catch(e){}}else!function(e,t){var r=p(e,["kInstance","kSetMemory"]),o=r[0],n=r[1];e[o]=t,e[n](t.exports.memory)}(n,e);else n.initialize(e);return e},e.prototype.start=function(e,t,r){var o=e.exports;return null!=r||(r=o.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r),{exitCode:this.wasi.start(e),instance:e}},e.prototype.terminateAllThreads=function(){var e;this.childThread?this.postMessage(a("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()},e}();function p(e,t){var r=Object.getOwnPropertySymbols(e),o=function(e){return function(t){return t.description?t.description===e:t.toString()==="Symbol(".concat(e,")")}};return Array.isArray(t)?t.map(function(e){return r.filter(o(e))[0]}):r.filter(o(t))[0]}var m=function(){function e(e){var t=o(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:function(e,t){throw t},this.instance=void 0,this.messagesBeforeLoad=[]}return e.prototype.instantiate=function(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")},e.prototype.handle=function(e){var t,r=this;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){var o=e.data.__emnapi__.type,n=e.data.__emnapi__.payload;try{"load"===o?this._load(n):"start"===o&&this.handleAfterLoad(e,function(){r._start(n)})}catch(e){this.onError(e,o)}}},e.prototype._load=function(e){var t=this;if(void 0===this.instance){var r;try{r=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}var o=r&&"then"in r?r.then:void 0;"function"==typeof o?o.call(r,function(r){t._loaded(null,r,e)},function(r){t._loaded(r,null,e)}):this._loaded(null,r,e)}},e.prototype._start=function(e){var t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){var r=new TypeError("wasi_thread_start is not exported");throw y(e.sab,2,r),r}var o=this.postMessage,n=e.tid,i=e.arg;y(e.sab,1);try{t(n,i)}catch(r){if("unwind"!==r)throw r;return}o(a("cleanup-thread",{tid:n}))},e.prototype._loaded=function(e,t,r){if(e)throw y(r.sab,2,e),e;if(null==t){var o=new TypeError("onLoad should return an object");throw y(r.sab,2,o),o}var n=t.instance;if(!n){var i=new TypeError('onLoad should return an object which includes "instance"');throw y(r.sab,2,i),i}this.instance=n,(0,this.postMessage)(a("loaded",{}));var s=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(var d=0;d<s.length;d++){var h=s[d];this.handle({data:h})}},e.prototype.handleAfterLoad=function(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)},e}();function y(e,t,r){e&&(!function(e,t,r){var o=new Int32Array(e);if(Atomics.store(o,0,t),t>1&&r){var n=r.name,i=r.message,a=r.stack,s=(new TextEncoder).encode(n),d=(new TextEncoder).encode(i),h=(new TextEncoder).encode(a);Atomics.store(o,1,s.length),Atomics.store(o,2,d.length),Atomics.store(o,3,h.length);var u=new Uint8Array(e);u.set(s,16),u.set(d,16+s.length),u.set(h,16+s.length+d.length)}}(e.buffer,t,r),Atomics.notify(e,0))}e.ThreadManager=h,e.ThreadMessageHandler=m,e.WASIThreads=f,e.createInstanceProxy=l,e.isSharedArrayBuffer=n,e.isTrapError=i}); | ||
| !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).wasiThreads={})}(this,function(e){var t="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,r="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function o(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function n(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function i(e){try{return e instanceof t.RuntimeError}catch(e){return!1}}function a(e,t){return{__emnapi__:{type:e,payload:t}}}function s(e){if(e){if(!n(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}var d=0,h=function(){function e(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;var r=null!==(t=Number(e.size))&&void 0!==t?t:0,o=Boolean(e.strict);if(!(r>0)&&o)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:o}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}return Object.defineProperty(e.prototype,"nextWorkerID",{get:function(){return d},enumerable:!1,configurable:!0}),e.prototype.init=function(){this._childThread||this.initMainThread()},e.prototype.initMainThread=function(){this.preparePool()},e.prototype.preparePool=function(){if(this._reuseWorker&&this._reuseWorker.size)for(var e=this._reuseWorker.size;e--;){var t=this.allocateUnusedWorker();r&&(t.once("message",function(){}),t.unref())}},e.prototype.shouldPreloadWorkers=function(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0},e.prototype.loadWasmModuleToAllWorkers=function(){for(var e=this,t=Array(this.unusedWorkers.length),o=function(e){var o=n.unusedWorkers[e];r&&o.ref(),t[e]=n.loadWasmModuleToWorker(o).then(function(e){return r&&o.unref(),e},function(e){throw r&&o.unref(),e})},n=this,i=0;i<this.unusedWorkers.length;++i)o(i);return Promise.all(t).catch(function(t){throw e.terminateAllThreads(),t})},e.prototype.preloadWorkers=function(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])},e.prototype.setup=function(e,t){this.wasmModule=e,this.wasmMemory=t},e.prototype.markId=function(e){if(e.__emnapi_tid)return e.__emnapi_tid;var t=d+43;return d=(d+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t},e.prototype.returnWorkerToPool=function(e){var t=e.__emnapi_tid;void 0!==t&&delete this.pthreads[t],this.unusedWorkers.push(e),delete e.__emnapi_tid,r&&e.unref()},e.prototype.loadWasmModuleToWorker=function(e,t){var o=this;if(e.whenLoaded)return e.whenLoaded;var n=this.printErr,i=this._beforeLoad,d=this;return e.whenLoaded=new Promise(function(h,u){e.onmessage=function(t){!function(t){if(t.__emnapi__){var n=t.__emnapi__.type,i=t.__emnapi__.payload;"loaded"===n?(e.loaded=!0,r&&!e.__emnapi_tid&&e.unref(),h(e)):"cleanup-thread"===n?i.tid in o.pthreads&&o.cleanThread(e,i.tid):"spawn-thread"===n?o.threadSpawn(i.startArg,i.errorOrTid):"terminate-all-threads"===n&&o.terminateAllThreads()}}(t.data),o.fireMessageEvent(e,t)},e.onerror=function(t){var r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(n(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{d.terminateAllThreads()}catch(e){}}else n(r);throw u(t),t},r&&(e.on("message",function(t){var r,o;null===(o=(r=e).onmessage)||void 0===o||o.call(r,{data:t})}),e.on("error",function(t){var r,o;null===(o=(r=e).onerror)||void 0===o||o.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof i&&i(e);try{e.postMessage(a("load",{wasmModule:o.wasmModule,wasmMemory:o.wasmMemory,sab:t}))}catch(e){throw s(o.wasmMemory),e}}),e.whenLoaded},e.prototype.allocateUnusedWorker=function(){var e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");var t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t},e.prototype.getNewWorker=function(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict)if(!r)return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.");var t=this.allocateUnusedWorker();this.loadWasmModuleToWorker(t,e)}return this.unusedWorkers.pop()}var o=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(o,e),this.unusedWorkers.pop()},e.prototype.cleanThread=function(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)},e.prototype.terminateWorker=function(e){var t,r=this,o=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=function(e){e.data.__emnapi__&&(0,r.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+o)}},e.prototype.terminateAllThreads=function(){for(var e=Object.values(this.pthreads),t=0;t<e.length;++t)this.terminateWorker(e[t]);for(t=0;t<this.unusedWorkers.length;++t)this.terminateWorker(this.unusedWorkers[t]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()},e.prototype.addMessageEventListener=function(e,t){var r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),function(){null==r||r.delete(t)}},e.prototype.fireMessageEvent=function(e,t){var r=this.messageEvents.get(e);if(r){var o=this.printErr;r.forEach(function(e){try{e(t)}catch(e){o(e.stack)}})}},e}(),u=Symbol("kIsProxy");function c(e,t){if(e[u])return e;var r=e.exports,o=function(e){for(var t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={},o=function(o){var n=t[o];r[n]=function(){var t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[n].apply(Reflect,t)}},n=0;n<t.length;n++)o(n);return r}(r),n=function(){},i=function(){return 0};o.get=function(e,o,a){var s;return"memory"===o?null!==(s="function"==typeof t?t():t)&&void 0!==s?s:Reflect.get(r,o,a):"_initialize"===o?o in r?n:void 0:"_start"===o?o in r?i:void 0:Reflect.get(r,o,a)},o.has=function(e,t){return"memory"===t||Reflect.has(r,t)};var a=new Proxy(Object.create(null),o);return new Proxy(e,{get:function(e,t,r){return"exports"===t?a:t===u||Reflect.get(e,t,r)}})}var l=new WeakMap,f=2*Int32Array.BYTES_PER_ELEMENT,p="function"==typeof SharedArrayBuffer?Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype,"byteLength").get:void 0;function m(e,t,r){var o="bigint"==typeof t?Number(t):t>>>0,n=e.buffer;return o+f>n.byteLength&&function(e){if(void 0===p)return!1;try{return p.call(e),!0}catch(e){return!1}}(n)&&(r?e.grow(BigInt(0)):e.grow(0),n=e.buffer),new Int32Array(n,o,2)}var y=function(){function e(e){var n=this;if(!e)throw new TypeError("WASIThreads(): options is not provided");if(!e.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");l.set(this,new WeakSet);var d=e.wasi;!function(e,t){var r=l.get(e);if(r.has(t))return;var o=e,n=t.wasiImport;if(n){var a=n.proc_exit;n.proc_exit=function(e){return o.terminateAllThreads(),a.call(this,e)}}if(!o.childThread){var s=t.start;"function"==typeof s&&(t.start=function(e){try{return s.call(this,e)}catch(e){throw i(e)&&o.terminateAllThreads(),e}})}r.add(t)}(this,d),this.wasi=d,this.childThread="childThread"in e&&Boolean(e.childThread),this.PThread=void 0,"threadManager"in e?"function"==typeof e.threadManager?this.PThread=e.threadManager():this.PThread=e.threadManager:this.childThread||(this.PThread=new h(e),this.PThread.init());var u=!1;"waitThreadStart"in e&&(u="number"==typeof e.waitThreadStart?e.waitThreadStart:Boolean(e.waitThreadStart));var c=o(e);if(this.childThread&&"function"!=typeof c)throw new TypeError("options.postMessage is not a function");this.postMessage=c;var f=Boolean(e.wasm64),p=function(e,o){var i,d=void 0!==o;try{s(n.wasmMemory)}catch(e){if(null===(i=n.PThread)||void 0===i||i.printErr(e.stack),d){var h=m(n.wasmMemory,o,f);return Atomics.store(h,0,1),Atomics.store(h,1,6),Atomics.notify(h,1),1}return-6}if(!d){var l=n.wasmInstance.exports.malloc;if(!(o=f?Number(l(BigInt(8))):l(8)>>>0))return-48}var p=n.wasmInstance.exports.free,y=f?function(e){p(BigInt(e))}:p,v=m(n.wasmMemory,o,f);if(Atomics.store(v,0,0),Atomics.store(v,1,0),n.childThread){c(a("spawn-thread",{startArg:e,errorOrTid:o})),Atomics.wait(v,1,0);var w=Atomics.load(v,0),g=Atomics.load(v,1);return d?w:(y(o),w?-g:g)}var _,T,k,W=u||0===u;W&&(_=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(_,0,0));var b=n.PThread;try{if(!(T=b.getNewWorker(_)))throw new Error("failed to get new worker");if(k=b.markId(T),r&&T.unref(),T.postMessage(a("start",{tid:k,arg:e,sab:_})),W){if("number"==typeof u){if("timed-out"===Atomics.wait(_,0,0,u))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(_,0,0);if(Atomics.load(_,0)>1)throw function(e){var r,o,n=new Int32Array(e);if(Atomics.load(n,0)<=1)return null;var i=Atomics.load(n,1),a=Atomics.load(n,2),s=Atomics.load(n,3),d=new Uint8Array(e),h=d.slice(16,16+i),u=d.slice(16+i,16+i+a),c=d.slice(16+i+a,16+i+a+s),l=(new TextDecoder).decode(h),f=(new TextDecoder).decode(u),p=(new TextDecoder).decode(c),m=new(null!==(r=globalThis[l])&&void 0!==r?r:"RuntimeError"===l&&null!==(o=t.RuntimeError)&&void 0!==o?o:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(_.buffer)}}catch(e){if(void 0!==T&&void 0!==k)try{b.cleanThread(T,k,!0)}catch(e){}return Atomics.store(v,0,1),Atomics.store(v,1,6),Atomics.notify(v,1),null==b||b.printErr(e.stack),d?1:(y(o),-6)}return Atomics.store(v,0,0),Atomics.store(v,1,k),Atomics.notify(v,1),W||T.whenLoaded.catch(function(e){throw delete T.whenLoaded,b.cleanThread(T,k,!0),e}),d?0:(y(o),k)};this.threadSpawn=p,this.PThread&&(this.PThread.threadSpawn=p)}return e.prototype.getImportObject=function(){return{wasi:{"thread-spawn":this.threadSpawn}}},e.prototype.setup=function(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)},e.prototype.preloadWorkers=function(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])},e.prototype.initialize=function(e,t,r){var o=e.exports;null!=r||(r=o.memory),this.childThread&&(e=c(e,r)),this.setup(e,t,r);var n=this.wasi;if("_start"in o&&"function"==typeof o._start)if(this.childThread){n.start(e);try{n[v(n,"kStarted")]=!1}catch(e){}}else!function(e,t){var r=v(e,["kInstance","kSetMemory"]),o=r[0],n=r[1];e[o]=t,e[n](t.exports.memory)}(n,e);else n.initialize(e);return e},e.prototype.start=function(e,t,r){var o=e.exports;return null!=r||(r=o.memory),this.childThread&&(e=c(e,r)),this.setup(e,t,r),{exitCode:this.wasi.start(e),instance:e}},e.prototype.terminateAllThreads=function(){var e;this.childThread?this.postMessage(a("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()},e}();function v(e,t){var r=Object.getOwnPropertySymbols(e),o=function(e){return function(t){return t.description?t.description===e:t.toString()==="Symbol(".concat(e,")")}};return Array.isArray(t)?t.map(function(e){return r.filter(o(e))[0]}):r.filter(o(t))[0]}var w=function(){function e(e){var t=o(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:function(e,t){throw t},this.instance=void 0,this.messagesBeforeLoad=[]}return e.prototype.instantiate=function(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")},e.prototype.handle=function(e){var t,r=this;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){var o=e.data.__emnapi__.type,n=e.data.__emnapi__.payload;try{"load"===o?this._load(n):"start"===o&&this.handleAfterLoad(e,function(){r._start(n)})}catch(e){this.onError(e,o)}}},e.prototype._load=function(e){var t=this;if(void 0===this.instance){var r;try{r=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}var o=r&&"then"in r?r.then:void 0;"function"==typeof o?o.call(r,function(r){t._loaded(null,r,e)},function(r){t._loaded(r,null,e)}):this._loaded(null,r,e)}},e.prototype._start=function(e){var t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){var r=new TypeError("wasi_thread_start is not exported");throw g(e.sab,2,r),r}var o=this.postMessage,n=e.tid,i=e.arg;g(e.sab,1);try{t(n,i)}catch(r){if("unwind"!==r)throw r;return}o(a("cleanup-thread",{tid:n}))},e.prototype._loaded=function(e,t,r){if(e)throw g(r.sab,2,e),e;if(null==t){var o=new TypeError("onLoad should return an object");throw g(r.sab,2,o),o}var n=t.instance;if(!n){var i=new TypeError('onLoad should return an object which includes "instance"');throw g(r.sab,2,i),i}this.instance=n,(0,this.postMessage)(a("loaded",{}));var s=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(var d=0;d<s.length;d++){var h=s[d];this.handle({data:h})}},e.prototype.handleAfterLoad=function(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)},e}();function g(e,t,r){e&&(!function(e,t,r){var o=new Int32Array(e);if(Atomics.store(o,0,t),t>1&&r){var n=r.name,i=r.message,a=r.stack,s=(new TextEncoder).encode(n),d=(new TextEncoder).encode(i),h=(new TextEncoder).encode(a);Atomics.store(o,1,s.length),Atomics.store(o,2,d.length),Atomics.store(o,3,h.length);var u=new Uint8Array(e);u.set(s,16),u.set(d,16+s.length),u.set(h,16+s.length+d.length)}}(e.buffer,t,r),Atomics.notify(e,0))}e.ThreadManager=h,e.ThreadMessageHandler=w,e.WASIThreads=y,e.createInstanceProxy=c,e.isSharedArrayBuffer=n,e.isTrapError=i}); |
@@ -1,1 +0,1 @@ | ||
| const e="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,t="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function r(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function s(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function o(t){try{return t instanceof e.RuntimeError}catch(e){return!1}}function n(e,t){return{__emnapi__:{type:e,payload:t}}}function i(e){if(e){if(!s(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}let a=0;class h{get nextWorkerID(){return a}constructor(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;const r=null!==(t=Number(e.size))&&void 0!==t?t:0,s=Boolean(e.strict);if(!(r>0)&&s)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:s}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}init(){this._childThread||this.initMainThread()}initMainThread(){this.preparePool()}preparePool(){if(this._reuseWorker&&this._reuseWorker.size){let e=this._reuseWorker.size;for(;e--;){const e=this.allocateUnusedWorker();t&&(e.once("message",()=>{}),e.unref())}}}shouldPreloadWorkers(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0}loadWasmModuleToAllWorkers(){const e=Array(this.unusedWorkers.length);for(let r=0;r<this.unusedWorkers.length;++r){const s=this.unusedWorkers[r];t&&s.ref(),e[r]=this.loadWasmModuleToWorker(s).then(e=>(t&&s.unref(),e),e=>{throw t&&s.unref(),e})}return Promise.all(e).catch(e=>{throw this.terminateAllThreads(),e})}preloadWorkers(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])}setup(e,t){this.wasmModule=e,this.wasmMemory=t}markId(e){if(e.__emnapi_tid)return e.__emnapi_tid;const t=a+43;return a=(a+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t}returnWorkerToPool(e){var r=e.__emnapi_tid;void 0!==r&&delete this.pthreads[r],this.unusedWorkers.push(e),delete e.__emnapi_tid,t&&e.unref()}loadWasmModuleToWorker(e,r){if(e.whenLoaded)return e.whenLoaded;const s=this.printErr,o=this._beforeLoad,a=this;return e.whenLoaded=new Promise((h,d)=>{const l=r=>{if(r.__emnapi__){const s=r.__emnapi__.type,o=r.__emnapi__.payload;"loaded"===s?(e.loaded=!0,t&&!e.__emnapi_tid&&e.unref(),h(e)):"cleanup-thread"===s?o.tid in this.pthreads&&this.cleanThread(e,o.tid):"spawn-thread"===s?this.threadSpawn(o.startArg,o.errorOrTid):"terminate-all-threads"===s&&this.terminateAllThreads()}};e.onmessage=t=>{l(t.data),this.fireMessageEvent(e,t)},e.onerror=function(t){let r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(s(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{a.terminateAllThreads()}catch(e){}}else s(r);throw d(t),t},t&&(e.on("message",function(t){var r,s;null===(s=(r=e).onmessage)||void 0===s||s.call(r,{data:t})}),e.on("error",function(t){var r,s;null===(s=(r=e).onerror)||void 0===s||s.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof o&&o(e);try{e.postMessage(n("load",{wasmModule:this.wasmModule,wasmMemory:this.wasmMemory,sab:r}))}catch(e){throw i(this.wasmMemory),e}}),e.whenLoaded}allocateUnusedWorker(){const e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");const t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t}getNewWorker(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict&&!t){return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.")}const r=this.allocateUnusedWorker();this.loadWasmModuleToWorker(r,e)}return this.unusedWorkers.pop()}const r=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(r,e),this.unusedWorkers.pop()}cleanThread(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)}terminateWorker(e){var t;const r=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=e=>{if(e.data.__emnapi__){(0,this.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+r)}}}terminateAllThreads(){const e=Object.values(this.pthreads);for(let t=0;t<e.length;++t)this.terminateWorker(e[t]);for(let e=0;e<this.unusedWorkers.length;++e)this.terminateWorker(this.unusedWorkers[e]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()}addMessageEventListener(e,t){let r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),()=>{null==r||r.delete(t)}}fireMessageEvent(e,t){const r=this.messageEvents.get(e);if(!r)return;const s=this.printErr;r.forEach(e=>{try{e(t)}catch(e){s(e.stack)}})}}const d=Symbol("kIsProxy");function l(e,t){if(e[d])return e;const r=e.exports,s=function(e){const t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={};for(let s=0;s<t.length;s++){const o=t[s];r[o]=function(){const t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[o].apply(Reflect,t)}}return r}(r),o=()=>{},n=()=>0;s.get=function(e,s,i){var a;return"memory"===s?null!==(a="function"==typeof t?t():t)&&void 0!==a?a:Reflect.get(r,s,i):"_initialize"===s?s in r?o:void 0:"_start"===s?s in r?n:void 0:Reflect.get(r,s,i)},s.has=function(e,t){return"memory"===t||Reflect.has(r,t)};const i=new Proxy(Object.create(null),s);return new Proxy(e,{get:(e,t,r)=>"exports"===t?i:t===d||Reflect.get(e,t,r)})}const c=new WeakMap;class u{constructor(s){if(!s)throw new TypeError("WASIThreads(): options is not provided");if(!s.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");c.set(this,new WeakSet);const a=s.wasi;!function(e,t){const r=c.get(e);if(r.has(t))return;const s=e,n=t.wasiImport;if(n){const e=n.proc_exit;n.proc_exit=function(t){return s.terminateAllThreads(),e.call(this,t)}}if(!s.childThread){const e=t.start;"function"==typeof e&&(t.start=function(t){try{return e.call(this,t)}catch(e){throw o(e)&&s.terminateAllThreads(),e}})}r.add(t)}(this,a),this.wasi=a,this.childThread="childThread"in s&&Boolean(s.childThread),this.PThread=void 0,"threadManager"in s?"function"==typeof s.threadManager?this.PThread=s.threadManager():this.PThread=s.threadManager:this.childThread||(this.PThread=new h(s),this.PThread.init());let d=!1;"waitThreadStart"in s&&(d="number"==typeof s.waitThreadStart?s.waitThreadStart:Boolean(s.waitThreadStart));const l=r(s);if(this.childThread&&"function"!=typeof l)throw new TypeError("options.postMessage is not a function");this.postMessage=l;const u=Boolean(s.wasm64),f=(r,s)=>{var o;const a=void 0!==s;try{i(this.wasmMemory)}catch(e){if(null===(o=this.PThread)||void 0===o||o.printErr(e.stack),a){const e=new Int32Array(this.wasmMemory.buffer,s,2);return Atomics.store(e,0,1),Atomics.store(e,1,6),Atomics.notify(e,1),1}return-6}if(!a){const e=this.wasmInstance.exports.malloc;if(!(s=u?Number(e(BigInt(8))):e(8)>>>0))return-48}const h=this.wasmInstance.exports.free,c=u?e=>{h(BigInt(e))}:h,f=new Int32Array(this.wasmMemory.buffer,s,2);if(Atomics.store(f,0,0),Atomics.store(f,1,0),this.childThread){l(n("spawn-thread",{startArg:r,errorOrTid:s})),Atomics.wait(f,1,0);const e=Atomics.load(f,0),t=Atomics.load(f,1);return a?e:(c(s),e?-t:t)}const p=d||0===d;let m,w,y;p&&(m=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(m,0,0));const _=this.PThread;try{if(w=_.getNewWorker(m),!w)throw new Error("failed to get new worker");if(y=_.markId(w),t&&w.unref(),w.postMessage(n("start",{tid:y,arg:r,sab:m})),p){if("number"==typeof d){if("timed-out"===Atomics.wait(m,0,0,d))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(m,0,0);if(Atomics.load(m,0)>1)throw function(t){var r,s;const o=new Int32Array(t);if(Atomics.load(o,0)<=1)return null;const n=Atomics.load(o,1),i=Atomics.load(o,2),a=Atomics.load(o,3),h=new Uint8Array(t),d=h.slice(16,16+n),l=h.slice(16+n,16+n+i),c=h.slice(16+n+i,16+n+i+a),u=(new TextDecoder).decode(d),f=(new TextDecoder).decode(l),p=(new TextDecoder).decode(c),m=new(null!==(r=globalThis[u])&&void 0!==r?r:"RuntimeError"===u&&null!==(s=e.RuntimeError)&&void 0!==s?s:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(m.buffer)}}catch(e){if(void 0!==w&&void 0!==y)try{_.cleanThread(w,y,!0)}catch(e){}return Atomics.store(f,0,1),Atomics.store(f,1,6),Atomics.notify(f,1),null==_||_.printErr(e.stack),a?1:(c(s),-6)}return Atomics.store(f,0,0),Atomics.store(f,1,y),Atomics.notify(f,1),p||w.whenLoaded.catch(e=>{throw delete w.whenLoaded,_.cleanThread(w,y,!0),e}),a?0:(c(s),y)};this.threadSpawn=f,this.PThread&&(this.PThread.threadSpawn=f)}getImportObject(){return{wasi:{"thread-spawn":this.threadSpawn}}}setup(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)}preloadWorkers(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])}initialize(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);const o=this.wasi;if("_start"in s&&"function"==typeof s._start)if(this.childThread){o.start(e);try{o[f(o,"kStarted")]=!1}catch(e){}}else!function(e,t){const[r,s]=f(e,["kInstance","kSetMemory"]);e[r]=t,e[s](t.exports.memory)}(o,e);else o.initialize(e);return e}start(e,t,r){const s=e.exports;null!=r||(r=s.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);return{exitCode:this.wasi.start(e),instance:e}}terminateAllThreads(){var e;this.childThread?this.postMessage(n("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()}}function f(e,t){const r=Object.getOwnPropertySymbols(e),s=e=>t=>t.description?t.description===e:t.toString()===`Symbol(${e})`;return Array.isArray(t)?t.map(e=>r.filter(s(e))[0]):r.filter(s(t))[0]}class p{constructor(e){const t=r(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:(e,t)=>{throw t},this.instance=void 0,this.messagesBeforeLoad=[]}instantiate(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")}handle(e){var t;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){const t=e.data.__emnapi__.type,r=e.data.__emnapi__.payload;try{"load"===t?this._load(r):"start"===t&&this.handleAfterLoad(e,()=>{this._start(r)})}catch(e){this.onError(e,t)}}}_load(e){if(void 0!==this.instance)return;let t;try{t=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}const r=t&&"then"in t?t.then:void 0;"function"==typeof r?r.call(t,t=>{this._loaded(null,t,e)},t=>{this._loaded(t,null,e)}):this._loaded(null,t,e)}_start(e){const t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){const t=new TypeError("wasi_thread_start is not exported");throw m(e.sab,2,t),t}const r=this.postMessage,s=e.tid,o=e.arg;m(e.sab,1);try{t(s,o)}catch(e){if("unwind"!==e)throw e;return}r(n("cleanup-thread",{tid:s}))}_loaded(e,t,r){if(e)throw m(r.sab,2,e),e;if(null==t){const e=new TypeError("onLoad should return an object");throw m(r.sab,2,e),e}const s=t.instance;if(!s){const e=new TypeError('onLoad should return an object which includes "instance"');throw m(r.sab,2,e),e}this.instance=s;(0,this.postMessage)(n("loaded",{}));const o=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(let e=0;e<o.length;e++){const t=o[e];this.handle({data:t})}}handleAfterLoad(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)}}function m(e,t,r){e&&(!function(e,t,r){const s=new Int32Array(e);if(Atomics.store(s,0,t),t>1&&r){const t=r.name,o=r.message,n=r.stack,i=(new TextEncoder).encode(t),a=(new TextEncoder).encode(o),h=(new TextEncoder).encode(n);Atomics.store(s,1,i.length),Atomics.store(s,2,a.length),Atomics.store(s,3,h.length);const d=new Uint8Array(e);d.set(i,16),d.set(a,16+i.length),d.set(h,16+i.length+a.length)}}(e.buffer,t,r),Atomics.notify(e,0))}export{h as ThreadManager,p as ThreadMessageHandler,u as WASIThreads,l as createInstanceProxy,s as isSharedArrayBuffer,o as isTrapError}; | ||
| const e="undefined"!=typeof WebAssembly?WebAssembly:"undefined"!=typeof WXWebAssembly?WXWebAssembly:void 0,t="object"==typeof process&&null!==process&&"object"==typeof process.versions&&null!==process.versions&&"string"==typeof process.versions.node;function r(e){return"function"==typeof(null==e?void 0:e.postMessage)?e.postMessage:"function"==typeof postMessage?postMessage:void 0}function o(e){return"function"==typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer||"[object SharedArrayBuffer]"===Object.prototype.toString.call(e)}function s(t){try{return t instanceof e.RuntimeError}catch(e){return!1}}function n(e,t){return{__emnapi__:{type:e,payload:t}}}function i(e){if(e){if(!o(e.buffer))throw new Error("Multithread features require shared wasm memory. Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, then create WebAssembly.Memory with `shared: true` option")}else if("undefined"==typeof SharedArrayBuffer)throw new Error("Current environment does not support SharedArrayBuffer, threads are not available!")}let a=0;class h{get nextWorkerID(){return a}constructor(e){var t;if(this.unusedWorkers=[],this.pthreads=Object.create(null),this.wasmModule=null,this.wasmMemory=null,this.messageEvents=new WeakMap,!e)throw new TypeError("ThreadManager(): options is not provided");this._childThread="childThread"in e&&Boolean(e.childThread),this._childThread?(this._onCreateWorker=void 0,this._reuseWorker=!1,this._beforeLoad=void 0):(this._onCreateWorker=e.onCreateWorker,this._reuseWorker=function(e){var t;if("boolean"==typeof e)return!!e&&{size:0,strict:!1};if("number"==typeof e){if(!(e>=0))throw new RangeError("reuseWorker: size must be a non-negative integer");return{size:e,strict:!1}}if(!e)return!1;const r=null!==(t=Number(e.size))&&void 0!==t?t:0,o=Boolean(e.strict);if(!(r>0)&&o)throw new RangeError("reuseWorker: size must be set to positive integer if strict is set to true");return{size:r,strict:o}}(e.reuseWorker),this._beforeLoad=e.beforeLoad),this.printErr=null!==(t=e.printErr)&&void 0!==t?t:console.error.bind(console),this.threadSpawn=e.threadSpawn}init(){this._childThread||this.initMainThread()}initMainThread(){this.preparePool()}preparePool(){if(this._reuseWorker&&this._reuseWorker.size){let e=this._reuseWorker.size;for(;e--;){const e=this.allocateUnusedWorker();t&&(e.once("message",()=>{}),e.unref())}}}shouldPreloadWorkers(){return!this._childThread&&this._reuseWorker&&this._reuseWorker.size>0}loadWasmModuleToAllWorkers(){const e=Array(this.unusedWorkers.length);for(let r=0;r<this.unusedWorkers.length;++r){const o=this.unusedWorkers[r];t&&o.ref(),e[r]=this.loadWasmModuleToWorker(o).then(e=>(t&&o.unref(),e),e=>{throw t&&o.unref(),e})}return Promise.all(e).catch(e=>{throw this.terminateAllThreads(),e})}preloadWorkers(){return this.shouldPreloadWorkers()?this.loadWasmModuleToAllWorkers():Promise.resolve([])}setup(e,t){this.wasmModule=e,this.wasmMemory=t}markId(e){if(e.__emnapi_tid)return e.__emnapi_tid;const t=a+43;return a=(a+1)%536870869,this.pthreads[t]=e,e.__emnapi_tid=t,t}returnWorkerToPool(e){var r=e.__emnapi_tid;void 0!==r&&delete this.pthreads[r],this.unusedWorkers.push(e),delete e.__emnapi_tid,t&&e.unref()}loadWasmModuleToWorker(e,r){if(e.whenLoaded)return e.whenLoaded;const o=this.printErr,s=this._beforeLoad,a=this;return e.whenLoaded=new Promise((h,d)=>{const l=r=>{if(r.__emnapi__){const o=r.__emnapi__.type,s=r.__emnapi__.payload;"loaded"===o?(e.loaded=!0,t&&!e.__emnapi_tid&&e.unref(),h(e)):"cleanup-thread"===o?s.tid in this.pthreads&&this.cleanThread(e,s.tid):"spawn-thread"===o?this.threadSpawn(s.startArg,s.errorOrTid):"terminate-all-threads"===o&&this.terminateAllThreads()}};e.onmessage=t=>{l(t.data),this.fireMessageEvent(e,t)},e.onerror=function(t){let r="worker sent an error!";if(void 0!==e.__emnapi_tid&&(r="worker (tid = "+e.__emnapi_tid+") sent an error!"),"message"in t){if(o(r+" "+t.message),-1!==t.message.indexOf("RuntimeError")||-1!==t.message.indexOf("unreachable"))try{a.terminateAllThreads()}catch(e){}}else o(r);throw d(t),t},t&&(e.on("message",function(t){var r,o;null===(o=(r=e).onmessage)||void 0===o||o.call(r,{data:t})}),e.on("error",function(t){var r,o;null===(o=(r=e).onerror)||void 0===o||o.call(r,t)}),e.on("detachedExit",function(){})),"function"==typeof s&&s(e);try{e.postMessage(n("load",{wasmModule:this.wasmModule,wasmMemory:this.wasmMemory,sab:r}))}catch(e){throw i(this.wasmMemory),e}}),e.whenLoaded}allocateUnusedWorker(){const e=this._onCreateWorker;if("function"!=typeof e)throw new TypeError("`options.onCreateWorker` is not provided");const t=e({type:"thread",name:"emnapi-pthread"});return this.unusedWorkers.push(t),t}getNewWorker(e){if(this._reuseWorker){if(0===this.unusedWorkers.length){if(this._reuseWorker.strict&&!t){return void(0,this.printErr)("Tried to spawn a new thread, but the thread pool is exhausted.\nThis might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.")}const r=this.allocateUnusedWorker();this.loadWasmModuleToWorker(r,e)}return this.unusedWorkers.pop()}const r=this.allocateUnusedWorker();return this.loadWasmModuleToWorker(r,e),this.unusedWorkers.pop()}cleanThread(e,t,r){!r&&this._reuseWorker?this.returnWorkerToPool(e):(delete this.pthreads[t],this.terminateWorker(e),delete e.__emnapi_tid)}terminateWorker(e){var t;const r=e.__emnapi_tid;e.terminate(),null===(t=this.messageEvents.get(e))||void 0===t||t.clear(),this.messageEvents.delete(e),e.onmessage=e=>{if(e.data.__emnapi__){(0,this.printErr)('received "'+e.data.__emnapi__.type+'" command from terminated worker: '+r)}}}terminateAllThreads(){const e=Object.values(this.pthreads);for(let t=0;t<e.length;++t)this.terminateWorker(e[t]);for(let e=0;e<this.unusedWorkers.length;++e)this.terminateWorker(this.unusedWorkers[e]);this.unusedWorkers=[],this.pthreads=Object.create(null),this.preparePool()}addMessageEventListener(e,t){let r=this.messageEvents.get(e);return r||(r=new Set,this.messageEvents.set(e,r)),r.add(t),()=>{null==r||r.delete(t)}}fireMessageEvent(e,t){const r=this.messageEvents.get(e);if(!r)return;const o=this.printErr;r.forEach(e=>{try{e(t)}catch(e){o(e.stack)}})}}const d=Symbol("kIsProxy");function l(e,t){if(e[d])return e;const r=e.exports,o=function(e){const t=["apply","construct","defineProperty","deleteProperty","get","getOwnPropertyDescriptor","getPrototypeOf","has","isExtensible","ownKeys","preventExtensions","set","setPrototypeOf"],r={};for(let o=0;o<t.length;o++){const s=t[o];r[s]=function(){const t=Array.prototype.slice.call(arguments,1);return t.unshift(e),Reflect[s].apply(Reflect,t)}}return r}(r),s=()=>{},n=()=>0;o.get=function(e,o,i){var a;return"memory"===o?null!==(a="function"==typeof t?t():t)&&void 0!==a?a:Reflect.get(r,o,i):"_initialize"===o?o in r?s:void 0:"_start"===o?o in r?n:void 0:Reflect.get(r,o,i)},o.has=function(e,t){return"memory"===t||Reflect.has(r,t)};const i=new Proxy(Object.create(null),o);return new Proxy(e,{get:(e,t,r)=>"exports"===t?i:t===d||Reflect.get(e,t,r)})}const c=new WeakMap,u=2*Int32Array.BYTES_PER_ELEMENT,f="function"==typeof SharedArrayBuffer?Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype,"byteLength").get:void 0;function p(e,t,r){const o="bigint"==typeof t?Number(t):t>>>0;let s=e.buffer;return o+u>s.byteLength&&function(e){if(void 0===f)return!1;try{return f.call(e),!0}catch(e){return!1}}(s)&&(r?e.grow(BigInt(0)):e.grow(0),s=e.buffer),new Int32Array(s,o,2)}class m{constructor(o){if(!o)throw new TypeError("WASIThreads(): options is not provided");if(!o.wasi)throw new TypeError("WASIThreads(): options.wasi is not provided");c.set(this,new WeakSet);const a=o.wasi;!function(e,t){const r=c.get(e);if(r.has(t))return;const o=e,n=t.wasiImport;if(n){const e=n.proc_exit;n.proc_exit=function(t){return o.terminateAllThreads(),e.call(this,t)}}if(!o.childThread){const e=t.start;"function"==typeof e&&(t.start=function(t){try{return e.call(this,t)}catch(e){throw s(e)&&o.terminateAllThreads(),e}})}r.add(t)}(this,a),this.wasi=a,this.childThread="childThread"in o&&Boolean(o.childThread),this.PThread=void 0,"threadManager"in o?"function"==typeof o.threadManager?this.PThread=o.threadManager():this.PThread=o.threadManager:this.childThread||(this.PThread=new h(o),this.PThread.init());let d=!1;"waitThreadStart"in o&&(d="number"==typeof o.waitThreadStart?o.waitThreadStart:Boolean(o.waitThreadStart));const l=r(o);if(this.childThread&&"function"!=typeof l)throw new TypeError("options.postMessage is not a function");this.postMessage=l;const u=Boolean(o.wasm64),f=(r,o)=>{var s;const a=void 0!==o;try{i(this.wasmMemory)}catch(e){if(null===(s=this.PThread)||void 0===s||s.printErr(e.stack),a){const e=p(this.wasmMemory,o,u);return Atomics.store(e,0,1),Atomics.store(e,1,6),Atomics.notify(e,1),1}return-6}if(!a){const e=this.wasmInstance.exports.malloc;if(!(o=u?Number(e(BigInt(8))):e(8)>>>0))return-48}const h=this.wasmInstance.exports.free,c=u?e=>{h(BigInt(e))}:h,f=p(this.wasmMemory,o,u);if(Atomics.store(f,0,0),Atomics.store(f,1,0),this.childThread){l(n("spawn-thread",{startArg:r,errorOrTid:o})),Atomics.wait(f,1,0);const e=Atomics.load(f,0),t=Atomics.load(f,1);return a?e:(c(o),e?-t:t)}const m=d||0===d;let w,y,_;m&&(w=new Int32Array(new SharedArrayBuffer(8208)),Atomics.store(w,0,0));const g=this.PThread;try{if(y=g.getNewWorker(w),!y)throw new Error("failed to get new worker");if(_=g.markId(y),t&&y.unref(),y.postMessage(n("start",{tid:_,arg:r,sab:w})),m){if("number"==typeof d){if("timed-out"===Atomics.wait(w,0,0,d))throw new Error("Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.")}else Atomics.wait(w,0,0);if(Atomics.load(w,0)>1)throw function(t){var r,o;const s=new Int32Array(t);if(Atomics.load(s,0)<=1)return null;const n=Atomics.load(s,1),i=Atomics.load(s,2),a=Atomics.load(s,3),h=new Uint8Array(t),d=h.slice(16,16+n),l=h.slice(16+n,16+n+i),c=h.slice(16+n+i,16+n+i+a),u=(new TextDecoder).decode(d),f=(new TextDecoder).decode(l),p=(new TextDecoder).decode(c),m=new(null!==(r=globalThis[u])&&void 0!==r?r:"RuntimeError"===u&&null!==(o=e.RuntimeError)&&void 0!==o?o:Error)(f);return Object.defineProperty(m,"stack",{value:p,writable:!0,enumerable:!1,configurable:!0}),m}(w.buffer)}}catch(e){if(void 0!==y&&void 0!==_)try{g.cleanThread(y,_,!0)}catch(e){}return Atomics.store(f,0,1),Atomics.store(f,1,6),Atomics.notify(f,1),null==g||g.printErr(e.stack),a?1:(c(o),-6)}return Atomics.store(f,0,0),Atomics.store(f,1,_),Atomics.notify(f,1),m||y.whenLoaded.catch(e=>{throw delete y.whenLoaded,g.cleanThread(y,_,!0),e}),a?0:(c(o),_)};this.threadSpawn=f,this.PThread&&(this.PThread.threadSpawn=f)}getImportObject(){return{wasi:{"thread-spawn":this.threadSpawn}}}setup(e,t,r){null!=r||(r=e.exports.memory),this.wasmInstance=e,this.wasmMemory=r,this.PThread&&this.PThread.setup(t,r)}preloadWorkers(){return this.PThread?this.PThread.preloadWorkers():Promise.resolve([])}initialize(e,t,r){const o=e.exports;null!=r||(r=o.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);const s=this.wasi;if("_start"in o&&"function"==typeof o._start)if(this.childThread){s.start(e);try{s[w(s,"kStarted")]=!1}catch(e){}}else!function(e,t){const[r,o]=w(e,["kInstance","kSetMemory"]);e[r]=t,e[o](t.exports.memory)}(s,e);else s.initialize(e);return e}start(e,t,r){const o=e.exports;null!=r||(r=o.memory),this.childThread&&(e=l(e,r)),this.setup(e,t,r);return{exitCode:this.wasi.start(e),instance:e}}terminateAllThreads(){var e;this.childThread?this.postMessage(n("terminate-all-threads",{})):null===(e=this.PThread)||void 0===e||e.terminateAllThreads()}}function w(e,t){const r=Object.getOwnPropertySymbols(e),o=e=>t=>t.description?t.description===e:t.toString()===`Symbol(${e})`;return Array.isArray(t)?t.map(e=>r.filter(o(e))[0]):r.filter(o(t))[0]}class y{constructor(e){const t=r(e);if("function"!=typeof t)throw new TypeError("options.postMessage is not a function");this.postMessage=t,this.onLoad=null==e?void 0:e.onLoad,this.onError="function"==typeof(null==e?void 0:e.onError)?e.onError:(e,t)=>{throw t},this.instance=void 0,this.messagesBeforeLoad=[]}instantiate(e){if("function"==typeof this.onLoad)return this.onLoad(e);throw new Error("ThreadMessageHandler.prototype.instantiate is not implemented")}handle(e){var t;if(null===(t=null==e?void 0:e.data)||void 0===t?void 0:t.__emnapi__){const t=e.data.__emnapi__.type,r=e.data.__emnapi__.payload;try{"load"===t?this._load(r):"start"===t&&this.handleAfterLoad(e,()=>{this._start(r)})}catch(e){this.onError(e,t)}}}_load(e){if(void 0!==this.instance)return;let t;try{t=this.instantiate(e)}catch(t){return void this._loaded(t,null,e)}const r=t&&"then"in t?t.then:void 0;"function"==typeof r?r.call(t,t=>{this._loaded(null,t,e)},t=>{this._loaded(t,null,e)}):this._loaded(null,t,e)}_start(e){const t=this.instance.exports.wasi_thread_start;if("function"!=typeof t){const t=new TypeError("wasi_thread_start is not exported");throw _(e.sab,2,t),t}const r=this.postMessage,o=e.tid,s=e.arg;_(e.sab,1);try{t(o,s)}catch(e){if("unwind"!==e)throw e;return}r(n("cleanup-thread",{tid:o}))}_loaded(e,t,r){if(e)throw _(r.sab,2,e),e;if(null==t){const e=new TypeError("onLoad should return an object");throw _(r.sab,2,e),e}const o=t.instance;if(!o){const e=new TypeError('onLoad should return an object which includes "instance"');throw _(r.sab,2,e),e}this.instance=o;(0,this.postMessage)(n("loaded",{}));const s=this.messagesBeforeLoad;this.messagesBeforeLoad=[];for(let e=0;e<s.length;e++){const t=s[e];this.handle({data:t})}}handleAfterLoad(e,t){void 0!==this.instance?t.call(this,e):this.messagesBeforeLoad.push(e.data)}}function _(e,t,r){e&&(!function(e,t,r){const o=new Int32Array(e);if(Atomics.store(o,0,t),t>1&&r){const t=r.name,s=r.message,n=r.stack,i=(new TextEncoder).encode(t),a=(new TextEncoder).encode(s),h=(new TextEncoder).encode(n);Atomics.store(o,1,i.length),Atomics.store(o,2,a.length),Atomics.store(o,3,h.length);const d=new Uint8Array(e);d.set(i,16),d.set(a,16+i.length),d.set(h,16+i.length+a.length)}}(e.buffer,t,r),Atomics.notify(e,0))}export{h as ThreadManager,y as ThreadMessageHandler,m as WASIThreads,l as createInstanceProxy,o as isSharedArrayBuffer,s as isTrapError}; |
@@ -473,2 +473,32 @@ const _WebAssembly = typeof WebAssembly !== 'undefined' | ||
| const patchedWasiInstances = new WeakMap(); | ||
| const THREAD_SPAWN_RESULT_SIZE = Int32Array.BYTES_PER_ELEMENT * 2; | ||
| const sharedArrayBufferByteLength = typeof SharedArrayBuffer === 'function' | ||
| ? Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, 'byteLength').get | ||
| : undefined; | ||
| function isConclusivelySharedArrayBuffer(buffer) { | ||
| if (sharedArrayBufferByteLength === undefined) | ||
| return false; | ||
| try { | ||
| sharedArrayBufferByteLength.call(buffer); | ||
| return true; | ||
| } | ||
| catch (_) { | ||
| return false; | ||
| } | ||
| } | ||
| function getThreadSpawnResultView(memory, address, wasm64) { | ||
| const offset = typeof address === 'bigint' ? Number(address) : address >>> 0; | ||
| let buffer = memory.buffer; | ||
| if (offset + THREAD_SPAWN_RESULT_SIZE > buffer.byteLength && | ||
| isConclusivelySharedArrayBuffer(buffer)) { | ||
| if (wasm64) { | ||
| memory.grow(BigInt(0)); | ||
| } | ||
| else { | ||
| memory.grow(0); | ||
| } | ||
| buffer = memory.buffer; | ||
| } | ||
| return new Int32Array(buffer, offset, 2); | ||
| } | ||
| class WASIThreads { | ||
@@ -527,3 +557,3 @@ constructor(options) { | ||
| if (isNewABI) { | ||
| const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2); | ||
| const struct = getThreadSpawnResultView(this.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 1); | ||
@@ -547,3 +577,3 @@ Atomics.store(struct, 1, EAGAIN); | ||
| const free = wasm64 ? (ptr) => { _free(BigInt(ptr)); } : _free; | ||
| const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2); | ||
| const struct = getThreadSpawnResultView(this.wasmMemory, errorOrTid, wasm64); | ||
| Atomics.store(struct, 0, 0); | ||
@@ -550,0 +580,0 @@ Atomics.store(struct, 1, 0); |
+1
-1
| { | ||
| "name": "@emnapi/wasi-threads", | ||
| "version": "1.2.2", | ||
| "version": "1.2.3", | ||
| "description": "WASI threads proposal implementation in JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
232189
3.17%4400
3.46%