From 6444559a66e9b253de63a83507a47658a0e044a2 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 19 Jan 2024 15:30:40 -0600 Subject: [PATCH] move selector construct onto signals --- packages/signals/src/global.rs | 2 +- packages/signals/src/selector.rs | 66 ++------------------------------ packages/signals/src/signal.rs | 62 +++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/packages/signals/src/global.rs b/packages/signals/src/global.rs index 0c81f8077..a7e7582b1 100644 --- a/packages/signals/src/global.rs +++ b/packages/signals/src/global.rs @@ -225,7 +225,7 @@ impl GlobalSelector { None => { drop(read); // Constructors are always run in the root scope - let signal = ScopeId::ROOT.in_runtime(|| selector(self.selector)); + let signal = ScopeId::ROOT.in_runtime(|| Signal::selector(self.selector)); context.signal.borrow_mut().insert(key, Box::new(signal)); signal } diff --git a/packages/signals/src/selector.rs b/packages/signals/src/selector.rs index 1328d3bde..d8f38e10a 100644 --- a/packages/signals/src/selector.rs +++ b/packages/signals/src/selector.rs @@ -2,8 +2,8 @@ use dioxus_core::prelude::*; use generational_box::Storage; use crate::dependency::Dependency; -use crate::{get_effect_ref, signal::SignalData, CopyValue, Effect, ReadOnlySignal, Signal}; -use crate::{use_signal, EffectInner, EFFECT_STACK}; +use crate::use_signal; +use crate::{signal::SignalData, ReadOnlySignal, Signal}; /// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes. /// @@ -50,7 +50,7 @@ pub fn use_selector(f: impl FnMut() -> R + 'static) -> ReadOnlySig pub fn use_maybe_sync_selector>>( f: impl FnMut() -> R + 'static, ) -> ReadOnlySignal { - use_hook(|| maybe_sync_selector(f)) + use_hook(|| Signal::maybe_sync_selector(f)) } /// Creates a new unsync Selector with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes @@ -112,7 +112,7 @@ where { let mut dependencies_signal = use_signal(|| dependencies.out()); let selector = use_hook(|| { - maybe_sync_selector(move || { + Signal::maybe_sync_selector(move || { let deref = &*dependencies_signal.read(); f(deref.clone()) }) @@ -123,61 +123,3 @@ where } selector } - -/// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes. -/// -/// Selectors can be used to efficiently compute derived data from signals. -#[track_caller] -pub fn selector(f: impl FnMut() -> R + 'static) -> ReadOnlySignal { - maybe_sync_selector(f) -} - -/// Creates a new Selector that may be Sync + Send. The selector will be run immediately and whenever any signal it reads changes. -/// -/// Selectors can be used to efficiently compute derived data from signals. -#[track_caller] -pub fn maybe_sync_selector>>( - mut f: impl FnMut() -> R + 'static, -) -> ReadOnlySignal { - let mut state = Signal:: { - inner: CopyValue::invalid(), - }; - let effect = Effect { - source: current_scope_id().expect("in a virtual dom"), - inner: CopyValue::invalid(), - }; - - { - EFFECT_STACK.with(|stack| stack.effects.write().push(effect)); - } - state.inner.value.set(SignalData { - subscribers: Default::default(), - update_any: schedule_update_any(), - value: f(), - effect_ref: get_effect_ref(), - }); - { - EFFECT_STACK.with(|stack| stack.effects.write().pop()); - } - - let invalid_id = effect.id(); - tracing::trace!("Creating effect: {:?}", invalid_id); - effect.inner.value.set(EffectInner { - callback: Box::new(move || { - let value = f(); - let changed = { - let old = state.inner.read(); - value != old.value - }; - if changed { - state.set(value) - } - }), - id: invalid_id, - }); - { - EFFECT_STACK.with(|stack| stack.effect_mapping.write().insert(invalid_id, effect)); - } - - ReadOnlySignal::new_maybe_sync(state) -} diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index ff34a75d2..25140182d 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -1,4 +1,4 @@ -use crate::{GlobalSelector, GlobalSignal, MappedSignal}; +use crate::{Effect, EffectInner, GlobalSelector, GlobalSignal, MappedSignal}; use std::{ cell::RefCell, marker::PhantomData, @@ -225,7 +225,9 @@ impl Signal { pub const fn global(constructor: fn() -> T) -> GlobalSignal { GlobalSignal::new(constructor) } +} +impl Signal { /// Creates a new global Signal that can be used in a global static. pub const fn global_selector(constructor: fn() -> T) -> GlobalSelector where @@ -233,6 +235,64 @@ impl Signal { { GlobalSelector::new(constructor) } + + /// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes. + /// + /// Selectors can be used to efficiently compute derived data from signals. + #[track_caller] + pub fn selector(f: impl FnMut() -> T + 'static) -> ReadOnlySignal { + Self::maybe_sync_selector(f) + } + + /// Creates a new Selector that may be Sync + Send. The selector will be run immediately and whenever any signal it reads changes. + /// + /// Selectors can be used to efficiently compute derived data from signals. + #[track_caller] + pub fn maybe_sync_selector>>( + mut f: impl FnMut() -> T + 'static, + ) -> ReadOnlySignal { + let mut state = Signal:: { + inner: CopyValue::invalid(), + }; + let effect = Effect { + source: current_scope_id().expect("in a virtual dom"), + inner: CopyValue::invalid(), + }; + + { + EFFECT_STACK.with(|stack| stack.effects.write().push(effect)); + } + state.inner.value.set(SignalData { + subscribers: Default::default(), + update_any: schedule_update_any(), + value: f(), + effect_ref: get_effect_ref(), + }); + { + EFFECT_STACK.with(|stack| stack.effects.write().pop()); + } + + let invalid_id = effect.id(); + tracing::trace!("Creating effect: {:?}", invalid_id); + effect.inner.value.set(EffectInner { + callback: Box::new(move || { + let value = f(); + let changed = { + let old = state.inner.read(); + value != old.value + }; + if changed { + state.set(value) + } + }), + id: invalid_id, + }); + { + EFFECT_STACK.with(|stack| stack.effect_mapping.write().insert(invalid_id, effect)); + } + + ReadOnlySignal::new_maybe_sync(state) + } } impl>> Signal {