Skip to content

Commit 07dd36a

Browse files
committed
Merge branch 'main' into remove-node-parent
2 parents 467c6ed + a6ad5af commit 07dd36a

File tree

9 files changed

+61
-35
lines changed

9 files changed

+61
-35
lines changed

.changeset/breezy-insects-live.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: show `:then` block for `null/undefined` value

.changeset/cool-gifts-sniff.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: relax html parent validation

packages/svelte/src/html-tree-validation.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,25 +167,23 @@ export function is_tag_valid_with_ancestor(tag, ancestors) {
167167
* Returns false if the tag is not allowed inside the parent tag such that it will result
168168
* in the browser repairing the HTML, which will likely result in an error during hydration.
169169
* @param {string} tag
170-
* @param {string | null} parent_tag
170+
* @param {string} parent_tag
171171
* @returns {boolean}
172172
*/
173173
export function is_tag_valid_with_parent(tag, parent_tag) {
174174
if (tag.includes('-') || parent_tag?.includes('-')) return true; // custom elements can be anything
175175

176-
if (parent_tag !== null) {
177-
const disallowed = disallowed_children[parent_tag];
176+
const disallowed = disallowed_children[parent_tag];
178177

179-
if (disallowed) {
180-
if ('direct' in disallowed && disallowed.direct.includes(tag)) {
181-
return false;
182-
}
183-
if ('descendant' in disallowed && disallowed.descendant.includes(tag)) {
184-
return false;
185-
}
186-
if ('only' in disallowed && disallowed.only) {
187-
return disallowed.only.includes(tag);
188-
}
178+
if (disallowed) {
179+
if ('direct' in disallowed && disallowed.direct.includes(tag)) {
180+
return false;
181+
}
182+
if ('descendant' in disallowed && disallowed.descendant.includes(tag)) {
183+
return false;
184+
}
185+
if ('only' in disallowed && disallowed.only) {
186+
return disallowed.only.includes(tag);
189187
}
190188
}
191189

packages/svelte/src/internal/client/dom/blocks/await.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '../../runtime.js';
1515
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
1616
import { queue_micro_task } from '../task.js';
17+
import { UNINITIALIZED } from '../../../../constants.js';
1718

1819
const PENDING = 0;
1920
const THEN = 1;
@@ -40,8 +41,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
4041
/** @type {any} */
4142
var component_function = DEV ? component_context?.function : null;
4243

43-
/** @type {V | Promise<V> | null} */
44-
var input;
44+
/** @type {V | Promise<V> | typeof UNINITIALIZED} */
45+
var input = UNINITIALIZED;
4546

4647
/** @type {Effect | null} */
4748
var pending_effect;
@@ -156,8 +157,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
156157
update(THEN, false);
157158
}
158159

159-
// Set the input to null, in order to disable the promise callbacks
160-
return () => (input = null);
160+
// Set the input to something else, in order to disable the promise callbacks
161+
return () => (input = UNINITIALIZED);
161162
});
162163

163164
if (hydrating) {

packages/svelte/src/internal/server/dev.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,12 @@ function stringify(element) {
3434

3535
/**
3636
* @param {Payload} payload
37-
* @param {Element | null} parent
37+
* @param {Element} parent
3838
* @param {Element} child
3939
*/
4040
function print_error(payload, parent, child) {
4141
var message =
42-
(parent === null
43-
? `node_invalid_placement_ssr: ${stringify(child)} needs a valid parent element\n\n`
44-
: `node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n`) +
42+
`node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n` +
4543
'This can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.';
4644

4745
if ((seen ??= new Set()).has(message)) return;
@@ -85,8 +83,6 @@ export function push_element(payload, tag, line, column) {
8583
}
8684
ancestor = ancestor.parent;
8785
}
88-
} else if (!is_tag_valid_with_parent(tag, null)) {
89-
print_error(payload, null, child);
9086
}
9187

9288
parent = child;
Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,27 @@
11
import { flushSync } from 'svelte';
2-
import { test } from '../../test';
2+
import { ok, test } from '../../test';
33

44
export default test({
55
compileOptions: {
66
dev: true
77
},
8-
test() {}
8+
test({ assert, target }) {
9+
const [btn1, btn2] = target.querySelectorAll('button');
10+
const p = target.querySelector('p');
11+
ok(p);
12+
13+
assert.htmlEqual(p.outerHTML, `<p></p>`);
14+
15+
btn1.click();
16+
flushSync();
17+
assert.htmlEqual(p.outerHTML, `<p>1</p>`);
18+
19+
btn2.click();
20+
flushSync();
21+
assert.htmlEqual(p.outerHTML, `<p></p>`);
22+
23+
btn1.click();
24+
flushSync();
25+
assert.htmlEqual(p.outerHTML, `<p>1</p>`);
26+
}
927
});
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
<script>
2-
let count = $state(43);
2+
let count = $state();
33
</script>
44

5-
{#await count}
6-
loading
7-
{:then count}
8-
{count}
9-
{/await}
5+
<button onclick={() => count = 1}>number</button>
6+
<button onclick={() => count = null}>nullify</button>
7+
8+
<p>
9+
{#await count}
10+
loading
11+
{:then count}
12+
{count}
13+
{/await}
14+
</p>

packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@ export default test({
55
dev: true
66
},
77

8-
html: `<p></p><h1>foo</h1><p></p><form></form> hello`,
8+
html: `<p></p><h1>foo</h1><p></p><form></form>`,
99

1010
recover: true,
1111

1212
mode: ['hydrate'],
1313

1414
errors: [
1515
'node_invalid_placement_ssr: `<p>` (main.svelte:6:0) cannot contain `<h1>` (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.',
16-
'node_invalid_placement_ssr: `<form>` (main.svelte:9:0) cannot contain `<form>` (form.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.',
17-
'node_invalid_placement_ssr: `<td>` (main.svelte:12:0) needs a valid parent element\n\nThis can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.'
16+
'node_invalid_placement_ssr: `<form>` (main.svelte:9:0) cannot contain `<form>` (form.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.'
1817
],
1918

2019
warnings: [

packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/main.svelte

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@
99
<form>
1010
<Form />
1111
</form>
12-
<td>hello</td>

0 commit comments

Comments
 (0)