import { Worker } from "worker_threads"; import { safeRun } from "../util"; // @ts-ignore import workerCode from "bundle-text:./node_worker.ts"; import { Sandbox } from "../sandbox"; import { WorkerLike } from "./worker"; import { Plug } from "../plug"; import path from "path"; import fs from "fs"; class NodeWorkerWrapper implements WorkerLike { onMessage?: (message: any) => Promise; private worker: Worker; ready: Promise; constructor(worker: Worker) { this.worker = worker; worker.on("message", (message: any) => { safeRun(async () => { await this.onMessage!(message); }); }); this.ready = new Promise((resolve) => { worker.once("online", resolve); }); } postMessage(message: any): void { this.worker.postMessage(message); } terminate(): void { this.worker.terminate(); } } // Look for the node_modules directory, to be passed to the worker to find e.g. the vm2 module let nodeModulesDir = __dirname; while (!fs.existsSync(nodeModulesDir + "/node_modules")) { nodeModulesDir = path.dirname(nodeModulesDir); } export function createSandbox(plug: Plug) { let worker = new Worker(workerCode, { eval: true, workerData: path.join(nodeModulesDir, "node_modules"), }); return new Sandbox(plug, new NodeWorkerWrapper(worker)); }