From 9496853fbcb1d783cacb4c0c226579fa6092877c Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 8 Sep 2023 10:05:58 -0500 Subject: [PATCH 1/4] expose public methods for manipulating the global runtime --- packages/core/src/lib.rs | 11 ++++--- packages/core/src/runtime.rs | 56 +++++++++++++++++++++++++++++--- packages/core/src/virtual_dom.rs | 5 +++ 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 62e142f60..5b2f83305 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -32,6 +32,7 @@ pub(crate) mod innerlude { pub use crate::nodes::RenderReturn; pub use crate::nodes::*; pub use crate::properties::*; + pub use crate::runtime::{in_runtime, override_runtime, Runtime}; pub use crate::scheduler::*; pub use crate::scope_context::*; pub use crate::scopes::*; @@ -86,11 +87,11 @@ pub use crate::innerlude::{ pub mod prelude { pub use crate::innerlude::{ consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, has_context, - provide_context, provide_context_to_scope, provide_root_context, push_future, - remove_future, schedule_update_any, spawn, spawn_forever, suspend, throw, AnyValue, - Component, Element, Event, EventHandler, Fragment, IntoAttributeValue, LazyNodes, - Properties, Scope, ScopeId, ScopeState, Scoped, TaskId, Template, TemplateAttribute, - TemplateNode, Throw, VNode, VirtualDom, + in_runtime, override_runtime, provide_context, provide_context_to_scope, + provide_root_context, push_future, remove_future, schedule_update_any, spawn, + spawn_forever, suspend, throw, AnyValue, Component, Element, Event, EventHandler, Fragment, + IntoAttributeValue, LazyNodes, Properties, Runtime, Scope, ScopeId, ScopeState, Scoped, + TaskId, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom, }; } diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index b2b535830..ea518dbd2 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -7,6 +7,39 @@ thread_local! { static RUNTIMES: RefCell>> = RefCell::new(vec![]); } +/// Run some code within a runtime +pub fn in_runtime(runtime: Rc, f: impl FnOnce() -> R) -> R { + let _guard = RuntimeGuard::new(runtime); + f() +} + +/// Override the current runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime. +/// +/// ```rust +/// use dioxus::prelude::*; +/// +/// fn main() { +/// let virtual_dom = VirtualDom::new(app); +/// } +/// +/// fn app(cx: Scope) -> Element { +/// render!{ Component { runtime: Runtime::current().unwrap() } } +/// } +/// +/// // In a dynamic library +/// #[inline_props] +/// fn Component(cx: Scope, runtime: Rc) -> Element { +/// cx.use_hook(|| override_runtime(runtime.clone())); +/// } +/// ``` +pub fn override_runtime(runtime: Rc) { + RUNTIMES.with(|stack| { + let mut stack = stack.borrow_mut(); + stack.pop(); + stack.push(runtime); + }); +} + /// Pushes a new scope onto the stack pub(crate) fn push_runtime(runtime: Rc) { RUNTIMES.with(|stack| stack.borrow_mut().push(runtime)); @@ -41,7 +74,8 @@ where .flatten() } -pub(crate) struct Runtime { +/// A global runtime that is shared across all scopes that provides the async runtime and context API +pub struct Runtime { pub(crate) scope_contexts: RefCell>>, pub(crate) scheduler: Rc, @@ -63,6 +97,11 @@ impl Runtime { }) } + /// Get the current runtime + pub fn current() -> Option> { + RUNTIMES.with(|stack| stack.borrow().last().cloned()) + } + /// Create a scope context. This slab is synchronized with the scope slab. pub(crate) fn create_context_at(&self, id: ScopeId, context: ScopeContext) { let mut contexts = self.scope_contexts.borrow_mut(); @@ -77,16 +116,25 @@ impl Runtime { } /// Get the current scope id - pub fn current_scope_id(&self) -> Option { + pub(crate) fn current_scope_id(&self) -> Option { self.scope_stack.borrow().last().copied() } /// Get the context for any scope given its ID /// /// This is useful for inserting or removing contexts from a scope, or rendering out its root node - pub fn get_context(&self, id: ScopeId) -> Option> { + pub(crate) fn get_context(&self, id: ScopeId) -> Option> { Ref::filter_map(self.scope_contexts.borrow(), |contexts| { - contexts.get(id.0).and_then(|f| f.as_ref()) + match contexts.get(id.0) { + Some(context) => context.as_ref(), + _ => { + tracing::error!( + "Attempted to get context for scope that doesn't exist (id: {})", + id.0 + ); + None + } + } }) .ok() } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index a1def71d2..aee0e3d2e 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -658,6 +658,11 @@ impl VirtualDom { fn finalize(&mut self) -> Mutations { std::mem::take(&mut self.mutations) } + + /// Get the current runtime + pub fn runtime(&self) -> Rc { + self.runtime.clone() + } } impl Drop for VirtualDom { From 28d71624ef8ad9996c75907cdca7d3cce4bf4925 Mon Sep 17 00:00:00 2001 From: ealmloff Date: Sat, 9 Sep 2023 16:00:29 -0500 Subject: [PATCH 2/4] Restore context changes --- packages/core/src/runtime.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index ea518dbd2..d06818673 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -125,16 +125,7 @@ impl Runtime { /// This is useful for inserting or removing contexts from a scope, or rendering out its root node pub(crate) fn get_context(&self, id: ScopeId) -> Option> { Ref::filter_map(self.scope_contexts.borrow(), |contexts| { - match contexts.get(id.0) { - Some(context) => context.as_ref(), - _ => { - tracing::error!( - "Attempted to get context for scope that doesn't exist (id: {})", - id.0 - ); - None - } - } + contexts.get(id.0).and_then(|f| f.as_ref()) }) .ok() } From 083ccd765ca64a3b3d6a723448206fd3f0eb5f82 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 10 Sep 2023 13:23:29 -0500 Subject: [PATCH 3/4] fix formatting --- packages/core/src/runtime.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index d06818673..07aeb7c24 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -14,22 +14,24 @@ pub fn in_runtime(runtime: Rc, f: impl FnOnce() -> R) -> R { } /// Override the current runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime. -/// +/// /// ```rust /// use dioxus::prelude::*; -/// +/// /// fn main() { /// let virtual_dom = VirtualDom::new(app); /// } -/// +/// /// fn app(cx: Scope) -> Element { /// render!{ Component { runtime: Runtime::current().unwrap() } } /// } -/// +/// /// // In a dynamic library /// #[inline_props] -/// fn Component(cx: Scope, runtime: Rc) -> Element { +/// fn Component(cx: Scope, runtime: std::rc::Rc) -> Element { /// cx.use_hook(|| override_runtime(runtime.clone())); +/// +/// render! { div {} } /// } /// ``` pub fn override_runtime(runtime: Rc) { From ed9573094cd9da6ae6733ed511b02ad164f8c468 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 11 Sep 2023 15:13:29 -0500 Subject: [PATCH 4/4] fix ComponentProps partialeq --- packages/core/src/runtime.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index 07aeb7c24..4b9dcdab0 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -27,9 +27,19 @@ pub fn in_runtime(runtime: Rc, f: impl FnOnce() -> R) -> R { /// } /// /// // In a dynamic library -/// #[inline_props] -/// fn Component(cx: Scope, runtime: std::rc::Rc) -> Element { -/// cx.use_hook(|| override_runtime(runtime.clone())); +/// #[derive(Props)] +/// struct ComponentProps { +/// runtime: std::rc::Rc, +/// } +/// +/// impl PartialEq for ComponentProps { +/// fn eq(&self, _other: &Self) -> bool { +/// true +/// } +/// } +/// +/// fn Component(cx: Scope) -> Element { +/// cx.use_hook(|| override_runtime(cx.props.runtime.clone())); /// /// render! { div {} } /// }