Skip to content

Commit e9fae33

Browse files
committed
perf: cache functions
1 parent 529a382 commit e9fae33

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

compiler.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ module.exports = {
55
compileExpression
66
}
77

8+
const expressionCache = new Map()
9+
const codeCache = new Map()
10+
811
function compileExpression (src, sandbox) {
912
if (typeof src !== 'string') {
1013
throw new TypeError('first argument must be a string')
1114
}
1215
if (typeof sandbox !== 'object') {
1316
throw new TypeError('second argument must be an object')
1417
}
15-
16-
sandbox = new Proxy(sandbox, {get, has})
17-
const expression = `
18-
try { with (sandbox) { return ${src} } } catch (err) {
19-
if (!(err instanceof ReferenceError || err instanceof TypeError)) throw err
20-
}`
21-
return new Function('sandbox', expression).bind(sandbox, sandbox) // eslint-disable-line
18+
sandbox = new Proxy(sandbox, {has})
19+
let expression = expressionCache.get(src)
20+
if (!expression) {
21+
expression = new Function('sandbox',
22+
`try { with (sandbox) { return ${src} } } catch (err) {
23+
if (!(err instanceof ReferenceError || err instanceof TypeError)) throw err
24+
}`)
25+
expressionCache.set(src, expression)
26+
}
27+
return expression.bind(sandbox, sandbox) // eslint-disable-line
2228
}
2329

2430
function compileCode (src, sandbox) {
@@ -28,18 +34,15 @@ function compileCode (src, sandbox) {
2834
if (typeof sandbox !== 'object') {
2935
throw new TypeError('second argument must be an object')
3036
}
31-
32-
sandbox = new Proxy(sandbox, {get, has})
33-
return new Function('sandbox', `with (sandbox) { ${src} }`).bind(sandbox, sandbox) // eslint-disable-line
34-
}
35-
36-
function get (target, key, receiver) {
37-
if (key === Symbol.unscopables) {
38-
return undefined
37+
sandbox = new Proxy(sandbox, {has})
38+
let code = codeCache.get(src)
39+
if (!code) {
40+
code = new Function('sandbox', `with (sandbox) { ${src} }`)
41+
codeCache.set(src, code)
3942
}
40-
return Reflect.get(target, key, receiver)
43+
return code.bind(sandbox, sandbox) // eslint-disable-line
4144
}
4245

43-
function has (target, key) {
46+
function has () {
4447
return true
4548
}

0 commit comments

Comments
 (0)