
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@antv/expr
Advanced tools
A secure, high-performance expression evaluator for dynamic chart rendering
Lightweight JavaScript expression parser and evaluator, safety and high-performance. 🚀
Used to parse a mathematical expressions to JavaScript function safely. For example, in @antv/g2, we can set the style with an expressions.
{
// Equivalent to function: `d => d.value > 100 ? 'red' : 'green'`
fill: "{ d.value > 100 ? 'red' : 'green' }",
}
eval or new Function.8 Kb.npm install @antv/expr
# or
yarn add @antv/expr
# or
pnpm add @antv/expr
import { evaluate } from '@antv/expr';
// Basic evaluation
const result = evaluate('x + y', { x: 10, y: 20 }); // returns 30
// Using dot notation and array access
const data = {
values: [1, 2, 3],
status: 'active'
};
const result = evaluate('data.values[0] + data.values[1]', { data }); // returns 3
import { compile } from '@antv/expr';
// Compile an expression
const evaluator = compile('price * quantity');
const result1 = evaluator({ price: 10, quantity: 5 }); // returns 50
const result2 = evaluator({ price: 20, quantity: 3 }); // returns 60
import { register, evaluate } from '@antv/expr';
// Register functions
register('formatCurrency', (amount) => `$${amount.toFixed(2)}`);
// Function call with arguments
const result = evaluate('@max(a, b, c)', { a: 5, b: 9, c: 2 }); // returns 9
// Expression as function arguments
const result = evaluate('@formatCurrency(price * quantity)', {
price: 10.5, quantity: 3
}); // returns '$31.50'
Build-in Functions: abs, ceil, floor, round, sqrt, pow, max, min.
// Simple variable reference
const result = evaluate('x', { x: 42 }); // returns 42
// Nested property access with dot notation
const result = evaluate('user.profile.name', {
user: { profile: { name: 'John' } }
}); // returns 'John'
// Array access with bracket notation
const result = evaluate('items[0]', { items: [10, 20, 30] }); // returns 10
// Mixed dot and bracket notation
const result = evaluate('data.items[0].value', {
data: { items: [{ value: 42 }] }
}); // returns 42
// Basic arithmetic
const result = evaluate('a + b * c', { a: 5, b: 3, c: 2 }); // returns 11
// Using parentheses for grouping
const result = evaluate('(a + b) * c', { a: 5, b: 3, c: 2 }); // returns 16
// Modulo operation
const result = evaluate('a % b', { a: 10, b: 3 }); // returns 1
// Comparison operators
const result = evaluate('age >= 18', { age: 20 }); // returns true
// Logical AND
const result = evaluate('isActive && !isDeleted', {
isActive: true, isDeleted: false
}); // returns true
// Logical OR
const result = evaluate('status === "active" || status === "pending"', {
status: 'pending'
}); // returns true
// Simple ternary expression
const result = evaluate('age >= 18 ? "adult" : "minor"', {
age: 20
}); // returns 'adult'
// Nested ternary expressions
const result = evaluate('score >= 90 ? "A" : score >= 80 ? "B" : "C"', {
score: 85
}); // returns 'B'
You can implement timeout handling by wrapping your evaluation in a Promise.race with a timeout:
import { evaluate } from "@antv/expr";
// Create a function that evaluates with a timeout
function evaluateWithTimeout(expr, context, timeoutMs) {
const evaluationPromise = new Promise((resolve) => {
resolve(evaluate(expr, context));
});
const timeoutPromise = new Promise((_, reject) => {
setTimeout(
() => reject(new Error(`Evaluation timed out after ${timeoutMs}ms`)),
timeoutMs,
);
});
return Promise.race([evaluationPromise, timeoutPromise]);
}
Performance comparison of different evaluation methods: (baseline: new Function)
| Expression Type | new Function vs evaluate after compile | new Function vs evaluate without compile | new Function vs expr-eval Parser |
|---|---|---|---|
| Simple Expressions | 1.59x faster | 6.36x faster | 23.94x faster |
| Medium Expressions | 2.16x faster | 9.81x faster | 37.81x faster |
| Complex Expressions | 1.59x faster | 4.89x faster | 32.74x faster |
gantt
title Performance Comparison (Baseline: new Function) * 100
dateFormat X
axisFormat %s
section Simple
expr evaluate after compile :done, 0, 159
expr evaluate without compile :done, 0, 636
expr-eval Parser :done, 0, 2394
section Medium
expr evaluate after compile :done, 0, 216
expr evaluate without compile :done, 0, 981
expr-eval Parser :done, 0, 3781
section Complex
expr evaluate after compile :done, 0, 159
expr evaluate without compile :done, 0, 489
expr-eval Parser :done, 0, 3274
evaluate(expression: string, context?: object): anySynchronously evaluates an expression and returns the result.
expression: The expression string to evaluatecontext: An object containing variables used in the expression (optional)compile(expression: string): (context?: object) => anySynchronously compiles an expression, returning a function that can be used multiple times.
expression: The expression string to compileregister(name: string, fn: Function): voidRegisters a custom function that can be used in expressions.
name: Function name (used with @ prefix in expressions)fn: Function implementationAll evaluation errors throw an ExpressionError type exception with detailed error information.
MIT
FAQs
A secure, high-performance expression evaluator for dynamic chart rendering
We found that @antv/expr demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 67 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.