Skip to content

2.0.0-beta.14: Keyed reconcile crashes on nullable or primitive array entries #2772

Description

@yumemi-thomas

Describe the bug

In Solid 2.0.0-beta.14, keyed reconcile(..., "id") can crash when an array contains entries that are not keyed objects.

Two related cases:

  1. An array contains null entries between keyed objects.
  2. An existing object entry is replaced by a primitive value.

Both are valid array shapes for API data or mixed collections, and reconcile should preserve/replace those entries rather than assuming every item can be keyed as an object.

Your Example Website or App

https://stackblitz.com/edit/solidjs-templates-gqv5mur8?file=src%2FApp.tsx

import { createSignal, createStore, reconcile } from 'solid-js';

function NullEntryRepro() {
  const [list, setList] = createStore<any[]>([{ id: 1 }, null, { id: 2 }]);
  const [result, setResult] = createSignal('not run');

  return (
    <section>
      <h2>null entry</h2>

      <button
        onClick={() => {
          try {
            setList(
              reconcile([{ id: 1 }, null, { id: 2, value: 'updated' }], 'id')
            );
            setResult(JSON.stringify(list));
          } catch (error) {
            setResult(String(error));
          }
        }}
      >
        reconcile null entry
      </button>

      <p>{result()}</p>
    </section>
  );
}

function PrimitiveEntryRepro() {
  const [list, setList] = createStore<any[]>([{ id: 1, value: 'object' }]);
  const [result, setResult] = createSignal('not run');

  return (
    <section>
      <h2>object to primitive</h2>

      <button
        onClick={() => {
          try {
            setList(reconcile([5], 'id'));
            setResult(JSON.stringify(list));
          } catch (error) {
            setResult(String(error));
          }
        }}
      >
        reconcile object to primitive
      </button>

      <p>{result()}</p>
    </section>
  );
}

export default function App() {
  return (
    <main>
      <NullEntryRepro />
      <PrimitiveEntryRepro />
    </main>
  );
}

Steps to Reproduce the Bug or Issue

Repro 1: null entry

  1. Open the repro.
  2. Click reconcile null entry.
  3. Observe the rendered result.

Repro 2: object entry replaced by primitive

  1. Open or refresh the repro.
  2. Click reconcile object to primitive.
  3. Observe the rendered result.

Expected behavior

The null entry should be preserved and the keyed object after it should update:

[{"id":1},null,{"id":2,"value":"updated"}]

Repro 2

The object entry should be replaced by the primitive:

[5]

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: Chrome
  • Version: current stable

Additional context

These appear related to packages/solid-signals/src/store/reconcile.ts in the keyed array reconciliation paths. The implementation appears to assume keyed object entries in places where arrays may contain null, undefined, or primitive values.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions