Shrinking an array with `length =` and growing it back loses the patches for the truncated indices
メンテナーはふだん 4 日以内に返信
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 75/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- javascript
- 領域
- backend
調査の方向性
src/plugins/patches.ts、特に generateArrayPatches_ から始め、draft 配列を縮小すると copy_ と assigned_ がどのように変化するかを追ってください。length を縮小して再び拡大する場合の、提供された回帰テストを追加し、patch 関連のテストを実行してください。完了条件は、順方向の patch が recipe の結果を再現し、逆方向の patch がベースを復元することです。
索引モデルが issue の本文から書いたものです。
説明
🐛 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/
- 主要言語
- JavaScript
- スター
- 29k
- フォーク
- 905
- 平均マージ
- 3日 16時間
- マージ済み PR(30日)
- 22
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
immerjs/immer のほかの issue
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
メンテナーはふだん 4 日以内に返信
-
Docs: Chinese (zh-CN) website translation is outdated vs English docs再び着手できるかも @lijiayou0728 が 91 日前に担当しましたが、オープン中のプルリクエストはありません。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
immerjs/immer#1242 · コメント 5 件 ·
メンテナーはふだん 4 日以内に返信
-
question
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
メンテナーはふだん 4 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
immerjs/immer#1217 · コメント 1 件 ·
メンテナーはふだん 4 日以内に返信
-
[Feature Request] Support for "Splice" patches in arrays for CRDT/Y.js integration (and others)オープンproposal
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
immerjs/immer#1202 · コメント 2 件 · リアクション 1 件 ·
メンテナーはふだん 4 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
Automattic/node-canvas#2633 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
capricorn86/happy-dom#2594 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
microsoft/monaco-editor#5575 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
メンテナーはふだん 1 日以内に返信