From 9dddb31b4a9260a520d19e2955393da0aa1d7f3b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Jul 2025 08:07:08 -0400
Subject: [PATCH 01/13] Version Packages (#16276)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
.changeset/new-trees-behave.md | 5 -----
.changeset/short-fireants-flow.md | 5 -----
packages/svelte/CHANGELOG.md | 10 ++++++++++
packages/svelte/package.json | 2 +-
packages/svelte/src/version.js | 2 +-
5 files changed, 12 insertions(+), 12 deletions(-)
delete mode 100644 .changeset/new-trees-behave.md
delete mode 100644 .changeset/short-fireants-flow.md
diff --git a/.changeset/new-trees-behave.md b/.changeset/new-trees-behave.md
deleted file mode 100644
index d5fab30f3e..0000000000
--- a/.changeset/new-trees-behave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-chore: simplify props
diff --git a/.changeset/short-fireants-flow.md b/.changeset/short-fireants-flow.md
deleted file mode 100644
index b9955ff577..0000000000
--- a/.changeset/short-fireants-flow.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': minor
----
-
-feat: add `getAbortSignal()`
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index ef64091ca3..7589eda728 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,15 @@
# svelte
+## 5.35.0
+
+### Minor Changes
+
+- feat: add `getAbortSignal()` ([#16266](https://github.com/sveltejs/svelte/pull/16266))
+
+### Patch Changes
+
+- chore: simplify props ([#16270](https://github.com/sveltejs/svelte/pull/16270))
+
## 5.34.9
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index 2d88d2a051..e8c28aeaa1 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.34.9",
+ "version": "5.35.0",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 1c0aed6e87..baa2dbd046 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.34.9';
+export const VERSION = '5.35.0';
export const PUBLIC_VERSION = '5';
From 32882a956bc1283063d6da52401ac02b0aedefdb Mon Sep 17 00:00:00 2001
From: Simon H <5968653+dummdidumm@users.noreply.github.com>
Date: Wed, 2 Jul 2025 14:12:25 +0200
Subject: [PATCH 02/13] feat: add parent hierarchy to `__svelte_meta` objects
at dev time (#16255)
* feat: add parent hierarchy to `__svelte_meta` objects at dev time
This adds a `parent` property to the `__svelte_meta` properties that are added to elements at dev time. This property represents the closest non-element parent the element is related to. For example for `{#if ...}
foo
{/if}` the `parent` of the div would be the line/column of the if block.
The parent is recursive and goes upwards (through component boundaries) until the root component is reached, which has no parent.
part of #11389
* oops
* Apply suggestions from code review
Co-authored-by: Rich Harris
* tweak
* original component tag
* make render appear in tree, keep tree in sync when rerenders occur
---------
Co-authored-by: Rich Harris
---
.changeset/hot-buses-end.md | 5 +
.../3-transform/client/visitors/AwaitBlock.js | 8 +-
.../3-transform/client/visitors/EachBlock.js | 4 +-
.../3-transform/client/visitors/IfBlock.js | 4 +-
.../3-transform/client/visitors/KeyBlock.js | 8 +-
.../3-transform/client/visitors/RenderTag.js | 14 +-
.../client/visitors/shared/component.js | 10 +-
.../client/visitors/shared/utils.js | 35 +++-
packages/svelte/src/compiler/state.js | 3 +
.../svelte/src/internal/client/context.js | 40 +++-
.../src/internal/client/dev/elements.js | 2 +
.../src/internal/client/dom/blocks/await.js | 16 +-
.../client/dom/blocks/svelte-element.js | 3 +-
packages/svelte/src/internal/client/index.js | 2 +-
.../src/internal/client/reactivity/effects.js | 8 +-
.../src/internal/client/reactivity/types.d.ts | 10 +-
.../svelte/src/internal/client/runtime.js | 9 +-
.../svelte/src/internal/client/types.d.ts | 9 +
.../samples/svelte-meta-parent/_config.js | 186 ++++++++++++++++++
.../samples/svelte-meta-parent/child.svelte | 1 +
.../samples/svelte-meta-parent/main.svelte | 50 +++++
.../svelte-meta-parent/passthrough.svelte | 9 +
22 files changed, 408 insertions(+), 28 deletions(-)
create mode 100644 .changeset/hot-buses-end.md
create mode 100644 packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/_config.js
create mode 100644 packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/child.svelte
create mode 100644 packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/main.svelte
create mode 100644 packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/passthrough.svelte
diff --git a/.changeset/hot-buses-end.md b/.changeset/hot-buses-end.md
new file mode 100644
index 0000000000..dd5a28fca8
--- /dev/null
+++ b/.changeset/hot-buses-end.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+feat: add parent hierarchy to `__svelte_meta` objects
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 7873cf3ddb..c550c8e17b 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
@@ -5,7 +5,7 @@ import { extract_identifiers } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { create_derived } from '../utils.js';
import { get_value } from './shared/declarations.js';
-import { build_expression } from './shared/utils.js';
+import { build_expression, add_svelte_meta } from './shared/utils.js';
/**
* @param {AST.AwaitBlock} node
@@ -54,7 +54,7 @@ export function AwaitBlock(node, context) {
}
context.state.init.push(
- b.stmt(
+ add_svelte_meta(
b.call(
'$.await',
context.state.node,
@@ -64,7 +64,9 @@ export function AwaitBlock(node, context) {
: b.null,
then_block,
catch_block
- )
+ ),
+ node,
+ 'await'
)
);
}
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 201c4b278f..353927b865 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
@@ -13,7 +13,7 @@ import { dev } from '../../../../state.js';
import { extract_paths, object } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { get_value } from './shared/declarations.js';
-import { build_expression } from './shared/utils.js';
+import { build_expression, add_svelte_meta } from './shared/utils.js';
/**
* @param {AST.EachBlock} node
@@ -337,7 +337,7 @@ export function EachBlock(node, context) {
);
}
- context.state.init.push(b.stmt(b.call('$.each', ...args)));
+ context.state.init.push(add_svelte_meta(b.call('$.each', ...args), node, 'each'));
}
/**
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 deab040e50..cfd2bb7b09 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
@@ -2,7 +2,7 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders';
-import { build_expression } from './shared/utils.js';
+import { build_expression, add_svelte_meta } from './shared/utils.js';
/**
* @param {AST.IfBlock} node
@@ -74,7 +74,7 @@ export function IfBlock(node, context) {
args.push(b.id('$$elseif'));
}
- statements.push(b.stmt(b.call('$.if', ...args)));
+ statements.push(add_svelte_meta(b.call('$.if', ...args), node, 'if'));
context.state.init.push(b.block(statements));
}
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 2f17479c7e..3add1fbe93 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
@@ -2,7 +2,7 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders';
-import { build_expression } from './shared/utils.js';
+import { build_expression, add_svelte_meta } from './shared/utils.js';
/**
* @param {AST.KeyBlock} node
@@ -15,6 +15,10 @@ export function KeyBlock(node, context) {
const body = /** @type {Expression} */ (context.visit(node.fragment));
context.state.init.push(
- b.stmt(b.call('$.key', context.state.node, b.thunk(key), b.arrow([b.id('$$anchor')], body)))
+ add_svelte_meta(
+ b.call('$.key', context.state.node, b.thunk(key), b.arrow([b.id('$$anchor')], body)),
+ node,
+ 'key'
+ )
);
}
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 c3615d9d50..7f1a4ae7ba 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
@@ -3,7 +3,7 @@
/** @import { ComponentContext } from '../types' */
import { unwrap_optional } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
-import { build_expression } from './shared/utils.js';
+import { add_svelte_meta, build_expression } from './shared/utils.js';
/**
* @param {AST.RenderTag} node
@@ -48,16 +48,22 @@ export function RenderTag(node, context) {
}
context.state.init.push(
- b.stmt(b.call('$.snippet', context.state.node, b.thunk(snippet_function), ...args))
+ add_svelte_meta(
+ b.call('$.snippet', context.state.node, b.thunk(snippet_function), ...args),
+ node,
+ 'render'
+ )
);
} else {
context.state.init.push(
- b.stmt(
+ add_svelte_meta(
(node.expression.type === 'CallExpression' ? b.call : b.maybe_call)(
snippet_function,
context.state.node,
...args
- )
+ ),
+ node,
+ 'render'
)
);
}
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 cb6e4de478..aa3704b50b 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
@@ -4,7 +4,12 @@
import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
-import { build_bind_this, memoize_expression, validate_binding } from '../shared/utils.js';
+import {
+ build_bind_this,
+ memoize_expression,
+ validate_binding,
+ add_svelte_meta
+} from '../shared/utils.js';
import { build_attribute_value } from '../shared/element.js';
import { build_event_handler } from './events.js';
import { determine_slot } from '../../../../../utils/slot.js';
@@ -483,7 +488,8 @@ export function build_component(node, component_name, context) {
);
} else {
context.state.template.push_comment();
- statements.push(b.stmt(fn(anchor)));
+
+ statements.push(add_svelte_meta(fn(anchor), node, 'component', { componentTag: node.name }));
}
return statements.length > 1 ? b.block(statements) : statements[0];
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 b80466ccc9..de74fede0c 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
@@ -1,4 +1,4 @@
-/** @import { AssignmentExpression, Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Literal, Super, UpdateExpression, Pattern } from 'estree' */
+/** @import { AssignmentExpression, Expression, Identifier, MemberExpression, SequenceExpression, Literal, Super, UpdateExpression, ExpressionStatement } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext, Context } from '../../types' */
import { walk } from 'zimmerframe';
@@ -7,7 +7,7 @@ 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';
-import { dev, is_ignored, locator } from '../../../../../state.js';
+import { dev, is_ignored, locator, component_name } from '../../../../../state.js';
import { build_getter, create_derived } from '../../utils.js';
/**
@@ -424,3 +424,34 @@ export function build_expression(context, expression, metadata, state = context.
return sequence;
}
+
+/**
+ * Wraps a statement/expression with dev stack tracking in dev mode
+ * @param {Expression} expression - The function call to wrap (e.g., $.if, $.each, etc.)
+ * @param {{ start?: number }} node - AST node for location info
+ * @param {'component' | 'if' | 'each' | 'await' | 'key' | 'render'} type - Type of block/component
+ * @param {Record} [additional] - Any additional properties to add to the dev stack entry
+ * @returns {ExpressionStatement} - Statement with or without dev stack wrapping
+ */
+export function add_svelte_meta(expression, node, type, additional) {
+ if (!dev) {
+ return b.stmt(expression);
+ }
+
+ const location = node.start !== undefined && locator(node.start);
+ if (!location) {
+ return b.stmt(expression);
+ }
+
+ return b.stmt(
+ b.call(
+ '$.add_svelte_meta',
+ b.arrow([], expression),
+ b.literal(type),
+ b.id(component_name),
+ b.literal(location.line),
+ b.literal(location.column),
+ additional && b.object(Object.entries(additional).map(([k, v]) => b.init(k, b.literal(v))))
+ )
+ );
+}
diff --git a/packages/svelte/src/compiler/state.js b/packages/svelte/src/compiler/state.js
index 9095651ced..5eb25dd6bb 100644
--- a/packages/svelte/src/compiler/state.js
+++ b/packages/svelte/src/compiler/state.js
@@ -16,6 +16,9 @@ export let warnings = [];
*/
export let filename;
+/**
+ * The name of the component that is used in the `export default function ...` statement.
+ */
export let component_name = '';
/**
diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js
index 7c7213b7a2..e4220149ab 100644
--- a/packages/svelte/src/internal/client/context.js
+++ b/packages/svelte/src/internal/client/context.js
@@ -1,4 +1,4 @@
-/** @import { ComponentContext } from '#client' */
+/** @import { ComponentContext, DevStackEntry } from '#client' */
import { DEV } from 'esm-env';
import { lifecycle_outside_component } from '../shared/errors.js';
@@ -11,6 +11,7 @@ import {
} from './runtime.js';
import { effect, teardown } from './reactivity/effects.js';
import { legacy_mode_flag } from '../flags/index.js';
+import { FILENAME } from '../../constants.js';
/** @type {ComponentContext | null} */
export let component_context = null;
@@ -20,6 +21,43 @@ export function set_component_context(context) {
component_context = context;
}
+/** @type {DevStackEntry | null} */
+export let dev_stack = null;
+
+/** @param {DevStackEntry | null} stack */
+export function set_dev_stack(stack) {
+ dev_stack = stack;
+}
+
+/**
+ * Execute a callback with a new dev stack entry
+ * @param {() => any} callback - Function to execute
+ * @param {DevStackEntry['type']} type - Type of block/component
+ * @param {any} component - Component function
+ * @param {number} line - Line number
+ * @param {number} column - Column number
+ * @param {Record} [additional] - Any additional properties to add to the dev stack entry
+ * @returns {any}
+ */
+export function add_svelte_meta(callback, type, component, line, column, additional) {
+ const parent = dev_stack;
+
+ dev_stack = {
+ type,
+ file: component[FILENAME],
+ line,
+ column,
+ parent,
+ ...additional
+ };
+
+ try {
+ return callback();
+ } finally {
+ dev_stack = parent;
+ }
+}
+
/**
* The current component function. Different from current component context:
* ```html
diff --git a/packages/svelte/src/internal/client/dev/elements.js b/packages/svelte/src/internal/client/dev/elements.js
index f70f893d1e..8dd54e0a2a 100644
--- a/packages/svelte/src/internal/client/dev/elements.js
+++ b/packages/svelte/src/internal/client/dev/elements.js
@@ -2,6 +2,7 @@
import { COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE } from '#client/constants';
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../../constants.js';
import { hydrating } from '../dom/hydration.js';
+import { dev_stack } from '../context.js';
/**
* @param {any} fn
@@ -28,6 +29,7 @@ export function add_locations(fn, filename, locations) {
function assign_location(element, filename, location) {
// @ts-expect-error
element.__svelte_meta = {
+ parent: dev_stack,
loc: { file: filename, line: location[0], column: location[1] }
};
diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js
index 47df5fc9a5..325224fff2 100644
--- a/packages/svelte/src/internal/client/dom/blocks/await.js
+++ b/packages/svelte/src/internal/client/dom/blocks/await.js
@@ -16,9 +16,11 @@ import { queue_micro_task } from '../task.js';
import { HYDRATION_START_ELSE, UNINITIALIZED } from '../../../../constants.js';
import {
component_context,
+ dev_stack,
is_runes,
set_component_context,
- set_dev_current_component_function
+ set_dev_current_component_function,
+ set_dev_stack
} from '../../context.js';
const PENDING = 0;
@@ -45,6 +47,7 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
/** @type {any} */
var component_function = DEV ? component_context?.function : null;
+ var dev_original_stack = DEV ? dev_stack : null;
/** @type {V | Promise | typeof UNINITIALIZED} */
var input = UNINITIALIZED;
@@ -75,7 +78,10 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
set_active_effect(effect);
set_active_reaction(effect); // TODO do we need both?
set_component_context(active_component_context);
- if (DEV) set_dev_current_component_function(component_function);
+ if (DEV) {
+ set_dev_current_component_function(component_function);
+ set_dev_stack(dev_original_stack);
+ }
}
try {
@@ -107,7 +113,11 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
}
} finally {
if (restore) {
- if (DEV) set_dev_current_component_function(null);
+ if (DEV) {
+ set_dev_current_component_function(null);
+ set_dev_stack(null);
+ }
+
set_component_context(null);
set_active_reaction(null);
set_active_effect(null);
diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
index ffa57b2d8b..231a3621b1 100644
--- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
+++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
@@ -18,7 +18,7 @@ import {
import { set_should_intro } from '../../render.js';
import { current_each_item, set_current_each_item } from './each.js';
import { active_effect } from '../../runtime.js';
-import { component_context } from '../../context.js';
+import { component_context, dev_stack } from '../../context.js';
import { DEV } from 'esm-env';
import { EFFECT_TRANSPARENT, ELEMENT_NODE } from '#client/constants';
import { assign_nodes } from '../template.js';
@@ -107,6 +107,7 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
if (DEV && location) {
// @ts-expect-error
element.__svelte_meta = {
+ parent: dev_stack,
loc: {
file: filename,
line: location[0],
diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js
index 60f9af9120..576a30fa77 100644
--- a/packages/svelte/src/internal/client/index.js
+++ b/packages/svelte/src/internal/client/index.js
@@ -1,6 +1,6 @@
export { createAttachmentKey as attachment } from '../../attachments/index.js';
export { FILENAME, HMR, NAMESPACE_SVG } from '../../constants.js';
-export { push, pop } from './context.js';
+export { push, pop, add_svelte_meta } from './context.js';
export { assign, assign_and, assign_or, assign_nullish } from './dev/assign.js';
export { cleanup_styles } from './dev/css.js';
export { add_locations } from './dev/elements.js';
diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js
index a2806bde81..a2de8940a6 100644
--- a/packages/svelte/src/internal/client/reactivity/effects.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -41,7 +41,7 @@ import { DEV } from 'esm-env';
import { define_property } from '../../shared/utils.js';
import { get_next_sibling } from '../dom/operations.js';
import { derived } from './deriveds.js';
-import { component_context, dev_current_component_function } from '../context.js';
+import { component_context, dev_current_component_function, dev_stack } from '../context.js';
/**
* @param {'$effect' | '$effect.pre' | '$inspect'} rune
@@ -359,7 +359,11 @@ export function template_effect(fn, thunks = [], d = derived) {
* @param {number} flags
*/
export function block(fn, flags = 0) {
- return create_effect(RENDER_EFFECT | BLOCK_EFFECT | flags, fn, true);
+ var effect = create_effect(RENDER_EFFECT | BLOCK_EFFECT | flags, fn, true);
+ if (DEV) {
+ effect.dev_stack = dev_stack;
+ }
+ return effect;
}
/**
diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts
index 88c84f27fe..80c4155705 100644
--- a/packages/svelte/src/internal/client/reactivity/types.d.ts
+++ b/packages/svelte/src/internal/client/reactivity/types.d.ts
@@ -1,4 +1,10 @@
-import type { ComponentContext, Dom, Equals, TemplateNode, TransitionManager } from '#client';
+import type {
+ ComponentContext,
+ DevStackEntry,
+ Equals,
+ TemplateNode,
+ TransitionManager
+} from '#client';
export interface Signal {
/** Flags bitmask */
@@ -80,6 +86,8 @@ export interface Effect extends Reaction {
parent: Effect | null;
/** Dev only */
component_function?: any;
+ /** Dev only. Only set for certain block effects. Contains a reference to the stack that represents the render tree */
+ dev_stack?: DevStackEntry | null;
}
export type Source = Value;
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index 5a798ba3e9..8e6242447e 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -34,12 +34,13 @@ import { tracing_expressions, get_stack } from './dev/tracing.js';
import {
component_context,
dev_current_component_function,
+ dev_stack,
is_runes,
set_component_context,
- set_dev_current_component_function
+ set_dev_current_component_function,
+ set_dev_stack
} from './context.js';
import { handle_error, invoke_error_boundary } from './error-handling.js';
-import { snapshot } from '../shared/clone.js';
let is_flushing = false;
@@ -444,6 +445,9 @@ export function update_effect(effect) {
if (DEV) {
var previous_component_fn = dev_current_component_function;
set_dev_current_component_function(effect.component_function);
+ var previous_stack = /** @type {any} */ (dev_stack);
+ // only block effects have a dev stack, keep the current one otherwise
+ set_dev_stack(effect.dev_stack ?? dev_stack);
}
try {
@@ -478,6 +482,7 @@ export function update_effect(effect) {
if (DEV) {
set_dev_current_component_function(previous_component_fn);
+ set_dev_stack(previous_stack);
}
}
}
diff --git a/packages/svelte/src/internal/client/types.d.ts b/packages/svelte/src/internal/client/types.d.ts
index 9703c2aac1..0b7310e172 100644
--- a/packages/svelte/src/internal/client/types.d.ts
+++ b/packages/svelte/src/internal/client/types.d.ts
@@ -187,4 +187,13 @@ export type SourceLocation =
| [line: number, column: number]
| [line: number, column: number, SourceLocation[]];
+export interface DevStackEntry {
+ file: string;
+ type: 'component' | 'if' | 'each' | 'await' | 'key' | 'render';
+ line: number;
+ column: number;
+ parent: DevStackEntry | null;
+ componentTag?: string;
+}
+
export * from './reactivity/types';
diff --git a/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/_config.js b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/_config.js
new file mode 100644
index 0000000000..eba85d5098
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/_config.js
@@ -0,0 +1,186 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ mode: ['client', 'hydrate'],
+ compileOptions: {
+ dev: true
+ },
+ html: `
+ no parent
+ toggle
+ if
+ each
+ loading
+ key
+ hi
+ hi
+ hi
+ hi
+ hi
+ `,
+
+ async test({ target, assert }) {
+ function check() {
+ const [main, if_, each, await_, key, child1, child2, child3, child4, dynamic] =
+ target.querySelectorAll('p');
+
+ // @ts-expect-error
+ assert.deepEqual(main.__svelte_meta.parent, null);
+
+ // @ts-expect-error
+ assert.deepEqual(if_.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'if',
+ line: 12,
+ column: 0,
+ parent: null
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(each.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'each',
+ line: 16,
+ column: 0,
+ parent: null
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(await_.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'await',
+ line: 20,
+ column: 0,
+ parent: null
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(key.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'key',
+ line: 26,
+ column: 0,
+ parent: null
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(child1.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Child',
+ line: 30,
+ column: 0,
+ parent: null
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(child2.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Child',
+ line: 33,
+ column: 1,
+ parent: {
+ file: 'passthrough.svelte',
+ type: 'render',
+ line: 5,
+ column: 0,
+ parent: {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Passthrough',
+ line: 32,
+ column: 0,
+ parent: null
+ }
+ }
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(child3.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Child',
+ line: 38,
+ column: 2,
+ parent: {
+ file: 'passthrough.svelte',
+ type: 'render',
+ line: 5,
+ column: 0,
+ parent: {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Passthrough',
+ line: 37,
+ column: 1,
+ parent: {
+ file: 'passthrough.svelte',
+ type: 'render',
+ line: 5,
+ column: 0,
+ parent: {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Passthrough',
+ line: 36,
+ column: 0,
+ parent: null
+ }
+ }
+ }
+ }
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(child4.__svelte_meta.parent, {
+ file: 'passthrough.svelte',
+ type: 'render',
+ line: 8,
+ column: 1,
+ parent: {
+ file: 'passthrough.svelte',
+ type: 'if',
+ line: 7,
+ column: 0,
+ parent: {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'Passthrough',
+ line: 43,
+ column: 1,
+ parent: {
+ file: 'main.svelte',
+ type: 'if',
+ line: 42,
+ column: 0,
+ parent: null
+ }
+ }
+ }
+ });
+
+ // @ts-expect-error
+ assert.deepEqual(dynamic.__svelte_meta.parent, {
+ file: 'main.svelte',
+ type: 'component',
+ componentTag: 'x.y',
+ line: 50,
+ column: 0,
+ parent: null
+ });
+ }
+
+ await tick();
+ check();
+
+ // Test that stack is kept when re-rendering
+ const button = target.querySelector('button');
+ button?.click();
+ await tick();
+ button?.click();
+ await tick();
+ check();
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/child.svelte b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/child.svelte
new file mode 100644
index 0000000000..0df6def593
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/child.svelte
@@ -0,0 +1 @@
+hi
\ No newline at end of file
diff --git a/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/main.svelte b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/main.svelte
new file mode 100644
index 0000000000..b9bd46d8f7
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/main.svelte
@@ -0,0 +1,50 @@
+
+
+no parent
+ show = !show}>toggle
+
+{#if true}
+ if
+{/if}
+
+{#each [1]}
+ each
+{/each}
+
+{#await Promise.resolve()}
+ loading
+{:then}
+ await
+{/await}
+
+{#key key}
+ key
+{/key}
+
+
+
+
+
+
+
+
+
+
+
+
+
+{#if show}
+
+ {#snippet named()}
+ hi
+ {/snippet}
+
+{/if}
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/passthrough.svelte b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/passthrough.svelte
new file mode 100644
index 0000000000..70ba81a4c1
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/svelte-meta-parent/passthrough.svelte
@@ -0,0 +1,9 @@
+
+
+{@render children?.()}
+
+{#if true}
+ {@render named?.()}
+{/if}
From 49cba86e9b604f66bcd037e5eeb7a27788510b3b Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Wed, 2 Jul 2025 11:19:51 -0400
Subject: [PATCH 03/13] chore: rename EFFECT_HAS_DERIVED to EFFECT_PRESERVED
(#16283)
---
packages/svelte/src/internal/client/constants.js | 2 +-
packages/svelte/src/internal/client/reactivity/deriveds.js | 4 ++--
packages/svelte/src/internal/client/reactivity/effects.js | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js
index cd5e0d2244..38db28fecf 100644
--- a/packages/svelte/src/internal/client/constants.js
+++ b/packages/svelte/src/internal/client/constants.js
@@ -17,7 +17,7 @@ export const EFFECT_RAN = 1 << 15;
export const EFFECT_TRANSPARENT = 1 << 16;
export const INSPECT_EFFECT = 1 << 18;
export const HEAD_EFFECT = 1 << 19;
-export const EFFECT_HAS_DERIVED = 1 << 20;
+export const EFFECT_PRESERVED = 1 << 20;
export const EFFECT_IS_UPDATING = 1 << 21;
export const STATE_SYMBOL = Symbol('$state');
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
index d3123d24a1..fdfc13c0e2 100644
--- a/packages/svelte/src/internal/client/reactivity/deriveds.js
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -1,6 +1,6 @@
/** @import { Derived, Effect } from '#client' */
import { DEV } from 'esm-env';
-import { CLEAN, DERIVED, DIRTY, EFFECT_HAS_DERIVED, MAYBE_DIRTY, UNOWNED } from '#client/constants';
+import { CLEAN, DERIVED, DIRTY, EFFECT_PRESERVED, MAYBE_DIRTY, UNOWNED } from '#client/constants';
import {
active_reaction,
active_effect,
@@ -38,7 +38,7 @@ export function derived(fn) {
} else {
// Since deriveds are evaluated lazily, any effects created inside them are
// created too late to ensure that the parent effect is added to the tree
- active_effect.f |= EFFECT_HAS_DERIVED;
+ active_effect.f |= EFFECT_PRESERVED;
}
/** @type {Derived} */
diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js
index a2de8940a6..702c410ce8 100644
--- a/packages/svelte/src/internal/client/reactivity/effects.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -31,7 +31,7 @@ import {
INSPECT_EFFECT,
HEAD_EFFECT,
MAYBE_DIRTY,
- EFFECT_HAS_DERIVED,
+ EFFECT_PRESERVED,
BOUNDARY_EFFECT,
STALE_REACTION
} from '#client/constants';
@@ -135,7 +135,7 @@ function create_effect(type, fn, sync, push = true) {
effect.first === null &&
effect.nodes_start === null &&
effect.teardown === null &&
- (effect.f & (EFFECT_HAS_DERIVED | BOUNDARY_EFFECT)) === 0;
+ (effect.f & (EFFECT_PRESERVED | BOUNDARY_EFFECT)) === 0;
if (!inert && push) {
if (parent !== null) {
From 7914cb183554b16627bec40c8e91b163beaf0480 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Wed, 2 Jul 2025 12:16:53 -0400
Subject: [PATCH 04/13] chore: convert boundary implementation to a class
(#16284)
* WIP class boundaries
* WIP
* WIP
* WIP
* unused
* unused
* unused
---
.../internal/client/dom/blocks/boundary.js | 233 +++++++++++-------
.../src/internal/client/error-handling.js | 4 +-
.../src/internal/client/reactivity/effects.js | 1 +
.../src/internal/client/reactivity/types.d.ts | 3 +
4 files changed, 149 insertions(+), 92 deletions(-)
diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js
index d7a53da1d1..03cec4fd2f 100644
--- a/packages/svelte/src/internal/client/dom/blocks/boundary.js
+++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js
@@ -1,6 +1,5 @@
/** @import { Effect, TemplateNode, } from '#client' */
-
-import { BOUNDARY_EFFECT, EFFECT_TRANSPARENT } from '#client/constants';
+import { BOUNDARY_EFFECT, EFFECT_PRESERVED, EFFECT_TRANSPARENT } from '#client/constants';
import { component_context, set_component_context } from '../../context.js';
import { invoke_error_boundary } from '../../error-handling.js';
import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';
@@ -21,116 +20,170 @@ import {
import { queue_micro_task } from '../task.js';
/**
- * @param {Effect} boundary
- * @param {() => void} fn
+ * @typedef {{
+ * onerror?: (error: unknown, reset: () => void) => void;
+ * failed?: (anchor: Node, error: () => unknown, reset: () => () => void) => void;
+ * }} BoundaryProps
*/
-function with_boundary(boundary, fn) {
- var previous_effect = active_effect;
- var previous_reaction = active_reaction;
- var previous_ctx = component_context;
-
- set_active_effect(boundary);
- set_active_reaction(boundary);
- set_component_context(boundary.ctx);
-
- try {
- fn();
- } finally {
- set_active_effect(previous_effect);
- set_active_reaction(previous_reaction);
- set_component_context(previous_ctx);
- }
-}
+
+var flags = EFFECT_TRANSPARENT | EFFECT_PRESERVED | BOUNDARY_EFFECT;
/**
* @param {TemplateNode} node
- * @param {{
- * onerror?: (error: unknown, reset: () => void) => void,
- * failed?: (anchor: Node, error: () => unknown, reset: () => () => void) => void
- * }} props
- * @param {((anchor: Node) => void)} boundary_fn
+ * @param {BoundaryProps} props
+ * @param {((anchor: Node) => void)} children
* @returns {void}
*/
-export function boundary(node, props, boundary_fn) {
- var anchor = node;
+export function boundary(node, props, children) {
+ new Boundary(node, props, children);
+}
+
+export class Boundary {
+ /** @type {TemplateNode} */
+ #anchor;
+
+ /** @type {TemplateNode} */
+ #hydrate_open;
+
+ /** @type {BoundaryProps} */
+ #props;
+
+ /** @type {((anchor: Node) => void)} */
+ #children;
/** @type {Effect} */
- var boundary_effect;
-
- block(() => {
- var boundary = /** @type {Effect} */ (active_effect);
- var hydrate_open = hydrate_node;
- var is_creating_fallback = false;
-
- // We re-use the effect's fn property to avoid allocation of an additional field
- boundary.fn = (/** @type {unknown}} */ error) => {
- var onerror = props.onerror;
- let failed = props.failed;
-
- // If we have nothing to capture the error, or if we hit an error while
- // rendering the fallback, re-throw for another boundary to handle
- if ((!onerror && !failed) || is_creating_fallback) {
- throw error;
- }
+ #effect;
- var reset = () => {
- pause_effect(boundary_effect);
+ /** @type {Effect | null} */
+ #main_effect = null;
- with_boundary(boundary, () => {
- is_creating_fallback = false;
- boundary_effect = branch(() => boundary_fn(anchor));
- });
- };
+ /** @type {Effect | null} */
+ #failed_effect = null;
- var previous_reaction = active_reaction;
+ #is_creating_fallback = false;
- try {
- set_active_reaction(null);
- onerror?.(error, reset);
- } finally {
- set_active_reaction(previous_reaction);
+ /**
+ * @param {TemplateNode} node
+ * @param {BoundaryProps} props
+ * @param {((anchor: Node) => void)} children
+ */
+ constructor(node, props, children) {
+ this.#anchor = node;
+ this.#props = props;
+ this.#children = children;
+
+ this.#hydrate_open = hydrate_node;
+
+ this.#effect = block(() => {
+ /** @type {Effect} */ (active_effect).b = this;
+
+ if (hydrating) {
+ hydrate_next();
}
- if (boundary_effect) {
- destroy_effect(boundary_effect);
- } else if (hydrating) {
- set_hydrate_node(hydrate_open);
- next();
- set_hydrate_node(remove_nodes());
+ try {
+ this.#main_effect = branch(() => children(this.#anchor));
+ } catch (error) {
+ this.error(error);
}
+ }, flags);
- if (failed) {
- // Render the `failed` snippet in a microtask
- queue_micro_task(() => {
- with_boundary(boundary, () => {
- is_creating_fallback = true;
-
- try {
- boundary_effect = branch(() => {
- failed(
- anchor,
- () => error,
- () => reset
- );
- });
- } catch (error) {
- invoke_error_boundary(error, /** @type {Effect} */ (boundary.parent));
- }
-
- is_creating_fallback = false;
- });
+ if (hydrating) {
+ this.#anchor = hydrate_node;
+ }
+ }
+
+ /**
+ * @param {() => Effect | null} fn
+ */
+ #run(fn) {
+ var previous_effect = active_effect;
+ var previous_reaction = active_reaction;
+ var previous_ctx = component_context;
+
+ set_active_effect(this.#effect);
+ set_active_reaction(this.#effect);
+ set_component_context(this.#effect.ctx);
+
+ try {
+ return fn();
+ } finally {
+ set_active_effect(previous_effect);
+ set_active_reaction(previous_reaction);
+ set_component_context(previous_ctx);
+ }
+ }
+
+ /** @param {unknown} error */
+ error(error) {
+ var onerror = this.#props.onerror;
+ let failed = this.#props.failed;
+
+ const reset = () => {
+ if (this.#failed_effect !== null) {
+ pause_effect(this.#failed_effect, () => {
+ this.#failed_effect = null;
});
}
+
+ this.#main_effect = this.#run(() => {
+ this.#is_creating_fallback = false;
+ return branch(() => this.#children(this.#anchor));
+ });
};
- if (hydrating) {
- hydrate_next();
+ // If we have nothing to capture the error, or if we hit an error while
+ // rendering the fallback, re-throw for another boundary to handle
+ if (this.#is_creating_fallback || (!onerror && !failed)) {
+ throw error;
+ }
+
+ var previous_reaction = active_reaction;
+
+ try {
+ set_active_reaction(null);
+ onerror?.(error, reset);
+ } finally {
+ set_active_reaction(previous_reaction);
}
- boundary_effect = branch(() => boundary_fn(anchor));
- }, EFFECT_TRANSPARENT | BOUNDARY_EFFECT);
+ if (this.#main_effect) {
+ destroy_effect(this.#main_effect);
+ this.#main_effect = null;
+ }
- if (hydrating) {
- anchor = hydrate_node;
+ if (this.#failed_effect) {
+ destroy_effect(this.#failed_effect);
+ this.#failed_effect = null;
+ }
+
+ if (hydrating) {
+ set_hydrate_node(this.#hydrate_open);
+ next();
+ set_hydrate_node(remove_nodes());
+ }
+
+ if (failed) {
+ queue_micro_task(() => {
+ this.#failed_effect = this.#run(() => {
+ this.#is_creating_fallback = true;
+
+ try {
+ return branch(() => {
+ failed(
+ this.#anchor,
+ () => error,
+ () => reset
+ );
+ });
+ } catch (error) {
+ invoke_error_boundary(error, /** @type {Effect} */ (this.#effect.parent));
+ return null;
+ } finally {
+ this.#is_creating_fallback = false;
+ }
+ });
+ });
+ }
}
}
diff --git a/packages/svelte/src/internal/client/error-handling.js b/packages/svelte/src/internal/client/error-handling.js
index 99f3ed6cd4..378f7408ef 100644
--- a/packages/svelte/src/internal/client/error-handling.js
+++ b/packages/svelte/src/internal/client/error-handling.js
@@ -1,4 +1,5 @@
/** @import { Effect } from '#client' */
+/** @import { Boundary } from './dom/blocks/boundary.js' */
import { DEV } from 'esm-env';
import { FILENAME } from '../../constants.js';
import { is_firefox } from './dom/operations.js';
@@ -39,8 +40,7 @@ export function invoke_error_boundary(error, effect) {
while (effect !== null) {
if ((effect.f & BOUNDARY_EFFECT) !== 0) {
try {
- // @ts-expect-error
- effect.fn(error);
+ /** @type {Boundary} */ (effect.b).error(error);
return;
} catch {}
}
diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js
index 702c410ce8..7570064c37 100644
--- a/packages/svelte/src/internal/client/reactivity/effects.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -104,6 +104,7 @@ function create_effect(type, fn, sync, push = true) {
last: null,
next: null,
parent,
+ b: parent && parent.b,
prev: null,
teardown: null,
transitions: null,
diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts
index 80c4155705..90f922df68 100644
--- a/packages/svelte/src/internal/client/reactivity/types.d.ts
+++ b/packages/svelte/src/internal/client/reactivity/types.d.ts
@@ -5,6 +5,7 @@ import type {
TemplateNode,
TransitionManager
} from '#client';
+import type { Boundary } from '../dom/blocks/boundary';
export interface Signal {
/** Flags bitmask */
@@ -84,6 +85,8 @@ export interface Effect extends Reaction {
last: null | Effect;
/** Parent effect */
parent: Effect | null;
+ /** The boundary this effect belongs to */
+ b: Boundary | null;
/** Dev only */
component_function?: any;
/** Dev only. Only set for certain block effects. Contains a reference to the stack that represents the render tree */
From dde791311d3c6a7b28e276548e6beb45a9f2e798 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Wed, 2 Jul 2025 13:06:45 -0400
Subject: [PATCH 05/13] chore: minor tweaks (#16285)
---
packages/svelte/src/internal/client/constants.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js
index 38db28fecf..1cffa43940 100644
--- a/packages/svelte/src/internal/client/constants.js
+++ b/packages/svelte/src/internal/client/constants.js
@@ -15,17 +15,17 @@ export const DESTROYED = 1 << 14;
export const EFFECT_RAN = 1 << 15;
/** 'Transparent' effects do not create a transition boundary */
export const EFFECT_TRANSPARENT = 1 << 16;
-export const INSPECT_EFFECT = 1 << 18;
-export const HEAD_EFFECT = 1 << 19;
-export const EFFECT_PRESERVED = 1 << 20;
-export const EFFECT_IS_UPDATING = 1 << 21;
+export const INSPECT_EFFECT = 1 << 17;
+export const HEAD_EFFECT = 1 << 18;
+export const EFFECT_PRESERVED = 1 << 19;
+export const EFFECT_IS_UPDATING = 1 << 20;
export const STATE_SYMBOL = Symbol('$state');
export const LEGACY_PROPS = Symbol('legacy props');
export const LOADING_ATTR_SYMBOL = Symbol('');
export const PROXY_PATH_SYMBOL = Symbol('proxy path');
-// allow users to ignore aborted signal errors if `reason.stale`
+/** allow users to ignore aborted signal errors if `reason.name === 'StaleReactionError` */
export const STALE_REACTION = new (class StaleReactionError extends Error {
name = 'StaleReactionError';
message = 'The reaction that called `getAbortSignal()` was re-run or destroyed';
From 5ebbedf2051715f1df10a884976d7d23b1d7f5fc Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 2 Jul 2025 22:18:28 +0200
Subject: [PATCH 06/13] Version Packages (#16281)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
.changeset/hot-buses-end.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/hot-buses-end.md
diff --git a/.changeset/hot-buses-end.md b/.changeset/hot-buses-end.md
deleted file mode 100644
index dd5a28fca8..0000000000
--- a/.changeset/hot-buses-end.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-feat: add parent hierarchy to `__svelte_meta` objects
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index 7589eda728..fb5d43c9dd 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,11 @@
# svelte
+## 5.35.1
+
+### Patch Changes
+
+- feat: add parent hierarchy to `__svelte_meta` objects ([#16255](https://github.com/sveltejs/svelte/pull/16255))
+
## 5.35.0
### Minor Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index e8c28aeaa1..b1e57b9829 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.35.0",
+ "version": "5.35.1",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index baa2dbd046..2efcf03eb1 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.35.0';
+export const VERSION = '5.35.1';
export const PUBLIC_VERSION = '5';
From eeb32a50d14d2ac69970b0e207746092a34d2fc3 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Thu, 3 Jul 2025 11:47:26 -0400
Subject: [PATCH 07/13] fix: bump esrap (#16295)
---
.changeset/fifty-hats-watch.md | 5 +++++
packages/svelte/package.json | 2 +-
pnpm-lock.yaml | 10 +++++-----
3 files changed, 11 insertions(+), 6 deletions(-)
create mode 100644 .changeset/fifty-hats-watch.md
diff --git a/.changeset/fifty-hats-watch.md b/.changeset/fifty-hats-watch.md
new file mode 100644
index 0000000000..83bb72e735
--- /dev/null
+++ b/.changeset/fifty-hats-watch.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: bump esrap
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index b1e57b9829..b6776a8fbc 100644
--- a/packages/svelte/package.json
+++ b/packages/svelte/package.json
@@ -171,7 +171,7 @@
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
"esm-env": "^1.2.1",
- "esrap": "^2.0.0",
+ "esrap": "^2.1.0",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b7fb655b2d..87fb2b2667 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -87,8 +87,8 @@ importers:
specifier: ^1.2.1
version: 1.2.1
esrap:
- specifier: ^2.0.0
- version: 2.0.0
+ specifier: ^2.1.0
+ version: 2.1.0
is-reference:
specifier: ^3.0.3
version: 3.0.3
@@ -1261,8 +1261,8 @@ packages:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
- esrap@2.0.0:
- resolution: {integrity: sha512-zhw1TDqno99Ld5wOpe0t47rzVyxfGc1fvxNzPsqk4idUf5dcAePkAyfTceLJaSTytjiWDu26S5tI+grjvymXJA==}
+ esrap@2.1.0:
+ resolution: {integrity: sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==}
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
@@ -3622,7 +3622,7 @@ snapshots:
dependencies:
estraverse: 5.3.0
- esrap@2.0.0:
+ esrap@2.1.0:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
From 220e901a825a23df7c310cd5978d3141e573e645 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 3 Jul 2025 11:50:58 -0400
Subject: [PATCH 08/13] Version Packages (#16297)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
.changeset/fifty-hats-watch.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/fifty-hats-watch.md
diff --git a/.changeset/fifty-hats-watch.md b/.changeset/fifty-hats-watch.md
deleted file mode 100644
index 83bb72e735..0000000000
--- a/.changeset/fifty-hats-watch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: bump esrap
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index fb5d43c9dd..ad72bfabb0 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,11 @@
# svelte
+## 5.35.2
+
+### Patch Changes
+
+- fix: bump esrap ([#16295](https://github.com/sveltejs/svelte/pull/16295))
+
## 5.35.1
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index b6776a8fbc..872c21a179 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.35.1",
+ "version": "5.35.2",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 2efcf03eb1..47c354c7a2 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.35.1';
+export const VERSION = '5.35.2';
export const PUBLIC_VERSION = '5';
From 432763a03ebcb4c03e7c5084cb52aac6f1afaa22 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Thu, 3 Jul 2025 12:11:28 -0400
Subject: [PATCH 09/13] chore: `reaction_sources` -> `source_ownership`
(#16287)
* reaction_sources -> source_ownership
* put equality statements first, it's faster
---
.../src/internal/client/reactivity/sources.js | 4 +--
.../svelte/src/internal/client/runtime.js | 28 ++++++++++++-------
2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index 0db3530232..a86ccfee4f 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -11,7 +11,7 @@ import {
untrack,
increment_write_version,
update_effect,
- reaction_sources,
+ source_ownership,
check_dirtiness,
untracking,
is_destroying_effect,
@@ -140,7 +140,7 @@ export function set(source, value, should_proxy = false) {
(!untracking || (active_reaction.f & INSPECT_EFFECT) !== 0) &&
is_runes() &&
(active_reaction.f & (DERIVED | BLOCK_EFFECT | INSPECT_EFFECT)) !== 0 &&
- !(reaction_sources?.[1].includes(source) && reaction_sources[0] === active_reaction)
+ !(source_ownership?.reaction === active_reaction && source_ownership.sources.includes(source))
) {
e.state_unsafe_mutation();
}
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index 8e6242447e..fce6c78b56 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -86,17 +86,17 @@ export function set_active_effect(effect) {
/**
* When sources are created within a reaction, reading and writing
* them within that reaction should not cause a re-run
- * @type {null | [active_reaction: Reaction, sources: Source[]]}
+ * @type {null | { reaction: Reaction, sources: Source[] }}
*/
-export let reaction_sources = null;
+export let source_ownership = null;
/** @param {Value} value */
export function push_reaction_value(value) {
if (active_reaction !== null && active_reaction.f & EFFECT_IS_UPDATING) {
- if (reaction_sources === null) {
- reaction_sources = [active_reaction, [value]];
+ if (source_ownership === null) {
+ source_ownership = { reaction: active_reaction, sources: [value] };
} else {
- reaction_sources[1].push(value);
+ source_ownership.sources.push(value);
}
}
}
@@ -235,7 +235,12 @@ function schedule_possible_effect_self_invalidation(signal, effect, root = true)
for (var i = 0; i < reactions.length; i++) {
var reaction = reactions[i];
- if (reaction_sources?.[1].includes(signal) && reaction_sources[0] === active_reaction) continue;
+ if (
+ source_ownership?.reaction === active_reaction &&
+ source_ownership.sources.includes(signal)
+ ) {
+ continue;
+ }
if ((reaction.f & DERIVED) !== 0) {
schedule_possible_effect_self_invalidation(/** @type {Derived} */ (reaction), effect, false);
@@ -257,7 +262,7 @@ export function update_reaction(reaction) {
var previous_untracked_writes = untracked_writes;
var previous_reaction = active_reaction;
var previous_skip_reaction = skip_reaction;
- var previous_reaction_sources = reaction_sources;
+ var previous_reaction_sources = source_ownership;
var previous_component_context = component_context;
var previous_untracking = untracking;
@@ -270,7 +275,7 @@ export function update_reaction(reaction) {
(flags & UNOWNED) !== 0 && (untracking || !is_updating_effect || active_reaction === null);
active_reaction = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
- reaction_sources = null;
+ source_ownership = null;
set_component_context(reaction.ctx);
untracking = false;
read_version++;
@@ -358,7 +363,7 @@ export function update_reaction(reaction) {
untracked_writes = previous_untracked_writes;
active_reaction = previous_reaction;
skip_reaction = previous_skip_reaction;
- reaction_sources = previous_reaction_sources;
+ source_ownership = previous_reaction_sources;
set_component_context(previous_component_context);
untracking = previous_untracking;
@@ -739,7 +744,10 @@ export function get(signal) {
// Register the dependency on the current reaction signal.
if (active_reaction !== null && !untracking) {
- if (!reaction_sources?.[1].includes(signal) || reaction_sources[0] !== active_reaction) {
+ if (
+ source_ownership?.reaction !== active_reaction ||
+ !source_ownership?.sources.includes(signal)
+ ) {
var deps = active_reaction.deps;
if (signal.rv < read_version) {
signal.rv = read_version;
From c3348aea06b5dcc13159b96053351f36d6cb6d71 Mon Sep 17 00:00:00 2001
From: 7nik
Date: Fri, 4 Jul 2025 17:54:37 +0300
Subject: [PATCH 10/13] fix: do not proxify the value assigned to a derived
(#16302)
---
.changeset/new-wolves-punch.md | 5 ++++
.../client/visitors/AssignmentExpression.js | 1 +
.../samples/writable-derived-4/_config.js | 23 +++++++++++++++++++
.../samples/writable-derived-4/main.svelte | 9 ++++++++
4 files changed, 38 insertions(+)
create mode 100644 .changeset/new-wolves-punch.md
create mode 100644 packages/svelte/tests/runtime-runes/samples/writable-derived-4/_config.js
create mode 100644 packages/svelte/tests/runtime-runes/samples/writable-derived-4/main.svelte
diff --git a/.changeset/new-wolves-punch.md b/.changeset/new-wolves-punch.md
new file mode 100644
index 0000000000..c856038cbc
--- /dev/null
+++ b/.changeset/new-wolves-punch.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: do not proxify the value assigned to a derived
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 ce190814f8..7d64d60bca 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
@@ -137,6 +137,7 @@ function build_assignment(operator, left, right, context) {
binding.kind !== 'prop' &&
binding.kind !== 'bindable_prop' &&
binding.kind !== 'raw_state' &&
+ binding.kind !== 'derived' &&
binding.kind !== 'store_sub' &&
context.state.analysis.runes &&
should_proxy(right, context.state.scope) &&
diff --git a/packages/svelte/tests/runtime-runes/samples/writable-derived-4/_config.js b/packages/svelte/tests/runtime-runes/samples/writable-derived-4/_config.js
new file mode 100644
index 0000000000..8d312ca73a
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/writable-derived-4/_config.js
@@ -0,0 +1,23 @@
+import { flushSync } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ test({ assert, target }) {
+ const [btn1, btn2, btn3] = target.getElementsByTagName('button');
+ const [div] = target.getElementsByTagName('div');
+
+ flushSync(() => btn1.click());
+ assert.equal(div.textContent, '1');
+ flushSync(() => btn2.click());
+ assert.equal(div.textContent, '1');
+ flushSync(() => btn3.click());
+ assert.equal(div.textContent, '2');
+
+ flushSync(() => btn1.click());
+ assert.equal(div.textContent, '2');
+ flushSync(() => btn2.click());
+ assert.equal(div.textContent, '2');
+ flushSync(() => btn3.click());
+ assert.equal(div.textContent, '3');
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/writable-derived-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/writable-derived-4/main.svelte
new file mode 100644
index 0000000000..a24f69ba77
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/writable-derived-4/main.svelte
@@ -0,0 +1,9 @@
+
+
+ count.value++}>mutate
+ count = count}>assign self
+ count = {...count} }>assign copy
+
+{count.value}
From 834cd91b367172859b26d35a23aad4e87800b881 Mon Sep 17 00:00:00 2001
From: Paolo Ricciuti
Date: Sun, 6 Jul 2025 14:57:45 +0200
Subject: [PATCH 11/13] fix: account for mounting when `select_option` in
`attribute_effect` (#16309)
---
.changeset/curvy-carrots-prove.md | 5 +++++
.../src/internal/client/dom/elements/attributes.js | 5 +++--
.../samples/select-spread-option-selected/_config.js | 9 +++++++++
.../samples/select-spread-option-selected/main.svelte | 8 ++++++++
4 files changed, 25 insertions(+), 2 deletions(-)
create mode 100644 .changeset/curvy-carrots-prove.md
create mode 100644 packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/_config.js
create mode 100644 packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/main.svelte
diff --git a/.changeset/curvy-carrots-prove.md b/.changeset/curvy-carrots-prove.md
new file mode 100644
index 0000000000..7723990179
--- /dev/null
+++ b/.changeset/curvy-carrots-prove.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: account for mounting when `select_option` in `attribute_effect`
diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js
index 5db685cf3e..c96338778f 100644
--- a/packages/svelte/src/internal/client/dom/elements/attributes.js
+++ b/packages/svelte/src/internal/client/dom/elements/attributes.js
@@ -514,9 +514,10 @@ export function attribute_effect(
if (is_select) {
var select = /** @type {HTMLSelectElement} */ (element);
-
+ var mounting = true;
effect(() => {
- select_option(select, /** @type {Record} */ (prev).value);
+ select_option(select, /** @type {Record} */ (prev).value, mounting);
+ mounting = false;
init_select(select);
});
}
diff --git a/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/_config.js b/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/_config.js
new file mode 100644
index 0000000000..50da3ac095
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/_config.js
@@ -0,0 +1,9 @@
+import { ok, test } from '../../test';
+
+export default test({
+ async test({ assert, target, instance }) {
+ const select = target.querySelector('select');
+ ok(select);
+ assert.equal(select.selectedIndex, 1);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/main.svelte b/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/main.svelte
new file mode 100644
index 0000000000..e5fc6c5535
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/select-spread-option-selected/main.svelte
@@ -0,0 +1,8 @@
+
+
+
+ o1
+ o2
+
From 4a26edf54576152affe8649eca8c9b3d1a5b8015 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 7 Jul 2025 10:17:17 -0400
Subject: [PATCH 12/13] chore: remove unused `mounting` variable from
`select_option` call (#16312)
---
.../svelte/src/internal/client/dom/elements/attributes.js | 7 +++----
.../src/internal/client/dom/elements/bindings/select.js | 4 ++--
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js
index c96338778f..66f484a59a 100644
--- a/packages/svelte/src/internal/client/dom/elements/attributes.js
+++ b/packages/svelte/src/internal/client/dom/elements/attributes.js
@@ -491,7 +491,7 @@ export function attribute_effect(
var current = set_attributes(element, prev, next, css_hash, skip_warning);
if (inited && is_select && 'value' in next) {
- select_option(/** @type {HTMLSelectElement} */ (element), next.value, false);
+ select_option(/** @type {HTMLSelectElement} */ (element), next.value);
}
for (let symbol of Object.getOwnPropertySymbols(effects)) {
@@ -514,10 +514,9 @@ export function attribute_effect(
if (is_select) {
var select = /** @type {HTMLSelectElement} */ (element);
- var mounting = true;
+
effect(() => {
- select_option(select, /** @type {Record} */ (prev).value, mounting);
- mounting = false;
+ select_option(select, /** @type {Record} */ (prev).value, true);
init_select(select);
});
}
diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/select.js b/packages/svelte/src/internal/client/dom/elements/bindings/select.js
index 5e89686d86..e39fb865cd 100644
--- a/packages/svelte/src/internal/client/dom/elements/bindings/select.js
+++ b/packages/svelte/src/internal/client/dom/elements/bindings/select.js
@@ -9,9 +9,9 @@ import * as w from '../../../warnings.js';
* @template V
* @param {HTMLSelectElement} select
* @param {V} value
- * @param {boolean} [mounting]
+ * @param {boolean} mounting
*/
-export function select_option(select, value, mounting) {
+export function select_option(select, value, mounting = false) {
if (select.multiple) {
// If value is null or undefined, keep the selection as is
if (value == undefined) {
From 63e48365fbad844f5a82cf5e5a994fdfd13f419b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 7 Jul 2025 10:53:41 -0400
Subject: [PATCH 13/13] Version Packages (#16303)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
.changeset/curvy-carrots-prove.md | 5 -----
.changeset/new-wolves-punch.md | 5 -----
packages/svelte/CHANGELOG.md | 8 ++++++++
packages/svelte/package.json | 2 +-
packages/svelte/src/version.js | 2 +-
5 files changed, 10 insertions(+), 12 deletions(-)
delete mode 100644 .changeset/curvy-carrots-prove.md
delete mode 100644 .changeset/new-wolves-punch.md
diff --git a/.changeset/curvy-carrots-prove.md b/.changeset/curvy-carrots-prove.md
deleted file mode 100644
index 7723990179..0000000000
--- a/.changeset/curvy-carrots-prove.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: account for mounting when `select_option` in `attribute_effect`
diff --git a/.changeset/new-wolves-punch.md b/.changeset/new-wolves-punch.md
deleted file mode 100644
index c856038cbc..0000000000
--- a/.changeset/new-wolves-punch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: do not proxify the value assigned to a derived
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index ad72bfabb0..4f1be5e299 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,13 @@
# svelte
+## 5.35.3
+
+### Patch Changes
+
+- fix: account for mounting when `select_option` in `attribute_effect` ([#16309](https://github.com/sveltejs/svelte/pull/16309))
+
+- fix: do not proxify the value assigned to a derived ([#16302](https://github.com/sveltejs/svelte/pull/16302))
+
## 5.35.2
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index 872c21a179..30a8f8833a 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.35.2",
+ "version": "5.35.3",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 47c354c7a2..d98b622908 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.35.2';
+export const VERSION = '5.35.3';
export const PUBLIC_VERSION = '5';