multithreading
Version:
The missing standard library for multithreading in JavaScript (Works in the browser, Node.js, Deno, Bun).
61 lines (60 loc) • 2.02 kB
JavaScript
import { Transferable } from "./transferable.js";
export const toSerialized = Symbol("Thread.Serialize");
export const toDeserialized = Symbol("Thread.Deserialize");
export class Serializable {
static [toDeserialized](_obj) {
throw new Error(`[toDeserialized] not implemented for ${this.name}`);
}
}
const classRegistry = new Map();
const reverseClassRegistry = new Map();
export function register(typeId, cls) {
classRegistry.set(typeId, cls);
reverseClassRegistry.set(cls, typeId);
}
export function serialize(arg) {
// Null/Undefined
if (arg === null || arg === undefined) {
return [[0 /* PayloadType.RAW */, arg], []];
}
// Library Object (Instance of Serializable)
if (typeof arg === "object" && arg !== null &&
typeof arg[toSerialized] === "function") {
const [value, transfer, typeId] = arg[toSerialized]();
const Ctor = arg.constructor;
return [[
1 /* PayloadType.LIB */,
value,
typeId ?? reverseClassRegistry.get(Ctor),
], transfer ?? []];
}
// Transferables / Raw Data
const transfer = [];
if (arg instanceof SharedArrayBuffer) {
// No-op
}
else if (ArrayBuffer.isView(arg)) {
if (!(arg.buffer instanceof SharedArrayBuffer)) {
transfer.push(arg.buffer);
}
}
else if (arg instanceof Transferable) {
transfer.push(arg);
}
return [[0 /* PayloadType.RAW */, arg], transfer];
}
export function deserialize(envelope) {
if (!envelope || typeof envelope !== "object")
return envelope;
if (envelope[0] === 0 /* PayloadType.RAW */) {
return envelope[1];
}
if (envelope[0] === 1 /* PayloadType.LIB */) {
const Cls = classRegistry.get(envelope[2]);
if (Cls) {
return Cls[toDeserialized](envelope[1]);
}
throw new Error(`Unknown TypeID ${envelope[2]}. Did you forget to import the class?`);
}
return envelope;
}