remove support for rendering guards directly, as they are !Send and holding onto them in State is also a bad idea

This commit is contained in:
Greg Johnston 2024-05-12 07:33:19 -04:00
parent 757a5c73c3
commit 26cf4848db
1 changed files with 99 additions and 96 deletions

View File

@ -1,4 +1,8 @@
//! Implements the [`Render`] and [`RenderHtml`] traits for signal guard types. /* The implementations here are no longer valid because the read guards are not Send.
* If we switch to using some kind of Send async lock, it would be possible to restore them.
*
*
* //! Implements the [`Render`] and [`RenderHtml`] traits for signal guard types.
use crate::{ use crate::{
html::attribute::Attribute, html::attribute::Attribute,
@ -21,68 +25,67 @@ use std::{
}, },
ops::Deref, ops::Deref,
}; };
// any changes here should also be made in src/view/primitives.rs // any changes here should also be made in src/view/primitives.rs
// TODO should also apply to mapped signal read guards // TODO should also apply to mapped signal read guards
macro_rules! render_primitive { macro_rules! render_primitive {
($($child_type:ty),* $(,)?) => { ($($child_type:ty),* $(,)?) => {
$( $(
paste::paste! { paste::paste! {
pub struct [<ReadGuard $child_type:camel State>]<R>(R::Text, $child_type) where R: Renderer; pub struct [<ReadGuard $child_type:camel State>]<R>(R::Text, $child_type) where R: Renderer;
impl<'a, R: Renderer> Mountable<R> for [<ReadGuard $child_type:camel State>]<R> { impl<'a, R: Renderer> Mountable<R> for [<ReadGuard $child_type:camel State>]<R> {
fn unmount(&mut self) { fn unmount(&mut self) {
self.0.unmount() self.0.unmount()
} }
fn mount( fn mount(
&mut self, &mut self,
parent: &<R as Renderer>::Element, parent: &<R as Renderer>::Element,
marker: Option<&<R as Renderer>::Node>, marker: Option<&<R as Renderer>::Node>,
) { ) {
R::insert_node(parent, self.0.as_ref(), marker); R::insert_node(parent, self.0.as_ref(), marker);
} }
fn insert_before_this( fn insert_before_this(
&self, &self,
parent: &<R as Renderer>::Element, parent: &<R as Renderer>::Element,
child: &mut dyn Mountable<R>, child: &mut dyn Mountable<R>,
) -> bool { ) -> bool {
child.mount(parent, Some(self.0.as_ref())); child.mount(parent, Some(self.0.as_ref()));
true true
} }
} }
impl<G, R: Renderer> Render<R> for ReadGuard<$child_type, G> impl<G, R: Renderer> Render<R> for ReadGuard<$child_type, G>
where G: Deref<Target = $child_type> where G: Deref<Target = $child_type>
{ {
type State = [<ReadGuard $child_type:camel State>]<R>; type State = [<ReadGuard $child_type:camel State>]<R>;
fn build(self) -> Self::State { fn build(self) -> Self::State {
let node = R::create_text_node(&self.to_string()); let node = R::create_text_node(&self.to_string());
[<ReadGuard $child_type:camel State>](node, *self) [<ReadGuard $child_type:camel State>](node, *self)
} }
fn rebuild(self, state: &mut Self::State) { fn rebuild(self, state: &mut Self::State) {
let [<ReadGuard $child_type:camel State>](node, this) = state; let [<ReadGuard $child_type:camel State>](node, this) = state;
if &self != this { if &self != this {
R::set_text(node, &self.to_string()); R::set_text(node, &self.to_string());
*this = *self; *this = *self;
} }
} }
} }
impl<G, R> AddAnyAttr<R> for ReadGuard<$child_type, G> impl<G, R> AddAnyAttr<R> for ReadGuard<$child_type, G>
where where
R: Renderer, R: Renderer,
G: Deref<Target = $child_type> + Send G: Deref<Target = $child_type> + Send
{ {
type Output<SomeNewAttr: Attribute<R>> = ReadGuard<$child_type, G>; type Output<SomeNewAttr: Attribute<R>> = ReadGuard<$child_type, G>;
fn add_any_attr<NewAttr: Attribute<R>>( fn add_any_attr<NewAttr: Attribute<R>>(
self, self,
attr: NewAttr, _attr: NewAttr,
) -> Self::Output<NewAttr> ) -> Self::Output<NewAttr>
where where
Self::Output<NewAttr>: RenderHtml<R>, Self::Output<NewAttr>: RenderHtml<R>,
@ -93,76 +96,76 @@ macro_rules! render_primitive {
} }
} }
impl<G, R> RenderHtml<R> for ReadGuard<$child_type, G> impl<G, R> RenderHtml<R> for ReadGuard<$child_type, G>
where where
R: Renderer, R: Renderer,
G: Deref<Target = $child_type> + Send G: Deref<Target = $child_type> + Send
{ {
type AsyncOutput = Self; type AsyncOutput = Self;
const MIN_LENGTH: usize = 0; const MIN_LENGTH: usize = 0;
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) { fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
// add a comment node to separate from previous sibling, if any // add a comment node to separate from previous sibling, if any
if matches!(position, Position::NextChildAfterText) { if matches!(position, Position::NextChildAfterText) {
buf.push_str("<!>") buf.push_str("<!>")
} }
_ = write!(buf, "{}", self); _ = write!(buf, "{}", self);
*position = Position::NextChildAfterText; *position = Position::NextChildAfterText;
} }
fn hydrate<const FROM_SERVER: bool>( fn hydrate<const FROM_SERVER: bool>(
self, self,
cursor: &Cursor<R>, cursor: &Cursor<R>,
position: &PositionState, position: &PositionState,
) -> Self::State { ) -> Self::State {
if position.get() == Position::FirstChild { if position.get() == Position::FirstChild {
cursor.child(); cursor.child();
} else { } else {
cursor.sibling(); cursor.sibling();
} }
// separating placeholder marker comes before text node // separating placeholder marker comes before text node
if matches!(position.get(), Position::NextChildAfterText) { if matches!(position.get(), Position::NextChildAfterText) {
cursor.sibling(); cursor.sibling();
} }
let node = cursor.current(); let node = cursor.current();
let node = R::Text::cast_from(node) let node = R::Text::cast_from(node)
.expect("couldn't cast text node from node"); .expect("couldn't cast text node from node");
if !FROM_SERVER { if !FROM_SERVER {
R::set_text(&node, &self.to_string()); R::set_text(&node, &self.to_string());
} }
position.set(Position::NextChildAfterText); position.set(Position::NextChildAfterText);
[<ReadGuard $child_type:camel State>](node, *self) [<ReadGuard $child_type:camel State>](node, *self)
} }
async fn resolve(self) -> Self::AsyncOutput { async fn resolve(self) -> Self::AsyncOutput {
self self
} }
} }
impl<'a, G> ToTemplate for ReadGuard<$child_type, G> impl<'a, G> ToTemplate for ReadGuard<$child_type, G>
{ {
const TEMPLATE: &'static str = " <!>"; const TEMPLATE: &'static str = " <!>";
fn to_template( fn to_template(
buf: &mut String, buf: &mut String,
_class: &mut String, _class: &mut String,
_style: &mut String, _style: &mut String,
_inner_html: &mut String, _inner_html: &mut String,
position: &mut Position, position: &mut Position,
) { ) {
if matches!(*position, Position::NextChildAfterText) { if matches!(*position, Position::NextChildAfterText) {
buf.push_str("<!>") buf.push_str("<!>")
} }
buf.push(' '); buf.push(' ');
*position = Position::NextChildAfterText; *position = Position::NextChildAfterText;
} }
} }
} }
)* )*
}; };
} }
@ -323,4 +326,4 @@ impl<R: Renderer> Mountable<R> for ReadGuardStringState<R> {
child.mount(parent, Some(self.node.as_ref())); child.mount(parent, Some(self.node.as_ref()));
true true
} }
} }*/