Comparing version 5.5.3 to 5.5.4
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.5.3", | ||
"version": "5.5.4", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -1046,10 +1046,9 @@ /* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
/** | ||
* %thing% is invalid inside `<%parent%>` | ||
* %message%. The browser will 'repair' the HTML (by moving, removing, or inserting elements) which breaks Svelte's assumptions about the structure of your components. | ||
* @param {null | number | NodeLike} node | ||
* @param {string} thing | ||
* @param {string} parent | ||
* @param {string} message | ||
* @returns {never} | ||
*/ | ||
export function node_invalid_placement(node, thing, parent) { | ||
e(node, "node_invalid_placement", `${thing} is invalid inside \`<${parent}>\``); | ||
export function node_invalid_placement(node, message) { | ||
e(node, "node_invalid_placement", `${message}. The browser will 'repair' the HTML (by moving, removing, or inserting elements) which breaks Svelte's assumptions about the structure of your components.`); | ||
} | ||
@@ -1056,0 +1055,0 @@ |
@@ -15,4 +15,5 @@ /** @import { AST } from '#compiler' */ | ||
if (in_template && context.state.parent_element) { | ||
if (!is_tag_valid_with_parent('#text', context.state.parent_element)) { | ||
e.node_invalid_placement(node, '`{expression}`', context.state.parent_element); | ||
const message = is_tag_valid_with_parent('#text', context.state.parent_element); | ||
if (message) { | ||
e.node_invalid_placement(node, message); | ||
} | ||
@@ -19,0 +20,0 @@ } |
@@ -117,11 +117,8 @@ /** @import { AST } from '#compiler' */ | ||
if (ancestor.type === 'RegularElement' && ancestor.name === context.state.parent_element) { | ||
if (!is_tag_valid_with_parent(node.name, context.state.parent_element)) { | ||
const message = is_tag_valid_with_parent(node.name, context.state.parent_element); | ||
if (message) { | ||
if (only_warn) { | ||
w.node_invalid_placement_ssr( | ||
node, | ||
`\`<${node.name}>\``, | ||
context.state.parent_element | ||
); | ||
w.node_invalid_placement_ssr(node, message); | ||
} else { | ||
e.node_invalid_placement(node, `\`<${node.name}>\``, context.state.parent_element); | ||
e.node_invalid_placement(node, message); | ||
} | ||
@@ -135,7 +132,8 @@ } | ||
if (!is_tag_valid_with_ancestor(node.name, ancestors)) { | ||
const message = is_tag_valid_with_ancestor(node.name, ancestors); | ||
if (message) { | ||
if (only_warn) { | ||
w.node_invalid_placement_ssr(node, `\`<${node.name}>\``, ancestor.name); | ||
w.node_invalid_placement_ssr(node, message); | ||
} else { | ||
e.node_invalid_placement(node, `\`<${node.name}>\``, ancestor.name); | ||
e.node_invalid_placement(node, message); | ||
} | ||
@@ -142,0 +140,0 @@ } |
@@ -15,6 +15,7 @@ /** @import { AST } from '#compiler' */ | ||
if (in_template && context.state.parent_element && regex_not_whitespace.test(node.data)) { | ||
if (!is_tag_valid_with_parent('#text', context.state.parent_element)) { | ||
e.node_invalid_placement(node, 'Text node', context.state.parent_element); | ||
const message = is_tag_valid_with_parent('#text', context.state.parent_element); | ||
if (message) { | ||
e.node_invalid_placement(node, message); | ||
} | ||
} | ||
} |
@@ -757,9 +757,8 @@ /* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
/** | ||
* %thing% is invalid inside `<%parent%>`. When rendering this component on the server, the resulting HTML will be modified by the browser, likely resulting in a `hydration_mismatch` warning | ||
* %message%. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a `hydration_mismatch` warning | ||
* @param {null | NodeLike} node | ||
* @param {string} thing | ||
* @param {string} parent | ||
* @param {string} message | ||
*/ | ||
export function node_invalid_placement_ssr(node, thing, parent) { | ||
w(node, "node_invalid_placement_ssr", `${thing} is invalid inside \`<${parent}>\`. When rendering this component on the server, the resulting HTML will be modified by the browser, likely resulting in a \`hydration_mismatch\` warning`); | ||
export function node_invalid_placement_ssr(node, message) { | ||
w(node, "node_invalid_placement_ssr", `${message}. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a \`hydration_mismatch\` warning`); | ||
} | ||
@@ -766,0 +765,0 @@ |
@@ -138,14 +138,16 @@ /** | ||
/** | ||
* Returns false if the tag is not allowed inside the ancestor tag (which is grandparent and above) such that it will result | ||
* Returns an error message if the tag is not allowed inside the ancestor tag (which is grandparent and above) 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} child_tag | ||
* @param {string[]} ancestors All nodes starting with the parent, up until the ancestor, which means two entries minimum | ||
* @returns {boolean} | ||
* @param {string} [child_loc] | ||
* @param {string} [ancestor_loc] | ||
* @returns {string | null} | ||
*/ | ||
export function is_tag_valid_with_ancestor(tag, ancestors) { | ||
if (tag.includes('-')) return true; // custom elements can be anything | ||
export function is_tag_valid_with_ancestor(child_tag, ancestors, child_loc, ancestor_loc) { | ||
if (child_tag.includes('-')) return null; // custom elements can be anything | ||
const target = ancestors[ancestors.length - 1]; | ||
const disallowed = disallowed_children[target]; | ||
if (!disallowed) return true; | ||
const ancestor_tag = ancestors[ancestors.length - 1]; | ||
const disallowed = disallowed_children[ancestor_tag]; | ||
if (!disallowed) return null; | ||
@@ -155,7 +157,7 @@ if ('reset_by' in disallowed && disallowed.reset_by) { | ||
const ancestor = ancestors[i]; | ||
if (ancestor.includes('-')) return true; // custom elements can be anything | ||
if (ancestor.includes('-')) return null; // custom elements can be anything | ||
// A reset means that forbidden descendants are allowed again | ||
if (disallowed.reset_by.includes(ancestors[i])) { | ||
return true; | ||
return null; | ||
} | ||
@@ -165,30 +167,54 @@ } | ||
return 'descendant' in disallowed ? !disallowed.descendant.includes(tag) : true; | ||
if ('descendant' in disallowed && disallowed.descendant.includes(child_tag)) { | ||
const child = child_loc ? `\`<${child_tag}>\` (${child_loc})` : `\`<${child_tag}>\``; | ||
const ancestor = ancestor_loc | ||
? `\`<${ancestor_tag}>\` (${ancestor_loc})` | ||
: `\`<${ancestor_tag}>\``; | ||
return `${child} cannot be a descendant of ${ancestor}`; | ||
} | ||
return null; | ||
} | ||
/** | ||
* Returns false if the tag is not allowed inside the parent tag such that it will result | ||
* Returns an error message 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} child_tag | ||
* @param {string} parent_tag | ||
* @returns {boolean} | ||
* @param {string} [child_loc] | ||
* @param {string} [parent_loc] | ||
* @returns {string | null} | ||
*/ | ||
export function is_tag_valid_with_parent(tag, parent_tag) { | ||
if (tag.includes('-') || parent_tag?.includes('-')) return true; // custom elements can be anything | ||
export function is_tag_valid_with_parent(child_tag, parent_tag, child_loc, parent_loc) { | ||
if (child_tag.includes('-') || parent_tag?.includes('-')) return null; // custom elements can be anything | ||
const disallowed = disallowed_children[parent_tag]; | ||
const child = child_loc ? `\`<${child_tag}>\` (${child_loc})` : `\`<${child_tag}>\``; | ||
const parent = parent_loc ? `\`<${parent_tag}>\` (${parent_loc})` : `\`<${parent_tag}>\``; | ||
if (disallowed) { | ||
if ('direct' in disallowed && disallowed.direct.includes(tag)) { | ||
return false; | ||
if ('direct' in disallowed && disallowed.direct.includes(child_tag)) { | ||
return `${child} cannot be a direct child of ${parent}`; | ||
} | ||
if ('descendant' in disallowed && disallowed.descendant.includes(tag)) { | ||
return false; | ||
if ('descendant' in disallowed && disallowed.descendant.includes(child_tag)) { | ||
return `${child} cannot be a child of ${parent}`; | ||
} | ||
if ('only' in disallowed && disallowed.only) { | ||
return disallowed.only.includes(tag); | ||
if (disallowed.only.includes(child_tag)) { | ||
return null; | ||
} else { | ||
return `${child} cannot be a child of ${parent}. \`<${parent_tag}>\` only allows these children: ${disallowed.only.map((d) => `\`<${d}>\``).join(', ')}`; | ||
} | ||
} | ||
} | ||
switch (tag) { | ||
// These tags are only valid with a few parents that have special child | ||
// parsing rules - if we're down here, then none of those matched and | ||
// so we allow it only if we don't know what the parent is, as all other | ||
// cases are invalid (and we only get into this function if we know the parent). | ||
switch (child_tag) { | ||
case 'body': | ||
@@ -202,16 +228,15 @@ case 'caption': | ||
case 'html': | ||
return `${child} cannot be a child of ${parent}`; | ||
case 'thead': | ||
case 'tbody': | ||
case 'tfoot': | ||
return `${child} must be the child of a \`<table>\`, not a ${parent}`; | ||
case 'td': | ||
case 'tfoot': | ||
case 'th': | ||
case 'thead': | ||
return `${child} must be the child of a \`<tr>\`, not a ${parent}`; | ||
case 'tr': | ||
// These tags are only valid with a few parents that have special child | ||
// parsing rules - if we're down here, then none of those matched and | ||
// so we allow it only if we don't know what the parent is, as all other | ||
// cases are invalid (and we only get into this function if we know the parent). | ||
return false; | ||
return `\`<tr>\` must be the child of a \`<thead>\`, \`<tbody>\`, or \`<tfoot>\`, not a ${parent}`; | ||
} | ||
return true; | ||
return null; | ||
} |
@@ -284,2 +284,5 @@ import { DEV } from 'esm-env'; | ||
} | ||
} else if (delegated) { | ||
// @ts-ignore | ||
element[`__${event_name}`] = undefined; | ||
} | ||
@@ -286,0 +289,0 @@ } else if (key === 'style' && value != null) { |
@@ -7,6 +7,9 @@ /** @import { TaskCallback, Task, TaskEntry } from '#client' */ | ||
/** | ||
* @param {number} now | ||
* @returns {void} | ||
*/ | ||
function run_tasks(now) { | ||
function run_tasks() { | ||
// use `raf.now()` instead of the `requestAnimationFrame` callback argument, because | ||
// otherwise things can get wonky https://github.com/sveltejs/svelte/pull/14541 | ||
const now = raf.now(); | ||
raf.tasks.forEach((task) => { | ||
@@ -13,0 +16,0 @@ if (!task.c(now)) { |
@@ -37,8 +37,7 @@ /** @import { Component, Payload } from '#server' */ | ||
* @param {Payload} payload | ||
* @param {Element} parent | ||
* @param {Element} child | ||
* @param {string} message | ||
*/ | ||
function print_error(payload, parent, child) { | ||
var message = | ||
`node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n` + | ||
function print_error(payload, message) { | ||
message = | ||
`node_invalid_placement_ssr: ${message}\n\n` + | ||
'This can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.'; | ||
@@ -76,11 +75,19 @@ | ||
if (!is_tag_valid_with_parent(tag, parent.tag)) { | ||
print_error(payload, parent, child); | ||
} | ||
const child_loc = filename ? `${filename}:${line}:${column}` : undefined; | ||
const parent_loc = parent.filename | ||
? `${parent.filename}:${parent.line}:${parent.column}` | ||
: undefined; | ||
const message = is_tag_valid_with_parent(tag, parent.tag, child_loc, parent_loc); | ||
if (message) print_error(payload, message); | ||
while (ancestor != null) { | ||
ancestors.push(ancestor.tag); | ||
if (!is_tag_valid_with_ancestor(tag, ancestors)) { | ||
print_error(payload, ancestor, child); | ||
} | ||
const ancestor_loc = ancestor.filename | ||
? `${ancestor.filename}:${ancestor.line}:${ancestor.column}` | ||
: undefined; | ||
const message = is_tag_valid_with_ancestor(tag, ancestors, child_loc, ancestor_loc); | ||
if (message) print_error(payload, message); | ||
ancestor = ancestor.parent; | ||
@@ -87,0 +94,0 @@ } |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.5.3'; | ||
export const VERSION = '5.5.4'; | ||
export const PUBLIC_VERSION = '5'; |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2360585
52134