diff --git a/tachys/src/html/element/custom.rs b/tachys/src/html/element/custom.rs index 3c8347e3e..fdb670b3a 100644 --- a/tachys/src/html/element/custom.rs +++ b/tachys/src/html/element/custom.rs @@ -17,8 +17,6 @@ where rndr: PhantomData, attributes: (), children: (), - #[cfg(debug_assertions)] - defined_at: std::panic::Location::caller(), } } diff --git a/tachys/src/html/element/elements.rs b/tachys/src/html/element/elements.rs index 210798aa6..f1a632ea0 100644 --- a/tachys/src/html/element/elements.rs +++ b/tachys/src/html/element/elements.rs @@ -35,8 +35,6 @@ macro_rules! html_element_inner { attributes: (), children: (), rndr: PhantomData, - #[cfg(debug_assertions)] - defined_at: std::panic::Location::caller() } } @@ -63,17 +61,12 @@ macro_rules! html_element_inner { At: NextTuple, ::Output], V, Rndr>>: Attribute, { - let HtmlElement { tag, rndr, children, attributes, - #[cfg(debug_assertions)] - defined_at - } = self; + let HtmlElement { tag, rndr, children, attributes } = self; HtmlElement { tag, rndr, children, attributes: attributes.next_tuple($crate::html::attribute::$attr(value)), - #[cfg(debug_assertions)] - defined_at } } )* @@ -161,8 +154,6 @@ macro_rules! html_self_closing_elements { children: (), rndr: PhantomData, tag: [<$tag:camel>], - #[cfg(debug_assertions)] - defined_at: std::panic::Location::caller() } } @@ -191,16 +182,12 @@ macro_rules! html_self_closing_elements { { let HtmlElement { tag, rndr, children, attributes, - #[cfg(debug_assertions)] - defined_at } = self; HtmlElement { tag, rndr, children, attributes: attributes.next_tuple($crate::html::attribute::$attr(value)), - #[cfg(debug_assertions)] - defined_at } } )* diff --git a/tachys/src/html/element/mod.rs b/tachys/src/html/element/mod.rs index 15ca66939..9715e19be 100644 --- a/tachys/src/html/element/mod.rs +++ b/tachys/src/html/element/mod.rs @@ -32,8 +32,6 @@ pub struct HtmlElement { pub(crate) rndr: PhantomData, pub(crate) attributes: At, pub(crate) children: Ch, - #[cfg(debug_assertions)] - pub(crate) defined_at: &'static std::panic::Location<'static>, } impl Clone @@ -45,8 +43,6 @@ impl Clone rndr: PhantomData, attributes: self.attributes.clone(), children: self.children.clone(), - #[cfg(debug_assertions)] - defined_at: self.defined_at, } } } @@ -85,16 +81,12 @@ where rndr, attributes, children, - #[cfg(debug_assertions)] - defined_at, } = self; HtmlElement { tag, rndr, attributes, children: children.next_tuple(child), - #[cfg(debug_assertions)] - defined_at, } } } @@ -122,16 +114,12 @@ where attributes, children, rndr, - #[cfg(debug_assertions)] - defined_at, } = self; HtmlElement { tag, attributes: attributes.add_any_attr(attr), children, rndr, - #[cfg(debug_assertions)] - defined_at, } } } @@ -262,8 +250,6 @@ where rndr: PhantomData, attributes, children, - #[cfg(debug_assertions)] - defined_at: self.defined_at, } } diff --git a/tachys/src/mathml/mod.rs b/tachys/src/mathml/mod.rs index 43119a2f3..779082d76 100644 --- a/tachys/src/mathml/mod.rs +++ b/tachys/src/mathml/mod.rs @@ -26,17 +26,12 @@ macro_rules! mathml_global { At: NextTuple, ::Output], V, Rndr>>: Attribute, { - let HtmlElement { tag, rndr, children, attributes, - #[cfg(debug_assertions)] - defined_at - } = self; + let HtmlElement { tag, rndr, children, attributes } = self; HtmlElement { tag, rndr, children, attributes: attributes.next_tuple($crate::html::attribute::$attr(value)), - #[cfg(debug_assertions)] - defined_at } } } @@ -59,8 +54,6 @@ macro_rules! mathml_elements { attributes: (), children: (), rndr: PhantomData, - #[cfg(debug_assertions)] - defined_at: std::panic::Location::caller() } } @@ -95,17 +88,12 @@ macro_rules! mathml_elements { At: NextTuple, ::Output], V, Rndr>>: Attribute, { - let HtmlElement { tag, rndr, children, attributes, - #[cfg(debug_assertions)] - defined_at - } = self; + let HtmlElement { tag, rndr, children, attributes } = self; HtmlElement { tag, rndr, children, attributes: attributes.next_tuple($crate::html::attribute::$attr(value)), - #[cfg(debug_assertions)] - defined_at } } )* diff --git a/tachys/src/svg/mod.rs b/tachys/src/svg/mod.rs index e6f227b62..e8c2b4b60 100644 --- a/tachys/src/svg/mod.rs +++ b/tachys/src/svg/mod.rs @@ -27,8 +27,6 @@ macro_rules! svg_elements { attributes: (), children: (), rndr: PhantomData, - #[cfg(debug_assertions)] - defined_at: std::panic::Location::caller() } } diff --git a/tachys/src/view/add_attr.rs b/tachys/src/view/add_attr.rs index 4d4df9531..dc5dc102a 100644 --- a/tachys/src/view/add_attr.rs +++ b/tachys/src/view/add_attr.rs @@ -1,4 +1,4 @@ -use super::RenderHtml; +use super::{BoxedView, RenderHtml}; use crate::{html::attribute::Attribute, renderer::Renderer}; /// Allows adding a new attribute to some type, before it is rendered. @@ -44,3 +44,22 @@ macro_rules! no_attrs { } }; } + +impl AddAnyAttr for BoxedView +where + T: AddAnyAttr, + Rndr: Renderer, +{ + type Output> = + BoxedView>; + + fn add_any_attr>( + self, + attr: NewAttr, + ) -> Self::Output + where + Self::Output: RenderHtml, + { + BoxedView::new(self.into_inner().add_any_attr(attr)) + } +} diff --git a/tachys/src/view/mod.rs b/tachys/src/view/mod.rs index 9e349ee86..d6eeb8e83 100644 --- a/tachys/src/view/mod.rs +++ b/tachys/src/view/mod.rs @@ -425,3 +425,85 @@ pub enum Position { /// This is the last child of its parent. LastChild, } + +/// A view stored on the heap. +/// +/// This is a newtype around `Box<_>` that allows us to implement rendering traits on it. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BoxedView(Box); + +impl BoxedView { + /// Stores view on the heap. + pub fn new(value: T) -> Self { + Self(Box::new(value)) + } + + /// Deferences the view to its inner value. + pub fn into_inner(self) -> T { + *self.0 + } + + /// Gives a shared reference to the view. + pub fn as_ref(&self) -> &T { + &self.0 + } + + /// Gives an exclusive reference to the view. + pub fn as_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl Render for BoxedView +where + T: Render, + Rndr: Renderer, +{ + type State = T::State; + + fn build(self) -> Self::State { + self.into_inner().build() + } + + fn rebuild(self, state: &mut Self::State) { + self.into_inner().rebuild(state); + } +} + +impl RenderHtml for BoxedView +where + T: RenderHtml, + Rndr: Renderer, +{ + type AsyncOutput = BoxedView; + + const MIN_LENGTH: usize = T::MIN_LENGTH; + + fn dry_resolve(&mut self) { + self.as_mut().dry_resolve(); + } + + async fn resolve(self) -> Self::AsyncOutput { + let inner = self.into_inner().resolve().await; + BoxedView::new(inner) + } + + fn to_html_with_buf( + self, + buf: &mut String, + position: &mut Position, + escape: bool, + mark_branches: bool, + ) { + self.into_inner() + .to_html_with_buf(buf, position, escape, mark_branches) + } + + fn hydrate( + self, + cursor: &Cursor, + position: &PositionState, + ) -> Self::State { + self.into_inner().hydrate::(cursor, position) + } +}