hello world example working

This commit is contained in:
Evan Almloff committed 2024-01-05 18:01:05 -06:00
1 parent 3865f44081
commit 4013341b6c
22 files changed
+159 -176

No files matched your search

+1 -1
View File
@@ -155,7 +155,7 @@ impl VirtualDom {
}
Element { .. } => {
#[cfg(not(debug_assertions))]
let id = self.write_element_root(node, idx, &mut attrs, &mut nodes, &[]);
let id = self.write_element_root(node, idx, &mut attrs, &mut nodes, &[], to);
#[cfg(debug_assertions)]
let id = self.write_element_root(
node,
+15 -10
View File
@@ -37,11 +37,22 @@ impl Debug for ErrorBoundaryInner {
}
}
/// A trait for any type that can be downcast to a concrete type and implements Debug. This is automatically implemented for all types that implement Any + Debug.
pub trait AnyDebug: Any + Debug {
fn as_any(&self) -> &dyn Any;
}
impl<T: Any + Debug> AnyDebug for T {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Debug)]
/// An instance of an error captured by a descendant component.
pub struct CapturedError {
/// The error captured by the error boundary
pub error: Box<dyn Debug + 'static>,
pub error: Box<dyn AnyDebug + 'static>,
/// The backtrace of the error
pub backtrace: Backtrace,
@@ -65,8 +76,7 @@ impl CapturedError {
/// Downcast the error type into a concrete error type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
if TypeId::of::<T>() == self.error.type_id() {
let raw = self.error.as_ref() as *const _ as *const T;
Some(unsafe { &*raw })
self.error.as_any().downcast_ref::<T>()
} else {
None
}
@@ -100,14 +110,9 @@ impl ErrorBoundary {
}
/// Push an error into this Error Boundary
pub fn insert_error(
&self,
scope: ScopeId,
error: Box<dyn Debug + 'static>,
backtrace: Backtrace,
) {
pub fn insert_error(&self, scope: ScopeId, error: impl Debug + 'static, backtrace: Backtrace) {
self.inner.error.replace(Some(CapturedError {
error,
error: Box::new(error),
scope,
backtrace,
}));
+20
View File
@@ -1,3 +1,5 @@
use std::sync::Arc;
use futures_util::Future;
use crate::{
@@ -113,3 +115,21 @@ pub fn parent_scope() -> Option<ScopeId> {
pub fn needs_update() {
with_current_scope(|cx| cx.needs_update());
}
/// Schedule an update for the current component
///
/// Note: Unlike [`needs_update`], the function returned by this method will work outside of the dioxus runtime.
///
/// You should prefer [`schedule_update_any`] if you need to update multiple components.
pub fn schedule_update() -> Arc<dyn Fn() + Send + Sync> {
with_current_scope(|cx| cx.schedule_update()).expect("to be in a dioxus runtime")
}
/// Schedule an update for any component given its [`ScopeId`].
///
/// A component's [`ScopeId`] can be obtained from the [`current_scope_id`] method.
///
/// 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> {
with_current_scope(|cx| cx.schedule_update_any()).expect("to be in a dioxus runtime")
}
+9 -8
View File
@@ -74,10 +74,11 @@ pub(crate) mod innerlude {
}
pub use crate::innerlude::{
fc_to_builder, generation, once, vdom_is_rendering, AnyValue, Attribute, AttributeValue,
CapturedError, Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode,
Mutation, MutationsVec, Properties, RenderReturn, ScopeId, Task, Template, TemplateAttribute,
TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom, WriteMutations,
fc_to_builder, generation, once, schedule_update, schedule_update_any, vdom_is_rendering,
AnyValue, Attribute, AttributeValue, CapturedError, Component, DynamicNode, Element, ElementId,
Event, Fragment, IntoDynNode, Mutation, MutationsVec, Properties, RenderReturn, ScopeId, Task,
Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
WriteMutations,
};
/// The purpose of this module is to alleviate imports of many common types
@@ -87,9 +88,9 @@ pub mod prelude {
pub use crate::innerlude::{
consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, generation,
has_context, needs_update, once, parent_scope, provide_context, provide_root_context,
push_future, remove_future, spawn, spawn_forever, suspend, use_error_boundary, AnyValue,
Component, Element, ErrorBoundary, Event, EventHandler, Fragment, IntoAttributeValue,
IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, Task, Template, TemplateAttribute,
TemplateNode, Throw, VNode, VirtualDom,
push_future, remove_future, schedule_update, schedule_update_any, spawn, spawn_forever,
suspend, use_error_boundary, AnyValue, Component, Element, ErrorBoundary, Event,
EventHandler, Fragment, IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard,
ScopeId, Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom,
};
}
+28
View File
@@ -9,6 +9,7 @@ use std::{
cell::{Cell, RefCell},
future::Future,
rc::Rc,
sync::Arc,
};
/// A component's state separate from its props.
@@ -69,6 +70,26 @@ impl ScopeContext {
.expect("Scheduler to exist if scope exists");
}
/// Create a subscription that schedules a future render for the reference component
///
/// ## Notice: you should prefer using [`Self::schedule_update_any`] and [`Self::scope_id`]
pub fn schedule_update(&self) -> Arc<dyn Fn() + Send + Sync + 'static> {
let (chan, id) = (self.tasks.sender.clone(), self.id);
Arc::new(move || drop(chan.unbounded_send(SchedulerMsg::Immediate(id))))
}
/// Schedule an update for any component given its [`ScopeId`].
///
/// A component's [`ScopeId`] can be obtained from `use_hook` or the [`ScopeState::scope_id`] method.
///
/// This method should be used when you want to schedule an update for a component
pub fn schedule_update_any(&self) -> Arc<dyn Fn(ScopeId) + Send + Sync> {
let chan = self.tasks.sender.clone();
Arc::new(move |id| {
chan.unbounded_send(SchedulerMsg::Immediate(id)).unwrap();
})
}
/// Return any context of type T if it exists on this scope
pub fn has_context<T: 'static + Clone>(&self) -> Option<T> {
self.shared_contexts
@@ -355,4 +376,11 @@ impl ScopeId {
pub fn needs_update(self) {
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.
///
/// ## 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> {
with_scope(*self, |cx| cx.schedule_update()).expect("to be in a dioxus runtime")
}
}
+3 -1
View File
@@ -549,7 +549,9 @@ impl VirtualDom {
pub fn rebuild(&mut self, to: &mut impl WriteMutations) {
self.flush_templates(to);
let _runtime = RuntimeGuard::new(self.runtime.clone());
match self.run_scope(ScopeId::ROOT) {
let new_nodes = self.run_scope(ScopeId::ROOT);
self.scopes[ScopeId::ROOT.0].last_rendered_node = Some(new_nodes.clone());
match new_nodes {
// Rebuilding implies we append the created elements to the root
RenderReturn::Ready(node) => {
let m = self.create_scope(ScopeId::ROOT, &node, to);