// npm 패키지
@antv/expr
A secure, high-performance expression evaluator for dynamic chart rendering
버전
3
메인테이너
51
라이선스
MIT
최초 publish
2025-03-18
publisher
bqxbqxbqx
tarball
32,979 B
AUTO-PUBLISHED·1개 버전 인덱싱됨·최근 publish: 2025-03-28
// publisher 캠페인by bqxbqxbqx
이 계정에서 catch된 패키지 2건고립된 catch가 아닙니다. 동일 publisher가 1개의 다른 패키지를 추가로 발행했고, 모두 파이프라인이 catch했습니다 — 일회성이 아닌 조직적 캠페인의 형태. 아래 링크는 각 형제 catch의 분석으로 이동합니다.
// offending code· @1.0.2· no static-pattern hits
llm: benign · 0.85→ 의심 전송지 없음, 원격 실행 형태 없음 — 1 known-vendor host(s).
- @1.0.2··AUTO-PUBLISHED·publisher: bqxbqxbqxheuristic 75/100static flags 0llm benign (0.85) via ollamaosv-flagged:MAL-2026-3880
→ 의심 전송지 없음, 원격 실행 형태 없음 — 1 known-vendor host(s).
// offending code· no static-pattern hits
--- install scripts --- ### prepublishOnly pnpm run test && pnpm run build --- package.json (entry) --- { "name": "@antv/expr", "version": "1.0.2", "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 --- bundled output (OSV-MAL flagged — LLM scope expansion) --- --- dist/compile.d.ts (bundled) --- import { type Context } from "./interpreter"; /** * Compile an expression into a reusable function * @param expression - The expression to compile * @returns A function that evaluates the expression with a given context */ export declare function compile(expression: string): (context?: Context) => any; --- dist/error.d.ts (bundled) --- /** * Error class for expression parsing errors. */ export declare class ExpressionError extends Error { readonly position?: number | undefined; readonly token?: string | undefined; constructor(message: string, position?: number | undefined, token?: string | undefined); } --- dist/evaluate.d.ts (bundled) --- import type { Context } from "./interpreter"; /** * Evaluate an expression with a given context * @param expression - The expression to evaluate * @param context - The context to use for evaluation * @returns The result of evaluating the expression */ export declare function evaluate(expression: string, context?: Context): any; --- dist/functions.d.ts (bundled) --- type ExpressionFunction = (...args: any[]) => any; /** * Register a function to be used in expressions with the @ prefix * @param name - The name of the function to register * @param fn - The function implementation */ export declare function register(name: string, fn: ExpressionFunction): void; /** * Get all the registered functions * @returns */ export declare function getFunctions(): Record<string, ExpressionFunction>; export {}; --- dist/index.cjs.js (bundled) --- "use strict";const e={abs:Math.abs,ceil:Math.ceil,floor:Math.floor,max:Math.max,min:Math.min,round:Math.round,sqrt:Math.sqrt,pow:Math.pow};class t extends Error{constructor(e,t,n){super(e),this.position=t,this.token=n,this.name="ExpressionError"}}var n;!function(e){e[e.STRING=0]="STRING",e[e.NUMBER=1]="NUMBER",e[e.BOOLEAN=2]="BOOLEAN",e[e.NULL=3]="NULL",e[e.IDENTIFIER=4]="IDENTIFIER",e[e.OPERATOR=5]="OPERATOR",e[e.FUNCTION=6]="FUNCTION",e[e.DOT=7]="DOT",e[e.BRACKET_LEFT=8]="BRACKET_LEFT",e[e.BRACKET_RIGHT=9]="BRACKET_RIGHT",e[e.PAREN_LEFT=10]="PAREN_LEFT",e[e.PAREN_RIGHT=11]="PAREN_RIGHT",e[e.COMMA=12]="COMMA",e[e.QUESTION=13]="QUESTION",e[e.COLON=14]="COLON",e[e.DOLLAR=15]="DOLLAR"}(n||(n={}));const r=new Set([32,9,10,13]),o=new Set([43,45,42,47,37,33,38,124,61,60,62]),s=new Map([["true",n.BOOLEAN],["false",n.BOOLEAN],["null",n.NULL]]),a=new Map([["===",!0],["!==",!0],["<=",!0],[">=",!0],["&&",!0],["||",!0],["+",!0],["-",!0],["*",!0],["/",!0],["%",!0],["!",!0],["<",!0],[">",!0]]),i=new Map([[46,n.DOT],[91,n.BRACKET_LEFT],[93,n.BRACKET_RIGHT],[40,n.PAREN_LEFT],[41,n.PAREN_RIGHT],[44,n.COMMA],[63,n.QUESTION],[58,n.COLON],[36,n.DOLLAR]]),u=new Map;for(const[e,t]of i.entries())u.set(e,{type:t,value:String.fromCharCode(e)});function c(e){return e>=48&&e<=57}function p(e){return e>=97&&e<=122||e>=65&&e<=90||95===e}function l(e){return p(e)||c(e)}function f(e){return o.has(e)}var E;!function(e){e[e.Program=0]="Program",e[e.Literal=1]="Literal",e[e.Identifier=2]="Identifier",e[e.MemberExpression=3]="MemberExpression",e[e.CallExpression=4]="CallExpression",e[e.BinaryExpression=5]="BinaryExpression",e[e.UnaryExpression=6]="UnaryExpression",e[e.ConditionalExpression=7]="ConditionalExpression"}(E||(E={}));const h=new Map([["||",2],["&&",3],["===",4],["!==",4],[">",5],[">=",5],["<",5],["<=",5],["+",6],["-",6],["*",7],["/",7],["%",7],["!",8]]),d={type:E.Literal,value:null},R={type:E.Literal,value:!0},T={type:E.Literal,value:!1},w=e=>{let r=0;const o=e.length,s=()=>r>=o?null:e[r] --- dist/index.d.ts (bundled) --- export { register } from "./functions"; export { compile } from "./compile"; export { evaluate } from "./evaluate"; export { ExpressionError } from "./error"; --- dist/index.esm.js (bundled) --- const e={abs:Math.abs,ceil:Math.ceil,floor:Math.floor,max:Math.max,min:Math.min,round:Math.round,sqrt:Math.sqrt,pow:Math.pow};function t(t,n){e[t]=n}class n extends Error{constructor(e,t,n){super(e),this.position=t,this.token=n,this.name="ExpressionError"}}var r;!function(e){e[e.STRING=0]="STRING",e[e.NUMBER=1]="NUMBER",e[e.BOOLEAN=2]="BOOLEAN",e[e.NULL=3]="NULL",e[e.IDENTIFIER=4]="IDENTIFIER",e[e.OPERATOR=5]="OPERATOR",e[e.FUNCTION=6]="FUNCTION",e[e.DOT=7]="DOT",e[e.BRACKET_LEFT=8]="BRACKET_LEFT",e[e.BRACKET_RIGHT=9]="BRACKET_RIGHT",e[e.PAREN_LEFT=10]="PAREN_LEFT",e[e.PAREN_RIGHT=11]="PAREN_RIGHT",e[e.COMMA=12]="COMMA",e[e.QUESTION=13]="QUESTION",e[e.COLON=14]="COLON",e[e.DOLLAR=15]="DOLLAR"}(r||(r={}));const o=new Set([32,9,10,13]),a=new Set([43,45,42,47,37,33,38,124,61,60,62]),s=new Map([["true",r.BOOLEAN],["false",r.BOOLEAN],["null",r.NULL]]),i=new Map([["===",!0],["!==",!0],["<=",!0],[">=",!0],["&&",!0],["||",!0],["+",!0],["-",!0],["*",!0],["/",!0],["%",!0],["!",!0],["<",!0],[">",!0]]),u=new Map([[46,r.DOT],[91,r.BRACKET_LEFT],[93,r.BRACKET_RIGHT],[40,r.PAREN_LEFT],[41,r.PAREN_RIGHT],[44,r.COMMA],[63,r.QUESTION],[58,r.COLON],[36,r.DOLLAR]]),c=new Map;for(const[e,t]of u.entries())c.set(e,{type:t,value:String.fromCharCode(e)});function p(e){return e>=48&&e<=57}function l(e){return e>=97&&e<=122||e>=65&&e<=90||95===e}function f(e){return l(e)||p(e)}function E(e){return a.has(e)}var h;!function(e){e[e.Program=0]="Program",e[e.Literal=1]="Literal",e[e.Identifier=2]="Identifier",e[e.MemberExpression=3]="MemberExpression",e[e.CallExpression=4]="CallExpression",e[e.BinaryExpression=5]="BinaryExpression",e[e.UnaryExpression=6]="UnaryExpression",e[e.ConditionalExpression=7]="ConditionalExpression"}(h||(h={}));const d=new Map([["||",2],["&&",3],["===",4],["!==",4],[">",5],[">=",5],["<",5],["<=",5],["+",6],["-",6],["*",7],["/",7],["%",7],["!",8]]),R={type:h.Literal,value:null},T={type:h.Literal,value:!0},w={type:h.Literal,value:!1},y=e=>{let t=0;const o=e.length,a=()=>t>=o --- dist/interpreter.d.ts (bundled) --- import { type Program } from "./parser"; export type Context = Record<string, any>; export type Functions = Record<string, (...args: any[]) => any>; /** * InterpreterState represents the current state of interpretation * @property context - Variables and values available during evaluation * @property functions - Functions available for calling during evaluation */ interface InterpreterState { context: Context; functions: Functions; } /** * Creates a new interpreter state with the provided context and functions * @param context - Initial variable context * @param functions - Available functions * @returns A new interpreter state */ export declare const createInterpreterState: (context?: Context, functions?: Functions) => InterpreterState; /** * Evaluates an AST and returns the result * @param ast - The AST to evaluate * @param state - Current interpreter state * @param context - Optional context to override the default context * @returns The result of evaluation * @example * const ast = parse(tokens); * const result = evaluate(ast, state); */ export declare const evaluateAst: (ast: Program, state: InterpreterState, context?: Context) => unknown; export {}; --- dist/parser.d.ts (bundled) --- import { type Token } from "./tokenizer"; /** * All possible node types in the Abstract Syntax Tree (AST) * - Program: Root node of the AST * - Literal: Constants (numbers, strings, booleans, null) * - Identifier: Variable and property names * - MemberExpression: Property access (dot or bracket notation) * - CallExpression: Function invocation * - BinaryExpression: Operations with two operands * - UnaryExpression: Operations with one operand * - ConditionalExpression: Ternary operator expressions */ export declare enum NodeType { Program = 0, Literal = 1, Identifier = 2, MemberExpression = 3, CallExpression = 4, BinaryExpression = 5, UnaryExpression = 6, ConditionalExpression = 7 } /** * Base interface for all AST nodes * Every node must have a type property identifying its kind */ export interface Node { type: NodeType; } /** * Root node of the AST * Contains a single expressi
