hello world example working
This commit is contained in:
1 parent
3865f44081
commit
4013341b6c
22 files changed
+159
-176
No files matched your search
@@ -17,7 +17,6 @@ proc-macro2 = { version = "1.0" }
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0", features = ["full", "extra-traits"] }
|
||||
dioxus-rsx = { workspace = true }
|
||||
dioxus-core = { workspace = true }
|
||||
constcat = "0.3.0"
|
||||
prettyplease = "0.2.15"
|
||||
|
||||
|
||||
@@ -147,9 +147,7 @@ pub mod utils;
|
||||
|
||||
pub use utils::DeserializerArgs;
|
||||
pub use utils::DeserializerOutput;
|
||||
pub use utils::TypeHelper;
|
||||
|
||||
use dioxus_core::{Element, Scope};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::*;
|
||||
@@ -167,12 +165,6 @@ pub struct ComponentBody {
|
||||
/// Keep this in mind when creating deserializers, because you often might want to ignore it.
|
||||
/// That might be annoying, but it would be bad design for this kind of struct to not be parsable from itself.
|
||||
pub item_fn: ItemFn,
|
||||
/// Parsing tries to ensure that this argument will be a [`Scope`].
|
||||
/// **However, macros have limitations that prevent this from always working,
|
||||
/// so don't take this for granted!**
|
||||
pub cx_arg: FnArg,
|
||||
/// The pattern (name) and type of the context argument.
|
||||
pub cx_pat_type: PatType,
|
||||
/// If the function has any arguments other than the context.
|
||||
pub has_extra_args: bool,
|
||||
}
|
||||
@@ -192,31 +184,8 @@ impl ComponentBody {
|
||||
impl Parse for ComponentBody {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let item_fn: ItemFn = input.parse()?;
|
||||
let scope_type_path = Scope::get_path_string();
|
||||
|
||||
let (cx_arg, cx_pat_type) = if let Some(first_arg) = item_fn.sig.inputs.first() {
|
||||
let incorrect_first_arg_err = Err(Error::new(
|
||||
first_arg.span(),
|
||||
format!("First argument must be a <{}>", scope_type_path),
|
||||
));
|
||||
|
||||
match first_arg.to_owned() {
|
||||
FnArg::Receiver(_) => {
|
||||
return incorrect_first_arg_err;
|
||||
}
|
||||
FnArg::Typed(f) => (first_arg.to_owned(), f),
|
||||
}
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
item_fn.sig.ident.span(), // Or maybe just item_f.sig.span()?
|
||||
format!(
|
||||
"Must have at least one argument that's a <{}>",
|
||||
scope_type_path
|
||||
),
|
||||
));
|
||||
};
|
||||
|
||||
let element_type_path = Element::get_path_string();
|
||||
let element_type_path = "::dioxus::core::Element";
|
||||
|
||||
if item_fn.sig.output == ReturnType::Default {
|
||||
return Err(Error::new(
|
||||
@@ -229,8 +198,6 @@ impl Parse for ComponentBody {
|
||||
|
||||
Ok(Self {
|
||||
item_fn,
|
||||
cx_arg,
|
||||
cx_pat_type,
|
||||
has_extra_args,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::component_body::ComponentBody;
|
||||
use dioxus_core::{Element, Scope};
|
||||
use quote::ToTokens;
|
||||
use syn::{parse_quote, Path};
|
||||
|
||||
@@ -36,22 +35,3 @@ where
|
||||
#[allow(unused_qualifications)]
|
||||
fn to_output(&self, component_body: &ComponentBody) -> syn::Result<TOutput>;
|
||||
}
|
||||
|
||||
pub trait TypeHelper {
|
||||
fn get_path() -> Path;
|
||||
fn get_path_string() -> String {
|
||||
Self::get_path().to_token_stream().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TypeHelper for Scope<'a> {
|
||||
fn get_path() -> Path {
|
||||
parse_quote!(::dioxus::core::Scope)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TypeHelper for Element<'a> {
|
||||
fn get_path() -> Path {
|
||||
parse_quote!(::dioxus::core::Element)
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ To ignore this check, pass the \"",
|
||||
|
||||
const INNER_FN_NAME: &str = "__dx_inner_comp";
|
||||
|
||||
fn get_out_comp_fn(orig_comp_fn: &ItemFn, cx_pat: &Pat) -> ItemFn {
|
||||
fn get_out_comp_fn(orig_comp_fn: &ItemFn) -> ItemFn {
|
||||
let inner_comp_ident = Ident::new(INNER_FN_NAME, orig_comp_fn.sig.ident.span());
|
||||
|
||||
let inner_comp_fn = ItemFn {
|
||||
@@ -34,7 +34,7 @@ fn get_out_comp_fn(orig_comp_fn: &ItemFn, cx_pat: &Pat) -> ItemFn {
|
||||
#[allow(clippy::inline_always)]
|
||||
#[inline(always)]
|
||||
#inner_comp_fn
|
||||
#inner_comp_ident (#cx_pat)
|
||||
#inner_comp_ident(__props)
|
||||
}
|
||||
},
|
||||
..orig_comp_fn.clone()
|
||||
@@ -88,14 +88,9 @@ impl DeserializerArgs<ComponentDeserializerOutput> for ComponentDeserializerArgs
|
||||
|
||||
impl ComponentDeserializerArgs {
|
||||
fn deserialize_no_props(component_body: &ComponentBody) -> ComponentDeserializerOutput {
|
||||
let ComponentBody {
|
||||
item_fn,
|
||||
cx_pat_type,
|
||||
..
|
||||
} = component_body;
|
||||
let cx_pat = &cx_pat_type.pat;
|
||||
let ComponentBody { item_fn, .. } = component_body;
|
||||
|
||||
let comp_fn = get_out_comp_fn(item_fn, cx_pat);
|
||||
let comp_fn = get_out_comp_fn(item_fn);
|
||||
|
||||
ComponentDeserializerOutput {
|
||||
comp_fn,
|
||||
@@ -106,12 +101,7 @@ impl ComponentDeserializerArgs {
|
||||
fn deserialize_with_props(
|
||||
component_body: &ComponentBody,
|
||||
) -> Result<ComponentDeserializerOutput> {
|
||||
let ComponentBody {
|
||||
item_fn,
|
||||
cx_pat_type,
|
||||
..
|
||||
} = component_body;
|
||||
let cx_pat = &cx_pat_type.pat;
|
||||
let ComponentBody { item_fn, .. } = component_body;
|
||||
|
||||
let comp_parsed = match parse2::<ComponentBody>(quote!(#item_fn)) {
|
||||
Ok(comp_body) => comp_body,
|
||||
@@ -130,7 +120,7 @@ impl ComponentDeserializerArgs {
|
||||
let props_struct = inlined_props_output.props_struct;
|
||||
let props_fn = inlined_props_output.comp_fn;
|
||||
|
||||
let comp_fn = get_out_comp_fn(&props_fn, cx_pat);
|
||||
let comp_fn = get_out_comp_fn(&props_fn);
|
||||
|
||||
Ok(ComponentDeserializerOutput {
|
||||
comp_fn,
|
||||
|
||||
@@ -225,11 +225,7 @@ fn get_props_docs(fn_ident: &Ident, inputs: Vec<&FnArg>) -> Vec<Attribute> {
|
||||
}
|
||||
|
||||
fn get_function(component_body: &ComponentBody) -> ItemFn {
|
||||
let ComponentBody {
|
||||
item_fn,
|
||||
cx_pat_type,
|
||||
..
|
||||
} = component_body;
|
||||
let ComponentBody { item_fn, .. } = component_body;
|
||||
let ItemFn {
|
||||
attrs: fn_attrs,
|
||||
vis,
|
||||
@@ -246,7 +242,6 @@ fn get_function(component_body: &ComponentBody) -> ItemFn {
|
||||
} = sig;
|
||||
let Generics { where_clause, .. } = generics;
|
||||
|
||||
let cx_pat = &cx_pat_type.pat;
|
||||
let struct_ident = Ident::new(&format!("{fn_ident}Props"), fn_ident.span());
|
||||
|
||||
// Skip first arg since that's the context
|
||||
@@ -298,10 +293,10 @@ fn get_function(component_body: &ComponentBody) -> ItemFn {
|
||||
parse_quote! {
|
||||
#(#fn_attrs)*
|
||||
#(#props_docs)*
|
||||
#asyncness #vis fn #fn_ident #fn_generics (#cx_pat: Scope<#scope_lifetime #struct_ident #generics_no_bounds>) #fn_output
|
||||
#asyncness #vis fn #fn_ident #fn_generics (__props: #struct_ident #generics_no_bounds) #fn_output
|
||||
#where_clause
|
||||
{
|
||||
let #struct_ident { #(#struct_field_names),* } = &#cx_pat.props;
|
||||
let #struct_ident { #(#struct_field_names),* } = &__props;
|
||||
#fn_block
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}));
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use async_trait::async_trait;
|
||||
use dioxus_core::prelude::consume_context;
|
||||
use dioxus_core::prelude::provide_context;
|
||||
use dioxus_core::ScopeId;
|
||||
use dioxus_html::prelude::{EvalError, EvalProvider, Evaluator};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
@@ -9,13 +10,13 @@ use crate::{query::Query, DesktopContext};
|
||||
|
||||
/// Provides the DesktopEvalProvider through [`cx.provide_context`].
|
||||
pub fn init_eval() {
|
||||
let desktop_ctx = consume_context::<DesktopContext>().unwrap();
|
||||
let desktop_ctx = ScopeId::ROOT.consume_context::<DesktopContext>().unwrap();
|
||||
let provider: Rc<dyn EvalProvider> = Rc::new(DesktopEvalProvider { desktop_ctx });
|
||||
provide_context(provider);
|
||||
ScopeId::ROOT.provide_context(provider);
|
||||
}
|
||||
|
||||
/// Reprents the desktop-target's provider of evaluators.
|
||||
pub struct DesktopEvalProvider {
|
||||
/// Represents the desktop-target's provider of evaluators.
|
||||
pub(crate) struct DesktopEvalProvider {
|
||||
desktop_ctx: DesktopContext,
|
||||
}
|
||||
|
||||
@@ -25,8 +26,8 @@ impl EvalProvider for DesktopEvalProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reprents a desktop-target's JavaScript evaluator.
|
||||
pub struct DesktopEvaluator {
|
||||
/// Represents a desktop-target's JavaScript evaluator.
|
||||
pub(crate) struct DesktopEvaluator {
|
||||
query: Rc<RefCell<Query<serde_json::Value>>>,
|
||||
}
|
||||
|
||||
|
||||
+27
-27
@@ -55,42 +55,42 @@ macro_rules! to_owned {
|
||||
};
|
||||
}
|
||||
|
||||
pub mod computed;
|
||||
// pub mod computed;
|
||||
|
||||
mod use_on_destroy;
|
||||
pub use use_on_destroy::*;
|
||||
// mod use_on_destroy;
|
||||
// pub use use_on_destroy::*;
|
||||
|
||||
mod use_const;
|
||||
pub use use_const::*;
|
||||
// mod use_const;
|
||||
// pub use use_const::*;
|
||||
|
||||
mod use_context;
|
||||
pub use use_context::*;
|
||||
// mod use_context;
|
||||
// pub use use_context::*;
|
||||
|
||||
mod use_state;
|
||||
pub use use_state::{use_state, UseState};
|
||||
// mod use_state;
|
||||
// pub use use_state::{use_state, UseState};
|
||||
|
||||
mod use_ref;
|
||||
pub use use_ref::*;
|
||||
// mod use_ref;
|
||||
// pub use use_ref::*;
|
||||
|
||||
mod use_shared_state;
|
||||
pub use use_shared_state::*;
|
||||
// mod use_shared_state;
|
||||
// pub use use_shared_state::*;
|
||||
|
||||
mod use_coroutine;
|
||||
pub use use_coroutine::*;
|
||||
// mod use_coroutine;
|
||||
// pub use use_coroutine::*;
|
||||
|
||||
mod use_future;
|
||||
pub use use_future::*;
|
||||
// mod use_future;
|
||||
// pub use use_future::*;
|
||||
|
||||
mod use_effect;
|
||||
pub use use_effect::*;
|
||||
// mod use_effect;
|
||||
// pub use use_effect::*;
|
||||
|
||||
mod use_callback;
|
||||
pub use use_callback::*;
|
||||
// mod use_callback;
|
||||
// pub use use_callback::*;
|
||||
|
||||
mod use_memo;
|
||||
pub use use_memo::*;
|
||||
// mod use_memo;
|
||||
// pub use use_memo::*;
|
||||
|
||||
mod use_on_create;
|
||||
pub use use_on_create::*;
|
||||
mod use_root_context;
|
||||
pub use use_root_context::*;
|
||||
// mod use_on_create;
|
||||
// pub use use_on_create::*;
|
||||
// mod use_root_context;
|
||||
// pub use use_root_context::*;
|
||||
@@ -68,7 +68,7 @@ impl ToTokens for ElementAttrNamed {
|
||||
let value = &self.attr.value;
|
||||
let value = quote! { #value };
|
||||
quote! {
|
||||
__cx.attr(
|
||||
::dioxus::core::Attribute::new(
|
||||
#attribute,
|
||||
#value,
|
||||
#ns,
|
||||
@@ -79,7 +79,7 @@ impl ToTokens for ElementAttrNamed {
|
||||
ElementAttrValue::EventTokens(tokens) => match &self.attr.name {
|
||||
ElementAttrName::BuiltIn(name) => {
|
||||
quote! {
|
||||
dioxus_elements::events::#name(__cx, #tokens)
|
||||
dioxus_elements::events::#name(#tokens)
|
||||
}
|
||||
}
|
||||
ElementAttrName::Custom(_) => todo!(),
|
||||
|
||||
@@ -189,11 +189,11 @@ impl ToTokens for Component {
|
||||
};
|
||||
|
||||
tokens.append_all(quote! {
|
||||
__cx.component(
|
||||
::dioxus::core::DynamicNode::Component(::dioxus::core::VComponent::new(
|
||||
#gen_name,
|
||||
#builder,
|
||||
#fn_name
|
||||
)
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -217,10 +217,10 @@ impl ToTokens for ContentField {
|
||||
match self {
|
||||
ContentField::ManExpr(e) => e.to_tokens(tokens),
|
||||
ContentField::Formatted(s) => tokens.append_all(quote! {
|
||||
__cx.raw_text(#s)
|
||||
#s.to_string()
|
||||
}),
|
||||
ContentField::OnHandlerRaw(e) => tokens.append_all(quote! {
|
||||
__cx.event_handler(#e)
|
||||
::dioxus::core::Attribute::EventHandler(EventHandler::new(#e))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,11 +184,11 @@ impl ToTokens for Element {
|
||||
.filter(|f| !matches!(f.attr.value, ElementAttrValue::EventTokens { .. }));
|
||||
|
||||
tokens.append_all(quote! {
|
||||
__cx.element(
|
||||
::dioxus::core::Element::new(
|
||||
#name,
|
||||
__cx.bump().alloc([ #(#listeners),* ]),
|
||||
__cx.bump().alloc([ #(#attr),* ]),
|
||||
__cx.bump().alloc([ #(#children),* ]),
|
||||
vec![ #(#listeners),* ],
|
||||
vec![ #(#attr),* ],
|
||||
vec![ #(#children),* ],
|
||||
#key,
|
||||
)
|
||||
});
|
||||
|
||||
@@ -69,7 +69,7 @@ impl CallBody {
|
||||
&self,
|
||||
template: Option<CallBody>,
|
||||
location: &'static str,
|
||||
) -> Option<Template<'static>> {
|
||||
) -> Option<Template> {
|
||||
let mut renderer: TemplateRenderer = TemplateRenderer {
|
||||
roots: &self.roots,
|
||||
location: None,
|
||||
@@ -138,7 +138,6 @@ impl ToTokens for RenderCallBody {
|
||||
|
||||
out_tokens.append_all(quote! {
|
||||
Some({
|
||||
let __cx = cx;
|
||||
#body
|
||||
})
|
||||
})
|
||||
@@ -156,7 +155,7 @@ impl<'a> TemplateRenderer<'a> {
|
||||
&mut self,
|
||||
previous_call: Option<CallBody>,
|
||||
location: &'static str,
|
||||
) -> Option<Template<'static>> {
|
||||
) -> Option<Template> {
|
||||
let mut mapping = previous_call.map(|call| DynamicMapping::from(call.roots));
|
||||
|
||||
let mut context = DynamicContext::default();
|
||||
@@ -202,7 +201,7 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
||||
};
|
||||
|
||||
let key_tokens = match key {
|
||||
Some(tok) => quote! { Some( __cx.raw_text(#tok) ) },
|
||||
Some(tok) => quote! { Some( #tok.to_string() ) },
|
||||
None => quote! { None },
|
||||
};
|
||||
|
||||
@@ -257,9 +256,9 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
||||
::dioxus::core::VNode::new(
|
||||
#key_tokens,
|
||||
TEMPLATE,
|
||||
dioxus::core::exports::bumpalo::collections::Vec::with_capacity_in(#root_count, __cx.bump()),
|
||||
__cx.bump().alloc([ #( #node_printer ),* ]),
|
||||
__cx.bump().alloc([ #( #dyn_attr_printer ),* ]),
|
||||
Vec::with_capacity(#root_count),
|
||||
vec![ #( #node_printer ),* ],
|
||||
vec![ #( #dyn_attr_printer ),* ],
|
||||
)
|
||||
});
|
||||
}
|
||||
@@ -360,7 +359,7 @@ impl<'a> DynamicContext<'a> {
|
||||
&mut self,
|
||||
root: &'a BodyNode,
|
||||
mapping: &mut Option<DynamicMapping>,
|
||||
) -> Option<TemplateNode<'static>> {
|
||||
) -> Option<TemplateNode> {
|
||||
match root {
|
||||
BodyNode::Element(el) => {
|
||||
let element_name_rust = el.name.to_string();
|
||||
|
||||
@@ -122,11 +122,11 @@ impl ToTokens for BodyNode {
|
||||
BodyNode::Element(el) => el.to_tokens(tokens),
|
||||
BodyNode::Component(comp) => comp.to_tokens(tokens),
|
||||
BodyNode::Text(txt) => tokens.append_all(quote! {
|
||||
__cx.text_node(#txt)
|
||||
::dioxus::core::DynamicNode::Text(::dioxus::core::VText::new(#txt.to_string()))
|
||||
}),
|
||||
BodyNode::RawExpr(exp) => tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#exp).into_dyn_node(__cx);
|
||||
let ___nodes = (#exp).into_dyn_node();
|
||||
___nodes
|
||||
}
|
||||
}),
|
||||
@@ -145,7 +145,7 @@ impl ToTokens for BodyNode {
|
||||
// And then we can return them into the dyn loop
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes =(#expr).into_iter().map(|#pat| { #renderer }).into_dyn_node(__cx);
|
||||
let ___nodes = (#expr).into_iter().map(|#pat| { #renderer }).into_dyn_node();
|
||||
___nodes
|
||||
}
|
||||
})
|
||||
@@ -154,7 +154,7 @@ impl ToTokens for BodyNode {
|
||||
if is_if_chain_terminated(chain) {
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#chain).into_dyn_node(__cx);
|
||||
let ___nodes = (#chain).into_dyn_node();
|
||||
___nodes
|
||||
}
|
||||
});
|
||||
@@ -211,7 +211,7 @@ impl ToTokens for BodyNode {
|
||||
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#body).into_dyn_node(__cx);
|
||||
let ___nodes = (#body).into_dyn_node();
|
||||
___nodes
|
||||
}
|
||||
});
|
||||
|
||||
@@ -38,21 +38,20 @@ pub(crate) fn get_effect_stack() -> EffectStack {
|
||||
|
||||
/// Create a new effect. The effect will be run immediately and whenever any signal it reads changes.
|
||||
/// The signal will be owned by the current component and will be dropped when the component is dropped.
|
||||
pub fn use_effect(cx: &ScopeState, callback: impl FnMut() + 'static) {
|
||||
cx.use_hook(|| Effect::new(callback));
|
||||
pub fn use_effect(callback: impl FnMut() + 'static) {
|
||||
once(|| Effect::new(callback));
|
||||
}
|
||||
|
||||
/// Create a new effect. The effect will be run immediately and whenever any signal it reads changes.
|
||||
/// The signal will be owned by the current component and will be dropped when the component is dropped.
|
||||
pub fn use_effect_with_dependencies<D: Dependency>(
|
||||
cx: &ScopeState,
|
||||
dependencies: D,
|
||||
mut callback: impl FnMut(D::Out) + 'static,
|
||||
) where
|
||||
D::Out: 'static,
|
||||
{
|
||||
let dependencies_signal = use_signal(cx, || dependencies.out());
|
||||
cx.use_hook(|| {
|
||||
let dependencies_signal = use_signal(|| dependencies.out());
|
||||
once(|| {
|
||||
Effect::new(move || {
|
||||
let deref = &*dependencies_signal.read();
|
||||
callback(deref.clone());
|
||||
|
||||
@@ -44,7 +44,7 @@ fn owner_in_scope(scope: ScopeId) -> Rc<Owner> {
|
||||
Some(rt) => rt,
|
||||
None => {
|
||||
let owner = Rc::new(current_store().owner());
|
||||
provide_context_to_scope(scope, owner).expect("in a virtual dom")
|
||||
scope.provide_context(owner).expect("in a virtual dom")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,8 @@ use crate::{get_effect_stack, signal::SignalData, CopyValue, Effect, ReadOnlySig
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"]
|
||||
pub fn use_selector<R: PartialEq>(
|
||||
cx: &ScopeState,
|
||||
f: impl FnMut() -> R + 'static,
|
||||
) -> ReadOnlySignal<R> {
|
||||
*cx.use_hook(|| selector(f))
|
||||
pub fn use_selector<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<R> {
|
||||
once(|| selector(f))
|
||||
}
|
||||
|
||||
/// Creates a new Selector with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
|
||||
@@ -47,15 +44,14 @@ pub fn use_selector<R: PartialEq>(
|
||||
/// ```
|
||||
#[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"]
|
||||
pub fn use_selector_with_dependencies<R: PartialEq, D: Dependency>(
|
||||
cx: &ScopeState,
|
||||
dependencies: D,
|
||||
mut f: impl FnMut(D::Out) -> R + 'static,
|
||||
) -> ReadOnlySignal<R>
|
||||
where
|
||||
D::Out: 'static,
|
||||
{
|
||||
let dependencies_signal = use_signal(cx, || dependencies.out());
|
||||
let selector = *cx.use_hook(|| {
|
||||
let dependencies_signal = use_signal(|| dependencies.out());
|
||||
let selector = once(|| {
|
||||
selector(move || {
|
||||
let deref = &*dependencies_signal.read();
|
||||
f(deref.clone())
|
||||
@@ -87,9 +83,9 @@ pub fn selector<R: PartialEq>(mut f: impl FnMut() -> R + 'static) -> ReadOnlySig
|
||||
state.inner.value.set(SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
value: f(),
|
||||
effect_stack: get_effect_stack(),
|
||||
update_any: schedule_update_any(),
|
||||
});
|
||||
{
|
||||
get_effect_stack().effects.write().pop();
|
||||
|
||||
@@ -7,8 +7,9 @@ use std::{
|
||||
};
|
||||
|
||||
use dioxus_core::{
|
||||
once,
|
||||
prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
|
||||
ScopeId, ScopeState,
|
||||
ScopeId,
|
||||
};
|
||||
use generational_box::{GenerationalRef, GenerationalRefMut};
|
||||
|
||||
@@ -47,11 +48,11 @@ use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[must_use]
|
||||
pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
|
||||
pub fn use_signal<T: 'static>(f: impl FnOnce() -> T) -> Signal<T> {
|
||||
#[cfg(debug_assertions)]
|
||||
let caller = std::panic::Location::caller();
|
||||
|
||||
*cx.use_hook(|| {
|
||||
once(|| {
|
||||
Signal::new_with_caller(
|
||||
f(),
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -155,7 +156,7 @@ impl<T: 'static> Signal<T> {
|
||||
inner: CopyValue::new(SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
update_any: schedule_update_any(),
|
||||
value,
|
||||
effect_stack: get_effect_stack(),
|
||||
}),
|
||||
@@ -172,7 +173,7 @@ impl<T: 'static> Signal<T> {
|
||||
SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
update_any: schedule_update_any(),
|
||||
value,
|
||||
effect_stack: get_effect_stack(),
|
||||
},
|
||||
@@ -189,7 +190,7 @@ impl<T: 'static> Signal<T> {
|
||||
SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
update_any: schedule_update_any(),
|
||||
value,
|
||||
effect_stack: get_effect_stack(),
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user