diff --git a/packages/svelte/src/compiler/phases/1-parse/state/element.js b/packages/svelte/src/compiler/phases/1-parse/state/element.js index f7784aea90..4a8afd7c9e 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -100,7 +100,7 @@ export default function element(parser) { if (root_only_special_elements.has(name)) { if (is_closing_tag) { if ( - ['svelte:options', 'svelte:window', 'svelte:body', 'svelte:document'].includes(name) && + ['svelte:options'].includes(name) && /** @type {Compiler.ElementLike} */ (parent).fragment.nodes.length ) { e.svelte_meta_invalid_content( diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index d54a2b2e55..0c3dd0b856 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -52,11 +52,14 @@ import { SlotElement } from './visitors/SlotElement.js'; import { SnippetBlock } from './visitors/SnippetBlock.js'; import { SpreadAttribute } from './visitors/SpreadAttribute.js'; import { StyleDirective } from './visitors/StyleDirective.js'; +import { SvelteBody } from './visitors/SvelteBody.js'; import { SvelteComponent } from './visitors/SvelteComponent.js'; +import { SvelteDocument } from './visitors/SvelteDocument.js'; import { SvelteElement } from './visitors/SvelteElement.js'; import { SvelteFragment } from './visitors/SvelteFragment.js'; import { SvelteHead } from './visitors/SvelteHead.js'; import { SvelteSelf } from './visitors/SvelteSelf.js'; +import { SvelteWindow } from './visitors/SvelteWindow.js'; import { TaggedTemplateExpression } from './visitors/TaggedTemplateExpression.js'; import { Text } from './visitors/Text.js'; import { TitleElement } from './visitors/TitleElement.js'; @@ -158,11 +161,14 @@ const visitors = { SnippetBlock, SpreadAttribute, StyleDirective, - SvelteHead, + SvelteBody, + SvelteComponent, + SvelteDocument, SvelteElement, SvelteFragment, - SvelteComponent, + SvelteHead, SvelteSelf, + SvelteWindow, TaggedTemplateExpression, Text, TitleElement, diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteBody.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteBody.js new file mode 100644 index 0000000000..72a2f0806e --- /dev/null +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteBody.js @@ -0,0 +1,12 @@ +/** @import { SvelteBody } from '#compiler' */ +/** @import { Context } from '../types' */ +import { disallow_children } from './shared/special-element.js'; + +/** + * @param {SvelteBody} node + * @param {Context} context + */ +export function SvelteBody(node, context) { + disallow_children(node); + context.next(); +} diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteDocument.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteDocument.js new file mode 100644 index 0000000000..eb61231d66 --- /dev/null +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteDocument.js @@ -0,0 +1,12 @@ +/** @import { SvelteDocument } from '#compiler' */ +/** @import { Context } from '../types' */ +import { disallow_children } from './shared/special-element.js'; + +/** + * @param {SvelteDocument} node + * @param {Context} context + */ +export function SvelteDocument(node, context) { + disallow_children(node); + context.next(); +} diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteWindow.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteWindow.js new file mode 100644 index 0000000000..53175d2ef6 --- /dev/null +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteWindow.js @@ -0,0 +1,12 @@ +/** @import { SvelteWindow } from '#compiler' */ +/** @import { Context } from '../types' */ +import { disallow_children } from './shared/special-element.js'; + +/** + * @param {SvelteWindow} node + * @param {Context} context + */ +export function SvelteWindow(node, context) { + disallow_children(node); + context.next(); +} diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/special-element.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/special-element.js new file mode 100644 index 0000000000..8df9456b28 --- /dev/null +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/special-element.js @@ -0,0 +1,16 @@ +/** @import { SvelteBody, SvelteDocument, SvelteWindow } from '#compiler' */ +import * as e from '../../../../errors.js'; + +/** + * @param {SvelteBody | SvelteDocument | SvelteWindow} node + */ +export function disallow_children(node) { + const { nodes } = node.fragment; + + if (nodes.length > 0) { + const first = nodes[0]; + const last = nodes[nodes.length - 1]; + + e.svelte_meta_invalid_content({ start: first.start, end: last.end }, node.name); + } +} diff --git a/packages/svelte/tests/compiler-errors/samples/window-children/_config.js b/packages/svelte/tests/compiler-errors/samples/window-children/_config.js index a336cf1cef..066b3d0025 100644 --- a/packages/svelte/tests/compiler-errors/samples/window-children/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/window-children/_config.js @@ -4,6 +4,6 @@ export default test({ error: { code: 'svelte_meta_invalid_content', message: ' cannot have children', - position: [15, 15] + position: [15, 23] } });