mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-17 06:08:26 +00:00
Cleanup runtime code
This commit is contained in:
parent
8b9bf57c03
commit
3008870818
6 changed files with 97 additions and 118 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::{global_context::current_scope_id, runtime::with_runtime, ScopeId};
|
use crate::{global_context::current_scope_id, Runtime, ScopeId};
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
@ -211,13 +211,9 @@ impl<T> EventHandler<T> {
|
||||||
/// This borrows the event using a RefCell. Recursively calling a listener will cause a panic.
|
/// This borrows the event using a RefCell. Recursively calling a listener will cause a panic.
|
||||||
pub fn call(&self, event: T) {
|
pub fn call(&self, event: T) {
|
||||||
if let Some(callback) = self.callback.borrow_mut().as_mut() {
|
if let Some(callback) = self.callback.borrow_mut().as_mut() {
|
||||||
with_runtime(|rt| {
|
Runtime::with(|rt| rt.scope_stack.borrow_mut().push(self.origin));
|
||||||
rt.scope_stack.borrow_mut().push(self.origin);
|
|
||||||
});
|
|
||||||
callback(event);
|
callback(event);
|
||||||
with_runtime(|rt| {
|
Runtime::with(|rt| rt.scope_stack.borrow_mut().pop());
|
||||||
rt.scope_stack.borrow_mut().pop();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,37 +2,34 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use futures_util::Future;
|
use futures_util::Future;
|
||||||
|
|
||||||
use crate::{
|
use crate::{runtime::Runtime, Element, ScopeId, Task};
|
||||||
runtime::{with_current_scope, with_runtime},
|
|
||||||
Element, ScopeId, Task,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Get the current scope id
|
/// Get the current scope id
|
||||||
pub fn current_scope_id() -> Option<ScopeId> {
|
pub fn current_scope_id() -> Option<ScopeId> {
|
||||||
with_runtime(|rt| rt.current_scope_id()).flatten()
|
Runtime::with(|rt| rt.current_scope_id()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Check if the virtual dom is currently inside of the body of a component
|
/// Check if the virtual dom is currently inside of the body of a component
|
||||||
pub fn vdom_is_rendering() -> bool {
|
pub fn vdom_is_rendering() -> bool {
|
||||||
with_runtime(|rt| rt.rendering.get()).unwrap_or_default()
|
Runtime::with(|rt| rt.rendering.get()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume context from the current scope
|
/// Consume context from the current scope
|
||||||
pub fn try_consume_context<T: 'static + Clone>() -> Option<T> {
|
pub fn try_consume_context<T: 'static + Clone>() -> Option<T> {
|
||||||
with_current_scope(|cx| cx.consume_context::<T>()).flatten()
|
Runtime::with_current_scope(|cx| cx.consume_context::<T>()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume context from the current scope
|
/// Consume context from the current scope
|
||||||
pub fn consume_context<T: 'static + Clone>() -> T {
|
pub fn consume_context<T: 'static + Clone>() -> T {
|
||||||
with_current_scope(|cx| cx.consume_context::<T>())
|
Runtime::with_current_scope(|cx| cx.consume_context::<T>())
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_else(|| panic!("Could not find context {}", std::any::type_name::<T>()))
|
.unwrap_or_else(|| panic!("Could not find context {}", std::any::type_name::<T>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume context from the current scope
|
/// Consume context from the current scope
|
||||||
pub fn consume_context_from_scope<T: 'static + Clone>(scope_id: ScopeId) -> Option<T> {
|
pub fn consume_context_from_scope<T: 'static + Clone>(scope_id: ScopeId) -> Option<T> {
|
||||||
with_runtime(|rt| {
|
Runtime::with(|rt| {
|
||||||
rt.get_context(scope_id)
|
rt.get_context(scope_id)
|
||||||
.and_then(|cx| cx.consume_context::<T>())
|
.and_then(|cx| cx.consume_context::<T>())
|
||||||
})
|
})
|
||||||
|
@ -41,22 +38,22 @@ pub fn consume_context_from_scope<T: 'static + Clone>(scope_id: ScopeId) -> Opti
|
||||||
|
|
||||||
/// Check if the current scope has a context
|
/// Check if the current scope has a context
|
||||||
pub fn has_context<T: 'static + Clone>() -> Option<T> {
|
pub fn has_context<T: 'static + Clone>() -> Option<T> {
|
||||||
with_current_scope(|cx| cx.has_context::<T>()).flatten()
|
Runtime::with_current_scope(|cx| cx.has_context::<T>()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide context to the current scope
|
/// Provide context to the current scope
|
||||||
pub fn provide_context<T: 'static + Clone>(value: T) -> T {
|
pub fn provide_context<T: 'static + Clone>(value: T) -> T {
|
||||||
with_current_scope(|cx| cx.provide_context(value)).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.provide_context(value)).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide a context to the root scope
|
/// Provide a context to the root scope
|
||||||
pub fn provide_root_context<T: 'static + Clone>(value: T) -> Option<T> {
|
pub fn provide_root_context<T: 'static + Clone>(value: T) -> Option<T> {
|
||||||
with_current_scope(|cx| cx.provide_root_context(value))
|
Runtime::with_current_scope(|cx| cx.provide_root_context(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Suspends the current component
|
/// Suspends the current component
|
||||||
pub fn suspend() -> Option<Element> {
|
pub fn suspend() -> Option<Element> {
|
||||||
with_current_scope(|cx| {
|
Runtime::with_current_scope(|cx| {
|
||||||
cx.suspend();
|
cx.suspend();
|
||||||
});
|
});
|
||||||
None
|
None
|
||||||
|
@ -64,21 +61,21 @@ pub fn suspend() -> Option<Element> {
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
pub fn spawn(fut: impl Future<Output = ()> + 'static) -> Task {
|
pub fn spawn(fut: impl Future<Output = ()> + 'static) -> Task {
|
||||||
with_current_scope(|cx| cx.spawn(fut)).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.spawn(fut)).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
||||||
///
|
///
|
||||||
/// This is good for tasks that need to be run after the component has been dropped.
|
/// This is good for tasks that need to be run after the component has been dropped.
|
||||||
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
||||||
with_current_scope(|cx| cx.spawn_forever(fut))
|
Runtime::with_current_scope(|cx| cx.spawn_forever(fut))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Informs the scheduler that this task is no longer needed and should be removed.
|
/// Informs the scheduler that this task is no longer needed and should be removed.
|
||||||
///
|
///
|
||||||
/// This drops the task immediately.
|
/// This drops the task immediately.
|
||||||
pub fn remove_future(id: Task) {
|
pub fn remove_future(id: Task) {
|
||||||
with_current_scope(|cx| cx.remove_future(id));
|
Runtime::with_current_scope(|cx| cx.remove_future(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store a value between renders. The foundational hook for all other hooks.
|
/// Store a value between renders. The foundational hook for all other hooks.
|
||||||
|
@ -98,24 +95,24 @@ pub fn remove_future(id: Task) {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn use_hook<State: Clone + 'static>(initializer: impl FnOnce() -> State) -> State {
|
pub fn use_hook<State: Clone + 'static>(initializer: impl FnOnce() -> State) -> State {
|
||||||
with_current_scope(|cx| cx.use_hook(initializer)).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.use_hook(initializer)).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current render since the inception of this component
|
/// Get the current render since the inception of this component
|
||||||
///
|
///
|
||||||
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
||||||
pub fn generation() -> usize {
|
pub fn generation() -> usize {
|
||||||
with_current_scope(|cx| cx.generation()).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.generation()).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the parent of the current scope if it exists
|
/// Get the parent of the current scope if it exists
|
||||||
pub fn parent_scope() -> Option<ScopeId> {
|
pub fn parent_scope() -> Option<ScopeId> {
|
||||||
with_current_scope(|cx| cx.parent_id()).flatten()
|
Runtime::with_current_scope(|cx| cx.parent_id()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark the current scope as dirty, causing it to re-render
|
/// Mark the current scope as dirty, causing it to re-render
|
||||||
pub fn needs_update() {
|
pub fn needs_update() {
|
||||||
with_current_scope(|cx| cx.needs_update());
|
Runtime::with_current_scope(|cx| cx.needs_update());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule an update for the current component
|
/// Schedule an update for the current component
|
||||||
|
@ -124,7 +121,7 @@ pub fn needs_update() {
|
||||||
///
|
///
|
||||||
/// You should prefer [`schedule_update_any`] if you need to update multiple components.
|
/// You should prefer [`schedule_update_any`] if you need to update multiple components.
|
||||||
pub fn schedule_update() -> Arc<dyn Fn() + Send + Sync> {
|
pub fn schedule_update() -> Arc<dyn Fn() + Send + Sync> {
|
||||||
with_current_scope(|cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule an update for any component given its [`ScopeId`].
|
/// Schedule an update for any component given its [`ScopeId`].
|
||||||
|
@ -133,5 +130,5 @@ pub fn schedule_update() -> Arc<dyn Fn() + Send + Sync> {
|
||||||
///
|
///
|
||||||
/// Note: Unlike [`needs_update`], the function returned by this method will work outside of the dioxus runtime.
|
/// Note: Unlike [`needs_update`], the function returned by this method will work outside of the dioxus runtime.
|
||||||
pub fn schedule_update_any() -> Arc<dyn Fn(ScopeId) + Send + Sync> {
|
pub fn schedule_update_any() -> Arc<dyn Fn(ScopeId) + Send + Sync> {
|
||||||
with_current_scope(|cx| cx.schedule_update_any()).expect("to be in a dioxus runtime")
|
Runtime::with_current_scope(|cx| cx.schedule_update_any()).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,8 @@ pub use crate::innerlude::{
|
||||||
AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component, ComponentFunction,
|
AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component, ComponentFunction,
|
||||||
CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment, HasAttributes,
|
CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment, HasAttributes,
|
||||||
IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties, RenderReturn,
|
IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties, RenderReturn,
|
||||||
ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, VComponent, VNode,
|
Runtime, ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, VComponent,
|
||||||
VNodeInner, VPlaceholder, VText, VirtualDom, WriteMutations,
|
VNode, VNodeInner, VPlaceholder, VText, VirtualDom, WriteMutations,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The purpose of this module is to alleviate imports of many common types
|
/// The purpose of this module is to alleviate imports of many common types
|
||||||
|
|
|
@ -14,48 +14,6 @@ thread_local! {
|
||||||
static RUNTIMES: RefCell<Vec<Rc<Runtime>>> = RefCell::new(vec![]);
|
static RUNTIMES: RefCell<Vec<Rc<Runtime>>> = RefCell::new(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new scope onto the stack
|
|
||||||
pub(crate) fn push_runtime(runtime: Rc<Runtime>) {
|
|
||||||
RUNTIMES.with(|stack| stack.borrow_mut().push(runtime));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pops a scope off the stack
|
|
||||||
pub(crate) fn pop_runtime() {
|
|
||||||
RUNTIMES.with(|stack| stack.borrow_mut().pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs a function with the current runtime
|
|
||||||
pub(crate) fn with_runtime<F, R>(f: F) -> Option<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&Runtime) -> R,
|
|
||||||
{
|
|
||||||
RUNTIMES.with(|stack| {
|
|
||||||
let stack = stack.borrow();
|
|
||||||
stack.last().map(|r| f(r))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs a function with the current scope
|
|
||||||
pub(crate) fn with_current_scope<F, R>(f: F) -> Option<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&ScopeContext) -> R,
|
|
||||||
{
|
|
||||||
with_runtime(|runtime| {
|
|
||||||
runtime
|
|
||||||
.current_scope_id()
|
|
||||||
.and_then(|scope| runtime.get_context(scope).map(|sc| f(&sc)))
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs a function with the current scope
|
|
||||||
pub(crate) fn with_scope<F, R>(scope: ScopeId, f: F) -> Option<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&ScopeContext) -> R,
|
|
||||||
{
|
|
||||||
with_runtime(|runtime| runtime.get_context(scope).map(|sc| f(&sc))).flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A global runtime that is shared across all scopes that provides the async runtime and context API
|
/// A global runtime that is shared across all scopes that provides the async runtime and context API
|
||||||
pub struct Runtime {
|
pub struct Runtime {
|
||||||
pub(crate) scope_contexts: RefCell<Vec<Option<ScopeContext>>>,
|
pub(crate) scope_contexts: RefCell<Vec<Option<ScopeContext>>>,
|
||||||
|
@ -112,7 +70,7 @@ impl Runtime {
|
||||||
/// Call this function with the current scope set to the given scope
|
/// Call this function with the current scope set to the given scope
|
||||||
///
|
///
|
||||||
/// Useful in a limited number of scenarios, not public.
|
/// Useful in a limited number of scenarios, not public.
|
||||||
pub(crate) fn with_scope<O>(&self, id: ScopeId, f: impl FnOnce() -> O) -> O {
|
pub fn on_scope<O>(&self, id: ScopeId, f: impl FnOnce() -> O) -> O {
|
||||||
self.scope_stack.borrow_mut().push(id);
|
self.scope_stack.borrow_mut().push(id);
|
||||||
let o = f();
|
let o = f();
|
||||||
self.scope_stack.borrow_mut().pop();
|
self.scope_stack.borrow_mut().pop();
|
||||||
|
@ -128,6 +86,47 @@ impl Runtime {
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes a new scope onto the stack
|
||||||
|
pub(crate) fn push_runtime(runtime: Rc<Runtime>) {
|
||||||
|
RUNTIMES.with(|stack| stack.borrow_mut().push(runtime));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pops a scope off the stack
|
||||||
|
pub(crate) fn pop_runtime() {
|
||||||
|
RUNTIMES.with(|stack| stack.borrow_mut().pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a function with the current runtime
|
||||||
|
pub(crate) fn with<F, R>(f: F) -> Option<R>
|
||||||
|
where
|
||||||
|
F: FnOnce(&Runtime) -> R,
|
||||||
|
{
|
||||||
|
RUNTIMES.with(|stack| {
|
||||||
|
let stack = stack.borrow();
|
||||||
|
stack.last().map(|r| f(r))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a function with the current scope
|
||||||
|
pub(crate) fn with_current_scope<F, R>(f: F) -> Option<R>
|
||||||
|
where
|
||||||
|
F: FnOnce(&ScopeContext) -> R,
|
||||||
|
{
|
||||||
|
Self::with(|rt| {
|
||||||
|
rt.current_scope_id()
|
||||||
|
.and_then(|scope| rt.get_context(scope).map(|sc| f(&sc)))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a function with the current scope
|
||||||
|
pub(crate) fn with_scope<F, R>(scope: ScopeId, f: F) -> Option<R>
|
||||||
|
where
|
||||||
|
F: FnOnce(&ScopeContext) -> R,
|
||||||
|
{
|
||||||
|
Self::with(|rt| rt.get_context(scope).map(|sc| f(&sc))).flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A guard for a new runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime.
|
/// A guard for a new runtime. This must be used to override the current runtime when importing components from a dynamic library that has it's own runtime.
|
||||||
|
@ -166,24 +165,13 @@ pub struct RuntimeGuard(());
|
||||||
impl RuntimeGuard {
|
impl RuntimeGuard {
|
||||||
/// Create a new runtime guard that sets the current Dioxus runtime. The runtime will be reset when the guard is dropped
|
/// Create a new runtime guard that sets the current Dioxus runtime. The runtime will be reset when the guard is dropped
|
||||||
pub fn new(runtime: Rc<Runtime>) -> Self {
|
pub fn new(runtime: Rc<Runtime>) -> Self {
|
||||||
push_runtime(runtime);
|
Runtime::push_runtime(runtime);
|
||||||
Self(())
|
Self(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a function with a given runtime and scope in context
|
|
||||||
pub fn with<O>(runtime: Rc<Runtime>, scope: Option<ScopeId>, f: impl FnOnce() -> O) -> O {
|
|
||||||
let guard = Self::new(runtime.clone());
|
|
||||||
let o = match scope {
|
|
||||||
Some(scope) => Runtime::with_scope(&runtime, scope, f),
|
|
||||||
None => f(),
|
|
||||||
};
|
|
||||||
drop(guard);
|
|
||||||
o
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for RuntimeGuard {
|
impl Drop for RuntimeGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
pop_runtime();
|
Runtime::pop_runtime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::{
|
use crate::{innerlude::SchedulerMsg, Element, Runtime, ScopeId, Task};
|
||||||
innerlude::SchedulerMsg,
|
|
||||||
runtime::{with_runtime, with_scope},
|
|
||||||
Element, ScopeId, Task,
|
|
||||||
};
|
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
|
@ -53,7 +49,7 @@ impl ScopeContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sender(&self) -> futures_channel::mpsc::UnboundedSender<SchedulerMsg> {
|
fn sender(&self) -> futures_channel::mpsc::UnboundedSender<SchedulerMsg> {
|
||||||
with_runtime(|rt| rt.sender.clone()).unwrap()
|
Runtime::with(|rt| rt.sender.clone()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark this scope as dirty, and schedule a render for it.
|
/// Mark this scope as dirty, and schedule a render for it.
|
||||||
|
@ -107,7 +103,7 @@ impl ScopeContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut search_parent = self.parent_id;
|
let mut search_parent = self.parent_id;
|
||||||
let cur_runtime = with_runtime(|runtime: &crate::runtime::Runtime| {
|
let cur_runtime = Runtime::with(|runtime| {
|
||||||
while let Some(parent_id) = search_parent {
|
while let Some(parent_id) = search_parent {
|
||||||
let parent = runtime.get_context(parent_id).unwrap();
|
let parent = runtime.get_context(parent_id).unwrap();
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
|
@ -210,7 +206,7 @@ impl ScopeContext {
|
||||||
/// Note that you should be checking if the context existed before trying to provide a new one. Providing a context
|
/// Note that you should be checking if the context existed before trying to provide a new one. Providing a context
|
||||||
/// when a context already exists will swap the context out for the new one, which may not be what you want.
|
/// when a context already exists will swap the context out for the new one, which may not be what you want.
|
||||||
pub fn provide_root_context<T: 'static + Clone>(&self, context: T) -> T {
|
pub fn provide_root_context<T: 'static + Clone>(&self, context: T) -> T {
|
||||||
with_runtime(|runtime| {
|
Runtime::with(|runtime| {
|
||||||
runtime
|
runtime
|
||||||
.get_context(ScopeId::ROOT)
|
.get_context(ScopeId::ROOT)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -221,7 +217,7 @@ impl ScopeContext {
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
pub fn spawn(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
pub fn spawn(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
||||||
let id = with_runtime(|rt| rt.spawn(self.id, fut)).expect("Runtime to exist");
|
let id = Runtime::with(|rt| rt.spawn(self.id, fut)).expect("Runtime to exist");
|
||||||
self.spawned_tasks.borrow_mut().insert(id);
|
self.spawned_tasks.borrow_mut().insert(id);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -231,14 +227,14 @@ impl ScopeContext {
|
||||||
/// This is good for tasks that need to be run after the component has been dropped.
|
/// This is good for tasks that need to be run after the component has been dropped.
|
||||||
pub fn spawn_forever(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
pub fn spawn_forever(&self, fut: impl Future<Output = ()> + 'static) -> Task {
|
||||||
// The root scope will never be unmounted so we can just add the task at the top of the app
|
// The root scope will never be unmounted so we can just add the task at the top of the app
|
||||||
with_runtime(|rt| rt.spawn(ScopeId::ROOT, fut)).expect("Runtime to exist")
|
Runtime::with(|rt| rt.spawn(ScopeId::ROOT, fut)).expect("Runtime to exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Informs the scheduler that this task is no longer needed and should be removed.
|
/// Informs the scheduler that this task is no longer needed and should be removed.
|
||||||
///
|
///
|
||||||
/// This drops the task immediately.
|
/// This drops the task immediately.
|
||||||
pub fn remove_future(&self, id: Task) {
|
pub fn remove_future(&self, id: Task) {
|
||||||
with_runtime(|rt| rt.remove_task(id)).expect("Runtime to exist");
|
Runtime::with(|rt| rt.remove_task(id)).expect("Runtime to exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark this component as suspended and then return None
|
/// Mark this component as suspended and then return None
|
||||||
|
@ -303,7 +299,7 @@ impl ScopeContext {
|
||||||
impl Drop for ScopeContext {
|
impl Drop for ScopeContext {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Drop all spawned tasks
|
// Drop all spawned tasks
|
||||||
_ = with_runtime(|rt| {
|
_ = Runtime::with(|rt| {
|
||||||
for id in self.spawned_tasks.borrow().iter() {
|
for id in self.spawned_tasks.borrow().iter() {
|
||||||
rt.remove_task(*id);
|
rt.remove_task(*id);
|
||||||
}
|
}
|
||||||
|
@ -314,23 +310,23 @@ impl Drop for ScopeContext {
|
||||||
impl ScopeId {
|
impl ScopeId {
|
||||||
/// Get the current scope id
|
/// Get the current scope id
|
||||||
pub fn current_scope_id(self) -> Option<ScopeId> {
|
pub fn current_scope_id(self) -> Option<ScopeId> {
|
||||||
with_runtime(|rt| rt.current_scope_id()).flatten()
|
Runtime::with(|rt| rt.current_scope_id()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Check if the virtual dom is currently inside of the body of a component
|
/// Check if the virtual dom is currently inside of the body of a component
|
||||||
pub fn vdom_is_rendering(self) -> bool {
|
pub fn vdom_is_rendering(self) -> bool {
|
||||||
with_runtime(|rt| rt.rendering.get()).unwrap_or_default()
|
Runtime::with(|rt| rt.rendering.get()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume context from the current scope
|
/// Consume context from the current scope
|
||||||
pub fn consume_context<T: 'static + Clone>(self) -> Option<T> {
|
pub fn consume_context<T: 'static + Clone>(self) -> Option<T> {
|
||||||
with_scope(self, |cx| cx.consume_context::<T>()).flatten()
|
Runtime::with_scope(self, |cx| cx.consume_context::<T>()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume context from the current scope
|
/// Consume context from the current scope
|
||||||
pub fn consume_context_from_scope<T: 'static + Clone>(self, scope_id: ScopeId) -> Option<T> {
|
pub fn consume_context_from_scope<T: 'static + Clone>(self, scope_id: ScopeId) -> Option<T> {
|
||||||
with_runtime(|rt| {
|
Runtime::with(|rt| {
|
||||||
rt.get_context(scope_id)
|
rt.get_context(scope_id)
|
||||||
.and_then(|cx| cx.consume_context::<T>())
|
.and_then(|cx| cx.consume_context::<T>())
|
||||||
})
|
})
|
||||||
|
@ -339,17 +335,18 @@ impl ScopeId {
|
||||||
|
|
||||||
/// Check if the current scope has a context
|
/// Check if the current scope has a context
|
||||||
pub fn has_context<T: 'static + Clone>(self) -> Option<T> {
|
pub fn has_context<T: 'static + Clone>(self) -> Option<T> {
|
||||||
with_scope(self, |cx| cx.has_context::<T>()).flatten()
|
Runtime::with_scope(self, |cx| cx.has_context::<T>()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide context to the current scope
|
/// Provide context to the current scope
|
||||||
pub fn provide_context<T: 'static + Clone>(self, value: T) -> T {
|
pub fn provide_context<T: 'static + Clone>(self, value: T) -> T {
|
||||||
with_scope(self, |cx| cx.provide_context(value)).expect("to be in a dioxus runtime")
|
Runtime::with_scope(self, |cx| cx.provide_context(value))
|
||||||
|
.expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Suspends the current component
|
/// Suspends the current component
|
||||||
pub fn suspend(self) -> Option<Element> {
|
pub fn suspend(self) -> Option<Element> {
|
||||||
with_scope(self, |cx| {
|
Runtime::with_scope(self, |cx| {
|
||||||
cx.suspend();
|
cx.suspend();
|
||||||
});
|
});
|
||||||
None
|
None
|
||||||
|
@ -357,40 +354,40 @@ impl ScopeId {
|
||||||
|
|
||||||
/// Pushes the future onto the poll queue to be polled after the component renders.
|
/// Pushes the future onto the poll queue to be polled after the component renders.
|
||||||
pub fn push_future(self, fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
pub fn push_future(self, fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
||||||
with_scope(self, |cx| cx.spawn(fut))
|
Runtime::with_scope(self, |cx| cx.spawn(fut))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns the future but does not return the [`TaskId`]
|
/// Spawns the future but does not return the [`TaskId`]
|
||||||
pub fn spawn(self, fut: impl Future<Output = ()> + 'static) {
|
pub fn spawn(self, fut: impl Future<Output = ()> + 'static) {
|
||||||
with_scope(self, |cx| cx.spawn(fut));
|
Runtime::with_scope(self, |cx| cx.spawn(fut));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current render since the inception of this component
|
/// Get the current render since the inception of this component
|
||||||
///
|
///
|
||||||
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
||||||
pub fn generation(self) -> Option<usize> {
|
pub fn generation(self) -> Option<usize> {
|
||||||
with_scope(self, |cx| Some(cx.generation())).expect("to be in a dioxus runtime")
|
Runtime::with_scope(self, |cx| Some(cx.generation())).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the parent of the current scope if it exists
|
/// Get the parent of the current scope if it exists
|
||||||
pub fn parent_scope(self) -> Option<ScopeId> {
|
pub fn parent_scope(self) -> Option<ScopeId> {
|
||||||
with_scope(self, |cx| cx.parent_id()).flatten()
|
Runtime::with_scope(self, |cx| cx.parent_id()).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark the current scope as dirty, causing it to re-render
|
/// Mark the current scope as dirty, causing it to re-render
|
||||||
pub fn needs_update(self) {
|
pub fn needs_update(self) {
|
||||||
with_scope(self, |cx| cx.needs_update());
|
Runtime::with_scope(self, |cx| cx.needs_update());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a subscription that schedules a future render for the reference component. Unlike [`Self::needs_update`], this function will work outside of the dioxus runtime.
|
/// Create a subscription that schedules a future render for the reference component. Unlike [`Self::needs_update`], this function will work outside of the dioxus runtime.
|
||||||
///
|
///
|
||||||
/// ## Notice: you should prefer using [`dioxus_core::schedule_update_any`] and [`Self::scope_id`]
|
/// ## Notice: you should prefer using [`dioxus_core::schedule_update_any`] and [`Self::scope_id`]
|
||||||
pub fn schedule_update(&self) -> Arc<dyn Fn() + Send + Sync + 'static> {
|
pub fn schedule_update(&self) -> Arc<dyn Fn() + Send + Sync + 'static> {
|
||||||
with_scope(*self, |cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
Runtime::with_scope(*self, |cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the height of the current scope
|
/// Get the height of the current scope
|
||||||
pub fn height(self) -> u32 {
|
pub fn height(self) -> u32 {
|
||||||
with_scope(self, |cx| cx.height()).expect("to be in a dioxus runtime")
|
Runtime::with_scope(self, |cx| cx.height()).expect("to be in a dioxus runtime")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,12 @@ impl AssetHandlerRegistry {
|
||||||
responder: RequestAsyncResponder,
|
responder: RequestAsyncResponder,
|
||||||
) {
|
) {
|
||||||
if let Some(handler) = self.handlers.borrow().get(name) {
|
if let Some(handler) = self.handlers.borrow().get(name) {
|
||||||
// make sure the runtime is alive for the duration of the handler
|
// Push the runtime onto the stack
|
||||||
// We should do this for all the things - not just asset handlers
|
let _guard = RuntimeGuard::new(self.dom_rt.clone());
|
||||||
RuntimeGuard::with(self.dom_rt.clone(), Some(handler.scope), || {
|
|
||||||
(handler.f)(request, responder)
|
// And run the handler in the scope of the component that created it
|
||||||
});
|
self.dom_rt
|
||||||
|
.on_scope(handler.scope, || (handler.f)(request, responder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue