@zvenigora/jse-eval
Version:
JavaScript expression parsing and evaluation.
3 lines (2 loc) • 13.4 kB
JavaScript
import e from"jsep";export{default as jsep,default as parse}from"jsep";function t(){return t=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},t.apply(this,arguments)}const n={undefined:void 0,null:null,true:!0,false:!1};class r{static getValue(e,t,n){const i=r.getScopedKeyValue(e,t,n);if(void 0===i)return;const[,s,o]=i,a=r.getBindFunction(s,t,n,o);return"function"==typeof a?a:s}static getScopePair(e,t,n){if(void 0!==e&&null!=n&&n.scopes){const e=r.getKeyValue(n.scopes,t,n);if(void 0!==e){const[t,n]=e;if(n)return[t,n]}}}static getBindFunction(e,t,n,i){var s;const o=r.hasProperty(null==n?void 0:n.scopes,i)?null==n||null==(s=n.scopes[i])?void 0:s.options:n;if("function"==typeof e&&null!=o&&o.functionBindings){const i=r.getKeyValue(o.functionBindings,t,n);if(void 0!==i){const[,t]=i;if(t){const n=t;return null!=n&&n.arguments?e.bind(null==n?void 0:n.thisRef,...n.arguments):e.bind(null==n?void 0:n.thisRef)}}}}static hasProperty(e,t){return!(!e||!t)&&Object.prototype.hasOwnProperty.call(e,t)}static getScopedKeyValue(e,t,n){const i=[""],s=r.hasProperty(e,null==n?void 0:n.currentScopeName)&&r.hasProperty(null==n?void 0:n.scopes,null==n?void 0:n.currentScopeName),o=r.hasProperty(e,null==n?void 0:n.globalScopeName)&&r.hasProperty(null==n?void 0:n.scopes,null==n?void 0:n.globalScopeName);s&&i.push(null==n?void 0:n.currentScopeName),o&&i.push(null==n?void 0:n.globalScopeName);for(const r of i){const i=this.getKeyValue(r?e[r]:e,t,n);if(void 0!==i){const[e,t]=i;return[e,t,r]}}}static getKeyValue(e,t,n){if(r.blockListTest(e,t,n),r.allowListTest(e,t,n),null!=n&&n.caseSensitive||"string"!=typeof t)return[t,e[t]];if("string"==typeof t){let n=e;do{const e=Object.getOwnPropertyNames(n);if(Array.isArray(e)){const r=e.find(e=>0===e.localeCompare(t,"en",{sensitivity:"base"}));if(r)return[r,n[r]]}}while(n=Object.getPrototypeOf(n))}}static getLiteralKeyValue(e,t,n){if(r.blockListTest(e,t,n),r.allowListTest(e,t,n),null!=n&&n.caseSensitive)return[t,e[t]];for(const[n,r]of Object.entries(e))if(0===n.localeCompare(t,"en",{sensitivity:"base"}))return[n,r]}static blockListTest(e,t,n){if(null!=n&&n.blockList&&"string"==typeof t&&n.blockList.find(n.caseSensitive?e=>e===t:e=>0===e.localeCompare(t,"en",{sensitivity:"base"})))throw Error(`Access to member "${t}" from blockList is not permitted.`)}static allowListTest(e,t,n){if(null!=n&&n.allowList&&"string"==typeof t&&!n.allowList.find(null!=n&&n.caseSensitive?e=>e===t:e=>0===e.localeCompare(t,"en",{sensitivity:"base"})))throw Error(`Access to member "${t}" not in allowList is not permitted.`)}}class i{static addUnaryOp(t,n){e.addUnaryOp(t),i.unops[t]=n}static addBinaryOp(t,n,r,s){let o,a,l;"function"==typeof n?l=n:(o=n,"function"==typeof r?l=r:(a=r,l=s)),e.addBinaryOp(t,o||1,a),i.binops[t]=l}static addEvaluator(e,t){i.evaluators[e]=t}static addConditionalEvaluator(e,t,n){i.conditionalEvaluators[e]||(i.conditionalEvaluators[e]=[]),i.conditionalEvaluators[e].push({evaluator:n,predicate:t})}static registerPlugin(...e){e.forEach(e=>{e.init&&i.parse.plugins.register(e),e.initEval&&e.initEval.call(i,i)})}static addOptions(e){i.defaultOptions=e}static eval(e,t,n){return new i(t,void 0,n).eval(e)}static async evalAsync(e,t,n){return new i(t,!0,n).eval(e)}static compile(e){return i.eval.bind(null,i.jsep(e))}static compileAsync(e){return i.evalAsync.bind(null,i.jsep(e))}static evalExpr(e,t){return i.compile(e)(t)}static evalExprAsync(e,t){return i.compileAsync(e)(t)}get caseSensitive(){return!(!this.options||!this.options.caseSensitive)}constructor(e,t,n){this.context=void 0,this.isAsync=void 0,this.options=void 0,this.context=e,this.isAsync=t,this.options=n||i.defaultOptions}eval(e,t=(e=>e)){const n=i.conditionalEvaluators[e.type];if(n)for(const r of n)if(r.predicate.call(this,e,this.context))return this.evalSyncAsync(r.evaluator.bind(this)(e,this.context),n=>(e._value=n,t(n)));const r=i.evaluators[e.type];if(void 0===r)throw new Error(`unknown node type: ${JSON.stringify(e,null,2)}`);return this.evalSyncAsync(r.bind(this)(e,this.context),n=>(e._value=n,t(n)))}evalSyncAsync(e,t){return this.isAsync?Promise.resolve(e).then(t):t(e)}evalArrayExpression(e){return this.evalArray(e.elements)}evalArray(e){const t=e.map(e=>this.eval(e)),n=t=>t.reduce((t,n,r)=>"SpreadElement"===e[r].type?[...t,...n]:(t.push(n),t),[]);return this.isAsync?Promise.all(t).then(n):n(t)}evalBinaryExpression(e){if("||"===e.operator)return this.eval(e.left,t=>t||this.eval(e.right));if("&&"===e.operator)return this.eval(e.left,t=>t&&this.eval(e.right));const t=[this.eval(e.left),this.eval(e.right)],n=([t,n])=>i.binops[e.operator](t,n);return this.isAsync?Promise.all(t).then(n):n(t)}evalCompoundExpression(e){return this.isAsync?e.body.reduce((e,t)=>e.then(()=>this.eval(t)),Promise.resolve()):e.body.map(e=>this.eval(e))[e.body.length-1]}evalCallExpression(e){return this.evalSyncAsync(this.evalCall(e.callee),([t,n])=>this.evalSyncAsync(this.evalArray(e.arguments),r=>t.apply(n===e.callee?this.context:n,r)))}evalCall(e){if("MemberExpression"===e.type)return this.evalSyncAsync(this.evaluateMember(e),([t,n])=>i.validateFnAndCall(n,t,e));if("Identifier"===e.type){const t=r.getValue(this.context,e.name,this.options);return i.validateFnAndCall(t,e)}return this.eval(e,t=>i.validateFnAndCall(t,e))}evalConditionalExpression(e){return this.eval(e.test,t=>this.eval(t?e.consequent:e.alternate))}evalIdentifier(e){if(this.caseSensitive)return r.getValue(this.context,e.name,this.options);if(0===e.name.localeCompare("this","en",{sensitivity:"base"}))return this.evalThisExpression();{const t=r.getLiteralKeyValue(n,e.name,this.options);if(t){const[,e]=t;return e}const i=r.getValue(this.context,e.name,this.options);if(void 0!==i&&this.options.scopes){const t=r.getScopePair(this.context,e.name,this.options);if(t){const[,n]=t;e._scope=n}}return i}}static evalLiteral(e){return e.value}evalMemberExpression(e){return this.evalSyncAsync(this.evaluateMember(e),([,e])=>e)}evaluateMember(e){return this.eval(e.object,n=>this.evalSyncAsync(e.computed?this.eval(e.property):e.property.name,i=>{if(/^__proto__|prototype|constructor$/.test(i))throw Error(`Access to member "${i}" disallowed.`);const s=e.optional?n||{}:n,o=e.object._scope,a=o?t({},this.options,o.options):this.options,l=r.getValue(s,i,a);return[n,l,i]}))}evalThisExpression(){return this.context}evalUnaryExpression(e){return this.eval(e.argument,t=>i.unops[e.operator](t))}evalArrowFunctionExpression(e){return this.isAsync!==e.async?i[e.async?"evalAsync":"eval"](e,this.context):(...t)=>{const n=this.evalArrowContext(e,t);return i[e.async?"evalAsync":"eval"](e.body,n)}}evalArrowContext(e,n){const r=t({},this.context);return(e.params||[]).forEach((e,i)=>{if("AssignmentExpression"===e.type&&(void 0===n[i]&&(n[i]=this.eval(e.right)),e=e.left),"Identifier"===e.type)r[e.name]=n[i];else if("ArrayExpression"===e.type)e.elements.forEach((e,t)=>{let s=n[i][t];if("AssignmentExpression"===e.type&&(void 0===s&&(s=this.eval(e.right)),e=e.left),"Identifier"!==e.type)throw new Error("Unexpected arrow function argument");r[e.name]=s});else if("ObjectExpression"===e.type){const s=[];e.properties.forEach(e=>{let o,a=e;if("AssignmentExpression"===a.type&&(a=a.left),"Property"===a.type)o="Identifier"===a.key.type?a.key.name:this.eval(a.key).toString();else if("Identifier"===a.type)o=a.name;else{if("SpreadElement"!==a.type||"Identifier"!==a.argument.type)throw new Error("Unexpected arrow function argument");o=a.argument.name}let l=n[i][o];"SpreadElement"===a.type?(l=t({},n[i]),s.forEach(e=>{delete l[e]})):void 0===l&&"AssignmentExpression"===e.type&&(l=this.eval(e.right)),r[o]=l,s.push(o)})}else{if("SpreadElement"!==e.type||"Identifier"!==e.argument.type)throw new Error("Unexpected arrow function argument");r[e.argument.name]=n.slice(i)}}),r}evalAssignmentExpression(e){return this.evalSyncAsync(this.getContextAndKey(e.left),([t,n])=>this.eval(e.right,r=>i.assignOps[e.operator](t,n,r)))}evalUpdateExpression(e){return this.evalSyncAsync(this.getContextAndKey(e.argument),([t,n])=>i.evalUpdateOperation(e,t,n))}evalAwaitExpression(e){return i.evalAsync(e.argument,this.context)}static evalUpdateOperation(e,t,n){return e.prefix?"++"===e.operator?++t[n]:--t[n]:"++"===e.operator?t[n]++:t[n]--}getContextAndKey(e){if("MemberExpression"===e.type)return this.evalSyncAsync(this.evaluateMember(e),([e,,t])=>{const n=r.getKeyValue(e,t,this.options),[i]=n||[t,void 0];return[e,i]});if("Identifier"===e.type){const t=r.getKeyValue(this.context,e.name,this.options),[n]=t||[e.name,void 0];return[this.context,n]}if("ConditionalExpression"===e.type)return this.eval(e.test,t=>this.getContextAndKey(t?e.consequent:e.alternate));throw new Error("Invalid Member Key")}evalNewExpression(e){return this.evalSyncAsync(this.evalCall(e.callee),([t])=>this.evalSyncAsync(this.evalArray(e.arguments),n=>i.construct(t,n,e)))}evalObjectExpression(e){const t={},n=e.properties.map(e=>{if("SpreadElement"===e.type)Object.assign(t,i.eval(e.argument,this.context,this.options));else if("Property"===e.type)return this.evalSyncAsync("Identifier"===e.key.type?e.key.name:this.eval(e.key),n=>this.eval(e.shorthand?e.key:e.value,e=>{t[n]=e}))});return this.isAsync?Promise.all(n).then(()=>t):t}evalSpreadElement(e){return this.eval(e.argument)}evalTaggedTemplateExpression(e){const t=[this.evalCall(e.tag),this.evalSyncAsync(this.evalArray(e.quasi.expressions),t=>[e.quasi.quasis.map(e=>e.value.cooked),...t])],n=([[e,t],n])=>e.apply(t,n);return this.isAsync?Promise.all(t).then(n):n(t)}evalTemplateLiteral(e){return this.evalSyncAsync(this.evalArray(e.expressions),t=>e.quasis.reduce((e,n,r)=>(e+=n.value.cooked,n.tail||(e+=t[r]),e),""))}static construct(e,t,n){try{return new(Function.prototype.bind.apply(e,[null].concat(t)))}catch(e){throw new Error(`${i.nodeFunctionName(n.callee)} is not a constructor`)}}static validateFnAndCall(e,t,n){if("function"!=typeof e){if(!e&&n&&n.optional)return[()=>{},t];const r=i.nodeFunctionName(n||t);throw new Error(`'${r}' is not a function`)}return[e,t]}static nodeFunctionName(e){return e&&(e.name||e.property&&e.property.name)}static getKeyValue(e,t,n){return r.getKeyValue(e,t,n)}}i.jsep=e,i.parse=e,i.evaluate=i.eval,i.evaluators={ArrayExpression:i.prototype.evalArrayExpression,LogicalExpression:i.prototype.evalBinaryExpression,BinaryExpression:i.prototype.evalBinaryExpression,CallExpression:i.prototype.evalCallExpression,Compound:i.prototype.evalCompoundExpression,ConditionalExpression:i.prototype.evalConditionalExpression,Identifier:i.prototype.evalIdentifier,Literal:i.evalLiteral,OptionalMemberExpression:i.prototype.evalMemberExpression,MemberExpression:i.prototype.evalMemberExpression,ThisExpression:i.prototype.evalThisExpression,UnaryExpression:i.prototype.evalUnaryExpression,ArrowFunctionExpression:i.prototype.evalArrowFunctionExpression,AssignmentExpression:i.prototype.evalAssignmentExpression,UpdateExpression:i.prototype.evalUpdateExpression,AwaitExpression:i.prototype.evalAwaitExpression,NewExpression:i.prototype.evalNewExpression,ObjectExpression:i.prototype.evalObjectExpression,SpreadElement:i.prototype.evalSpreadElement,TaggedTemplateExpression:i.prototype.evalTaggedTemplateExpression,TemplateLiteral:i.prototype.evalTemplateLiteral},i.conditionalEvaluators={},i.DEFAULT_PRECEDENCE={"||":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10},i.binops={"||":function(e,t){return e||t},"&&":function(e,t){return e&&t},"|":function(e,t){return e|t},"^":function(e,t){return e^t},"&":function(e,t){return e&t},"==":function(e,t){return e==t},"!=":function(e,t){return e!=t},"===":function(e,t){return e===t},"!==":function(e,t){return e!==t},"<":function(e,t){return e<t},">":function(e,t){return e>t},"<=":function(e,t){return e<=t},">=":function(e,t){return e>=t},"<<":function(e,t){return e<<t},">>":function(e,t){return e>>t},">>>":function(e,t){return e>>>t},"+":function(e,t){return e+t},"-":function(e,t){return e-t},"*":function(e,t){return e*t},"/":function(e,t){return e/t},"%":function(e,t){return e%t}},i.unops={"-":function(e){return-e},"+":function(e){return+e},"~":function(e){return~e},"!":function(e){return!e}},i.assignOps={"=":function(e,t,n){return e[t]=n},"*=":function(e,t,n){return e[t]*=n},"**=":function(e,t,n){return e[t]**=n},"/=":function(e,t,n){return e[t]/=n},"%=":function(e,t,n){return e[t]%=n},"+=":function(e,t,n){return e[t]+=n},"-=":function(e,t,n){return e[t]-=n},"<<=":function(e,t,n){return e[t]<<=n},">>=":function(e,t,n){return e[t]>>=n},">>>=":function(e,t,n){return e[t]>>>=n},"&=":function(e,t,n){return e[t]&=n},"^=":function(e,t,n){return e[t]^=n},"|=":function(e,t,n){return e[t]|=n}},i.defaultOptions={caseSensitive:!0};const s=i.DEFAULT_PRECEDENCE,o=i.evaluators,a=i.binops,l=i.unops,p=i.assignOps,c=i.addUnaryOp,u=i.addBinaryOp,y=i.addEvaluator,v=i.registerPlugin,h=i.addOptions,d=i.eval,f=i.evalAsync,m=i.compile,E=i.compileAsync,x=i.evalExpr,g=i.evalExprAsync,A=i.getKeyValue;export{s as DEFAULT_PRECEDENCE,u as addBinaryOp,y as addEvaluator,h as addOptions,c as addUnaryOp,p as assignOps,a as binops,m as compile,E as compileAsync,i as default,f as evalAsync,x as evalExpr,g as evalExprAsync,d as evaluate,o as evaluators,A as getKeyValue,v as registerPlugin,l as unops};
//# sourceMappingURL=jse-eval.modern.js.map