Skip to content

Solid 2: reconcile repeats unchanged presence and holds unrelated updates #3743

Description

@GabbeV

Describe the bug

Reconciling a plain store can hold an unrelated field's rendered update behind a pending action when a separate in expression observes a property that the action deleted. The incoming snapshot leaves that property absent, matching its already-staged presence.

Reproduction

One-button playground — preview 3ed3810, Tailwind disabled.

Click Build, then Run reproduction. The sequence is:

// Initial store: { a: { value: 0 }, b: { failed: true } }
const removeFlag = action(function* () {
  setState(draft => { delete draft.b.failed; });
  yield gate;
});

// In a later event, while removeFlag is pending:
setState(reconcile({ a: { value: 1 }, b: {} }));

The component separately renders state.a.value and "failed" in state.b; no memo combines them. The playground releases the action after 2.5 seconds.

Expected: Value: 1 appears while the deletion action remains pending.

Actual: Value: 0 remains until that action finishes, then becomes 1.

Controls and investigation

Verified in Chromium and Firefox, in development and production builds:

  • Removing the separate presence expression allows the value to update immediately.
  • Assigning failed = false instead of deleting it, and reconciling the same false, allows it to update immediately.
  • Writing a.value = 1 directly instead of reconciling allows it to update immediately.

The suspected cause is the presence notification in notifyFold and notifyFoldTail. Value notifications compare old/new values, but the presence loops call setSignal for every observed key without comparing presence. The core joins the node's holding transaction before rejecting an equal value, so repeating false can entangle the reconciliation with the deletion action.

Adding an old/new presence comparison to both loops in an isolated test bundle prevents the hold. This is diagnostic evidence, not a fully validated patch.

Actual presence changes must still notify: deleting a prop override can select another merge source even when the resulting value is equal. This reproduction has no merge or provider switch; the suspected problem is the repeated absence-to-absence notification.

Version

solid-js and @solidjs/web from https://pkg.pr.new/mizulu/solid2/...@3ed3810 (Solid commit 3ed3810097bfc5e5d15829277b40315bbd2b5f74).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions