Skip to content

chore(engine): remove node:vm evaluator#25

Open
albertgwo wants to merge 2 commits intofeat/engine-pr0b-ast-arithmetic-lrufrom
feat/engine-pr13-delete-nodevm
Open

chore(engine): remove node:vm evaluator#25
albertgwo wants to merge 2 commits intofeat/engine-pr0b-ast-arithmetic-lrufrom
feat/engine-pr13-delete-nodevm

Conversation

@albertgwo
Copy link
Copy Markdown
Contributor

@albertgwo albertgwo commented Mar 19, 2026

User description

Summary

  • Delete `packages/engine/src/runner/evaluator.ts` (the `node:vm` sandbox evaluator)
  • Replace all call sites with AST interpreter from PR 0b
  • Delete evaluator tests (28 tests removed, replaced by interpreter tests)
  • Remove `evaluateExpression` and `ExpressionTimeoutError` from public API
  • Zero `node:vm` imports remain in engine package

Dependency

Base: `feat/engine-pr0b-ast-arithmetic-lru` (only needs AST interpreter)

PR 17 of 16 (cleanup) in the execution engine implementation.

Test plan

  • Zero `node:vm` imports in engine source
  • All remaining tests pass (314 tests)
  • Walker and rules evaluator use AST interpreter correctly
  • No runtime regression

Generated description

Below is a concise technical summary of the changes proposed in this PR:
Replace the node:vm-based evaluator with the AST interpreter throughout the walker and rules evaluation flows, removing the old sandboxed evaluator from the runner API. Update the walker and rules loader to call interpretExpression, drop the exported evaluateExpression/ExpressionTimeoutError, and rely on the interpreter context for guarded expression handling.

TopicDetails
AST Expression Flow Switch all labeled-expression evaluation in the runner and rules flows to interpretExpression, so walker inputs/conditions and rules inputs now resolve through the AST interpreter instead of the removed node:vm sandbox.
Modified files (3)
  • packages/engine/src/rules/evaluator.ts
  • packages/engine/src/runner/evaluator.ts
  • packages/engine/src/runner/walker.ts
Latest Contributors(1)
UserCommitDate
albertgwo@gmail.comfeat-complete-the-loop...March 02, 2026
API & Tests Cleanup Clean up the runner API and regression tests after removing the sandboxed evaluator, deleting its exports and dedicated tests while ensuring remaining suites rely on the interpreter behavior.
Modified files (5)
  • packages/engine/src/__tests__/expressions/evaluator-security.test.ts
  • packages/engine/src/__tests__/runner/evaluator.test.ts
  • packages/engine/src/__tests__/runner/fixtures-edge-cases.test.ts
  • packages/engine/src/index.ts
  • packages/engine/src/runner/index.ts
Latest Contributors(1)
UserCommitDate
albertgwo@gmail.comrefactor-consolidate-v...February 23, 2026
This pull request is reviewed by Baz. Review like a pro on (Baz).

Switch walker.ts and rules/evaluator.ts from the node:vm-based
evaluateExpression to the browser-safe AST interpretExpression.
This removes the runtime dependency on node:vm for expression
evaluation while maintaining identical behavior for supported
expression syntax.
Delete runner/evaluator.ts (node:vm sandbox), its test suite
(evaluator.test.ts, evaluator-security.test.ts), and remove
evaluateExpression/ExpressionTimeoutError from public exports.
The AST interpreter now handles all expression evaluation.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying flowprint with  Cloudflare Pages  Cloudflare Pages

Latest commit: ff838eb
Status: ✅  Deploy successful!
Preview URL: https://8b4befd7.flowprint.pages.dev
Branch Preview URL: https://feat-engine-pr13-delete-node.flowprint.pages.dev

View logs

Comment on lines 159 to 162
const rulesDoc = loadRulesFile(node.rules.file, options.projectRoot)
const rulesResult = evaluateRules(rulesDoc, context, options.expressionTimeout)
const rulesResult = evaluateRules(rulesDoc, context)
context.results.set(nodeId, rulesResult.output)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunOptions.expressionTimeout is ignored by the new interpreter — should we enforce it in interpretExpression/evaluateRules or remove/deprecate the option?
interpretExpression(...) => interpretExpression(..., options.expressionTimeout)

Finding type: Breaking Changes | Severity: 🔴 High


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

In packages/engine/src/runner/walker.ts around lines 159 to 162, the call to
evaluateRules(rulesDoc, context) no longer passes the RunOptions.expressionTimeout so
expression evaluation has no execution bound. Reintroduce timeout enforcement by
updating the evaluator/interpreter APIs to accept a timeout parameter and pass
options.expressionTimeout (use a default of 1000 ms if undefined) from walker.ts;
specifically, change calls at the action rules evaluation (around lines 159-162), switch
rules evaluation (around lines 257-263), per-case interpretExpression calls (around line
302), and parallel branch input evaluation (around line 368) to pass the timeout. Also
update the imported function signatures and any callers/tests/CLI forwarding to ensure
the option is honored; alternatively, if you prefer to remove the option, deprecate and
remove RunOptions.expressionTimeout and update CLI help/forwarding consistently.

Heads up!

Your free trial ends tomorrow.
To keep getting your PRs reviewed by Baz, update your team's subscription

Comment on lines 365 to 370
if (branchNode.inputs) {
const evaluated: Record<string, unknown> = {}
for (const [key, expr] of Object.entries(branchNode.inputs)) {
evaluated[key] = evaluateExpression(expr, context, options.expressionTimeout)
evaluated[key] = interpretExpression(expr, context)
}
args = evaluated
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input-evaluation loop is duplicated, should we extract an evaluateInputs(inputs, ctx) helper and reuse it?

const evaluateInputs = (inputs, ctx) => Object.fromEntries(Object.entries(inputs).map(([k, expr]) => [k, interpretExpression(expr, ctx)]));

Finding type: Conciseness | Severity: 🟢 Low


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

In packages/engine/src/runner/walker.ts around lines 365 to 370 (and also update the
identical loop at ~lines 183 to 189 in executeAction), the code duplicates the logic
that evaluates input expressions by calling interpretExpression for each key. Extract a
small helper function in this file, for example: const evaluateInputs = (inputs:
Record<string, string>, ctx: ExecutionContext) => { const out: Record<string, unknown> =
{}; for (const [k, expr] of Object.entries(inputs)) out[k] = interpretExpression(expr,
ctx); return out; }; Then replace both duplicated loops with a call to
evaluateInputs(node.inputs, context) (or branchNode.inputs) so both executeAction and
executeParallel use the single helper and maintain identical behavior.

Heads up!

Your free trial ends tomorrow.
To keep getting your PRs reviewed by Baz, update your team's subscription

Comment on lines 20 to 24
export {
runGraph,
formatTrace,
evaluateExpression,
ExpressionTimeoutError,
loadEntryPoint,
loadFixtures,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing evaluateExpression and ExpressionTimeoutError from runner exports breaks existing imports — should we keep exporting them or provide documented replacements?

Finding type: Breaking Changes | Severity: 🔴 High


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

In packages/engine/src/index.ts around lines 20-24, the top-level exports removed
evaluateExpression and ExpressionTimeoutError from the public API. Restore backward
compatibility by re-adding those exports (for example: export { evaluateExpression,
ExpressionTimeoutError } from './runner/index.js') or, if those symbols were moved,
re-export them from their new module locations and ensure ExpressionTimeoutError still
exists (or provide a compatible alias/class). Also update the package exports/comments
to document any replacement path if applicable.

Heads up!

Your free trial ends tomorrow.
To keep getting your PRs reviewed by Baz, update your team's subscription

Comment on lines 20 to 25
export {
runGraph,
formatTrace,
evaluateExpression,
ExpressionTimeoutError,
loadEntryPoint,
loadFixtures,
} from './runner/index.js'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packages/engine was modified but there's no .changeset/*.md entry—should we add the required changeset per CLAUDE.md to document these package changes?

Finding type: AI Coding Guidelines | Severity: 🟠 Medium


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

In packages/engine/src/index.ts around lines 20-25, the public exports were modified
(removed evaluateExpression and ExpressionTimeoutError), but there is no .changeset
entry for packages/engine. Add a new changeset file under .changeset (e.g.
.changeset/<short-descriptive-name>.md) that names the package packages/engine,
summarizes the change (mention removal of exports and other changes in
src/rules/evaluator.ts and src/runner/walker.ts), and specifies the correct version bump
(treat removal of exported API as a breaking change—major bump—unless you confirm
it’s internal-only, otherwise use minor/patch). Also run a quick scan of all modified
files under packages/engine and include a short bullet list of affected files in the
changeset description so release notes capture the scope.

Heads up!

Your free trial ends tomorrow.
To keep getting your PRs reviewed by Baz, update your team's subscription

@albertgwo
Copy link
Copy Markdown
Contributor Author

Code Review Findings

Verification Summary

  • Zero node:vm runtime imports: Confirmed via git grep
  • All 5 call sites migrated: walker (3), rules evaluator (2)
  • Public API updated: evaluateExpression and ExpressionTimeoutError removed
  • No orphaned code: Zero remaining references to deleted module
  • Type compatibility: InterpreterContext and ExecutionContext are structurally identical
  • Test coverage: 28 deleted tests have equivalents in interpreter/parser-security test files

Important (80-89 confidence)

1. expressionTimeout in RunOptions and CLI is now dead code (85)

  • Files: packages/engine/src/runner/types.ts:5 and packages/cli/src/commands/run.ts:24,91
  • options.expressionTimeout is never read by the engine after this PR. CLI still accepts --expression-timeout and passes it to runGraph, where it's silently ignored.
  • Fix: Remove expressionTimeout from RunOptions interface and --expression-timeout from CLI, or add TODO for follow-up.

Overall

Clean PR. Migration is complete and thorough. Merge-ready after addressing the dead option cleanup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant