From 8d383aed7e8a15b30c5835a50bb14fd24dc4ad72 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 24 Feb 2024 00:39:00 -0500 Subject: [PATCH] tidy up --- .../internal/client/reactivity/deriveds.js | 8 ++--- .../src/internal/client/reactivity/effects.js | 2 +- .../src/internal/client/reactivity/sources.js | 11 ++----- .../src/internal/client/reactivity/types.d.ts | 20 +++-------- packages/svelte/src/internal/client/render.js | 8 ++--- .../svelte/src/internal/client/runtime.js | 33 ++++++++++--------- packages/svelte/tests/signals/test.ts | 10 +++--- 7 files changed, 39 insertions(+), 53 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index e6ea131973..28d78bff2a 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -15,11 +15,11 @@ export function derived(fn) { /** @type {import('#client').Derived} */ const signal = { - c: null, + consumers: null, d: null, - e: default_equals, + eq: default_equals, f: flags, - i: fn, + fn: fn, r: null, // @ts-expect-error v: UNINITIALIZED, @@ -51,6 +51,6 @@ export function derived(fn) { /*#__NO_SIDE_EFFECTS__*/ export function derived_safe_equal(fn) { const signal = derived(fn); - signal.e = safe_equal; + signal.eq = safe_equal; return signal; } diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 8ca2260218..06add13e59 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -31,7 +31,7 @@ function create_effect(type, fn, sync, schedule) { d: null, f: type | DIRTY, l: 0, - i: fn, + fn: fn, r: null, v: null, ctx: current_component_context, diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index c6eb3d31e0..cc4b9e5b57 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -12,15 +12,10 @@ import { CLEAN, SOURCE } from '../constants.js'; export function source(value) { /** @type {import('#client').Source} */ const source = { - // consumers - c: null, - // equals - e: default_equals, - // flags f: SOURCE | CLEAN, - // value v: value, - // write version + eq: default_equals, + consumers: null, w: 0 }; @@ -39,7 +34,7 @@ export function source(value) { /*#__NO_SIDE_EFFECTS__*/ export function mutable_source(initial_value) { const s = source(initial_value); - s.e = safe_equal; + s.eq = safe_equal; // bind the signal to the component context, in case we need to // track updates to trigger beforeUpdate/afterUpdate callbacks diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts index 1e7febacf3..856625bd95 100644 --- a/packages/svelte/src/internal/client/reactivity/types.d.ts +++ b/packages/svelte/src/internal/client/reactivity/types.d.ts @@ -12,9 +12,9 @@ export type EffectType = typeof EFFECT | typeof PRE_EFFECT | typeof RENDER_EFFEC export interface Source { /** consumers: Signals that read from the current signal */ - c: null | Reaction[]; + consumers: null | Reaction[]; /** equals: For value equality */ - e: EqualsFunctions; + eq: EqualsFunctions; /** flags: The types that the signal represent, as a bitwise value */ f: SignalFlags; /** value: The latest value for this signal */ @@ -27,23 +27,13 @@ export interface SourceDebug extends Source { inspect: Set; } -export interface Derived { - /** consumers: Signals that read from the current signal */ - c: null | Reaction[]; +export interface Derived extends Source { /** dependencies: Signals that this signal reads from */ d: null | ValueSignal[]; - /** equals: For value equality */ - e: EqualsFunctions; - /** The types that the signal represent, as a bitwise value */ - f: SignalFlags; /** init: The function that we invoke for effects and computeds */ - i: () => V; + fn: () => V; /** references: Anything that a signal owns */ r: null | Reaction[]; - /** value: The latest value for this signal */ - v: V; - /** write version: used for unowned signals to track if their depdendencies are dirty or not **/ - w: number; } export interface DerivedDebug extends Derived { @@ -60,7 +50,7 @@ export interface Effect { /** The types that the signal represent, as a bitwise value */ f: SignalFlags; /** init: The function that we invoke for effects and computeds */ - i: null | (() => void | (() => void)); + fn: null | (() => void | (() => void)); /** deriveds belonging to this effect */ r: null | Derived[]; /** teardown */ diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 51fe0fc043..707a642ea3 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -67,8 +67,8 @@ import { import { run } from '../common.js'; import { bind_transition } from './transitions.js'; import { mutable_source, source } from './reactivity/sources.js'; -import { safe_equal, safe_not_equal } from './reactivity/equality.js'; -import { derived } from './reactivity/deriveds.js'; +import { safe_not_equal } from './reactivity/equality.js'; +import { derived, derived_safe_equal } from './reactivity/deriveds.js'; /** @type {Set} */ const all_registered_events = new Set(); @@ -2448,7 +2448,7 @@ export function prop(props, key, flags, initial) { // The derived returns the current value. The underlying mutable // source is written to from various places to persist this value. var inner_current_value = mutable_source(prop_value); - var current_value = derived(() => { + var current_value = (immutable ? derived : derived_safe_equal)(() => { var parent_value = getter(); var child_value = get(inner_current_value); @@ -2462,8 +2462,6 @@ export function prop(props, key, flags, initial) { return (inner_current_value.v = parent_value); }); - if (!immutable) current_value.e = safe_equal; - return function (/** @type {V} */ value, mutation = false) { var current = get(current_value); diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 97c51d3e34..d29bc143c8 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -212,8 +212,8 @@ function is_signal_dirty(signal) { * @param {import('#client').Reaction} signal * @returns {V} */ -function execute_signal_fn(signal) { - const init = signal.i; +function execute_reaction(signal) { + const init = signal.fn; const flags = signal.f; const previous_dependencies = current_dependencies; const previous_dependencies_index = current_dependencies_index; @@ -273,10 +273,10 @@ function execute_signal_fn(signal) { if (!current_skip_consumer) { for (i = current_dependencies_index; i < dependencies.length; i++) { const dependency = dependencies[i]; - const consumers = dependency.c; + const consumers = dependency.consumers; if (consumers === null) { - dependency.c = [signal]; + dependency.consumers = [signal]; } else if (consumers[consumers.length - 1] !== signal) { // TODO: should this be: // @@ -308,14 +308,14 @@ function execute_signal_fn(signal) { * @returns {void} */ function remove_consumer(signal, dependency) { - const consumers = dependency.c; + const consumers = dependency.consumers; let consumers_length = 0; if (consumers !== null) { consumers_length = consumers.length - 1; const index = consumers.indexOf(signal); if (index !== -1) { if (consumers_length === 0) { - dependency.c = null; + dependency.consumers = null; } else { // Swap with last element and then remove. consumers[index] = consumers[consumers_length]; @@ -394,7 +394,7 @@ export function execute_effect(effect) { current_component_context = component_context; - const possible_teardown = execute_signal_fn(effect); + const possible_teardown = execute_reaction(effect); if (typeof possible_teardown === 'function') { effect.v = possible_teardown; @@ -660,15 +660,17 @@ export async function tick() { function update_derived(signal, force_schedule) { const previous_updating_derived = updating_derived; updating_derived = true; - const value = execute_signal_fn(signal); + const value = execute_reaction(signal); updating_derived = previous_updating_derived; + const status = (current_skip_consumer || (signal.f & UNOWNED) !== 0) && signal.d !== null ? MAYBE_DIRTY : CLEAN; + set_signal_status(signal, status); - const equals = /** @type {import('#client').EqualsFunctions} */ (signal.e); - if (!equals(value, signal.v)) { + + if (!signal.eq(value, signal.v)) { signal.v = value; mark_signal_consumers(signal, DIRTY, force_schedule); @@ -772,13 +774,13 @@ export function set(signal, value) { : '') ); } - if ( - (signal.f & SOURCE) !== 0 && - !(/** @type {import('#client').EqualsFunctions} */ (signal.e)(value, signal.v)) - ) { + + if (!signal.eq(value, signal.v)) { signal.v = value; + // Increment write version so that unowned signals can properly track dirtyness signal.w++; + // If the current signal is running for the first time, it won't have any // consumers as we only allocate and assign the consumers after the signal // has fully executed. So in the case of ensuring it registers the consumer @@ -807,6 +809,7 @@ export function set(signal, value) { } } } + mark_signal_consumers(signal, DIRTY, true); // @ts-expect-error @@ -881,7 +884,7 @@ export function mutate(source, value) { */ function mark_signal_consumers(signal, to_status, force_schedule) { const runes = is_runes(null); - const consumers = signal.c; + const consumers = signal.consumers; if (consumers !== null) { const length = consumers.length; diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index c023469df6..c81c99e937 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -192,13 +192,13 @@ describe('signals', () => { return () => { $.flushSync(() => $.set(count, 1)); // Ensure we're not leaking consumers - assert.deepEqual(count.c?.length, 1); + assert.deepEqual(count.consumers?.length, 1); $.flushSync(() => $.set(count, 2)); // Ensure we're not leaking consumers - assert.deepEqual(count.c?.length, 1); + assert.deepEqual(count.consumers?.length, 1); $.flushSync(() => $.set(count, 3)); // Ensure we're not leaking consumers - assert.deepEqual(count.c?.length, 1); + assert.deepEqual(count.consumers?.length, 1); assert.deepEqual(log, [0, 1, 2, 3]); }; }); @@ -258,11 +258,11 @@ describe('signals', () => { $.flushSync(() => $.set(count, 4)); $.flushSync(() => $.set(count, 0)); // Ensure we're not leaking consumers - assert.deepEqual(count.c?.length, 1); + assert.deepEqual(count.consumers?.length, 1); assert.deepEqual(log, [0, 2, 'limit', 0]); $.destroy_signal(effect); // Ensure we're not leaking consumers - assert.deepEqual(count.c, null); + assert.deepEqual(count.consumers, null); }; });