diff --git a/.changeset/weak-frogs-bow.md b/.changeset/weak-frogs-bow.md new file mode 100644 index 0000000000..f897249948 --- /dev/null +++ b/.changeset/weak-frogs-bow.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: widen ownership when sub state is assigned to new state diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index bef9fb8437..30dceab486 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -127,8 +127,8 @@ export function add_owner(object, owner, global = false) { } /** - * @param {import('#client').ProxyMetadata | null} from - * @param {import('#client').ProxyMetadata} to + * @param {import('#client').ProxyMetadata | null} from + * @param {import('#client').ProxyMetadata} to */ export function widen_ownership(from, to) { if (to.owners === null) { diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index 17f8e1b2cd..136458c99d 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -38,6 +38,9 @@ export function proxy(value, immutable = true, parent = null) { // someone copied the state symbol using `Reflect.ownKeys(...)` if (metadata.t === value || metadata.p === value) { if (DEV) { + // Since original parent relationship gets lost, we need to copy over ancestor owners + // into current metadata. The object might still exist on both, so we need to widen it. + widen_ownership(metadata, metadata); metadata.parent = parent; } 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-7/Child.svelte new file mode 100644 index 0000000000..220638c07a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/Child.svelte @@ -0,0 +1,10 @@ + + +
{item?.name}
+ 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 new file mode 100644 index 0000000000..df3ca08f03 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/_config.js @@ -0,0 +1,41 @@ +import { tick } 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 [btn1, btn2] = target.querySelectorAll('button'); + + btn1.click(); + await tick(); + + assert.deepEqual(warnings.length, 0); + + btn2.click(); + await tick(); + + 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 new file mode 100644 index 0000000000..8e8343790b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-inherited-owner-7/main.svelte @@ -0,0 +1,13 @@ + + + +