{"id":15893,"library":"vega-expression","title":"Vega Expression Parser and Code Generator","description":"vega-expression is a JavaScript/TypeScript library that provides a secure and configurable expression parser and code generator, forming a core component of the broader Vega visualization toolkit. It processes a limited subset of JavaScript expressions into an Abstract Syntax Tree (AST) and then generates `eval`'able JavaScript code. The library intentionally restricts language features like assignment operators, `new` expressions, and control flow to prioritize security and prevent unwanted side effects, making it suitable for user-provided expressions in visualization contexts. It is currently in active development, with version 6.2.0 as the latest stable release at the time of this entry, following a fairly active release cadence that often aligns with the larger Vega monorepo. Its key differentiators include its security-first approach, a stripped-down Esprima-based parser, and highly configurable code generation options for managing constants, functions, and variable scopes, including tracking data field dependencies.","status":"active","version":"6.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/vega/vega","tags":["javascript","vega","expression","parser","codegen","typescript"],"install":[{"cmd":"npm install vega-expression","lang":"bash","label":"npm"},{"cmd":"yarn add vega-expression","lang":"bash","label":"yarn"},{"cmd":"pnpm add vega-expression","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides additional custom functions beyond the basic utilities, many specific to Vega dataflows.","package":"vega-functions","optional":false}],"imports":[{"note":"Vega v6.0.0 and above are ESM-only. Use `import` statements. For older v5.x versions, CommonJS `require` was standard.","wrong":"const parse = require('vega-expression').parse;","symbol":"parse","correct":"import { parse } from 'vega-expression';"},{"note":"Vega v6.0.0 and above are ESM-only. Use `import` statements. `codegen` is a function that returns a generator function.","wrong":"const codegen = require('vega-expression').codegen;","symbol":"codegen","correct":"import { codegen } from 'vega-expression';"},{"note":"Explicit type import for TypeScript users to define options passed to `codegen`.","symbol":"CodegenOptions","correct":"import type { CodegenOptions } from 'vega-expression';"}],"quickstart":{"code":"import { parse, codegen } from 'vega-expression';\n\ninterface DataItem {\n  value: number;\n  category: string;\n}\n\n// 1. Define the expression string\nconst expressionString = \"datum.value * 2 + 5\";\n\n// 2. Parse the expression into an AST\nconst ast = parse(expressionString);\nconsole.log('Parsed AST:', JSON.stringify(ast, null, 2));\n\n// 3. Create a code generator, specifying the field variable ('datum' in this case)\n//    and any allowed globals/functions if needed.\nconst generator = codegen({\n  fieldvar: 'datum',\n  allowed: ['datum'], // 'datum' is an allowed variable in the expression scope\n  // You can also provide custom functions or constants\n  functions: () => ({\n    pow: (args: any[]) => `Math.pow(${args[0]}, ${args[1]})`\n  })\n});\n\n// 4. Generate the executable code from the AST\nconst { code, fields, globals } = generator(ast);\nconsole.log('\\nGenerated Code:', code);\nconsole.log('Referenced Fields:', fields);\nconsole.log('Referenced Globals:', globals);\n\n// 5. Evaluate and use the generated function\n//    NOTE: Using `Function` constructor is generally discouraged due to CSP issues.\n//          For Vega runtime, `vega-interpreter` offers CSP-compliant evaluation.\nconst evaluateExpression = new Function('datum', `return ${code};`);\n\nconst sampleData: DataItem = { value: 10, category: 'A' };\nconst result = evaluateExpression(sampleData);\nconsole.log(`\\nResult for { value: 10 } (10 * 2 + 5):`, result); // Expected: 25\n\nconst anotherData: DataItem = { value: 7, category: 'B' };\nconst anotherResult = evaluateExpression(anotherData);\nconsole.log(`Result for { value: 7 } (7 * 2 + 5):`, anotherResult); // Expected: 19","lang":"typescript","description":"This quickstart demonstrates parsing a basic mathematical expression, generating executable JavaScript code, and evaluating it within a defined data context. It highlights the use of `parse` and `codegen` with `fieldvar` and `allowed` options."},"warnings":[{"fix":"Migrate all `require()` calls to `import` statements. Ensure your project is configured for ESM, typically by setting `\"type\": \"module\"` in `package.json` or using `.mjs` file extensions.","message":"Vega v6.0.0, including `vega-expression`, transitioned to ESM-only. CommonJS `require()` statements will no longer work, leading to import errors.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"Upgrade to `vega-expression@5.33.1` or higher (including all `v6.x` versions) to mitigate the prototype pollution vulnerability. Always validate user-provided expressions carefully.","message":"A prototype pollution vulnerability (GHSA-7f2v-3qq3-vvjf, CVE-2025-59840) was identified in `vega-expression` versions prior to `5.33.1`. This could allow cross-site scripting (XSS) via expressions abusing `toString` calls in specific environments. While fixed in newer versions, users on older `v5.x` releases should upgrade immediately.","severity":"breaking","affected_versions":"<5.33.1"},{"fix":"Ensure expressions adhere to the allowed syntax. Refer to the Vega expression language documentation for a full list of supported features, constants, and functions. Use the `codegen` options (`forbidden`, `allowed`, `functions`) to explicitly control what can be referenced.","message":"The `vega-expression` language is a restricted subset of JavaScript. It does not allow assignment operators (`=`, `+=`, etc.), pre/postfix updates (`++`), `new` expressions, or most control flow statements (`for`, `while`, `switch`). Function calls involving nested properties (e.g., `foo.bar()`) are also forbidden.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If CSP is a concern, integrate `vega-interpreter` into your runtime. Invoke the Vega parser with the `{ast: true}` option and pass the interpreter as an option to the Vega View constructor to enable AST-based evaluation.","message":"When using `codegen`, the `Function` constructor is used to evaluate the generated code. This can violate Content Security Policies (CSPs) that prohibit `unsafe-eval`. For CSP-compliant evaluation, consider using the `vega-interpreter` package, which evaluates expressions by traversing the AST directly.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Replace `const { parse } = require('vega-expression');` with `import { parse } from 'vega-expression';`. Ensure your `package.json` has `\"type\": \"module\"` or use `.mjs` file extensions for ESM files.","cause":"Attempting to use CommonJS `require()` syntax in a project after upgrading to `vega-expression` v6.0.0 or later, which is ESM-only.","error":"ReferenceError: require is not defined"},{"fix":"Rewrite the expression to use only the allowed subset of JavaScript. Avoid assignment operators, `new` expressions, `for`/`while` loops, and direct method calls on nested properties.","cause":"The parsed expression contains forbidden JavaScript syntax, such as an assignment operator (`=`).","error":"Error: Invalid AST Node Type: AssignmentExpression"},{"fix":"When creating the code generator, use the `allowed` array for variables within the expression scope, or the `globalvar` option to specify the object through which global variables should be looked up.","cause":"The generated code attempts to access a global variable (`myGlobalVar`) that was not explicitly allowed or provided in the `codegen` options.","error":"ReferenceError: myGlobalVar is not defined"}],"ecosystem":"npm"}