From 9e9fb2463cda29e5ed75601515651379ff328cfd Mon Sep 17 00:00:00 2001
From: Simon H <5968653+dummdidumm@users.noreply.github.com>
Date: Tue, 26 Nov 2024 16:00:54 +0100
Subject: [PATCH] fix: relax parent validation (#14442)
This reverts #13255 / #13158, and helps with the validation error part of #14120
If you would have a component like this...
```svelte
hi there |
```
...and then render it on the server via our `render` function like this:
```js
const result = render(Main);
```
...then right now you get an error saying that `td` is not valid at this position. But that doesn't seem right, because we should give people the benefit of the doubt: It may very well be that someone renders such a component and then correctly puts it into a `tr` tag themselves on the server (another example is rendering a full html document like in #14120).
All the other validation where there's a known parent (X not valid inside Y) is untouched by this.
Doing this as cleanup prior to tackling #13331
---
.changeset/cool-gifts-sniff.md | 5 ++++
packages/svelte/src/html-tree-validation.js | 24 +++++++++----------
packages/svelte/src/internal/server/dev.js | 8 ++-----
.../samples/invalid-html-ssr/_config.js | 5 ++--
.../samples/invalid-html-ssr/main.svelte | 1 -
5 files changed, 20 insertions(+), 23 deletions(-)
create mode 100644 .changeset/cool-gifts-sniff.md
diff --git a/.changeset/cool-gifts-sniff.md b/.changeset/cool-gifts-sniff.md
new file mode 100644
index 0000000000..ab9680309f
--- /dev/null
+++ b/.changeset/cool-gifts-sniff.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: relax html parent validation
diff --git a/packages/svelte/src/html-tree-validation.js b/packages/svelte/src/html-tree-validation.js
index da5567f56a..0ebf45e166 100644
--- a/packages/svelte/src/html-tree-validation.js
+++ b/packages/svelte/src/html-tree-validation.js
@@ -167,25 +167,23 @@ export function is_tag_valid_with_ancestor(tag, ancestors) {
* Returns false if the tag is not allowed inside the parent tag such that it will result
* in the browser repairing the HTML, which will likely result in an error during hydration.
* @param {string} tag
- * @param {string | null} parent_tag
+ * @param {string} parent_tag
* @returns {boolean}
*/
export function is_tag_valid_with_parent(tag, parent_tag) {
if (tag.includes('-') || parent_tag?.includes('-')) return true; // custom elements can be anything
- if (parent_tag !== null) {
- const disallowed = disallowed_children[parent_tag];
+ const disallowed = disallowed_children[parent_tag];
- if (disallowed) {
- if ('direct' in disallowed && disallowed.direct.includes(tag)) {
- return false;
- }
- if ('descendant' in disallowed && disallowed.descendant.includes(tag)) {
- return false;
- }
- if ('only' in disallowed && disallowed.only) {
- return disallowed.only.includes(tag);
- }
+ if (disallowed) {
+ if ('direct' in disallowed && disallowed.direct.includes(tag)) {
+ return false;
+ }
+ if ('descendant' in disallowed && disallowed.descendant.includes(tag)) {
+ return false;
+ }
+ if ('only' in disallowed && disallowed.only) {
+ return disallowed.only.includes(tag);
}
}
diff --git a/packages/svelte/src/internal/server/dev.js b/packages/svelte/src/internal/server/dev.js
index 61c7c6d5e8..145b37479b 100644
--- a/packages/svelte/src/internal/server/dev.js
+++ b/packages/svelte/src/internal/server/dev.js
@@ -34,14 +34,12 @@ function stringify(element) {
/**
* @param {Payload} payload
- * @param {Element | null} parent
+ * @param {Element} parent
* @param {Element} child
*/
function print_error(payload, parent, child) {
var message =
- (parent === null
- ? `node_invalid_placement_ssr: ${stringify(child)} needs a valid parent element\n\n`
- : `node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n`) +
+ `node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n` +
'This can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.';
if ((seen ??= new Set()).has(message)) return;
@@ -85,8 +83,6 @@ export function push_element(payload, tag, line, column) {
}
ancestor = ancestor.parent;
}
- } else if (!is_tag_valid_with_parent(tag, null)) {
- print_error(payload, null, child);
}
parent = child;
diff --git a/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js b/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js
index f7327d1608..d815d10fc7 100644
--- a/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js
@@ -5,7 +5,7 @@ export default test({
dev: true
},
- html: `foo
hello`,
+ html: `foo
`,
recover: true,
@@ -13,8 +13,7 @@ export default test({
errors: [
'node_invalid_placement_ssr: `` (main.svelte:6:0) cannot contain `
` (h1.svelte:1:0)\n\nThis can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.',
- 'node_invalid_placement_ssr: `