Skip to content

Latest commit

 

History

History
146 lines (108 loc) · 4.61 KB

File metadata and controls

146 lines (108 loc) · 4.61 KB

Breaking Changes

This document lists breaking changes in the library to help users migrate between versions.

Version 6.0.0

null is no longer silently casted to 0. This means that from version 6 onwards, null == 0 will no longer be true and null == someVariable with someVariable having a null value will become true. (This was not the case before.)

Version 5.0.0

Security: Functions Must Be Registered Explicitly

Background: This change addresses critical security vulnerabilities:

What Changed: Functions can no longer be passed directly via the evaluation context. All functions that need to be called from expressions must be explicitly registered in parser.functions.

Before (Vulnerable):

const parser = new Parser();

// This pattern is NO LONGER ALLOWED
parser.evaluate('customFunc()', { customFunc: () => 'result' });

// This also NO LONGER WORKS
parser.evaluate('obj.method()', { 
  obj: { 
    method: () => 'dangerous' 
  } 
});

After (Secure):

const parser = new Parser();

// Register functions explicitly
parser.functions.customFunc = () => 'result';
parser.evaluate('customFunc()');

// For methods on objects, register them as top-level functions
parser.functions.objMethod = () => 'safe';
parser.evaluate('objMethod()');

What Still Works:

  • Passing primitive values (strings, numbers, booleans) via context
  • Passing arrays and objects with non-function properties via context
  • Using built-in Math functions (sin, cos, sqrt, etc.)
  • Using inline-defined functions in expressions: (f(x) = x * 2)(5)
  • Using functions registered in parser.functions

Migration Guide:

  1. Identify function usage: Search your codebase for patterns like evaluate('...', { fn: ... }) where fn is a function.

  2. Register functions before evaluation:

    // Before
    parser.evaluate('calculate(x)', { calculate: myFunc, x: 5 });
    
    // After
    parser.functions.calculate = myFunc;
    parser.evaluate('calculate(x)', { x: 5 });
  3. For dynamic functions: If you need to register functions dynamically:

    const parser = new Parser();
    parser.functions.dynamicFn = createDynamicFunction();
    const result = parser.evaluate('dynamicFn()');
    delete parser.functions.dynamicFn; // Clean up if needed

Protected Properties

Access to the following properties is now blocked to prevent prototype pollution attacks:

  • __proto__
  • prototype
  • constructor

Attempting to access these properties in variable names or member expressions will throw an AccessError.

Example:

// These will throw AccessError
parser.evaluate('x.__proto__', { x: {} });
parser.evaluate('__proto__', { __proto__: {} });

Version 4.0.0

Concatenation Operator Changed from || to |

What Changed: The || operator was repurposed for logical OR (JavaScript-style). A new | (pipe) operator was introduced for array and string concatenation. Additionally, the && operator was added for logical AND.

Before (original expr-eval 2.x):

// || was used for concatenation
parser.evaluate('"hello" || " world"');  // "hello world"
parser.evaluate('[1, 2] || [3, 4]');     // [1, 2, 3, 4]

After (v4.0.0+):

// | is now used for concatenation
parser.evaluate('"hello" | " world"');   // "hello world"
parser.evaluate('[1, 2] | [3, 4]');      // [1, 2, 3, 4]

// || is now logical OR
parser.evaluate('true || false');        // true
parser.evaluate('false || true');        // true

// && is logical AND (new)
parser.evaluate('true && false');        // false
parser.evaluate('true && true');         // true

Migration Guide:

  1. Find concatenation usage: Search your expressions for || used with strings or arrays
  2. Replace with pipe: Change || to | for concatenation operations
  3. Review logical operations: If you were using or keyword, you can now also use ||

Package Renamed

The package was renamed from expr-eval to @pro-fa/expr-eval and ported to TypeScript.

# Remove old package
npm uninstall expr-eval

# Install new package
npm install @pro-fa/expr-eval

Update imports:

// Before
const { Parser } = require('expr-eval');

// After
import { Parser } from '@pro-fa/expr-eval';