1
0
silverbullet/packages/plugos/environments/sandbox_worker.ts

127 lines
3.3 KiB
TypeScript
Raw Normal View History

2022-04-05 15:02:17 +00:00
import { safeRun } from "../util";
2022-05-09 12:59:12 +00:00
import { ConsoleLogger } from "./custom_logger";
2022-04-05 15:02:17 +00:00
import { ControllerMessage, WorkerMessage } from "./worker";
let loadedFunctions = new Map<string, Function>();
let pendingRequests = new Map<
number,
{
resolve: (result: unknown) => void;
reject: (e: any) => void;
}
>();
2022-04-04 13:25:07 +00:00
function workerPostMessage(msg: ControllerMessage) {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(msg, "*");
} else {
self.postMessage(msg);
}
}
2022-03-24 09:48:56 +00:00
declare global {
function syscall(name: string, ...args: any[]): Promise<any>;
// function require(moduleName: string): any;
2022-03-24 09:48:56 +00:00
}
let syscallReqId = 0;
self.syscall = async (name: string, ...args: any[]) => {
return await new Promise((resolve, reject) => {
2022-03-24 09:48:56 +00:00
syscallReqId++;
pendingRequests.set(syscallReqId, { resolve, reject });
2022-04-04 13:25:07 +00:00
workerPostMessage({
type: "syscall",
id: syscallReqId,
name,
args,
});
});
};
2022-05-13 12:36:26 +00:00
let loadedModules = new Map<string, any>();
// @ts-ignore
self.require = (moduleName: string): any => {
2022-05-13 12:36:26 +00:00
// console.log("Loading", moduleName, loadedModules.get(moduleName));
return loadedModules.get(moduleName);
};
2022-05-09 12:59:12 +00:00
// @ts-ignore
self.console = new ConsoleLogger((level, message) => {
workerPostMessage({ type: "log", level, message });
}, false);
2022-04-01 13:02:35 +00:00
function wrapScript(code: string) {
return `return (${code})["default"]`;
}
self.addEventListener("message", (event: { data: WorkerMessage }) => {
safeRun(async () => {
2022-03-29 10:13:46 +00:00
let data = event.data;
switch (data.type) {
case "load":
2022-04-01 13:02:35 +00:00
let fn2 = new Function(wrapScript(data.code!));
loadedFunctions.set(data.name!, fn2());
2022-04-04 13:25:07 +00:00
workerPostMessage({
type: "inited",
name: data.name,
});
break;
2022-05-13 12:36:26 +00:00
case "load-dependency":
// console.log("Received dep", data.name);
let fn3 = new Function(`return ${data.code!}`);
let v = fn3();
loadedModules.set(data.name!, v);
// console.log("Dep val", v);
workerPostMessage({
type: "dependency-inited",
name: data.name,
});
break;
case "invoke":
let fn = loadedFunctions.get(data.name!);
if (!fn) {
throw new Error(`Function not loaded: ${data.name}`);
}
try {
let result = await Promise.resolve(fn(...(data.args || [])));
2022-04-04 13:25:07 +00:00
workerPostMessage({
type: "result",
id: data.id,
result: result,
} as ControllerMessage);
} catch (e: any) {
2022-04-04 13:25:07 +00:00
workerPostMessage({
type: "result",
id: data.id,
error: e.message,
});
2022-05-11 09:49:27 +00:00
console.error("Error invoking function", data.name, e.message);
// throw e;
}
break;
case "syscall-response":
let syscallId = data.id!;
const lookup = pendingRequests.get(syscallId);
if (!lookup) {
console.log(
"Current outstanding requests",
pendingRequests,
"looking up",
syscallId
);
throw Error("Invalid request id");
}
pendingRequests.delete(syscallId);
if (data.error) {
lookup.reject(new Error(data.error));
} else {
lookup.resolve(data.result);
}
break;
}
});
});