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)
+ }
+}