Skip to content

Commit f07d4da

Browse files
committed
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
1 parent f67cf20 commit f07d4da

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

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

@@ -415,6 +431,10 @@ export function set_attributes(
415431
}
416432
}
417433

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

0 commit comments

Comments
 (0)