Repository navigation
fix: pass array indices to the replacer as strings - #32
Conversation
Native JSON.stringify calls the replacer with string keys for array elements. Passing the numeric loop index made a replacer written for native JSON (`key === '0'`) silently skip array items. `'' + i` is used over `String(i)`: on an array-heavy benchmark with no replacer it measured ~1% over baseline against ~5% for `String(i)`. Closes #31 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Closes #31
What changed
opts.replacerreceived array indices as numbers (0,1). NativeJSON.stringifypasses them as strings ('0','1'), so a replacer written for native JSON, likekey === '0', silently skipped array items.lib/index.jsnow passes'' + ifor array elements.Behavior change to call out in the release note
A replacer that relied on the old numeric keys (
key === 0,typeof key === 'number') stops matching array items. That is the native behavior, andlib/index.d.tsalready typeskey: string.How it was tested
npm test: lint + 45 passing, 100% coverage.test/replacer.js:(typeof key, key)call sequence compared with nativeJSON.stringifyover 8 array fixtures (flat, nested, inside objects, sparse,undefined/null, 12 items, empty), under default options and underspace+cyclesthisis the holding arraymasterand pass with the fix.masterand this branch, zero output differences.Performance
Array-heavy input, no replacer, median of 9 runs x 200 iterations, 3 interleaved rounds:
String(i)'' + i(this PR)'' + iwas chosen for that reason: roughly 1% over master against roughly 5% forString(i).Notes
prettier-standard) reformatted a few untouched lines inlib/index.jsandtest/replacer.js. The only logic change is the'' + iline.masterand found during review:toJSONis called without the key argument; an array passed asopts.replacerthrows; boxed primitives (Object(1)) serialize as{}; a replacer that pushes to its holding array changes the output because length is re-read each iteration.🤖 Generated with Claude Code
Note
Medium Risk
Behavior change for any replacer that matched array items via numeric keys; otherwise localized to replacer/array serialization with strong native-parity tests.
Overview
Fixes replacer callbacks so array element keys are strings (
'0','1', …), matching nativeJSON.stringifyinstead of numeric indices.In
lib/index.js, recursive serialization now passes'' + iwhen walking arrays, so replacers that checkkey === '0'(or similar) apply to array items as they do with the built-in API. Replacers that depended on numeric keys (key === 0) will no longer match array elements—this is intentional alignment with documentedreplacer?: (key: string, …)typing.test/replacer.jsadds coverage for the reported case, parity of replacer key sequences vsJSON.stringifyacross several array shapes and option sets,thisbinding on arrays, and string indices when the replacer returns a nested array. Remaining diff in those files is mostly formatting.Reviewed by Cursor Bugbot for commit 0c6f1c8. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
JSON.stringifybehavior.