refactor(v4): converge the two expression evaluators - #860
Conversation
Action/expression.ts and Data/expression.ts each had their own new
Function cache with their own key scheme, plus an uncached third call
site in Fetch.parseResponse() that recompiled on every response.
Data's key = code + name also let two unrelated expressions collide,
e.g. ('bc', 'return "A"') and ('c', 'return "A"b').
Replace all three with one compileExpression(argNames, body), cached
in two Map levels instead of a hand-built cacheKey string so nothing a
caller writes can collide. Data's getCallback() drops its group
parameter, which was never part of the executed function's arguments.
Closes F2 in #780.
Code ReviewRisk: Low — The refactor is safe to merge; no concrete defects were found. This change centralizes expression compilation for Action, Data, and Fetch behind a shared two-level cache. It also removes the unused Data group parameter and adds regression coverage for cache separation and reuse. Review usage: 16,030 in (7,935 cached) / 1,084 out tokens — $0.0087 (openrouter/openai/gpt-5.6-luna, thinking: low) Reviewed by @weareikko/code-review v0.9.5 for commit b485b97. |
Export sizeBundled per export with peer dependencies left external, dynamic imports excluded and the output minified; sizes are gzipped. ✅ No export size changes. Unchanged (393)@studiometa/js-toolkit
@studiometa/js-toolkit-v4
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #860 +/- ##
=======================================
Coverage 97.04% 97.04%
=======================================
Files 175 175
Lines 4535 4535
Branches 1323 1322 -1
=======================================
Hits 4401 4401
Misses 122 122
Partials 12 12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
v4 mount benchmarksBase and head measured on this runner, alternating over 3 rounds each; every value is the median of the round medians. Running both sides on one machine is what removes cross-machine noise — a cached baseline from another runner would put it back. A move under 25%, or on a benchmark under 5 ms, is not reported as a change: it is inside the measured noise of a shared runner. No benchmark moved beyond the noise floor. Within noise (18)
|
Summary
compileExpression(argNames, body)inpackages/v4/migration/expression.ts, replacing the separatenew Functioncaches inAction/expression.tsandData/expression.ts, plus the uncached third call site inFetch.parseResponse()(recompiled on every response).Maplevels (argument-list key, then body key) instead of a hand-builtcacheKeystring, so nothing a caller writes can collide — this fixesData's still-open collision wherekey = code + namemade('bc', 'return "A"')and('c', 'return "A"b')the same entry.getCallback()drops itsgroupparameter entirely, since it was never part of the executed function's arguments.Test plan
npx tsc -p tsconfig.jsonandtsconfig.coexistence.json— cleannpx oxlint --type-aware packages/v4— clean (pre-existing unrelated warning incontext.tsonly)npx oxfmt --checkon touched files — cleanvitest runinpackages/v4— 1413 tests passedmigration/expression.spec.tsregression test pinning the collision fix🤖 Generated with Claude Code