@dandre3000/thread
Advanced tools
@@ -0,2 +1,3 @@ | ||
| import './compatibility.ts'; | ||
| import { Thread } from './Thread.ts'; | ||
| export { Thread }; |
@@ -1,1 +0,1 @@ | ||
| import{isMainThread}from"@dandre3000/is-main-thread";class OnlineEvent extends Event{thread;constructor(key,thread){if(key!==privateKey)throw new Error("illegal invocation");super("online");this.thread=thread}}class ExitEvent extends Event{threadId;exitCode;constructor(key,threadId,exitCode){if(key!==privateKey)throw new Error("illegal invocation");super("exit");this.threadId=threadId,this.exitCode=exitCode}}var getPrivateData=Symbol(),privateKey=Symbol(),messageTypeEnum={create:0,connect:1,import:2,call:3,resolve:4,reject:5,close:6,terminate:7,disconnect:8},importMessage={type:messageTypeEnum.import,responseId:-1,moduleId:""},callMessage={type:messageTypeEnum.call,responseId:-1,functionId:"",args:[]},resolveMessage={type:messageTypeEnum.resolve,responseId:-1,value:void 0},rejectMessage={type:messageTypeEnum.reject,responseId:-1,reason:void 0},importHandler=(threadData,message)=>{let promise=import(message.moduleId);promise.then(()=>{resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage)}),promise.catch((error)=>{rejectMessage.responseId=message.responseId,rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage),rejectMessage.reason=void 0})};var callHandler=(threadData,message)=>{let{responseId,functionId,args}=message,fn=functionMap.get(functionId);try{let result=fn(...args);resolveMessage.responseId=responseId,resolveMessage.value=result,threadData.messagePort.postMessage(resolveMessage,Thread.transfer)}catch(error){rejectMessage.responseId=responseId,rejectMessage.reason=error;try{threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0}resolveMessage.value=void 0,Thread.transfer.length=0},resolveHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.resolve(message.value),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},rejectHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.reject(message.reason),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},ThreadPrivateStaticData={nextResponseId:0,enablePrivateAccess:!1,createWorker:null,[messageTypeEnum.create]:null,[messageTypeEnum.connect]:null,[messageTypeEnum.import]:importHandler,[messageTypeEnum.call]:callHandler,[messageTypeEnum.resolve]:resolveHandler,[messageTypeEnum.reject]:rejectHandler,[messageTypeEnum.close]:null,[messageTypeEnum.terminate]:null,[messageTypeEnum.disconnect]:null},messageListener=function(event){ThreadPrivateStaticData[event.data.type](this,event.data)},abortListener=function(){this.reject(this.signal.reason),this.signal.removeEventListener("abort",this),this.threadData.messageResponseMap.delete(this.id)},threadPrivateDataMap=new Map,functionMap=new Map;class Thread{static isMainThread=isMainThread;static id=NaN;static workerData;static transfer=[];static eventTarget=new EventTarget;static mainThread=null;static create=(workerData)=>{throw new Error("Thread.create is not implemented")};static getThread=(threadId)=>threadPrivateDataMap.get(threadId)?.thread||null;static getAllThreads=()=>[...threadPrivateDataMap.values()].map((threadData)=>threadData.thread);static setFunction=(functionId,fn)=>{if(typeof fn!=="function")throw new TypeError(`fn (${typeof fn}) is not a function`);functionMap.set(String(functionId),fn)};static deleteFunction=(functionId)=>functionMap.delete(String(functionId));static close=(exitCode)=>{throw new Error("Thread.prototype.close is not implemented")};static[Symbol.hasInstance]=(thread)=>{return ThreadPrivateStaticData.enablePrivateAccess=!0,thread[getPrivateData]().handleEvent===messageListener};id=-1;[getPrivateData];constructor(key,threadId,messagePort){if(key!==privateKey)throw new Error("Illegal invocation");let threadData={thread:this,exitCode:NaN,messagePort,messageResponseMap:new Map,handleEvent:messageListener};this.id=threadId,messagePort.addEventListener("message",threadData),messagePort.start(),this[getPrivateData]=()=>{if(!ThreadPrivateStaticData.enablePrivateAccess)throw new Error("illegal invocation");return ThreadPrivateStaticData.enablePrivateAccess=!1,threadData},threadPrivateDataMap.set(threadId,threadData),Thread.eventTarget.dispatchEvent(new OnlineEvent(privateKey,this))}isOnline(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);return threadData.exitCode!==threadData.exitCode}import(moduleId,signal){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)throw new Error(`thread ${this.id} is closed`);if(moduleId=String(moduleId),signal!==void 0&&!(signal instanceof AbortSignal))throw new TypeError(`signal (${Object.prototype.toString.call(signal)}) is not an AbortSignal instance`);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),importMessage.responseId=messageResponse.id,importMessage.moduleId=moduleId,threadData.messagePort.postMessage(importMessage),importMessage.moduleId=""})}call(functionId,argsOrOptions){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)throw new Error(`thread ${this.id} is closed`);functionId=String(functionId);let transfer,signal;if(argsOrOptions!==void 0){if(typeof argsOrOptions!=="object")throw new TypeError(`argsOrOptions (${typeof argsOrOptions}) is not an object`);if(argsOrOptions instanceof Array)callMessage.args=argsOrOptions;else{if(argsOrOptions.args&&!(argsOrOptions.args instanceof Array))throw new TypeError(`options.args (${Object.prototype.toString.call(argsOrOptions.args)}) is not an Array`);if(transfer=argsOrOptions.transfer,transfer&&!(transfer instanceof Array))throw new TypeError(`options.transfer (${Object.prototype.toString.call(transfer)}) is not an Array`);if(signal=argsOrOptions.signal,signal&&!(signal instanceof AbortSignal))throw new TypeError(`options.signal (${Object.prototype.toString.call(signal)}) is not an AbortSignal`);callMessage.args=argsOrOptions.args||[]}}return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),callMessage.responseId=messageResponse.id,callMessage.functionId=functionId;try{threadData.messagePort.postMessage(callMessage,transfer)}catch(error){reject(error),signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(messageResponse.id)}callMessage.functionId="",callMessage.args=null})}terminate(){throw new Error("Thread.prototype.terminate is not implemented")}}var destructThreadPrivateData=(threadData,exitCode)=>{if(threadData.messagePort){for(let[id,response]of threadData.messageResponseMap)response.reject(new Error(`thread ${threadData.thread.id} closed`)),response.signal?.removeEventListener("abort",response),threadData.messageResponseMap.delete(id);threadData.exitCode=Number(exitCode),threadData.messagePort=void 0,threadData.messageResponseMap=void 0,threadPrivateDataMap.delete(threadData.thread.id),Thread.eventTarget.dispatchEvent(new ExitEvent(privateKey,threadData.thread.id,exitCode))}};var setupWorker;if(Thread.isMainThread){let workerMap=new Map,connectMessage={type:messageTypeEnum.connect,threadId:-1,messagePort:null},disconnectMessage={type:messageTypeEnum.disconnect,threadId:-1,exitCode:-1},closeThread=(threadData,exitCode)=>{destructThreadPrivateData(threadData);let{thread,messagePort}=threadData;disconnectMessage.threadId=thread.id,disconnectMessage.exitCode=exitCode||0;for(let[id,threadData2]of threadPrivateDataMap)threadData2.messagePort.postMessage(disconnectMessage);workerMap.get(thread.id).terminate(),workerMap.delete(thread.id)};setupWorker=(threadId,worker,setupWorkerMessage)=>{let{port1,port2}=new MessageChannel;connectMessage.threadId=threadId,setupWorkerMessage.currentThreadIds.push(0),setupWorkerMessage.currentMessagePorts.push(port2);for(let[id,threadData]of threadPrivateDataMap){let{port1:port12,port2:port22}=new MessageChannel;connectMessage.messagePort=port12,threadData.messagePort.postMessage(connectMessage,[port12]),setupWorkerMessage.currentThreadIds.push(id),setupWorkerMessage.currentMessagePorts.push(port22)}return workerMap.set(threadId,worker),worker.postMessage(setupWorkerMessage,setupWorkerMessage.currentMessagePorts),setupWorkerMessage.currentThreadIds.length=0,setupWorkerMessage.currentMessagePorts.length=0,new Thread(privateKey,threadId,port1)};let createHandler=(threadData,message)=>{resolveMessage.value=ThreadPrivateStaticData.createWorker(message.workerData).id,resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage),resolveMessage.value=void 0},terminateHandler=(_threadData,message)=>{if(message.threadId===0)Thread.close();let threadData=threadPrivateDataMap.get(message.threadId);if(threadData)closeThread(threadData);resolveMessage.responseId=message.responseId,_threadData.messagePort.postMessage(resolveMessage)},closeHandler=(threadData,message)=>{if(threadData.exitCode!==threadData.exitCode)closeThread(threadData,message.exitCode)};ThreadPrivateStaticData[messageTypeEnum.create]=createHandler,ThreadPrivateStaticData[messageTypeEnum.terminate]=terminateHandler,ThreadPrivateStaticData[messageTypeEnum.close]=closeHandler,Thread.create=(workerData)=>new Promise((resolve)=>{resolve(ThreadPrivateStaticData.createWorker(workerData))}),Thread.prototype.terminate=function(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);return closeThread(threadData),Promise.resolve(threadData.exitCode)}}var setupHandler,closeFactory;if(!Thread.isMainThread){let createMessage={type:messageTypeEnum.create,responseId:-1,workerData:void 0},terminateMessage={type:messageTypeEnum.terminate,responseId:-1,threadId:-1},closeMessage={type:messageTypeEnum.close,exitCode:NaN};setupHandler=(message)=>{for(let i=0;i<message.currentThreadIds.length;i++){let thread=new Thread(privateKey,message.currentThreadIds[i],message.currentMessagePorts[i]);if(message.currentThreadIds[i]===0)Thread.mainThread=thread}},closeFactory=(threadId,exit)=>(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadPrivateStaticData.enablePrivateAccess=!0,Thread.mainThread[getPrivateData]().messagePort.postMessage(closeMessage),exit(exitCode)};let connectHandler=(threadData,message)=>{new Thread(privateKey,message.threadId,message.messagePort)},disconnectHandler=(threadData,message)=>{let disconnectThreadData=threadPrivateDataMap.get(message.threadId);if(disconnectThreadData)destructThreadPrivateData(disconnectThreadData,message.exitCode)};ThreadPrivateStaticData[messageTypeEnum.connect]=connectHandler,ThreadPrivateStaticData[messageTypeEnum.disconnect]=disconnectHandler,Thread.create=(workerData)=>{return new Promise((resolve,reject)=>{ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=Thread.mainThread[getPrivateData](),messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal:null,resolve:(threadId)=>{resolve(threadPrivateDataMap.get(threadId).thread)},reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),createMessage.responseId=messageResponse.id,createMessage.workerData=workerData,threadData.messagePort.postMessage(createMessage),createMessage.workerData=void 0})},Thread.prototype.terminate=function(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)return Promise.resolve(threadData.exitCode);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal:null,resolve:()=>threadData.exitCode,reject,handleEvent:abortListener};terminateMessage.responseId=messageResponse.id,terminateMessage.threadId=this.id,ThreadPrivateStaticData.enablePrivateAccess=!0,Thread.mainThread[getPrivateData]().messagePort.postMessage(terminateMessage)})}}if(Thread.isMainThread){let nextThreadId=1,setupWorkerMessage={threadId:-1,workerData:void 0,currentThreadIds:[],currentMessagePorts:[]};Thread.id=0,Thread.workerData=null,Thread.close=close,ThreadPrivateStaticData.createWorker=(workerData)=>{setupWorkerMessage.threadId=nextThreadId++,setupWorkerMessage.workerData=workerData;let thread=setupWorker(setupWorkerMessage.threadId,new Worker(import.meta.url,{type:"module"}),setupWorkerMessage);return setupWorkerMessage.workerData=void 0,thread}}else{Thread.close=globalThis.close=closeFactory(Thread.id,globalThis.close),addEventListener("message",(event)=>{Thread.id=event.data.threadId,Thread.workerData=event.data.workerData,setupHandler(event.data)},{once:!0});let errorListener=()=>{setTimeout(()=>Thread.close(1))};addEventListener("error",errorListener),addEventListener("unhandledrejection",errorListener)}export{Thread}; | ||
| import{isMainThread}from"@dandre3000/is-main-thread";var illegalConstructor=()=>Error("Illegal constructor."),notTypeOf=(id,value,type)=>TypeError(`${id} (${typeof value}) is not ${type==="object"||type==="undefined"?"an":"a"} ${type}.`),notInstanceOf=(id,value,constructor)=>TypeError(`${id} (${Object.prototype.toString.call(value)}) is not an instance of ${constructor.name}.`),notImplemented=(id)=>Error(`${id} is not implemented.`),threadClosed=(thread)=>Error(`Thread ${thread.id} is closed`),apiDoesNotExist=(id)=>ReferenceError(`${id} is required to use @dandre3000/thread but does not exist`),errorReference={illegalConstructor,notTypeOf,notInstanceOf,notImplemented,threadClosed,apiDoesNotExist},emptyArray=[];class OnlineEvent extends Event{thread;constructor(thread){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;super("online");this.thread=thread}}class ExitEvent extends Event{thread;exitCode;constructor(thread,exitCode){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;super("exit");this.thread=thread,this.exitCode=exitCode}}var importMessage={type:2,responseId:-1,moduleId:""},invokeMessage={type:3,responseId:-1,functionId:"",args:null},resolveMessage={type:4,responseId:-1,value:void 0},rejectMessage={type:5,responseId:-1,reason:void 0},importHandler=(threadData,message)=>{let promise=import(message.moduleId);promise.then(()=>{resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage)}),promise.catch((error)=>{rejectMessage.responseId=message.responseId;try{rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0})},invokeHandler=async(threadData,message)=>{let{responseId,functionId,args}=message,fn=functionMap.get(functionId);try{if(typeof fn!=="function")throw Error(`Function ${functionId} does not exist`);let result=await fn(...args||emptyArray);if(result instanceof Promise)result=await result;resolveMessage.responseId=responseId,resolveMessage.value=result,threadData.messagePort.postMessage(resolveMessage,Thread.transfer)}catch(error){rejectMessage.responseId=responseId;try{rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0}resolveMessage.value=void 0,Thread.transfer.length=0},resolveHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.resolve(message.value),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},rejectHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.reject(message.reason),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},ThreadPrivateStatic={privateKey:!1,nextResponseId:0,createWorker:null,[0]:null,[1]:null,[2]:importHandler,[3]:invokeHandler,[4]:resolveHandler,[5]:rejectHandler,[6]:null,[7]:null,[8]:null},messageListener=function(event){ThreadPrivateStatic[event.data.type](this,event.data)},abortListener=function(){this.reject(this.signal.reason),this.signal.removeEventListener("abort",this),this.threadData.messageResponseMap.delete(this.id)},ThreadMap=new WeakMap,ThreadIdMap=new Map,functionMap=new Map;class Thread{static isMainThread=isMainThread;static id=NaN;static workerData;static transfer=[];static eventTarget=new EventTarget;static mainThread=null;static create=(workerData)=>{throw errorReference.notImplemented("Thread.create")};static getThread=(threadId)=>ThreadIdMap.get(threadId)?.thread||null;static getAllThreads=()=>[...ThreadIdMap.values()].map((threadData)=>threadData.thread);static setFunction=(id,fn)=>{if(id=String(id),typeof fn!=="function")throw errorReference.notTypeOf("fn",fn,"function");functionMap.set(id,fn)};static deleteFunction=(id)=>functionMap.delete(String(id));static close=(exitCode)=>{throw errorReference.notImplemented("Thread.close")};static[Symbol.hasInstance]=(thread)=>ThreadMap.has(thread);id=-1;constructor(threadId,messagePort){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;let threadData={thread:this,exitCode:NaN,messagePort,messageResponseMap:new Map,handleEvent:messageListener};this.id=threadId,messagePort.addEventListener("message",threadData),messagePort.start(),ThreadMap.set(this,threadData),ThreadIdMap.set(threadId,threadData),ThreadPrivateStatic.privateKey=!0,Thread.eventTarget.dispatchEvent(new OnlineEvent(this))}isOnline(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);return ThreadIdMap.has(this.id)}import(moduleId,signal){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadIdMap.get(this.id);if(!threadData)throw errorReference.threadClosed(this);if(moduleId=String(moduleId),signal!==void 0&&!(signal instanceof AbortSignal))throw errorReference.notInstanceOf("signal",signal,AbortSignal);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),importMessage.responseId=messageResponse.id,importMessage.moduleId=moduleId,threadData.messagePort.postMessage(importMessage),importMessage.moduleId=""})}invoke(id,args,transfer,signal){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadIdMap.get(this.id);if(!threadData)throw errorReference.threadClosed(this);if(id=String(id),args!==void 0&&!(args instanceof Array))throw errorReference.notInstanceOf("args",args,Array);if(transfer!==void 0&&!(transfer instanceof Array))throw errorReference.notInstanceOf("transfer",transfer,Array);if(signal!==void 0&&!(signal instanceof AbortSignal))throw errorReference.notInstanceOf("signal",signal,AbortSignal);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:signal||null,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),invokeMessage.responseId=messageResponse.id,invokeMessage.functionId=id,invokeMessage.args=args||null;try{threadData.messagePort.postMessage(invokeMessage,transfer||emptyArray)}catch(error){reject(error),signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(messageResponse.id)}invokeMessage.functionId="",invokeMessage.args=null})}terminate(){throw errorReference.notImplemented("Thread.prototype.terminate")}}var disconnectThread=(threadData,exitCode)=>{if(threadData.messagePort){for(let[id,response]of threadData.messageResponseMap)response.reject(errorReference.threadClosed(threadData.thread)),response.signal?.removeEventListener("abort",response),threadData.messageResponseMap.delete(id);threadData.exitCode=Number(exitCode),threadData.messagePort.close(),threadData.messagePort=void 0,threadData.messageResponseMap=void 0,ThreadIdMap.delete(threadData.thread.id),ThreadPrivateStatic.privateKey=!0,Thread.eventTarget.dispatchEvent(new ExitEvent(threadData.thread,threadData.exitCode))}};if(typeof Promise!=="function"||typeof Promise.prototype!=="object")throw errorReference.apiDoesNotExist("Promise");if(typeof WeakMap!=="function"||typeof WeakMap.prototype!=="object")throw errorReference.apiDoesNotExist("WeakMap");if(typeof MessageChannel!=="function"||typeof MessageChannel.prototype!=="object")throw errorReference.apiDoesNotExist("MessageChannel");if(typeof Symbol!=="function"||typeof Symbol.prototype!=="object")throw errorReference.apiDoesNotExist("Symbol");if(typeof Symbol.hasInstance!=="symbol")throw errorReference.apiDoesNotExist("Symbol.hasInstance");try{await(async()=>{})()}catch(error){throw errorReference.apiDoesNotExist("async functions")}if(typeof AbortController!=="function"||typeof AbortController.prototype!=="object")throw errorReference.apiDoesNotExist("AbortController");try{if(typeof import.meta!=="object")throw errorReference.apiDoesNotExist("import.meta")}catch(error){throw errorReference.apiDoesNotExist("import.meta")}try{import(import.meta.url)}catch(error){throw errorReference.apiDoesNotExist("dynamic import")}var setupWorker;if(Thread.isMainThread){let workerMap=new Map,connectMessage={type:1,threadId:-1,messagePort:null},disconnectMessage={type:8,threadId:-1,exitCode:-1},closeThread=async(threadData,exitCode)=>{let{thread,messagePort}=threadData;disconnectMessage.threadId=thread.id,disconnectMessage.exitCode=exitCode||0;for(let _ of ThreadIdMap)messagePort.postMessage(disconnectMessage);disconnectThread(threadData,exitCode),await workerMap.get(thread.id).terminate(),workerMap.delete(thread.id)};setupWorker=(threadId,worker,setupWorkerMessage)=>{let{port1,port2}=new MessageChannel;connectMessage.threadId=threadId,setupWorkerMessage.currentThreadIds.push(0),setupWorkerMessage.currentMessagePorts.push(port2);for(let[id,threadData]of ThreadIdMap){let{port1:port12,port2:port22}=new MessageChannel;connectMessage.messagePort=port12,threadData.messagePort.postMessage(connectMessage,[port12]),setupWorkerMessage.currentThreadIds.push(id),setupWorkerMessage.currentMessagePorts.push(port22)}return workerMap.set(threadId,worker),worker.postMessage(setupWorkerMessage,setupWorkerMessage.currentMessagePorts),setupWorkerMessage.currentThreadIds.length=0,setupWorkerMessage.currentMessagePorts.length=0,ThreadPrivateStatic.privateKey=!0,new Thread(threadId,port1)};let createHandler=(threadData,message)=>{resolveMessage.value=ThreadPrivateStatic.createWorker(message.workerData).id,resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage),resolveMessage.value=void 0},terminateHandler=(_threadData,message)=>{if(message.threadId===0)Thread.close();let threadData=ThreadIdMap.get(message.threadId);if(threadData)closeThread(threadData);resolveMessage.responseId=message.responseId,_threadData.messagePort.postMessage(resolveMessage)},closeHandler=(threadData,message)=>{if(threadData.exitCode!==threadData.exitCode)closeThread(threadData,message.exitCode)};ThreadPrivateStatic[0]=createHandler,ThreadPrivateStatic[7]=terminateHandler,ThreadPrivateStatic[6]=closeHandler,Thread.close=globalThis.close||process.exit,Thread.create=async(workerData)=>await ThreadPrivateStatic.createWorker(workerData),Thread.prototype.terminate=async function(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadMap.get(this);if(ThreadIdMap.has(this.id))await closeThread(threadData,0);return threadData.exitCode}}var setupHandler;if(!Thread.isMainThread){let createMessage={type:0,responseId:-1,workerData:void 0},terminateMessage={type:7,responseId:-1,threadId:-1},closeMessage={type:6,exitCode:NaN};setupHandler=(message)=>{for(let i=0;i<message.currentThreadIds.length;i++){ThreadPrivateStatic.privateKey=!0;let thread=new Thread(message.currentThreadIds[i],message.currentMessagePorts[i]);if(message.currentThreadIds[i]===0)Thread.mainThread=thread}};let connectHandler=(_,message)=>{ThreadPrivateStatic.privateKey=!0,new Thread(message.threadId,message.messagePort)},disconnectHandler=(_,message)=>{let disconnectThreadData=ThreadIdMap.get(message.threadId);if(disconnectThreadData)disconnectThread(disconnectThreadData,message.exitCode)};ThreadPrivateStatic[1]=connectHandler,ThreadPrivateStatic[8]=disconnectHandler,Thread.close=globalThis.close?(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadIdMap.get(0).messagePort.postMessage(closeMessage),close()}:(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadIdMap.get(0).messagePort.postMessage(closeMessage),process.exit(exitCode)},Thread.create=(workerData)=>{return new Promise((resolve,reject)=>{let threadData=ThreadIdMap.get(0),messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:null,resolve:(threadId)=>{resolve(ThreadIdMap.get(threadId).thread)},reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),createMessage.responseId=messageResponse.id,createMessage.workerData=workerData,threadData.messagePort.postMessage(createMessage),createMessage.workerData=void 0})},Thread.prototype.terminate=function(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadMap.get(this);if(threadData.exitCode===threadData.exitCode)return Promise.resolve(threadData.exitCode);return new Promise((_,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:null,resolve:()=>threadData.exitCode,reject,handleEvent:abortListener};terminateMessage.responseId=messageResponse.id,terminateMessage.threadId=this.id,ThreadIdMap.get(0).messagePort.postMessage(terminateMessage)})}}if(typeof Worker!=="function"||typeof Worker.prototype!=="object")throw errorReference.apiDoesNotExist("Worker");if(typeof setTimeout!=="function")throw errorReference.apiDoesNotExist("setTimeout");if(Thread.isMainThread){let nextThreadId=1,setupWorkerMessage={threadId:-1,workerData:void 0,currentThreadIds:[],currentMessagePorts:[]};Thread.id=0,Thread.workerData=null,Thread.close=globalThis.close,ThreadPrivateStatic.createWorker=(workerData)=>{setupWorkerMessage.threadId=nextThreadId++,setupWorkerMessage.workerData=workerData;let thread=setupWorker(setupWorkerMessage.threadId,new Worker(import.meta.url,{type:"module"}),setupWorkerMessage);return setupWorkerMessage.workerData=void 0,thread}}else{addEventListener("message",(event)=>{Thread.id=event.data.threadId,Thread.workerData=event.data.workerData,setupHandler(event.data)},{once:!0});let errorListener=()=>{setTimeout(()=>Thread.close(1))};addEventListener("error",errorListener),addEventListener("unhandledrejection",errorListener)}export{Thread}; |
@@ -0,2 +1,3 @@ | ||
| import './compatibility.ts'; | ||
| import { Thread } from './Thread.ts'; | ||
| export { Thread }; |
@@ -1,1 +0,1 @@ | ||
| import{parentPort,threadId,Worker,workerData}from"node:worker_threads";import{isMainThread}from"@dandre3000/is-main-thread";class OnlineEvent extends Event{thread;constructor(key,thread){if(key!==privateKey)throw new Error("illegal invocation");super("online");this.thread=thread}}class ExitEvent extends Event{threadId;exitCode;constructor(key,threadId,exitCode){if(key!==privateKey)throw new Error("illegal invocation");super("exit");this.threadId=threadId,this.exitCode=exitCode}}var getPrivateData=Symbol(),privateKey=Symbol(),messageTypeEnum={create:0,connect:1,import:2,call:3,resolve:4,reject:5,close:6,terminate:7,disconnect:8},importMessage={type:messageTypeEnum.import,responseId:-1,moduleId:""},callMessage={type:messageTypeEnum.call,responseId:-1,functionId:"",args:[]},resolveMessage={type:messageTypeEnum.resolve,responseId:-1,value:void 0},rejectMessage={type:messageTypeEnum.reject,responseId:-1,reason:void 0},importHandler=(threadData,message)=>{let promise=import(message.moduleId);promise.then(()=>{resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage)}),promise.catch((error)=>{rejectMessage.responseId=message.responseId,rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage),rejectMessage.reason=void 0})};var callHandler=(threadData,message)=>{let{responseId,functionId,args}=message,fn=functionMap.get(functionId);try{let result=fn(...args);resolveMessage.responseId=responseId,resolveMessage.value=result,threadData.messagePort.postMessage(resolveMessage,Thread.transfer)}catch(error){rejectMessage.responseId=responseId,rejectMessage.reason=error;try{threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0}resolveMessage.value=void 0,Thread.transfer.length=0},resolveHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.resolve(message.value),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},rejectHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.reject(message.reason),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},ThreadPrivateStaticData={nextResponseId:0,enablePrivateAccess:!1,createWorker:null,[messageTypeEnum.create]:null,[messageTypeEnum.connect]:null,[messageTypeEnum.import]:importHandler,[messageTypeEnum.call]:callHandler,[messageTypeEnum.resolve]:resolveHandler,[messageTypeEnum.reject]:rejectHandler,[messageTypeEnum.close]:null,[messageTypeEnum.terminate]:null,[messageTypeEnum.disconnect]:null},messageListener=function(event){ThreadPrivateStaticData[event.data.type](this,event.data)},abortListener=function(){this.reject(this.signal.reason),this.signal.removeEventListener("abort",this),this.threadData.messageResponseMap.delete(this.id)},threadPrivateDataMap=new Map,functionMap=new Map;class Thread{static isMainThread=isMainThread;static id=NaN;static workerData;static transfer=[];static eventTarget=new EventTarget;static mainThread=null;static create=(workerData)=>{throw new Error("Thread.create is not implemented")};static getThread=(threadId)=>threadPrivateDataMap.get(threadId)?.thread||null;static getAllThreads=()=>[...threadPrivateDataMap.values()].map((threadData)=>threadData.thread);static setFunction=(functionId,fn)=>{if(typeof fn!=="function")throw new TypeError(`fn (${typeof fn}) is not a function`);functionMap.set(String(functionId),fn)};static deleteFunction=(functionId)=>functionMap.delete(String(functionId));static close=(exitCode)=>{throw new Error("Thread.prototype.close is not implemented")};static[Symbol.hasInstance]=(thread)=>{return ThreadPrivateStaticData.enablePrivateAccess=!0,thread[getPrivateData]().handleEvent===messageListener};id=-1;[getPrivateData];constructor(key,threadId,messagePort){if(key!==privateKey)throw new Error("Illegal invocation");let threadData={thread:this,exitCode:NaN,messagePort,messageResponseMap:new Map,handleEvent:messageListener};this.id=threadId,messagePort.addEventListener("message",threadData),messagePort.start(),this[getPrivateData]=()=>{if(!ThreadPrivateStaticData.enablePrivateAccess)throw new Error("illegal invocation");return ThreadPrivateStaticData.enablePrivateAccess=!1,threadData},threadPrivateDataMap.set(threadId,threadData),Thread.eventTarget.dispatchEvent(new OnlineEvent(privateKey,this))}isOnline(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);return threadData.exitCode!==threadData.exitCode}import(moduleId,signal){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)throw new Error(`thread ${this.id} is closed`);if(moduleId=String(moduleId),signal!==void 0&&!(signal instanceof AbortSignal))throw new TypeError(`signal (${Object.prototype.toString.call(signal)}) is not an AbortSignal instance`);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),importMessage.responseId=messageResponse.id,importMessage.moduleId=moduleId,threadData.messagePort.postMessage(importMessage),importMessage.moduleId=""})}call(functionId,argsOrOptions){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)throw new Error(`thread ${this.id} is closed`);functionId=String(functionId);let transfer,signal;if(argsOrOptions!==void 0){if(typeof argsOrOptions!=="object")throw new TypeError(`argsOrOptions (${typeof argsOrOptions}) is not an object`);if(argsOrOptions instanceof Array)callMessage.args=argsOrOptions;else{if(argsOrOptions.args&&!(argsOrOptions.args instanceof Array))throw new TypeError(`options.args (${Object.prototype.toString.call(argsOrOptions.args)}) is not an Array`);if(transfer=argsOrOptions.transfer,transfer&&!(transfer instanceof Array))throw new TypeError(`options.transfer (${Object.prototype.toString.call(transfer)}) is not an Array`);if(signal=argsOrOptions.signal,signal&&!(signal instanceof AbortSignal))throw new TypeError(`options.signal (${Object.prototype.toString.call(signal)}) is not an AbortSignal`);callMessage.args=argsOrOptions.args||[]}}return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),callMessage.responseId=messageResponse.id,callMessage.functionId=functionId;try{threadData.messagePort.postMessage(callMessage,transfer)}catch(error){reject(error),signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(messageResponse.id)}callMessage.functionId="",callMessage.args=null})}terminate(){throw new Error("Thread.prototype.terminate is not implemented")}}var destructThreadPrivateData=(threadData,exitCode)=>{if(threadData.messagePort){for(let[id,response]of threadData.messageResponseMap)response.reject(new Error(`thread ${threadData.thread.id} closed`)),response.signal?.removeEventListener("abort",response),threadData.messageResponseMap.delete(id);threadData.exitCode=Number(exitCode),threadData.messagePort=void 0,threadData.messageResponseMap=void 0,threadPrivateDataMap.delete(threadData.thread.id),Thread.eventTarget.dispatchEvent(new ExitEvent(privateKey,threadData.thread.id,exitCode))}};var setupWorker;if(Thread.isMainThread){let workerMap=new Map,connectMessage={type:messageTypeEnum.connect,threadId:-1,messagePort:null},disconnectMessage={type:messageTypeEnum.disconnect,threadId:-1,exitCode:-1},closeThread=(threadData,exitCode)=>{destructThreadPrivateData(threadData);let{thread,messagePort}=threadData;disconnectMessage.threadId=thread.id,disconnectMessage.exitCode=exitCode||0;for(let[id,threadData2]of threadPrivateDataMap)threadData2.messagePort.postMessage(disconnectMessage);workerMap.get(thread.id).terminate(),workerMap.delete(thread.id)};setupWorker=(threadId,worker,setupWorkerMessage)=>{let{port1,port2}=new MessageChannel;connectMessage.threadId=threadId,setupWorkerMessage.currentThreadIds.push(0),setupWorkerMessage.currentMessagePorts.push(port2);for(let[id,threadData]of threadPrivateDataMap){let{port1:port12,port2:port22}=new MessageChannel;connectMessage.messagePort=port12,threadData.messagePort.postMessage(connectMessage,[port12]),setupWorkerMessage.currentThreadIds.push(id),setupWorkerMessage.currentMessagePorts.push(port22)}return workerMap.set(threadId,worker),worker.postMessage(setupWorkerMessage,setupWorkerMessage.currentMessagePorts),setupWorkerMessage.currentThreadIds.length=0,setupWorkerMessage.currentMessagePorts.length=0,new Thread(privateKey,threadId,port1)};let createHandler=(threadData,message)=>{resolveMessage.value=ThreadPrivateStaticData.createWorker(message.workerData).id,resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage),resolveMessage.value=void 0},terminateHandler=(_threadData,message)=>{if(message.threadId===0)Thread.close();let threadData=threadPrivateDataMap.get(message.threadId);if(threadData)closeThread(threadData);resolveMessage.responseId=message.responseId,_threadData.messagePort.postMessage(resolveMessage)},closeHandler=(threadData,message)=>{if(threadData.exitCode!==threadData.exitCode)closeThread(threadData,message.exitCode)};ThreadPrivateStaticData[messageTypeEnum.create]=createHandler,ThreadPrivateStaticData[messageTypeEnum.terminate]=terminateHandler,ThreadPrivateStaticData[messageTypeEnum.close]=closeHandler,Thread.create=(workerData)=>new Promise((resolve)=>{resolve(ThreadPrivateStaticData.createWorker(workerData))}),Thread.prototype.terminate=function(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);return closeThread(threadData),Promise.resolve(threadData.exitCode)}}var setupHandler,closeFactory;if(!Thread.isMainThread){let createMessage={type:messageTypeEnum.create,responseId:-1,workerData:void 0},terminateMessage={type:messageTypeEnum.terminate,responseId:-1,threadId:-1},closeMessage={type:messageTypeEnum.close,exitCode:NaN};setupHandler=(message)=>{for(let i=0;i<message.currentThreadIds.length;i++){let thread=new Thread(privateKey,message.currentThreadIds[i],message.currentMessagePorts[i]);if(message.currentThreadIds[i]===0)Thread.mainThread=thread}},closeFactory=(threadId,exit)=>(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadPrivateStaticData.enablePrivateAccess=!0,Thread.mainThread[getPrivateData]().messagePort.postMessage(closeMessage),exit(exitCode)};let connectHandler=(threadData,message)=>{new Thread(privateKey,message.threadId,message.messagePort)},disconnectHandler=(threadData,message)=>{let disconnectThreadData=threadPrivateDataMap.get(message.threadId);if(disconnectThreadData)destructThreadPrivateData(disconnectThreadData,message.exitCode)};ThreadPrivateStaticData[messageTypeEnum.connect]=connectHandler,ThreadPrivateStaticData[messageTypeEnum.disconnect]=disconnectHandler,Thread.create=(workerData)=>{return new Promise((resolve,reject)=>{ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=Thread.mainThread[getPrivateData](),messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal:null,resolve:(threadId)=>{resolve(threadPrivateDataMap.get(threadId).thread)},reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),createMessage.responseId=messageResponse.id,createMessage.workerData=workerData,threadData.messagePort.postMessage(createMessage),createMessage.workerData=void 0})},Thread.prototype.terminate=function(){ThreadPrivateStaticData.enablePrivateAccess=!0;let threadData=this[getPrivateData]();if(threadData?.handleEvent!==messageListener)throw new TypeError(`this (${Object.prototype.toString.call(this)}) is not a Thread instance`);if(threadData.exitCode===threadData.exitCode)return Promise.resolve(threadData.exitCode);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStaticData.nextResponseId++,threadData,signal:null,resolve:()=>threadData.exitCode,reject,handleEvent:abortListener};terminateMessage.responseId=messageResponse.id,terminateMessage.threadId=this.id,ThreadPrivateStaticData.enablePrivateAccess=!0,Thread.mainThread[getPrivateData]().messagePort.postMessage(terminateMessage)})}}if(Thread.isMainThread){Thread.id=threadId,Thread.workerData=workerData,Thread.close=process.exit;let setupWorkerMessage={currentThreadIds:[],currentMessagePorts:[]};ThreadPrivateStaticData.createWorker=(workerData2)=>{let worker=new Worker(new URL(import.meta.url),{workerData:workerData2});return setupWorker(worker.threadId,worker,setupWorkerMessage)}}else{Thread.id=threadId,Thread.workerData=workerData,Thread.close=process.exit=closeFactory(threadId,process.exit),parentPort.once("message",(message)=>{setupHandler(message)});let errorListener=()=>{setImmediate(()=>Thread.close(1))};process.on("uncaughtException",errorListener),process.on("unhandledRejection",errorListener)}export{Thread}; | ||
| import{createRequire}from"node:module";var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defProp,getOwnPropertyNames:__getOwnPropNames}=Object;var __hasOwnProp=Object.prototype.hasOwnProperty;var __toESM=(mod,isNodeMode,target)=>{target=mod!=null?__create(__getProtoOf(mod)):{};let to=isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target;for(let key of __getOwnPropNames(mod))if(!__hasOwnProp.call(to,key))__defProp(to,key,{get:()=>mod[key],enumerable:!0});return to};var __require=createRequire(import.meta.url);import{isMainThread}from"@dandre3000/is-main-thread";var illegalConstructor=()=>Error("Illegal constructor."),notTypeOf=(id,value,type)=>TypeError(`${id} (${typeof value}) is not ${type==="object"||type==="undefined"?"an":"a"} ${type}.`),notInstanceOf=(id,value,constructor)=>TypeError(`${id} (${Object.prototype.toString.call(value)}) is not an instance of ${constructor.name}.`),notImplemented=(id)=>Error(`${id} is not implemented.`),threadClosed=(thread)=>Error(`Thread ${thread.id} is closed`),apiDoesNotExist=(id)=>ReferenceError(`${id} is required to use @dandre3000/thread but does not exist`),errorReference={illegalConstructor,notTypeOf,notInstanceOf,notImplemented,threadClosed,apiDoesNotExist},emptyArray=[];class OnlineEvent extends Event{thread;constructor(thread){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;super("online");this.thread=thread}}class ExitEvent extends Event{thread;exitCode;constructor(thread,exitCode){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;super("exit");this.thread=thread,this.exitCode=exitCode}}var importMessage={type:2,responseId:-1,moduleId:""},invokeMessage={type:3,responseId:-1,functionId:"",args:null},resolveMessage={type:4,responseId:-1,value:void 0},rejectMessage={type:5,responseId:-1,reason:void 0},importHandler=(threadData,message)=>{let promise=import(message.moduleId);promise.then(()=>{resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage)}),promise.catch((error)=>{rejectMessage.responseId=message.responseId;try{rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0})},invokeHandler=async(threadData,message)=>{let{responseId,functionId,args}=message,fn=functionMap.get(functionId);try{if(typeof fn!=="function")throw Error(`Function ${functionId} does not exist`);let result=await fn(...args||emptyArray);if(result instanceof Promise)result=await result;resolveMessage.responseId=responseId,resolveMessage.value=result,threadData.messagePort.postMessage(resolveMessage,Thread.transfer)}catch(error){rejectMessage.responseId=responseId;try{rejectMessage.reason=error,threadData.messagePort.postMessage(rejectMessage)}catch(error2){rejectMessage.reason=error2,threadData.messagePort.postMessage(rejectMessage)}rejectMessage.reason=void 0}resolveMessage.value=void 0,Thread.transfer.length=0},resolveHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.resolve(message.value),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},rejectHandler=(threadData,message)=>{let messageResponse=threadData.messageResponseMap.get(message.responseId);if(messageResponse)messageResponse.reject(message.reason),messageResponse.signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(message.responseId)},ThreadPrivateStatic={privateKey:!1,nextResponseId:0,createWorker:null,[0]:null,[1]:null,[2]:importHandler,[3]:invokeHandler,[4]:resolveHandler,[5]:rejectHandler,[6]:null,[7]:null,[8]:null},messageListener=function(event){ThreadPrivateStatic[event.data.type](this,event.data)},abortListener=function(){this.reject(this.signal.reason),this.signal.removeEventListener("abort",this),this.threadData.messageResponseMap.delete(this.id)},ThreadMap=new WeakMap,ThreadIdMap=new Map,functionMap=new Map;class Thread{static isMainThread=isMainThread;static id=NaN;static workerData;static transfer=[];static eventTarget=new EventTarget;static mainThread=null;static create=(workerData)=>{throw errorReference.notImplemented("Thread.create")};static getThread=(threadId)=>ThreadIdMap.get(threadId)?.thread||null;static getAllThreads=()=>[...ThreadIdMap.values()].map((threadData)=>threadData.thread);static setFunction=(id,fn)=>{if(id=String(id),typeof fn!=="function")throw errorReference.notTypeOf("fn",fn,"function");functionMap.set(id,fn)};static deleteFunction=(id)=>functionMap.delete(String(id));static close=(exitCode)=>{throw errorReference.notImplemented("Thread.close")};static[Symbol.hasInstance]=(thread)=>ThreadMap.has(thread);id=-1;constructor(threadId,messagePort){if(!ThreadPrivateStatic.privateKey)throw errorReference.illegalConstructor();ThreadPrivateStatic.privateKey=!1;let threadData={thread:this,exitCode:NaN,messagePort,messageResponseMap:new Map,handleEvent:messageListener};this.id=threadId,messagePort.addEventListener("message",threadData),messagePort.start(),ThreadMap.set(this,threadData),ThreadIdMap.set(threadId,threadData),ThreadPrivateStatic.privateKey=!0,Thread.eventTarget.dispatchEvent(new OnlineEvent(this))}isOnline(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);return ThreadIdMap.has(this.id)}import(moduleId,signal){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadIdMap.get(this.id);if(!threadData)throw errorReference.threadClosed(this);if(moduleId=String(moduleId),signal!==void 0&&!(signal instanceof AbortSignal))throw errorReference.notInstanceOf("signal",signal,AbortSignal);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),importMessage.responseId=messageResponse.id,importMessage.moduleId=moduleId,threadData.messagePort.postMessage(importMessage),importMessage.moduleId=""})}invoke(id,args,transfer,signal){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadIdMap.get(this.id);if(!threadData)throw errorReference.threadClosed(this);if(id=String(id),args!==void 0&&!(args instanceof Array))throw errorReference.notInstanceOf("args",args,Array);if(transfer!==void 0&&!(transfer instanceof Array))throw errorReference.notInstanceOf("transfer",transfer,Array);if(signal!==void 0&&!(signal instanceof AbortSignal))throw errorReference.notInstanceOf("signal",signal,AbortSignal);return new Promise((resolve,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:signal||null,resolve,reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),signal?.addEventListener("abort",messageResponse),invokeMessage.responseId=messageResponse.id,invokeMessage.functionId=id,invokeMessage.args=args||null;try{threadData.messagePort.postMessage(invokeMessage,transfer||emptyArray)}catch(error){reject(error),signal?.removeEventListener("abort",messageResponse),threadData.messageResponseMap.delete(messageResponse.id)}invokeMessage.functionId="",invokeMessage.args=null})}terminate(){throw errorReference.notImplemented("Thread.prototype.terminate")}}var disconnectThread=(threadData,exitCode)=>{if(threadData.messagePort){for(let[id,response]of threadData.messageResponseMap)response.reject(errorReference.threadClosed(threadData.thread)),response.signal?.removeEventListener("abort",response),threadData.messageResponseMap.delete(id);threadData.exitCode=Number(exitCode),threadData.messagePort.close(),threadData.messagePort=void 0,threadData.messageResponseMap=void 0,ThreadIdMap.delete(threadData.thread.id),ThreadPrivateStatic.privateKey=!0,Thread.eventTarget.dispatchEvent(new ExitEvent(threadData.thread,threadData.exitCode))}};if(typeof Promise!=="function"||typeof Promise.prototype!=="object")throw errorReference.apiDoesNotExist("Promise");if(typeof WeakMap!=="function"||typeof WeakMap.prototype!=="object")throw errorReference.apiDoesNotExist("WeakMap");if(typeof MessageChannel!=="function"||typeof MessageChannel.prototype!=="object")throw errorReference.apiDoesNotExist("MessageChannel");if(typeof Symbol!=="function"||typeof Symbol.prototype!=="object")throw errorReference.apiDoesNotExist("Symbol");if(typeof Symbol.hasInstance!=="symbol")throw errorReference.apiDoesNotExist("Symbol.hasInstance");try{await(async()=>{})()}catch(error){throw errorReference.apiDoesNotExist("async functions")}if(typeof AbortController!=="function"||typeof AbortController.prototype!=="object")throw errorReference.apiDoesNotExist("AbortController");try{if(typeof import.meta!=="object")throw errorReference.apiDoesNotExist("import.meta")}catch(error){throw errorReference.apiDoesNotExist("import.meta")}try{import(import.meta.url)}catch(error){throw errorReference.apiDoesNotExist("dynamic import")}var setupWorker;if(Thread.isMainThread){let workerMap=new Map,connectMessage={type:1,threadId:-1,messagePort:null},disconnectMessage={type:8,threadId:-1,exitCode:-1},closeThread=async(threadData,exitCode)=>{let{thread,messagePort}=threadData;disconnectMessage.threadId=thread.id,disconnectMessage.exitCode=exitCode||0;for(let _ of ThreadIdMap)messagePort.postMessage(disconnectMessage);disconnectThread(threadData,exitCode),await workerMap.get(thread.id).terminate(),workerMap.delete(thread.id)};setupWorker=(threadId,worker,setupWorkerMessage)=>{let{port1,port2}=new MessageChannel;connectMessage.threadId=threadId,setupWorkerMessage.currentThreadIds.push(0),setupWorkerMessage.currentMessagePorts.push(port2);for(let[id,threadData]of ThreadIdMap){let{port1:port12,port2:port22}=new MessageChannel;connectMessage.messagePort=port12,threadData.messagePort.postMessage(connectMessage,[port12]),setupWorkerMessage.currentThreadIds.push(id),setupWorkerMessage.currentMessagePorts.push(port22)}return workerMap.set(threadId,worker),worker.postMessage(setupWorkerMessage,setupWorkerMessage.currentMessagePorts),setupWorkerMessage.currentThreadIds.length=0,setupWorkerMessage.currentMessagePorts.length=0,ThreadPrivateStatic.privateKey=!0,new Thread(threadId,port1)};let createHandler=(threadData,message)=>{resolveMessage.value=ThreadPrivateStatic.createWorker(message.workerData).id,resolveMessage.responseId=message.responseId,threadData.messagePort.postMessage(resolveMessage),resolveMessage.value=void 0},terminateHandler=(_threadData,message)=>{if(message.threadId===0)Thread.close();let threadData=ThreadIdMap.get(message.threadId);if(threadData)closeThread(threadData);resolveMessage.responseId=message.responseId,_threadData.messagePort.postMessage(resolveMessage)},closeHandler=(threadData,message)=>{if(threadData.exitCode!==threadData.exitCode)closeThread(threadData,message.exitCode)};ThreadPrivateStatic[0]=createHandler,ThreadPrivateStatic[7]=terminateHandler,ThreadPrivateStatic[6]=closeHandler,Thread.close=globalThis.close||process.exit,Thread.create=async(workerData)=>await ThreadPrivateStatic.createWorker(workerData),Thread.prototype.terminate=async function(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadMap.get(this);if(ThreadIdMap.has(this.id))await closeThread(threadData,0);return threadData.exitCode}}var setupHandler;if(!Thread.isMainThread){let createMessage={type:0,responseId:-1,workerData:void 0},terminateMessage={type:7,responseId:-1,threadId:-1},closeMessage={type:6,exitCode:NaN};setupHandler=(message)=>{for(let i=0;i<message.currentThreadIds.length;i++){ThreadPrivateStatic.privateKey=!0;let thread=new Thread(message.currentThreadIds[i],message.currentMessagePorts[i]);if(message.currentThreadIds[i]===0)Thread.mainThread=thread}};let connectHandler=(_,message)=>{ThreadPrivateStatic.privateKey=!0,new Thread(message.threadId,message.messagePort)},disconnectHandler=(_,message)=>{let disconnectThreadData=ThreadIdMap.get(message.threadId);if(disconnectThreadData)disconnectThread(disconnectThreadData,message.exitCode)};ThreadPrivateStatic[1]=connectHandler,ThreadPrivateStatic[8]=disconnectHandler,Thread.close=globalThis.close?(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadIdMap.get(0).messagePort.postMessage(closeMessage),close()}:(exitCode)=>{return closeMessage.exitCode=Number(exitCode),ThreadIdMap.get(0).messagePort.postMessage(closeMessage),process.exit(exitCode)},Thread.create=(workerData)=>{return new Promise((resolve,reject)=>{let threadData=ThreadIdMap.get(0),messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:null,resolve:(threadId)=>{resolve(ThreadIdMap.get(threadId).thread)},reject,handleEvent:abortListener};threadData.messageResponseMap.set(messageResponse.id,messageResponse),createMessage.responseId=messageResponse.id,createMessage.workerData=workerData,threadData.messagePort.postMessage(createMessage),createMessage.workerData=void 0})},Thread.prototype.terminate=function(){if(!(this instanceof Thread))throw errorReference.notInstanceOf("this",this,Thread);let threadData=ThreadMap.get(this);if(threadData.exitCode===threadData.exitCode)return Promise.resolve(threadData.exitCode);return new Promise((_,reject)=>{let messageResponse={id:ThreadPrivateStatic.nextResponseId++,threadData,signal:null,resolve:()=>threadData.exitCode,reject,handleEvent:abortListener};terminateMessage.responseId=messageResponse.id,terminateMessage.threadId=this.id,ThreadIdMap.get(0).messagePort.postMessage(terminateMessage)})}}var workerThreads;try{workerThreads=await import("node:worker_threads")}catch(error){throw errorReference.apiDoesNotExist("node:worker_threads")}if(typeof setImmediate!=="function"&&typeof setTimeout!=="function")throw errorReference.apiDoesNotExist("setImmediate or setTimeout");var{parentPort,threadId,Worker,workerData}=workerThreads;if(Thread.isMainThread){Thread.id=threadId,Thread.workerData=workerData;let setupWorkerMessage={currentThreadIds:[],currentMessagePorts:[]};ThreadPrivateStatic.createWorker=(workerData2)=>{let worker=new Worker(new URL(import.meta.url),{workerData:workerData2});return setupWorker(worker.threadId,worker,setupWorkerMessage)}}else{Thread.id=threadId,Thread.workerData=workerData,parentPort.once("message",(message)=>{setupHandler(message)});let errorListener=typeof setImmediate==="function"?()=>{setImmediate(()=>Thread.close(1))}:()=>{setTimeout(()=>Thread.close(1))};process.on("uncaughtException",errorListener),process.on("unhandledRejection",errorListener)}export{Thread}; |
+97
-103
| import { type Transferable as NodeJSTransferable } from 'node:worker_threads'; | ||
| export type MessageId = number; | ||
| export interface MessageResponse extends EventListenerObject { | ||
| id: MessageId; | ||
| threadData: ThreadPrivateInstanceData; | ||
| signal: AbortSignal; | ||
| resolve(value: any): void; | ||
| reject(reason: any): void; | ||
| export declare enum MessageType { | ||
| /** Thread.prototype.create from worker thread to main thread */ | ||
| Create = 0, | ||
| /** Thread.prototype.create from main thread */ | ||
| Connect = 1, | ||
| /** Thread.prototype.import */ | ||
| Import = 2, | ||
| /** Thread.prototype.invoke */ | ||
| Invoke = 3, | ||
| /** Thread.prototype.create, Thread.prototype.import, Thread.prototype.invoke, Thread.prototype.terminate */ | ||
| Resolve = 4, | ||
| /** Thread.prototype.create, Thread.prototype.import, Thread.prototype.invoke, Thread.prototype.terminate */ | ||
| Reject = 5, | ||
| /** globalThis.close, process.exit, Thread.close */ | ||
| Close = 6, | ||
| /** Thread.prototype.terminate */ | ||
| Terminate = 7, | ||
| /** globalThis.close, process.exit, Thread.close, Thread.prototype.terminate */ | ||
| Disconnect = 8 | ||
| } | ||
| export interface SetupMessage { | ||
| currentThreadIds: Thread['id'][]; | ||
| currentMessagePorts: MessagePort[]; | ||
| } | ||
| export type MessageType = number; | ||
| export interface Message { | ||
@@ -31,3 +39,3 @@ type: MessageType; | ||
| } | ||
| interface CallMessage extends AsyncMessage { | ||
| interface InvokeMessage extends AsyncMessage { | ||
| functionId: string; | ||
@@ -51,4 +59,15 @@ args: any[]; | ||
| } | ||
| export type MessageHandler<T extends Message> = (threadData: ThreadPrivateInstanceData, message: T) => void; | ||
| export interface ThreadPrivateInstanceData extends EventListenerObject { | ||
| export type MessageHandler<T extends Message> = (threadData: ThreadPrivate, message: T) => void; | ||
| export interface SetupMessage { | ||
| currentThreadIds: Thread['id'][]; | ||
| currentMessagePorts: MessagePort[]; | ||
| } | ||
| export interface MessageResponse extends EventListenerObject { | ||
| id: MessageId; | ||
| threadData: ThreadPrivate; | ||
| signal: AbortSignal; | ||
| resolve(value: any): void; | ||
| reject(reason: any): void; | ||
| } | ||
| export interface ThreadPrivate extends EventListenerObject { | ||
| thread: Thread; | ||
@@ -58,71 +77,50 @@ exitCode: number; | ||
| messageResponseMap: Map<MessageId, MessageResponse>; | ||
| handleEvent(this: ThreadPrivateInstanceData, event: MessageEvent<Message>): void; | ||
| handleEvent(this: ThreadPrivate, event: MessageEvent<Message>): void; | ||
| } | ||
| /** Thread.prototype.call */ | ||
| export interface CallOptions { | ||
| args?: any[]; | ||
| transfer?: (Transferable | NodeJSTransferable)[]; | ||
| signal?: AbortSignal; | ||
| } | ||
| export declare const errorReference: { | ||
| illegalConstructor: () => Error; | ||
| notTypeOf: (id: string, value: any, type: "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined") => TypeError; | ||
| notInstanceOf: <T>(id: string, value: any, constructor: new (...args: any[]) => T) => TypeError; | ||
| notImplemented: (id: any) => Error; | ||
| threadClosed: (thread: Thread) => Error; | ||
| apiDoesNotExist: (id: any) => ReferenceError; | ||
| }; | ||
| /** Default array */ | ||
| export declare const emptyArray: never[]; | ||
| /** Dispatched when a Thread is created. */ | ||
| export declare class OnlineEvent extends Event { | ||
| thread: Thread; | ||
| constructor(); | ||
| constructor(thread?: Thread); | ||
| } | ||
| /** Dispatched when a Thread is closed. */ | ||
| export declare class ExitEvent extends Event { | ||
| threadId: number; | ||
| thread: Thread; | ||
| exitCode: number; | ||
| constructor(); | ||
| constructor(thread?: Thread, exitCode?: number); | ||
| } | ||
| /** Return the private data of a Thread. */ | ||
| export declare const getPrivateData: unique symbol; | ||
| export declare const privateKey: unique symbol; | ||
| export declare const messageTypeEnum: { | ||
| /** Thread.prototype.create from worker thread to main thread */ | ||
| create: number; | ||
| /** Thread.prototype.create from main thread */ | ||
| connect: number; | ||
| /** Thread.prototype.import */ | ||
| import: number; | ||
| /** Thread.prototype.call */ | ||
| call: number; | ||
| /** Thread.prototype.create, Thread.prototype.import, Thread.prototype.call, Thread.prototype.terminate */ | ||
| resolve: number; | ||
| /** Thread.prototype.create, Thread.prototype.import, Thread.prototype.call, Thread.prototype.terminate */ | ||
| reject: number; | ||
| /** globalThis.close, process.exit, Thread.close */ | ||
| close: number; | ||
| /** Thread.prototype.terminate */ | ||
| terminate: number; | ||
| /** globalThis.close, process.exit, Thread.close, Thread.prototype.terminate */ | ||
| disconnect: number; | ||
| }; | ||
| export declare const resolveMessage: ResolveMessage; | ||
| export declare const transferables: (Transferable | NodeJSTransferable)[]; | ||
| export declare const ThreadPrivateStaticData: { | ||
| [messageTypeEnum.create]: any; | ||
| [messageTypeEnum.connect]: any; | ||
| [messageTypeEnum.import]: MessageHandler<ImportMessage>; | ||
| [messageTypeEnum.call]: MessageHandler<CallMessage>; | ||
| [messageTypeEnum.resolve]: MessageHandler<ResolveMessage>; | ||
| [messageTypeEnum.reject]: MessageHandler<RejectMessage>; | ||
| [messageTypeEnum.close]: any; | ||
| [messageTypeEnum.terminate]: any; | ||
| [messageTypeEnum.disconnect]: any; | ||
| /** Variables that will be passed by reference. */ | ||
| export declare const ThreadPrivateStatic: { | ||
| /** Required to use methods that are locked to the user. */ | ||
| privateKey: boolean; | ||
| /** The id of the next async message that is incremented upon assignment. */ | ||
| nextResponseId: number; | ||
| /** | ||
| * Set to true before calling (Thread instance)[getPrivateData] or an error is thrown. | ||
| * Is set to false by (Thread instance)[getPrivateData] to prevent user from accessing private data. | ||
| * */ | ||
| enablePrivateAccess: boolean; | ||
| /** Closure for the web or node.js Worker constructor that creates a Worker and return the corresponding thread instance. Implemented by the main thread. */ | ||
| createWorker: (workerData: any) => Thread; | ||
| 0: MessageHandler<CreateMessage>; | ||
| 1: MessageHandler<ConnectMessage>; | ||
| 2: MessageHandler<ImportMessage>; | ||
| 3: MessageHandler<InvokeMessage>; | ||
| 4: MessageHandler<ResolveMessage>; | ||
| 5: MessageHandler<RejectMessage>; | ||
| 6: MessageHandler<CloseMessage>; | ||
| 7: MessageHandler<TerminateMessage>; | ||
| 8: MessageHandler<DisconnectMessage>; | ||
| }; | ||
| /** The message listener for each thread's MessagePort. */ | ||
| export declare const messageListener: ThreadPrivateInstanceData['handleEvent']; | ||
| export declare const messageListener: ThreadPrivate['handleEvent']; | ||
| /** The abort listener for AbortSignal arguments in Thread methods. */ | ||
| export declare const abortListener: (this: MessageResponse) => void; | ||
| export declare const threadPrivateDataMap: Map<number, ThreadPrivateInstanceData>; | ||
| export declare const ThreadMap: WeakMap<Thread, ThreadPrivate>; | ||
| export declare const ThreadIdMap: Map<number, ThreadPrivate>; | ||
| /** Class for managing web and node.js Workers. */ | ||
@@ -137,5 +135,5 @@ export declare class Thread { | ||
| /** | ||
| * Array of objects that will be transfered and emptied whenever another thread uses Thread.prototype.call | ||
| * to call a function on this thread made available using Thread.setFunction. | ||
| * If an object is not transferable the Promise returned by Thread.prototype.call will be rejected. | ||
| * Array of objects that will be transfered and emptied whenever another thread uses Thread.prototype.invoke | ||
| * to invoke a function on this thread made available using Thread.setFunction. | ||
| * If an object is not transferable the Promise returned by Thread.prototype.invoke will be rejected. | ||
| */ | ||
@@ -149,3 +147,6 @@ static transfer: (Transferable | NodeJSTransferable)[]; | ||
| * Return a Promise that resolves to a new Thread. | ||
| * @param workerData Arbitrary value that is copied to the thread as Thread.workerData. If workerData is not compatible with the HTML structured clone algorithm the returned Promise will be rejected. | ||
| * | ||
| * @param workerData Arbitrary value that is copied to the thread as Thread.workerData. | ||
| * | ||
| * @throws {DOMException} if workerData is not compatible with the structuredClone function. | ||
| */ | ||
@@ -155,2 +156,3 @@ static create: (workerData: CreateMessage["workerData"]) => Promise<Thread>; | ||
| * Return the Thread corresponding to the given threadId or return null if no online Thread exists where Thread.id === threadId. | ||
| * | ||
| * @throws {TypeError} if threadId can not be converted to a number. | ||
@@ -162,12 +164,16 @@ */ | ||
| /** | ||
| * Add a function to those available to other threads using Thread.prototype.call. | ||
| * Add a function to those available to other threads using Thread.prototype.invoke. | ||
| * | ||
| * @param functionId Identifier to associate with the function. | ||
| * @param fn The function. | ||
| * | ||
| * @throws {TypeError} if fn is not a function. | ||
| */ | ||
| static setFunction: (functionId: any, fn: (...args: any[]) => any) => void; | ||
| static setFunction: (id: any, fn: (...args: any[]) => any) => void; | ||
| /** | ||
| * Remove a function from those available to other threads using Thread.prototype.call. | ||
| * @param functionId Identifier associated with the function. | ||
| * Remove a function from those available to other threads using Thread.prototype.invoke. | ||
| * | ||
| * @param id Identifier associated with the function. | ||
| */ | ||
| static deleteFunction: (functionId: any) => boolean; | ||
| static deleteFunction: (id: any) => boolean; | ||
| /** | ||
@@ -181,7 +187,7 @@ * Alias for globalThis.close or process.exit. | ||
| id: number; | ||
| [getPrivateData]: () => ThreadPrivateInstanceData; | ||
| /** Do not use. */ | ||
| constructor(); | ||
| constructor(threadId?: Thread['id'], messagePort?: MessagePort); | ||
| /** | ||
| * Returns true until the thread is closed. | ||
| * | ||
| * @throws {TypeError} if this is not a Thread instance. | ||
@@ -192,6 +198,8 @@ * */ | ||
| * Dynamically import an ES module to the thread and return a Promise that resolves when the module is loaded. | ||
| * | ||
| * @param moduleId Determines what module to import. | ||
| * @param signal An AbortSignal that may be used to reject the returned Promise. | ||
| * | ||
| * @throws {TypeError} if this is not a Thread instance. | ||
| * @throws {TypeError} if the Thread is closed. | ||
| * @throws {Error} if the Thread is closed. | ||
| * @throws {TypeError} if moduleId can not be converted to a number. | ||
@@ -202,33 +210,19 @@ */ | ||
| * Call a function on the thread added using Thread.setFunction and return a Promise that resolves to the value returned by that function. | ||
| * If no function is associated with functionId or the function throws an error then the returned Promise will be rejected. | ||
| * @param functionId An identifier that maps to a function. | ||
| * @param args An array of arguments that will be passed to the function. If an argument is not compatible with the HTML structured clone algorithm the returned Promise will be rejected. | ||
| * @throws {TypeError} if this is not a Thread instance. | ||
| * @throws {TypeError} if the Thread is closed. | ||
| * @throws {TypeError} if functionId can not be converted to a string. | ||
| */ | ||
| call(functionId: any, args?: any[]): Promise<any>; | ||
| /** | ||
| * Call a function on the thread added using Thread.setFunction and return a Promise that resolves to the value returned by that function. | ||
| * If no function is associated with functionId or the function throws an error then the Promise will be rejected. | ||
| * @param functionId An identifier that maps to a function. | ||
| * @param options An object containing the following properties: | ||
| * If no function is associated with id or the function throws an error then the Promise will be rejected. | ||
| * | ||
| * args: An array of arguments that will be passed to the function. If an argument is not compatible with the HTML structured clone algorithm the Promise will be rejected. | ||
| * @param id An identifier that maps to a function. | ||
| * @param args: An array of arguments that will be passed to the function. If an argument is not compatible with the HTML structured clone algorithm the Promise will be rejected. | ||
| * @param transfer: An array of objects to transfer to the thread. If an object is not transferable the Promise will be rejected. | ||
| * @param signal: An abortSignal that may be used to reject the Promise. | ||
| * | ||
| * transfer: An array of objects to transfer to the thread. If an object is not transferable the Promise will be rejected. | ||
| * | ||
| * signal: An abortSignal that may be used to reject the Promise. | ||
| * | ||
| * @throws {TypeError} if this is not a Thread instance. | ||
| * @throws {TypeError} if the Thread is closed. | ||
| * @throws {TypeError} if functionId can not be converted to a string. | ||
| * @throws {TypeError} if options is not an object. | ||
| * @throws {TypeError} if options.args is not an array. | ||
| * @throws {TypeError} if options.transfer is not an array. | ||
| * @throws {TypeError} if options.signal is not an AbortSignal. | ||
| * @throws {Error} if the Thread is closed. | ||
| * @throws {TypeError} if args is defined but not an array. | ||
| * @throws {TypeError} if transfer is defined but not an array. | ||
| * @throws {TypeError} if signal is defined but not an AbortSignal. | ||
| */ | ||
| call(functionId: any, options?: CallOptions): Promise<any>; | ||
| invoke(id: any, args?: any[], transfer?: (Transferable | NodeJSTransferable)[], signal?: AbortSignal): Promise<unknown>; | ||
| /** | ||
| * Close this thread. | ||
| * | ||
| * @throws {TypeError} if this is not a Thread instance. | ||
@@ -239,3 +233,3 @@ * */ | ||
| /** Thread cleanup */ | ||
| export declare const destructThreadPrivateData: (threadData: ThreadPrivateInstanceData, exitCode?: number) => void; | ||
| export declare const disconnectThread: (threadData: ThreadPrivate, exitCode?: number) => void; | ||
| export {}; |
+10
-6
| { | ||
| "name": "@dandre3000/thread", | ||
| "version": "0.1.1", | ||
| "version": "0.2.1", | ||
| "license": "MIT", | ||
@@ -49,10 +49,14 @@ "author": { | ||
| "build": "bun run build-node && bun run build-browser", | ||
| "prepack": "bun run build" | ||
| "test-node": "node --test ./tests/node.test.js", | ||
| "test-bun": "bun test ./tests/bun.node.test.js && bun test ./tests/bun.browser.test.js", | ||
| "test-deno": "deno test ./tests/deno.node.test.js ./tests/deno.browser.test.js --no-check --allow-read", | ||
| "test": "bun run test-node && bun run test-bun && bun run test-deno", | ||
| "prepack": "bun run build && bun run test" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/bun": "^1.3.1", | ||
| "@types/bun": "^1.3.5", | ||
| "@types/deno": "^2.5.0", | ||
| "@types/node": "^24.9.1", | ||
| "typescript": "^5.9.3", | ||
| "vite": "^7.1.12" | ||
| "@types/node": "^24.10.4", | ||
| "expect": "^30.2.0", | ||
| "typescript": "^5.9.3" | ||
| }, | ||
@@ -59,0 +63,0 @@ "dependencies": { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
43271
1.02%1
Infinity%