Skip to content

Commit 3b7066f

Browse files
fix: ensure custom element updates don't run in hydration mode (#15217)
* fix: ensure custom element updates don't run in hydration mode When a custom element is created before Svelte hydration kicks in, it will scaffold itself, using the properties given via attributes. Now when a custom element property is set during Svelte's hydration, the Svelte custom element component could run logic like updating an each block. Without turning off hydration mode during that time, the update would try to pick up existing element nodes (because it thinks they must be there because of hydration mode), and crash. No test because it would require a setup where we can ensure the element is scaffolded before hydration runs. Fixes #15213 * changeset --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 6f392d6 commit 3b7066f

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

.changeset/light-ligers-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: ensure custom element updates don't run in hydration mode

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DEV } from 'esm-env';
2-
import { hydrating } from '../hydration.js';
2+
import { hydrating, set_hydrating } from '../hydration.js';
33
import { get_descriptors, get_prototype_of } from '../../../shared/utils.js';
44
import { create_event, delegate } from './events.js';
55
import { add_form_reset_listener, autofocus } from './misc.js';
@@ -213,6 +213,12 @@ export function set_custom_element_data(node, prop, value) {
213213
// or effect
214214
var previous_reaction = active_reaction;
215215
var previous_effect = active_effect;
216+
// If we're hydrating but the custom element is from Svelte, and it already scaffolded,
217+
// then it might run block logic in hydration mode, which we have to prevent.
218+
let was_hydrating = hydrating;
219+
if (hydrating) {
220+
set_hydrating(false);
221+
}
216222

217223
set_active_reaction(null);
218224
set_active_effect(null);
@@ -239,6 +245,9 @@ export function set_custom_element_data(node, prop, value) {
239245
} finally {
240246
set_active_reaction(previous_reaction);
241247
set_active_effect(previous_effect);
248+
if (was_hydrating) {
249+
set_hydrating(true);
250+
}
242251
}
243252
}
244253

@@ -262,6 +271,13 @@ export function set_attributes(
262271
is_custom_element = false,
263272
skip_warning = false
264273
) {
274+
// If we're hydrating but the custom element is from Svelte, and it already scaffolded,
275+
// then it might run block logic in hydration mode, which we have to prevent.
276+
let is_hydrating_custom_element = hydrating && is_custom_element;
277+
if (is_hydrating_custom_element) {
278+
set_hydrating(false);
279+
}
280+
265281
var current = prev || {};
266282
var is_option_element = element.tagName === 'OPTION';
267283

@@ -416,6 +432,10 @@ export function set_attributes(
416432
}
417433
}
418434

435+
if (is_hydrating_custom_element) {
436+
set_hydrating(true);
437+
}
438+
419439
return current;
420440
}
421441

0 commit comments

Comments
 (0)