* @param {string} expression * @param {EvalContext} context * @returns {string | number | boolean}
(expression, context)
| 10 | * @returns {string | number | boolean} |
| 11 | */ |
| 12 | evaluateJavaScript(expression, context) { |
| 13 | let result; |
| 14 | const that = this; |
| 15 | /** @type {Record<string, { value: Node, toJS: () => string }>} */ |
| 16 | const evalContext = {}; |
| 17 | |
| 18 | if (!context.javascriptEnabled) { |
| 19 | throw { message: 'Inline JavaScript is not enabled. Is it set in your options?', |
| 20 | filename: this.fileInfo().filename, |
| 21 | index: this.getIndex() }; |
| 22 | } |
| 23 | |
| 24 | expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) { |
| 25 | return that.jsify(new Variable(`@${name}`, that.getIndex(), that.fileInfo()).eval(context)); |
| 26 | }); |
| 27 | |
| 28 | /** @type {Function} */ |
| 29 | let expressionFunc; |
| 30 | try { |
| 31 | expressionFunc = new Function(`return (${expression})`); |
| 32 | } catch (e) { |
| 33 | throw { message: `JavaScript evaluation error: ${/** @type {Error} */ (e).message} from \`${expression}\`` , |
| 34 | filename: this.fileInfo().filename, |
| 35 | index: this.getIndex() }; |
| 36 | } |
| 37 | |
| 38 | const variables = /** @type {Node & { variables: () => Record<string, { value: Node }> }} */ (context.frames[0]).variables(); |
| 39 | for (const k in variables) { |
| 40 | // eslint-disable-next-line no-prototype-builtins |
| 41 | if (variables.hasOwnProperty(k)) { |
| 42 | evalContext[k.slice(1)] = { |
| 43 | value: variables[k].value, |
| 44 | toJS: function () { |
| 45 | return this.value.eval(context).toCSS(context); |
| 46 | } |
| 47 | }; |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | try { |
| 52 | result = expressionFunc.call(evalContext); |
| 53 | } catch (e) { |
| 54 | throw { message: `JavaScript evaluation error: '${/** @type {Error} */ (e).name}: ${/** @type {Error} */ (e).message.replace(/["]/g, '\'')}'` , |
| 55 | filename: this.fileInfo().filename, |
| 56 | index: this.getIndex() }; |
| 57 | } |
| 58 | return result; |
| 59 | } |
| 60 | |
| 61 | /** |
| 62 | * @param {Node} obj |