Fix re-used context in JS runner.
This commit is contained in:
parent
634bf5f8ba
commit
93b18b81e0
|
@ -3,9 +3,10 @@ import { IsolatedVM } from "../../jsRunner/vm"
|
|||
|
||||
export async function execute(ctx: Ctx) {
|
||||
const { script, context } = ctx.request.body
|
||||
const runner = new IsolatedVM().withContext(context)
|
||||
|
||||
const result = runner.execute(`(function(){\n${script}\n})();`)
|
||||
const vm = new IsolatedVM()
|
||||
const result = vm.withContext(context, () =>
|
||||
vm.execute(`(function(){\n${script}\n})();`)
|
||||
)
|
||||
ctx.body = result
|
||||
}
|
||||
|
||||
|
|
|
@ -23,22 +23,17 @@ export function init() {
|
|||
try {
|
||||
const bbCtx = context.getCurrentContext()!
|
||||
|
||||
let { vm } = bbCtx
|
||||
if (!vm) {
|
||||
// Can't copy the native helpers into the isolate. We just ignore them as they are handled properly from the helpersSource
|
||||
const { helpers, ...ctxToPass } = ctx
|
||||
|
||||
vm = new IsolatedVM({
|
||||
if (!bbCtx.vm) {
|
||||
const vm = new IsolatedVM({
|
||||
memoryLimit: env.JS_RUNNER_MEMORY_LIMIT,
|
||||
invocationTimeout: env.JS_PER_INVOCATION_TIMEOUT_MS,
|
||||
isolateAccumulatedTimeout: env.JS_PER_REQUEST_TIMEOUT_MS,
|
||||
})
|
||||
.withContext(ctxToPass)
|
||||
.withHelpers()
|
||||
}).withHelpers()
|
||||
|
||||
bbCtx.vm = vm
|
||||
}
|
||||
return vm.execute(js)
|
||||
const { helpers, ...rest } = ctx
|
||||
return bbCtx.vm.withContext(rest, () => bbCtx.vm!.execute(js))
|
||||
} catch (error: any) {
|
||||
if (error.message === "Script execution timed out.") {
|
||||
throw new JsErrorTimeout()
|
||||
|
|
|
@ -97,10 +97,14 @@ export class IsolatedVM implements VM {
|
|||
return this
|
||||
}
|
||||
|
||||
withContext(context: Record<string, any>) {
|
||||
withContext<T>(context: Record<string, any>, f: () => T) {
|
||||
this.addToContext(context)
|
||||
|
||||
return this
|
||||
try {
|
||||
return f()
|
||||
} finally {
|
||||
this.removeFromContext(Object.keys(context))
|
||||
}
|
||||
}
|
||||
|
||||
withParsingBson(data: any) {
|
||||
|
@ -224,6 +228,12 @@ export class IsolatedVM implements VM {
|
|||
}
|
||||
}
|
||||
|
||||
private removeFromContext(keys: string[]) {
|
||||
for (let key of keys) {
|
||||
this.jail.deleteSync(key)
|
||||
}
|
||||
}
|
||||
|
||||
private getFromContext(key: string) {
|
||||
const ref = this.vm.global.getSync(key, { reference: true })
|
||||
const result = ref.copySync()
|
||||
|
|
|
@ -7,16 +7,26 @@ export class VM2 implements VM {
|
|||
vm: vm2.VM
|
||||
results: { out: string }
|
||||
|
||||
constructor(context: any) {
|
||||
constructor() {
|
||||
this.vm = new vm2.VM({
|
||||
timeout: JS_TIMEOUT_MS,
|
||||
})
|
||||
this.results = { out: "" }
|
||||
this.vm.setGlobals(context)
|
||||
this.vm.setGlobal("fetch", fetch)
|
||||
this.vm.setGlobal("results", this.results)
|
||||
}
|
||||
|
||||
withContext<T>(context: Record<string, any>, fn: () => T): T {
|
||||
this.vm.setGlobals(context)
|
||||
try {
|
||||
return fn()
|
||||
} finally {
|
||||
for (const key in context) {
|
||||
this.vm.setGlobal(key, undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
execute(script: string) {
|
||||
const code = `let fn = () => {\n${script}\n}; results.out = fn();`
|
||||
const vmScript = new vm2.VMScript(code)
|
||||
|
|
|
@ -131,24 +131,21 @@ class QueryRunner {
|
|||
if (transformer) {
|
||||
let runner: VM
|
||||
if (!USE_ISOLATED_VM) {
|
||||
runner = new VM2({
|
||||
data: rows,
|
||||
params: enrichedParameters,
|
||||
})
|
||||
runner = new VM2()
|
||||
} else {
|
||||
transformer = `(function(){\n${transformer}\n})();`
|
||||
let isolatedVm = new IsolatedVM().withContext({
|
||||
data: rows,
|
||||
params: enrichedParameters,
|
||||
})
|
||||
let vm = new IsolatedVM()
|
||||
if (datasource.source === SourceName.MONGODB) {
|
||||
isolatedVm = isolatedVm.withParsingBson(rows)
|
||||
vm = vm.withParsingBson(rows)
|
||||
}
|
||||
|
||||
runner = isolatedVm
|
||||
runner = vm
|
||||
}
|
||||
|
||||
rows = runner.execute(transformer)
|
||||
const ctx = {
|
||||
data: rows,
|
||||
params: enrichedParameters,
|
||||
}
|
||||
rows = runner.withContext(ctx, () => runner.execute(transformer))
|
||||
}
|
||||
|
||||
// if the request fails we retry once, invalidating the cached value
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export interface VM {
|
||||
execute(code: string): any
|
||||
withContext<T>(context: Record<string, any>, fn: () => T): T
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue