import {Thread, type ThreadOptions} from '../Thread.ts'; import {portToMessageTarget} from './ThreadMessagePort.ts'; /** * Creates a thread from a web worker. This function can be used either from a JavaScript * environment that *created* a web worker, or from within a web worker that has been * created. * * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers * * @example * import {ThreadWebWorker} from '@quilted/threads'; * * // If inside a web worker: * const thread = new ThreadWebWorker(self, { * exports: { * async sendMessage(message) { * console.log(message); * }, * }, * }); * * // If in an environment that creates a worker: * const worker = new Worker('worker.js'); * const thread = new ThreadWebWorker(worker); * * await thread.imports.sendMessage('Hello world!'); */ export class ThreadWebWorker< Imports = Record, Exports = Record, > extends Thread { readonly worker: Worker; static from, Exports = Record>( worker: Worker, options?: ThreadOptions, ) { return new ThreadWebWorker(worker, options); } /** * Starts a thread wrapped around a `Worker` object, and returns the imports * of the thread. * * @example * ```ts * import {ThreadWebWorker} from '@quilted/threads'; * * // On the main thread: * const worker = new Worker('worker.js'); * const {getMessage} = ThreadWebWorker.import(worker); * const message = await getMessage(); // 'Hello, world!' * * // Inside a web worker: * * import {ThreadWebWorker} from '@quilted/threads'; * * ThreadWebWorker.export(self, { * async getMessage() { * return 'Hello, world!'; * }, * }); * ``` */ static import>( worker: Worker, options?: Omit>, 'exports'>, ) { return new ThreadWebWorker(worker, options).imports; } /** * Starts a thread wrapped around a `Worker` object, providing the second * argument as the exports of the thread. * * @example * ```ts * import {ThreadWebWorker} from '@quilted/threads'; * * // Inside a web worker: * ThreadWebWorker.export(self, { * async getMessage() { * return 'Hello, world!'; * }, * }); * * // On the main thread: * * import {ThreadWebWorker} from '@quilted/threads'; * * const worker = new Worker('worker.js'); * const {getMessage} = ThreadWebWorker.import(worker); * const message = await getMessage(); // 'Hello, world!' * ``` */ static export>( worker: Worker, exports: Exports, options?: Omit< ThreadOptions, Exports>, 'exports' | 'imports' >, ) { new ThreadWebWorker(worker, {...options, exports}); } static self = Object.assign( , Exports = Record>( options?: ThreadOptions, ) => ThreadWebWorker.from(selfAsWorker(), options), { import: >( options?: Omit< ThreadOptions>, 'exports' >, ) => ThreadWebWorker.import(selfAsWorker(), options), export: >( exports: Exports, options?: Omit< ThreadOptions, Exports>, 'exports' | 'imports' >, ) => ThreadWebWorker.export(selfAsWorker(), exports, options), }, ); constructor(worker: Worker, options?: ThreadOptions) { super(portToMessageTarget(worker), options); this.worker = worker; } } function selfAsWorker() { if (typeof self === 'undefined') { throw new Error('You are not inside a web worker.'); } return self as unknown as Worker; }