From dce14811854b40201b35eeb51b8cd17f54cf739d Mon Sep 17 00:00:00 2001 From: Nelu Platonov Date: Thu, 23 Nov 2023 23:38:43 +0100 Subject: [PATCH 1/3] fix(#521): Allow "context" as the name of a key/var in a JS expression --- packages/bruno-js/src/utils.js | 10 +++++---- packages/bruno-js/tests/utils.spec.js | 30 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/bruno-js/src/utils.js b/packages/bruno-js/src/utils.js index 7d6b2db30..92f3a2c08 100644 --- a/packages/bruno-js/src/utils.js +++ b/packages/bruno-js/src/utils.js @@ -18,8 +18,8 @@ const JS_KEYWORDS = ` * ```js * res.data.pets.map(pet => pet.name.toUpperCase()) * - * function(context) { - * const { res, pet } = context; + * function(_BrunoNewFunctionInnerContext) { + * const { res, pet } = _BrunoNewFunctionInnerContext; * return res.data.pets.map(pet => pet.name.toUpperCase()) * } * ``` @@ -45,9 +45,11 @@ const compileJsExpression = (expr) => { globals: globals.map((name) => ` ${name} = ${name} ?? globalThis.${name};`).join('') }; - const body = `let { ${code.vars} } = context; ${code.globals}; return ${expr}`; + // param name that is unlikely to show up as a var in an expression + const param = `_BrunoNewFunctionInnerContext`; + const body = `let { ${code.vars} } = ${param}; ${code.globals}; return ${expr}`; - return new Function('context', body); + return new Function(param, body); }; const internalExpressionCache = new Map(); diff --git a/packages/bruno-js/tests/utils.spec.js b/packages/bruno-js/tests/utils.spec.js index 6ac687f07..6a454fde7 100644 --- a/packages/bruno-js/tests/utils.spec.js +++ b/packages/bruno-js/tests/utils.spec.js @@ -5,7 +5,9 @@ describe('utils', () => { describe('expression evaluation', () => { const context = { res: { - data: { pets: ['bruno', 'max'] } + data: { pets: ['bruno', 'max'] }, + context: 'testContext', + _BrunoNewFunctionInnerContext: 0 } }; @@ -45,32 +47,32 @@ describe('utils', () => { it('should identify top level variables', () => { const expr = 'res.data.pets[0].toUpperCase()'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = context;'); + expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); }); it('should not duplicate variables', () => { const expr = 'res.data.pets[0] + res.data.pets[1]'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = context;'); + expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); }); it('should exclude js keywords like true false from vars', () => { const expr = 'res.data.pets.length > 0 ? true : false'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = context;'); + expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); }); it('should exclude numbers from vars', () => { const expr = 'res.data.pets.length + 10'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = context;'); + expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); }); it('should pick variables from complex expressions', () => { const expr = 'res.data.pets.map(pet => pet.length)'; const result = evaluateJsExpression(expr, context); expect(result).toEqual([5, 3]); - expect(cache.get(expr).toString()).toContain('let { res, pet } = context;'); + expect(cache.get(expr).toString()).toContain('let { res, pet } = _BrunoNewFunctionInnerContext;'); }); it('should be ok picking extra vars from strings', () => { @@ -78,7 +80,7 @@ describe('utils', () => { const result = evaluateJsExpression(expr, context); expect(result).toBe('hello bruno'); // extra var hello is harmless - expect(cache.get(expr).toString()).toContain('let { hello, res } = context;'); + expect(cache.get(expr).toString()).toContain('let { hello, res } = _BrunoNewFunctionInnerContext;'); }); it('should evaluate expressions referencing globals', () => { @@ -112,6 +114,20 @@ describe('utils', () => { expect(result).toBe(startTime); }); + + it('should allow "context" as a var name', () => { + const expr = 'res["context"].toUpperCase()'; + evaluateJsExpression(expr, context); + expect(cache.get(expr).toString()).toContain('let { res, context } = _BrunoNewFunctionInnerContext;'); + }); + + it('should throw an error when we use "_BrunoNewFunctionInnerContext" as a var name', () => { + const expr = 'res["_BrunoNewFunctionInnerContext"].toUpperCase()'; + expect(() => evaluateJsExpression(expr, context)).toThrow(SyntaxError); + expect(() => evaluateJsExpression(expr, context)).toThrow( + "Identifier '_BrunoNewFunctionInnerContext' has already been declared" + ); + }); }); describe('response parser', () => { From 22612a7dbe3b180a9b3cb9465eb2b58023edcea0 Mon Sep 17 00:00:00 2001 From: lohit Date: Sun, 15 Dec 2024 20:00:13 +0530 Subject: [PATCH 2/3] `_BrunoNewFunctionInnerContext` to `__bruno__functionInnerContext` --- packages/bruno-js/src/utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-js/src/utils.js b/packages/bruno-js/src/utils.js index 92f3a2c08..a9bf78260 100644 --- a/packages/bruno-js/src/utils.js +++ b/packages/bruno-js/src/utils.js @@ -18,8 +18,8 @@ const JS_KEYWORDS = ` * ```js * res.data.pets.map(pet => pet.name.toUpperCase()) * - * function(_BrunoNewFunctionInnerContext) { - * const { res, pet } = _BrunoNewFunctionInnerContext; + * function(__bruno__functionInnerContext) { + * const { res, pet } = __bruno__functionInnerContext; * return res.data.pets.map(pet => pet.name.toUpperCase()) * } * ``` @@ -46,7 +46,7 @@ const compileJsExpression = (expr) => { }; // param name that is unlikely to show up as a var in an expression - const param = `_BrunoNewFunctionInnerContext`; + const param = `__bruno__functionInnerContext`; const body = `let { ${code.vars} } = ${param}; ${code.globals}; return ${expr}`; return new Function(param, body); From 434ae6c70f4dad54b46db130fd8e902a2052f228 Mon Sep 17 00:00:00 2001 From: lohit Date: Sun, 15 Dec 2024 20:00:57 +0530 Subject: [PATCH 3/3] `_BrunoNewFunctionInnerContext` to `__bruno__functionInnerContext` --- packages/bruno-js/tests/utils.spec.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/bruno-js/tests/utils.spec.js b/packages/bruno-js/tests/utils.spec.js index 6a454fde7..b1ecc7db7 100644 --- a/packages/bruno-js/tests/utils.spec.js +++ b/packages/bruno-js/tests/utils.spec.js @@ -7,7 +7,7 @@ describe('utils', () => { res: { data: { pets: ['bruno', 'max'] }, context: 'testContext', - _BrunoNewFunctionInnerContext: 0 + __bruno__functionInnerContext: 0 } }; @@ -47,32 +47,32 @@ describe('utils', () => { it('should identify top level variables', () => { const expr = 'res.data.pets[0].toUpperCase()'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res } = __bruno__functionInnerContext;'); }); it('should not duplicate variables', () => { const expr = 'res.data.pets[0] + res.data.pets[1]'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res } = __bruno__functionInnerContext;'); }); it('should exclude js keywords like true false from vars', () => { const expr = 'res.data.pets.length > 0 ? true : false'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res } = __bruno__functionInnerContext;'); }); it('should exclude numbers from vars', () => { const expr = 'res.data.pets.length + 10'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res } = __bruno__functionInnerContext;'); }); it('should pick variables from complex expressions', () => { const expr = 'res.data.pets.map(pet => pet.length)'; const result = evaluateJsExpression(expr, context); expect(result).toEqual([5, 3]); - expect(cache.get(expr).toString()).toContain('let { res, pet } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res, pet } = __bruno__functionInnerContext;'); }); it('should be ok picking extra vars from strings', () => { @@ -80,7 +80,7 @@ describe('utils', () => { const result = evaluateJsExpression(expr, context); expect(result).toBe('hello bruno'); // extra var hello is harmless - expect(cache.get(expr).toString()).toContain('let { hello, res } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { hello, res } = __bruno__functionInnerContext;'); }); it('should evaluate expressions referencing globals', () => { @@ -118,14 +118,14 @@ describe('utils', () => { it('should allow "context" as a var name', () => { const expr = 'res["context"].toUpperCase()'; evaluateJsExpression(expr, context); - expect(cache.get(expr).toString()).toContain('let { res, context } = _BrunoNewFunctionInnerContext;'); + expect(cache.get(expr).toString()).toContain('let { res, context } = __bruno__functionInnerContext;'); }); - it('should throw an error when we use "_BrunoNewFunctionInnerContext" as a var name', () => { - const expr = 'res["_BrunoNewFunctionInnerContext"].toUpperCase()'; + it('should throw an error when we use "__bruno__functionInnerContext" as a var name', () => { + const expr = 'res["__bruno__functionInnerContext"].toUpperCase()'; expect(() => evaluateJsExpression(expr, context)).toThrow(SyntaxError); expect(() => evaluateJsExpression(expr, context)).toThrow( - "Identifier '_BrunoNewFunctionInnerContext' has already been declared" + "Identifier '__bruno__functionInnerContext' has already been declared" ); }); });