const filters = new Map();
const limiters = new Map();
function filter(name, handler) {
if (typeof name !== 'string') {
throw new TypeError('First argument must be a string.');
}
if (typeof handler !== 'function') {
throw new TypeError('Second argument must be a function.');
}
if (filters.has(name)) {
throw new Error(`A filter named ${name} is already registered.`);
}
filters.set(name, handler);
}
function limiter(name, handler) {
if (typeof name !== 'string') {
throw new TypeError('First argument must be a string.');
}
if (typeof handler !== 'function') {
throw new TypeError('Second argument must be a function.');
}
if (limiters.has(name)) {
throw new Error(`A limiter named ${name} is already registered.`);
}
limiters.set(name, handler);
}
function compileRawExpression(src) {
return new Function('context', 'tempVars', // eslint-disable-line
`const sandbox = $nxCompileToSandbox(context, tempVars)
try { with (sandbox) { return ${src} } } catch (err) {
if (!(err instanceof TypeError)) throw err
}
$nxClearSandbox()`);
}
function compileRawCode(src) {
return new Function('context', 'tempVars', // eslint-disable-line
`const sandbox = $nxCompileToSandbox(context, tempVars)
with (sandbox) { ${src} }
$nxClearSandbox()`);
}
const filterRegex = /(?:[^\|]|\|\|)+/g;
const limiterRegex = /(?:[^&]|&&)+/g;
const argsRegex = /\S+/g;
function parseExpression(src) {
const tokens = src.match(filterRegex);
if (tokens.length === 1) {
return compileRawExpression(tokens[0]);
}
const expression = {
exec: compileRawExpression(tokens[0]),
filters: []
};
for (let i = 1; i < tokens.length; i++) {
let filterTokens = tokens[i].match(argsRegex);
const filterName = filterTokens.shift();
const effect = filters.get(filterName);
if (!effect) {
throw new Error(`There is no filter named: ${filterName}.`);
}
expression.filters.push({ effect, argExpressions: filterTokens.map(compileRawExpression) });
}
return expression;
}
function parseCode(src) {
const tokens = src.match(limiterRegex);
if (tokens.length === 1) {
return compileRawCode(tokens[0]);
}
const code = {
exec: compileRawCode(tokens[0]),
limiters: []
};
for (let i = 1; i < tokens.length; i++) {
const limiterTokens = tokens[i].match(argsRegex);
const limiterName = limiterTokens.shift();
const effect = limiters.get(limiterName);
if (!effect) {
throw new Error(`There is no limiter named: ${limiterName}.`);
}
code.limiters.push({ effect, argExpressions: limiterTokens.map(compileRawExpression) });
}
return code;
}
const expressionCache = new Map();
const codeCache = new Map();
function compileExpression(src) {
if (typeof src !== 'string') {
throw new TypeError('First argument must be a string.');
}
let expression = expressionCache.get(src);
if (!expression) {
expression = parseExpression(src);
expressionCache.set(src, expression);
}
if (typeof expression === 'function') {
return expression;
}
return function evaluateExpression(context, tempVars) {
let value = expression.exec(context, tempVars);
for (let filter of expression.filters) {
const args = filter.argExpressions.map(evaluateArgExpression, context);
value = filter.effect(value, args);
}
return value;
};
}
function compileCode(src) {
if (typeof src !== 'string') {
throw new TypeError('First argument must be a string.');
}
let code = codeCache.get(src);
if (!code) {
code = parseCode(src);
codeCache.set(src, code);
}
if (typeof code === 'function') {
return code;
}
const context = {};
return function evaluateCode(state, tempVars) {
let i = 0;
function next() {
Object.assign(context, tempVars);
if (i < code.limiters.length) {
const limiter = code.limiters[i++];
const args = limiter.argExpressions.map(evaluateArgExpression, state);
limiter.effect(next, context, args);
} else {
code.exec(state, tempVars);
}
}
next();
};
}
function evaluateArgExpression(argExpression) {
return argExpression(this);
}
const hasHandler = { has };
const allHandlers = { has, get };
const globals = new Set();
let temp;
let globalObj;
if (typeof window !== 'undefined') globalObj = window; // eslint-disable-line
else if (typeof global !== 'undefined') globalObj = global; // eslint-disable-line
else if (typeof self !== 'undefined') globalObj = self; // eslint-disable-line
globalObj.$nxCompileToSandbox = toSandbox;
globalObj.$nxClearSandbox = clearSandbox;
function expose(globalNames) {
for (let globalName of globalNames) {
globals.add(globalName);
}
}
function hide(globalNames) {
for (let globalName of globalNames) {
globals.delete(globalName);
}
}
function hideAll() {
globals.clear();
}
function has(target, key) {
return globals.has(key) ? key in target : true;
}
function get(target, key) {
return key in temp ? temp[key] : target[key];
}
function toSandbox(obj, tempVars) {
if (tempVars) {
temp = tempVars;
return new Proxy(obj, allHandlers);
}
return new Proxy(obj, hasHandler);
}
function clearSandbox() {
temp = undefined;
}
window.codeopti = compileCode('return prop1 + prop2');
const code = compileCode('return prop1 + prop2');
const sum = code({prop1: 1, prop2: 2});
eval('1+2');
const sum = codeopti({prop1: 1, prop2: 2});
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
Compile and exec | |
Eval | |
Exec only |
Test name | Executions per second |
---|---|
Compile and exec | 1177744.4 Ops/sec |
Eval | 3135623.0 Ops/sec |
Exec only | 1097512.9 Ops/sec |
Based on the provided information, I'll attempt to answer your question.
Context
The code snippet appears to be a part of a compiler or interpreter for a JavaScript-like language. The compileCode
function takes a string as input and returns an object with a limiters
property. This object is then used to execute a series of operations.
Benchmarking
The benchmarking data shows the execution time for three different test cases:
eval('1+2')
const code = compileCode('return prop1 + prop2');
and then executing it with an object {prop1: 1, prop2: 2}
Observations
Compile and exec
test case is slower than the Eval
and Exec only
tests, indicating that compilation introduces some overhead.Compiling
test case has a higher variance in execution times, suggesting that there may be variations in how the code is executed.Question
Unfortunately, I don't see a specific question being asked. Are you looking for:
compileCode
function?Please provide more context or clarify what you're looking for, and I'll do my best to assist you!