fix: hydration comments during hmr (#17975)

Closes #17972

Claude found this fix I had a look and I think it makes sense (we are
injecting a new comment which messes up the marching during hydration).

I'm slightly confused why this only applied to `css_props` but I guess
that's because there's an "hidden" element there which makes it special.

I don't super-like the `if` situation, but I guess it is what it is.

Also the test was using `hmr` without `dev` and this brought to my
attention that we were just assuming components return something while
it's not the case...I guess it doesn't really matter unless you are
using `hmr` in prod which is not a thing but fixing this is simple so we
might just as well doing it
pull/17980/head
Paolo Ricciuti 1 month ago committed by GitHub
parent 803c565feb
commit 425fba33fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: hydration comments during hmr

@ -34,7 +34,13 @@ export function hmr(fn) {
let start = create_comment();
let end = create_comment();
anchor.before(start);
// 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))) {
@ -52,13 +58,13 @@ export function hmr(fn) {
if (ran) set_should_intro(false);
// preserve getters/setters
Object.defineProperties(
instance,
Object.getOwnPropertyDescriptors(
// @ts-expect-error
new.target ? new component(anchor, props) : component(anchor, props)
)
);
var result =
// @ts-expect-error
new.target ? new component(anchor, props) : component(anchor, props);
// a component is not guaranteed to return something and we can't invoke getOwnPropertyDescriptors on undefined
if (result) {
Object.defineProperties(instance, Object.getOwnPropertyDescriptors(result));
}
if (ran) set_should_intro(true);
});
@ -67,6 +73,9 @@ export function hmr(fn) {
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;
}

@ -0,0 +1,7 @@
<h1>Hello</h1>
<style>
h1 {
color: var(--color);
}
</style>

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
compileOptions: {
hmr: true
}
});

@ -0,0 +1,5 @@
<script>
import Component from "./Component.svelte";
</script>
<Component --color="red" />
Loading…
Cancel
Save