fix: exit resolved async blocks on correct node when hydrating (#17640)

* fix: exit resolved async blocks on correct node when hydrating

* expand test + fix

* tweak, add note to self

---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/17644/head
Rich Harris 4 days ago committed by GitHub
parent bc44975869
commit 6e5f2b157a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: exit resolved async blocks on correct node when hydrating

@ -20,13 +20,27 @@ import { get_boundary } from './boundary.js';
*/
export function async(node, blockers = [], expressions = [], fn) {
var was_hydrating = hydrating;
var end = null;
if (was_hydrating) {
hydrate_next();
end = skip_nodes(false);
}
if (expressions.length === 0 && blockers.every((b) => b.settled)) {
fn(node);
// This is necessary because it is not guaranteed that the render function will
// advance the hydration node to $.async's end marker: it may stop at an inner
// block's end marker (in case of an inner if block for example), but it also may
// stop at the correct $.async end marker (in case of component child) - hence
// we can't just use hydrate_next()
// TODO this feels indicative of a bug elsewhere; ideally we wouldn't need
// to double-traverse in the already-resolved case
if (was_hydrating) {
set_hydrate_node(end);
}
return;
}
@ -39,7 +53,6 @@ export function async(node, blockers = [], expressions = [], fn) {
if (was_hydrating) {
var previous_hydrate_node = hydrate_node;
var end = skip_nodes(false);
set_hydrate_node(end);
}

@ -0,0 +1,5 @@
<script>
let { b } = $props();
</script>
{b}

@ -0,0 +1,11 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
mode: ['hydrate'],
async test({ assert, target }) {
await tick();
assert.htmlEqual(target.innerHTML, `<div><p>hello</p></div> <div>true</div>`);
}
});

@ -0,0 +1,18 @@
<script lang="ts">
import Child from "./Child.svelte";
await 1;
let b = true;
let a = true;
</script>
{#if a}
<div>
{#if b}
<p>hello</p>
{/if}
</div>
<div>
<Child {b} />
</div>
{/if}
Loading…
Cancel
Save