From 029dcfeabf3aa74b3c67ae946a3dce71fec6d5fa Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 20 Aug 2024 17:50:38 -0400 Subject: [PATCH 1/3] breaking: remove `$state.link` callback --- .changeset/sharp-foxes-whisper.md | 5 +++ documentation/docs/03-runes/01-state.md | 18 --------- packages/svelte/src/ambient.d.ts | 2 +- .../client/visitors/VariableDeclaration.js | 6 +-- .../src/internal/client/reactivity/sources.js | 8 +--- .../samples/state-link-callback/_config.js | 38 ------------------- .../samples/state-link-callback/main.svelte | 12 ------ .../routes/docs/content/01-api/02-runes.md | 18 --------- 8 files changed, 9 insertions(+), 98 deletions(-) create mode 100644 .changeset/sharp-foxes-whisper.md delete mode 100644 packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte diff --git a/.changeset/sharp-foxes-whisper.md b/.changeset/sharp-foxes-whisper.md new file mode 100644 index 000000000000..553ae1bd6d00 --- /dev/null +++ b/.changeset/sharp-foxes-whisper.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +breaking: remove callback from `$state.link` diff --git a/documentation/docs/03-runes/01-state.md b/documentation/docs/03-runes/01-state.md index 35dc2f357db5..8d78e6c73ea1 100644 --- a/documentation/docs/03-runes/01-state.md +++ b/documentation/docs/03-runes/01-state.md @@ -89,24 +89,6 @@ console.log(a, b); // 3, 3 As with `$state`, if `$state.link` is passed a plain object or array it will be made deeply reactive. If passed an existing state proxy it will be reused, meaning that mutating the linked state will mutate the original. To clone a state proxy, you can use [`$state.snapshot`](#$state-snapshot). -If you pass a callback to `$state.link`, changes to the input value will invoke the callback rather than updating the linked state, allowing you to choose whether to (for example) preserve or discard local changes, or merge incoming changes with local ones: - -```js -let { stuff } = $props(); - -let incoming = $state(); -let hasUnsavedChanges = $state(false); - -let current = $state.link({ ...stuff }, (stuff) => { - if (hasUnsavedChanges) { - incoming = stuff; - } else { - incoming = null; - current = stuff; - } -}); -``` - ## `$state.raw` State declared with `$state.raw` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it: diff --git a/packages/svelte/src/ambient.d.ts b/packages/svelte/src/ambient.d.ts index e58b2c5aa5a5..a84085fd5a70 100644 --- a/packages/svelte/src/ambient.d.ts +++ b/packages/svelte/src/ambient.d.ts @@ -148,7 +148,7 @@ declare namespace $state { * * @param value The linked value */ - export function link(value: T, callback?: (value: T) => void): T; + export function link(value: T): T; export function raw(initial: T): T; export function raw(): T | undefined; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index 2c1db714ca72..84713f73ca72 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -131,11 +131,7 @@ export function VariableDeclaration(node, context) { } if (rune === '$state.link') { - value = b.call( - '$.source_link', - b.thunk(value), - args.length === 2 && /** @type {Expression} */ (context.visit(args[1])) - ); + value = b.call('$.source_link', b.thunk(value)); } else if (is_state_source(binding, context.state.analysis)) { value = b.call('$.source', value); } diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index d0c6441040c2..cde7a73a4f6a 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -49,10 +49,9 @@ export function source(v) { /** * @template V * @param {() => V} get_value - * @param {(value: V) => void} [callback] * @returns {(value?: V) => V} */ -export function source_link(get_value, callback) { +export function source_link(get_value) { var was_local = false; var init = false; var local_source = source(/** @type {V} */ (undefined)); @@ -80,10 +79,7 @@ export function source_link(get_value, callback) { var linked_value = get(linked_derived); if (init) { - if (callback !== undefined) { - untrack(() => callback(linked_value)); - return local_source.v; - } + // do nothing } else { init = true; } diff --git a/packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js b/packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js deleted file mode 100644 index bb56464ec1ed..000000000000 --- a/packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js +++ /dev/null @@ -1,38 +0,0 @@ -import { flushSync } from 'svelte'; -import { test } from '../../test'; - -export default test({ - html: ``, - - test({ assert, target }) { - const [btn1, btn2, btn3] = target.querySelectorAll('button'); - - flushSync(() => btn1.click()); - assert.htmlEqual( - target.innerHTML, - `` - ); - - flushSync(() => btn2.click()); - assert.htmlEqual( - target.innerHTML, - `` - ); - - flushSync(() => btn3.click()); - assert.htmlEqual(target.innerHTML, ``); - - flushSync(() => btn1.click()); - assert.htmlEqual(target.innerHTML, ``); - - flushSync(() => btn1.click()); - assert.htmlEqual(target.innerHTML, ``); - - flushSync(() => btn1.click()); - flushSync(() => btn3.click()); - assert.htmlEqual( - target.innerHTML, - `` - ); - } -}); diff --git a/packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte b/packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte deleted file mode 100644 index 3b52359d05d4..000000000000 --- a/packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md b/sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md index 665d522815f8..5fbed65a09ee 100644 --- a/sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md +++ b/sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md @@ -91,24 +91,6 @@ console.log(a, b); // 3, 3 As with `$state`, if `$state.link` is passed a plain object or array it will be made deeply reactive. If passed an existing state proxy it will be reused, meaning that mutating the linked state will mutate the original. To clone a state proxy, you can use [`$state.snapshot`](#$state-snapshot). -If you pass a callback to `$state.link`, changes to the input value will invoke the callback rather than updating the linked state, allowing you to choose whether to (for example) preserve or discard local changes, or merge incoming changes with local ones: - -```js -let { stuff } = $props(); - -let incoming = $state(); -let hasUnsavedChanges = $state(false); - -let current = $state.link({ ...stuff }, (stuff) => { - if (hasUnsavedChanges) { - incoming = stuff; - } else { - incoming = null; - current = stuff; - } -}); -``` - ## `$state.raw` State declared with `$state.raw` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it: From 325e3a8ffc1b987a588a01c10a0815b24b19ada1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 20 Aug 2024 17:57:14 -0400 Subject: [PATCH 2/3] simplify --- .../src/internal/client/reactivity/sources.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index cde7a73a4f6a..edfa8806e838 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -53,7 +53,6 @@ export function source(v) { */ export function source_link(get_value) { var was_local = false; - var init = false; var local_source = source(/** @type {V} */ (undefined)); var linked_derived = derived(() => { @@ -76,17 +75,7 @@ export function source_link(get_value) { return value; } - var linked_value = get(linked_derived); - - if (init) { - // do nothing - } else { - init = true; - } - - local_source.v = linked_value; - - return linked_value; + return (local_source.v = get(linked_derived)); }; } From 1a4008ee9ffac4ad609db9a26d139453b3f49e4c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 20 Aug 2024 18:03:00 -0400 Subject: [PATCH 3/3] regenerate --- packages/svelte/types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 35b4e60f4598..6f9828375a0b 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -2937,7 +2937,7 @@ declare namespace $state { * * @param value The linked value */ - export function link(value: T, callback?: (value: T) => void): T; + export function link(value: T): T; export function raw(initial: T): T; export function raw(): T | undefined;