fix: resume inert effects when they come from offscreen (#17942)

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/17936/head
Simon H 4 months ago committed by GitHub
parent 1cd06451af
commit f081a6c3b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

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

@ -480,6 +480,14 @@ function reconcile(state, array, anchor, flags, get_key) {
}
}
if ((effect.f & INERT) !== 0) {
resume_effect(effect);
if (is_animated) {
effect.nodes?.a?.unfix();
(to_animate ??= new Set()).delete(effect);
}
}
if ((effect.f & EFFECT_OFFSCREEN) !== 0) {
effect.f ^= EFFECT_OFFSCREEN;
@ -508,14 +516,6 @@ function reconcile(state, array, anchor, flags, get_key) {
}
}
if ((effect.f & INERT) !== 0) {
resume_effect(effect);
if (is_animated) {
effect.nodes?.a?.unfix();
(to_animate ??= new Set()).delete(effect);
}
}
if (effect !== current) {
if (seen !== undefined && seen.has(effect)) {
if (matched.length < stashed.length) {

@ -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