Git Product home page Git Product logo

expression-eval's Introduction

expression-eval

Latest NPM release Minzipped size License CI

JavaScript expression parsing and evaluation.

⚠️ UNMAINTAINED: The expression-eval npm package is no longer maintained. The package was originally published as part of a now-completed personal project, and I do not have incentives to continue maintenance. Please feel free to use the code, but be aware that support and updates will not be available.

⚠️ SECURITY NOTICE: As mentioned under Security below, this library does not attempt to provide a secure sandbox for evaluation. Evaluation involving user inputs (expressions or values) may lead to unsafe behavior. If your project requires a secure sandbox, consider alternatives such as vm2.

Powered by jsep.

Installation

Install:

npm install --save expression-eval

Import:

// ES6
import { parse, eval } from 'expression-eval';
// CommonJS
const { parse, eval } = require('expression-eval');
// UMD / standalone script
const { parse, eval } = window.expressionEval;

API

Parsing

import { parse } from 'expression-eval';
const ast = parse('1 + foo');

The result of the parse is an AST (abstract syntax tree), like:

{
  "type": "BinaryExpression",
  "operator": "+",
  "left": {
    "type": "Literal",
    "value": 1,
    "raw": "1"
  },
  "right": {
    "type": "Identifier",
    "name": "foo"
  }
}

Evaluation

import { parse, eval } from 'expression-eval';
const ast = parse('a + b / c'); // abstract syntax tree (AST)
const value = eval(ast, {a: 2, b: 2, c: 5}); // 2.4

Alternatively, use evalAsync for asynchronous evaluation.

Compilation

import { compile } from 'expression-eval';
const fn = compile('foo.bar + 10');
fn({foo: {bar: 'baz'}}); // 'baz10'

Alternatively, use compileAsync for asynchronous compilation.

Security

Although this package does avoid the use of eval(), it cannot guarantee that user-provided expressions, or user-provided inputs to evaluation, will not modify the state or behavior of your application. This library does not attempt to provide a secure sandbox for evaluation. Evaluation of arbitrary user inputs (expressions or values) may lead to unsafe behavior. If your project requires a secure sandbox, consider alternatives such as vm2.

License

MIT License.

expression-eval's People

Contributors

dependabot[bot] avatar donmccurdy avatar dreamdevil00 avatar eight04 avatar goobles avatar hafizjef avatar johnarrowwood avatar josh-hemphill avatar kamikadze4game avatar nodece avatar probil avatar rbayliss avatar skermes avatar ubreddy avatar yoshino-s avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

expression-eval's Issues

Possible arbitrary code execution

Althrough we have decleared in the README.MD that do not use this package with user-provided inputs, but after i exam some project with this project, i found that many developers still use in that way, which may lead to some serious security problem. So I think that we still need to do some basic thing to prevent some dangerous action in the package itself.

I have made a tiny fix to prevent access prototype on object, which may prevent all prototype pollution and code execution.

418sec#1

Should we use this fix or just ignore the possible vuln?

Expression Eval fails on nested functions

I have an expression that retrieves the String stored in an index of an Array. The index is obtained as a result of a function call...

User.address[ User.getCurrentAddressIndex() ]

The evaluator fails in the described scenario, returning undefined.

const expr = require('expression-eval');
const ast = expr.parse( 'User.address[ User.getCurrentAddressIndex() ]' );
const User:{
  address:[
    'mystreet, num 23',
    'myOtherStreet, num 222',
  ],
  getCurrentAddressIndex: function(){ return 1 }
}
const address = expr.eval(ast, {User : User} );  
// Expected : 'myOtherStreet, num 222'
// Returned : undefined

Changelog?

Just saw that the version bumps to 4.0.0. Is there any breaking change compared to v3.1.2?

Request support for CallExpression node type

I'm creating an application that lets me declare variables and assign them expressions. I'd like to be able to support expressions like random.int(min,max) or random.guid() and have it evaluate as you might expect.

Unfortunately, the evaluation engine ignores nodes of type CallExpression.

Is there any reason why it would be a bad idea for me to initialize certain names to functions so that they can be used in an expression?

The processing of floating-point numbers failed

The processing of floating-point numbers failed

console.log('---------tesst');
const ast4 = parse('a * b +c *9.9');
const value4 = eval(ast4, {a: 5, b: 2, c: 4.9});
console.log(ast4);
console.log(value4);

----------------result---------
image
How do we ensure that floating-point number calculations are normal digits

jsep dependency error while using expression-eval

From TypeScript ('esnext' module), when trying to use expression-eval:

import {parse} from "expression-eval";
  
evalVariable(varName: string) {
    let ast = parse(varName);
    console.log("ast=" + ast);
}

I get the following error in the console:
Uncaught SyntaxError: The requested module '../../jsep/build/jsep.js' does not provide an export named 'default'

context of expression ?

Hello,

I need to use this package to evaluate expression for vue.js schema form builder.
My question is how can I set context of the expression? I mean to access to data model for example.

I've tried the following and it works

const fn = compile("value.source=='ldap'")
fn({ value : this.value })

but do it possible to a set default context like this ?

const fn = compile("source=='ldap'")
fn({ undefined : this.value })

Regards

Support optional-chain-like behavior for context objects

I found the need for accessing deep properties on the context which may be undefined. This module currently will throw when trying to access those properties; a behavior that treats the deep object access similar to an optional chain seemed like a good solution.

Writing this to highlight the PR (#48) I submitted a couple days ago, in the event it was missed, or anybody not checking out the PRs wanted to chime in.

Thanks for the great project here!

Use correct thisArg when evaluating CallExpression

const expr = require("expression-eval");
console.log(expr.compile("a.slice()")({a: "foo"}));

Result:

D:\Dev\node-test\node_modules\expression-eval\index.js:56
        return fn.apply( null, evaluate_array( node.arguments, context ) );
                  ^

TypeError: String.prototype.slice called on null or undefined
    at slice (native)
    at evaluate (D:\Dev\node-test\node_modules\expression-eval\index.js:56:19)
    at Object.<anonymous> (D:\Dev\node-test\test.js:2:38)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:423:7)

Library still not fully ES5-compatible

First of all, thanks for the library @donmccurdy It's nice 💪

But I got an issue with it.
You have made ES5-compatible code in 1.2.1 but that work is not done yet.

1) let and const operator usage in the code

44 |  const object = evaluate(node.object, context);
63 |  let caller, fn;

Use var instead, because let and const was introduced as part of ES6 specification.

2) Destructors usage
Destructors are also part of ES6 spec. The only usage is here:

65 |  [ caller, fn ] = evaluateMember( node.callee, context );

Compare code with and without ES6 here: https://www.diffchecker.com/fDsmMQV5
I've made ES6->ES5 using Bublé: https://buble.surge.sh

If you'd like to use ES6 in your code let's precompile it with babel. I can help you with that if you wish :)

Remove dist/ folder

Including the dist/ folder in source control is a regular source of confusion for new contributors, because the files are modified when building or testing changes, but shouldn't be included in PRs. These files cannot be reviewed easily, and are meant to be rebuilt by an author when publishing a new release. To avoid this confusion, the dist/ folder should be added to .gitignore and explicitly added to the published files in package.json. Because it's published to NPM, it will still be available from CDNs like Unpkg.

Using addBinaryOp causes some expressions to fail to parse

The addBinaryOp in expression-eval doesn't set the precedence parameter when it calls addBinaryOp in jsep, which will make some valid expressions raise an exception while parsing. This can be worked around by calling jsep.addBinaryOp as well, but it would be better to not have to do that.

Reproduction:

> ee = require('expression-eval')
> ee.parse('(1 + 2 + 3)')           // This returns a valid AST
> ee.addBinaryOp('+', (a, b) => a + b + 1)
> ee.parse('(1 + 2 + 3)')          // This raises an exception about a missing close paren
> ee.parse.addBinaryOp('+', 9)
> ee.parse('(1 + 2 + 3)')          // This returns a valid AST again 

Unfortunately from glancing at the jsep source it looks like the binary_ops dictionary is stuck inside a closure so there isn't an easy way to use it as a source of default precedence values.

NPE

const ast = parse('object.id === 1');
const context = {object: null};//
console.log( eval(ast, context)); // Error: cannot read property

Some fields in context may be null, because you can form it dynamic.
Maybe it better use optional-chaining operator in eval method

Thanks

How to call async functions in an expression?

Thanks for this good project! In my scenario, I need to put async functions into expression. But I don't know how to do this. It seems that jsep doesn't support sync functions?

The following code generates async functions which will be injected into the expression:

https://github.com/casbin/node-casbin/blob/e40a13ffd8fbb2d924f36541beb24b3a02593261/src/util/builtinOperators.ts#L138-L153

The following code shows how the above async functions are injected:

https://github.com/casbin/node-casbin/blob/504047efd9317550e223680a4a81dc046fe63848/src/coreEnforcer.ts#L253-L311

Wrong results when using exponent symbol (^) in expression

Hello, I've noticed that the result of my expressions seems wrong when using the exponent symbol (^):

const foo = { a: 1, b: 2, c: 3 };

console.log(evaluate(parse("10 + (2 ^ a)"), foo)); // expected: 12, result: 13
console.log(evaluate(parse("10 + (2 ^ b)"), foo)); // expected: 14, result: 10
console.log(evaluate(parse("10 + (2 ^ c)"), foo)); // expected: 18, result: 11

Reproducible codesandbox: https://codesandbox.io/s/expression-eval-exponent-zof7gt?file=/src/index.js:0-350

Question: support for new JSEP plugin system (and new node types)

I've been helping to update jsep (PR) to allow for plugins to extend it further. It's not quite released yet, but it adds the option of numerous supplied plugins, so that it can support things like arrow-function, template-literals, objects, etc.

I wonder if expression-eval could be made extensible to support new node types? I was thinking that one option might be converting the switch statement to a map of { [key: keyof ExpressionType]: (node: Expression, context?: object) => any perhaps? Or perhaps another way to allow users to add evaluators for arbitrary node types?

I could also help with support for some of the new node types if wanted?

Doesnt work change filename

Hello,

I try use on firefox change to ${index-1} - ${name}${ext}, and images downloaded with name like this:
undefined - EmbeddedRelated_smalltab.jpg

How i can fix, to change start from 0, or something else number?

0 - EmbeddedRelated_smalltab.jpg
100 - EmbeddedRelated_smalltab.jpg

Sorry for my pure english.

Is parse considered safe?

Do you consider parse to be safe enough to run on the server? The use-case is to run expression-eval parse but not eval before vm2 does parsing and evaluating. The purpose is to ensure the server-side expressions are only valid if they are valid on the client, and also to help reduce the chance of hitting a security vulnerability in vm2.

Typescript compile errors

Using the latest version (3.1.0) the following typescript errors are generated from simple app.

$ tsc
node_modules/expression-eval/index.d.ts:7:41 - error TS1138: Parameter declaration expected.
7 declare function addUnaryOp(op: string, (a: any) => any): void;

node_modules/expression-eval/index.d.ts:7:56 - error TS1005: ';' expected.
7 declare function addUnaryOp(op: string, (a: any) => any): void;

node_modules/expression-eval/index.d.ts:7:57 - error TS1128: Declaration or statement expected.
7 declare function addUnaryOp(op: string, (a: any) => any): void;

node_modules/expression-eval/index.d.ts:7:63 - error TS1109: Expression expected.
7 declare function addUnaryOp(op: string, (a: any) => any): void;

node_modules/expression-eval/index.d.ts:8:42 - error TS1138: Parameter declaration expected.
8 declare function addBinaryOp(op: string, (a: any, b: any) => any): void;

node_modules/expression-eval/index.d.ts:8:65 - error TS1005: ';' expected.
8 declare function addBinaryOp(op: string, (a: any, b: any) => any): void;

node_modules/expression-eval/index.d.ts:8:66 - error TS1128: Declaration or statement expected.
8 declare function addBinaryOp(op: string, (a: any, b: any) => any): void;


node_modules/expression-eval/index.d.ts:8:72 - error TS1109: Expression expected.
8 declare function addBinaryOp(op: string, (a: any, b: any) => any): void;

Found 8 errors.
error Command failed with exit code 2.

Here is the project
ts-example.zip

This change in index.d.ts fixed the compile errors:

type ff = (a: any) => any
declare function addUnaryOp(op: string, ff): void;
type fff = (a: any, b: any) => any
declare function addBinaryOp(op: string, fff): void;

Eval collision in examples

In the change to the readme 28feab5 you show destructuring the functions instead of leaving it in an object. This would cause expression-eval eval() to replace the native eval().

Fast eval

When there are || conditions, can we have the evaluation not evaluate the right side of || if left is already true?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.