1
0
Fork 0
mirror of synced 2024-10-05 12:34:50 +13:00

Replace ivm.module for script

This commit is contained in:
Adria Navarro 2024-02-13 14:13:09 +01:00
parent 7e43fff018
commit 53d4fc2fa0
3 changed files with 3592 additions and 68 deletions

File diff suppressed because one or more lines are too long

View file

@ -2,9 +2,8 @@ const {
getJsHelperList, getJsHelperList,
} = require("../../../../string-templates/src/helpers/list.js") } = require("../../../../string-templates/src/helpers/list.js")
const helpers = getJsHelperList() export const helpers = {
export default { ...getJsHelperList(),
...helpers,
// pointing stripProtocol to a unexisting function to be able to declare it on isolated-vm // pointing stripProtocol to a unexisting function to be able to declare it on isolated-vm
// @ts-ignore // @ts-ignore
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef

View file

@ -16,31 +16,14 @@ class ExecutionTimeoutError extends Error {
} }
class ModuleHandler { class ModuleHandler {
private modules: { private modules: string[] = []
import: string
moduleKey: string
module: ivm.Module
}[] = []
private generateRandomKey = () => `i${crypto.randomUUID().replace(/-/g, "")}` registerModule(code: string) {
this.modules.push(code)
registerModule(module: ivm.Module, imports: string) {
this.modules.push({
moduleKey: this.generateRandomKey(),
import: imports,
module: module,
})
} }
generateImports() { generateImports() {
return this.modules return this.modules.join(";")
.map(m => `import ${m.import} from "${m.moduleKey}"`)
.join(";")
}
getModule(key: string) {
const module = this.modules.find(m => m.moduleKey === key)
return module?.module
} }
} }
@ -98,34 +81,39 @@ export class IsolatedVM implements VM {
}), }),
}) })
const cryptoModule = this.registerCallbacks({
randomUUID: crypto.randomUUID,
})
const injectedRequire = `const require=function req(val) { const injectedRequire = `const require=function req(val) {
switch (val) { switch (val) {
case "url": return ${urlModule}; case "url": return ${urlModule};
case "querystring": return ${querystringModule}; case "querystring": return ${querystringModule};
case "crypto": return ${cryptoModule};
} }
}` }`
const helpersSource = loadBundle(BundleType.HELPERS) const helpersSource = loadBundle(BundleType.HELPERS)
const helpersModule = this.isolate.compileModuleSync( // const helpersModule = this.isolate.compileModuleSync(
`${injectedRequire};${helpersSource}` // `${injectedRequire};${helpersSource}`
) // )
helpersModule.instantiateSync(this.vm, specifier => { // helpersModule.instantiateSync(this.vm, specifier => {
if (specifier === "crypto") { // if (specifier === "crypto") {
const cryptoModule = this.registerCallbacks({ // const cryptoModule = this.registerCallbacks({
randomUUID: crypto.randomUUID, // randomUUID: crypto.randomUUID,
}) // })
const module = this.isolate.compileModuleSync( // const module = this.isolate.compileModuleSync(
`export default ${cryptoModule}` // `export default ${cryptoModule}`
) // )
module.instantiateSync(this.vm, specifier => { // module.instantiateSync(this.vm, specifier => {
throw new Error(`No imports allowed. Required: ${specifier}`) // throw new Error(`No imports allowed. Required: ${specifier}`)
}) // })
return module // return module
} // }
throw new Error(`No imports allowed. Required: ${specifier}`) // throw new Error(`No imports allowed. Required: ${specifier}`)
}) // })
this.moduleHandler.registerModule(helpersModule, "helpers") this.moduleHandler.registerModule(`${injectedRequire};${helpersSource}`)
return this return this
} }
@ -191,7 +179,11 @@ export class IsolatedVM implements VM {
throw new Error(`No imports allowed. Required: ${specifier}`) throw new Error(`No imports allowed. Required: ${specifier}`)
}) })
this.moduleHandler.registerModule(bsonModule, "{deserialize, toJson}") this.moduleHandler.registerModule(
bsonModule,
"{deserialize, toJson}",
"bson"
)
return this return this
} }
@ -206,25 +198,13 @@ export class IsolatedVM implements VM {
} }
} }
code = `${this.moduleHandler.generateImports()};results.out=${this.codeWrapper( code = `${this.moduleHandler.generateImports()};${this.codeWrapper(code)};`
code
)};`
const script = this.isolate.compileModuleSync(code) const script = this.isolate.compileScriptSync(code)
script.instantiateSync(this.vm, specifier => { const result = script.runSync(this.vm, { timeout: this.invocationTimeout })
const module = this.moduleHandler.getModule(specifier)
if (module) {
return module
}
throw new Error(`"${specifier}" import not allowed`) return result
})
script.evaluateSync({ timeout: this.invocationTimeout })
const result = this.getFromContext(this.resultKey)
return result.out
} }
private registerCallbacks(functions: Record<string, any>) { private registerCallbacks(functions: Record<string, any>) {
@ -260,11 +240,4 @@ export class IsolatedVM implements VM {
) )
} }
} }
private getFromContext(key: string) {
const ref = this.vm.global.getSync(key, { reference: true })
const result = ref.copySync()
ref.release()
return result
}
} }