fix: ensure HMR wrapper forwards correct start/end nodes to active effect (#17985)

Fixes #17982 (two issues reported there)

Adding the start/end statically at the end once does not work because
it's going to be stale when there's a HMR reload of the wrapped
component. For reasons not completely clear to me it also fails in
another case.

So instead of wrapping the HMR with comments we just forward the nodes
of the inner effect to the outer active effect, pretending the wrapper
isn't there from a "remove dom nodes"-perspective.
pull/17984/head
Simon H 5 months ago committed by GitHub
parent b90a5dfb61
commit 1773cb5b59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure HMR wrapper forwards correct start/end nodes to active effect

@ -5,9 +5,7 @@ import { hydrate_node, hydrating } from '../dom/hydration.js';
import { block, branch, destroy_effect } from '../reactivity/effects.js';
import { set, source } from '../reactivity/sources.js';
import { set_should_intro } from '../render.js';
import { get } from '../runtime.js';
import { assign_nodes } from '../dom/template.js';
import { create_comment } from '../dom/operations.js';
import { active_effect, get } from '../runtime.js';
/**
* @template {(anchor: Comment, props: any) => any} Component
@ -29,19 +27,6 @@ export function hmr(fn) {
let ran = false;
// Surround the wrapped effects with comments and assign the nodes
// on the wrapping effects so the parent can properly do DOM operations.
let start = create_comment();
let end = create_comment();
// During hydration, inserting the start comment before the anchor could
// corrupt the DOM tree that the hydration walker is navigating (e.g. when
// a component is inside a CSS props wrapper gh-issue#17972). We defer the insertion until
// after the component has hydrated.
if (!hydrating) {
anchor.before(start);
}
block(() => {
if (component === (component = get(current))) {
return;
@ -68,21 +53,19 @@ export function hmr(fn) {
if (ran) set_should_intro(true);
});
// Forward the nodes from the inner effect to the outer active effect which would
// get them if the HMR wrapper wasn't there. Do this inside the block not outside
// so that HMR updates to the component will also update the nodes on the active effect.
/** @type {Effect} */ (active_effect).nodes = effect.nodes;
}, EFFECT_TRANSPARENT);
ran = true;
if (hydrating) {
// Insert start comment now that hydration is done, so it doesn't
// corrupt the hydration walk
anchor.before(start);
anchor = hydrate_node;
}
anchor.before(end);
assign_nodes(start, end);
return instance;
}

Loading…
Cancel
Save