mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Better expect
error messages (#2629)
* Replace expect error messages * Change message * Create RuntimeError struct * Pass error through core methods * Fix use of Runtime::current in signals package * Fix tests * Add #[track_caller] for better error output and fix maybe_with_rt * provide a help message along with RuntimeError --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
parent
9167cd9dec
commit
d07e81005f
12 changed files with 165 additions and 63 deletions
|
@ -167,7 +167,7 @@ where
|
|||
error.context.push(Rc::new(AdditionalErrorContext {
|
||||
backtrace: Backtrace::capture(),
|
||||
context: Box::new(context()),
|
||||
scope: current_scope_id(),
|
||||
scope: current_scope_id().ok(),
|
||||
}));
|
||||
Err(error)
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ impl<Args: 'static, Ret: 'static> Callback<Args, Ret> {
|
|||
));
|
||||
Self {
|
||||
callback,
|
||||
origin: current_scope_id().expect("to be in a dioxus runtime"),
|
||||
origin: current_scope_id().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,7 +409,7 @@ impl<Args: 'static, Ret: 'static> Callback<Args, Ret> {
|
|||
as Rc<RefCell<dyn FnMut(Args) -> Ret>>));
|
||||
Self {
|
||||
callback,
|
||||
origin: current_scope_id().expect("to be in a dioxus runtime"),
|
||||
origin: current_scope_id().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,7 +427,7 @@ impl<Args: 'static, Ret: 'static> Callback<Args, Ret> {
|
|||
value
|
||||
})
|
||||
})
|
||||
.expect("Callback must be called from within the dioxus runtime")
|
||||
.unwrap()
|
||||
} else {
|
||||
panic!("Callback was manually dropped")
|
||||
}
|
||||
|
|
|
@ -91,6 +91,6 @@ pub fn current_owner<S: AnyStorage>() -> Owner<S> {
|
|||
impl ScopeId {
|
||||
/// Get the owner for the current scope.
|
||||
pub fn owner<S: AnyStorage>(self) -> Owner<S> {
|
||||
Runtime::with_scope(self, |cx| cx.owner::<S>()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_scope(self, |cx| cx.owner::<S>()).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
use crate::runtime::RuntimeError;
|
||||
use crate::{innerlude::SuspendedFuture, runtime::Runtime, CapturedError, Element, ScopeId, Task};
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Get the current scope id
|
||||
pub fn current_scope_id() -> Option<ScopeId> {
|
||||
Runtime::with(|rt| rt.current_scope_id()).flatten()
|
||||
pub fn current_scope_id() -> Result<ScopeId, RuntimeError> {
|
||||
Runtime::with(|rt| rt.current_scope_id().ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or(RuntimeError::new())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -31,19 +35,20 @@ pub fn vdom_is_rendering() -> bool {
|
|||
/// }
|
||||
/// ```
|
||||
pub fn throw_error(error: impl Into<CapturedError> + 'static) {
|
||||
current_scope_id()
|
||||
.expect("to be in a dioxus runtime")
|
||||
.throw_error(error)
|
||||
current_scope_id().unwrap().throw_error(error)
|
||||
}
|
||||
|
||||
/// Consume context from the current scope
|
||||
pub fn try_consume_context<T: 'static + Clone>() -> Option<T> {
|
||||
Runtime::with_current_scope(|cx| cx.consume_context::<T>()).flatten()
|
||||
Runtime::with_current_scope(|cx| cx.consume_context::<T>())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Consume context from the current scope
|
||||
pub fn consume_context<T: 'static + Clone>() -> T {
|
||||
Runtime::with_current_scope(|cx| cx.consume_context::<T>())
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_else(|| panic!("Could not find context {}", std::any::type_name::<T>()))
|
||||
}
|
||||
|
@ -54,23 +59,25 @@ pub fn consume_context_from_scope<T: 'static + Clone>(scope_id: ScopeId) -> Opti
|
|||
rt.get_state(scope_id)
|
||||
.and_then(|cx| cx.consume_context::<T>())
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Check if the current scope has a context
|
||||
pub fn has_context<T: 'static + Clone>() -> Option<T> {
|
||||
Runtime::with_current_scope(|cx| cx.has_context::<T>()).flatten()
|
||||
Runtime::with_current_scope(|cx| cx.has_context::<T>())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Provide context to the current scope
|
||||
pub fn provide_context<T: 'static + Clone>(value: T) -> T {
|
||||
Runtime::with_current_scope(|cx| cx.provide_context(value)).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.provide_context(value)).unwrap()
|
||||
}
|
||||
|
||||
/// Provide a context to the root scope
|
||||
pub fn provide_root_context<T: 'static + Clone>(value: T) -> T {
|
||||
Runtime::with_current_scope(|cx| cx.provide_root_context(value))
|
||||
.expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.provide_root_context(value)).unwrap()
|
||||
}
|
||||
|
||||
/// Suspended the current component on a specific task and then return None
|
||||
|
@ -108,7 +115,7 @@ pub fn suspend(task: Task) -> Element {
|
|||
///
|
||||
#[doc = include_str!("../docs/common_spawn_errors.md")]
|
||||
pub fn spawn_isomorphic(fut: impl Future<Output = ()> + 'static) -> Task {
|
||||
Runtime::with_current_scope(|cx| cx.spawn_isomorphic(fut)).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.spawn_isomorphic(fut)).unwrap()
|
||||
}
|
||||
|
||||
/// Spawns the future but does not return the [`Task`]. This task will automatically be canceled when the component is dropped.
|
||||
|
@ -134,12 +141,12 @@ pub fn spawn_isomorphic(fut: impl Future<Output = ()> + 'static) -> Task {
|
|||
///
|
||||
#[doc = include_str!("../docs/common_spawn_errors.md")]
|
||||
pub fn spawn(fut: impl Future<Output = ()> + 'static) -> Task {
|
||||
Runtime::with_current_scope(|cx| cx.spawn(fut)).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.spawn(fut)).unwrap()
|
||||
}
|
||||
|
||||
/// Queue an effect to run after the next render. You generally shouldn't need to interact with this function directly. [use_effect](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_effect.html) will call this function for you.
|
||||
pub fn queue_effect(f: impl FnOnce() + 'static) {
|
||||
Runtime::with_current_scope(|cx| cx.queue_effect(f)).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.queue_effect(f)).unwrap()
|
||||
}
|
||||
|
||||
/// Spawn a future that Dioxus won't clean up when this component is unmounted
|
||||
|
@ -195,7 +202,7 @@ pub fn queue_effect(f: impl FnOnce() + 'static) {
|
|||
///
|
||||
#[doc = include_str!("../docs/common_spawn_errors.md")]
|
||||
pub fn spawn_forever(fut: impl Future<Output = ()> + 'static) -> Option<Task> {
|
||||
Runtime::with_scope(ScopeId::ROOT, |cx| cx.spawn(fut))
|
||||
Runtime::with_scope(ScopeId::ROOT, |cx| cx.spawn(fut)).ok()
|
||||
}
|
||||
|
||||
/// Informs the scheduler that this task is no longer needed and should be removed.
|
||||
|
@ -248,30 +255,33 @@ pub fn remove_future(id: Task) {
|
|||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn use_hook<State: Clone + 'static>(initializer: impl FnOnce() -> State) -> State {
|
||||
Runtime::with_current_scope(|cx| cx.use_hook(initializer)).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.use_hook(initializer)).unwrap()
|
||||
}
|
||||
|
||||
/// Get the current render since the inception of this component
|
||||
///
|
||||
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
||||
pub fn generation() -> usize {
|
||||
Runtime::with_current_scope(|cx| cx.generation()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.generation()).unwrap()
|
||||
}
|
||||
|
||||
/// Get the parent of the current scope if it exists
|
||||
pub fn parent_scope() -> Option<ScopeId> {
|
||||
Runtime::with_current_scope(|cx| cx.parent_id()).flatten()
|
||||
Runtime::with_current_scope(|cx| cx.parent_id())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Mark the current scope as dirty, causing it to re-render
|
||||
pub fn needs_update() {
|
||||
Runtime::with_current_scope(|cx| cx.needs_update());
|
||||
let _ = Runtime::with_current_scope(|cx| cx.needs_update());
|
||||
}
|
||||
|
||||
/// Mark the current scope as dirty, causing it to re-render
|
||||
pub fn needs_update_any(id: ScopeId) {
|
||||
Runtime::with_current_scope(|cx| cx.needs_update_any(id));
|
||||
let _ = Runtime::with_current_scope(|cx| cx.needs_update_any(id));
|
||||
}
|
||||
|
||||
/// Schedule an update for the current component
|
||||
|
@ -280,7 +290,7 @@ pub fn needs_update_any(id: ScopeId) {
|
|||
///
|
||||
/// You should prefer [`schedule_update_any`] if you need to update multiple components.
|
||||
pub fn schedule_update() -> Arc<dyn Fn() + Send + Sync> {
|
||||
Runtime::with_current_scope(|cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.schedule_update()).unwrap()
|
||||
}
|
||||
|
||||
/// Schedule an update for any component given its [`ScopeId`].
|
||||
|
@ -289,7 +299,7 @@ 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.
|
||||
pub fn schedule_update_any() -> Arc<dyn Fn(ScopeId) + Send + Sync> {
|
||||
Runtime::with_current_scope(|cx| cx.schedule_update_any()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_current_scope(|cx| cx.schedule_update_any()).unwrap()
|
||||
}
|
||||
|
||||
/// Creates a callback that will be run before the component is removed.
|
||||
|
@ -393,12 +403,12 @@ pub fn use_after_render(f: impl FnMut() + 'static) {
|
|||
/// This is a hook and will always run, so you can't unschedule it
|
||||
/// Will run for every progression of suspense, though this might change in the future
|
||||
pub fn before_render(f: impl FnMut() + 'static) {
|
||||
Runtime::with_current_scope(|cx| cx.push_before_render(f));
|
||||
let _ = Runtime::with_current_scope(|cx| cx.push_before_render(f));
|
||||
}
|
||||
|
||||
/// Push a function to be run after the render is complete, even if it didn't complete successfully
|
||||
pub fn after_render(f: impl FnMut() + 'static) {
|
||||
Runtime::with_current_scope(|cx| cx.push_after_render(f));
|
||||
let _ = Runtime::with_current_scope(|cx| cx.push_after_render(f));
|
||||
}
|
||||
|
||||
/// Use a hook with a cleanup function
|
||||
|
|
|
@ -130,9 +130,11 @@ pub fn verify_component_called_as_component<C: ComponentFunction<P, M>, P, M>(co
|
|||
}
|
||||
let component_name = Runtime::with(|rt| {
|
||||
current_scope_id()
|
||||
.ok()
|
||||
.and_then(|id| rt.get_state(id))
|
||||
.map(|scope| scope.name)
|
||||
})
|
||||
.ok()
|
||||
.flatten();
|
||||
|
||||
// If we are in a component, and the type name is the same as the active component name, then we can just return
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
};
|
||||
use slotmap::DefaultKey;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
use std::{
|
||||
cell::{Cell, Ref, RefCell},
|
||||
rc::Rc,
|
||||
|
@ -66,8 +67,10 @@ impl Runtime {
|
|||
}
|
||||
|
||||
/// Get the current runtime
|
||||
pub fn current() -> Option<Rc<Self>> {
|
||||
RUNTIMES.with(|stack| stack.borrow().last().cloned())
|
||||
pub fn current() -> Result<Rc<Self>, RuntimeError> {
|
||||
RUNTIMES
|
||||
.with(|stack| stack.borrow().last().cloned())
|
||||
.ok_or(RuntimeError::new())
|
||||
}
|
||||
|
||||
/// Create a scope context. This slab is synchronized with the scope slab.
|
||||
|
@ -106,8 +109,12 @@ impl Runtime {
|
|||
}
|
||||
|
||||
/// Get the current scope id
|
||||
pub(crate) fn current_scope_id(&self) -> Option<ScopeId> {
|
||||
self.scope_stack.borrow().last().copied()
|
||||
pub(crate) fn current_scope_id(&self) -> Result<ScopeId, RuntimeError> {
|
||||
self.scope_stack
|
||||
.borrow()
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(RuntimeError { _priv: () })
|
||||
}
|
||||
|
||||
/// Call this function with the current scope set to the given scope
|
||||
|
@ -190,22 +197,31 @@ impl Runtime {
|
|||
}
|
||||
|
||||
/// Runs a function with the current runtime
|
||||
pub(crate) fn with<R>(f: impl FnOnce(&Runtime) -> R) -> Option<R> {
|
||||
pub(crate) fn with<R>(f: impl FnOnce(&Runtime) -> R) -> Result<R, RuntimeError> {
|
||||
Self::current().map(|r| f(&r))
|
||||
}
|
||||
|
||||
/// Runs a function with the current scope
|
||||
pub(crate) fn with_current_scope<R>(f: impl FnOnce(&Scope) -> R) -> Option<R> {
|
||||
pub(crate) fn with_current_scope<R>(f: impl FnOnce(&Scope) -> R) -> Result<R, RuntimeError> {
|
||||
Self::with(|rt| {
|
||||
rt.current_scope_id()
|
||||
.ok()
|
||||
.and_then(|scope| rt.get_state(scope).map(|sc| f(&sc)))
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or(RuntimeError::new())
|
||||
}
|
||||
|
||||
/// Runs a function with the current scope
|
||||
pub(crate) fn with_scope<R>(scope: ScopeId, f: impl FnOnce(&Scope) -> R) -> Option<R> {
|
||||
Self::with(|rt| rt.get_state(scope).map(|sc| f(&sc))).flatten()
|
||||
pub(crate) fn with_scope<R>(
|
||||
scope: ScopeId,
|
||||
f: impl FnOnce(&Scope) -> R,
|
||||
) -> Result<R, RuntimeError> {
|
||||
Self::with(|rt| rt.get_state(scope).map(|sc| f(&sc)))
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or(RuntimeError::new())
|
||||
}
|
||||
|
||||
/// Finish a render. This will mark all effects as ready to run and send the render signal.
|
||||
|
@ -279,3 +295,61 @@ impl Drop for RuntimeGuard {
|
|||
Runtime::pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// Missing Dioxus runtime error.
|
||||
pub struct RuntimeError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl RuntimeError {
|
||||
#[inline(always)]
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { _priv: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RuntimeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("RuntimeError").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RuntimeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Must be called from inside a Dioxus runtime.
|
||||
|
||||
Help: Some APIs in dioxus require a global runtime to be present.
|
||||
If you are calling one of these APIs from outside of a dioxus runtime
|
||||
(typically in a web-sys closure or dynamic library), you will need to
|
||||
grab the runtime from a scope that has it and then move it into your
|
||||
new scope with a runtime guard.
|
||||
|
||||
For example, if you are trying to use dioxus apis from a web-sys
|
||||
closure, you can grab the runtime from the scope it is created in:
|
||||
|
||||
```rust
|
||||
use dioxus::prelude::*;
|
||||
static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
|
||||
|
||||
#[component]
|
||||
fn MyComponent() -> Element {
|
||||
use_effect(|| {
|
||||
// Grab the runtime from the MyComponent scope
|
||||
let runtime = Runtime::current().expect(\"Components run in the Dioxus runtime\");
|
||||
// Move the runtime into the web-sys closure scope
|
||||
let web_sys_closure = Closure::new(|| {
|
||||
// Then create a guard to provide the runtime to the closure
|
||||
let _guard = RuntimeGuard::new(runtime);
|
||||
// and run whatever code needs the runtime
|
||||
tracing::info!(\"The count is: {COUNT}\");
|
||||
});
|
||||
})
|
||||
}
|
||||
```"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RuntimeError {}
|
||||
|
|
|
@ -16,7 +16,7 @@ impl VirtualDom {
|
|||
props: BoxedAnyProps,
|
||||
name: &'static str,
|
||||
) -> &mut ScopeState {
|
||||
let parent_id = self.runtime.current_scope_id();
|
||||
let parent_id = self.runtime.current_scope_id().ok();
|
||||
let height = match parent_id.and_then(|id| self.runtime.get_state(id)) {
|
||||
Some(parent) => parent.height() + 1,
|
||||
None => 0,
|
||||
|
@ -47,11 +47,11 @@ impl VirtualDom {
|
|||
|
||||
/// Run a scope and return the rendered nodes. This will not modify the DOM or update the last rendered node of the scope.
|
||||
#[tracing::instrument(skip(self), level = "trace", name = "VirtualDom::run_scope")]
|
||||
#[track_caller]
|
||||
pub(crate) fn run_scope(&mut self, scope_id: ScopeId) -> RenderReturn {
|
||||
debug_assert!(
|
||||
crate::Runtime::current().is_some(),
|
||||
"Must be in a dioxus runtime"
|
||||
);
|
||||
// Ensure we are currently inside a `Runtime`.
|
||||
crate::Runtime::current().unwrap();
|
||||
|
||||
self.runtime.clone().with_scope_on_stack(scope_id, || {
|
||||
let scope = &self.scopes[scope_id.0];
|
||||
let output = {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::runtime::RuntimeError;
|
||||
use crate::{innerlude::SchedulerMsg, Runtime, ScopeId, Task};
|
||||
use crate::{
|
||||
innerlude::{throw_into, CapturedError},
|
||||
|
@ -219,7 +220,7 @@ impl Scope {
|
|||
None
|
||||
});
|
||||
|
||||
match cur_runtime.flatten() {
|
||||
match cur_runtime.ok().flatten() {
|
||||
Some(ctx) => Some(ctx),
|
||||
None => {
|
||||
tracing::trace!(
|
||||
|
@ -450,13 +451,18 @@ impl Scope {
|
|||
|
||||
impl ScopeId {
|
||||
/// Get the current scope id
|
||||
pub fn current_scope_id(self) -> Option<ScopeId> {
|
||||
Runtime::with(|rt| rt.current_scope_id()).flatten()
|
||||
pub fn current_scope_id(self) -> Result<ScopeId, RuntimeError> {
|
||||
Runtime::with(|rt| rt.current_scope_id().ok())
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or(RuntimeError::new())
|
||||
}
|
||||
|
||||
/// Consume context from the current scope
|
||||
pub fn consume_context<T: 'static + Clone>(self) -> Option<T> {
|
||||
Runtime::with_scope(self, |cx| cx.consume_context::<T>()).flatten()
|
||||
Runtime::with_scope(self, |cx| cx.consume_context::<T>())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Consume context from the current scope
|
||||
|
@ -465,64 +471,67 @@ impl ScopeId {
|
|||
rt.get_state(scope_id)
|
||||
.and_then(|cx| cx.consume_context::<T>())
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Check if the current scope has a context
|
||||
pub fn has_context<T: 'static + Clone>(self) -> Option<T> {
|
||||
Runtime::with_scope(self, |cx| cx.has_context::<T>()).flatten()
|
||||
Runtime::with_scope(self, |cx| cx.has_context::<T>())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Provide context to the current scope
|
||||
pub fn provide_context<T: 'static + Clone>(self, value: T) -> T {
|
||||
Runtime::with_scope(self, |cx| cx.provide_context(value))
|
||||
.expect("to be in a dioxus runtime")
|
||||
Runtime::with_scope(self, |cx| cx.provide_context(value)).unwrap()
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
Runtime::with_scope(self, |cx| cx.spawn(fut))
|
||||
Runtime::with_scope(self, |cx| cx.spawn(fut)).ok()
|
||||
}
|
||||
|
||||
/// Spawns the future but does not return the [`Task`]
|
||||
pub fn spawn(self, fut: impl Future<Output = ()> + 'static) {
|
||||
Runtime::with_scope(self, |cx| cx.spawn(fut));
|
||||
Runtime::with_scope(self, |cx| cx.spawn(fut)).unwrap();
|
||||
}
|
||||
|
||||
/// Get the current render since the inception of this component
|
||||
///
|
||||
/// This can be used as a helpful diagnostic when debugging hooks/renders, etc
|
||||
pub fn generation(self) -> Option<usize> {
|
||||
Runtime::with_scope(self, |cx| Some(cx.generation())).expect("to be in a dioxus runtime")
|
||||
Runtime::with_scope(self, |cx| Some(cx.generation())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the parent of the current scope if it exists
|
||||
pub fn parent_scope(self) -> Option<ScopeId> {
|
||||
Runtime::with_scope(self, |cx| cx.parent_id()).flatten()
|
||||
Runtime::with_scope(self, |cx| cx.parent_id())
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Mark the current scope as dirty, causing it to re-render
|
||||
pub fn needs_update(self) {
|
||||
Runtime::with_scope(self, |cx| cx.needs_update());
|
||||
Runtime::with_scope(self, |cx| cx.needs_update()).unwrap();
|
||||
}
|
||||
|
||||
/// 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 [`crate::prelude::schedule_update_any`]
|
||||
pub fn schedule_update(&self) -> Arc<dyn Fn() + Send + Sync + 'static> {
|
||||
Runtime::with_scope(*self, |cx| cx.schedule_update()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_scope(*self, |cx| cx.schedule_update()).unwrap()
|
||||
}
|
||||
|
||||
/// Get the height of the current scope
|
||||
pub fn height(self) -> u32 {
|
||||
Runtime::with_scope(self, |cx| cx.height()).expect("to be in a dioxus runtime")
|
||||
Runtime::with_scope(self, |cx| cx.height()).unwrap()
|
||||
}
|
||||
|
||||
/// Run a closure inside of scope's runtime
|
||||
#[track_caller]
|
||||
pub fn in_runtime<T>(self, f: impl FnOnce() -> T) -> T {
|
||||
Runtime::current()
|
||||
.expect("to be in a dioxus runtime")
|
||||
.on_scope(self, f)
|
||||
Runtime::current().unwrap().on_scope(self, f)
|
||||
}
|
||||
|
||||
/// Throw a [`CapturedError`] into a scope. The error will bubble up to the nearest [`ErrorBoundary`] or the root of the app.
|
||||
|
|
|
@ -21,6 +21,7 @@ impl std::fmt::Debug for ScopeId {
|
|||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if let Some(name) = Runtime::current()
|
||||
.ok()
|
||||
.as_ref()
|
||||
.and_then(|rt| rt.get_state(*self))
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ impl SuspendedFuture {
|
|||
pub fn new(task: Task) -> Self {
|
||||
Self {
|
||||
task,
|
||||
origin: current_scope_id().expect("to be in a dioxus runtime"),
|
||||
origin: current_scope_id().unwrap(),
|
||||
placeholder: VNode::placeholder(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@ impl Task {
|
|||
_ = rt
|
||||
.sender
|
||||
.unbounded_send(SchedulerMsg::TaskNotified(self.id))
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Poll the task immediately.
|
||||
|
@ -100,7 +101,8 @@ impl Task {
|
|||
.unbounded_send(SchedulerMsg::TaskNotified(self.id));
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +248,11 @@ impl Runtime {
|
|||
}
|
||||
|
||||
pub(crate) fn handle_task_wakeup(&self, id: Task) -> Poll<()> {
|
||||
debug_assert!(Runtime::current().is_some(), "Must be in a dioxus runtime");
|
||||
#[cfg(feature = "debug_assertions")]
|
||||
{
|
||||
// Ensure we are currently inside a `Runtime`.
|
||||
Runtime::current().unwrap();
|
||||
}
|
||||
|
||||
let task = self.tasks.borrow().get(id.id).cloned();
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ impl<T: 'static> GlobalSignal<T> {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn maybe_with_rt<O>(&self, f: impl FnOnce(&T) -> O) -> O {
|
||||
if Runtime::current().is_none() {
|
||||
if Runtime::current().is_err() {
|
||||
f(&(self.initializer)())
|
||||
} else {
|
||||
self.with(f)
|
||||
|
|
Loading…
Reference in a new issue