Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @antv/expr
# @antv/expr ![gzip size](https://img.badgesize.io/https://unpkg.com/@antv/expr/dist/index.esm.js?compression=gzip)

Have you ever wanted to make your SSR charts more dynamic but worried about security risks?

Expand All @@ -9,7 +9,7 @@ We've got you covered! Our solution introduces an easy-to-use template syntax th
- 🔒 **Secure by default** - No access to global objects or prototype chain, does not use `eval` or `new Function`.
- 🚀 **High performance** - Supports pre-compilation of expressions for improved performance with repeated evaluations.
- 🛠️ **Extensible** - Register custom functions to easily extend functionality.
- 🪩 **Lightweight** - Zero dependencies, small footprint, only `7.8 Kb` before gzip.
- 🪩 **Lightweight** - Zero dependencies, small footprint, before gzip it was less than `8 Kb`.


## 📥 Installation
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@antv/expr",
"version": "1.0.0",
"version": "1.0.1",
"description": "A secure, high-performance expression evaluator for dynamic chart rendering",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
Expand All @@ -10,7 +10,7 @@
"build": "rollup -c",
"test": "vitest run --coverage",
"benchmark": "vitest bench",
"prepublishOnly": "npm run build"
"prepublishOnly": "pnpm run test && pnpm run build"
},
"keywords": [
"expression",
Expand Down
5 changes: 1 addition & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,13 @@ function compile(
// biome-ignore lint/suspicious/noExplicitAny: Return type depends on the expression
return (context: Context = {}): any => {
try {
// Execute the evaluation with timeout protection
return evaluateAst(ast, interpreterState, context);
} catch (error) {
if (error instanceof ExpressionError) {
throw error;
}

if (error instanceof Error) {
throw new ExpressionError(error.message);
}
// Pass through other errors without wrapping them
throw error;
}
};
Expand Down
52 changes: 22 additions & 30 deletions src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,9 @@ export const evaluateAst = (

switch (node.operator) {
case "+":
if (typeof left === "number" && typeof right === "number") {
return left + right;
}
return String(left) + String(right);
// For addition, handle both numeric addition and string concatenation
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
return (left as any) + (right as any);
case "-":
return (left as number) - (right as number);
case "*":
Expand Down Expand Up @@ -224,32 +223,25 @@ export const evaluateAst = (
* @returns The result of evaluation
*/
const evaluateNode = (node: Expression): unknown => {
try {
switch (node.type) {
case NodeType.Literal:
return evaluateLiteral(node);
case NodeType.Identifier:
return evaluateIdentifier(node);
case NodeType.MemberExpression:
return evaluateMemberExpression(node);
case NodeType.CallExpression:
return evaluateCallExpression(node);
case NodeType.BinaryExpression:
return evaluateBinaryExpression(node);
case NodeType.UnaryExpression:
return evaluateUnaryExpression(node);
case NodeType.ConditionalExpression:
return evaluateConditionalExpression(node);
default:
throw new ExpressionError(
`Unsupported node type: ${(node as Expression).type}`,
);
}
} catch (error) {
if (error instanceof ExpressionError) {
throw new ExpressionError(`Evaluation error: ${error.message}`);
}
throw error;
switch (node.type) {
case NodeType.Literal:
return evaluateLiteral(node);
case NodeType.Identifier:
return evaluateIdentifier(node);
case NodeType.MemberExpression:
return evaluateMemberExpression(node);
case NodeType.CallExpression:
return evaluateCallExpression(node);
case NodeType.BinaryExpression:
return evaluateBinaryExpression(node);
case NodeType.UnaryExpression:
return evaluateUnaryExpression(node);
case NodeType.ConditionalExpression:
return evaluateConditionalExpression(node);
default:
throw new ExpressionError(
`Evaluation error: Unsupported node type: ${(node as Expression).type}`,
);
}
};

Expand Down
2 changes: 1 addition & 1 deletion tests/coverage-improvement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe("Coverage Improvement Tests", () => {
};

expect(() => evaluateAst(ast, interpreterState, {})).toThrow(
"Evaluation error: Postfix operators are not supported: ~",
"Postfix operators are not supported: ~",
);
});
});
Expand Down
Loading