Merge branch 'main' into remove-node-parent

pull/14447/head
Rich Harris 2 years ago
commit 07dd36afc3

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: show `:then` block for `null/undefined` value

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: relax html parent validation

@ -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);
}
}

@ -14,6 +14,7 @@ import {
} from '../../runtime.js';
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
import { queue_micro_task } from '../task.js';
import { UNINITIALIZED } from '../../../../constants.js';
const PENDING = 0;
const THEN = 1;
@ -40,8 +41,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
/** @type {any} */
var component_function = DEV ? component_context?.function : null;
/** @type {V | Promise<V> | null} */
var input;
/** @type {V | Promise<V> | typeof UNINITIALIZED} */
var input = UNINITIALIZED;
/** @type {Effect | null} */
var pending_effect;
@ -156,8 +157,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
update(THEN, false);
}
// Set the input to null, in order to disable the promise callbacks
return () => (input = null);
// Set the input to something else, in order to disable the promise callbacks
return () => (input = UNINITIALIZED);
});
if (hydrating) {

@ -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;

@ -1,9 +1,27 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
import { ok, test } from '../../test';
export default test({
compileOptions: {
dev: true
},
test() {}
test({ assert, target }) {
const [btn1, btn2] = target.querySelectorAll('button');
const p = target.querySelector('p');
ok(p);
assert.htmlEqual(p.outerHTML, `<p></p>`);
btn1.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p>1</p>`);
btn2.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p></p>`);
btn1.click();
flushSync();
assert.htmlEqual(p.outerHTML, `<p>1</p>`);
}
});

@ -1,9 +1,14 @@
<script>
let count = $state(43);
let count = $state();
</script>
{#await count}
loading
{:then count}
{count}
{/await}
<button onclick={() => count = 1}>number</button>
<button onclick={() => count = null}>nullify</button>
<p>
{#await count}
loading
{:then count}
{count}
{/await}
</p>

@ -5,7 +5,7 @@ export default test({
dev: true
},
html: `<p></p><h1>foo</h1><p></p><form></form> hello`,
html: `<p></p><h1>foo</h1><p></p><form></form>`,
recover: true,
@ -13,8 +13,7 @@ export default test({
errors: [
'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.',
'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.',
'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.'
'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.'
],
warnings: [

Loading…
Cancel
Save