Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 94x 94x 94x 94x 232x 231x 231x 231x 232x 94x 94x 94x 12x 12x 12x 12x 12x 12x 12x 12x 12x 76x 76x 76x 76x 12x 12x 12x 12x 12x 12x 12x 12x 12x 18x 18x 18x 18x 12x 12x 12x 12x 12x 12x 12x 12x 12x 26x 26x 26x 24x 17x 24x 7x 7x 7x 7x 7x 7x 24x 26x 26x 26x 12x | /**
* Provides dynamic expression and statement evaluation within a given scope.
*/
export class DynamicEvaluator {
/**
* Converts a scope object into binding names and values for Function constructor.
* @param {Object} [scope={}] - The scope object.
* @returns {{names: string[], values: any[]}}
* @private
*/
#toScopeBindings(scope = {}) {
const names = [];
const values = [];
for (const [name, value] of Object.entries(scope)) {
if (/^[A-Za-z_$][\w$]*$/.test(name)) {
names.push(name);
values.push(value);
}
}
return { names, values };
}
/**
* Evaluates a JavaScript expression within a scope.
* @param {string} expression - The expression to evaluate.
* @param {Object} [scope={}] - The scope variables.
* @param {Object} [thisArg=scope] - The 'this' context for evaluation.
* @returns {any} The result of evaluation.
*/
evaluateExpression(expression, scope = {}, thisArg = scope) {
const { names, values } = this.#toScopeBindings(scope);
const fn = new Function(...names, `return (${expression})`);
return fn.call(thisArg, ...values);
}
/**
* Executes a JavaScript statement within a scope.
* @param {string} source - The statement(s) to execute.
* @param {Object} [scope={}] - The scope variables.
* @param {Object} [thisArg=scope] - The 'this' context for execution.
* @returns {any} The result of execution.
*/
executeStatement(source, scope = {}, thisArg = scope) {
const { names, values } = this.#toScopeBindings(scope);
const fn = new Function(...names, `with(this) { ${source} }`);
return fn.call(thisArg, ...values);
}
/**
* Creates a map of executable methods from string definitions.
* @param {Object} [methods={}] - An object containing method name and source code pairs.
* @param {function(Object): Object} getScope - Function to retrieve the scope for a method.
* @param {function(): Object} getThisArg - Function to retrieve the 'this' context for methods.
* @returns {Object} A map of functions.
*/
createMethodMap(methods = {}, getScope, getThisArg) {
const executable = {};
for (const [name, source] of Object.entries(methods)) {
if (typeof source === 'function') {
executable[name] = source.bind(getThisArg());
} else {
executable[name] = (...args) => this.executeStatement(
source,
{ ...getScope(executable), args },
getThisArg()
);
}
}
return executable;
}
}
|