Use my old reactive system again
This commit is contained in:
parent
47cb10ccb0
commit
c2c4a4afe6
|
@ -16,7 +16,7 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
|
|||
});
|
||||
|
||||
let add_counter = move |_| {
|
||||
let id = *next_counter_id.get_untracked();
|
||||
let id = next_counter_id();
|
||||
let (read, write) = cx.create_signal(0);
|
||||
set_counters(|counters| counters.push((id, (read.clone(), write.clone()))));
|
||||
set_next_counter_id(|id| *id += 1);
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn map_keyed<'a, T, U, K>(
|
|||
where
|
||||
T: PartialEq + Clone + 'a,
|
||||
K: Eq + Hash,
|
||||
U: Clone,
|
||||
U: PartialEq + Clone,
|
||||
{
|
||||
// Previous state used for diffing.
|
||||
let mut items = Vec::new();
|
||||
|
|
|
@ -98,16 +98,6 @@ impl<'a> IntoChild<'a> for Vec<web_sys::Element> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoChild<'a> for ReadSignal<T>
|
||||
where
|
||||
T: Clone + IntoChild<'a>,
|
||||
{
|
||||
fn into_child(self, cx: Scope<'a>) -> Child<'a> {
|
||||
let modified_fn = cx.create_ref(move || self.get().clone().into_child(cx));
|
||||
Child::Fn(modified_fn)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, U> IntoChild<'a> for T
|
||||
where
|
||||
T: Fn() -> U + 'a,
|
||||
|
|
|
@ -73,7 +73,7 @@ fn class_expression(el: &web_sys::Element, class_name: &str, value: bool) {
|
|||
}
|
||||
|
||||
pub fn insert<'a>(
|
||||
cx: Scope,
|
||||
cx: Scope<'a>,
|
||||
parent: web_sys::Node,
|
||||
value: Child<'a>,
|
||||
before: Option<web_sys::Node>,
|
||||
|
|
|
@ -34,17 +34,17 @@ mod tests {
|
|||
let (a, set_a) = cx.create_signal(0);
|
||||
let (b, set_b) = cx.create_signal(0);
|
||||
|
||||
let c = cx.create_memo(|| *(&a)() + *(&b)());
|
||||
let c = cx.create_memo(|| a() + b());
|
||||
|
||||
assert_eq!(*c.get_untracked(), 0);
|
||||
assert_eq!(c(), 0);
|
||||
|
||||
set_a(|n| *n = 2);
|
||||
|
||||
assert_eq!(*c.get_untracked(), 2);
|
||||
assert_eq!(c(), 2);
|
||||
|
||||
set_b(|n| *n = 2);
|
||||
|
||||
assert_eq!(*c.get_untracked(), 4);
|
||||
assert_eq!(c(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,8 @@ mod tests {
|
|||
let (show_last_name, set_show_last_name) = cx.create_signal(true);
|
||||
|
||||
let out = cx.create_memo(move || {
|
||||
if *(&show_last_name)() {
|
||||
format!("{} {}", *(&first_name)(), *(&last_name)())
|
||||
if show_last_name() {
|
||||
format!("{} {}", first_name(), last_name())
|
||||
} else {
|
||||
(*(&first_name)()).to_string()
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ use std::{
|
|||
|
||||
pub type Scope<'a> = BoundedScope<'a, 'a>;
|
||||
|
||||
#[must_use = "Creating a Scope without calling its disposer will leak memory."]
|
||||
pub fn with_root_scope<'a>(f: impl FnOnce(Scope)) -> ScopeDisposer<'a> {
|
||||
let root = Box::leak(Box::new(RootContext::new()));
|
||||
create_scope(root, |cx| f(cx))
|
||||
}
|
||||
|
||||
#[must_use = "Creating a Scope without calling its disposer will leak memory."]
|
||||
pub fn create_scope<'disposer>(
|
||||
root_context: &'static RootContext,
|
||||
|
|
|
@ -71,7 +71,7 @@ impl<T: 'static> ReadSignal<T> {
|
|||
self.value()
|
||||
}
|
||||
|
||||
pub fn get_untracked(&self) -> ReadSignalRef<T> {
|
||||
pub(crate) fn get_untracked(&self) -> ReadSignalRef<T> {
|
||||
self.value()
|
||||
}
|
||||
|
||||
|
@ -138,28 +138,38 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> FnOnce<()> for &'a ReadSignal<T> {
|
||||
type Output = ReadSignalRef<'a, T>;
|
||||
impl<T> FnOnce<()> for ReadSignal<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
self.get().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> FnMut<()> for &'a ReadSignal<T> {
|
||||
impl<T> FnMut<()> for ReadSignal<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
self.get().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Fn<()> for &'a ReadSignal<T> {
|
||||
impl<T> Fn<()> for ReadSignal<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
self.get().clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SignalState<T> {
|
||||
pub(crate) value: RefCell<T>,
|
||||
pub(crate) t_value: RefCell<Option<T>>,
|
||||
pub(crate) subscriptions: RefCell<HashSet<Rc<EffectInner>>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,12 @@ use futures::{
|
|||
use crate::{BoundedScope, Effect, EffectDependency, ReadSignal, SuspenseContext};
|
||||
|
||||
impl<'a, 'b> BoundedScope<'a, 'b> {
|
||||
pub fn use_transition<F>(self) -> (ReadSignal<bool>, impl Fn())
|
||||
where
|
||||
F: Fn(),
|
||||
{
|
||||
if let Some(transition) = self.inner.root_context.transition {
|
||||
/* pub fn use_transition(self) -> (ReadSignal<bool>, impl Fn()) {
|
||||
todo!()
|
||||
/* if let Some(transition) = self.inner.root_context.transition {
|
||||
transition
|
||||
}
|
||||
}
|
||||
} */
|
||||
} */
|
||||
|
||||
/* pub fn start_transition(self, f: impl Fn()) {
|
||||
// If a transition is already running, run this function
|
||||
|
@ -77,9 +75,10 @@ impl TransitionState {
|
|||
}
|
||||
|
||||
pub fn complete(&self) -> bool {
|
||||
match &self.pending_resources {
|
||||
todo!()
|
||||
/* match &self.pending_resources {
|
||||
Some(_) => !self.pending(),
|
||||
None => false,
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
use leptos_reactive::{with_root_scope, Scope};
|
||||
|
||||
#[test]
|
||||
fn effect_runs() {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(-1);
|
||||
|
||||
// simulate an arbitrary side effect
|
||||
let b = Rc::new(RefCell::new(String::new()));
|
||||
|
||||
cx.create_effect({
|
||||
let b = b.clone();
|
||||
move || {
|
||||
let formatted = format!("Value is {}", a());
|
||||
*b.borrow_mut() = formatted;
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(b.borrow().as_str(), "Value is -1");
|
||||
|
||||
set_a(|a| *a = 1);
|
||||
|
||||
assert_eq!(b.borrow().as_str(), "Value is 1");
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn effect_tracks_memo() {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(-1);
|
||||
let b = cx.create_memo(move || format!("Value is {}", a()));
|
||||
|
||||
// simulate an arbitrary side effect
|
||||
let c = Rc::new(RefCell::new(String::new()));
|
||||
|
||||
cx.create_effect({
|
||||
let c = c.clone();
|
||||
move || {
|
||||
*c.borrow_mut() = b();
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(b().as_str(), "Value is -1");
|
||||
assert_eq!(c.borrow().as_str(), "Value is -1");
|
||||
|
||||
set_a(|a| *a = 1);
|
||||
|
||||
assert_eq!(b().as_str(), "Value is 1");
|
||||
assert_eq!(c.borrow().as_str(), "Value is 1");
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn untrack_mutes_effect() {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(-1);
|
||||
|
||||
// simulate an arbitrary side effect
|
||||
let b = Rc::new(RefCell::new(String::new()));
|
||||
|
||||
cx.create_effect({
|
||||
let b = b.clone();
|
||||
move || {
|
||||
let formatted = format!("Value is {}", cx.untrack(a));
|
||||
*b.borrow_mut() = formatted;
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(a(), -1);
|
||||
assert_eq!(b.borrow().as_str(), "Value is -1");
|
||||
|
||||
set_a(|a| *a = 1);
|
||||
|
||||
assert_eq!(a(), 1);
|
||||
assert_eq!(b.borrow().as_str(), "Value is -1");
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
use leptos_reactive::{with_root_scope, Scope};
|
||||
|
||||
#[test]
|
||||
fn basic_signal() {
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(0);
|
||||
assert_eq!(a(), 0);
|
||||
set_a(|a| *a = 5);
|
||||
assert_eq!(a(), 5);
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_signals() {
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(0);
|
||||
let (b, set_b) = cx.create_signal(0);
|
||||
let c = move || a() + b();
|
||||
assert_eq!(c(), 0);
|
||||
set_a(|a| *a = 5);
|
||||
assert_eq!(c(), 5);
|
||||
set_b(|b| *b = 1);
|
||||
assert_eq!(c(), 6);
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_memo() {
|
||||
let d = with_root_scope(|cx| {
|
||||
let a = cx.create_memo(|| 5);
|
||||
assert_eq!(a(), 5);
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memo_with_computed_value() {
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(0);
|
||||
let (b, set_b) = cx.create_signal(0);
|
||||
let c = cx.create_memo(move || a() + b());
|
||||
assert_eq!(c(), 0);
|
||||
set_a(|a| *a = 5);
|
||||
assert_eq!(c(), 5);
|
||||
set_b(|b| *b = 1);
|
||||
assert_eq!(c(), 6);
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_memos() {
|
||||
let d = with_root_scope(|cx| {
|
||||
let (a, set_a) = cx.create_signal(0);
|
||||
let (b, set_b) = cx.create_signal(0);
|
||||
let c = cx.create_memo(move || a() + b());
|
||||
let d = cx.create_memo(move || c() * 2);
|
||||
let e = cx.create_memo(move || d() + 1);
|
||||
assert_eq!(d(), 0);
|
||||
set_a(|a| *a = 5);
|
||||
assert_eq!(c(), 5);
|
||||
assert_eq!(d(), 10);
|
||||
assert_eq!(e(), 11);
|
||||
set_b(|b| *b = 1);
|
||||
assert_eq!(c(), 6);
|
||||
assert_eq!(d(), 12);
|
||||
assert_eq!(e(), 13);
|
||||
});
|
||||
unsafe { d.dispose() }
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use leptos_core as leptos;
|
||||
use leptos_dom::IntoChild;
|
||||
use leptos_leptos_reactive::Scope;
|
||||
use leptos_macro::{component, Props};
|
||||
use leptos_reactive::Scope;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
pub struct RouterProps<C, D>
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
|||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use crate::{Observer, RootContext, Scope, State, SuspenseContextType, Update, WeakSignalState};
|
||||
use crate::{Observer, RootContext, Scope, State, SuspenseContext, Update, WeakSignalState};
|
||||
|
||||
pub(crate) type Source = WeakSignalState;
|
||||
|
||||
|
@ -30,7 +30,7 @@ pub(crate) trait AnyComputation {
|
|||
|
||||
fn pure(&self) -> bool;
|
||||
|
||||
fn suspense(&self) -> Option<&SuspenseContextType>;
|
||||
fn suspense(&self) -> Option<&SuspenseContext>;
|
||||
|
||||
fn updated_at(&self) -> Option<Update>;
|
||||
|
||||
|
@ -104,7 +104,7 @@ pub struct ComputationInner<T> {
|
|||
updated_at: Cell<Update>,
|
||||
pure: Cell<bool>,
|
||||
user: Cell<bool>,
|
||||
suspense: RefCell<Option<SuspenseContextType>>,
|
||||
suspense: RefCell<Option<SuspenseContext>>,
|
||||
}
|
||||
|
||||
impl<T> AnyComputation for Computation<T> {
|
||||
|
@ -152,7 +152,7 @@ impl<T> AnyComputation for Computation<T> {
|
|||
*self.inner.t_state.borrow_mut() = state;
|
||||
}
|
||||
|
||||
fn suspense(&self) -> Option<&SuspenseContextType> {
|
||||
fn suspense(&self) -> Option<&SuspenseContext> {
|
||||
todo!() //self.inner.suspense.borrow().as_ref()
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,13 @@ use std::any::{Any, TypeId};
|
|||
use crate::{BoundedScope, ScopeInner};
|
||||
|
||||
impl<'a, 'b> BoundedScope<'a, 'b> {
|
||||
pub fn provide_context<T: 'static>(&'a self, value: T) {
|
||||
pub fn provide_context<T: 'static>(self, value: T) {
|
||||
let id = value.type_id();
|
||||
let value = self.inner.arena.alloc(value);
|
||||
self.inner.context.borrow_mut().insert(id, &*value);
|
||||
}
|
||||
|
||||
pub fn use_context<T: 'static>(&'a self) -> Option<&T> {
|
||||
pub fn use_context<T: 'static>(self) -> Option<&'a T> {
|
||||
self.inner.use_context()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,16 @@ impl<'a, 'b> BoundedScope<'a, 'b> {
|
|||
pub fn create_effect<T>(self, effect_fn: impl FnMut(Option<&T>) -> T + 'a)
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.create_effect_with_init(effect_fn, None)
|
||||
}
|
||||
|
||||
pub fn create_effect_with_init<T>(
|
||||
self,
|
||||
effect_fn: impl FnMut(Option<&T>) -> T + 'a,
|
||||
init: Option<T>,
|
||||
) where
|
||||
T: 'static,
|
||||
{
|
||||
let f: Box<dyn FnMut(Option<&T>) -> T + 'a> = Box::new(effect_fn);
|
||||
// SAFETY: Memo will be cleaned up when the Scope lifetime 'a is over,
|
||||
|
@ -13,7 +23,7 @@ impl<'a, 'b> BoundedScope<'a, 'b> {
|
|||
// This is necessary to allow &'a Signal<_> etc. to be moved into F
|
||||
let f: Box<dyn FnMut(Option<&T>) -> T + 'static> = unsafe { std::mem::transmute(f) };
|
||||
|
||||
let c = Computation::new(self, f, None, false);
|
||||
let c = Computation::new(self, f, init, false);
|
||||
// TODO suspense piece here
|
||||
c.set_user(true);
|
||||
let root = self.root_context();
|
||||
|
|
|
@ -63,6 +63,41 @@ impl<'a, 'b> BoundedScope<'a, 'b> {
|
|||
pub fn untrack<T>(&self, f: impl FnOnce() -> T) -> T {
|
||||
self.inner.root_context.untrack(f)
|
||||
}
|
||||
|
||||
pub fn child_scope<F>(self, f: F) -> ScopeDisposer<'a>
|
||||
where
|
||||
F: for<'child_lifetime> FnOnce(BoundedScope<'child_lifetime, 'a>),
|
||||
{
|
||||
let mut child = ScopeInner::new(self.inner.root_context);
|
||||
// SAFETY: The only fields that are accessed on self from child is `context` which does not
|
||||
// have any lifetime annotations.
|
||||
child.parent = Some(unsafe { &*(self.inner as *const _) });
|
||||
let boxed = Box::new(child);
|
||||
let ptr = Box::into_raw(boxed);
|
||||
|
||||
let key = self
|
||||
.inner
|
||||
.children
|
||||
.borrow_mut()
|
||||
// SAFETY: None of the fields of ptr are accessed through child_scopes therefore we can
|
||||
// safely transmute the lifetime.
|
||||
.insert(unsafe { std::mem::transmute(ptr) });
|
||||
|
||||
// SAFETY: the address of the cx lives as long as 'a because:
|
||||
// - It is allocated on the heap and therefore has a stable address.
|
||||
// - self.child_cx is append only. That means that the Box<cx> will not be dropped until Self is
|
||||
// dropped.
|
||||
f(unsafe { Scope::new(&*ptr) });
|
||||
// ^^^ -> `ptr` is still accessible here after call to f.
|
||||
ScopeDisposer::new(move || unsafe {
|
||||
let cx = self.inner.children.borrow_mut().remove(key).unwrap();
|
||||
// SAFETY: Safe because ptr created using Box::into_raw and closure cannot live longer
|
||||
// than 'a.
|
||||
let cx = Box::from_raw(cx);
|
||||
// SAFETY: Outside of call to f.
|
||||
cx.dispose();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ScopeInner<'a> {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
Accessor, AnyComputation, AnySignalState, Observer, Pending, ReadSignalRef, RootContext,
|
||||
Source, State, SuspenseContextType, Update, WeakSignalState,
|
||||
Source, State, SuspenseContext, Update, WeakSignalState,
|
||||
};
|
||||
|
||||
pub struct Memo<T>
|
||||
|
@ -236,7 +236,7 @@ where
|
|||
self.t_state.set(state);
|
||||
}
|
||||
|
||||
fn suspense(&self) -> Option<&SuspenseContextType> {
|
||||
fn suspense(&self) -> Option<&SuspenseContext> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ impl<'a, 'b> BoundedScope<'a, 'b> {
|
|||
/// `([ReadSignal](crate::ReadSignal), [WriteSignal](crate::WriteSignal)`
|
||||
/// pair. This is the basic building block of reactivity.
|
||||
/// ```
|
||||
/// # use reactive::{create_scope, RootContext, Scope};
|
||||
/// # use leptos_reactive::{create_scope, RootContext, Scope};
|
||||
/// # let root = Box::leak(Box::new(RootContext::new()));
|
||||
/// # let _ = create_scope(root, |cx| {
|
||||
/// let (a, set_a) = cx.create_signal(0);
|
||||
|
@ -63,7 +63,7 @@ impl<'a, 'b> BoundedScope<'a, 'b> {
|
|||
/// takes the previous value of the memo as its argument (as `Option<T>`, as it is `None`
|
||||
/// the first time the memo is read.)
|
||||
/// ```
|
||||
/// # use reactive::{create_scope, RootContext, Scope};
|
||||
/// # use leptos_reactive::{create_scope, RootContext, Scope};
|
||||
/// # let root = Box::leak(Box::new(RootContext::new()));
|
||||
/// # let _ = create_scope(root, |cx| {
|
||||
/// let (a, set_a) = cx.create_signal(0);
|
||||
|
|
|
@ -324,3 +324,19 @@ where
|
|||
WeakSignalState(self.state.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for ReadSignal<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Rc::ptr_eq(&self.state, &other.state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for ReadSignal<T> {}
|
||||
|
||||
impl<T> PartialEq for WriteSignal<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Weak::ptr_eq(&self.state, &other.state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for WriteSignal<T> {}
|
||||
|
|
|
@ -1 +1,29 @@
|
|||
pub struct SuspenseContextType {}
|
||||
use crate::{ReadSignal, Scope, WriteSignal};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SuspenseContext {
|
||||
pending_resources: ReadSignal<usize>,
|
||||
set_pending_resources: WriteSignal<usize>,
|
||||
}
|
||||
|
||||
impl SuspenseContext {
|
||||
pub fn new(cx: Scope) -> Self {
|
||||
let (pending_resources, set_pending_resources) = cx.create_signal_owned(0);
|
||||
Self {
|
||||
pending_resources,
|
||||
set_pending_resources,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn increment(&self) {
|
||||
self.set_pending_resources.update(|n| *n += 1);
|
||||
}
|
||||
|
||||
pub fn decrement(&self) {
|
||||
self.set_pending_resources.update(|n| *n -= 1);
|
||||
}
|
||||
|
||||
pub fn ready(&self) -> bool {
|
||||
*self.pending_resources.get() == 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use reactive::Scope;
|
||||
use leptos_reactive::Scope;
|
||||
|
||||
fn with_testing_scope(f: impl FnOnce(Scope)) {
|
||||
use reactive::{create_scope, RootContext};
|
||||
use leptos_reactive::{create_scope, RootContext};
|
||||
let root = Box::leak(Box::new(RootContext::new()));
|
||||
let _ = create_scope(root, |cx| f(cx));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use reactive::Scope;
|
||||
use leptos_reactive::Scope;
|
||||
|
||||
fn with_testing_scope(f: impl FnOnce(Scope)) {
|
||||
use reactive::{create_scope, RootContext};
|
||||
use leptos_reactive::{create_scope, RootContext};
|
||||
let root = Box::leak(Box::new(RootContext::new()));
|
||||
let _ = create_scope(root, |cx| f(cx));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue