1
0
Fork 0
mirror of synced 2024-07-30 18:46:00 +12:00
This commit is contained in:
Adria Navarro 2024-02-06 17:15:40 +01:00
parent 1ee20b0464
commit e2a1d8c880

View file

@ -13,25 +13,24 @@ class ScriptRunner {
this.vm = new IsolatedVM({ this.vm = new IsolatedVM({
memoryLimit: env.JS_RUNNER_MEMORY_LIMIT, memoryLimit: env.JS_RUNNER_MEMORY_LIMIT,
parseBson, parseBson,
context: {
...context,
data: parseBson
? bson.BSON.serialize({ data: context.data })
: context.data,
},
}) })
this.vm.context = {
...context,
data: parseBson
? bson.BSON.serialize({ data: context.data })
: context.data,
results: { out: "" },
}
if (parseBson) { if (parseBson) {
script = `return JSON.parse(JSON.stringify((function(){data=deserialize(data).data;${script}})()));` script = `return JSON.parse(JSON.stringify((function(){data=deserialize(data).data;${script}})()));`
} }
const code = `const fn=function(){${script}};cb(fn());` this.vm.code = script
this.vm.code = code
} }
execute() { execute() {
const result = this.vm.runScript() this.vm.runScript()
const result = this.vm.getResult()
return result return result
} }
} }
@ -43,18 +42,27 @@ class IsolatedVM {
#script: ivm.Module = undefined! #script: ivm.Module = undefined!
#bsonModule?: ivm.Module #bsonModule?: ivm.Module
readonly #resultKey = "results"
constructor({ constructor({
memoryLimit, memoryLimit,
parseBson, parseBson,
context,
}: { }: {
memoryLimit: number memoryLimit: number
parseBson: boolean parseBson: boolean
context: Record<string, any>
}) { }) {
this.#isolate = new ivm.Isolate({ memoryLimit }) this.#isolate = new ivm.Isolate({ memoryLimit })
this.#vm = this.#isolate.createContextSync() this.#vm = this.#isolate.createContextSync()
this.#jail = this.#vm.global this.#jail = this.#vm.global
this.#jail.setSync("global", this.#jail.derefInto()) this.#jail.setSync("global", this.#jail.derefInto())
this.#addToContext(context)
this.#addToContext({
[this.#resultKey]: { out: "" },
})
if (parseBson) { if (parseBson) {
const bsonSource = loadBundle(BundleType.BSON) const bsonSource = loadBundle(BundleType.BSON)
this.#bsonModule = this.#isolate.compileModuleSync(bsonSource) this.#bsonModule = this.#isolate.compileModuleSync(bsonSource)
@ -64,27 +72,28 @@ class IsolatedVM {
} }
} }
getValue(key: string) { getResult() {
const ref = this.#vm.global.getSync(key, { reference: true }) const ref = this.#vm.global.getSync(this.#resultKey, { reference: true })
const result = ref.copySync() const result = ref.copySync()
ref.release() ref.release()
return result return result.out
} }
set context(context: Record<string, any>) { #addToContext(context: Record<string, any>) {
for (let key in context) { for (let key in context) {
this.#jail.setSync(key, this.copyRefToVm(context[key])) this.#jail.setSync(key, this.#copyRefToVm(context[key]))
} }
} }
set code(code: string) { set code(code: string) {
code = `const fn=function(){${code}};results.out=fn();`
if (this.#bsonModule) { if (this.#bsonModule) {
code = `import {deserialize} from "compiled_module";${code}` code = `import {deserialize} from "compiled_module";${code}`
} }
this.#script = this.#isolate.compileModuleSync(code) this.#script = this.#isolate.compileModuleSync(code)
} }
runScript() { runScript(): void {
if (this.#bsonModule) { if (this.#bsonModule) {
this.#script.instantiateSync(this.#vm, specifier => { this.#script.instantiateSync(this.#vm, specifier => {
if (specifier === "compiled_module") { if (specifier === "compiled_module") {
@ -95,20 +104,10 @@ class IsolatedVM {
}) })
} }
let result
this.#vm.global.setSync(
"cb",
new ivm.Callback((value: any) => {
result = value
})
)
this.#script.evaluateSync({ timeout: JS_TIMEOUT_MS }) this.#script.evaluateSync({ timeout: JS_TIMEOUT_MS })
return result
} }
copyRefToVm(value: Object): ivm.Copy<Object> { #copyRefToVm(value: Object): ivm.Copy<Object> {
return new ivm.ExternalCopy(value).copyInto({ release: true }) return new ivm.ExternalCopy(value).copyInto({ release: true })
} }
} }