Refactoring
parent
09d07d587f
commit
b51730d33f
|
@ -10,6 +10,7 @@ class IFrameWrapper implements WorkerLike {
|
|||
private iframe: HTMLIFrameElement;
|
||||
onMessage?: (message: any) => Promise<void>;
|
||||
ready: Promise<void>;
|
||||
private messageListener: (evt: any) => void;
|
||||
|
||||
constructor() {
|
||||
const iframe = document.createElement("iframe", {});
|
||||
|
@ -18,7 +19,7 @@ class IFrameWrapper implements WorkerLike {
|
|||
// Let's lock this down significantly
|
||||
iframe.setAttribute("sandbox", "allow-scripts");
|
||||
iframe.srcdoc = sandboxHtml;
|
||||
window.addEventListener("message", (evt: any) => {
|
||||
this.messageListener = (evt: any) => {
|
||||
if (evt.source !== iframe.contentWindow) {
|
||||
return;
|
||||
}
|
||||
|
@ -27,7 +28,8 @@ class IFrameWrapper implements WorkerLike {
|
|||
safeRun(async () => {
|
||||
await this.onMessage!(data);
|
||||
});
|
||||
});
|
||||
};
|
||||
window.addEventListener("message", this.messageListener);
|
||||
document.body.appendChild(iframe);
|
||||
this.ready = new Promise((resolve) => {
|
||||
iframe.onload = () => {
|
||||
|
@ -42,6 +44,7 @@ class IFrameWrapper implements WorkerLike {
|
|||
}
|
||||
|
||||
terminate() {
|
||||
window.removeEventListener("message", this.messageListener);
|
||||
return this.iframe.remove();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,16 +10,19 @@ let pendingRequests = new Map<
|
|||
}
|
||||
>();
|
||||
|
||||
let syscallReqId = 0;
|
||||
|
||||
let vm = new VM({
|
||||
sandbox: {
|
||||
console: console,
|
||||
self: {
|
||||
syscall: (reqId: number, name: string, args: any[]) => {
|
||||
syscall: (name: string, ...args: any[]) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
pendingRequests.set(reqId, { resolve, reject });
|
||||
syscallReqId++;
|
||||
pendingRequests.set(syscallReqId, { resolve, reject });
|
||||
parentPort.postMessage({
|
||||
type: "syscall",
|
||||
id: reqId,
|
||||
id: syscallReqId,
|
||||
name,
|
||||
// TODO: Figure out why this is necessary (to avoide a CloneError)
|
||||
args: JSON.parse(JSON.stringify(args)),
|
||||
|
|
|
@ -9,24 +9,26 @@ let pendingRequests = new Map<
|
|||
reject: (e: any) => void;
|
||||
}
|
||||
>();
|
||||
|
||||
declare global {
|
||||
function syscall(id: number, name: string, args: any[]): Promise<any>;
|
||||
}
|
||||
|
||||
let postMessage = self.postMessage.bind(self);
|
||||
|
||||
if (window.parent !== window) {
|
||||
postMessage = window.parent.postMessage.bind(window.parent);
|
||||
}
|
||||
|
||||
self.syscall = async (id: number, name: string, args: any[]) => {
|
||||
declare global {
|
||||
function syscall(name: string, ...args: any[]): Promise<any>;
|
||||
}
|
||||
|
||||
let syscallReqId = 0;
|
||||
|
||||
self.syscall = async (name: string, ...args: any[]) => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
pendingRequests.set(id, { resolve, reject });
|
||||
syscallReqId++;
|
||||
pendingRequests.set(syscallReqId, { resolve, reject });
|
||||
postMessage(
|
||||
{
|
||||
type: "syscall",
|
||||
id,
|
||||
id: syscallReqId,
|
||||
name,
|
||||
args,
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ export interface WorkerLike {
|
|||
}
|
||||
|
||||
export type WorkerMessageType = "load" | "invoke" | "syscall-response";
|
||||
|
||||
export type WorkerMessage = {
|
||||
type: WorkerMessageType;
|
||||
id?: number;
|
||||
|
|
|
@ -29,7 +29,7 @@ test("Run a Node sandbox", async () => {
|
|||
code: `(() => {
|
||||
return {
|
||||
default: async (a, b) => {
|
||||
return await self.syscall(1, "addNumbers", [a, b]);
|
||||
return await self.syscall("addNumbers", a, b);
|
||||
}
|
||||
};
|
||||
})()`,
|
||||
|
@ -47,7 +47,7 @@ test("Run a Node sandbox", async () => {
|
|||
code: `(() => {
|
||||
return {
|
||||
default: async () => {
|
||||
await self.syscall(2, "failingSyscall", []);
|
||||
await self.syscall("failingSyscall");
|
||||
}
|
||||
};
|
||||
})()`,
|
||||
|
|
|
@ -3,11 +3,12 @@ import { EventEmitter } from "../common/event";
|
|||
import { Sandbox } from "./sandbox";
|
||||
import { Plug } from "./plug";
|
||||
|
||||
interface SysCallMapping {
|
||||
export interface SysCallMapping {
|
||||
[key: string]: (...args: any) => Promise<any> | any;
|
||||
}
|
||||
|
||||
export type SystemJSON<HookT> = { [key: string]: Manifest<HookT> };
|
||||
|
||||
export type SystemEvents<HookT> = {
|
||||
plugLoaded: (name: string, plug: Plug<HookT>) => void;
|
||||
plugUnloaded: (name: string, plug: Plug<HookT>) => void;
|
||||
|
@ -32,13 +33,13 @@ export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
|
|||
|
||||
registerSyscalls(...registrationObjects: SysCallMapping[]) {
|
||||
for (const registrationObject of registrationObjects) {
|
||||
for (let p in registrationObject) {
|
||||
this.registeredSyscalls[p] = registrationObject[p];
|
||||
for (let [name, def] of Object.entries(registrationObject)) {
|
||||
this.registeredSyscalls[name] = def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async syscall(name: string, args: Array<any>): Promise<any> {
|
||||
async syscall(name: string, args: any[]): Promise<any> {
|
||||
const callback = this.registeredSyscalls[name];
|
||||
if (!name) {
|
||||
throw Error(`Unregistered syscall ${name}`);
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
declare global {
|
||||
function syscall(id: number, name: string, args: any[]): Promise<any>;
|
||||
var reqId: number;
|
||||
function syscall(name: string, ...args: any[]): Promise<any>;
|
||||
}
|
||||
|
||||
// This needs to be global, because this will be shared with all other functions in the same environment (worker-like)
|
||||
if (typeof self.reqId === "undefined") {
|
||||
self.reqId = 0;
|
||||
}
|
||||
|
||||
export async function syscall(name: string, ...args: any[]): Promise<any> {
|
||||
self.reqId++;
|
||||
// console.log("Syscall", name, reqId);
|
||||
return await self.syscall(self.reqId, name, args);
|
||||
}
|
||||
export const syscall = self.syscall;
|
||||
|
|
|
@ -54,9 +54,9 @@ export class PageApi implements ApiProvider {
|
|||
broadcastCursors(page: Page) {
|
||||
page.clientStates.forEach((client) => {
|
||||
client.socket.emit(
|
||||
"cursorSnapshot",
|
||||
page.name,
|
||||
Object.fromEntries(page.cursors.entries())
|
||||
"cursorSnapshot",
|
||||
page.name,
|
||||
Object.fromEntries(page.cursors.entries())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue