diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index 59a3289731..8e390068df 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -41,6 +41,7 @@ let autoSchema = {} let rows = [] + let keys = {} const parseQuery = query => { modified = false @@ -137,8 +138,20 @@ const handleScroll = e => { scrolling = e.target.scrollTop !== 0 } + + async function handleKeyDown(evt) { + keys[evt.key] = true + if ((keys["Meta"] || keys["Control"]) && keys["Enter"]) { + await runQuery({ suppressErrors: false }) + } + } + + function handleKeyUp(evt) { + delete keys[evt.key] + } + checkIsModified(newQuery)} attemptSave={() => runQuery({ suppressErrors: false }).then(saveQuery)} diff --git a/packages/server/package.json b/packages/server/package.json index 66220c9f45..b8dcab3642 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -109,7 +109,6 @@ "undici-types": "^6.0.1", "uuid": "3.3.2", "validate.js": "0.13.1", - "vm2": "^3.9.19", "worker-farm": "1.7.0", "xml2js": "0.5.0" }, diff --git a/packages/server/src/utilities/scriptRunner.ts b/packages/server/src/utilities/scriptRunner.ts index fee0215d2e..e6df8fa829 100644 --- a/packages/server/src/utilities/scriptRunner.ts +++ b/packages/server/src/utilities/scriptRunner.ts @@ -1,29 +1,64 @@ -import fetch from "node-fetch" -import { VM, VMScript } from "vm2" +import ivm, { Context, Script } from "isolated-vm" const JS_TIMEOUT_MS = 1000 class ScriptRunner { - vm: VM - results: { out: string } - script: VMScript + vm: IsolatedVM constructor(script: string, context: any) { const code = `let fn = () => {\n${script}\n}; results.out = fn();` - this.vm = new VM({ - timeout: JS_TIMEOUT_MS, - }) - this.results = { out: "" } - this.vm.setGlobals(context) - this.vm.setGlobal("fetch", fetch) - this.vm.setGlobal("results", this.results) - this.script = new VMScript(code) + this.vm = new IsolatedVM(8) + this.vm.context = { + data: context.data, + params: context.params, + results: { out: "" }, + } + this.vm.code = code } execute() { - this.vm.run(this.script) - return this.results.out + this.vm.runScript() + const results = this.vm.getValue("results") + return results.out } } +class IsolatedVM { + isolate: ivm.Isolate + vm: ivm.Context + jail: ivm.Reference + script: any + + constructor(memoryLimit: number) { + this.isolate = new ivm.Isolate({ memoryLimit }) + this.vm = this.isolate.createContextSync() + this.jail = this.vm.global + this.jail.setSync("global", this.jail.derefInto()) + } + + getValue(key: string) { + const ref = this.vm.global.getSync(key, { reference: true }) + const result = ref.copySync() + ref.release() + return result + } + + set context(context: Record) { + for (let key in context) { + this.jail.setSync(key, this.copyRefToVm(context[key])) + } + } + + set code(code: string) { + this.script = this.isolate.compileScriptSync(code) + } + + runScript() { + this.script.runSync(this.vm, { timeout: JS_TIMEOUT_MS }) + } + + copyRefToVm(value: Object): ivm.Copy { + return new ivm.ExternalCopy(value).copyInto({ release: true }) + } +} export default ScriptRunner diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index 52c77f5c4a..690ae7745f 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -2,7 +2,6 @@ "name": "@budibase/string-templates", "version": "0.0.0", "description": "Handlebars wrapper for Budibase templating.", - "main": "src/index.cjs", "module": "dist/bundle.mjs", "license": "MPL-2.0", "types": "dist/index.d.ts", @@ -28,8 +27,8 @@ "@budibase/handlebars-helpers": "^0.11.9", "dayjs": "^1.10.8", "handlebars": "^4.7.6", - "lodash": "4.17.21", - "vm2": "^3.9.19" + "isolated-vm": "^4.6.0", + "lodash": "4.17.21" }, "devDependencies": { "@rollup/plugin-commonjs": "^17.1.0", diff --git a/packages/string-templates/src/index.cjs b/packages/string-templates/src/index.cjs deleted file mode 100644 index 1cf3c8d0c6..0000000000 --- a/packages/string-templates/src/index.cjs +++ /dev/null @@ -1,36 +0,0 @@ -const templates = require("./index.js") - -/** - * CJS entrypoint for rollup - */ -module.exports.isValid = templates.isValid -module.exports.makePropSafe = templates.makePropSafe -module.exports.getManifest = templates.getManifest -module.exports.isJSBinding = templates.isJSBinding -module.exports.encodeJSBinding = templates.encodeJSBinding -module.exports.decodeJSBinding = templates.decodeJSBinding -module.exports.processStringSync = templates.processStringSync -module.exports.processObjectSync = templates.processObjectSync -module.exports.processString = templates.processString -module.exports.processObject = templates.processObject -module.exports.doesContainStrings = templates.doesContainStrings -module.exports.doesContainString = templates.doesContainString -module.exports.disableEscaping = templates.disableEscaping -module.exports.findHBSBlocks = templates.findHBSBlocks -module.exports.convertToJS = templates.convertToJS -module.exports.FIND_ANY_HBS_REGEX = templates.FIND_ANY_HBS_REGEX - -if (!process.env.NO_JS) { - const { VM } = require("vm2") - const { setJSRunner } = require("./helpers/javascript") - /** - * Use vm2 to run JS scripts in a node env - */ - setJSRunner((js, context) => { - const vm = new VM({ - sandbox: context, - timeout: 1000, - }) - return vm.run(js) - }) -} diff --git a/yarn.lock b/yarn.lock index dc27c8d435..ef572d0958 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6322,7 +6322,7 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.1.0, acorn@^8.10.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.1.0, acorn@^8.10.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.11.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== @@ -11986,7 +11986,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -18772,7 +18772,7 @@ request@^2.88.0: performance-now "^2.1.0" qs "~6.5.2" safe-buffer "^5.1.2" - tough-cookie "^4.1.3" + tough-cookie "~2.5.0" tunnel-agent "^0.6.0" uuid "^3.3.2" @@ -20931,7 +20931,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@^4.1.3, tough-cookie@~2.5.0: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -21729,14 +21729,6 @@ vlq@^0.2.2: resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== -vm2@^3.9.19: - version "3.9.19" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.19.tgz#be1e1d7a106122c6c492b4d51c2e8b93d3ed6a4a" - integrity sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg== - dependencies: - acorn "^8.7.0" - acorn-walk "^8.2.0" - vuvuzela@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b"