Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[2.0] IMMUTABLE_UPDATE_IN_STORE false positive when an in-place `splice` shifts the next item into the removed index

クローズ
#4,262 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
55/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
javascript, typescript

調査の方向性

Start in packages/signals/src/store/store.ts at reportReplacedContainers and trace how array writes from splice are checked; compare that with the array branch’s oldItems identity set. Read packages/signals/src/core/attribution.ts for checkImmutableUpdate, then reproduce the case in a dev build and check that moving an existing item emits no report while replacing it with a fresh similar object still does.

索引モデルが issue の本文から書いたものです。

説明

Version: solid-js / @solidjs/signals 2.0.0-rc.18, dev build. The relevant code is unchanged on next (4ea2f4986).

Description

Removing an item from a store array with an in-place splice (the repair the diagnostic itself recommends for arrays) can report IMMUTABLE_UPDATE_IN_STORE for the index the next item shifts into. This happens when the removed item and the one after it share at least half of their leaf values, for example two lines of the same product that differ only in one field.

No container was copied. After the splice, index 0 holds the object that was already at index 1.

Reproduction

Run in a dev build with the diagnostics observed (I used captureArtifact from @solidjs/diagnostics in a vitest jsdom test; the same message appears in the dev console):

import { createStore, flush } from 'solid-js'

const [, setState] = createStore({
  items: [
    { id: 'a', product: 'p1', name: 'Pancakes', variant: 'meat', quantity: 2 },
    { id: 'b', product: 'p1', name: 'Pancakes', variant: 'cheese', quantity: 2 },
  ],
})

setState((draft) => {
  draft.items.splice(0, 1)
})
flush()

No reader or effect is needed.

Actual

[IMMUTABLE_UPDATE_IN_STORE] "store.items.0" was replaced with a fresh object whose leaves are mostly the same values (3 of 5 unchanged, 2 changed) — a spread-copy update. The store already tracks leaves; a new container makes every reader of "store.items.0" re-run for the few that moved. Instead, assign the leaf on the draft (`store.items.0.<key> = …`) so only readers of that key re-run. For data arriving from outside (a fetch result), merge it with reconcile(data, key)(store.items.0).

Control: if the two items share fewer than half of their leaves (for example { id: 'b', product: 'p2', name: 'Soup', variant: 'cheese', quantity: 5 } as the second item), nothing is reported.

Expected

No report. The object now at items[0] is an item that was already in the same array before the write, so the write moved an existing item and did not replace it with a fresh copy. The suggested repair ("assign the leaf on the draft") does not apply here.

Code location

reportReplacedContainers in packages/signals/src/store/store.ts. For each written key it compares the leaves of the old and new object at that key. For an array index written by splice, the new value is the shifted sibling, so the leaf census compares two different existing items and checkImmutableUpdate (packages/signals/src/core/attribution.ts) sees "mostly the same values".

A possible fix is to skip the report when the new value at an array index is unwrapValue-identical to one of the old array's items (the same identity set the array branch already builds for oldItems), since that is a move and not a fresh container.

主要言語
TypeScript
スター
36.2k
フォーク
1.1k
平均マージ
11時間 5分
マージ済み PR(30日)
353

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

solidjs/solid のほかの issue

solidjs/solid の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。