preactjs / preact

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
https://preactjs.com
MIT License
36.35k stars 1.93k forks source link

preact@10.22.0 unexpected child ordering with skew based diff #4412

Closed hzy closed 1 week ago

hzy commented 2 weeks ago

Describe the bug With preact version from 10.16.0 to 10.22.0, and code below:

<div>
  {items.map((key) => (
    <div key={key}>{key}</div>
  ))}
</div>

Updating array items (shuffle it) leads to unexpected ordering.

preact version 10.15.0 and below will not reproduce this issue.

To Reproduce (with Stackblitz)

Steps to reproduce the behavior:

  1. Open project at https://stackblitz.com/edit/create-preact-starter-ckjsze?file=src%2Findex.jsx
  2. You can see numbers in order:
    1
    3
    4
    0
    5
    2
    6

Expected behavior Numbers should be in order:

1
3
5
2
6
4
0

To Reproduce (in preact unit test)

  1. Put code below inside file test/browser/render.test.js,

    it("shuffle", function () {
        const jsx = (items) => (
            <div>
                {items.map((key) => (
                    <div key={key}>{key}</div>
                ))}
            </div>
        );
        const a = ["0", "1", "2", "3", "4", "5", "6"];
        const b = ["1", "3", "5", "2", "6", "4", "0"];
        render(jsx(a), scratch);
        render(jsx(b), scratch);
    
        expect(scratch.innerHTML).to.equal(
            `<div>${b.map(n => `<div>${n}</div>`).join("")}</div>`
        );
    });
  2. run test, the test above will FAIL

Expected behavior Test should pass.