From 44d70ca02aba41153e2311c0aa9b737cf2dcf69a Mon Sep 17 00:00:00 2001 From: lohit Date: Fri, 23 Aug 2024 16:18:41 +0530 Subject: [PATCH] fix: boolean, undefined, null values eval in quickjs vm (#2893) fix: boolean, undeifned, null values in pre-request vars --- .../src/components/CodeEditor/index.js | 4 +- .../JsSandboxModeModal/index.js | 3 +- packages/bruno-cli/package.json | 2 +- packages/bruno-electron/package.json | 2 +- packages/bruno-js/package.json | 2 +- .../bruno-js/src/sandbox/quickjs/index.js | 32 +++++++++ .../js/data types - request vars.bru | 68 +++++++++++++++++++ 7 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 packages/bruno-tests/collection/scripting/js/data types - request vars.bru diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 85f6c2da4..af8cda247 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -66,7 +66,9 @@ if (!SERVER_RENDERED) { 'bru.getVar(key)', 'bru.setVar(key,value)', 'bru.deleteVar(key)', - 'bru.setNextRequest(requestName)' + 'bru.setNextRequest(requestName)', + 'bru.getRequestVar(key)', + 'bru.sleep(ms)' ]; CodeMirror.registerHelper('hint', 'brunoJS', (editor, options) => { const cursor = editor.getCursor(); diff --git a/packages/bruno-app/src/components/SecuritySettings/JsSandboxModeModal/index.js b/packages/bruno-app/src/components/SecuritySettings/JsSandboxModeModal/index.js index 4e5ec7292..2f010f71f 100644 --- a/packages/bruno-app/src/components/SecuritySettings/JsSandboxModeModal/index.js +++ b/packages/bruno-app/src/components/SecuritySettings/JsSandboxModeModal/index.js @@ -6,7 +6,7 @@ import Portal from 'components/Portal'; import Modal from 'components/Modal'; import StyledWrapper from './StyledWrapper'; -const JsSandboxModeModal = ({ collection, onClose }) => { +const JsSandboxModeModal = ({ collection }) => { const dispatch = useDispatch(); const [jsSandboxMode, setJsSandboxMode] = useState(collection?.securityConfig?.jsSandboxMode || 'safe'); @@ -22,7 +22,6 @@ const JsSandboxModeModal = ({ collection, onClose }) => { ) .then(() => { toast.success('Sandbox mode updated successfully'); - onClose(); }) .catch((err) => console.log(err) && toast.error('Failed to update sandbox mode')); }; diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json index 7dd157e4a..e856846c8 100644 --- a/packages/bruno-cli/package.json +++ b/packages/bruno-cli/package.json @@ -14,7 +14,7 @@ "url": "git+https://github.com/usebruno/bruno.git" }, "scripts": { - "test": "node --experimental-vm-modules $(npx --no-install which jest)" + "test": "node --experimental-vm-modules $(npx which jest)" }, "files": [ "src", diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 4ce7e565e..818d66bee 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -16,7 +16,7 @@ "dist:rpm": "electron-builder --linux rpm --config electron-builder-config.js", "dist:snap": "electron-builder --linux snap --config electron-builder-config.js", "pack": "electron-builder --dir", - "test": "node --experimental-vm-modules $(npx --no-install which jest)" + "test": "node --experimental-vm-modules $(npx which jest)" }, "jest": { "modulePaths": ["node_modules"] diff --git a/packages/bruno-js/package.json b/packages/bruno-js/package.json index 41a8b7bcb..fdd8bfbd9 100644 --- a/packages/bruno-js/package.json +++ b/packages/bruno-js/package.json @@ -11,7 +11,7 @@ "@n8n/vm2": "^3.9.23" }, "scripts": { - "test": "node --experimental-vm-modules $(npx --no-install which jest) --testPathIgnorePatterns test.js", + "test": "node --experimental-vm-modules $(npx which jest) --testPathIgnorePatterns test.js", "sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js" }, "dependencies": { diff --git a/packages/bruno-js/src/sandbox/quickjs/index.js b/packages/bruno-js/src/sandbox/quickjs/index.js index 5e568ee66..79ee2b8e8 100644 --- a/packages/bruno-js/src/sandbox/quickjs/index.js +++ b/packages/bruno-js/src/sandbox/quickjs/index.js @@ -21,11 +21,30 @@ const toNumber = (value) => { return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value); }; +const removeQuotes = (str) => { + if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) { + return str.slice(1, -1); + } + return str; +}; + const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'template-literal' }) => { + if (!externalScript?.length || typeof externalScript !== 'string') { + return externalScript; + } + externalScript = externalScript?.trim(); + if (!isNaN(Number(externalScript))) { return Number(externalScript); } + if (externalScript === 'true') return true; + if (externalScript === 'false') return false; + if (externalScript === 'null') return null; + if (externalScript === 'undefined') return undefined; + + externalScript = removeQuotes(externalScript); + const vm = QuickJSSyncContext; try { @@ -57,9 +76,22 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc }; const executeQuickJsVmAsync = async ({ script: externalScript, context: externalContext, collectionPath }) => { + if (!externalScript?.length || typeof externalScript !== 'string') { + return externalScript; + } + externalScript = externalScript?.trim(); + if (!isNaN(Number(externalScript))) { return toNumber(externalScript); } + + if (externalScript === 'true') return true; + if (externalScript === 'false') return false; + if (externalScript === 'null') return null; + if (externalScript === 'undefined') return undefined; + + externalScript = removeQuotes(externalScript); + try { const module = await newQuickJSWASMModule(); const vm = module.newContext(); diff --git a/packages/bruno-tests/collection/scripting/js/data types - request vars.bru b/packages/bruno-tests/collection/scripting/js/data types - request vars.bru new file mode 100644 index 000000000..3692c46cb --- /dev/null +++ b/packages/bruno-tests/collection/scripting/js/data types - request vars.bru @@ -0,0 +1,68 @@ +meta { + name: data types - request vars + type: http + seq: 3 +} + +post { + url: {{host}}/api/echo/json + body: json + auth: none +} + +body:json { + { + "boolean": false, + "number": 1, + "string": "bruno", + "array": [1, 2, 3, 4, 5], + "object": { + "hello": "bruno" + }, + "null": null + } +} + +vars:pre-request { + number: 1 + boolean: false + undefined: undefined + null: null + string: foo +} + +assert { + req.body.boolean: isBoolean false + req.body.number: isNumber 1 + req.body.undefined: isUndefined undefined + req.body.string: isString bruno + req.body.null: isNull null + req.body.array: isArray + req.body.boolean: eq false + req.body.number: eq 1 + req.body.undefined: eq undefined + req.body.string: eq bruno + req.body.null: eq null +} + +tests { + test("boolean pre var", function() { + expect(bru.getRequestVar('boolean')).to.eql(false); + }); + + test("number pre var", function() { + expect(bru.getRequestVar('number')).to.eql(1); + }); + + test("null pre var", function() { + expect(bru.getRequestVar('null')).to.eql(null); + }); + + test("undefined pre var", function() { + expect(bru.getRequestVar('undefined')).to.eql(undefined); + }); + + test("string pre var", function() { + expect(bru.getRequestVar('string')).to.eql('foo'); + }); +}