Shrinking an array with `length =` and growing it back loses the patches for the truncated indices
Les mainteneurs répondent en général sous 4 jours
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 75/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- javascript
- Domaine
- backend
Piste de recherche
Commencez dans src/plugins/patches.ts, en particulier dans generateArrayPatches_, et suivez comment la réduction d’un tableau brouillon modifie copy_ et assigned_. Ajoutez le test de régression fourni pour réduire puis augmenter à nouveau length, puis exécutez les tests liés aux patches. Le travail est terminé lorsque les patches directs reproduisent le résultat de la recette et que les patches inverses restaurent la base.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
🐛 Bug Report
With enablePatches(), if a recipe shrinks a draft array by assigning .length and then grows it back to at least its original length, no replace patch (and no inverse patch) is produced for the truncated indices. Replaying the patches on the base gives a different state than the recipe, and the inverse patches do not restore the base. The same recipe written with splice(0) produces correct patches.
Link to repro
Not applicable: no CodeSandbox account; the script below and the unit test at the end reproduce it.
To Reproduce
npm i [email protected], save as t.mjs, run node t.mjs:
import { produceWithPatches, applyPatches, enablePatches } from "immer";
enablePatches();
const base = [1];
const [result, patches, inverse] = produceWithPatches(base, d => {
d.length = 0; // truncate index 0
d[1] = 2; // grow again
});
console.log(result);
console.log(patches);
console.log(inverse);
console.log(applyPatches(base, patches));
console.log(applyPatches(result, inverse));
const [r2, p2, i2] = produceWithPatches([1, 2], d => { d.length = 0; d.length = 2; });
console.log(r2, p2, i2);
Observed behavior
[ <1 empty item>, 2 ]
[ { op: 'add', path: [ 1 ], value: 2 } ]
[ { op: 'remove', path: [ 1 ] } ]
[ 1, 2 ]
[ <1 empty item> ]
[ <2 empty items> ] [] []
applyPatches(base, patches) keeps the stale 1 at index 0, and applyPatches(result, inverse) does not bring it back. The second recipe changes both elements but produces no patches at all.
Expected behavior
The same patches as for d.splice(0); d[1] = 2, which immer already gets right:
[
{ op: 'replace', path: [ 0 ], value: undefined },
{ op: 'add', path: [ 1 ], value: 2 }
] [
{ op: 'replace', path: [ 0 ], value: 1 },
{ op: 'remove', path: [ 1 ] }
]
so that applyPatches(base, patches) gives [ undefined, 2 ] and applyPatches(result, inverse) gives [ 1 ].
generateArrayPatches_ in src/plugins/patches.ts only emits a replace for an index below base.length when assigned_.get(i) is set (or allIndicesReassigned_). Assigning a smaller length truncates copy_ without marking the dropped indices as assigned, so they are skipped once the array is long again.
Unit test:
test("length shrink then grow produces replace patches", () => {
const base = [1]
const [result, patches, inverse] = produceWithPatches(base, d => {
d.length = 0
d[1] = 2
})
expect(applyPatches(base, patches)).toEqual(result)
expect(applyPatches(result, inverse)).toEqual(base)
})
Environment
We only accept bug reports against the latest Immer version.
- Immer version: 11.2.9 (also main 75a290e, built from source), Node.js v26.13.0
- I filed this report against the latest version of Immer
- Occurs with
setUseProxies(true) - Occurs with
setUseProxies(false)(ES5 only)
Credit: https://ucsbplse.github.io/
- Langage dominant
- JavaScript
- Étoiles
- 29k
- Forks
- 905
- Merge moyen
- 3 j 16 h
- PR mergées (30 j)
- 22
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de immerjs/immer
-
Difficulté 3/5 1-2 jours Accessibilité débutants 35/100
Les mainteneurs répondent en général sous 4 jours
-
Docs: Chinese (zh-CN) website translation is outdated vs English docsPeut-être à nouveau libre @lijiayou0728 l’a pris il y a 91 jours, et aucune pull request n’est ouverte. Ouverte
Difficulté 4/5 3-5 jours Accessibilité débutants 55/100
immerjs/immer#1242 · 5 commentaires ·
Les mainteneurs répondent en général sous 4 jours
-
Branding Drafts on Type levelOuvertequestion
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
Les mainteneurs répondent en général sous 4 jours
-
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
immerjs/immer#1217 · 1 commentaire ·
Les mainteneurs répondent en général sous 4 jours
-
[Feature Request] Support for "Splice" patches in arrays for CRDT/Y.js integration (and others)Ouverteproposal
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 25/100
immerjs/immer#1202 · 2 commentaires · 1 réaction ·
Les mainteneurs répondent en général sous 4 jours
Toutes les issues de immerjs/immer
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Automattic/node-canvas#2633 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
capricorn86/happy-dom#2594 ·
Les mainteneurs répondent en général sous 1 jour
-
Decoding tag 1 (epoch date) with an 8-byte integer throws "Cannot mix BigInt and other types"Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 79/100
microsoft/monaco-editor#5575 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
Les mainteneurs répondent en général sous 1 jour