From ba0bdc7aa19feb183094aec7b60b7081d3218bf7 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 16 Feb 2024 17:41:42 +0100 Subject: [PATCH] chore: document and test signals edge case (#10228) --- .../svelte/src/internal/client/runtime.js | 6 ++++- packages/svelte/tests/signals/test.ts | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index cf55be1f5e..c47f0d4638 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -74,7 +74,11 @@ export let current_effect = null; /** @type {null | import('./types.js').Signal[]} */ let current_dependencies = null; let current_dependencies_index = 0; -/** @type {null | import('./types.js').Signal[]} */ +/** + * Tracks writes that the effect it's executed in doesn't listen to yet, + * so that the dependency can be added to the effect later on if it then reads it + * @type {null | import('./types.js').Signal[]} + */ let current_untracked_writes = null; /** @type {null | import('./types.js').SignalDebug} */ let last_inspected_signal = null; diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 7ba75deb49..d34cd7f06c 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -7,7 +7,7 @@ import type { ComputationSignal } from '../../src/internal/client/types'; * @param fn A function that returns a function because we first need to setup all the signals * and then execute the test in order to simulate a real component */ -function run_test(runes: boolean, fn: () => () => void) { +function run_test(runes: boolean, fn: (runes: boolean) => () => void) { return () => { // Create a component context to test runes vs legacy mode $.push({}, runes); @@ -15,7 +15,7 @@ function run_test(runes: boolean, fn: () => () => void) { let execute: any; const signal = $.render_effect( () => { - execute = fn(); + execute = fn(runes); }, null, true, @@ -27,7 +27,7 @@ function run_test(runes: boolean, fn: () => () => void) { }; } -function test(text: string, fn: () => any) { +function test(text: string, fn: (runes: boolean) => any) { it(`${text} (legacy mode)`, run_test(false, fn)); it(`${text} (runes mode)`, run_test(true, fn)); } @@ -262,4 +262,25 @@ describe('signals', () => { assert.deepEqual(count.c, null); }; }); + + test('schedules rerun when writing to signal before reading it', (runes) => { + if (!runes) return () => {}; + + const value = $.source({ count: 0 }); + $.user_effect(() => { + $.set(value, { count: 0 }); + $.get(value); + }); + + return () => { + let errored = false; + try { + $.flushSync(); + } catch (e: any) { + assert.include(e.message, 'ERR_SVELTE_TOO_MANY_UPDATES'); + errored = true; + } + assert.equal(errored, true); + }; + }); });