fix: improve reconciliation of inert each block rows (#13379)

* fix: improve reconcilation of inert each block rows

* fix: improve reconcilation of inert each block rows

* add test
pull/13383/head
Dominic Gannaway 1 month ago committed by GitHub
parent 0b3fd4e42d
commit d309023cb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve reconciliation of inert each block rows

@ -373,7 +373,11 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) {
stashed = [];
while (current !== null && current.k !== key) {
(seen ??= new Set()).add(current);
// If the item has an effect that is already inert, skip over adding it
// to our seen Set as the item is already being handled
if ((current.e.f & INERT) === 0) {
(seen ??= new Set()).add(current);
}
stashed.push(current);
current = current.next;
}

@ -0,0 +1,34 @@
import { flushSync } from '../../../../src/index-client.js';
import { test } from '../../test';
export default test({
test({ assert, raf, target }) {
const [btn1, btn2] = target.querySelectorAll('button');
btn1?.click();
btn1?.click();
btn1?.click();
flushSync();
assert.htmlEqual(
target.innerHTML,
'<button>Push</button><button>Remove</button><ul><li>0</li><li>1</li><li>2</li></ul'
);
btn2?.click();
flushSync();
raf.tick(50);
const li = /** @type {HTMLElement & { foo: number }} */ (target.querySelector('ul > li'));
assert.equal(li.foo, 0.5);
btn1?.click();
flushSync();
assert.equal(li.foo, 0.5);
assert.htmlEqual(
target.innerHTML,
'<button>Push</button><button>Remove</button><ul><li>0</li><li>1</li><li>2</li><li>3</li></ul'
);
}
});

@ -0,0 +1,30 @@
<script>
function foo(node, params) {
return {
duration: 100,
tick: (t, u) => {
node.foo = t;
}
};
}
let list = $state([]);
let id = 0;
function push() {
list.push({ id: id++ })
}
function removeFirst() {
list.splice(0, 1);
}
</script>
<button onclick={push}>Push</button>
<button onclick={removeFirst}>Remove</button>
<ul>
{#each list as item (item.id)}
<li out:foo>{item.id}</li>
{/each}
</ul>
Loading…
Cancel
Save