fix: resume inert effects when they come from offscreen

The offscreen branch was missing the "resume inert effects" logic that was just below; it never reached that because of the early continue.

Fixes #17851
pull/17942/head
Simon Holthausen 3 days ago
parent 98e8b635fa
commit b448a62823

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: resume inert effects when they come from offscreen

@ -500,6 +500,14 @@ function reconcile(state, array, anchor, flags, get_key) {
move(effect, next, anchor);
prev = effect;
if ((effect.f & INERT) !== 0) {
resume_effect(effect);
if (is_animated) {
effect.nodes?.a?.unfix();
(to_animate ??= new Set()).delete(effect);
}
}
matched = [];
stashed = [];

@ -0,0 +1,32 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
const spam = /** @type {HTMLButtonElement} */ (target.querySelector('button.spam'));
const resolve = /** @type {HTMLButtonElement} */ (target.querySelector('button.resolve'));
resolve.click();
await tick();
for (let i = 0; i < 5; i += 1) {
spam.click();
await tick();
}
for (let i = 0; i < 5; i += 1) {
resolve.click();
await tick();
}
assert.equal(target.querySelectorAll('div').length, 1);
assert.htmlEqual(
target.innerHTML,
`
<button class="spam">Spam</button>
<button class="resolve">Resolve</button>
<div>5</div>
`
);
}
});

@ -0,0 +1,28 @@
<script>
let value = $state({ id: '0' });
const resolvers = [];
function wait() {
const promise = Promise.withResolvers();
resolvers.push(promise.resolve);
return promise.promise;
}
function spam() {
value.id = `${Number(value.id) + 1}`;
}
</script>
<button class="spam" onclick={spam}>Spam</button>
<button class="resolve" onclick={() => resolvers.shift()?.()}>Resolve</button>
<svelte:boundary>
{#each [value.id] as s (s)}
{await wait()}
<div>{s}</div>
{/each}
{#snippet pending()}
<p>pending</p>
{/snippet}
</svelte:boundary>
Loading…
Cancel
Save