@xylabs/threads
Version:
Web workers & worker threads as simple as a function call
162 lines (159 loc) • 5.55 kB
JavaScript
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
// src/master/implementation.node.ts
import { EventEmitter } from "node:events";
import { cpus } from "node:os";
import path from "node:path";
import { cwd } from "node:process";
import { Worker as NativeWorker } from "node:worker_threads";
var defaultPoolSize = cpus().length;
function resolveScriptPath(scriptPath, baseURL) {
const makeAbsolute = (filePath) => {
return path.isAbsolute(filePath) ? filePath : path.join(baseURL ?? cwd(), filePath);
};
const absolutePath = makeAbsolute(scriptPath);
return absolutePath;
}
function initWorkerThreadsWorker() {
let allWorkers = [];
class Worker2 extends NativeWorker {
mappedEventListeners;
constructor(scriptPath, options) {
const resolvedScriptPath = options && options.fromSource ? null : resolveScriptPath(scriptPath, (options ?? {})._baseURL);
if (resolvedScriptPath) {
super(resolvedScriptPath, options);
} else {
const sourceCode = scriptPath;
super(sourceCode, { ...options, eval: true });
}
this.mappedEventListeners = /* @__PURE__ */ new WeakMap();
allWorkers.push(this);
}
addEventListener(eventName, rawListener) {
const listener = (message) => {
rawListener({ data: message });
};
this.mappedEventListeners.set(rawListener, listener);
this.on(eventName, listener);
}
removeEventListener(eventName, rawListener) {
const listener = this.mappedEventListeners.get(rawListener) || rawListener;
this.off(eventName, listener);
}
}
const terminateWorkersAndMaster = () => {
Promise.all(allWorkers.map((worker) => worker.terminate())).then(
() => process.exit(0),
() => process.exit(1)
);
allWorkers = [];
};
process.on("SIGINT", () => terminateWorkersAndMaster());
process.on("SIGTERM", () => terminateWorkersAndMaster());
class BlobWorker2 extends Worker2 {
constructor(blob, options) {
super(Buffer.from(blob).toString("utf-8"), { ...options, fromSource: true });
}
static fromText(source, options) {
return new Worker2(source, { ...options, fromSource: true });
}
}
return {
blob: BlobWorker2,
default: Worker2
};
}
function initTinyWorker() {
const TinyWorker = __require("tiny-worker");
let allWorkers = [];
class Worker2 extends TinyWorker {
emitter;
constructor(scriptPath, options) {
const resolvedScriptPath = options && options.fromSource ? null : process.platform === "win32" ? `file:///${resolveScriptPath(scriptPath).replaceAll("\\", "/")}` : resolveScriptPath(scriptPath);
if (resolvedScriptPath) {
super(resolvedScriptPath, [], { esm: true });
} else {
const sourceCode = scriptPath;
super(new Function(sourceCode), [], { esm: true });
}
allWorkers.push(this);
this.emitter = new EventEmitter();
this.onerror = (error) => this.emitter.emit("error", error);
this.onmessage = (message) => this.emitter.emit("message", message);
}
addEventListener(eventName, listener) {
this.emitter.addListener(eventName, listener);
}
removeEventListener(eventName, listener) {
this.emitter.removeListener(eventName, listener);
}
terminate() {
allWorkers = allWorkers.filter((worker) => worker !== this);
return super.terminate();
}
}
const terminateWorkersAndMaster = () => {
Promise.all(allWorkers.map((worker) => worker.terminate())).then(
() => process.exit(0),
() => process.exit(1)
);
allWorkers = [];
};
process.on("SIGINT", () => terminateWorkersAndMaster());
process.on("SIGTERM", () => terminateWorkersAndMaster());
class BlobWorker2 extends Worker2 {
constructor(blob, options) {
super(Buffer.from(blob).toString("utf-8"), { ...options, fromSource: true });
}
static fromText(source, options) {
return new Worker2(source, { ...options, fromSource: true });
}
}
return {
blob: BlobWorker2,
default: Worker2
};
}
var implementation;
var isTinyWorker;
function selectWorkerImplementation() {
try {
isTinyWorker = false;
return initWorkerThreadsWorker();
} catch (ex) {
console.error(ex);
console.debug("Node worker_threads not available. Trying to fall back to tiny-worker polyfill...");
isTinyWorker = true;
return initTinyWorker();
}
}
function getWorkerImplementation() {
if (!implementation) {
implementation = selectWorkerImplementation();
}
return implementation;
}
function isWorkerRuntime() {
if (isTinyWorker) {
return globalThis !== void 0 && self["postMessage"] ? true : false;
} else {
const isMainThread = typeof __non_webpack_require__ === "function" ? __non_webpack_require__("worker_threads").isMainThread : eval("require")("worker_threads").isMainThread;
return !isMainThread;
}
}
// src/master/index-node.ts
var BlobWorker = getWorkerImplementation().blob;
var Worker = getWorkerImplementation().default;
// src/master/register.ts
if (typeof globalThis !== "undefined") {
;
globalThis.Worker = Worker;
} else if (window !== void 0) {
;
window.Worker = Worker;
}
//# sourceMappingURL=register.mjs.map