Lots of tweaks
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
export type LogLevel = "info" | "warn" | "error" | "log";
|
||||
|
||||
export class ConsoleLogger {
|
||||
print: boolean;
|
||||
callback: (level: LogLevel, entry: string) => void;
|
||||
|
||||
constructor(
|
||||
callback: (level: LogLevel, entry: string) => void,
|
||||
print: boolean = true
|
||||
) {
|
||||
this.print = print;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
log(...args: any[]): void {
|
||||
this.push("log", args);
|
||||
}
|
||||
|
||||
warn(...args: any[]): void {
|
||||
this.push("warn", args);
|
||||
}
|
||||
|
||||
error(...args: any[]): void {
|
||||
this.push("error", args);
|
||||
}
|
||||
|
||||
info(...args: any[]): void {
|
||||
this.push("info", args);
|
||||
}
|
||||
|
||||
push(level: LogLevel, args: any[]) {
|
||||
this.callback(level, this.logMessage(args));
|
||||
if (this.print) {
|
||||
console[level](...args);
|
||||
}
|
||||
}
|
||||
|
||||
logMessage(values: any[]): string {
|
||||
let pieces: string[] = [];
|
||||
for (let val of values) {
|
||||
switch (typeof val) {
|
||||
case "string":
|
||||
case "number":
|
||||
pieces.push("" + val);
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
let s = JSON.stringify(val, null, 2);
|
||||
if (s.length > 500) {
|
||||
s = s.substring(0, 500) + "...";
|
||||
}
|
||||
pieces.push(s);
|
||||
} catch {
|
||||
// May be cyclical reference
|
||||
pieces.push("[circular object]");
|
||||
}
|
||||
}
|
||||
}
|
||||
return pieces.join(" ");
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ConsoleLogger } from "./custom_logger";
|
||||
|
||||
const {
|
||||
parentPort,
|
||||
workerData: { preloadedModules, nodeModulesPath },
|
||||
@@ -16,10 +18,18 @@ let pendingRequests = new Map<
|
||||
|
||||
let syscallReqId = 0;
|
||||
|
||||
let consoleLogger = new ConsoleLogger((level, message) => {
|
||||
parentPort.postMessage({
|
||||
type: "log",
|
||||
level,
|
||||
message,
|
||||
});
|
||||
}, false);
|
||||
|
||||
let vm = new VM({
|
||||
sandbox: {
|
||||
// Exposing some "safe" APIs
|
||||
console,
|
||||
console: consoleLogger,
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
setInterval,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { safeRun } from "../util";
|
||||
import { ConsoleLogger } from "./custom_logger";
|
||||
import { ControllerMessage, WorkerMessage } from "./worker";
|
||||
|
||||
let loadedFunctions = new Map<string, Function>();
|
||||
@@ -53,6 +54,11 @@ self.require = (moduleName: string): any => {
|
||||
return preloadedModules[moduleName];
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
self.console = new ConsoleLogger((level, message) => {
|
||||
workerPostMessage({ type: "log", level, message });
|
||||
}, false);
|
||||
|
||||
function wrapScript(code: string) {
|
||||
return `return (${code})["default"]`;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
export type ControllerMessageType = "inited" | "result" | "syscall";
|
||||
import type { LogLevel } from "./custom_logger";
|
||||
|
||||
export type ControllerMessageType = "inited" | "result" | "syscall" | "log";
|
||||
export type ControllerMessage = {
|
||||
type: ControllerMessageType;
|
||||
id?: number;
|
||||
name?: string;
|
||||
args?: any[];
|
||||
error?: string;
|
||||
level?: LogLevel;
|
||||
message?: string;
|
||||
result?: any;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import { ControllerMessage, WorkerLike, WorkerMessage } from "./environments/worker";
|
||||
import type { LogLevel } from "./environments/custom_logger";
|
||||
import {
|
||||
ControllerMessage,
|
||||
WorkerLike,
|
||||
WorkerMessage,
|
||||
} from "./environments/worker";
|
||||
import { Plug } from "./plug";
|
||||
|
||||
export type SandboxFactory<HookT> = (plug: Plug<HookT>) => Sandbox;
|
||||
|
||||
export type LogEntry = {
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
date: number;
|
||||
};
|
||||
|
||||
export class Sandbox {
|
||||
protected worker: WorkerLike;
|
||||
protected reqId = 0;
|
||||
@@ -13,6 +24,8 @@ export class Sandbox {
|
||||
>();
|
||||
protected loadedFunctions = new Set<string>();
|
||||
protected plug: Plug<any>;
|
||||
public logBuffer: LogEntry[] = [];
|
||||
public maxLogBufferSize = 100;
|
||||
|
||||
constructor(plug: Plug<any>, worker: WorkerLike) {
|
||||
worker.onMessage = this.onMessage.bind(this);
|
||||
@@ -84,6 +97,17 @@ export class Sandbox {
|
||||
resultCbs && resultCbs.resolve(data.result);
|
||||
}
|
||||
break;
|
||||
case "log":
|
||||
this.logBuffer.push({
|
||||
level: data.level!,
|
||||
message: data.message!,
|
||||
date: Date.now(),
|
||||
});
|
||||
if (this.logBuffer.length > this.maxLogBufferSize) {
|
||||
this.logBuffer.shift();
|
||||
}
|
||||
console.log(`[Sandbox ${data.level}]`, data.message);
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown message type", data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { LogEntry } from "../sandbox";
|
||||
import { SysCallMapping, System } from "../system";
|
||||
|
||||
export default function sandboxSyscalls(system: System<any>): SysCallMapping {
|
||||
return {
|
||||
"sandbox.getLogs": async (ctx): Promise<LogEntry[]> => {
|
||||
let allLogs: LogEntry[] = [];
|
||||
for (let plug of system.loadedPlugs.values()) {
|
||||
allLogs = allLogs.concat(plug.sandbox.logBuffer);
|
||||
}
|
||||
allLogs = allLogs.sort((a, b) => a.date - b.date);
|
||||
return allLogs;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user