From 8f3924177a914df4fb883478dc109386f408d4ee Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Sun, 27 Jul 2025 15:12:03 -0700 Subject: [PATCH 1/6] chore: remove some todos --- .changeset/happy-countries-dance.md | 5 ++++ packages/svelte/src/compiler/legacy.js | 2 +- packages/svelte/src/compiler/migrate/index.js | 6 ++--- .../src/compiler/phases/1-parse/index.js | 1 - .../compiler/phases/1-parse/state/element.js | 6 ++--- .../src/compiler/phases/2-analyze/index.js | 4 ++-- .../phases/2-analyze/visitors/SnippetBlock.js | 2 +- .../phases/2-analyze/visitors/Text.js | 2 +- .../2-analyze/visitors/shared/a11y/index.js | 2 +- .../2-analyze/visitors/shared/component.js | 4 ++-- .../2-analyze/visitors/shared/element.js | 2 +- .../3-transform/client/transform-client.js | 4 ++-- .../client/visitors/CallExpression.js | 2 +- .../{Comment.js => TemplateComment.js} | 4 ++-- .../server/visitors/shared/utils.js | 8 +++---- .../src/compiler/phases/3-transform/utils.js | 4 ++-- packages/svelte/src/compiler/types/css.d.ts | 2 +- .../src/compiler/types/legacy-nodes.d.ts | 2 +- .../svelte/src/compiler/types/template.d.ts | 21 ++++++++++++----- .../samples/comment-with-ignores/output.json | 2 +- .../parser-legacy/samples/comment/output.json | 2 +- .../dynamic-element-string/output.json | 4 ++-- .../samples/comment-before-script/output.json | 2 +- packages/svelte/types/index.d.ts | 23 +++++++++++++------ 24 files changed, 69 insertions(+), 47 deletions(-) create mode 100644 .changeset/happy-countries-dance.md rename packages/svelte/src/compiler/phases/3-transform/client/visitors/{Comment.js => TemplateComment.js} (77%) diff --git a/.changeset/happy-countries-dance.md b/.changeset/happy-countries-dance.md new file mode 100644 index 000000000000..641cf21fd87c --- /dev/null +++ b/.changeset/happy-countries-dance.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: remove some todos diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index 85345bca4a22..817ade97f771 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -190,7 +190,7 @@ export function convert(source, ast) { ClassDirective(node) { return { ...node, type: 'Class' }; }, - Comment(node) { + TemplateComment(node) { return { ...node, ignores: extract_svelte_ignore(node.start, node.data, false) diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 6b2e6cda70a4..eeda67f29c78 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -1362,7 +1362,7 @@ const template = { ); } }, - Comment(node, { state }) { + TemplateComment(node, { state }) { const migrated = migrate_svelte_ignore(node.data); if (migrated !== node.data) { state.str.overwrite(node.start + ''.length, migrated); @@ -1707,14 +1707,14 @@ function extract_type_and_comment(declarator, state, path) { } // Ensure modifiers are applied in the same order as Svelte 4 -const modifier_order = [ +const modifier_order = /** @type {const} */ ([ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation', 'self', 'trusted', 'once' -]; +]); /** * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteWindow | AST.SvelteDocument | AST.SvelteBody} element diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 77cc2bf3fa43..a7482b2caf3e 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -1,5 +1,4 @@ /** @import { AST } from '#compiler' */ -/** @import { Comment } from 'estree' */ // @ts-expect-error acorn type definitions are borked in the release we use import { isIdentifierStart, isIdentifierChar } from 'acorn'; import fragment from './state/fragment.js'; 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 87332f647d86..97c0da7e7983 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -59,7 +59,7 @@ export default function element(parser) { parser.eat('-->', true); parser.append({ - type: 'Comment', + type: 'TemplateComment', start, end: parser.index, data @@ -302,7 +302,7 @@ export default function element(parser) { if (is_top_level_script_or_style) { parser.eat('>', true); - /** @type {AST.Comment | null} */ + /** @type {AST.TemplateComment | null} */ let prev_comment = null; for (let i = current.fragment.nodes.length - 1; i >= 0; i--) { const node = current.fragment.nodes[i]; @@ -311,7 +311,7 @@ export default function element(parser) { break; } - if (node.type === 'Comment') { + if (node.type === 'TemplateComment') { prev_comment = node; break; } else if (node.type !== 'Text' || node.data.trim()) { diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index cd44fd998aed..58ba7aed93a0 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -89,13 +89,13 @@ const visitors = { /** @type {string[]} */ const ignores = []; - if (parent?.type === 'Fragment' && node.type !== 'Comment' && node.type !== 'Text') { + if (parent?.type === 'Fragment' && node.type !== 'TemplateComment' && node.type !== 'Text') { const idx = parent.nodes.indexOf(/** @type {any} */ (node)); for (let i = idx - 1; i >= 0; i--) { const prev = parent.nodes[i]; - if (prev.type === 'Comment') { + if (prev.type === 'TemplateComment') { ignores.push( ...extract_svelte_ignore( prev.start + 4 /* '` : escape_html(node.data); + node.type === 'TemplateComment' ? `` : escape_html(node.data); } else { const evaluated = state.scope.evaluate(node.expression); @@ -68,7 +68,7 @@ export function process_children(nodes, { visit, state }) { for (let i = 0; i < nodes.length; i += 1) { const node = nodes[i]; - if (node.type === 'Text' || node.type === 'Comment' || node.type === 'ExpressionTag') { + if (node.type === 'Text' || node.type === 'TemplateComment' || node.type === 'ExpressionTag') { sequence.push(node); } else { if (sequence.length > 0) { diff --git a/packages/svelte/src/compiler/phases/3-transform/utils.js b/packages/svelte/src/compiler/phases/3-transform/utils.js index 1445ce3aa6b1..29f8c0847377 100644 --- a/packages/svelte/src/compiler/phases/3-transform/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/utils.js @@ -165,7 +165,7 @@ export function clean_nodes( const regular = []; for (const node of nodes) { - if (node.type === 'Comment' && !preserve_comments) { + if (node.type === 'TemplateComment' && !preserve_comments) { continue; } @@ -285,7 +285,7 @@ export function clean_nodes( // and would still call node.replaceWith() on the script tag, it would be a no-op because the script tag has no parent. if (trimmed.length === 1 && first.type === 'RegularElement' && first.name === 'script') { trimmed.push({ - type: 'Comment', + type: 'TemplateComment', data: '', start: -1, end: -1 diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index 154a06ffb11c..da15731f4ad4 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -15,7 +15,7 @@ export namespace _CSS { end: number; styles: string; /** Possible comment atop the style tag */ - comment: AST.Comment | null; + comment: AST.TemplateComment | null; }; } diff --git a/packages/svelte/src/compiler/types/legacy-nodes.d.ts b/packages/svelte/src/compiler/types/legacy-nodes.d.ts index 389fc923327a..6db84840b627 100644 --- a/packages/svelte/src/compiler/types/legacy-nodes.d.ts +++ b/packages/svelte/src/compiler/types/legacy-nodes.d.ts @@ -210,7 +210,7 @@ export interface LegacyWindow extends BaseElement { } export interface LegacyComment extends BaseNode { - type: 'Comment'; + type: 'TemplateComment'; /** the contents of the comment */ data: string; /** any svelte-ignore directives — would result in ['a', 'b', 'c'] */ diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index de06a4146933..47c0fba19585 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -43,7 +43,7 @@ export namespace AST { export interface Fragment { type: 'Fragment'; - nodes: Array; + nodes: Array; /** @internal */ metadata: { /** @@ -144,9 +144,8 @@ export namespace AST { } /** An HTML comment */ - // TODO rename to disambiguate - export interface Comment extends BaseNode { - type: 'Comment'; + export interface TemplateComment extends BaseNode { + type: 'TemplateComment'; /** the contents of the comment */ data: string; } @@ -247,7 +246,17 @@ export namespace AST { name: string; /** The 'y' in `on:x={y}` */ expression: null | Expression; - modifiers: string[]; // TODO specify + modifiers: Array< + | 'capture' + | 'nonpassive' + | 'once' + | 'passive' + | 'preventDefault' + | 'self' + | 'stopImmediatePropagation' + | 'stopPropagation' + | 'trusted' + >; /** @internal */ metadata: { expression: ExpressionMetadata; @@ -604,7 +613,7 @@ export namespace AST { | AST.SpreadAttribute | Directive | AST.AttachTag - | AST.Comment + | AST.TemplateComment | Block; export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script; diff --git a/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json b/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json index cf2dc9f75209..8b067e5e1388 100644 --- a/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json +++ b/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json @@ -5,7 +5,7 @@ "end": 31, "children": [ { - "type": "Comment", + "type": "TemplateComment", "start": 0, "end": 31, "data": " svelte-ignore foo, bar ", diff --git a/packages/svelte/tests/parser-legacy/samples/comment/output.json b/packages/svelte/tests/parser-legacy/samples/comment/output.json index 6017db404cb9..ce455d5441f1 100644 --- a/packages/svelte/tests/parser-legacy/samples/comment/output.json +++ b/packages/svelte/tests/parser-legacy/samples/comment/output.json @@ -5,7 +5,7 @@ "end": 18, "children": [ { - "type": "Comment", + "type": "TemplateComment", "start": 0, "end": 18, "data": " a comment ", diff --git a/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json b/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json index 9ba15d604484..9167aba26503 100644 --- a/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json +++ b/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json @@ -21,7 +21,7 @@ "data": "\n" }, { - "type": "Comment", + "type": "TemplateComment", "start": 45, "end": 69, "data": " prettier-ignore ", @@ -83,7 +83,7 @@ "data": "\n" }, { - "type": "Comment", + "type": "TemplateComment", "start": 162, "end": 186, "data": " prettier-ignore ", diff --git a/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json b/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json index 1aca0ce03607..c897a268ab7f 100644 --- a/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json +++ b/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json @@ -8,7 +8,7 @@ "type": "Fragment", "nodes": [ { - "type": "Comment", + "type": "TemplateComment", "start": 0, "end": 27, "data": "should not error out" diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 9ea45af7e6b7..5a606f814748 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -1145,7 +1145,7 @@ declare module 'svelte/compiler' { export interface Fragment { type: 'Fragment'; - nodes: Array; + nodes: Array; } export interface Root extends BaseNode { @@ -1220,9 +1220,8 @@ declare module 'svelte/compiler' { } /** An HTML comment */ - // TODO rename to disambiguate - export interface Comment extends BaseNode { - type: 'Comment'; + export interface TemplateComment extends BaseNode { + type: 'TemplateComment'; /** the contents of the comment */ data: string; } @@ -1296,7 +1295,17 @@ declare module 'svelte/compiler' { name: string; /** The 'y' in `on:x={y}` */ expression: null | Expression; - modifiers: string[]; + modifiers: Array< + | 'capture' + | 'nonpassive' + | 'once' + | 'passive' + | 'preventDefault' + | 'self' + | 'stopImmediatePropagation' + | 'stopPropagation' + | 'trusted' + >; } /** A `style:` directive */ @@ -1544,7 +1553,7 @@ declare module 'svelte/compiler' { | AST.SpreadAttribute | Directive | AST.AttachTag - | AST.Comment + | AST.TemplateComment | Block; export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script; @@ -1599,7 +1608,7 @@ declare module 'svelte/compiler' { end: number; styles: string; /** Possible comment atop the style tag */ - comment: AST.Comment | null; + comment: AST.TemplateComment | null; }; } From 7f47f86d5ab76209e1bcdf2ebdefdc65f2dc82db Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Sun, 27 Jul 2025 15:21:25 -0700 Subject: [PATCH 2/6] fix --- .../phases/3-transform/client/visitors/CallExpression.js | 6 ++++-- packages/svelte/src/compiler/phases/scope.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js index dead8465aa7e..608c62d3ee97 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js @@ -2,7 +2,7 @@ /** @import { Context } from '../types' */ import { dev, is_ignored } from '../../../../state.js'; import * as b from '#compiler/builders'; -import { get_rune } from '../../../scope.js'; +import { get_rune, UNKNOWN } from '../../../scope.js'; import { transform_inspect_rune } from '../../utils.js'; import { should_proxy } from '../utils.js'; @@ -82,7 +82,9 @@ export function CallExpression(node, context) { ['debug', 'dir', 'error', 'group', 'groupCollapsed', 'info', 'log', 'trace', 'warn'].includes( node.callee.property.name ) && - node.arguments.some((arg) => arg.type === 'SpreadElement' || !context.state.scope.evaluate(arg).is_known) + node.arguments.some( + (arg) => arg.type === 'SpreadElement' || !context.state.scope.evaluate(arg).values.has(UNKNOWN) + ) ) { return b.call( node.callee, diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js index 700e098e4511..b72ec705ab9c 100644 --- a/packages/svelte/src/compiler/phases/scope.js +++ b/packages/svelte/src/compiler/phases/scope.js @@ -16,7 +16,7 @@ import { is_reserved, is_rune } from '../../utils.js'; import { determine_slot } from '../utils/slot.js'; import { validate_identifier_name } from './2-analyze/visitors/shared/utils.js'; -const UNKNOWN = Symbol('unknown'); +export const UNKNOWN = Symbol('unknown'); /** Includes `BigInt` */ const NUMBER = Symbol('number'); const STRING = Symbol('string'); From 528ff394c4510525759f6525f0e95a955b34acda Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Sun, 27 Jul 2025 15:22:15 -0700 Subject: [PATCH 3/6] fix --- .../phases/3-transform/client/visitors/OnDirective.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js index 7a66a8ecbb41..0ee3b0fb1046 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js @@ -3,14 +3,14 @@ import * as b from '#compiler/builders'; import { build_event, build_event_handler } from './shared/events.js'; -const modifiers = [ +const modifiers = /** @type {const} */ ([ 'stopPropagation', 'stopImmediatePropagation', 'preventDefault', 'self', 'trusted', 'once' -]; +]); /** * @param {AST.OnDirective} node From e2f4ad359fba9f393f0bc3ebbbcb56384f2910a8 Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Sun, 27 Jul 2025 15:23:06 -0700 Subject: [PATCH 4/6] doh --- .../phases/3-transform/client/visitors/CallExpression.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js index 608c62d3ee97..069357924539 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js @@ -83,7 +83,7 @@ export function CallExpression(node, context) { node.callee.property.name ) && node.arguments.some( - (arg) => arg.type === 'SpreadElement' || !context.state.scope.evaluate(arg).values.has(UNKNOWN) + (arg) => arg.type === 'SpreadElement' || context.state.scope.evaluate(arg).values.has(UNKNOWN) ) ) { return b.call( From 719860a27c3d6e9813269c65dd8835fc4bfd5b89 Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:42:13 -0700 Subject: [PATCH 5/6] convert `TemplateComment` back to `Comment` --- packages/svelte/src/compiler/legacy.js | 2 +- packages/svelte/src/compiler/migrate/index.js | 2 +- .../src/compiler/phases/1-parse/state/element.js | 6 +++--- .../svelte/src/compiler/phases/2-analyze/index.js | 4 ++-- .../phases/2-analyze/visitors/SnippetBlock.js | 2 +- .../src/compiler/phases/2-analyze/visitors/Text.js | 2 +- .../phases/2-analyze/visitors/shared/a11y/index.js | 2 +- .../phases/2-analyze/visitors/shared/component.js | 4 ++-- .../phases/2-analyze/visitors/shared/element.js | 2 +- .../phases/3-transform/client/transform-client.js | 4 ++-- .../visitors/{TemplateComment.js => Comment.js} | 4 ++-- .../3-transform/server/visitors/shared/utils.js | 8 ++++---- .../svelte/src/compiler/phases/3-transform/utils.js | 4 ++-- packages/svelte/src/compiler/types/css.d.ts | 2 +- packages/svelte/src/compiler/types/legacy-nodes.d.ts | 2 +- packages/svelte/src/compiler/types/template.d.ts | 9 +++++---- .../samples/comment-with-ignores/output.json | 2 +- .../tests/parser-legacy/samples/comment/output.json | 2 +- .../samples/dynamic-element-string/output.json | 4 ++-- .../samples/comment-before-script/output.json | 2 +- packages/svelte/types/index.d.ts | 11 ++++++----- 21 files changed, 41 insertions(+), 39 deletions(-) rename packages/svelte/src/compiler/phases/3-transform/client/visitors/{TemplateComment.js => Comment.js} (77%) diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index 817ade97f771..85345bca4a22 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -190,7 +190,7 @@ export function convert(source, ast) { ClassDirective(node) { return { ...node, type: 'Class' }; }, - TemplateComment(node) { + Comment(node) { return { ...node, ignores: extract_svelte_ignore(node.start, node.data, false) diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index eeda67f29c78..eb0e4eff8cc4 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -1362,7 +1362,7 @@ const template = { ); } }, - TemplateComment(node, { state }) { + Comment(node, { state }) { const migrated = migrate_svelte_ignore(node.data); if (migrated !== node.data) { state.str.overwrite(node.start + ''.length, migrated); 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 97c0da7e7983..87332f647d86 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -59,7 +59,7 @@ export default function element(parser) { parser.eat('-->', true); parser.append({ - type: 'TemplateComment', + type: 'Comment', start, end: parser.index, data @@ -302,7 +302,7 @@ export default function element(parser) { if (is_top_level_script_or_style) { parser.eat('>', true); - /** @type {AST.TemplateComment | null} */ + /** @type {AST.Comment | null} */ let prev_comment = null; for (let i = current.fragment.nodes.length - 1; i >= 0; i--) { const node = current.fragment.nodes[i]; @@ -311,7 +311,7 @@ export default function element(parser) { break; } - if (node.type === 'TemplateComment') { + if (node.type === 'Comment') { prev_comment = node; break; } else if (node.type !== 'Text' || node.data.trim()) { diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 58ba7aed93a0..cd44fd998aed 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -89,13 +89,13 @@ const visitors = { /** @type {string[]} */ const ignores = []; - if (parent?.type === 'Fragment' && node.type !== 'TemplateComment' && node.type !== 'Text') { + if (parent?.type === 'Fragment' && node.type !== 'Comment' && node.type !== 'Text') { const idx = parent.nodes.indexOf(/** @type {any} */ (node)); for (let i = idx - 1; i >= 0; i--) { const prev = parent.nodes[i]; - if (prev.type === 'TemplateComment') { + if (prev.type === 'Comment') { ignores.push( ...extract_svelte_ignore( prev.start + 4 /* '` : escape_html(node.data); + node.type === 'Comment' ? `` : escape_html(node.data); } else { const evaluated = state.scope.evaluate(node.expression); @@ -68,7 +68,7 @@ export function process_children(nodes, { visit, state }) { for (let i = 0; i < nodes.length; i += 1) { const node = nodes[i]; - if (node.type === 'Text' || node.type === 'TemplateComment' || node.type === 'ExpressionTag') { + if (node.type === 'Text' || node.type === 'Comment' || node.type === 'ExpressionTag') { sequence.push(node); } else { if (sequence.length > 0) { diff --git a/packages/svelte/src/compiler/phases/3-transform/utils.js b/packages/svelte/src/compiler/phases/3-transform/utils.js index 29f8c0847377..1445ce3aa6b1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/utils.js @@ -165,7 +165,7 @@ export function clean_nodes( const regular = []; for (const node of nodes) { - if (node.type === 'TemplateComment' && !preserve_comments) { + if (node.type === 'Comment' && !preserve_comments) { continue; } @@ -285,7 +285,7 @@ export function clean_nodes( // and would still call node.replaceWith() on the script tag, it would be a no-op because the script tag has no parent. if (trimmed.length === 1 && first.type === 'RegularElement' && first.name === 'script') { trimmed.push({ - type: 'TemplateComment', + type: 'Comment', data: '', start: -1, end: -1 diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index da15731f4ad4..154a06ffb11c 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -15,7 +15,7 @@ export namespace _CSS { end: number; styles: string; /** Possible comment atop the style tag */ - comment: AST.TemplateComment | null; + comment: AST.Comment | null; }; } diff --git a/packages/svelte/src/compiler/types/legacy-nodes.d.ts b/packages/svelte/src/compiler/types/legacy-nodes.d.ts index 6db84840b627..389fc923327a 100644 --- a/packages/svelte/src/compiler/types/legacy-nodes.d.ts +++ b/packages/svelte/src/compiler/types/legacy-nodes.d.ts @@ -210,7 +210,7 @@ export interface LegacyWindow extends BaseElement { } export interface LegacyComment extends BaseNode { - type: 'TemplateComment'; + type: 'Comment'; /** the contents of the comment */ data: string; /** any svelte-ignore directives — would result in ['a', 'b', 'c'] */ diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index 47c0fba19585..058a1a8e66c3 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -43,7 +43,7 @@ export namespace AST { export interface Fragment { type: 'Fragment'; - nodes: Array; + nodes: Array; /** @internal */ metadata: { /** @@ -144,8 +144,9 @@ export namespace AST { } /** An HTML comment */ - export interface TemplateComment extends BaseNode { - type: 'TemplateComment'; + // TODO rename to disambiguate + export interface Comment extends BaseNode { + type: 'Comment'; /** the contents of the comment */ data: string; } @@ -613,7 +614,7 @@ export namespace AST { | AST.SpreadAttribute | Directive | AST.AttachTag - | AST.TemplateComment + | AST.Comment | Block; export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script; diff --git a/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json b/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json index 8b067e5e1388..cf2dc9f75209 100644 --- a/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json +++ b/packages/svelte/tests/parser-legacy/samples/comment-with-ignores/output.json @@ -5,7 +5,7 @@ "end": 31, "children": [ { - "type": "TemplateComment", + "type": "Comment", "start": 0, "end": 31, "data": " svelte-ignore foo, bar ", diff --git a/packages/svelte/tests/parser-legacy/samples/comment/output.json b/packages/svelte/tests/parser-legacy/samples/comment/output.json index ce455d5441f1..6017db404cb9 100644 --- a/packages/svelte/tests/parser-legacy/samples/comment/output.json +++ b/packages/svelte/tests/parser-legacy/samples/comment/output.json @@ -5,7 +5,7 @@ "end": 18, "children": [ { - "type": "TemplateComment", + "type": "Comment", "start": 0, "end": 18, "data": " a comment ", diff --git a/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json b/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json index 9167aba26503..9ba15d604484 100644 --- a/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json +++ b/packages/svelte/tests/parser-legacy/samples/dynamic-element-string/output.json @@ -21,7 +21,7 @@ "data": "\n" }, { - "type": "TemplateComment", + "type": "Comment", "start": 45, "end": 69, "data": " prettier-ignore ", @@ -83,7 +83,7 @@ "data": "\n" }, { - "type": "TemplateComment", + "type": "Comment", "start": 162, "end": 186, "data": " prettier-ignore ", diff --git a/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json b/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json index c897a268ab7f..1aca0ce03607 100644 --- a/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json +++ b/packages/svelte/tests/parser-modern/samples/comment-before-script/output.json @@ -8,7 +8,7 @@ "type": "Fragment", "nodes": [ { - "type": "TemplateComment", + "type": "Comment", "start": 0, "end": 27, "data": "should not error out" diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 5a606f814748..64aa9e23baf6 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -1145,7 +1145,7 @@ declare module 'svelte/compiler' { export interface Fragment { type: 'Fragment'; - nodes: Array; + nodes: Array; } export interface Root extends BaseNode { @@ -1220,8 +1220,9 @@ declare module 'svelte/compiler' { } /** An HTML comment */ - export interface TemplateComment extends BaseNode { - type: 'TemplateComment'; + // TODO rename to disambiguate + export interface Comment extends BaseNode { + type: 'Comment'; /** the contents of the comment */ data: string; } @@ -1553,7 +1554,7 @@ declare module 'svelte/compiler' { | AST.SpreadAttribute | Directive | AST.AttachTag - | AST.TemplateComment + | AST.Comment | Block; export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script; @@ -1608,7 +1609,7 @@ declare module 'svelte/compiler' { end: number; styles: string; /** Possible comment atop the style tag */ - comment: AST.TemplateComment | null; + comment: AST.Comment | null; }; } From 59ac0670681a9091c9ac3d0538f55f67638241f2 Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:46:41 -0700 Subject: [PATCH 6/6] `Evaluation.has_unknown` --- .../3-transform/client/visitors/CallExpression.js | 4 ++-- packages/svelte/src/compiler/phases/scope.js | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js index 069357924539..c126742d3c5c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js @@ -2,7 +2,7 @@ /** @import { Context } from '../types' */ import { dev, is_ignored } from '../../../../state.js'; import * as b from '#compiler/builders'; -import { get_rune, UNKNOWN } from '../../../scope.js'; +import { get_rune } from '../../../scope.js'; import { transform_inspect_rune } from '../../utils.js'; import { should_proxy } from '../utils.js'; @@ -83,7 +83,7 @@ export function CallExpression(node, context) { node.callee.property.name ) && node.arguments.some( - (arg) => arg.type === 'SpreadElement' || context.state.scope.evaluate(arg).values.has(UNKNOWN) + (arg) => arg.type === 'SpreadElement' || context.state.scope.evaluate(arg).has_unknown ) ) { return b.call( diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js index b72ec705ab9c..eaacf5dda9a7 100644 --- a/packages/svelte/src/compiler/phases/scope.js +++ b/packages/svelte/src/compiler/phases/scope.js @@ -16,7 +16,7 @@ import { is_reserved, is_rune } from '../../utils.js'; import { determine_slot } from '../utils/slot.js'; import { validate_identifier_name } from './2-analyze/visitors/shared/utils.js'; -export const UNKNOWN = Symbol('unknown'); +const UNKNOWN = Symbol('unknown'); /** Includes `BigInt` */ const NUMBER = Symbol('number'); const STRING = Symbol('string'); @@ -180,6 +180,13 @@ class Evaluation { */ is_known = true; + /** + * True if the possible values contains `UNKNOWN` + * @readonly + * @type {boolean} + */ + has_unknown = false; + /** * True if the value is known to not be null/undefined * @readonly @@ -540,6 +547,10 @@ class Evaluation { if (value == null || value === UNKNOWN) { this.is_defined = false; } + + if (value === UNKNOWN) { + this.has_unknown = true; + } } if (this.values.size > 1 || typeof this.value === 'symbol') {