Repository navigation
Conversation
Assigning a smaller `length` to a draft array truncated `copy_` without marking the dropped indices as assigned. If the array then grew back to at least its base length, generateArrayPatches skipped those indices, so the patches did not replay to the result and the inverse patches did not restore the base. Mark the dropped base indices as assigned in the array set trap, as deleting them one by one already does. Fixes immerjs#1355
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1355
What
With
enablePatches(), shrinking a draft array by assigninglengthand then growing it back to at least its base length produced noreplacepatch (and no inverse patch) for the truncated indices. SoapplyPatches(base, patches)kept the stale values, and the inverse patches did not restore the base. The same recipe withsplice(0)was already correct.Why
generateArrayPatchesonly emits areplacefor an index belowbase_.lengthwhenassigned_has it (orallIndicesReassigned_is set).spliceremoves elements throughdeleteProperty, which marks each index. Assigninglengthgoes through thesettrap for"length"only, so the dropped indices were never marked.Change
In the array
settrap, whenlengthshrinks, mark the dropped indices that exist in the base as assigned. Only indices belowbase_.lengthare marked, since those are the only ones the replace loop looks at. If the array stays short, nothing changes: the replace loop only runs up to the shorter length, and the dropped indices still getremovepatches.Tests
New cases in
__tests__/patch.js(throughrunPatchTests, so they also check replay and reversal):length = 0thend[1] = 2(the case from the issue)length = 0thenlength = 2length = 1thenpush(4, 5)(control, already passing)length = 0then the same values written back (control: no patches)Before the fix, the first two fail (6 assertions). After, all pass.
Repro from the issue, run against the build:
Checks run locally (Node 24):
yarn test(src, build and flow),yarn coverage,yarn test:perf,prettier --check.