diff --git a/documentation/docs/02-runes/05-$props.md b/documentation/docs/02-runes/05-$props.md
index f300fb239d..222b4831b6 100644
--- a/documentation/docs/02-runes/05-$props.md
+++ b/documentation/docs/02-runes/05-$props.md
@@ -37,7 +37,7 @@ On the other side, inside `MyComponent.svelte`, we can receive props with the `$
## Fallback values
-Destructuring allows us to declare fallback values, which are used if the parent component does not set a given prop:
+Destructuring allows us to declare fallback values, which are used if the parent component does not set a given prop (or the value is `undefined`):
```js
let { adjective = 'happy' } = $props();
@@ -219,4 +219,4 @@ This is useful for linking elements via attributes like `for` and `aria-labelled
-```
\ No newline at end of file
+```
diff --git a/documentation/docs/03-template-syntax/01-basic-markup.md b/documentation/docs/03-template-syntax/01-basic-markup.md
index 5e8b4342d3..fe5f8b02aa 100644
--- a/documentation/docs/03-template-syntax/01-basic-markup.md
+++ b/documentation/docs/03-template-syntax/01-basic-markup.md
@@ -154,6 +154,8 @@ A JavaScript expression can be included as text by surrounding it with curly bra
{expression}
```
+Expressions that are `null` or `undefined` will be omitted; all others are [coerced to strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion).
+
Curly braces can be included in a Svelte template by using their [HTML entity](https://developer.mozilla.org/docs/Glossary/Entity) strings: `{`, `{`, or `{` for `{` and `}`, `}`, or `}` for `}`.
If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses.
diff --git a/documentation/docs/03-template-syntax/06-snippet.md b/documentation/docs/03-template-syntax/06-snippet.md
index c9951d3f34..ab536c6e5c 100644
--- a/documentation/docs/03-template-syntax/06-snippet.md
+++ b/documentation/docs/03-template-syntax/06-snippet.md
@@ -112,6 +112,8 @@ Snippets can reference themselves and each other ([demo](/playground/untitled#H4
## Passing snippets to components
+### Explicit props
+
Within the template, snippets are values just like any other. As such, they can be passed to components as props ([demo](/playground/untitled#H4sIAAAAAAAAE3VS247aMBD9lZGpBGwDASRegonaPvQL2qdlH5zYEKvBNvbQLbL875VzAcKyj3PmzJnLGU8UOwqSkd8KJdaCk4TsZS0cyV49wYuJuQiQpGd-N2bu_ooaI1YwJ57hpVYoFDqSEepKKw3mO7VDeTTaIvxiRS1gb_URxvO0ibrS8WanIrHUyiHs7Vmigy28RmyHHmKvDMbMmFq4cQInvGSwTsBYWYoMVhCSB2rBFFPsyl0uruTlR3JZCWvlTXl1Yy_mawiR_rbZKZrellJ-5JQ0RiBUgnFhJ9OGR7HKmwVoilXeIye8DOJGfYCgRlZ3iE876TBsZPX7hPdteO75PC4QaIo8vwNPePmANQ2fMeEFHrLD7rR1jTNkW986E8C3KwfwVr8HSHOSEBT_kGRozyIkn_zQveXDL3rIfPJHtUDwzShJd_Qk3gQCbOGLsdq4yfTRJopRuin3I7nv6kL7ARRjmLdBDG3uv1mhuLA3V2mKtqNEf_oCn8p9aN-WYqH5peP4kWBl1UwJzAEPT9U7K--0fRrrWnPTXpCm1_EVdXjpNmlA8G1hPPyM1fKgMqjFHjctXGjLhZ05w0qpDhksGrybuNEHtJnCalZWsuaTlfq6nPaaBSv_HKw-K57BjzOiVj9ZKQYKzQjZodYFqydYTRN4gPhVzTDO2xnma3HsVWjaLjT8nbfwHy7Q5f2dBAAA)):
```svelte
@@ -144,6 +146,8 @@ Within the template, snippets are values just like any other. As such, they can
Think about it like passing content instead of data to a component. The concept is similar to slots in web components.
+### Implicit props
+
As an authoring convenience, snippets declared directly _inside_ a component implicitly become props _on_ the component ([demo](/playground/untitled#H4sIAAAAAAAAE3VSTa_aMBD8Kyu_SkAbCA-JSzBR20N_QXt6vIMTO8SqsY29tI2s_PcqTiB8vaPHs7MzuxuIZgdBMvJLo0QlOElIJZXwJHsLBBvb_XUASc7Mb9Yu_B-hsMMK5sUzvDQahUZPMkJ96aTFfKd3KA_WOISfrFACKmcOMFmk8TWUTjY73RFLoz1C5U4SPWzhrcN2GKDrlcGEWauEnyRwxCaDdQLWyVJksII2uaMWTDPNLtzX5YX8-kgua-GcHJVXI3u5WEPb0d83O03TMZSmfRzOkG1Db7mNacOL19JagVALxoWbztq-H8U6j0SaYp2P2BGbOyQ2v8PQIFMXLKRDk177pq0zf6d8bMrzwBdd0pamyPMb-IjNEzS2f86Gz_Dwf-2F9nvNSUJQ_EOSoTuJNvngqK5v4Pas7n4-OCwlEEJcQTIMO-nSQwtb-GSdsX46e9gbRoP9yGQ11I0rEuycunu6PHx1QnPhxm3SFN15MOlYEFJZtf0dUywMbwZOeBGsrKNLYB54-1R9WNqVdki7usim6VmQphf7mnpshiQRhNAXdoOfMyX3OgMlKtz0cGEcF27uLSul3mewjPjgOOoDukxjPS9rqfh0pb-8zs6aBSt_7505aZ7B9xOi0T9YKW4UooVsr0zB1BTrWQJ3EL-oWcZ572GxFoezCk37QLe3897-B2i2U62uBAAA)):
```svelte
@@ -165,6 +169,8 @@ As an authoring convenience, snippets declared directly _inside_ a component imp
```
+### Implicit `children` snippet
+
Any content inside the component tags that is _not_ a snippet declaration implicitly becomes part of the `children` snippet ([demo](/playground/untitled#H4sIAAAAAAAAE3WOQQrCMBBFrzIMggql3ddY1Du4si5sOmIwnYRkFKX07lKqglqX8_7_w2uRDw1hjlsWI5ZqTPBoLEXMdy3K3fdZDzB5Ndfep_FKVnpWHSKNce1YiCVijirqYLwUJQOYxrsgsLmIOIZjcA1M02w4n-PpomSVvTclqyEutDX6DA2pZ7_ABIVugrmEC3XJH92P55_G39GodCmWBFrQJ2PrQAwdLGHig_NxNv9xrQa1dhWIawrv1Wzeqawa8953D-8QOmaEAQAA)):
```svelte
@@ -184,6 +190,8 @@ Any content inside the component tags that is _not_ a snippet declaration implic
> [!NOTE] Note that you cannot have a prop called `children` if you also have content inside the component — for this reason, you should avoid having props with that name
+### Optional snippet props
+
You can declare snippet props as being optional. You can either use optional chaining to not render anything if the snippet isn't set...
```svelte
diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md
index a8c39aaf97..6196a85ade 100644
--- a/documentation/docs/98-reference/.generated/compile-errors.md
+++ b/documentation/docs/98-reference/.generated/compile-errors.md
@@ -235,7 +235,31 @@ A top-level `:global {...}` block can only contain rules, not declarations
### css_global_block_invalid_list
```
-A `:global` selector cannot be part of a selector list with more than one item
+A `:global` selector cannot be part of a selector list with entries that don't contain `:global`
+```
+
+The following CSS is invalid:
+
+```css
+:global, x {
+ y {
+ color: red;
+ }
+}
+```
+
+This is mixing a `:global` block, which means "everything in here is unscoped", with a scoped selector (`x` in this case). As a result it's not possible to transform the inner selector (`y` in this case) into something that satisfies both requirements. You therefore have to split this up into two selectors:
+
+```css
+:global {
+ y {
+ color: red;
+ }
+}
+
+x y {
+ color: red;
+}
```
### css_global_block_invalid_modifier
diff --git a/documentation/docs/98-reference/.generated/shared-errors.md b/documentation/docs/98-reference/.generated/shared-errors.md
index 4c81d7b894..6c31aaafd0 100644
--- a/documentation/docs/98-reference/.generated/shared-errors.md
+++ b/documentation/docs/98-reference/.generated/shared-errors.md
@@ -60,6 +60,43 @@ Certain lifecycle methods can only be used during component initialisation. To f
```
+### snippet_without_render_tag
+
+```
+Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
+```
+
+A component throwing this error will look something like this (`children` is not being rendered):
+
+```svelte
+
+
+{children}
+```
+
+...or like this (a parent component is passing a snippet where a non-snippet value is expected):
+
+```svelte
+
+
{label}
+``` + ### store_invalid_shape ``` diff --git a/documentation/docs/98-reference/21-svelte-reactivity.md b/documentation/docs/98-reference/21-svelte-reactivity.md index 6857c1dba8..8070331f48 100644 --- a/documentation/docs/98-reference/21-svelte-reactivity.md +++ b/documentation/docs/98-reference/21-svelte-reactivity.md @@ -2,24 +2,6 @@ title: svelte/reactivity --- -Svelte provides reactive versions of various built-ins like `SvelteMap`, `SvelteSet` and `SvelteURL`. These can be imported from `svelte/reactivity` and used just like their native counterparts. - -```svelte - - - - - - - -{label}
+``` + ## store_invalid_shape > `%name%` is not a store with a `subscribe` method diff --git a/packages/svelte/package.json b/packages/svelte/package.json index a06c73429a..dc6c57b1a2 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.26.1", + "version": "5.27.2", "type": "module", "types": "./types/index.d.ts", "engines": { @@ -103,6 +103,17 @@ "default": "./src/events/index.js" } }, + "imports": { + "#client": "./src/internal/client/types.d.ts", + "#client/constants": "./src/internal/client/constants.js", + "#compiler": { + "types": "./src/compiler/private.d.ts", + "default": "./src/compiler/index.js" + }, + "#compiler/builders": "./src/compiler/utils/builders.js", + "#server": "./src/internal/server/types.d.ts", + "#shared": "./src/internal/shared/types.d.ts" + }, "repository": { "type": "git", "url": "git+https://github.com/sveltejs/svelte.git", diff --git a/packages/svelte/scripts/generate-types.js b/packages/svelte/scripts/generate-types.js index d44afe8205..377fca4343 100644 --- a/packages/svelte/scripts/generate-types.js +++ b/packages/svelte/scripts/generate-types.js @@ -24,7 +24,12 @@ await createBundle({ output: `${dir}/types/index.d.ts`, compilerOptions: { // so that types/properties with `@internal` (and its dependencies) are removed from the output - stripInternal: true + stripInternal: true, + paths: Object.fromEntries( + Object.entries(pkg.imports).map(([key, value]) => { + return [key, [value.types ?? value.default ?? value]]; + }) + ) }, modules: { [pkg.name]: `${dir}/src/index.d.ts`, diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 6bf973948b..aa328764e1 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -555,12 +555,12 @@ export function css_global_block_invalid_declaration(node) { } /** - * A `:global` selector cannot be part of a selector list with more than one item + * A `:global` selector cannot be part of a selector list with entries that don't contain `:global` * @param {null | number | NodeLike} node * @returns {never} */ export function css_global_block_invalid_list(node) { - e(node, 'css_global_block_invalid_list', `A \`:global\` selector cannot be part of a selector list with more than one item\nhttps://svelte.dev/e/css_global_block_invalid_list`); + e(node, 'css_global_block_invalid_list', `A \`:global\` selector cannot be part of a selector list with entries that don't contain \`:global\`\nhttps://svelte.dev/e/css_global_block_invalid_list`); } /** diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 523389a25a..75a9a64905 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -1,7 +1,7 @@ /** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */ /** @import { Visitors } from 'zimmerframe' */ /** @import { ComponentAnalysis } from '../phases/types.js' */ -/** @import { Scope, ScopeRoot } from '../phases/scope.js' */ +/** @import { Scope } from '../phases/scope.js' */ /** @import { AST, Binding, ValidatedCompileOptions } from '#compiler' */ import MagicString from 'magic-string'; import { walk } from 'zimmerframe'; diff --git a/packages/svelte/src/compiler/phases/1-parse/remove_typescript_nodes.js b/packages/svelte/src/compiler/phases/1-parse/remove_typescript_nodes.js index 4ff6a782b4..aba94ee20d 100644 --- a/packages/svelte/src/compiler/phases/1-parse/remove_typescript_nodes.js +++ b/packages/svelte/src/compiler/phases/1-parse/remove_typescript_nodes.js @@ -1,7 +1,7 @@ /** @import { Context, Visitors } from 'zimmerframe' */ /** @import { FunctionExpression, FunctionDeclaration } from 'estree' */ import { walk } from 'zimmerframe'; -import * as b from '../../utils/builders.js'; +import * as b from '#compiler/builders'; import * as e from '../../errors.js'; /** diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js index 76cb2f56e9..2dc3435648 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js @@ -193,10 +193,12 @@ const css_visitors = { Rule(node, context) { node.metadata.parent_rule = context.state.rule; - node.metadata.is_global_block = node.prelude.children.some((selector) => { + // We gotta allow :global x, :global y because CSS preprocessors might generate that from :global { x, y {...} } + for (const complex_selector of node.prelude.children) { let is_global_block = false; - for (const child of selector.children) { + for (let selector_idx = 0; selector_idx < complex_selector.children.length; selector_idx++) { + const child = complex_selector.children[selector_idx]; const idx = child.selectors.findIndex(is_global_block_selector); if (is_global_block) { @@ -204,58 +206,56 @@ const css_visitors = { child.metadata.is_global_like = true; } - if (idx !== -1) { - is_global_block = true; + if (idx === 0) { + if ( + child.selectors.length > 1 && + selector_idx === 0 && + node.metadata.parent_rule === null + ) { + e.css_global_block_invalid_modifier_start(child.selectors[1]); + } else { + // `child` starts with `:global` + node.metadata.is_global_block = is_global_block = true; + + for (let i = 1; i < child.selectors.length; i++) { + walk(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, { + ComplexSelector(node) { + node.metadata.used = true; + } + }); + } - for (let i = idx + 1; i < child.selectors.length; i++) { - walk(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, { - ComplexSelector(node) { - node.metadata.used = true; - } - }); - } - } - } + if (child.combinator && child.combinator.name !== ' ') { + e.css_global_block_invalid_combinator(child, child.combinator.name); + } - return is_global_block; - }); + const declaration = node.block.children.find((child) => child.type === 'Declaration'); + const is_lone_global = + complex_selector.children.length === 1 && + complex_selector.children[0].selectors.length === 1; // just `:global`, not e.g. `:global x` - if (node.metadata.is_global_block) { - if (node.prelude.children.length > 1) { - e.css_global_block_invalid_list(node.prelude); - } + if (is_lone_global && node.prelude.children.length > 1) { + // `:global, :global x { z { ... } }` would become `x { z { ... } }` which means `z` is always + // constrained by `x`, which is not what the user intended + e.css_global_block_invalid_list(node.prelude); + } - const complex_selector = node.prelude.children[0]; - const global_selector = complex_selector.children.find((r, selector_idx) => { - const idx = r.selectors.findIndex(is_global_block_selector); - if (idx === 0) { - if (r.selectors.length > 1 && selector_idx === 0 && node.metadata.parent_rule === null) { - e.css_global_block_invalid_modifier_start(r.selectors[1]); + if ( + declaration && + // :global { color: red; } is invalid, but foo :global { color: red; } is valid + node.prelude.children.length === 1 && + is_lone_global + ) { + e.css_global_block_invalid_declaration(declaration); + } } - return true; } else if (idx !== -1) { - e.css_global_block_invalid_modifier(r.selectors[idx]); + e.css_global_block_invalid_modifier(child.selectors[idx]); } - }); - - if (!global_selector) { - throw new Error('Internal error: global block without :global selector'); - } - - if (global_selector.combinator && global_selector.combinator.name !== ' ') { - e.css_global_block_invalid_combinator(global_selector, global_selector.combinator.name); } - const declaration = node.block.children.find((child) => child.type === 'Declaration'); - - if ( - declaration && - // :global { color: red; } is invalid, but foo :global { color: red; } is valid - node.prelude.children.length === 1 && - node.prelude.children[0].children.length === 1 && - node.prelude.children[0].children[0].selectors.length === 1 - ) { - e.css_global_block_invalid_declaration(declaration); + if (node.metadata.is_global_block && !is_global_block) { + e.css_global_block_invalid_list(node.prelude); } } diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index a6eb9565cb..2e36a89649 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -5,8 +5,8 @@ import { walk } from 'zimmerframe'; import * as e from '../../errors.js'; import * as w from '../../warnings.js'; -import { extract_identifiers, is_text_attribute } from '../../utils/ast.js'; -import * as b from '../../utils/builders.js'; +import { extract_identifiers } from '../../utils/ast.js'; +import * as b from '#compiler/builders'; import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js'; import check_graph_for_cycles from './utils/check_graph_for_cycles.js'; import { create_attribute, is_custom_element_node } from '../nodes.js'; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js index e58bf5bb69..979fb62316 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js @@ -3,10 +3,10 @@ /** @import { Context } from '../types' */ import { get_rune } from '../../scope.js'; import * as e from '../../../errors.js'; -import { get_parent, unwrap_optional } from '../../../utils/ast.js'; +import { get_parent } from '../../../utils/ast.js'; import { is_pure, is_safe_identifier } from './shared/utils.js'; import { dev, locate_node, source } from '../../../state.js'; -import * as b from '../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {CallExpression} node diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js index 547f6ab9c7..4b85894e52 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js @@ -1,7 +1,5 @@ -/** @import { ExportNamedDeclaration, Identifier, Node } from 'estree' */ -/** @import { Binding } from '#compiler' */ +/** @import { ExportNamedDeclaration, Identifier } from 'estree' */ /** @import { Context } from '../types' */ -/** @import { Scope } from '../../scope' */ import * as e from '../../../errors.js'; import { extract_identifiers } from '../../../utils/ast.js'; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js index dcbe564543..efbbe6cfa2 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js @@ -1,5 +1,4 @@ /** @import { Expression, Identifier } from 'estree' */ -/** @import { EachBlock } from '#compiler' */ /** @import { Context } from '../types' */ import is_reference from 'is-reference'; import { should_proxy } from '../../3-transform/client/utils.js'; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js index 6ea8f238e1..245a164c71 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js @@ -1,10 +1,7 @@ -/** @import { MemberExpression, Node } from 'estree' */ +/** @import { MemberExpression } from 'estree' */ /** @import { Context } from '../types' */ import * as e from '../../../errors.js'; -import * as w from '../../../warnings.js'; -import { object } from '../../../utils/ast.js'; import { is_pure, is_safe_identifier } from './shared/utils.js'; -import { mark_subtree_dynamic } from './shared/fragment.js'; /** * @param {MemberExpression} node diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js index 03dfaebcb7..d5689e5d55 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js @@ -173,7 +173,8 @@ export function RegularElement(node, context) { if ( context.state.analysis.source[node.end - 2] === '/' && !is_void(node_name) && - !is_svg(node_name) + !is_svg(node_name) && + !is_mathml(node_name) ) { w.element_invalid_self_closing_tag(node, node.name); } diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js index d6c74eddb6..12e21c386c 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js @@ -1,4 +1,4 @@ -/** @import { AssignmentExpression, Expression, Identifier, Literal, Node, Pattern, PrivateIdentifier, Super, UpdateExpression, VariableDeclarator } from 'estree' */ +/** @import { AssignmentExpression, Expression, Literal, Node, Pattern, Super, UpdateExpression, VariableDeclarator } from 'estree' */ /** @import { AST, Binding } from '#compiler' */ /** @import { AnalysisState, Context } from '../../types' */ /** @import { Scope } from '../../../scope' */ @@ -6,7 +6,7 @@ import * as e from '../../../../errors.js'; import { extract_identifiers } from '../../../../utils/ast.js'; import * as w from '../../../../warnings.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index adc4164f95..b39ffc63b3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -3,7 +3,7 @@ /** @import { ComponentAnalysis, Analysis } from '../../types' */ /** @import { Visitors, ComponentClientTransformState, ClientTransformState } from './types' */ import { walk } from 'zimmerframe'; -import * as b from '../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_getter, is_state_source } from './utils.js'; import { render_stylesheet } from '../css/index.js'; import { dev, filename } from '../../../state.js'; 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 a37ecd31cc..6d9dac8a33 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js @@ -3,7 +3,7 @@ /** @import { ClientTransformState, ComponentClientTransformState, ComponentContext } from './types.js' */ /** @import { Analysis } from '../../types.js' */ /** @import { Scope } from '../../scope.js' */ -import * as b from '../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { is_simple_expression } from '../../../utils/ast.js'; import { PROPS_IS_LAZY_INITIAL, diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js index 2e051ec674..16f9735370 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { parse_directive_name } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js index 4baa1c8e6c..e3f9450050 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js @@ -1,7 +1,7 @@ /** @import { AssignmentExpression, AssignmentOperator, Expression, Identifier, Pattern } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_assignment_value, get_attribute_expression, diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js index 7588b24280..96a4addb72 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ import { extract_identifiers } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { create_derived } from '../utils.js'; import { get_value } from './shared/declarations.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js index c563920855..18028fa071 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js @@ -1,7 +1,7 @@ /** @import { Expression, BinaryExpression } from 'estree' */ /** @import { ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {BinaryExpression} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js index 0a49e89cfe..506fd4aafd 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../types' */ import { dev, is_ignored } from '../../../../state.js'; import { is_text_attribute } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { binding_properties } from '../../../bindings.js'; import { build_attribute_value } from './shared/element.js'; import { build_bind_this, validate_binding } from './shared/utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js index 5bfc8a3ef9..d1c0978a81 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js @@ -1,7 +1,7 @@ -/** @import { ArrowFunctionExpression, BlockStatement, CallExpression, Expression, FunctionDeclaration, FunctionExpression, Statement } from 'estree' */ +/** @import { ArrowFunctionExpression, BlockStatement, Expression, FunctionDeclaration, FunctionExpression, Statement } from 'estree' */ /** @import { ComponentContext } from '../types' */ import { add_state_transformers } from './shared/declarations.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {BlockStatement} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BreakStatement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BreakStatement.js index 66b66c64f2..daa54018c0 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BreakStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BreakStatement.js @@ -1,6 +1,6 @@ /** @import { BreakStatement } from 'estree' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {BreakStatement} node 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 fda43ad791..b110f8eae8 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 @@ -1,7 +1,7 @@ /** @import { CallExpression, Expression } from 'estree' */ /** @import { Context } from '../types' */ import { dev, is_ignored } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; import { transform_inspect_rune } from '../../utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js index 4081ef7bbf..44ba7837b8 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js @@ -1,8 +1,6 @@ /** @import { ClassBody, Expression, Identifier, Literal, MethodDefinition, PrivateIdentifier, PropertyDefinition } from 'estree' */ -/** @import { } from '#compiler' */ /** @import { Context, StateField } from '../types' */ -import { dev, is_ignored } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { regex_invalid_identifier_chars } from '../../../patterns.js'; import { get_rune } from '../../../scope.js'; import { should_proxy } from '../utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Component.js index a10a3da6e3..783bc38e3c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Component.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_component } from './shared/component.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js index 7e33aea435..2f3c0b3d0e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; import { extract_identifiers } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { create_derived } from '../utils.js'; import { get_value } from './shared/declarations.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/DebugTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/DebugTag.js index d2697fd039..ef9a070859 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/DebugTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/DebugTag.js @@ -1,7 +1,7 @@ /** @import { Expression} from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.DebugTag} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js index 629cacda01..e5aee24765 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js @@ -11,7 +11,7 @@ import { } from '../../../../../constants.js'; import { dev } from '../../../../state.js'; import { extract_paths, object } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_getter } from '../utils.js'; import { get_value } from './shared/declarations.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExportNamedDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExportNamedDeclaration.js index cab7f90c3d..16e400d50c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExportNamedDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExportNamedDeclaration.js @@ -1,6 +1,6 @@ /** @import { ExportNamedDeclaration } from 'estree' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {ExportNamedDeclaration} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js index 0424e595be..859842ebc3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js @@ -1,6 +1,6 @@ /** @import { Expression, ExpressionStatement } from 'estree' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js index 389a694741..b6dca0779a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js @@ -4,7 +4,7 @@ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../../../constants.js'; import { dev } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { sanitize_template_string } from '../../../../utils/sanitize_template_string.js'; import { clean_nodes, infer_namespace } from '../../utils.js'; import { process_children } from './shared/fragment.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js index ed8fefc6ba..5dc8fa5cf9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js @@ -1,7 +1,7 @@ /** @import { FunctionDeclaration } from 'estree' */ /** @import { ComponentContext } from '../types' */ import { build_hoisted_params } from '../utils.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {FunctionDeclaration} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js index 32439879de..a69b9cfe70 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { is_ignored } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.HtmlTag} node @@ -11,17 +11,22 @@ import * as b from '../../../../utils/builders.js'; export function HtmlTag(node, context) { context.state.template.push(''); - // push into init, so that bindings run afterwards, which might trigger another run and override hydration - context.state.init.push( - b.stmt( - b.call( - '$.html', - context.state.node, - b.thunk(/** @type {Expression} */ (context.visit(node.expression))), - b.literal(context.state.metadata.namespace === 'svg'), - b.literal(context.state.metadata.namespace === 'mathml'), - is_ignored(node, 'hydration_html_changed') && b.true - ) + const expression = /** @type {Expression} */ (context.visit(node.expression)); + + const is_svg = context.state.metadata.namespace === 'svg'; + const is_mathml = context.state.metadata.namespace === 'mathml'; + + const statement = b.stmt( + b.call( + '$.html', + context.state.node, + b.thunk(expression), + is_svg && b.true, + is_mathml && b.true, + is_ignored(node, 'hydration_html_changed') && b.true ) ); + + // push into init, so that bindings run afterwards, which might trigger another run and override hydration + context.state.init.push(statement); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Identifier.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Identifier.js index ae62909eff..b01ed01bd7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Identifier.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Identifier.js @@ -1,7 +1,7 @@ /** @import { Identifier, Node } from 'estree' */ /** @import { Context } from '../types' */ import is_reference from 'is-reference'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_getter } from '../utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js index fdd21b2b7e..c650a1e15c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js @@ -1,7 +1,7 @@ -/** @import { BlockStatement, Expression, Identifier } from 'estree' */ +/** @import { BlockStatement, Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.IfBlock} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ImportDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ImportDeclaration.js index 29700246d4..b572e1d17f 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ImportDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ImportDeclaration.js @@ -1,6 +1,6 @@ /** @import { ImportDeclaration } from 'estree' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {ImportDeclaration} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/KeyBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/KeyBlock.js index a013827f60..7d6a8b0006 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/KeyBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/KeyBlock.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.KeyBlock} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/LabeledStatement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/LabeledStatement.js index 3c8f57f46b..8d24d260c5 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/LabeledStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/LabeledStatement.js @@ -1,9 +1,7 @@ -/** @import { Location } from 'locate-character' */ /** @import { Expression, LabeledStatement, Statement } from 'estree' */ /** @import { ReactiveStatement } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import { dev, is_ignored, locator } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_getter } from '../utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/LetDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/LetDirective.js index e174073a26..abdbc381d9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/LetDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/LetDirective.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { create_derived } from '../utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/MemberExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/MemberExpression.js index 3f2aada1f5..ab88345ddd 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/MemberExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/MemberExpression.js @@ -1,6 +1,6 @@ /** @import { MemberExpression } from 'estree' */ /** @import { Context } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {MemberExpression} node 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 7c2b1209e9..7a66a8ecbb 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 @@ -1,6 +1,6 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_event, build_event_handler } from './shared/events.js'; const modifiers = [ diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js index 29403ca6ed..07342da314 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js @@ -1,7 +1,7 @@ /** @import { Expression, ImportDeclaration, MemberExpression, Program } from 'estree' */ /** @import { ComponentContext } from '../types' */ import { build_getter, is_prop_source } from '../utils.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { add_state_transformers } from './shared/declarations.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js index 45a594af1f..7468fcbbc7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js @@ -1,4 +1,4 @@ -/** @import { ArrayExpression, Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression, Statement } from 'estree' */ +/** @import { ArrayExpression, Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { SourceLocation } from '#shared' */ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ @@ -13,7 +13,7 @@ import { import { escape_html } from '../../../../../escaping.js'; import { dev, is_ignored, locator } from '../../../../state.js'; import { is_event_attribute, is_text_attribute } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { is_custom_element_node } from '../../../nodes.js'; import { clean_nodes, determine_namespace_for_children } from '../../utils.js'; import { build_getter } from '../utils.js'; @@ -685,14 +685,13 @@ function build_element_special_value_attribute(element, node_id, attribute, cont : value ); + const evaluated = context.state.scope.evaluate(value); + const assignment = b.assignment('=', b.member(node_id, '__value'), value); + const inner_assignment = b.assignment( '=', b.member(node_id, 'value'), - b.conditional( - b.binary('==', b.null, b.assignment('=', b.member(node_id, '__value'), value)), - b.literal(''), // render null/undefined values as empty string to support placeholder options - value - ) + evaluated.is_defined ? assignment : b.logical('??', assignment, b.literal('')) ); const update = b.stmt( diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js index 33ae6d4d2b..6067c2562a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RenderTag.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { unwrap_optional } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.RenderTag} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js index c6f4ba1ed3..ba9fcc7377 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js @@ -1,7 +1,7 @@ /** @import { BlockStatement, Expression, ExpressionStatement, Literal, Property } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_attribute_value } from './shared/element.js'; import { memoize_expression } from './shared/utils.js'; 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 7eb043aa5d..a82645cd7a 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 @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; import { extract_paths } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_value } from './shared/declarations.js'; /** @@ -21,6 +21,10 @@ export function SnippetBlock(node, context) { /** @type {Statement[]} */ const declarations = []; + if (dev) { + declarations.push(b.stmt(b.call('$.validate_snippet_args', b.spread(b.id('arguments'))))); + } + const transform = { ...context.state.transform }; const child_state = { ...context.state, transform }; @@ -30,12 +34,7 @@ export function SnippetBlock(node, context) { if (!argument) continue; if (argument.type === 'Identifier') { - args.push({ - type: 'AssignmentPattern', - left: argument, - right: b.id('$.noop') - }); - + args.push(b.assignment_pattern(argument, b.id('$.noop'))); transform[argument.name] = { read: b.call }; continue; @@ -66,29 +65,16 @@ export function SnippetBlock(node, context) { } } } - if (dev) { - declarations.unshift( - b.stmt( - b.call( - '$.validate_snippet_args', - .../** @type {Identifier[]} */ ( - args.map((arg) => (arg?.type === 'Identifier' ? arg : arg?.left)) - ) - ) - ) - ); - } + body = b.block([ ...declarations, .../** @type {BlockStatement} */ (context.visit(node.body, child_state)).body ]); - /** @type {Expression} */ - let snippet = b.arrow(args, body); - - if (dev) { - snippet = b.call('$.wrap_snippet', b.id(context.state.analysis.name), snippet); - } + // in dev we use a FunctionExpression (not arrow function) so we can use `arguments` + let snippet = dev + ? b.call('$.wrap_snippet', b.id(context.state.analysis.name), b.function(null, args, body)) + : b.arrow(args, body); const declaration = b.const(node.expression, snippet); diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js index 9228df9703..b279b5badd 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.SvelteBoundary} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js index 115eb6ccc1..ee597dd043 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteElement.js @@ -3,10 +3,10 @@ /** @import { ComponentContext } from '../types' */ import { dev, locator } from '../../../../state.js'; import { is_text_attribute } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { determine_namespace_for_children } from '../../utils.js'; import { build_attribute_value, build_set_attributes, build_set_class } from './shared/element.js'; -import { build_render_statement, get_expression_id } from './shared/utils.js'; +import { build_render_statement } from './shared/utils.js'; /** * @param {AST.SvelteElement} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteHead.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteHead.js index 25fcff0631..0701c37c48 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteHead.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteHead.js @@ -1,7 +1,7 @@ /** @import { BlockStatement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.SvelteHead} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js index 72cc57b068..7bfdaf1850 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TitleElement.js @@ -1,6 +1,6 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_template_chunk } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TransitionDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TransitionDirective.js index e331f36472..41340c1290 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/TransitionDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/TransitionDirective.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../../constants.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { parse_directive_name } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js index 63c03b0eb6..96be119b84 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js @@ -1,7 +1,7 @@ /** @import { AssignmentExpression, Expression, UpdateExpression } from 'estree' */ /** @import { Context } from '../types' */ import { object } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { validate_mutation } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseDirective.js index be9eb2d516..b95f2fc3ef 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseDirective.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { parse_directive_name } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index d12735d151..0dfd9c2113 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -3,7 +3,7 @@ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; import { extract_paths } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import * as assert from '../../../../utils/assert.js'; import { get_rune } from '../../../scope.js'; import { get_prop_source, is_prop_source, is_state_source, should_proxy } from '../utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index 2ea68e206e..c4071c67fe 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../../types.js' */ import { dev, is_ignored } from '../../../../../state.js'; import { get_attribute_chunks, object } from '../../../../../utils/ast.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_bind_this, memoize_expression, validate_binding } from '../shared/utils.js'; import { build_attribute_value } from '../shared/element.js'; import { build_event_handler } from './events.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js index a13ecfed2c..f6bb26daac 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js @@ -1,7 +1,7 @@ /** @import { Identifier } from 'estree' */ /** @import { ComponentContext, Context } from '../../types' */ import { is_state_source } from '../../utils.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * Turns `foo` into `$.get(foo)` diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js index 97cec7a729..a093a0bf4a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js @@ -1,11 +1,11 @@ /** @import { ArrayExpression, Expression, Identifier, ObjectExpression } from 'estree' */ /** @import { AST, ExpressionMetadata } from '#compiler' */ -/** @import { ComponentClientTransformState, ComponentContext } from '../../types' */ +/** @import { ComponentContext } from '../../types' */ import { escape_html } from '../../../../../../escaping.js'; import { normalize_attribute } from '../../../../../../utils.js'; import { is_ignored } from '../../../../../state.js'; import { is_event_attribute } from '../../../../../utils/ast.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_class_directives_object, build_style_directives_object } from '../RegularElement.js'; import { build_template_chunk, get_expression_id } from './utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js index 2667a96f6a..d252bd5474 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/events.js @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../../types' */ import { is_capture_event, is_passive_event } from '../../../../../../utils.js'; import { dev, locator } from '../../../../../state.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.Attribute} node diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js index f076d7c11e..c91e2b3b44 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/fragment.js @@ -3,7 +3,7 @@ /** @import { ComponentContext } from '../../types' */ import { cannot_be_set_statically } from '../../../../../../utils.js'; import { is_event_attribute, is_text_attribute } from '../../../../../utils/ast.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { is_custom_element_node } from '../../../../nodes.js'; import { build_template_chunk } from './utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/special_element.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/special_element.js index 558bc4fee7..c878f2fc07 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/special_element.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/special_element.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../../types' */ -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js index af6e56f70c..380cf6cd02 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js @@ -3,7 +3,7 @@ /** @import { ComponentClientTransformState, Context } from '../../types' */ import { walk } from 'zimmerframe'; import { object } from '../../../../../utils/ast.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js'; import { regex_is_valid_identifier } from '../../../../patterns.js'; import is_reference from 'is-reference'; @@ -89,21 +89,21 @@ export function build_template_chunk( } } - const is_defined = - value.type === 'BinaryExpression' || - (value.type === 'UnaryExpression' && value.operator !== 'void') || - (value.type === 'LogicalExpression' && value.right.type === 'Literal') || - (value.type === 'Identifier' && value.name === state.analysis.props_id?.name); + const evaluated = state.scope.evaluate(value); - if (!is_defined) { - // add `?? ''` where necessary (TODO optimise more cases) - value = b.logical('??', value, b.literal('')); - } + if (evaluated.is_known) { + quasi.value.cooked += evaluated.value + ''; + } else { + if (!evaluated.is_defined) { + // add `?? ''` where necessary + value = b.logical('??', value, b.literal('')); + } - expressions.push(value); + expressions.push(value); - quasi = b.quasi('', i + 1 === values.length); - quasis.push(quasi); + quasi = b.quasi('', i + 1 === values.length); + quasis.push(quasi); + } } } diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index dff034f8aa..9f1142cce9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -170,7 +170,11 @@ const visitors = { if (node.metadata.is_global_block) { const selector = node.prelude.children[0]; - if (selector.children.length === 1 && selector.children[0].selectors.length === 1) { + if ( + node.prelude.children.length === 1 && + selector.children.length === 1 && + selector.children[0].selectors.length === 1 + ) { // `:global {...}` if (state.minify) { state.code.remove(node.start, node.block.start + 1); @@ -194,7 +198,7 @@ const visitors = { SelectorList(node, { state, next, path }) { // Only add comments if we're not inside a complex selector that itself is unused or a global block if ( - !is_in_global_block(path) && + (!is_in_global_block(path) || node.children.length > 1) && !path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used) ) { const children = node.children; @@ -282,13 +286,24 @@ const visitors = { const global = /** @type {AST.CSS.PseudoClassSelector} */ (relative_selector.selectors[0]); remove_global_pseudo_class(global, relative_selector.combinator, context.state); - if ( - node.metadata.rule?.metadata.parent_rule && - global.args === null && - relative_selector.combinator === null - ) { - // div { :global.x { ... } } becomes div { &.x { ... } } - context.state.code.prependRight(global.start, '&'); + const parent_rule = node.metadata.rule?.metadata.parent_rule; + if (parent_rule && global.args === null) { + if (relative_selector.combinator === null) { + // div { :global.x { ... } } becomes div { &.x { ... } } + context.state.code.prependRight(global.start, '&'); + } + + // In case of multiple :global selectors in a selector list we gotta delete the comma, too, but only if + // the next selector is used; if it's unused then the comma deletion happens as part of removal of that next selector + if ( + parent_rule.prelude.children.length > 1 && + node.children.length === node.children.findIndex((s) => s === relative_selector) - 1 + ) { + const next_selector = parent_rule.prelude.children.find((s) => s.start > global.end); + if (next_selector && next_selector.metadata.used) { + context.state.code.update(global.end, next_selector.start, ''); + } + } } continue; } else { @@ -380,7 +395,9 @@ function remove_global_pseudo_class(selector, combinator, state) { // div :global.x becomes div.x while (/\s/.test(state.code.original[start - 1])) start--; } - state.code.remove(start, selector.start + ':global'.length); + + // update(...), not remove(...) because there could be a closing unused comment at the end + state.code.update(start, selector.start + ':global'.length, ''); } else { state.code .remove(selector.start, selector.start + ':global('.length) diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index f746e90fe2..e7896991d9 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -5,7 +5,7 @@ import { walk } from 'zimmerframe'; import { set_scope } from '../../scope.js'; import { extract_identifiers } from '../../../utils/ast.js'; -import * as b from '../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { dev, filename } from '../../../state.js'; import { render_stylesheet } from '../css/index.js'; import { AssignmentExpression } from './visitors/AssignmentExpression.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js index 6364063b3b..071a12f9bc 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js @@ -1,7 +1,7 @@ /** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { Context, ServerTransformState } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_assignment_value } from '../../../../utils/ast.js'; import { visit_assignment_expression } from '../../shared/assignments.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js index 2aa534d257..35e431f43d 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js @@ -1,7 +1,7 @@ /** @import { BlockStatement, Expression, Pattern } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { block_close } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js index a425bc5ec4..5bcbdee9fb 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js @@ -1,7 +1,7 @@ /** @import { CallExpression, Expression } from 'estree' */ /** @import { Context } from '../types.js' */ import { is_ignored } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; import { transform_inspect_rune } from '../../utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js index 365084a284..c0ebdeae08 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ClassBody.js @@ -2,7 +2,7 @@ /** @import { Context } from '../types.js' */ /** @import { StateField } from '../../client/types.js' */ import { dev } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Component.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Component.js index 01bf50fafa..503b380c50 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Component.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Component.js @@ -1,6 +1,6 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_inline_component } from './shared/component.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ConstTag.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ConstTag.js index 5f6aea8338..a8e4e575cc 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ConstTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ConstTag.js @@ -1,7 +1,7 @@ /** @import { Expression, Pattern } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.ConstTag} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/DebugTag.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/DebugTag.js index 6fe4e0b82b..31b53fd3eb 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/DebugTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/DebugTag.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.DebugTag} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js index 104f1f2405..ac6c9891a7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js @@ -1,8 +1,8 @@ -/** @import { BlockStatement, Expression, Pattern, Statement } from 'estree' */ +/** @import { BlockStatement, Expression, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import { BLOCK_OPEN_ELSE } from '../../../../../internal/server/hydration.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { block_close, block_open } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ExpressionStatement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ExpressionStatement.js index 00d0dba5da..f77e19aec2 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/ExpressionStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/ExpressionStatement.js @@ -1,6 +1,6 @@ /** @import { ExpressionStatement } from 'estree' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Fragment.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Fragment.js index a293b98e7e..a1d25980c4 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Fragment.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Fragment.js @@ -1,7 +1,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */ import { clean_nodes, infer_namespace } from '../../utils.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { empty_comment, process_children, build_template } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/HtmlTag.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/HtmlTag.js index 0d551a884a..9e857a9308 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/HtmlTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/HtmlTag.js @@ -1,7 +1,7 @@ /** @import { Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.HtmlTag} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Identifier.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Identifier.js index b8c2699d54..fa887650b3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/Identifier.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/Identifier.js @@ -1,7 +1,7 @@ /** @import { Identifier, Node } from 'estree' */ /** @import { Context } from '../types.js' */ import is_reference from 'is-reference'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_getter } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js index cbdd2cd8cc..eb51c941f5 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js @@ -1,8 +1,8 @@ -/** @import { BlockStatement, Expression, IfStatement } from 'estree' */ +/** @import { BlockStatement, Expression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import { BLOCK_OPEN_ELSE } from '../../../../../internal/server/hydration.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { block_close, block_open } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js index 2b394e94e3..83c828b839 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js @@ -1,6 +1,6 @@ /** @import { ExpressionStatement, LabeledStatement } from 'estree' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {LabeledStatement} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js index 527c8cf6ed..73631395e6 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/MemberExpression.js @@ -1,6 +1,6 @@ /** @import { MemberExpression } from 'estree' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {MemberExpression} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/PropertyDefinition.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/PropertyDefinition.js index 04751a19d1..c9225bb8da 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/PropertyDefinition.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/PropertyDefinition.js @@ -1,6 +1,6 @@ /** @import { Expression, PropertyDefinition } from 'estree' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js index af50695efa..5901cb4c50 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js @@ -4,7 +4,7 @@ /** @import { Scope } from '../../../scope.js' */ import { is_void } from '../../../../../utils.js'; import { dev, locator } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { clean_nodes, determine_namespace_for_children } from '../../utils.js'; import { build_element_attributes } from './shared/element.js'; import { process_children, build_template } from './shared/utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RenderTag.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RenderTag.js index ebf8c3be1c..dd2ede3ba3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RenderTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RenderTag.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import { unwrap_optional } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { empty_comment } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js index e7925071cd..fee7cb6e02 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js @@ -1,7 +1,7 @@ /** @import { BlockStatement, Expression, Literal, Property } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { empty_comment, build_attribute_value } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js index cae3e7d79c..5118679b34 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js @@ -1,28 +1,35 @@ -/** @import { BlockStatement } from 'estree' */ +/** @import { ArrowFunctionExpression, BlockStatement, CallExpression } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import { dev } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.SnippetBlock} node * @param {ComponentContext} context */ export function SnippetBlock(node, context) { - const fn = b.function_declaration( - node.expression, - [b.id('$$payload'), ...node.parameters], - /** @type {BlockStatement} */ (context.visit(node.body)) - ); + const body = /** @type {BlockStatement} */ (context.visit(node.body)); + if (dev) { - fn.body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload')))); + body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload')))); } + + /** @type {ArrowFunctionExpression | CallExpression} */ + let fn = b.arrow([b.id('$$payload'), ...node.parameters], body); + + if (dev) { + fn = b.call('$.prevent_snippet_stringification', fn); + } + + const declaration = b.declaration('const', [b.declarator(node.expression, fn)]); + // @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone fn.___snippet = true; if (node.metadata.can_hoist) { - context.state.hoisted.push(fn); + context.state.hoisted.push(declaration); } else { - context.state.init.push(fn); + context.state.init.push(declaration); } } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js index 0d54feee11..734740c1b1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js @@ -2,7 +2,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { BLOCK_CLOSE, BLOCK_OPEN } from '../../../../../internal/server/hydration.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.SvelteBoundary} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js index 9f6faa33c8..fd16219860 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js @@ -3,7 +3,7 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import { dev, locator } from '../../../../state.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { determine_namespace_for_children } from '../../utils.js'; import { build_element_attributes } from './shared/element.js'; import { build_template } from './shared/utils.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js index 7da7d8355c..7d064ffbf5 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js @@ -1,7 +1,7 @@ /** @import { BlockStatement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {AST.SvelteHead} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteSelf.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteSelf.js index fbedcff283..bb0ecb21b2 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteSelf.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteSelf.js @@ -1,6 +1,6 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { build_inline_component } from './shared/component.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/TitleElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/TitleElement.js index 8fd1973453..c42df4c646 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/TitleElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/TitleElement.js @@ -1,6 +1,6 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { process_children, build_template } from './shared/utils.js'; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/UpdateExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/UpdateExpression.js index ae78e14c13..8a2f874e22 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/UpdateExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/UpdateExpression.js @@ -1,6 +1,6 @@ /** @import { UpdateExpression } from 'estree' */ /** @import { Context } from '../types.js' */ -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; /** * @param {UpdateExpression} node diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js index a9c9777335..1f2bd3e2b1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js @@ -3,7 +3,7 @@ /** @import { Context } from '../types.js' */ /** @import { Scope } from '../../../scope.js' */ import { build_fallback, extract_paths } from '../../../../utils/ast.js'; -import * as b from '../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; import { walk } from 'zimmerframe'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js index 695161ff9b..9bccf9e05e 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js @@ -2,8 +2,9 @@ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../../types.js' */ import { empty_comment, build_attribute_value } from './utils.js'; -import * as b from '../../../../../utils/builders.js'; +import * as b from '#compiler/builders'; import { is_element_node } from '../../../../nodes.js'; +import { dev } from '../../../../../state.js'; /** * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node @@ -238,7 +239,13 @@ export function build_inline_component(node, expression, context) { ) ) { // create `children` prop... - push_prop(b.prop('init', b.id('children'), slot_fn)); + push_prop( + b.prop( + 'init', + b.id('children'), + dev ? b.call('$.prevent_snippet_stringification', slot_fn) : slot_fn + ) + ); // and `$$slots.default: true` so that `The time is {formatter.format(date)}
+ * ``` + */ export class SvelteDate extends Date { #time = source(super.getTime()); diff --git a/packages/svelte/src/reactivity/map.js b/packages/svelte/src/reactivity/map.js index 3fa2945ef0..3ae8fe5ad1 100644 --- a/packages/svelte/src/reactivity/map.js +++ b/packages/svelte/src/reactivity/map.js @@ -5,6 +5,47 @@ import { get } from '../internal/client/runtime.js'; import { increment } from './utils.js'; /** + * A reactive version of the built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) object. + * Reading contents of the map (by iterating, or by reading `map.size` or calling `map.get(...)` or `map.has(...)` as in the [tic-tac-toe example](https://svelte.dev/playground/0b0ff4aa49c9443f9b47fe5203c78293) below) in an [effect](https://svelte.dev/docs/svelte/$effect) or [derived](https://svelte.dev/docs/svelte/$derived) + * will cause it to be re-evaluated as necessary when the map is updated. + * + * Note that values in a reactive map are _not_ made [deeply reactive](https://svelte.dev/docs/svelte/$state#Deep-state). + * + * ```svelte + * + * + *{winner} wins!
+ * + * {:else} + *{player} is next
+ * {/if} + * ``` + * * @template K * @template V * @extends {Mapsee no evil
{/if} + * {#if monkeys.has('🙉')}hear no evil
{/if} + * {#if monkeys.has('🙊')}speak no evil
{/if} + * ``` + * * @template T * @extends {Set?{params.toString()}
+ * + * {#each params as [key, value]} + *{key}: {value}
+ * {/each} + * ``` + */ export class SvelteURLSearchParams extends URLSearchParams { #version = source(0); #url = get_current_url(); @@ -23,6 +49,7 @@ export class SvelteURLSearchParams extends URLSearchParams { /** * @param {URLSearchParams} params + * @internal */ [REPLACE](params) { if (this.#updating) return; diff --git a/packages/svelte/src/reactivity/url.js b/packages/svelte/src/reactivity/url.js index 5d003be021..879006f057 100644 --- a/packages/svelte/src/reactivity/url.js +++ b/packages/svelte/src/reactivity/url.js @@ -10,6 +10,33 @@ export function get_current_url() { return current_url; } +/** + * A reactive version of the built-in [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) object. + * Reading properties of the URL (such as `url.href` or `url.pathname`) in an [effect](https://svelte.dev/docs/svelte/$effect) or [derived](https://svelte.dev/docs/svelte/$derived) + * will cause it to be re-evaluated as necessary when the URL changes. + * + * The `searchParams` property is an instance of [SvelteURLSearchParams](https://svelte.dev/docs/svelte/svelte-reactivity#SvelteURLSearchParams). + * + * [Example](https://svelte.dev/playground/5a694758901b448c83dc40dc31c71f2a): + * + * ```svelte + * + * + * + * + * + * + * + *hi again
+{/snippet} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js new file mode 100644 index 0000000000..f47bee71df --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js @@ -0,0 +1,3 @@ +import { test } from '../../test'; + +export default test({}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte new file mode 100644 index 0000000000..3f8edfe4fa --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte @@ -0,0 +1,5 @@ +{testSnippet} + +{#snippet testSnippet()} +hi again
+{/snippet} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js new file mode 100644 index 0000000000..f47bee71df --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js @@ -0,0 +1,3 @@ +import { test } from '../../test'; + +export default test({}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte new file mode 100644 index 0000000000..4a4ed3176f --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte @@ -0,0 +1,5 @@ + + +default
` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/validate-undefined-snippet-default-arg/main.svelte b/packages/svelte/tests/runtime-runes/samples/validate-undefined-snippet-default-arg/main.svelte new file mode 100644 index 0000000000..3f00eba46b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/validate-undefined-snippet-default-arg/main.svelte @@ -0,0 +1,5 @@ +{#snippet test(param = "default")} +{param}
+{/snippet} + +{@render test()} \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js index cadae2cf15..04bfbf6ae4 100644 --- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js @@ -1,9 +1,9 @@ import * as $ from 'svelte/internal/server'; import TextInput from './Child.svelte'; -function snippet($$payload) { +const snippet = ($$payload) => { $$payload.out += `Something`; -} +}; export default function Bind_component_snippet($$payload) { let value = ''; diff --git a/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/client/index.svelte.js index 332c909ebe..21f6ed9680 100644 --- a/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/client/index.svelte.js @@ -10,11 +10,11 @@ export default function Nullish_coallescence_omittance($$anchor) { var fragment = root(); var h1 = $.first_child(fragment); - h1.textContent = `Hello, ${name ?? ''}!`; + h1.textContent = 'Hello, world!'; var b = $.sibling(h1, 2); - b.textContent = `${1 ?? 'stuff'}${2 ?? 'more stuff'}${3 ?? 'even more stuff'}`; + b.textContent = '123'; var button = $.sibling(b, 2); @@ -26,7 +26,7 @@ export default function Nullish_coallescence_omittance($$anchor) { var h1_1 = $.sibling(button, 2); - h1_1.textContent = `Hello, ${name ?? 'earth' ?? ''}`; + h1_1.textContent = 'Hello, world'; $.template_effect(() => $.set_text(text, `Count is ${$.get(count) ?? ''}`)); $.append($$anchor, fragment); } diff --git a/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/server/index.svelte.js index 8181bfd98e..3b23befcd4 100644 --- a/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/server/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/nullish-coallescence-omittance/_expected/server/index.svelte.js @@ -4,5 +4,5 @@ export default function Nullish_coallescence_omittance($$payload) { let name = 'world'; let count = 0; - $$payload.out += `The time is {formatter.format(date)}
+ * ``` + */ export class SvelteDate extends Date { constructor(...params: any[]); #private; } + /** + * A reactive version of the built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) object. + * Reading contents of the set (by iterating, or by reading `set.size` or calling `set.has(...)` as in the [example](https://svelte.dev/playground/53438b51194b4882bcc18cddf9f96f15) below) in an [effect](https://svelte.dev/docs/svelte/$effect) or [derived](https://svelte.dev/docs/svelte/$derived) + * will cause it to be re-evaluated as necessary when the set is updated. + * + * Note that values in a reactive set are _not_ made [deeply reactive](https://svelte.dev/docs/svelte/$state#Deep-state). + * + * ```svelte + * + * + * {#each ['🙈', '🙉', '🙊'] as monkey} + * + * {/each} + * + * + * + * {#if monkeys.has('🙈')}see no evil
{/if} + * {#if monkeys.has('🙉')}hear no evil
{/if} + * {#if monkeys.has('🙊')}speak no evil
{/if} + * ``` + * + * + */ export class SvelteSet{winner} wins!
+ * + * {:else} + *{player} is next
+ * {/if} + * ``` + * + * + */ export class SvelteMap?{params.toString()}
+ * + * {#each params as [key, value]} + *{key}: {value}
+ * {/each} + * ``` + */ export class SvelteURLSearchParams extends URLSearchParams { [REPLACE](params: URLSearchParams): void;