fix: svelte:element hydration in raw text elements#17974
fix: svelte:element hydration in raw text elements#17974sudip-kumar-prasad wants to merge 6 commits intosveltejs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: a2a5323 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
Fixes a hydration crash when <svelte:element> is used with raw-text elements (e.g. style/script) by ensuring hydration has a sentinel sibling to advance to, and adds a runtime-runes sample to cover the scenario.
Changes:
- Add a temporary comment node during hydration for raw-text
<svelte:element>sohydrate_next()can safely advance, then remove it. - Add a new runtime-runes sample exercising
<svelte:element this="style">with hydration enabled.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/svelte/src/internal/client/dom/blocks/svelte-element.js | Injects/removes a temporary comment node to avoid hydration traversal errors in raw-text elements. |
| packages/svelte/tests/runtime-runes/samples/svelte-element-style-hydration/main.svelte | New sample component rendering CSS via <svelte:element>. |
| packages/svelte/tests/runtime-runes/samples/svelte-element-style-hydration/_config.js | New sample config enabling hydration + expected HTML. |
Comments suppressed due to low confidence (1)
packages/svelte/src/internal/client/dom/blocks/svelte-element.js:105
- The temporary comment is appended before determining
child_anchor. For empty raw-text elements (e.g.<style></style>,<script></script>,<textarea></textarea>), this makesget_first_child(element)return the injected comment instead ofnull, so hydration stays enabled andhydrate_next()can still throw when it hits a missing sibling. Consider computingchild_anchorfirst, and only appending the comment whenchild_anchor !== nulland it has no next sibling (i.e. when there is existing SSR content that needs a sentinel).
if (hydrating && is_raw_text_element(next_tag)) { // prevent hydration glitches comment = document.createComment(''); element.append(comment); } // If hydrating, use the existing ssr comment as the anchor so that the // inner open and close methods can pick up the existing nodes correctly var child_anchor = hydrating ? get_first_child(element) : element.appendChild(create_text()); 💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/svelte/src/internal/client/dom/blocks/svelte-element.js Outdated Show resolved Hide resolved
packages/svelte/tests/runtime-runes/samples/svelte-element-style-hydration/_config.js Outdated Show resolved Hide resolved
packages/svelte/tests/runtime-runes/samples/svelte-element-style-hydration/_config.js Outdated Show resolved Hide resolved
| Hi 👋 This PR is ready for review. The hydration issue for raw text elements has been fixed and covered with a regression test. All feedback has been addressed, and a changeset is included. Could a maintainer please take a look and approve the workflow so remaining checks can run? Thanks! |
| Hi 👋 Just a quick update — I’ve addressed all feedback, synced with main, and updated the test expectations based on the current behavior after hydration. Everything should be ready now. Please let me know if any changes are needed! Would appreciate a review when you get time. Thanks! |
| Thank you but I'm not sure I understand what problem this addresses? I'm not seeing any hydration errors with script/style elements. Do you have an issue or a repro? |
| Hi Rich! Thanks for taking a look. This happens specifically during hydration (SSR → client) when svelte:element renders a raw-text element like <style> or <script>. Minimal repro Hydrating SSR output: Root cause Raw-text elements (style, script, etc.) do not get hydration markers (, ) in SSR output. Fix The fix temporarily inserts a comment node inside the raw-text element before render_fn runs, so hydrate_next() has a valid sibling to advance to. It’s then removed in a finally block, so it doesn’t affect the final DOM. The regression test (svelte-element-style-hydration) specifically covers the mode: ['hydrate'] path. |
Fix hydration error for raw text elements in svelte:element
Hydration was failing when using svelte:element with raw text elements like <style> and <script>.
This happened because $.append calls hydrate_next(), which expects a sibling node to move to. However, SSR doesn’t insert hydration markers inside raw text elements, so hydrate_next() ended up hitting a null sibling and throwing.
This change adds a temporary comment node during hydration so hydrate_next() has a valid sibling to work with. The comment is removed immediately after, so it doesn’t affect the final DOM.
Also added a regression test in runtime-runes to cover this case.