From 03f2e44757925d0ca53f4e563965c3135ef81f16 Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:56:41 -0700 Subject: [PATCH 01/28] chore: remove some todos (#16515) * chore: remove some todos * fix * fix * doh * convert `TemplateComment` back to `Comment` * `Evaluation.has_unknown` --- .changeset/happy-countries-dance.md | 5 +++++ packages/svelte/src/compiler/migrate/index.js | 4 ++-- packages/svelte/src/compiler/phases/1-parse/index.js | 1 - .../3-transform/client/visitors/CallExpression.js | 4 +++- .../3-transform/client/visitors/OnDirective.js | 4 ++-- packages/svelte/src/compiler/phases/scope.js | 11 +++++++++++ packages/svelte/src/compiler/types/template.d.ts | 12 +++++++++++- packages/svelte/types/index.d.ts | 12 +++++++++++- 8 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 .changeset/happy-countries-dance.md diff --git a/.changeset/happy-countries-dance.md b/.changeset/happy-countries-dance.md new file mode 100644 index 0000000000..641cf21fd8 --- /dev/null +++ b/.changeset/happy-countries-dance.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: remove some todos diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 6b2e6cda70..eb0e4eff8c 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -1707,14 +1707,14 @@ function extract_type_and_comment(declarator, state, path) { } // Ensure modifiers are applied in the same order as Svelte 4 -const modifier_order = [ +const modifier_order = /** @type {const} */ ([ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation', 'self', 'trusted', 'once' -]; +]); /** * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteWindow | AST.SvelteDocument | AST.SvelteBody} element diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index f5e0693b31..8f7ef76be5 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -1,5 +1,4 @@ /** @import { AST } from '#compiler' */ -/** @import { Comment } from 'estree' */ // @ts-expect-error acorn type definitions are borked in the release we use import { isIdentifierStart, isIdentifierChar } from 'acorn'; import fragment from './state/fragment.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js index 3e2f1414e6..c126742d3c 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 @@ -82,7 +82,9 @@ export function CallExpression(node, context) { ['debug', 'dir', 'error', 'group', 'groupCollapsed', 'info', 'log', 'trace', 'warn'].includes( node.callee.property.name ) && - node.arguments.some((arg) => arg.type !== 'Literal') // TODO more cases? + node.arguments.some( + (arg) => arg.type === 'SpreadElement' || context.state.scope.evaluate(arg).has_unknown + ) ) { return b.call( node.callee, 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 7a66a8ecbb..0ee3b0fb10 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/OnDirective.js @@ -3,14 +3,14 @@ import * as b from '#compiler/builders'; import { build_event, build_event_handler } from './shared/events.js'; -const modifiers = [ +const modifiers = /** @type {const} */ ([ 'stopPropagation', 'stopImmediatePropagation', 'preventDefault', 'self', 'trusted', 'once' -]; +]); /** * @param {AST.OnDirective} node diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js index 700e098e45..eaacf5dda9 100644 --- a/packages/svelte/src/compiler/phases/scope.js +++ b/packages/svelte/src/compiler/phases/scope.js @@ -180,6 +180,13 @@ class Evaluation { */ is_known = true; + /** + * True if the possible values contains `UNKNOWN` + * @readonly + * @type {boolean} + */ + has_unknown = false; + /** * True if the value is known to not be null/undefined * @readonly @@ -540,6 +547,10 @@ class Evaluation { if (value == null || value === UNKNOWN) { this.is_defined = false; } + + if (value === UNKNOWN) { + this.has_unknown = true; + } } if (this.values.size > 1 || typeof this.value === 'symbol') { diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index de06a41469..058a1a8e66 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -247,7 +247,17 @@ export namespace AST { name: string; /** The 'y' in `on:x={y}` */ expression: null | Expression; - modifiers: string[]; // TODO specify + modifiers: Array< + | 'capture' + | 'nonpassive' + | 'once' + | 'passive' + | 'preventDefault' + | 'self' + | 'stopImmediatePropagation' + | 'stopPropagation' + | 'trusted' + >; /** @internal */ metadata: { expression: ExpressionMetadata; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 9ea45af7e6..64aa9e23ba 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -1296,7 +1296,17 @@ declare module 'svelte/compiler' { name: string; /** The 'y' in `on:x={y}` */ expression: null | Expression; - modifiers: string[]; + modifiers: Array< + | 'capture' + | 'nonpassive' + | 'once' + | 'passive' + | 'preventDefault' + | 'self' + | 'stopImmediatePropagation' + | 'stopPropagation' + | 'trusted' + >; } /** A `style:` directive */ From 48f2fa22c0c941ac6e550151212845adc628b3de Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:04:06 -0700 Subject: [PATCH 02/28] fix: allow await expressions inside `{#await ...}` argument (#16514) * fix: allow await expressions inside `{#await ...}` argument * add test * apply suggestion from review --------- Co-authored-by: 7nik --- .changeset/long-roses-train.md | 5 +++ .../3-transform/client/visitors/AwaitBlock.js | 7 ++- .../samples/async-await/_config.js | 43 +++++++++++++++++++ .../samples/async-await/main.svelte | 22 ++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 .changeset/long-roses-train.md create mode 100644 packages/svelte/tests/runtime-runes/samples/async-await/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-await/main.svelte diff --git a/.changeset/long-roses-train.md b/.changeset/long-roses-train.md new file mode 100644 index 0000000000..10920ac5c4 --- /dev/null +++ b/.changeset/long-roses-train.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow await expressions inside `{#await ...}` argument 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 c550c8e17b..4246091bcf 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 @@ -1,7 +1,7 @@ /** @import { BlockStatement, Pattern, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentClientTransformState, ComponentContext } from '../types' */ -import { extract_identifiers } from '../../../../utils/ast.js'; +import { extract_identifiers, is_expression_async } from '../../../../utils/ast.js'; import * as b from '#compiler/builders'; import { create_derived } from '../utils.js'; import { get_value } from './shared/declarations.js'; @@ -15,7 +15,10 @@ export function AwaitBlock(node, context) { context.state.template.push_comment(); // Visit {#await } first to ensure that scopes are in the correct order - const expression = b.thunk(build_expression(context, node.expression, node.metadata.expression)); + const expression = b.thunk( + build_expression(context, node.expression, node.metadata.expression), + node.metadata.expression.has_await + ); let then_block; let catch_block; diff --git a/packages/svelte/tests/runtime-runes/samples/async-await/_config.js b/packages/svelte/tests/runtime-runes/samples/async-await/_config.js new file mode 100644 index 0000000000..dda6a7a895 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-await/_config.js @@ -0,0 +1,43 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const [reset, one, two, reject] = target.querySelectorAll('button'); + + await tick(); + assert.htmlEqual( + target.innerHTML, + ' waiting' + ); + + one.click(); + await tick(); + assert.htmlEqual( + target.innerHTML, + ' one_res' + ); + + reset.click(); + await tick(); + assert.htmlEqual( + target.innerHTML, + ' waiting' + ); + + two.click(); + await tick(); + assert.htmlEqual( + target.innerHTML, + ' two_res' + ); + + reset.click(); + reject.click(); + await tick(); + assert.htmlEqual( + target.innerHTML, + ' reject_catch' + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-await/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-await/main.svelte new file mode 100644 index 0000000000..8673e45414 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-await/main.svelte @@ -0,0 +1,22 @@ + + + + + + + + + {#await await deferred.promise + "_res"} + waiting + {:then res} + {res} + {:catch err} + {err}_catch + {/await} + + {#snippet pending()} +

pending

+ {/snippet} +
From d82edf6b1dfaac8af70462b1009f3b9da47a701a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:07:57 -0700 Subject: [PATCH 03/28] Version Packages (#16513) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/happy-countries-dance.md | 5 ----- .changeset/long-roses-train.md | 5 ----- .changeset/shaggy-comics-fail.md | 5 ----- .changeset/shiny-berries-call.md | 5 ----- .changeset/wise-hairs-pay.md | 5 ----- packages/svelte/CHANGELOG.md | 14 ++++++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 8 files changed, 16 insertions(+), 27 deletions(-) delete mode 100644 .changeset/happy-countries-dance.md delete mode 100644 .changeset/long-roses-train.md delete mode 100644 .changeset/shaggy-comics-fail.md delete mode 100644 .changeset/shiny-berries-call.md delete mode 100644 .changeset/wise-hairs-pay.md diff --git a/.changeset/happy-countries-dance.md b/.changeset/happy-countries-dance.md deleted file mode 100644 index 641cf21fd8..0000000000 --- a/.changeset/happy-countries-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -chore: remove some todos diff --git a/.changeset/long-roses-train.md b/.changeset/long-roses-train.md deleted file mode 100644 index 10920ac5c4..0000000000 --- a/.changeset/long-roses-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: allow await expressions inside `{#await ...}` argument diff --git a/.changeset/shaggy-comics-fail.md b/.changeset/shaggy-comics-fail.md deleted file mode 100644 index 981a25c978..0000000000 --- a/.changeset/shaggy-comics-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: `append_styles` in an effect to make them available on mount diff --git a/.changeset/shiny-berries-call.md b/.changeset/shiny-berries-call.md deleted file mode 100644 index adc62b3cd0..0000000000 --- a/.changeset/shiny-berries-call.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -chore: remove `parser.template_untrimmed` diff --git a/.changeset/wise-hairs-pay.md b/.changeset/wise-hairs-pay.md deleted file mode 100644 index 7d96c1daab..0000000000 --- a/.changeset/wise-hairs-pay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: always inject styles when compiling as a custom element diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index f939f69d28..59c44dd4f9 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,19 @@ # svelte +## 5.37.1 + +### Patch Changes + +- chore: remove some todos ([#16515](https://github.com/sveltejs/svelte/pull/16515)) + +- fix: allow await expressions inside `{#await ...}` argument ([#16514](https://github.com/sveltejs/svelte/pull/16514)) + +- fix: `append_styles` in an effect to make them available on mount ([#16509](https://github.com/sveltejs/svelte/pull/16509)) + +- chore: remove `parser.template_untrimmed` ([#16511](https://github.com/sveltejs/svelte/pull/16511)) + +- fix: always inject styles when compiling as a custom element ([#16509](https://github.com/sveltejs/svelte/pull/16509)) + ## 5.37.0 ### Minor Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index c781eda8c8..826850ea60 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.37.0", + "version": "5.37.1", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index e83ba6fb30..2d5083a2a5 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.37.0'; +export const VERSION = '5.37.1'; export const PUBLIC_VERSION = '5'; From a91e0154d4bc4b0a3209956647f868e518d0acba Mon Sep 17 00:00:00 2001 From: Laszlo Korte Date: Thu, 31 Jul 2025 09:45:52 +0200 Subject: [PATCH 04/28] fix: double event processing in Firefox (#16522) (#16527) * Fix double event processing (#16522) Firefox seems to garbage collect event objects during event propagation if no global reference to the event object is kept. That discards the __root marker set on the event object to early, leading to duplicate processing. * minor tweaks --------- Co-authored-by: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> --- .changeset/chilly-bananas-train.md | 5 +++++ .../svelte/src/internal/client/dom/elements/events.js | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 .changeset/chilly-bananas-train.md diff --git a/.changeset/chilly-bananas-train.md b/.changeset/chilly-bananas-train.md new file mode 100644 index 0000000000..b0305f9e61 --- /dev/null +++ b/.changeset/chilly-bananas-train.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: double event processing in firefox due to event object being garbage collected diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index fa3bf0b021..19bd1cfa18 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -141,6 +141,13 @@ export function delegate(events) { } } +// used to store the reference to the currently propagated event +// to prevent garbage collection between microtasks in Firefox +// If the event object is GCed too early, the expando __root property +// set on the event object is lost, causing the event delegation +// to process the event twice +let last_propagated_event = null; + /** * @this {EventTarget} * @param {Event} event @@ -153,6 +160,8 @@ export function handle_event_propagation(event) { var path = event.composedPath?.() || []; var current_target = /** @type {null | Element} */ (path[0] || event.target); + last_propagated_event = event; + // composedPath contains list of nodes the event has propagated through. // We check __root to skip all nodes below it in case this is a // parent of the __root node, which indicates that there's nested From f5950f866c51d9325a432ebfd5362bcf2647763a Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Thu, 31 Jul 2025 02:11:52 -0700 Subject: [PATCH 05/28] fix: correctly differentiate static fields before emitting `duplicate_class_field` (#16526) * fix: correctly differentiate static fields before emitting `duplicate_class_field` * remove unnecessary `#` concatenation * add test --- .changeset/nine-cups-film.md | 5 +++++ .../src/compiler/phases/2-analyze/visitors/ClassBody.js | 6 +++--- .../samples/class-state-constructor-9/input.svelte.js | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/nine-cups-film.md diff --git a/.changeset/nine-cups-film.md b/.changeset/nine-cups-film.md new file mode 100644 index 0000000000..ba72337dac --- /dev/null +++ b/.changeset/nine-cups-film.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: correctly differentiate static fields before emitting `duplicate_class_field` diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js index 2bfc1dbce3..dd21637174 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassBody.js @@ -57,7 +57,7 @@ export function ClassBody(node, context) { e.state_field_duplicate(node, name); } - const _key = (key.type === 'PrivateIdentifier' ? '#' : '') + name; + const _key = (node.type === 'AssignmentExpression' || !node.static ? '' : '@') + name; const field = fields.get(_key); // if there's already a method or assigned field, error @@ -78,7 +78,7 @@ export function ClassBody(node, context) { for (const child of node.body) { if (child.type === 'PropertyDefinition' && !child.computed && !child.static) { handle(child, child.key, child.value); - const key = (child.key.type === 'PrivateIdentifier' ? '#' : '') + get_name(child.key); + const key = /** @type {string} */ (get_name(child.key)); const field = fields.get(key); if (!field) { fields.set(key, [child.value ? 'assigned_prop' : 'prop']); @@ -91,7 +91,7 @@ export function ClassBody(node, context) { if (child.kind === 'constructor') { constructor = child; } else if (!child.computed) { - const key = (child.key.type === 'PrivateIdentifier' ? '#' : '') + get_name(child.key); + const key = (child.static ? '@' : '') + get_name(child.key); const field = fields.get(key); if (!field) { fields.set(key, [child.kind]); diff --git a/packages/svelte/tests/validator/samples/class-state-constructor-9/input.svelte.js b/packages/svelte/tests/validator/samples/class-state-constructor-9/input.svelte.js index a8469e13af..3806046f3f 100644 --- a/packages/svelte/tests/validator/samples/class-state-constructor-9/input.svelte.js +++ b/packages/svelte/tests/validator/samples/class-state-constructor-9/input.svelte.js @@ -1,6 +1,6 @@ export class Counter { count = -1; - + static count() {} constructor() { this.count = $state(0); } From 72e46d31c075eeea232a1cc320efc272f5ef87d7 Mon Sep 17 00:00:00 2001 From: Elliot Bentley Date: Thu, 31 Jul 2025 11:34:28 +0100 Subject: [PATCH 06/28] fix: add types for SVG bindable attributes (#16525) * fix: types for SVG bind: attributes * add changeset and tweak --------- Co-authored-by: 7nik --- .changeset/cuddly-feet-doubt.md | 5 +++++ packages/svelte/elements.d.ts | 14 ++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 .changeset/cuddly-feet-doubt.md diff --git a/.changeset/cuddly-feet-doubt.md b/.changeset/cuddly-feet-doubt.md new file mode 100644 index 0000000000..8d7d955daa --- /dev/null +++ b/.changeset/cuddly-feet-doubt.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: add bindable dimension attributes types to SVG and MathML elements diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index 2e1042dfd6..b3d44d9ed6 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -464,6 +464,14 @@ export interface DOMAttributes { onfullscreenerror?: EventHandler | undefined | null; onfullscreenerrorcapture?: EventHandler | undefined | null; + // Dimensions + readonly 'bind:contentRect'?: DOMRectReadOnly | undefined | null; + readonly 'bind:contentBoxSize'?: Array | undefined | null; + readonly 'bind:borderBoxSize'?: Array | undefined | null; + readonly 'bind:devicePixelContentBoxSize'?: Array | undefined | null; + readonly 'bind:clientWidth'?: number | undefined | null; + readonly 'bind:clientHeight'?: number | undefined | null; + xmlns?: string | undefined | null; } @@ -839,13 +847,7 @@ export interface HTMLAttributes extends AriaAttributes, D */ 'bind:innerText'?: string | undefined | null; - readonly 'bind:contentRect'?: DOMRectReadOnly | undefined | null; - readonly 'bind:contentBoxSize'?: Array | undefined | null; - readonly 'bind:borderBoxSize'?: Array | undefined | null; - readonly 'bind:devicePixelContentBoxSize'?: Array | undefined | null; readonly 'bind:focused'?: boolean | undefined | null; - readonly 'bind:clientWidth'?: number | undefined | null; - readonly 'bind:clientHeight'?: number | undefined | null; readonly 'bind:offsetWidth'?: number | undefined | null; readonly 'bind:offsetHeight'?: number | undefined | null; From c04975d3db74e59f8612ffd0f64d3b3bb3133ef1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 31 Jul 2025 18:28:01 -0400 Subject: [PATCH 07/28] fix: prevent last_propagated_event from being DCE'd (#16538) * fix: prevent last_propagated_event from being DCE'd * changeset --- .changeset/serious-cars-hear.md | 5 +++++ packages/svelte/src/internal/client/dom/elements/events.js | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/serious-cars-hear.md diff --git a/.changeset/serious-cars-hear.md b/.changeset/serious-cars-hear.md new file mode 100644 index 0000000000..4647e89ed9 --- /dev/null +++ b/.changeset/serious-cars-hear.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: prevent last_propagated_event from being DCE'd diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index 19bd1cfa18..15544d7426 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -168,8 +168,11 @@ export function handle_event_propagation(event) { // mounted apps. In this case we don't want to trigger events multiple times. var path_idx = 0; + // the `last_propagated_event === event` check is redundant, but + // without it the variable will be DCE'd and things will + // fail mysteriously in Firefox // @ts-expect-error is added below - var handled_at = event.__root; + var handled_at = last_propagated_event === event && event.__root; if (handled_at) { var at_idx = path.indexOf(handled_at); From 9134856fece750608ba81da45c4a330b3d8ebb1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 19:15:45 -0400 Subject: [PATCH 08/28] Version Packages (#16529) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/chilly-bananas-train.md | 5 ----- .changeset/cuddly-feet-doubt.md | 5 ----- .changeset/nine-cups-film.md | 5 ----- .changeset/serious-cars-hear.md | 5 ----- packages/svelte/CHANGELOG.md | 12 ++++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 7 files changed, 14 insertions(+), 22 deletions(-) delete mode 100644 .changeset/chilly-bananas-train.md delete mode 100644 .changeset/cuddly-feet-doubt.md delete mode 100644 .changeset/nine-cups-film.md delete mode 100644 .changeset/serious-cars-hear.md diff --git a/.changeset/chilly-bananas-train.md b/.changeset/chilly-bananas-train.md deleted file mode 100644 index b0305f9e61..0000000000 --- a/.changeset/chilly-bananas-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: double event processing in firefox due to event object being garbage collected diff --git a/.changeset/cuddly-feet-doubt.md b/.changeset/cuddly-feet-doubt.md deleted file mode 100644 index 8d7d955daa..0000000000 --- a/.changeset/cuddly-feet-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: add bindable dimension attributes types to SVG and MathML elements diff --git a/.changeset/nine-cups-film.md b/.changeset/nine-cups-film.md deleted file mode 100644 index ba72337dac..0000000000 --- a/.changeset/nine-cups-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: correctly differentiate static fields before emitting `duplicate_class_field` diff --git a/.changeset/serious-cars-hear.md b/.changeset/serious-cars-hear.md deleted file mode 100644 index 4647e89ed9..0000000000 --- a/.changeset/serious-cars-hear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: prevent last_propagated_event from being DCE'd diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 59c44dd4f9..6e0a199ddc 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,17 @@ # svelte +## 5.37.2 + +### Patch Changes + +- fix: double event processing in firefox due to event object being garbage collected ([#16527](https://github.com/sveltejs/svelte/pull/16527)) + +- fix: add bindable dimension attributes types to SVG and MathML elements ([#16525](https://github.com/sveltejs/svelte/pull/16525)) + +- fix: correctly differentiate static fields before emitting `duplicate_class_field` ([#16526](https://github.com/sveltejs/svelte/pull/16526)) + +- fix: prevent last_propagated_event from being DCE'd ([#16538](https://github.com/sveltejs/svelte/pull/16538)) + ## 5.37.1 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 826850ea60..8536135ca8 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.37.1", + "version": "5.37.2", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 2d5083a2a5..b8f3bcfdd5 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.37.1'; +export const VERSION = '5.37.2'; export const PUBLIC_VERSION = '5'; From 80678411706e99c0224b8bf995959c2d4e7fd4db Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Thu, 31 Jul 2025 16:16:47 -0700 Subject: [PATCH 09/28] docs: add note about attachments to `svelte/action` docs (#16537) --- documentation/docs/98-reference/21-svelte-action.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/docs/98-reference/21-svelte-action.md b/documentation/docs/98-reference/21-svelte-action.md index 53423ec409..ef3ebfbf70 100644 --- a/documentation/docs/98-reference/21-svelte-action.md +++ b/documentation/docs/98-reference/21-svelte-action.md @@ -2,4 +2,6 @@ title: svelte/action --- +This module provides types for [actions](use), which have been superseded by [attachments](@attach). + > MODULE: svelte/action From 540f1b19ec56a69dde85f24471f25d9d465937e4 Mon Sep 17 00:00:00 2001 From: 7nik Date: Sat, 2 Aug 2025 22:29:10 +0300 Subject: [PATCH 10/28] fix: reset attribute cache after setting corresponding property (#16543) --- .changeset/afraid-carrots-study.md | 5 +++++ .../client/dom/elements/attributes.js | 4 +++- .../attribute-after-property/_config.js | 19 +++++++++++++++++++ .../attribute-after-property/main.svelte | 6 ++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .changeset/afraid-carrots-study.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/attribute-after-property/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/attribute-after-property/main.svelte diff --git a/.changeset/afraid-carrots-study.md b/.changeset/afraid-carrots-study.md new file mode 100644 index 0000000000..71f4232edb --- /dev/null +++ b/.changeset/afraid-carrots-study.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: reset attribute cache after setting corresponding property diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 22e532f5e4..2fa5d4541c 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -19,7 +19,7 @@ import { attach } from './attachments.js'; import { clsx } from '../../../shared/attributes.js'; import { set_class } from './class.js'; import { set_style } from './style.js'; -import { ATTACHMENT_KEY, NAMESPACE_HTML } from '../../../../constants.js'; +import { ATTACHMENT_KEY, NAMESPACE_HTML, UNINITIALIZED } from '../../../../constants.js'; import { block, branch, destroy_effect, effect } from '../../reactivity/effects.js'; import { init_select, select_option } from './bindings/select.js'; import { flatten } from '../../reactivity/async.js'; @@ -446,6 +446,8 @@ export function set_attributes(element, prev, next, css_hash, skip_warning = fal ) { // @ts-ignore element[name] = value; + // remove it from attributes's cache + if (name in attributes) attributes[name] = UNINITIALIZED; } else if (typeof value !== 'function') { set_attribute(element, name, value, skip_warning); } diff --git a/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/_config.js b/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/_config.js new file mode 100644 index 0000000000..f6a98b1797 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/_config.js @@ -0,0 +1,19 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + test({ target, assert }) { + const input = target.querySelector('input'); + const button = target.querySelector('button'); + + assert.equal(input?.step, 'any'); + + button?.click(); + flushSync(); + assert.equal(input?.step, '10'); + + button?.click(); + flushSync(); + assert.equal(input?.step, 'any'); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/main.svelte b/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/main.svelte new file mode 100644 index 0000000000..2921e4e241 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/attribute-after-property/main.svelte @@ -0,0 +1,6 @@ + + + + \ No newline at end of file From 0cbb5becf6d62ae3334b78606a76d21a91eda32b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 21:17:58 -0700 Subject: [PATCH 11/28] Version Packages (#16544) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/afraid-carrots-study.md | 5 ----- packages/svelte/CHANGELOG.md | 6 ++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) delete mode 100644 .changeset/afraid-carrots-study.md diff --git a/.changeset/afraid-carrots-study.md b/.changeset/afraid-carrots-study.md deleted file mode 100644 index 71f4232edb..0000000000 --- a/.changeset/afraid-carrots-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: reset attribute cache after setting corresponding property diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 6e0a199ddc..9766e3f06b 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,11 @@ # svelte +## 5.37.3 + +### Patch Changes + +- fix: reset attribute cache after setting corresponding property ([#16543](https://github.com/sveltejs/svelte/pull/16543)) + ## 5.37.2 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 8536135ca8..e8927fcf56 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.37.2", + "version": "5.37.3", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index b8f3bcfdd5..127b43e205 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.37.2'; +export const VERSION = '5.37.3'; export const PUBLIC_VERSION = '5'; From a3f18351af4f70df4b9029aaa7198ac5dfeac6dc Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 5 Aug 2025 05:38:30 +0200 Subject: [PATCH 12/28] docs: corrections (#16550) * Add missing hyphen in "server-side rendering" * Fix incorrect use of "as such" * regenerate types --------- Co-authored-by: Chew Tee Ming --- documentation/docs/02-runes/04-$effect.md | 2 +- documentation/docs/03-template-syntax/06-snippet.md | 2 +- documentation/docs/03-template-syntax/08-@html.md | 2 +- .../docs/05-special-elements/07-svelte-options.md | 2 +- documentation/docs/06-runtime/03-lifecycle-hooks.md | 2 +- documentation/docs/07-misc/07-v5-migration-guide.md | 12 ++++++------ .../docs/98-reference/.generated/compile-errors.md | 2 +- .../docs/98-reference/.generated/compile-warnings.md | 2 +- packages/svelte/messages/compile-errors/script.md | 2 +- .../svelte/messages/compile-warnings/template.md | 2 +- packages/svelte/src/ambient.d.ts | 4 ++-- packages/svelte/types/index.d.ts | 4 ++-- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/documentation/docs/02-runes/04-$effect.md b/documentation/docs/02-runes/04-$effect.md index 5820e178a0..6c42f55795 100644 --- a/documentation/docs/02-runes/04-$effect.md +++ b/documentation/docs/02-runes/04-$effect.md @@ -135,7 +135,7 @@ An effect only reruns when the object it reads changes, not when a property insi An effect only depends on the values that it read the last time it ran. This has interesting implications for effects that have conditional code. -For instance, if `condition` is `true` in the code snippet below, the code inside the `if` block will run and `color` will be evaluated. As such, changes to either `condition` or `color` [will cause the effect to re-run](/playground/untitled#H4sIAAAAAAAAE21RQW6DMBD8ytaNBJHaJFLViwNIVZ8RcnBgXVk1xsILTYT4e20TQg89IOPZ2fHM7siMaJBx9tmaWpFqjQNlAKXEihx7YVJpdIyfRkY3G4gB8Pi97cPanRtQU8AuwuF_eNUaQuPlOMtc1SlLRWlKUo1tOwJflUikQHZtA0klzCDc64Imx0ANn8bInV1CDhtHgjClrsftcSXotluLybOUb3g4JJHhOZs5WZpuIS9gjNqkJKQP5e2ClrR4SMdZ13E4xZ8zTPOTJU2A2uE_PQ9COCI926_hTVarIU4hu_REPlBrKq2q73ycrf1N-vS4TMUsulaVg3EtR8H9rFgsg8uUsT1B2F9eshigZHBRpuaD0D3mY8Qm2BfB5N2YyRzdNEYVDy0Ja-WsFjcOUuP1HvFLWA6H3XuHTUSmmDV2--0TXonxsKbp7G9C6R__NONS-MFNvxj_d6mBAgAA). +For instance, if `condition` is `true` in the code snippet below, the code inside the `if` block will run and `color` will be evaluated. This means that changes to either `condition` or `color` [will cause the effect to re-run](/playground/untitled#H4sIAAAAAAAAE21RQW6DMBD8ytaNBJHaJFLViwNIVZ8RcnBgXVk1xsILTYT4e20TQg89IOPZ2fHM7siMaJBx9tmaWpFqjQNlAKXEihx7YVJpdIyfRkY3G4gB8Pi97cPanRtQU8AuwuF_eNUaQuPlOMtc1SlLRWlKUo1tOwJflUikQHZtA0klzCDc64Imx0ANn8bInV1CDhtHgjClrsftcSXotluLybOUb3g4JJHhOZs5WZpuIS9gjNqkJKQP5e2ClrR4SMdZ13E4xZ8zTPOTJU2A2uE_PQ9COCI926_hTVarIU4hu_REPlBrKq2q73ycrf1N-vS4TMUsulaVg3EtR8H9rFgsg8uUsT1B2F9eshigZHBRpuaD0D3mY8Qm2BfB5N2YyRzdNEYVDy0Ja-WsFjcOUuP1HvFLWA6H3XuHTUSmmDV2--0TXonxsKbp7G9C6R__NONS-MFNvxj_d6mBAgAA). Conversely, if `condition` is `false`, `color` will not be evaluated, and the effect will _only_ re-run again when `condition` changes. diff --git a/documentation/docs/03-template-syntax/06-snippet.md b/documentation/docs/03-template-syntax/06-snippet.md index ab536c6e5c..02f58e0f6c 100644 --- a/documentation/docs/03-template-syntax/06-snippet.md +++ b/documentation/docs/03-template-syntax/06-snippet.md @@ -277,4 +277,4 @@ Snippets can be created programmatically with the [`createRawSnippet`](svelte#cr ## Snippets and slots -In Svelte 4, content can be passed to components using [slots](legacy-slots). Snippets are more powerful and flexible, and as such slots are deprecated in Svelte 5. +In Svelte 4, content can be passed to components using [slots](legacy-slots). Snippets are more powerful and flexible, and so slots have been deprecated in Svelte 5. diff --git a/documentation/docs/03-template-syntax/08-@html.md b/documentation/docs/03-template-syntax/08-@html.md index 30456fa666..a92accd093 100644 --- a/documentation/docs/03-template-syntax/08-@html.md +++ b/documentation/docs/03-template-syntax/08-@html.md @@ -22,7 +22,7 @@ It also will not compile Svelte code. ## Styling -Content rendered this way is 'invisible' to Svelte and as such will not receive [scoped styles](scoped-styles) — in other words, this will not work, and the `a` and `img` styles will be regarded as unused: +Content rendered this way is 'invisible' to Svelte and thus will not receive [scoped styles](scoped-styles). In other words, this will not work, and the `a` and `img` styles will be regarded as unused: ```svelte diff --git a/documentation/docs/05-special-elements/07-svelte-options.md b/documentation/docs/05-special-elements/07-svelte-options.md index d29042e278..a2e47aa04f 100644 --- a/documentation/docs/05-special-elements/07-svelte-options.md +++ b/documentation/docs/05-special-elements/07-svelte-options.md @@ -12,7 +12,7 @@ The `` element provides a place to specify per-component compile - `runes={false}` — forces a component into _legacy mode_ - `namespace="..."` — the namespace where this component will be used, can be "html" (the default), "svg" or "mathml" - `customElement={...}` — the [options](custom-elements#Component-options) to use when compiling this component as a custom element. If a string is passed, it is used as the `tag` option -- `css="injected"` — the component will inject its styles inline: During server side rendering, it's injected as a `