From 60a71cc5934b1c19f86f4aa84288d0676fbe1e49 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 20 Aug 2024 16:11:50 -0400 Subject: [PATCH 1/2] move test --- .../_config.js | 0 .../main.svelte | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/svelte/tests/runtime-runes/samples/{state-link-callback => state-link-callback-condition}/_config.js (100%) rename packages/svelte/tests/runtime-runes/samples/{state-link-callback => state-link-callback-condition}/main.svelte (100%) diff --git a/packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js b/packages/svelte/tests/runtime-runes/samples/state-link-callback-condition/_config.js similarity index 100% rename from packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js rename to packages/svelte/tests/runtime-runes/samples/state-link-callback-condition/_config.js diff --git a/packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte b/packages/svelte/tests/runtime-runes/samples/state-link-callback-condition/main.svelte similarity index 100% rename from packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte rename to packages/svelte/tests/runtime-runes/samples/state-link-callback-condition/main.svelte From 1534c1d0bbb51d958e852b3a2f0859cd86baf07b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 20 Aug 2024 16:34:24 -0400 Subject: [PATCH 2/2] fix: invoke `$state.link` callback at the correct time --- .changeset/proud-dots-swim.md | 5 +++ .../src/internal/client/reactivity/sources.js | 44 +++++-------------- .../samples/state-link-callback/_config.js | 22 ++++++++++ .../samples/state-link-callback/main.svelte | 10 +++++ 4 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 .changeset/proud-dots-swim.md create mode 100644 packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte diff --git a/.changeset/proud-dots-swim.md b/.changeset/proud-dots-swim.md new file mode 100644 index 000000000000..3f86f115aee5 --- /dev/null +++ b/.changeset/proud-dots-swim.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: invoke `$state.link` callback at the correct time diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index d0c6441040c2..d6cc28c5c716 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -27,6 +27,7 @@ import { } from '../constants.js'; import * as e from '../errors.js'; import { derived } from './deriveds.js'; +import { render_effect } from './effects.js'; let inspect_effects = new Set(); @@ -53,44 +54,23 @@ export function source(v) { * @returns {(value?: V) => V} */ export function source_link(get_value, callback) { - var was_local = false; - var init = false; - var local_source = source(/** @type {V} */ (undefined)); + var s = source(/** @type {V} */ (undefined)); + var ran = false; - var linked_derived = derived(() => { - var local_value = /** @type {V} */ (get(local_source)); - var linked_value = get_value(); + callback ??= (value) => set(s, value); - if (was_local) { - was_local = false; - return local_value; - } - - return linked_value; - }); - - return function (/** @type {any} */ value) { - if (arguments.length > 0) { - was_local = true; - set(local_source, value); - get(linked_derived); - return value; - } - - var linked_value = get(linked_derived); - - if (init) { - if (callback !== undefined) { - untrack(() => callback(linked_value)); - return local_source.v; - } + render_effect(() => { + if (ran) { + callback(get_value()); } else { - init = true; + s.v = get_value(); } + }); - local_source.v = linked_value; + ran = true; - return linked_value; + return function (/** @type {any} */ value) { + return arguments.length === 1 ? set(s, /** @type {V} */ (value)) : get(s); }; } 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 new file mode 100644 index 000000000000..978fdb14d608 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/state-link-callback/_config.js @@ -0,0 +1,22 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: ``, + + test({ assert, target, logs }) { + const [btn1, btn2] = target.querySelectorAll('button'); + + flushSync(() => btn1.click()); + assert.deepEqual(logs, ['in callback 1']); + assert.htmlEqual(target.innerHTML, ``); + + flushSync(() => btn2.click()); + assert.deepEqual(logs, ['in callback 1']); + assert.htmlEqual(target.innerHTML, ``); + + flushSync(() => btn1.click()); + assert.deepEqual(logs, ['in callback 1', 'in callback 2']); + 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 new file mode 100644 index 000000000000..8ef97c454fc5 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/state-link-callback/main.svelte @@ -0,0 +1,10 @@ + + + +