Skip to content

Commit 0189b9c

Browse files
committed
feat(code): allow temp vars
1 parent 4eb00aa commit 0189b9c

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ const code = compiler.compileCode('return prop1 + prop2')
4040
const sum = code({prop1: 1, prop2: 2}) // sum is 3
4141
```
4242

43+
The returned function also accepts a second object argument, that may contain temporary variables.
44+
Temporary variables are added to the context object while the code is executing and removed after.
45+
They are favored over the permanent context variables.
46+
47+
```js
48+
const code = compiler.compileCode('return prop1 + prop2')
49+
const context = {prop1: 1, prop2: 2}
50+
const temporary = {prop1: 2}
51+
const sum = code(context, temporary) // sum is 4, context is still {prop1: 1, prop2: 2}
52+
```
53+
4354
### compiler.compileExpression(String)
4455

4556
This method creates a function out of a string and returns it. The returned function takes

compiler.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ if (typeof window !== 'undefined') globalObj = window // eslint-disable-line
1010
else if (typeof global !== 'undefined') globalObj = global // eslint-disable-line
1111
else if (typeof self !== 'undefined') globalObj = self // eslint-disable-line
1212
globalObj.$nxCompileToSandbox = toSandbox
13+
globalObj.$nxCompileCreateBackup = createBackup
1314

1415
const proxies = new WeakMap()
1516
const expressionCache = new Map()
@@ -22,10 +23,10 @@ function compileExpression (src) {
2223
}
2324
let expression = expressionCache.get(src)
2425
if (!expression) {
25-
expression = new Function('sandbox', // eslint-disable-line
26-
`sandbox = $nxCompileToSandbox(sandbox)
26+
expression = new Function('context', // eslint-disable-line
27+
`const sandbox = $nxCompileToSandbox(context)
2728
try { with (sandbox) { return ${src} } } catch (err) {
28-
if (!(err instanceof ReferenceError || err instanceof TypeError)) throw err
29+
if (!(err instanceof TypeError)) throw err
2930
}`)
3031
expressionCache.set(src, expression)
3132
}
@@ -38,9 +39,15 @@ function compileCode (src) {
3839
}
3940
let code = codeCache.get(src)
4041
if (!code) {
41-
code = new Function('sandbox', // eslint-disable-line
42-
`sandbox = $nxCompileToSandbox(sandbox)
43-
with (sandbox) { ${src} }`)
42+
code = new Function('context, tempVars', // eslint-disable-line
43+
`const backup = $nxCompileCreateBackup(context, tempVars)
44+
Object.assign(context, tempVars)
45+
const sandbox = $nxCompileToSandbox(context)
46+
try {
47+
with (sandbox) { ${src} }
48+
} finally {
49+
Object.assign(context, backup)
50+
}`)
4451
codeCache.set(src, code)
4552
}
4653
return code
@@ -58,6 +65,16 @@ function toSandbox (obj) {
5865
return sandbox
5966
}
6067

68+
function createBackup (context, tempVars) {
69+
if (typeof tempVars === 'object') {
70+
const backup = {}
71+
for (let key of Object.keys(tempVars)) {
72+
backup[key] = context[key]
73+
}
74+
return backup
75+
}
76+
}
77+
6178
function has () {
6279
return true
6380
}

compiler.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,23 @@ describe('nx-compile', () => {
6060
const code = compiler.compileCode('inner.prop1')
6161
expect(() => code({})).to.throw(TypeError)
6262
})
63+
64+
it('should accept temporary variables', () => {
65+
const code = compiler.compileCode('return tempVar')
66+
expect(code({}, {tempVar: 'temp'})).to.equal('temp')
67+
})
68+
69+
it('should favour temporary variables over persistent ones', () => {
70+
const code = compiler.compileCode('return tempVar')
71+
expect(code({tempVar: 'persistent'}, {tempVar: 'temp'})).to.equal('temp')
72+
})
73+
74+
it('should not modify the passed context persistently', () => {
75+
const code = compiler.compileCode('return tempVar')
76+
const context = {}
77+
const result = code(context, {tempVar: 'temp'})
78+
expect(result).to.equal('temp')
79+
expect(context.tempVar).to.be.undefined
80+
})
6381
})
6482
})

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@risingstack/nx-compile",
3-
"version": "4.0.0",
3+
"version": "4.1.0",
44
"description": "Execution of string as code in the context of an object, similarly to Object.eval().",
55
"main": "compiler.js",
66
"scripts": {

0 commit comments

Comments
 (0)