From 140d6b1e2cd5fb837b6e14fec208f3c71d6456d0 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 4 Nov 2024 22:36:29 +0000 Subject: [PATCH] feat: allow reserved snippet names when embedded in component --- .changeset/strong-donkeys-matter.md | 5 +++++ .../src/compiler/phases/1-parse/state/tag.js | 2 +- .../compiler/phases/3-transform/client/utils.js | 14 ++++++++++++++ .../3-transform/client/visitors/SnippetBlock.js | 7 ++++++- .../client/visitors/shared/component.js | 13 +++++++------ .../3-transform/server/visitors/SnippetBlock.js | 8 +++++++- .../server/visitors/shared/component.js | 14 ++++++++------ .../src/compiler/phases/3-transform/utils.js | 16 +++++++++++++++- .../samples/snippet-reserved/Child.svelte | 5 +++++ .../samples/snippet-reserved/_config.js | 5 +++++ .../samples/snippet-reserved/main.svelte | 9 +++++++++ 11 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 .changeset/strong-donkeys-matter.md create mode 100644 packages/svelte/tests/runtime-runes/samples/snippet-reserved/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/snippet-reserved/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/snippet-reserved/main.svelte diff --git a/.changeset/strong-donkeys-matter.md b/.changeset/strong-donkeys-matter.md new file mode 100644 index 000000000000..c37dda5cd670 --- /dev/null +++ b/.changeset/strong-donkeys-matter.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: allow reserved snippet names when embedded in component diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index de118960ecea..8d11710399c4 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -271,7 +271,7 @@ function open(parser) { parser.require_whitespace(); const name_start = parser.index; - const name = parser.read_identifier(); + const name = parser.read_identifier(parser.stack.at(-1)?.type === 'Component'); const name_end = parser.index; if (name === null) { diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js index 2647f0a3be3b..bb1f6c9e3881 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js @@ -326,3 +326,17 @@ export function can_inline_variable(binding) { binding.initial?.type === 'Literal' ); } + +/** + * @param {Statement[]} statements + */ +export function get_variable_declaration_name(statements) { + if ( + statements.length !== 1 || + statements[0].type !== 'VariableDeclaration' || + statements[0].declarations[0].id?.type !== 'Identifier' + ) { + return null; + } + return statements[0].declarations[0].id.name; +} diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js index 814fd3b0fb29..272d29b24607 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js @@ -1,6 +1,7 @@ /** @import { BlockStatement, Expression, Identifier, Pattern, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ +import { is_reserved } from '../../../../../utils.js'; import { dev } from '../../../../state.js'; import { extract_paths } from '../../../../utils/ast.js'; import * as b from '../../../../utils/builders.js'; @@ -79,7 +80,11 @@ export function SnippetBlock(node, context) { snippet = b.call('$.wrap_snippet', b.id(context.state.analysis.name), snippet); } - const declaration = b.const(node.expression, snippet); + const id_expression = + node.expression.type === 'Identifier' && is_reserved(node.expression.name) + ? b.id(`$_${node.expression.name}`) + : node.expression; + const declaration = b.const(id_expression, snippet); // Top-level snippets are hoisted so they can be referenced in the ` + +{@render catch_snippet()} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-reserved/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-reserved/_config.js new file mode 100644 index 000000000000..33e7def9f1a2 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-reserved/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: `

hello world

` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-reserved/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-reserved/main.svelte new file mode 100644 index 000000000000..c8b3a6348406 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-reserved/main.svelte @@ -0,0 +1,9 @@ + + + + {#snippet catch()} +

hello world

+ {/snippet} +