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
176 changes: 88 additions & 88 deletions bench/expr.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@ import { bench, describe } from "vitest";
import { compile, evaluate, register } from "../dist/index.esm.js";

const context = {
user: {
name: "John",
age: 30,
isAdmin: true,
scores: [85, 90, 78, 92],
address: {
city: "New York",
zip: "10001",
},
},
products: [
{ id: 1, name: "Laptop", price: 1200 },
{ id: 2, name: "Phone", price: 800 },
{ id: 3, name: "Tablet", price: 500 },
],
calculateTotal: (items: any[]) => {
const total = items.reduce((sum, item) => sum + item.price, 0);
return total;
},
applyDiscount: (total: number, percentage: number) => {
const value = total * (1 - percentage / 100);
return value;
},
user: {
name: "John",
age: 30,
isAdmin: true,
scores: [85, 90, 78, 92],
address: {
city: "New York",
zip: "10001",
},
},
products: [
{ id: 1, name: "Laptop", price: 1200 },
{ id: 2, name: "Phone", price: 800 },
{ id: 3, name: "Tablet", price: 500 },
],
calculateTotal: (items: any[]) => {
const total = items.reduce((sum, item) => sum + item.price, 0);
return total;
},
applyDiscount: (total: number, percentage: number) => {
const value = total * (1 - percentage / 100);
return value;
},
};

const simpleExpression = "user.age + 5";
const mediumExpression = 'user.scores[2] > 80 ? "Good" : "Needs improvement"';
const complexExpression =
'@applyDiscount(@calculateTotal(products), 10) > 2000 ? "High value" : "Standard"';
'@applyDiscount(@calculateTotal(products), 10) > 2000 ? "High value" : "Standard"';

const complexExpression2 =
'applyDiscount(calculateTotal(products), 10) > 2000 ? "High value" : "Standard"';
'applyDiscount(calculateTotal(products), 10) > 2000 ? "High value" : "Standard"';

const simpleExpressionCompiler = compile(simpleExpression);
const mediumExpressionCompiler = compile(mediumExpression);
Expand All @@ -48,80 +48,80 @@ parser.functions.calculateTotal = context.calculateTotal;
parser.functions.applyDiscount = context.applyDiscount;

const newFunctionSimple = new Function(
"context",
`with(context) { return ${simpleExpression}; }`,
"context",
`with(context) { return ${simpleExpression}; }`,
);
const newFunctionMedium = new Function(
"context",
`with(context) { return ${mediumExpression}; }`,
"context",
`with(context) { return ${mediumExpression}; }`,
);
const newFunctionComplex = new Function(
"context",
`with(context) { return ${complexExpression2}; }`,
"context",
`with(context) { return ${complexExpression2}; }`,
);

describe("Simple Expression Benchmarks", () => {
bench("evaluate after compile (baseline) only interpreter", () => {
simpleExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionSimple(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(simpleExpression, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
Parser.evaluate(simpleExpression, context);
});
bench("evaluate after compile (baseline) only interpreter", () => {
simpleExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionSimple(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(simpleExpression, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
Parser.evaluate(simpleExpression, context);
});
});

describe("Medium Expression Benchmarks", () => {
bench("evaluate after compile (baseline) only interpreter", () => {
mediumExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionMedium(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(mediumExpression, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
Parser.evaluate(mediumExpression, context);
});
bench("evaluate after compile (baseline) only interpreter", () => {
mediumExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionMedium(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(mediumExpression, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
Parser.evaluate(mediumExpression, context);
});
});

describe("Complex Expression Benchmarks", () => {
bench("evaluate after compile (baseline) only interpreter", () => {
complexExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionComplex(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(complexExpression2, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
parser.evaluate(complexExpression2, context);
});
bench("evaluate after compile (baseline) only interpreter", () => {
complexExpressionCompiler(context);
});

bench("new Function (vs evaluate)", () => {
newFunctionComplex(context);
});

bench(
"evaluate without compile (vs evaluate) tokenize + parse + interpreter",
() => {
evaluate(complexExpression2, context);
},
);

bench("expr-eval Parser (vs evaluate)", () => {
// @ts-ignore
parser.evaluate(complexExpression2, context);
});
});
59 changes: 30 additions & 29 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["dist", "node_modules", "coverage"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"ignore": ["node_modules", "dist", "tests", "bench", "coverage"]
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["dist", "node_modules", "coverage"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"ignore": ["node_modules", "dist", "tests", "bench", "coverage"]
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}
89 changes: 51 additions & 38 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,53 @@
{
"name": "@antv/expr",
"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",
"types": "dist/index.d.ts",
"files": ["dist", "LICENSE", "README.md", "package.json"],
"scripts": {
"build": "rollup -c",
"test": "vitest run --coverage",
"benchmark": "vitest bench",
"prepublishOnly": "pnpm run test && pnpm run build"
},
"keywords": [
"expression",
"evaluator",
"parser",
"secure",
"antv",
"chart",
"expr"
],
"repository": {
"type": "git",
"url": "https://github.com/antvis/expr"
},
"license": "MIT",
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.2",
"@vitest/coverage-v8": "^3.0.8",
"expr-eval": "^2.0.2",
"rollup": "^4.34.6",
"tslib": "^2.8.1",
"vitest": "^3.0.8"
}
"name": "@antv/expr",
"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",
"types": "dist/index.d.ts",
"files": ["dist", "LICENSE", "README.md", "package.json"],
"scripts": {
"build": "rollup -c && npm run size",
"test": "vitest run --coverage",
"size": "limit-size",
"benchmark": "vitest bench",
"prepublishOnly": "pnpm run test && pnpm run build"
},
"keywords": [
"expression",
"evaluator",
"parser",
"secure",
"antv",
"chart",
"expr"
],
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.2",
"@vitest/coverage-v8": "^3.0.8",
"expr-eval": "^2.0.2",
"limit-size": "^0.1.4",
"rollup": "^4.34.6",
"tslib": "^2.8.1",
"vitest": "^3.0.8"
},
"limit-size": [
{
"path": "dist/index.cjs.js",
"limit": "8 Kb"
},
{
"path": "dist/index.cjs.js",
"limit": "3 Kb",
"gzip": true
}
],
"repository": {
"type": "git",
"url": "https://github.com/antvis/expr"
},
"license": "MIT"
}
Loading
Loading