From 9a47d991a3dc643f156ce94cbd717f35a4007f0f Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 27 Aug 2024 14:10:27 -0400 Subject: [PATCH] more --- .../src/compiler/phases/1-parse/index.js | 4 ++ .../compiler/phases/1-parse/state/element.js | 42 +++++++------------ .../visitors/shared/special-element.js | 4 +- .../samples/options-children/_config.js | 2 +- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 1bf52cd932..7429e325b0 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -8,6 +8,7 @@ import * as e from '../../errors.js'; import { create_fragment } from './utils/create.js'; import read_options from './read/options.js'; import { is_reserved } from '../../../utils.js'; +import { disallow_children } from '../2-analyze/visitors/shared/special-element.js'; const regex_position_indicator = / \(\d+:\d+\)$/; @@ -124,6 +125,9 @@ export class Parser { const options = /** @type {SvelteOptionsRaw} */ (this.root.fragment.nodes[options_index]); this.root.fragment.nodes.splice(options_index, 1); this.root.options = read_options(options); + + disallow_children(options); + // We need this for the old AST format Object.defineProperty(this.root.options, '__raw__', { value: options, 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 4a8afd7c9e..389dcd4c39 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -21,7 +21,7 @@ const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/; const regex_starts_with_invalid_attr_value = /^(\/>|[\s"'=<>`])/; /** @type {Map} */ -const root_only_special_elements = new Map([ +const root_only_meta_tags = new Map([ ['svelte:head', 'SvelteHead'], ['svelte:options', 'SvelteOptions'], ['svelte:window', 'SvelteWindow'], @@ -30,8 +30,8 @@ const root_only_special_elements = new Map([ ]); /** @type {Map} */ -const special_elements = new Map([ - ...root_only_special_elements, +const meta_tags = new Map([ + ...root_only_meta_tags, ['svelte:element', 'SvelteElement'], ['svelte:component', 'SvelteComponent'], ['svelte:self', 'SvelteSelf'], @@ -97,32 +97,20 @@ export default function element(parser) { const name = read_tag_name(parser); - if (root_only_special_elements.has(name)) { - if (is_closing_tag) { - if ( - ['svelte:options'].includes(name) && - /** @type {Compiler.ElementLike} */ (parent).fragment.nodes.length - ) { - e.svelte_meta_invalid_content( - /** @type {Compiler.ElementLike} */ (parent).fragment.nodes[0].start, - name - ); - } - } else { - if (name in parser.meta_tags) { - e.svelte_meta_duplicate(start, name); - } - - if (parent.type !== 'Root') { - e.svelte_meta_invalid_placement(start, name); - } + if (!is_closing_tag && root_only_meta_tags.has(name)) { + if (name in parser.meta_tags) { + e.svelte_meta_duplicate(start, name); + } - parser.meta_tags[name] = true; + if (parent.type !== 'Root') { + e.svelte_meta_invalid_placement(start, name); } + + parser.meta_tags[name] = true; } - const type = special_elements.has(name) - ? special_elements.get(name) + const type = meta_tags.has(name) + ? meta_tags.get(name) : regex_component_name.test(name) ? 'Component' : name === 'title' && parent_is_head(parser.stack) @@ -387,12 +375,12 @@ function read_tag_name(parser) { const start = parser.index; const name = parser.read_until(regex_whitespace_or_slash_or_closing_tag); - if (special_elements.has(name)) return name; + if (meta_tags.has(name)) return name; const end = start + name.length; if (name.startsWith('svelte:')) { - e.svelte_meta_invalid_tag({ start, end }, list(Array.from(special_elements.keys()))); + e.svelte_meta_invalid_tag({ start, end }, list(Array.from(meta_tags.keys()))); } if (!valid_tag_name.test(name)) { 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 index 8df9456b28..86e9f12199 100644 --- 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 @@ -1,8 +1,8 @@ -/** @import { SvelteBody, SvelteDocument, SvelteWindow } from '#compiler' */ +/** @import { SvelteBody, SvelteDocument, SvelteOptionsRaw, SvelteWindow } from '#compiler' */ import * as e from '../../../../errors.js'; /** - * @param {SvelteBody | SvelteDocument | SvelteWindow} node + * @param {SvelteBody | SvelteDocument | SvelteOptionsRaw | SvelteWindow} node */ export function disallow_children(node) { const { nodes } = node.fragment; diff --git a/packages/svelte/tests/compiler-errors/samples/options-children/_config.js b/packages/svelte/tests/compiler-errors/samples/options-children/_config.js index 1ed4778aa5..3ec671867a 100644 --- a/packages/svelte/tests/compiler-errors/samples/options-children/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/options-children/_config.js @@ -4,6 +4,6 @@ export default test({ error: { code: 'svelte_meta_invalid_content', message: ' cannot have children', - position: [16, 16] + position: [16, 24] } });