Repository navigation
perf(router): add a __proto__ param with a computed key, not defineProperty - #194
Conversation
…Property A computed key in an object literal defines an own property, so spreading the params into a new object with the `__proto__` key keeps it off the prototype, as `Object.defineProperty` did, in less code. It runs only for a param named `__proto__`, so the spread is not repeated per param. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VVaw7Sutbw6xMTMyDFeNfw
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance1 warning
Comparing Footnotes
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
toParams__proto__branch — theObject.defineProperty(params, name, {…})call is replaced by a computed-key spread,params = { ...params, [name]: value }. An object-literal computed key defines an own data property, so this is behavior-equivalent to the old path: an own, enumerable, writable, configurable__proto__key on a plainObject.prototype-backed object, same insertion position, and a later same-named param still overwrites in place. Only the__proto__branch spreads, so steady-state cost is unaffected.paramsmoves fromconsttoletaccordingly.- Lint suppression —
oxc/no-accumulating-spreadis enabled (deny) and is genuinely tripped by the in-loop spread. The function-leveloxlint-disable/oxlint-enablepair is required rather than anext-linedirective: the rule anchors its diagnostic to thelet paramsdeclaration, not the spread element, so anext-lineon the spread line leaves it reported. The comment explains this accurately.
Verified locally: oxlint --print-config confirms the rule is deny; the router suite passes 73/73; uncheck packages/router/src/index.ts is green (oxlint, oxfmt, tsc). Existing tests already pin the exact semantics — router.test.ts's "keeps a param named proto as an own key of a plain object" (prototype, Object.keys, full descriptor) and encoding.test.ts's "names that objects inherit".
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Requested by dinwwwh · project thread
Summary
toParamsadded a param named__proto__withObject.defineProperty, since assigning it would set the prototype instead. A computed key in an object literal defines an own property too, soparams = { ...params, [name]: value }does the same in much less code. The result is the same: a plain object withObject.prototype, and__proto__as an own, writable, enumerable, configurable key in its place among the params. A later param of the same name still overwrites it in place.The spread runs only for a param named
__proto__, so oxlint'sno-accumulating-spread(which guards against spreading on every pass of a loop) is turned off aroundtoParamswith a comment saying why. Anext-linedirective does not cover it, because the rule reports from theletto the spread.Measurements
--minify, gzip -9): 5128 B to 5068 B minified, 2151 B to 2112 B gzip (-39 B).--single-threaded, fixed hash seeds): router import -6k instructions, REST add -9k, REST cold + 10 requests -16k. RPC unchanged.__proto__).Checks
pnpm run checkgreen; router tests 73/73 with 100% statement, branch, function and line coverage.fuzz,fuzz-big,fuzz-brace,fuzz-prefix,fuzz-inter*,fuzz-latek3/k7) at 3 seeds: 0 diffs.if (true)for the__proto__check, which only makes every param take the slower spread.Generated by Claude Code