From 6c00666b277271c4f8eda011e461ff24b0a46d4e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Wed, 17 Jan 2024 16:51:43 +0100 Subject: [PATCH] fix: ensure derived is always added as a consumer fixes #10097 --- .../svelte/src/internal/client/runtime.js | 11 ++++++---- packages/svelte/tests/signals/test.ts | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index dc117a26d..959ef9c8b 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -84,10 +84,12 @@ export let current_untracking = false; /** Exists to opt out of the mutation validation for stores which may be set for the first time during a derivation */ let ignore_mutation_validation = false; -// If we are working with a get() chain that has no active container, -// to prevent memory leaks, we skip adding the consumer. +/** + * If we are working with a get() chain that has no active container, + * to prevent memory leaks, we skip adding the consumer. + */ let current_skip_consumer = false; -// Handle collecting all signals which are read during a specific time frame +/** Handle collecting all signals which are read during a specific time frame */ let is_signals_recorded = false; let captured_signals = new Set(); @@ -343,7 +345,8 @@ function execute_signal_fn(signal) { current_consumer = signal; current_block = signal.b; current_component_context = signal.x; - current_skip_consumer = current_effect === null && (signal.f & UNOWNED) !== 0; + current_skip_consumer = + current_effect === null && (signal.f & UNOWNED) !== 0 && (signal.f & DERIVED) === 0; current_untracking = false; // Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 241d57356..052b921be 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -128,6 +128,27 @@ describe('signals', () => { }; }); + test('effect with derived using new derived every time', () => { + const log: number[] = []; + + let count = $.source(0); + const read = () => { + const x = $.derived(() => ({ count: $.get(count) })); + return $.get(x); + }; + const derivedCount = $.derived(() => read().count); + $.user_effect(() => { + log.push($.get(derivedCount)); + }); + + return () => { + $.flushSync(() => $.set(count, 1)); + $.flushSync(() => $.set(count, 2)); + + assert.deepEqual(log, [0, 1, 2]); + }; + }); + test('https://perf.js.hyoo.ru/#!bench=9h2as6_u0mfnn', () => { let res: number[] = [];