1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| const globalConsole = global.console
const sandboxConsole = (level: string, msg: any, ...args: any[]) => { console.result += `${new Date().toLocaleString()} ${level}:\n${msg}` args.forEach(item => { if (typeof item !== 'object') { console.result += ` ${item}` } else { console.result += ` ${JSON.stringify(item)}` } }) console.result += '\n\n' }
const console: { result: string, log: Function, warn: Function, error: Function } = { result: '', log: (msg: any, ...args: any[]) => { globalConsole.log('Sandbox console', msg, ...args) sandboxConsole('debug', msg, ...args) } }
export default async function executeCodeInSandbox(sandbox: any, code?: string) { if (!code || code.trim().length === 0) { throw Error('Nothing executed.') }
const slices = code.trim().split(/\r?\n/) .map((l: string, i: number) => { return l.trimEnd() }) .filter((l: string, i: number) => { return /^[A-Za-z0-9{}(&|]/.test(l.trimStart()) }) if (slices.length == 0) { throw Error('Nothing executed.') } else if (slices.length == 1) { code = slices[0] } else { code = slices.reduce((p: string, c: string, i: number, a: string[]) => { return `${p}\n ${c}` }) }
let wrapCode = `globalConsole.log('VM exec in process:', process.pid, process.title) try { console.result = '' await connectDBAsync() ${code} await disconnectDBAsync() inject(console.result) } catch (e) { inject(e) }`
console.log(wrapCode);
await (async (code: string) => { return new Promise((resolve) => { const script: Script = new vm.Script(`(async()=>{${code}})()`) const options: RunningScriptOptions = { timeout: 1000, displayErrors: true, } const context: Context = vm.createContext({ ...sandbox, console, globalConsole, process, connectDBAsync, disconnectDBAsync, inject: (result: any) => { sandbox.result = result resolve(result) } }) script.runInContext(context, options) }) })(wrapCode)
return sandbox.result }
|