import { PromiseQueue } from "$sb/lib/async.ts"; import { Plug } from "../plug.ts"; import { Sandbox } from "./sandbox.ts"; import { Manifest } from "../types.ts"; // We need to hard inject the syscall function into the global scope declare global { interface globalThis { syscall(name: string, ...args: any[]): Promise; } } export type PlugExport = { manifest: Manifest; functionMapping: Record; }; const functionQueue = new PromiseQueue(); let activePlug: Plug | undefined; // @ts-ignore: globalThis globalThis.syscall = (name: string, ...args: any[]): Promise => { if (!activePlug) { throw new Error("No active plug"); } console.log("Calling syscall", name, args); return activePlug.syscall(name, args); }; export class NoSandbox implements Sandbox { manifest?: Manifest | undefined; constructor( private plug: Plug, private plugExport: PlugExport, ) { this.manifest = plugExport.manifest; plug.manifest = this.manifest; } init(): Promise { return Promise.resolve(); } invoke(name: string, args: any[]): Promise { activePlug = this.plug; return functionQueue.runInQueue(async () => { try { const fn = this.plugExport.functionMapping[name]; if (!fn) { throw new Error(`Function not loaded: ${name}`); } return await fn(...args); } finally { activePlug = undefined; } }); } stop() { } } export function noSandboxFactory( plugExport: PlugExport, ): (plug: Plug) => Sandbox { return (plug: Plug) => new NoSandbox(plug, plugExport); }