diff --git a/.changeset/kind-elephants-behave.md b/.changeset/kind-elephants-behave.md
deleted file mode 100644
index f52dc1fd36..0000000000
--- a/.changeset/kind-elephants-behave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: ensure clearing of old values happens independent of root flushes
diff --git a/.changeset/nervous-kids-shake.md b/.changeset/nervous-kids-shake.md
new file mode 100644
index 0000000000..3fc6429797
--- /dev/null
+++ b/.changeset/nervous-kids-shake.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: set deriveds as `CLEAN` if they are assigned to
diff --git a/.changeset/stupid-vans-draw.md b/.changeset/stupid-vans-draw.md
new file mode 100644
index 0000000000..24892f1e8f
--- /dev/null
+++ b/.changeset/stupid-vans-draw.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: better scope `:global()` with nesting selector `&`
diff --git a/.github/workflows/pkg.pr.new.yml b/.github/workflows/pkg.pr.new.yml
index 90d219faae..b2b521dc6f 100644
--- a/.github/workflows/pkg.pr.new.yml
+++ b/.github/workflows/pkg.pr.new.yml
@@ -11,13 +11,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- - name: install corepack
- run: npm i -g corepack@0.31.0
-
- run: corepack enable
- uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 22.x
cache: pnpm
- name: Install dependencies
diff --git a/documentation/docs/02-runes/04-$effect.md b/documentation/docs/02-runes/04-$effect.md
index ae1a2146c9..46ea9b81e9 100644
--- a/documentation/docs/02-runes/04-$effect.md
+++ b/documentation/docs/02-runes/04-$effect.md
@@ -25,7 +25,7 @@ You can create an effect with the `$effect` rune ([demo](/playground/untitled#H4
});
-
+
```
When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes.
@@ -135,19 +135,33 @@ 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 `a` is `true` in the code snippet below, the code inside the `if` block will run and `b` will be evaluated. As such, changes to either `a` or `b` [will cause the effect to re-run](/playground/untitled#H4sIAAAAAAAAE3VQzWrDMAx-FdUU4kBp71li6EPstOxge0ox8-QQK2PD-N1nLy2F0Z2Evj9_chKkP1B04pnYscc3cRCT8xhF95IEf8-Vq0DBr8rzPB_jJ3qumNERH-E2ECNxiRF9tIubWY00lgcYNAywj6wZJS8rtk83wjwgCrXHaULLUrYwKEgVGrnkx-Dx6MNFNstK5OjSbFGbwE0gdXuT_zGYrjmAuco515Hr1p_uXak3K3MgCGS9s-9D2grU-judlQYXIencnzad-tdR79qZrMyvw9wd5Z8Yv1h09dz8mn8AkM7Pfo0BAAA=).
+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).
-Conversely, if `a` is `false`, `b` will not be evaluated, and the effect will _only_ re-run when `a` changes.
+Conversely, if `condition` is `false`, `color` will not be evaluated, and the effect will _only_ re-run again when `condition` changes.
```ts
-let a = false;
-let b = false;
+// @filename: ambient.d.ts
+declare module 'canvas-confetti' {
+ interface ConfettiOptions {
+ colors: string[];
+ }
+
+ function confetti(opts?: ConfettiOptions): void;
+ export default confetti;
+}
+
+// @filename: index.js
// ---cut---
-$effect(() => {
- console.log('running');
+import confetti from 'canvas-confetti';
- if (a) {
- console.log('b:', b);
+let condition = $state(true);
+let color = $state('#ff3e00');
+
+$effect(() => {
+ if (condition) {
+ confetti({ colors: [color] });
+ } else {
+ confetti();
}
});
```
@@ -211,20 +225,19 @@ It is used to implement abstractions like [`createSubscriber`](/docs/svelte/svel
The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for the creation of effects outside of the component initialisation phase.
-```svelte
-
+// later...
+destroy();
```
## When not to use `$effect`
diff --git a/documentation/docs/02-runes/08-$host.md b/documentation/docs/02-runes/08-$host.md
index 7b5e041e5e..ba6f0a5b5b 100644
--- a/documentation/docs/02-runes/08-$host.md
+++ b/documentation/docs/02-runes/08-$host.md
@@ -2,7 +2,7 @@
title: $host
---
-When compiling a component as a custom element, the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA)):
+When compiling a component as a [custom element](custom-elements), the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA)):
```svelte
diff --git a/documentation/docs/03-template-syntax/13-transition.md b/documentation/docs/03-template-syntax/13-transition.md
index 51c11e8b34..c51175c272 100644
--- a/documentation/docs/03-template-syntax/13-transition.md
+++ b/documentation/docs/03-template-syntax/13-transition.md
@@ -22,10 +22,6 @@ The `transition:` directive indicates a _bidirectional_ transition, which means
{/if}
```
-## Built-in transitions
-
-A selection of built-in transitions can be imported from the [`svelte/transition`](svelte-transition) module.
-
## Local vs global
Transitions are local by default. Local transitions only play when the block they belong to is created or destroyed, _not_ when parent blocks are created or destroyed.
@@ -40,6 +36,10 @@ Transitions are local by default. Local transitions only play when the block the
{/if}
```
+## Built-in transitions
+
+A selection of built-in transitions can be imported from the [`svelte/transition`](svelte-transition) module.
+
## Transition parameters
Transitions can have parameters.
diff --git a/documentation/docs/06-runtime/02-context.md b/documentation/docs/06-runtime/02-context.md
index b698323a04..4204bcfe6d 100644
--- a/documentation/docs/06-runtime/02-context.md
+++ b/documentation/docs/06-runtime/02-context.md
@@ -94,7 +94,7 @@ interface User {}
// ---cut---
import { getContext, setContext } from 'svelte';
-let key = {};
+const key = {};
/** @param {User} user */
export function setUserContext(user) {
diff --git a/documentation/docs/98-reference/.generated/client-warnings.md b/documentation/docs/98-reference/.generated/client-warnings.md
index 284e9a7c3e..77d1df4cdd 100644
--- a/documentation/docs/98-reference/.generated/client-warnings.md
+++ b/documentation/docs/98-reference/.generated/client-warnings.md
@@ -161,7 +161,7 @@ Tried to unmount a component that was not mounted
### ownership_invalid_binding
```
-%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
+%parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
```
Consider three components `GrandParent`, `Parent` and `Child`. If you do ``, inside `GrandParent` pass on the variable via `` (note the missing `bind:`) and then do `` inside `Parent`, this warning is thrown.
@@ -171,11 +171,7 @@ To fix it, `bind:` to the value instead of just passing a property (i.e. in this
### ownership_invalid_mutation
```
-Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
-```
-
-```
-%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
+Mutating unbound props (`%name%`, at %location%) is strongly discouraged. Consider using `bind:%prop%={...}` in %parent% (or using a callback) instead
```
Consider the following code:
diff --git a/package.json b/package.json
index ad69bfc9ca..70e85438f0 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"private": true,
"type": "module",
"license": "MIT",
- "packageManager": "pnpm@9.4.0",
+ "packageManager": "pnpm@10.4.0",
"engines": {
"pnpm": ">=9.0.0"
},
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index 15dc5e2234..eb76e9a9e9 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,25 @@
# svelte
+## 5.25.9
+
+### Patch Changes
+
+- fix: allow `$.state` and `$.derived` to be treeshaken ([#15702](https://github.com/sveltejs/svelte/pull/15702))
+
+- fix: rework binding ownership validation ([#15678](https://github.com/sveltejs/svelte/pull/15678))
+
+## 5.25.8
+
+### Patch Changes
+
+- fix: address untracked_writes memory leak ([#15694](https://github.com/sveltejs/svelte/pull/15694))
+
+## 5.25.7
+
+### Patch Changes
+
+- fix: ensure clearing of old values happens independent of root flushes ([#15664](https://github.com/sveltejs/svelte/pull/15664))
+
## 5.25.6
### Patch Changes
diff --git a/packages/svelte/messages/client-warnings/warnings.md b/packages/svelte/messages/client-warnings/warnings.md
index 943cf6f01f..f8e9ebd8a0 100644
--- a/packages/svelte/messages/client-warnings/warnings.md
+++ b/packages/svelte/messages/client-warnings/warnings.md
@@ -132,7 +132,7 @@ During development, this error is often preceeded by a `console.error` detailing
## ownership_invalid_binding
-> %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
+> %parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
Consider three components `GrandParent`, `Parent` and `Child`. If you do ``, inside `GrandParent` pass on the variable via `` (note the missing `bind:`) and then do `` inside `Parent`, this warning is thrown.
@@ -140,9 +140,7 @@ To fix it, `bind:` to the value instead of just passing a property (i.e. in this
## ownership_invalid_mutation
-> Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
-
-> %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
+> Mutating unbound props (`%name%`, at %location%) is strongly discouraged. Consider using `bind:%prop%={...}` in %parent% (or using a callback) instead
Consider the following code:
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index eeb2211151..3fb843b3a2 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.25.6",
+ "version": "5.25.9",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js
index 0646c6341a..fbe6ca1cd3 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js
@@ -1,6 +1,11 @@
/** @import * as Compiler from '#compiler' */
import { walk } from 'zimmerframe';
-import { get_parent_rules, get_possible_values, is_outer_global } from './utils.js';
+import {
+ get_parent_rules,
+ get_possible_values,
+ is_outer_global,
+ is_unscoped_pseudo_class
+} from './utils.js';
import { regex_ends_with_whitespace, regex_starts_with_whitespace } from '../../patterns.js';
import { get_attribute_chunks, is_text_attribute } from '../../../utils/ast.js';
@@ -286,20 +291,26 @@ function apply_combinator(relative_selector, rest_selectors, rule, node, directi
* a global selector
* @param {Compiler.AST.CSS.RelativeSelector} selector
* @param {Compiler.AST.CSS.Rule} rule
+ * @returns {boolean}
*/
function is_global(selector, rule) {
if (selector.metadata.is_global || selector.metadata.is_global_like) {
return true;
}
+ let explicitly_global = false;
+
for (const s of selector.selectors) {
/** @type {Compiler.AST.CSS.SelectorList | null} */
let selector_list = null;
+ let can_be_global = false;
let owner = rule;
if (s.type === 'PseudoClassSelector') {
if ((s.name === 'is' || s.name === 'where') && s.args) {
selector_list = s.args;
+ } else {
+ can_be_global = is_unscoped_pseudo_class(s);
}
}
@@ -308,18 +319,19 @@ function is_global(selector, rule) {
selector_list = owner.prelude;
}
- const has_global_selectors = selector_list?.children.some((complex_selector) => {
+ const has_global_selectors = !!selector_list?.children.some((complex_selector) => {
return complex_selector.children.every((relative_selector) =>
is_global(relative_selector, owner)
);
});
+ explicitly_global ||= has_global_selectors;
- if (!has_global_selectors) {
+ if (!has_global_selectors && !can_be_global) {
return false;
}
}
- return true;
+ return explicitly_global || selector.selectors.length === 0;
}
const regex_backslash_and_following_character = /\\(.)/g;
diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js
index 1f636c32df..c62fb03e8f 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/index.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/index.js
@@ -432,6 +432,7 @@ export function analyze_component(root, source, options) {
uses_component_bindings: false,
uses_render_tags: false,
needs_context: false,
+ needs_mutation_validation: false,
needs_props: false,
event_directive_node: null,
uses_event_attributes: false,
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
index 0bdfbae746..38fcee8d6f 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
@@ -393,6 +393,12 @@ export function client_component(analysis, options) {
);
}
+ if (analysis.needs_mutation_validation) {
+ component_block.body.unshift(
+ b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props')))
+ );
+ }
+
const should_inject_context =
dev ||
analysis.needs_context ||
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js
index 28e3fabb19..a37ecd31cc 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js
@@ -1,10 +1,10 @@
-/** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, Pattern, PrivateIdentifier, Statement } from 'estree' */
-/** @import { AST, Binding } from '#compiler' */
+/** @import { ArrowFunctionExpression, AssignmentExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, Node, Pattern, UpdateExpression } from 'estree' */
+/** @import { Binding } from '#compiler' */
/** @import { ClientTransformState, ComponentClientTransformState, ComponentContext } from './types.js' */
/** @import { Analysis } from '../../types.js' */
/** @import { Scope } from '../../scope.js' */
import * as b from '../../../utils/builders.js';
-import { extract_identifiers, is_simple_expression } from '../../../utils/ast.js';
+import { is_simple_expression } from '../../../utils/ast.js';
import {
PROPS_IS_LAZY_INITIAL,
PROPS_IS_IMMUTABLE,
@@ -13,7 +13,8 @@ import {
PROPS_IS_BINDABLE
} from '../../../../constants.js';
import { dev } from '../../../state.js';
-import { get_value } from './visitors/shared/declarations.js';
+import { walk } from 'zimmerframe';
+import { validate_mutation } from './visitors/shared/utils.js';
/**
* @param {Binding} binding
@@ -110,6 +111,30 @@ function get_hoisted_params(node, context) {
}
}
}
+
+ if (dev) {
+ // this is a little hacky, but necessary for ownership validation
+ // to work inside hoisted event handlers
+
+ /**
+ * @param {AssignmentExpression | UpdateExpression} node
+ * @param {{ next: () => void, stop: () => void }} context
+ */
+ function visit(node, { next, stop }) {
+ if (validate_mutation(node, /** @type {any} */ (context), node) !== node) {
+ params.push(b.id('$$ownership_validator'));
+ stop();
+ } else {
+ next();
+ }
+ }
+
+ walk(/** @type {Node} */ (node), null, {
+ AssignmentExpression: visit,
+ UpdateExpression: visit
+ });
+ }
+
return params;
}
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 850cd83b15..4baa1c8e6c 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
@@ -7,9 +7,10 @@ import {
get_attribute_expression,
is_event_attribute
} from '../../../../utils/ast.js';
-import { dev, is_ignored, locate_node } from '../../../../state.js';
+import { dev, locate_node } from '../../../../state.js';
import { should_proxy } from '../utils.js';
import { visit_assignment_expression } from '../../shared/assignments.js';
+import { validate_mutation } from './shared/utils.js';
/**
* @param {AssignmentExpression} node
@@ -20,9 +21,7 @@ export function AssignmentExpression(node, context) {
visit_assignment_expression(node, context, build_assignment) ?? context.next()
);
- return is_ignored(node, 'ownership_invalid_mutation')
- ? b.call('$.skip_ownership_validation', b.thunk(expression))
- : expression;
+ return validate_mutation(node, context, expression);
}
/**
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js
index 24c20d7f94..efc3c95c3c 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js
@@ -161,33 +161,6 @@ export function ClassBody(node, context) {
body.push(/** @type {MethodDefinition} **/ (context.visit(definition, child_state)));
}
- if (dev && public_state.size > 0) {
- // add an `[$.ADD_OWNER]` method so that a class with state fields can widen ownership
- body.push(
- b.method(
- 'method',
- b.id('$.ADD_OWNER'),
- [b.id('owner')],
- [
- b.stmt(
- b.call(
- '$.add_owner_to_class',
- b.this,
- b.id('owner'),
- b.array(
- Array.from(public_state).map(([name]) =>
- b.thunk(b.call('$.get', b.member(b.this, b.private_id(name))))
- )
- ),
- is_ignored(node, 'ownership_invalid_binding') && b.true
- )
- )
- ],
- true
- )
- );
- }
-
return { ...node, body };
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js
index 13c1b4bc51..63c03b0eb6 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js
@@ -1,8 +1,8 @@
/** @import { AssignmentExpression, Expression, UpdateExpression } from 'estree' */
/** @import { Context } from '../types' */
-import { is_ignored } from '../../../../state.js';
import { object } from '../../../../utils/ast.js';
import * as b from '../../../../utils/builders.js';
+import { validate_mutation } from './shared/utils.js';
/**
* @param {UpdateExpression} node
@@ -51,7 +51,5 @@ export function UpdateExpression(node, context) {
);
}
- return is_ignored(node, 'ownership_invalid_mutation')
- ? b.call('$.skip_ownership_validation', b.thunk(update))
- : update;
+ return validate_mutation(node, context, update);
}
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 2bae4486dc..2ea68e206e 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
@@ -179,19 +179,29 @@ export function build_component(node, component_name, context, anchor = context.
} else if (attribute.type === 'BindDirective') {
const expression = /** @type {Expression} */ (context.visit(attribute.expression));
- if (dev && attribute.name !== 'this') {
- binding_initializers.push(
- b.stmt(
- b.call(
- b.id('$.add_owner_effect'),
- expression.type === 'SequenceExpression'
- ? expression.expressions[0]
- : b.thunk(expression),
- b.id(component_name),
- is_ignored(node, 'ownership_invalid_binding') && b.true
+ if (
+ dev &&
+ attribute.name !== 'this' &&
+ !is_ignored(node, 'ownership_invalid_binding') &&
+ // bind:x={() => x.y, y => x.y = y} will be handled by the assignment expression binding validation
+ attribute.expression.type !== 'SequenceExpression'
+ ) {
+ const left = object(attribute.expression);
+ const binding = left && context.state.scope.get(left.name);
+
+ if (binding?.kind === 'bindable_prop' || binding?.kind === 'prop') {
+ context.state.analysis.needs_mutation_validation = true;
+ binding_initializers.push(
+ b.stmt(
+ b.call(
+ '$$ownership_validator.binding',
+ b.literal(binding.node.name),
+ b.id(component_name),
+ b.thunk(expression)
+ )
)
- )
- );
+ );
+ }
}
if (expression.type === 'SequenceExpression') {
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 df6308d631..af6e56f70c 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,13 +1,13 @@
-/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Statement, Super } from 'estree' */
+/** @import { AssignmentExpression, Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Literal, Super, UpdateExpression } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
-/** @import { ComponentClientTransformState } from '../../types' */
+/** @import { ComponentClientTransformState, Context } from '../../types' */
import { walk } from 'zimmerframe';
import { object } from '../../../../../utils/ast.js';
import * as b from '../../../../../utils/builders.js';
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 { locator } from '../../../../../state.js';
+import { dev, is_ignored, locator } from '../../../../../state.js';
import { create_derived } from '../../utils.js';
/**
@@ -295,3 +295,60 @@ export function validate_binding(state, binding, expression) {
)
);
}
+
+/**
+ * In dev mode validate mutations to props
+ * @param {AssignmentExpression | UpdateExpression} node
+ * @param {Context} context
+ * @param {Expression} expression
+ */
+export function validate_mutation(node, context, expression) {
+ let left = /** @type {Expression | Super} */ (
+ node.type === 'AssignmentExpression' ? node.left : node.argument
+ );
+
+ if (!dev || left.type !== 'MemberExpression' || is_ignored(node, 'ownership_invalid_mutation')) {
+ return expression;
+ }
+
+ const name = object(left);
+ if (!name) return expression;
+
+ const binding = context.state.scope.get(name.name);
+ if (binding?.kind !== 'prop' && binding?.kind !== 'bindable_prop') return expression;
+
+ const state = /** @type {ComponentClientTransformState} */ (context.state);
+ state.analysis.needs_mutation_validation = true;
+
+ /** @type {Array} */
+ const path = [];
+
+ while (left.type === 'MemberExpression') {
+ if (left.property.type === 'Literal') {
+ path.unshift(left.property);
+ } else if (left.property.type === 'Identifier') {
+ if (left.computed) {
+ path.unshift(left.property);
+ } else {
+ path.unshift(b.literal(left.property.name));
+ }
+ } else {
+ return expression;
+ }
+
+ left = left.object;
+ }
+
+ path.unshift(b.literal(name.name));
+
+ const loc = locator(/** @type {number} */ (left.start));
+
+ return b.call(
+ '$$ownership_validator.mutation',
+ b.literal(binding.prop_alias),
+ b.array(path),
+ expression,
+ loc && b.literal(loc.line),
+ loc && b.literal(loc.column)
+ );
+}
diff --git a/packages/svelte/src/compiler/phases/types.d.ts b/packages/svelte/src/compiler/phases/types.d.ts
index abe2b115de..f09b881303 100644
--- a/packages/svelte/src/compiler/phases/types.d.ts
+++ b/packages/svelte/src/compiler/phases/types.d.ts
@@ -53,6 +53,7 @@ export interface ComponentAnalysis extends Analysis {
uses_component_bindings: boolean;
uses_render_tags: boolean;
needs_context: boolean;
+ needs_mutation_validation: boolean;
needs_props: boolean;
/** Set to the first event directive (on:x) found on a DOM element in the code */
event_directive_node: AST.OnDirective | null;
diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js
index 21377c1cc8..7e5196c606 100644
--- a/packages/svelte/src/internal/client/constants.js
+++ b/packages/svelte/src/internal/client/constants.js
@@ -23,6 +23,5 @@ export const EFFECT_HAS_DERIVED = 1 << 20;
export const EFFECT_IS_UPDATING = 1 << 21;
export const STATE_SYMBOL = Symbol('$state');
-export const STATE_SYMBOL_METADATA = Symbol('$state metadata');
export const LEGACY_PROPS = Symbol('legacy props');
export const LOADING_ATTR_SYMBOL = Symbol('');
diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js
index bfca9d5e6a..7a2fdd0edb 100644
--- a/packages/svelte/src/internal/client/context.js
+++ b/packages/svelte/src/internal/client/context.js
@@ -1,7 +1,6 @@
/** @import { ComponentContext } from '#client' */
import { DEV } from 'esm-env';
-import { add_owner } from './dev/ownership.js';
import { lifecycle_outside_component } from '../shared/errors.js';
import { source } from './reactivity/sources.js';
import {
@@ -67,15 +66,6 @@ export function getContext(key) {
*/
export function setContext(key, context) {
const context_map = get_or_init_context_map('setContext');
-
- if (DEV) {
- // When state is put into context, we treat as if it's global from now on.
- // We do for performance reasons (it's for example very expensive to call
- // getContext on a big object many times when part of a list component)
- // and danger of false positives.
- untrack(() => add_owner(context, null, true));
- }
-
context_map.set(key, context);
return context;
}
diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js
index 62119b36db..6c40a744df 100644
--- a/packages/svelte/src/internal/client/dev/ownership.js
+++ b/packages/svelte/src/internal/client/dev/ownership.js
@@ -1,12 +1,11 @@
-/** @import { ProxyMetadata } from '#client' */
/** @typedef {{ file: string, line: number, column: number }} Location */
-import { STATE_SYMBOL_METADATA } from '../constants.js';
-import { render_effect, user_pre_effect } from '../reactivity/effects.js';
-import { dev_current_component_function } from '../context.js';
-import { get_prototype_of } from '../../shared/utils.js';
+import { get_descriptor } from '../../shared/utils.js';
+import { LEGACY_PROPS, STATE_SYMBOL } from '../constants.js';
+import { FILENAME } from '../../../constants.js';
+import { component_context } from '../context.js';
import * as w from '../warnings.js';
-import { FILENAME, UNINITIALIZED } from '../../../constants.js';
+import { sanitize_location } from '../../../utils.js';
/** @type {Record>} */
const boundaries = {};
@@ -71,8 +70,6 @@ export function get_component() {
return null;
}
-export const ADD_OWNER = Symbol('ADD_OWNER');
-
/**
* Together with `mark_module_end`, this function establishes the boundaries of a `.svelte` file,
* such that subsequent calls to `get_component` can tell us which component is responsible
@@ -108,197 +105,69 @@ export function mark_module_end(component) {
}
/**
- * @param {any} object
- * @param {any | null} owner
- * @param {boolean} [global]
- * @param {boolean} [skip_warning]
+ * Sets up a validator that
+ * - traverses the path of a prop to find out if it is allowed to be mutated
+ * - checks that the binding chain is not interrupted
+ * @param {Record} props
*/
-export function add_owner(object, owner, global = false, skip_warning = false) {
- if (object && !global) {
- const component = dev_current_component_function;
- const metadata = object[STATE_SYMBOL_METADATA];
- if (metadata && !has_owner(metadata, component)) {
- let original = get_owner(metadata);
-
- if (owner && owner[FILENAME] !== component[FILENAME] && !skip_warning) {
- w.ownership_invalid_binding(component[FILENAME], owner[FILENAME], original[FILENAME]);
+export function create_ownership_validator(props) {
+ const component = component_context?.function;
+ const parent = component_context?.p?.function;
+
+ return {
+ /**
+ * @param {string} prop
+ * @param {any[]} path
+ * @param {any} result
+ * @param {number} line
+ * @param {number} column
+ */
+ mutation: (prop, path, result, line, column) => {
+ const name = path[0];
+ if (is_bound(props, name) || !parent) {
+ return result;
}
- }
- }
- add_owner_to_object(object, owner, new Set());
-}
-
-/**
- * @param {() => unknown} get_object
- * @param {any} Component
- * @param {boolean} [skip_warning]
- */
-export function add_owner_effect(get_object, Component, skip_warning = false) {
- user_pre_effect(() => {
- add_owner(get_object(), Component, false, skip_warning);
- });
-}
-
-/**
- * @param {any} _this
- * @param {Function} owner
- * @param {Array<() => any>} getters
- * @param {boolean} skip_warning
- */
-export function add_owner_to_class(_this, owner, getters, skip_warning) {
- _this[ADD_OWNER].current ||= getters.map(() => UNINITIALIZED);
-
- for (let i = 0; i < getters.length; i += 1) {
- const current = getters[i]();
- // For performance reasons we only re-add the owner if the state has changed
- if (current !== _this[ADD_OWNER][i]) {
- _this[ADD_OWNER].current[i] = current;
- add_owner(current, owner, false, skip_warning);
- }
- }
-}
-
-/**
- * @param {ProxyMetadata | null} from
- * @param {ProxyMetadata} to
- */
-export function widen_ownership(from, to) {
- if (to.owners === null) {
- return;
- }
-
- while (from) {
- if (from.owners === null) {
- to.owners = null;
- break;
- }
-
- for (const owner of from.owners) {
- to.owners.add(owner);
- }
-
- from = from.parent;
- }
-}
-
-/**
- * @param {any} object
- * @param {Function | null} owner If `null`, then the object is globally owned and will not be checked
- * @param {Set} seen
- */
-function add_owner_to_object(object, owner, seen) {
- const metadata = /** @type {ProxyMetadata} */ (object?.[STATE_SYMBOL_METADATA]);
+ let value = props[name];
- if (metadata) {
- // this is a state proxy, add owner directly, if not globally shared
- if ('owners' in metadata && metadata.owners != null) {
- if (owner) {
- metadata.owners.add(owner);
- } else {
- metadata.owners = null;
+ for (let i = 1; i < path.length - 1; i++) {
+ if (!value?.[STATE_SYMBOL]) {
+ return result;
+ }
+ value = value[path[i]];
}
- }
- } else if (object && typeof object === 'object') {
- if (seen.has(object)) return;
- seen.add(object);
- if (ADD_OWNER in object && object[ADD_OWNER]) {
- // this is a class with state fields. we put this in a render effect
- // so that if state is replaced (e.g. `instance.name = { first, last }`)
- // the new state is also co-owned by the caller of `getContext`
- render_effect(() => {
- object[ADD_OWNER](owner);
- });
- } else {
- var proto = get_prototype_of(object);
- if (proto === Object.prototype) {
- // recurse until we find a state proxy
- for (const key in object) {
- if (Object.getOwnPropertyDescriptor(object, key)?.get) {
- // Similar to the class case; the getter could update with a new state
- let current = UNINITIALIZED;
- render_effect(() => {
- const next = object[key];
- if (current !== next) {
- current = next;
- add_owner_to_object(next, owner, seen);
- }
- });
- } else {
- add_owner_to_object(object[key], owner, seen);
- }
- }
- } else if (proto === Array.prototype) {
- // recurse until we find a state proxy
- for (let i = 0; i < object.length; i += 1) {
- add_owner_to_object(object[i], owner, seen);
- }
+ const location = sanitize_location(`${component[FILENAME]}:${line}:${column}`);
+
+ w.ownership_invalid_mutation(name, location, prop, parent[FILENAME]);
+
+ return result;
+ },
+ /**
+ * @param {any} key
+ * @param {any} child_component
+ * @param {() => any} value
+ */
+ binding: (key, child_component, value) => {
+ if (!is_bound(props, key) && parent && value()?.[STATE_SYMBOL]) {
+ w.ownership_invalid_binding(
+ component[FILENAME],
+ key,
+ child_component[FILENAME],
+ parent[FILENAME]
+ );
}
}
- }
+ };
}
/**
- * @param {ProxyMetadata} metadata
- * @param {Function} component
- * @returns {boolean}
+ * @param {Record} props
+ * @param {string} prop_name
*/
-function has_owner(metadata, component) {
- if (metadata.owners === null) {
- return true;
- }
-
- return (
- metadata.owners.has(component) ||
- // This helps avoid false positives when using HMR, where the component function is replaced
- (FILENAME in component &&
- [...metadata.owners].some(
- (owner) => /** @type {any} */ (owner)[FILENAME] === component[FILENAME]
- )) ||
- (metadata.parent !== null && has_owner(metadata.parent, component))
- );
-}
-
-/**
- * @param {ProxyMetadata} metadata
- * @returns {any}
- */
-function get_owner(metadata) {
- return (
- metadata?.owners?.values().next().value ??
- get_owner(/** @type {ProxyMetadata} */ (metadata.parent))
- );
-}
-
-let skip = false;
-
-/**
- * @param {() => any} fn
- */
-export function skip_ownership_validation(fn) {
- skip = true;
- fn();
- skip = false;
-}
-
-/**
- * @param {ProxyMetadata} metadata
- */
-export function check_ownership(metadata) {
- if (skip) return;
-
- const component = get_component();
-
- if (component && !has_owner(metadata, component)) {
- let original = get_owner(metadata);
-
- // @ts-expect-error
- if (original[FILENAME] !== component[FILENAME]) {
- // @ts-expect-error
- w.ownership_invalid_mutation(component[FILENAME], original[FILENAME]);
- } else {
- w.ownership_invalid_mutation();
- }
- }
+function is_bound(props, prop_name) {
+ // Can be the case when someone does `mount(Component, props)` with `let props = $state({...})`
+ // or `createClassComponent(Component, props)`
+ const is_entry_props = STATE_SYMBOL in props || LEGACY_PROPS in props;
+ return !!get_descriptor(props, prop_name)?.set || (is_entry_props && prop_name in props);
}
diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js
index 5e72a46554..eaab1a3bea 100644
--- a/packages/svelte/src/internal/client/index.js
+++ b/packages/svelte/src/internal/client/index.js
@@ -4,15 +4,7 @@ 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';
export { hmr } from './dev/hmr.js';
-export {
- ADD_OWNER,
- add_owner,
- mark_module_start,
- mark_module_end,
- add_owner_effect,
- add_owner_to_class,
- skip_ownership_validation
-} from './dev/ownership.js';
+export { mark_module_start, mark_module_end, create_ownership_validator } from './dev/ownership.js';
export { check_target, legacy_api } from './dev/legacy.js';
export { trace } from './dev/tracing.js';
export { inspect } from './dev/inspect.js';
diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js
index fab271c916..5e0aa3dbc3 100644
--- a/packages/svelte/src/internal/client/proxy.js
+++ b/packages/svelte/src/internal/client/proxy.js
@@ -1,7 +1,6 @@
-/** @import { ProxyMetadata, Source } from '#client' */
+/** @import { Source } from '#client' */
import { DEV } from 'esm-env';
import { get, active_effect, active_reaction, set_active_reaction } from './runtime.js';
-import { component_context } from './context.js';
import {
array_prototype,
get_descriptor,
@@ -9,24 +8,19 @@ import {
is_array,
object_prototype
} from '../shared/utils.js';
-import { check_ownership, widen_ownership } from './dev/ownership.js';
import { state as source, set } from './reactivity/sources.js';
-import { STATE_SYMBOL, STATE_SYMBOL_METADATA } from './constants.js';
+import { STATE_SYMBOL } from './constants.js';
import { UNINITIALIZED } from '../../constants.js';
import * as e from './errors.js';
import { get_stack } from './dev/tracing.js';
import { tracing_mode_flag } from '../flags/index.js';
-/** @type {ProxyMetadata | null} */
-var parent_metadata = null;
-
/**
* @template T
* @param {T} value
- * @param {Source} [prev] dev mode only
* @returns {T}
*/
-export function proxy(value, prev) {
+export function proxy(value) {
// if non-proxyable, or is already a proxy, return `value`
if (typeof value !== 'object' || value === null || STATE_SYMBOL in value) {
return value;
@@ -55,16 +49,7 @@ export function proxy(value, prev) {
set_active_reaction(reaction);
/** @type {T} */
- var result;
-
- if (DEV) {
- var previous_metadata = parent_metadata;
- parent_metadata = metadata;
- result = fn();
- parent_metadata = previous_metadata;
- } else {
- result = fn();
- }
+ var result = fn();
set_active_reaction(previous_reaction);
return result;
@@ -76,31 +61,6 @@ export function proxy(value, prev) {
sources.set('length', source(/** @type {any[]} */ (value).length, stack));
}
- /** @type {ProxyMetadata} */
- var metadata;
-
- if (DEV) {
- metadata = {
- parent: parent_metadata,
- owners: null
- };
-
- if (prev) {
- // Reuse owners from previous state; necessary because reassignment is not guaranteed to have correct component context.
- // If no previous proxy exists we play it safe and assume ownerless state
- // @ts-expect-error
- const prev_owners = prev.v?.[STATE_SYMBOL_METADATA]?.owners;
- metadata.owners = prev_owners ? new Set(prev_owners) : null;
- } else {
- metadata.owners =
- parent_metadata === null
- ? component_context !== null
- ? new Set([component_context.function])
- : null
- : new Set();
- }
- }
-
return new Proxy(/** @type {any} */ (value), {
defineProperty(_, prop, descriptor) {
if (
@@ -160,10 +120,6 @@ export function proxy(value, prev) {
},
get(target, prop, receiver) {
- if (DEV && prop === STATE_SYMBOL_METADATA) {
- return metadata;
- }
-
if (prop === STATE_SYMBOL) {
return value;
}
@@ -179,22 +135,6 @@ export function proxy(value, prev) {
if (s !== undefined) {
var v = get(s);
-
- // In case of something like `foo = bar.map(...)`, foo would have ownership
- // of the array itself, while the individual items would have ownership
- // of the component that created bar. That means if we later do `foo[0].baz = 42`,
- // we could get a false-positive ownership violation, since the two proxies
- // are not connected to each other via the parent metadata relationship.
- // For this reason, we need to widen the ownership of the children
- // upon access when we detect they are not connected.
- if (DEV) {
- /** @type {ProxyMetadata | undefined} */
- var prop_metadata = v?.[STATE_SYMBOL_METADATA];
- if (prop_metadata && prop_metadata?.parent !== metadata) {
- widen_ownership(metadata, prop_metadata);
- }
- }
-
return v === UNINITIALIZED ? undefined : v;
}
@@ -225,10 +165,6 @@ export function proxy(value, prev) {
},
has(target, prop) {
- if (DEV && prop === STATE_SYMBOL_METADATA) {
- return true;
- }
-
if (prop === STATE_SYMBOL) {
return true;
}
@@ -295,15 +231,6 @@ export function proxy(value, prev) {
);
}
- if (DEV) {
- /** @type {ProxyMetadata | undefined} */
- var prop_metadata = value?.[STATE_SYMBOL_METADATA];
- if (prop_metadata && prop_metadata?.parent !== metadata) {
- widen_ownership(metadata, prop_metadata);
- }
- check_ownership(metadata);
- }
-
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
// Set the new value before updating any signals so that any listeners get the new value
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
index cd7bbba02f..c9a8f7674a 100644
--- a/packages/svelte/src/internal/client/reactivity/deriveds.js
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -67,6 +67,7 @@ export function derived(fn) {
* @param {() => V} fn
* @returns {Derived}
*/
+/*#__NO_SIDE_EFFECTS__*/
export function user_derived(fn) {
const d = derived(fn);
@@ -130,7 +131,7 @@ function get_derived_parent_effect(derived) {
* @param {Derived} derived
* @returns {T}
*/
-function execute_derived(derived) {
+export function execute_derived(derived) {
var value;
var prev_active_effect = active_effect;
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index 3bb8a2e4cf..7724edad68 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -28,14 +28,14 @@ import {
UNOWNED,
MAYBE_DIRTY,
BLOCK_EFFECT,
- ROOT_EFFECT,
- EFFECT_IS_UPDATING
+ ROOT_EFFECT
} from '../constants.js';
import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack } from '../dev/tracing.js';
import { component_context, is_runes } from '../context.js';
import { proxy } from '../proxy.js';
+import { execute_derived } from './deriveds.js';
export let inspect_effects = new Set();
export const old_values = new Map();
@@ -78,6 +78,7 @@ export function source(v, stack) {
* @param {V} v
* @param {Error | null} [stack]
*/
+/*#__NO_SIDE_EFFECTS__*/
export function state(v, stack) {
const s = source(v, stack);
@@ -139,7 +140,7 @@ export function set(source, value, should_proxy = false) {
e.state_unsafe_mutation();
}
- let new_value = should_proxy ? proxy(value, source) : value;
+ let new_value = should_proxy ? proxy(value) : value;
return internal_set(source, new_value);
}
@@ -171,6 +172,14 @@ export function internal_set(source, value) {
}
}
+ if ((source.f & DERIVED) !== 0) {
+ // if we are assigning to a dirty derived we set it to clean/maybe dirty but we also eagerly execute it to track the dependencies
+ if ((source.f & DIRTY) !== 0) {
+ execute_derived(/** @type {Derived} */ (source));
+ }
+ set_signal_status(source, (source.f & UNOWNED) === 0 ? CLEAN : MAYBE_DIRTY);
+ }
+
mark_reactions(source, DIRTY);
// It's possible that the current reaction might not have up-to-date dependencies
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index a69181da98..a7662be617 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -27,7 +27,7 @@ import {
} from './constants.js';
import { flush_tasks } from './dom/task.js';
import { internal_set, old_values } from './reactivity/sources.js';
-import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js';
+import { destroy_derived_effects, execute_derived, update_derived } from './reactivity/deriveds.js';
import * as e from './errors.js';
import { FILENAME } from '../../constants.js';
import { tracing_mode_flag } from '../flags/index.js';
@@ -476,7 +476,7 @@ export function update_reaction(reaction) {
// we need to increment the read version to ensure that
// any dependencies in this reaction aren't marked with
// the same version
- if (previous_reaction !== null) {
+ if (previous_reaction !== reaction) {
read_version++;
if (untracked_writes !== null) {
diff --git a/packages/svelte/src/internal/client/types.d.ts b/packages/svelte/src/internal/client/types.d.ts
index 0c260a0a9f..b46bdf2013 100644
--- a/packages/svelte/src/internal/client/types.d.ts
+++ b/packages/svelte/src/internal/client/types.d.ts
@@ -179,14 +179,6 @@ export type TaskCallback = (now: number) => boolean | void;
export type TaskEntry = { c: TaskCallback; f: () => void };
-/** Dev-only */
-export interface ProxyMetadata {
- /** The components that 'own' this state, if any. `null` means no owners, i.e. everyone can mutate this state. */
- owners: null | Set;
- /** The parent metadata object */
- parent: null | ProxyMetadata;
-}
-
export type ProxyStateObject> = T & {
[STATE_SYMBOL]: T;
};
diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js
index 250c6eca2f..c84b487e28 100644
--- a/packages/svelte/src/internal/client/warnings.js
+++ b/packages/svelte/src/internal/client/warnings.js
@@ -129,27 +129,30 @@ export function lifecycle_double_unmount() {
}
/**
- * %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
+ * %parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
* @param {string} parent
+ * @param {string} prop
* @param {string} child
* @param {string} owner
*/
-export function ownership_invalid_binding(parent, child, owner) {
+export function ownership_invalid_binding(parent, prop, child, owner) {
if (DEV) {
- console.warn(`%c[svelte] ownership_invalid_binding\n%c${parent} passed a value to ${child} with \`bind:\`, but the value is owned by ${owner}. Consider creating a binding between ${owner} and ${parent}\nhttps://svelte.dev/e/ownership_invalid_binding`, bold, normal);
+ console.warn(`%c[svelte] ownership_invalid_binding\n%c${parent} passed property \`${prop}\` to ${child} with \`bind:\`, but its parent component ${owner} did not declare \`${prop}\` as a binding. Consider creating a binding between ${owner} and ${parent} (e.g. \`bind:${prop}={...}\` instead of \`${prop}={...}\`)\nhttps://svelte.dev/e/ownership_invalid_binding`, bold, normal);
} else {
console.warn(`https://svelte.dev/e/ownership_invalid_binding`);
}
}
/**
- * %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
- * @param {string | undefined | null} [component]
- * @param {string | undefined | null} [owner]
+ * Mutating unbound props (`%name%`, at %location%) is strongly discouraged. Consider using `bind:%prop%={...}` in %parent% (or using a callback) instead
+ * @param {string} name
+ * @param {string} location
+ * @param {string} prop
+ * @param {string} parent
*/
-export function ownership_invalid_mutation(component, owner) {
+export function ownership_invalid_mutation(name, location, prop, parent) {
if (DEV) {
- console.warn(`%c[svelte] ownership_invalid_mutation\n%c${component ? `${component} mutated a value owned by ${owner}. This is strongly discouraged. Consider passing values to child components with \`bind:\`, or use a callback instead` : 'Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead'}\nhttps://svelte.dev/e/ownership_invalid_mutation`, bold, normal);
+ console.warn(`%c[svelte] ownership_invalid_mutation\n%cMutating unbound props (\`${name}\`, at ${location}) is strongly discouraged. Consider using \`bind:${prop}={...}\` in ${parent} (or using a callback) instead\nhttps://svelte.dev/e/ownership_invalid_mutation`, bold, normal);
} else {
console.warn(`https://svelte.dev/e/ownership_invalid_mutation`);
}
diff --git a/packages/svelte/src/utils.js b/packages/svelte/src/utils.js
index 9c64fe0fad..b9c1229159 100644
--- a/packages/svelte/src/utils.js
+++ b/packages/svelte/src/utils.js
@@ -466,8 +466,10 @@ export function is_raw_text_element(name) {
/**
* Prevent devtools trying to make `location` a clickable link by inserting a zero-width space
- * @param {string | undefined} location
+ * @template {string | undefined} T
+ * @param {T} location
+ * @returns {T};
*/
export function sanitize_location(location) {
- return location?.replace(/\//g, '/\u200b');
+ return /** @type {T} */ (location?.replace(/\//g, '/\u200b'));
}
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 8bcf91ce39..13a69857a7 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.25.6';
+export const VERSION = '5.25.9';
export const PUBLIC_VERSION = '5';
diff --git a/packages/svelte/tests/css/samples/global-with-nesting/expected.css b/packages/svelte/tests/css/samples/global-with-nesting/expected.css
index dcb8a0e481..1863c57d85 100644
--- a/packages/svelte/tests/css/samples/global-with-nesting/expected.css
+++ b/packages/svelte/tests/css/samples/global-with-nesting/expected.css
@@ -1,5 +1,10 @@
div.svelte-xyz {
&.class{
- color: red;
+ color: green;
+ }
+ }
+ * {
+ &:hover .class.svelte-xyz {
+ color: green;
}
}
\ No newline at end of file
diff --git a/packages/svelte/tests/css/samples/global-with-nesting/input.svelte b/packages/svelte/tests/css/samples/global-with-nesting/input.svelte
index 0c73ed7a78..2c1d2b5ebd 100644
--- a/packages/svelte/tests/css/samples/global-with-nesting/input.svelte
+++ b/packages/svelte/tests/css/samples/global-with-nesting/input.svelte
@@ -1,7 +1,12 @@
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-discouraged/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-discouraged/_config.js
index 62c6961242..8452661026 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-discouraged/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-discouraged/_config.js
@@ -10,7 +10,7 @@ export default test({
test({ assert, target, warnings }) {
const warning =
- 'Counter.svelte mutated a value owned by main.svelte. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead';
+ 'Mutating unbound props (`object`, at Counter.svelte:5:23) is strongly discouraged. Consider using `bind:object={...}` in main.svelte (or using a callback) instead';
const [btn1, btn2] = target.querySelectorAll('button');
btn1.click();
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/_config.js
deleted file mode 100644
index b4864154c3..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/_config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { test } from '../../test';
-
-export default test({
- compileOptions: {
- dev: true
- },
-
- async test({ assert, warnings }) {
- assert.deepEqual(warnings, []);
- }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/child.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/child.svelte
deleted file mode 100644
index 13de753647..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/child.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/main.svelte
deleted file mode 100644
index 8a6922e9e2..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-global-2/main.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/_config.js
similarity index 74%
rename from packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/_config.js
rename to packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/_config.js
index c07b9ce129..96b18d1854 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/_config.js
@@ -8,7 +8,7 @@ let warn;
let warnings = [];
export default test({
- html: ``,
+ html: ``,
compileOptions: {
dev: true
@@ -34,8 +34,8 @@ export default test({
btn?.click();
});
- assert.htmlEqual(target.innerHTML, ``);
+ assert.htmlEqual(target.innerHTML, ``);
- assert.deepEqual(warnings, []);
+ assert.deepEqual(warnings, [], 'expected getContext to have widened ownership');
}
});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/main.svelte
new file mode 100644
index 0000000000..2dd7cab141
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/main.svelte
@@ -0,0 +1,9 @@
+
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/sub.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/sub.svelte
similarity index 100%
rename from packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/sub.svelte
rename to packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-1/sub.svelte
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/_config.js
index c07b9ce129..66f1726a2a 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/_config.js
@@ -1,41 +1,24 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
-/** @type {typeof console.warn} */
-let warn;
-
-/** @type {any[]} */
-let warnings = [];
-
export default test({
- html: ``,
-
compileOptions: {
dev: true
},
- before_test: () => {
- warn = console.warn;
-
- console.warn = (...args) => {
- warnings.push(...args);
- };
- },
+ test({ assert, target, warnings }) {
+ const [btn1, btn2] = target.querySelectorAll('button');
- after_test: () => {
- console.warn = warn;
- warnings = [];
- },
+ flushSync(() => {
+ btn1.click();
+ });
- test({ assert, target }) {
- const btn = target.querySelector('button');
+ assert.deepEqual(warnings.length, 0);
flushSync(() => {
- btn?.click();
+ btn2.click();
});
- assert.htmlEqual(target.innerHTML, ``);
-
- assert.deepEqual(warnings, []);
+ assert.deepEqual(warnings.length, 1);
}
});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/main.svelte
index ad450a937e..0be7e434e4 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/main.svelte
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/main.svelte
@@ -1,9 +1,8 @@
-
-
+
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/state.svelte.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/state.svelte.js
index 3e7a68cf97..2906b9bce5 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/state.svelte.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/state.svelte.js
@@ -1 +1,14 @@
-export let global = $state({});
+export function create_my_state() {
+ const my_state = $state({
+ a: 0
+ });
+
+ function inc() {
+ my_state.a++;
+ }
+
+ return {
+ my_state,
+ inc
+ };
+}
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/sub.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/sub.svelte
similarity index 100%
rename from packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/sub.svelte
rename to packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-2/sub.svelte
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/Child.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/Child.svelte
similarity index 100%
rename from packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/Child.svelte
rename to packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/Child.svelte
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/_config.js
index 96b18d1854..ab7327ab8b 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/_config.js
@@ -1,41 +1,24 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
-/** @type {typeof console.warn} */
-let warn;
-
-/** @type {any[]} */
-let warnings = [];
-
export default test({
- html: ``,
-
compileOptions: {
dev: true
},
- before_test: () => {
- warn = console.warn;
-
- console.warn = (...args) => {
- warnings.push(...args);
- };
- },
+ async test({ assert, target, warnings }) {
+ const [btn1, btn2] = target.querySelectorAll('button');
- after_test: () => {
- console.warn = warn;
- warnings = [];
- },
+ flushSync(() => {
+ btn1.click();
+ });
- test({ assert, target }) {
- const btn = target.querySelector('button');
+ assert.deepEqual(warnings.length, 0);
flushSync(() => {
- btn?.click();
+ btn2.click();
});
- assert.htmlEqual(target.innerHTML, ``);
-
- assert.deepEqual(warnings, [], 'expected getContext to have widened ownership');
+ assert.deepEqual(warnings.length, 1);
}
});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/main.svelte
index 2dd7cab141..8e8343790b 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/main.svelte
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-3/main.svelte
@@ -1,9 +1,13 @@
-
+
+
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/_config.js
deleted file mode 100644
index aeb3740dfe..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/_config.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { flushSync } from 'svelte';
-import { test } from '../../test';
-
-/** @type {typeof console.warn} */
-let warn;
-
-/** @type {any[]} */
-let warnings = [];
-
-export default test({
- compileOptions: {
- dev: true
- },
-
- before_test: () => {
- warn = console.warn;
-
- console.warn = (...args) => {
- warnings.push(...args);
- };
- },
-
- after_test: () => {
- console.warn = warn;
- warnings = [];
- },
-
- test({ assert, target }) {
- const btn = target.querySelector('button');
-
- flushSync(() => {
- btn?.click();
- });
-
- assert.deepEqual(warnings, []);
- }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/main.svelte
deleted file mode 100644
index 2d40c13949..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/main.svelte
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/state.svelte.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/state.svelte.js
deleted file mode 100644
index 4079059171..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/state.svelte.js
+++ /dev/null
@@ -1,13 +0,0 @@
-class Global {
- state = $state({});
-
- add_a(a) {
- this.state.a = a;
- }
-
- increment_a_b() {
- this.state.a.b++;
- }
-}
-
-export const global = new Global();
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/sub.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/sub.svelte
deleted file mode 100644
index 044904aa18..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-4/sub.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/_config.js
deleted file mode 100644
index 66f1726a2a..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/_config.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { flushSync } from 'svelte';
-import { test } from '../../test';
-
-export default test({
- compileOptions: {
- dev: true
- },
-
- test({ assert, target, warnings }) {
- const [btn1, btn2] = target.querySelectorAll('button');
-
- flushSync(() => {
- btn1.click();
- });
-
- assert.deepEqual(warnings.length, 0);
-
- flushSync(() => {
- btn2.click();
- });
-
- assert.deepEqual(warnings.length, 1);
- }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/main.svelte
deleted file mode 100644
index 0be7e434e4..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/main.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/state.svelte.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/state.svelte.js
deleted file mode 100644
index 2906b9bce5..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-5/state.svelte.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export function create_my_state() {
- const my_state = $state({
- a: 0
- });
-
- function inc() {
- my_state.a++;
- }
-
- return {
- my_state,
- inc
- };
-}
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/Child.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/Child.svelte
deleted file mode 100644
index aa31fd7606..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/Child.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/_config.js
deleted file mode 100644
index cc9ea715f0..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/_config.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { flushSync } from 'svelte';
-import { test } from '../../test';
-
-/** @type {typeof console.warn} */
-let warn;
-
-/** @type {any[]} */
-let warnings = [];
-
-export default test({
- compileOptions: {
- dev: true
- },
-
- before_test: () => {
- warn = console.warn;
-
- console.warn = (...args) => {
- warnings.push(...args);
- };
- },
-
- after_test: () => {
- console.warn = warn;
- warnings = [];
- },
-
- async test({ assert, target }) {
- const btn = target.querySelector('button');
-
- flushSync(() => {
- btn?.click();
- });
-
- assert.deepEqual(warnings.length, 0);
- }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/main.svelte
deleted file mode 100644
index 92d7dbd2db..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-6/main.svelte
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/_config.js
deleted file mode 100644
index ab7327ab8b..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/_config.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { flushSync } from 'svelte';
-import { test } from '../../test';
-
-export default test({
- compileOptions: {
- dev: true
- },
-
- async test({ assert, target, warnings }) {
- const [btn1, btn2] = target.querySelectorAll('button');
-
- flushSync(() => {
- btn1.click();
- });
-
- assert.deepEqual(warnings.length, 0);
-
- flushSync(() => {
- btn2.click();
- });
-
- assert.deepEqual(warnings.length, 1);
- }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/main.svelte
deleted file mode 100644
index 8e8343790b..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/main.svelte
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/Counter.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/Counter.svelte
deleted file mode 100644
index ffe6ef75c4..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/Counter.svelte
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/main.svelte
deleted file mode 100644
index 5f1c7461f6..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/main.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/state.svelte.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/state.svelte.js
deleted file mode 100644
index 6881c2faf6..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner/state.svelte.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export let global = $state({
- object: { count: -1 }
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-2/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-2/_config.js
index 87474a05cc..39fa80c55a 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-2/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-2/_config.js
@@ -8,6 +8,6 @@ export default test({
},
warnings: [
- 'Intermediate.svelte passed a value to Counter.svelte with `bind:`, but the value is owned by main.svelte. Consider creating a binding between main.svelte and Intermediate.svelte'
+ 'Intermediate.svelte passed property `object` to Counter.svelte with `bind:`, but its parent component main.svelte did not declare `object` as a binding. Consider creating a binding between main.svelte and Intermediate.svelte (e.g. `bind:object={...}` instead of `object={...}`)'
]
});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js
index 66e5184380..7b8cc676d5 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js
@@ -33,7 +33,7 @@ export default test({
assert.htmlEqual(target.innerHTML, ``);
assert.deepEqual(warnings, [
- 'Counter.svelte mutated a value owned by main.svelte. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead'
+ 'Mutating unbound props (`notshared`, at Counter.svelte:10:23) is strongly discouraged. Consider using `bind:notshared={...}` in main.svelte (or using a callback) instead'
]);
}
});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-7/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-7/_config.js
index e766a946d0..bd2ecc28b6 100644
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-7/_config.js
+++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-7/_config.js
@@ -1,7 +1,6 @@
import { flushSync } from 'svelte';
import { ok, test } from '../../test';
-// Tests that proxies widen ownership correctly even if not directly connected to each other
export default test({
compileOptions: {
dev: true
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterBinding.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterBinding.svelte
deleted file mode 100644
index d6da559fb1..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterBinding.svelte
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-Binding
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterContext.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterContext.svelte
deleted file mode 100644
index b935f0a472..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/CounterContext.svelte
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-Context
-
-
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/_config.js
deleted file mode 100644
index d6d12d01cd..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/_config.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { flushSync } from 'svelte';
-import { test } from '../../test';
-
-// Tests that ownership is widened with $derived (on class or on its own) that contains $state
-export default test({
- compileOptions: {
- dev: true
- },
-
- test({ assert, target, warnings }) {
- const [root, counter_context1, counter_context2, counter_binding1, counter_binding2] =
- target.querySelectorAll('button');
-
- counter_context1.click();
- counter_context2.click();
- counter_binding1.click();
- counter_binding2.click();
- flushSync();
-
- assert.equal(warnings.length, 0);
-
- root.click();
- flushSync();
- counter_context1.click();
- counter_context2.click();
- counter_binding1.click();
- counter_binding2.click();
- flushSync();
-
- assert.equal(warnings.length, 0);
- },
-
- warnings: []
-});
diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/main.svelte b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/main.svelte
deleted file mode 100644
index aaade26e16..0000000000
--- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-8/main.svelte
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-Parent
-
-
-
-
diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts
index 3db817997c..55bec5020f 100644
--- a/packages/svelte/tests/signals/test.ts
+++ b/packages/svelte/tests/signals/test.ts
@@ -1086,6 +1086,38 @@ describe('signals', () => {
};
});
+ test("deriveds set after they are DIRTY doesn't get updated on get", () => {
+ return () => {
+ const a = state(0);
+ const b = derived(() => $.get(a));
+
+ set(b, 1);
+ assert.equal($.get(b), 1);
+
+ set(a, 2);
+ assert.equal($.get(b), 2);
+ set(b, 3);
+
+ assert.equal($.get(b), 3);
+ };
+ });
+
+ test("unowned deriveds set after they are DIRTY doesn't get updated on get", () => {
+ return () => {
+ const a = state(0);
+ const b = derived(() => $.get(a));
+ const c = derived(() => $.get(b));
+
+ set(b, 1);
+ assert.equal($.get(c), 1);
+
+ set(a, 2);
+
+ assert.equal($.get(b), 2);
+ assert.equal($.get(c), 2);
+ };
+ });
+
test('deriveds containing effects work correctly when used with untrack', () => {
return () => {
let a = render_effect(() => {});
diff --git a/playgrounds/sandbox/package.json b/playgrounds/sandbox/package.json
index cb44905309..d392349b60 100644
--- a/playgrounds/sandbox/package.json
+++ b/playgrounds/sandbox/package.json
@@ -18,7 +18,7 @@
"polka": "^1.0.0-next.25",
"svelte": "workspace:*",
"tinyglobby": "^0.2.12",
- "vite": "^5.4.16",
+ "vite": "^5.4.17",
"vite-plugin-inspect": "^0.8.4"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e1f276d23f..f0e66d1681 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -152,7 +152,7 @@ importers:
devDependencies:
'@sveltejs/vite-plugin-svelte':
specifier: ^4.0.0-next.6
- version: 4.0.0-next.6(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
+ version: 4.0.0-next.6(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
polka:
specifier: ^1.0.0-next.25
version: 1.0.0-next.25
@@ -163,11 +163,11 @@ importers:
specifier: ^0.2.12
version: 0.2.12
vite:
- specifier: ^5.4.16
- version: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ specifier: ^5.4.17
+ version: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
vite-plugin-inspect:
specifier: ^0.8.4
- version: 0.8.4(rollup@4.38.0)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
+ version: 0.8.4(rollup@4.39.0)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
packages:
@@ -551,8 +551,8 @@ packages:
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm-eabi@4.38.0':
- resolution: {integrity: sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==}
+ '@rollup/rollup-android-arm-eabi@4.39.0':
+ resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==}
cpu: [arm]
os: [android]
@@ -561,8 +561,8 @@ packages:
cpu: [arm64]
os: [android]
- '@rollup/rollup-android-arm64@4.38.0':
- resolution: {integrity: sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==}
+ '@rollup/rollup-android-arm64@4.39.0':
+ resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==}
cpu: [arm64]
os: [android]
@@ -571,8 +571,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-arm64@4.38.0':
- resolution: {integrity: sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==}
+ '@rollup/rollup-darwin-arm64@4.39.0':
+ resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==}
cpu: [arm64]
os: [darwin]
@@ -581,18 +581,18 @@ packages:
cpu: [x64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.38.0':
- resolution: {integrity: sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==}
+ '@rollup/rollup-darwin-x64@4.39.0':
+ resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-freebsd-arm64@4.38.0':
- resolution: {integrity: sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==}
+ '@rollup/rollup-freebsd-arm64@4.39.0':
+ resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.38.0':
- resolution: {integrity: sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==}
+ '@rollup/rollup-freebsd-x64@4.39.0':
+ resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==}
cpu: [x64]
os: [freebsd]
@@ -601,8 +601,8 @@ packages:
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-gnueabihf@4.38.0':
- resolution: {integrity: sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==}
+ '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
+ resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==}
cpu: [arm]
os: [linux]
@@ -611,8 +611,8 @@ packages:
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.38.0':
- resolution: {integrity: sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==}
+ '@rollup/rollup-linux-arm-musleabihf@4.39.0':
+ resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==}
cpu: [arm]
os: [linux]
@@ -621,8 +621,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.38.0':
- resolution: {integrity: sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==}
+ '@rollup/rollup-linux-arm64-gnu@4.39.0':
+ resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==}
cpu: [arm64]
os: [linux]
@@ -631,13 +631,13 @@ packages:
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.38.0':
- resolution: {integrity: sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==}
+ '@rollup/rollup-linux-arm64-musl@4.39.0':
+ resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-loongarch64-gnu@4.38.0':
- resolution: {integrity: sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==}
+ '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
+ resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==}
cpu: [loong64]
os: [linux]
@@ -646,8 +646,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-powerpc64le-gnu@4.38.0':
- resolution: {integrity: sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==}
+ '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
+ resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==}
cpu: [ppc64]
os: [linux]
@@ -656,13 +656,13 @@ packages:
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.38.0':
- resolution: {integrity: sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==}
+ '@rollup/rollup-linux-riscv64-gnu@4.39.0':
+ resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-musl@4.38.0':
- resolution: {integrity: sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==}
+ '@rollup/rollup-linux-riscv64-musl@4.39.0':
+ resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==}
cpu: [riscv64]
os: [linux]
@@ -671,8 +671,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.38.0':
- resolution: {integrity: sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==}
+ '@rollup/rollup-linux-s390x-gnu@4.39.0':
+ resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==}
cpu: [s390x]
os: [linux]
@@ -681,8 +681,8 @@ packages:
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.38.0':
- resolution: {integrity: sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==}
+ '@rollup/rollup-linux-x64-gnu@4.39.0':
+ resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==}
cpu: [x64]
os: [linux]
@@ -691,8 +691,8 @@ packages:
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.38.0':
- resolution: {integrity: sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==}
+ '@rollup/rollup-linux-x64-musl@4.39.0':
+ resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==}
cpu: [x64]
os: [linux]
@@ -701,8 +701,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-arm64-msvc@4.38.0':
- resolution: {integrity: sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==}
+ '@rollup/rollup-win32-arm64-msvc@4.39.0':
+ resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==}
cpu: [arm64]
os: [win32]
@@ -711,8 +711,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.38.0':
- resolution: {integrity: sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==}
+ '@rollup/rollup-win32-ia32-msvc@4.39.0':
+ resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==}
cpu: [ia32]
os: [win32]
@@ -721,8 +721,8 @@ packages:
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.38.0':
- resolution: {integrity: sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==}
+ '@rollup/rollup-win32-x64-msvc@4.39.0':
+ resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==}
cpu: [x64]
os: [win32]
@@ -1974,8 +1974,8 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
- rollup@4.38.0:
- resolution: {integrity: sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==}
+ rollup@4.39.0:
+ resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -2310,8 +2310,8 @@ packages:
terser:
optional: true
- vite@5.4.16:
- resolution: {integrity: sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==}
+ vite@5.4.17:
+ resolution: {integrity: sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
@@ -2860,120 +2860,120 @@ snapshots:
optionalDependencies:
rollup: 4.22.4
- '@rollup/pluginutils@5.1.0(rollup@4.38.0)':
+ '@rollup/pluginutils@5.1.0(rollup@4.39.0)':
dependencies:
'@types/estree': 1.0.6
estree-walker: 2.0.2
picomatch: 2.3.1
optionalDependencies:
- rollup: 4.38.0
+ rollup: 4.39.0
'@rollup/rollup-android-arm-eabi@4.22.4':
optional: true
- '@rollup/rollup-android-arm-eabi@4.38.0':
+ '@rollup/rollup-android-arm-eabi@4.39.0':
optional: true
'@rollup/rollup-android-arm64@4.22.4':
optional: true
- '@rollup/rollup-android-arm64@4.38.0':
+ '@rollup/rollup-android-arm64@4.39.0':
optional: true
'@rollup/rollup-darwin-arm64@4.22.4':
optional: true
- '@rollup/rollup-darwin-arm64@4.38.0':
+ '@rollup/rollup-darwin-arm64@4.39.0':
optional: true
'@rollup/rollup-darwin-x64@4.22.4':
optional: true
- '@rollup/rollup-darwin-x64@4.38.0':
+ '@rollup/rollup-darwin-x64@4.39.0':
optional: true
- '@rollup/rollup-freebsd-arm64@4.38.0':
+ '@rollup/rollup-freebsd-arm64@4.39.0':
optional: true
- '@rollup/rollup-freebsd-x64@4.38.0':
+ '@rollup/rollup-freebsd-x64@4.39.0':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.22.4':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.38.0':
+ '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.22.4':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.38.0':
+ '@rollup/rollup-linux-arm-musleabihf@4.39.0':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.22.4':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.38.0':
+ '@rollup/rollup-linux-arm64-gnu@4.39.0':
optional: true
'@rollup/rollup-linux-arm64-musl@4.22.4':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.38.0':
+ '@rollup/rollup-linux-arm64-musl@4.39.0':
optional: true
- '@rollup/rollup-linux-loongarch64-gnu@4.38.0':
+ '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.22.4':
optional: true
- '@rollup/rollup-linux-powerpc64le-gnu@4.38.0':
+ '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.22.4':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.38.0':
+ '@rollup/rollup-linux-riscv64-gnu@4.39.0':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.38.0':
+ '@rollup/rollup-linux-riscv64-musl@4.39.0':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.22.4':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.38.0':
+ '@rollup/rollup-linux-s390x-gnu@4.39.0':
optional: true
'@rollup/rollup-linux-x64-gnu@4.22.4':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.38.0':
+ '@rollup/rollup-linux-x64-gnu@4.39.0':
optional: true
'@rollup/rollup-linux-x64-musl@4.22.4':
optional: true
- '@rollup/rollup-linux-x64-musl@4.38.0':
+ '@rollup/rollup-linux-x64-musl@4.39.0':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.22.4':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.38.0':
+ '@rollup/rollup-win32-arm64-msvc@4.39.0':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.22.4':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.38.0':
+ '@rollup/rollup-win32-ia32-msvc@4.39.0':
optional: true
'@rollup/rollup-win32-x64-msvc@4.22.4':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.38.0':
+ '@rollup/rollup-win32-x64-msvc@4.39.0':
optional: true
'@stylistic/eslint-plugin-js@1.8.0(eslint@9.9.1)':
@@ -3000,25 +3000,25 @@ snapshots:
typescript: 5.5.4
typescript-eslint: 8.26.0(eslint@9.9.1)(typescript@5.5.4)
- '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.2(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)))(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))':
+ '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.2(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)))(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))':
dependencies:
- '@sveltejs/vite-plugin-svelte': 4.0.0-next.6(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
+ '@sveltejs/vite-plugin-svelte': 4.0.0-next.6(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
debug: 4.4.0
svelte: link:packages/svelte
- vite: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ vite: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
transitivePeerDependencies:
- supports-color
- '@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))':
+ '@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))':
dependencies:
- '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.2(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)))(svelte@packages+svelte)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
+ '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.2(@sveltejs/vite-plugin-svelte@4.0.0-next.6(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)))(svelte@packages+svelte)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
debug: 4.4.0
deepmerge: 4.3.1
kleur: 4.1.5
magic-string: 0.30.17
svelte: link:packages/svelte
- vite: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
- vitefu: 0.2.5(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
+ vite: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ vitefu: 0.2.5(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))
transitivePeerDependencies:
- supports-color
@@ -4292,30 +4292,30 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.22.4
fsevents: 2.3.3
- rollup@4.38.0:
+ rollup@4.39.0:
dependencies:
'@types/estree': 1.0.7
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.38.0
- '@rollup/rollup-android-arm64': 4.38.0
- '@rollup/rollup-darwin-arm64': 4.38.0
- '@rollup/rollup-darwin-x64': 4.38.0
- '@rollup/rollup-freebsd-arm64': 4.38.0
- '@rollup/rollup-freebsd-x64': 4.38.0
- '@rollup/rollup-linux-arm-gnueabihf': 4.38.0
- '@rollup/rollup-linux-arm-musleabihf': 4.38.0
- '@rollup/rollup-linux-arm64-gnu': 4.38.0
- '@rollup/rollup-linux-arm64-musl': 4.38.0
- '@rollup/rollup-linux-loongarch64-gnu': 4.38.0
- '@rollup/rollup-linux-powerpc64le-gnu': 4.38.0
- '@rollup/rollup-linux-riscv64-gnu': 4.38.0
- '@rollup/rollup-linux-riscv64-musl': 4.38.0
- '@rollup/rollup-linux-s390x-gnu': 4.38.0
- '@rollup/rollup-linux-x64-gnu': 4.38.0
- '@rollup/rollup-linux-x64-musl': 4.38.0
- '@rollup/rollup-win32-arm64-msvc': 4.38.0
- '@rollup/rollup-win32-ia32-msvc': 4.38.0
- '@rollup/rollup-win32-x64-msvc': 4.38.0
+ '@rollup/rollup-android-arm-eabi': 4.39.0
+ '@rollup/rollup-android-arm64': 4.39.0
+ '@rollup/rollup-darwin-arm64': 4.39.0
+ '@rollup/rollup-darwin-x64': 4.39.0
+ '@rollup/rollup-freebsd-arm64': 4.39.0
+ '@rollup/rollup-freebsd-x64': 4.39.0
+ '@rollup/rollup-linux-arm-gnueabihf': 4.39.0
+ '@rollup/rollup-linux-arm-musleabihf': 4.39.0
+ '@rollup/rollup-linux-arm64-gnu': 4.39.0
+ '@rollup/rollup-linux-arm64-musl': 4.39.0
+ '@rollup/rollup-linux-loongarch64-gnu': 4.39.0
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.39.0
+ '@rollup/rollup-linux-riscv64-gnu': 4.39.0
+ '@rollup/rollup-linux-riscv64-musl': 4.39.0
+ '@rollup/rollup-linux-s390x-gnu': 4.39.0
+ '@rollup/rollup-linux-x64-gnu': 4.39.0
+ '@rollup/rollup-linux-x64-musl': 4.39.0
+ '@rollup/rollup-win32-arm64-msvc': 4.39.0
+ '@rollup/rollup-win32-ia32-msvc': 4.39.0
+ '@rollup/rollup-win32-x64-msvc': 4.39.0
fsevents: 2.3.3
rrweb-cssom@0.7.1: {}
@@ -4562,7 +4562,7 @@ snapshots:
debug: 4.4.0
es-module-lexer: 1.6.0
pathe: 1.1.2
- vite: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ vite: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -4574,10 +4574,10 @@ snapshots:
- supports-color
- terser
- vite-plugin-inspect@0.8.4(rollup@4.38.0)(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)):
+ vite-plugin-inspect@0.8.4(rollup@4.39.0)(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)):
dependencies:
'@antfu/utils': 0.7.8
- '@rollup/pluginutils': 5.1.0(rollup@4.38.0)
+ '@rollup/pluginutils': 5.1.0(rollup@4.39.0)
debug: 4.4.0
error-stack-parser-es: 0.1.1
fs-extra: 11.2.0
@@ -4585,7 +4585,7 @@ snapshots:
perfect-debounce: 1.0.0
picocolors: 1.1.1
sirv: 2.0.4
- vite: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ vite: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
transitivePeerDependencies:
- rollup
- supports-color
@@ -4602,11 +4602,11 @@ snapshots:
sass: 1.70.0
terser: 5.27.0
- vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0):
+ vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0):
dependencies:
esbuild: 0.21.5
postcss: 8.5.3
- rollup: 4.38.0
+ rollup: 4.39.0
optionalDependencies:
'@types/node': 20.12.7
fsevents: 2.3.3
@@ -4614,9 +4614,9 @@ snapshots:
sass: 1.70.0
terser: 5.27.0
- vitefu@0.2.5(vite@5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)):
+ vitefu@0.2.5(vite@5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)):
optionalDependencies:
- vite: 5.4.16(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
+ vite: 5.4.17(@types/node@20.12.7)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)
vitest@2.1.9(@types/node@20.12.7)(jsdom@25.0.1)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0):
dependencies: