Keep isolateRefs in context
This commit is contained in:
parent
d7b5aa08db
commit
bc7825dc93
|
@ -1,5 +1,5 @@
|
||||||
import { IdentityContext } from "@budibase/types"
|
import { IdentityContext } from "@budibase/types"
|
||||||
import { Isolate, Context } from "isolated-vm"
|
import { Isolate, Context, Module } from "isolated-vm"
|
||||||
|
|
||||||
// keep this out of Budibase types, don't want to expose context info
|
// keep this out of Budibase types, don't want to expose context info
|
||||||
export type ContextMap = {
|
export type ContextMap = {
|
||||||
|
@ -10,6 +10,9 @@ export type ContextMap = {
|
||||||
isScim?: boolean
|
isScim?: boolean
|
||||||
automationId?: string
|
automationId?: string
|
||||||
isMigrating?: boolean
|
isMigrating?: boolean
|
||||||
jsIsolate?: Isolate
|
isolateRefs?: {
|
||||||
jsContext?: Context
|
jsIsolate: Isolate
|
||||||
|
jsContext: Context
|
||||||
|
helpersModule: Module
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,22 @@ import fs from "fs"
|
||||||
import url from "url"
|
import url from "url"
|
||||||
import crypto from "crypto"
|
import crypto from "crypto"
|
||||||
|
|
||||||
|
const helpersSource = fs.readFileSync(
|
||||||
|
`${require.resolve("@budibase/string-templates/index-helpers")}`,
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
|
||||||
export function init() {
|
export function init() {
|
||||||
const helpersSource = fs.readFileSync(
|
|
||||||
`${require.resolve("@budibase/string-templates/index-helpers")}`,
|
|
||||||
"utf8"
|
|
||||||
)
|
|
||||||
setJSRunner((js: string, ctx: Record<string, any>) => {
|
setJSRunner((js: string, ctx: Record<string, any>) => {
|
||||||
return tracer.trace("runJS", {}, span => {
|
return tracer.trace("runJS", {}, span => {
|
||||||
const bbCtx = context.getCurrentContext() || {}
|
const bbCtx = context.getCurrentContext()!
|
||||||
let { jsIsolate = new ivm.Isolate({ memoryLimit: 64 }) } = bbCtx
|
|
||||||
let { jsContext = jsIsolate.createContextSync() } = bbCtx
|
|
||||||
|
|
||||||
const injectedRequire = `const require = function(val){
|
const isolateRefs = bbCtx.isolateRefs
|
||||||
|
if (!isolateRefs) {
|
||||||
|
const jsIsolate = new ivm.Isolate({ memoryLimit: 64 })
|
||||||
|
const jsContext = jsIsolate.createContextSync()
|
||||||
|
|
||||||
|
const injectedRequire = `const require = function(val){
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case "url":
|
case "url":
|
||||||
return {
|
return {
|
||||||
|
@ -28,63 +32,70 @@ export function init() {
|
||||||
}
|
}
|
||||||
};`
|
};`
|
||||||
|
|
||||||
const global = jsContext.global
|
const global = jsContext.global
|
||||||
global.setSync(
|
global.setSync(
|
||||||
"urlResolveCb",
|
"urlResolveCb",
|
||||||
new ivm.Callback((...params: Parameters<typeof url.resolve>) =>
|
new ivm.Callback((...params: Parameters<typeof url.resolve>) =>
|
||||||
url.resolve(...params)
|
url.resolve(...params)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
global.setSync(
|
global.setSync(
|
||||||
"urlParseCb",
|
"urlParseCb",
|
||||||
new ivm.Callback((...params: Parameters<typeof url.parse>) =>
|
new ivm.Callback((...params: Parameters<typeof url.parse>) =>
|
||||||
url.parse(...params)
|
url.parse(...params)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
const helpersModule = jsIsolate.compileModuleSync(
|
const helpersModule = jsIsolate.compileModuleSync(
|
||||||
`${injectedRequire};${helpersSource}`
|
`${injectedRequire};${helpersSource}`
|
||||||
)
|
)
|
||||||
|
|
||||||
const cryptoModule = jsIsolate.compileModuleSync(`export default {
|
const cryptoModule = jsIsolate.compileModuleSync(`export default {
|
||||||
randomUUID: cryptoRandomUUIDCb,
|
randomUUID: cryptoRandomUUIDCb,
|
||||||
}`)
|
}`)
|
||||||
cryptoModule.instantiateSync(jsContext, specifier => {
|
cryptoModule.instantiateSync(jsContext, specifier => {
|
||||||
throw new Error(`No imports allowed. Required: ${specifier}`)
|
throw new Error(`No imports allowed. Required: ${specifier}`)
|
||||||
})
|
|
||||||
|
|
||||||
global.setSync(
|
|
||||||
"cryptoRandomUUIDCb",
|
|
||||||
new ivm.Callback((...params: Parameters<typeof crypto.randomUUID>) => {
|
|
||||||
return crypto.randomUUID(...params)
|
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
|
||||||
helpersModule.instantiateSync(jsContext, specifier => {
|
global.setSync(
|
||||||
if (specifier === "crypto") {
|
"cryptoRandomUUIDCb",
|
||||||
return cryptoModule
|
new ivm.Callback(
|
||||||
}
|
(...params: Parameters<typeof crypto.randomUUID>) => {
|
||||||
throw new Error(`No imports allowed. Required: ${specifier}`)
|
return crypto.randomUUID(...params)
|
||||||
})
|
}
|
||||||
|
|
||||||
const perRequestLimit = env.JS_PER_REQUEST_TIME_LIMIT_MS
|
|
||||||
if (perRequestLimit) {
|
|
||||||
const cpuMs = Number(jsIsolate.cpuTime) / 1e6
|
|
||||||
if (cpuMs > perRequestLimit) {
|
|
||||||
throw new Error(
|
|
||||||
`CPU time limit exceeded (${cpuMs}ms > ${perRequestLimit}ms)`
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
helpersModule.instantiateSync(jsContext, specifier => {
|
||||||
|
if (specifier === "crypto") {
|
||||||
|
return cryptoModule
|
||||||
|
}
|
||||||
|
throw new Error(`No imports allowed. Required: ${specifier}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
const perRequestLimit = env.JS_PER_REQUEST_TIME_LIMIT_MS
|
||||||
|
if (perRequestLimit) {
|
||||||
|
const cpuMs = Number(jsIsolate.cpuTime) / 1e6
|
||||||
|
if (cpuMs > perRequestLimit) {
|
||||||
|
throw new Error(
|
||||||
|
`CPU time limit exceeded (${cpuMs}ms > ${perRequestLimit}ms)`
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(ctx)) {
|
||||||
|
if (key === "helpers") {
|
||||||
|
// Can't copy the native helpers into the isolate. We just ignore them as they are handled properly from the helpersSource
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
global.setSync(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
bbCtx.isolateRefs = { jsContext, jsIsolate, helpersModule }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(ctx)) {
|
let { jsIsolate, jsContext, helpersModule } = bbCtx.isolateRefs!
|
||||||
if (key === "helpers") {
|
|
||||||
// Can't copy the native helpers into the isolate. We just ignore them as they are handled properly from the helpersSource
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
global.setSync(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const script = jsIsolate.compileModuleSync(
|
const script = jsIsolate.compileModuleSync(
|
||||||
`import helpers from "compiled_module";${js};cb(run());`,
|
`import helpers from "compiled_module";${js};cb(run());`,
|
||||||
|
@ -100,7 +111,7 @@ export function init() {
|
||||||
})
|
})
|
||||||
|
|
||||||
let result
|
let result
|
||||||
global.setSync(
|
jsContext.global.setSync(
|
||||||
"cb",
|
"cb",
|
||||||
new ivm.Callback((value: any) => {
|
new ivm.Callback((value: any) => {
|
||||||
result = value
|
result = value
|
||||||
|
|
Loading…
Reference in New Issue