From 61571ed24bca0538ecff8a3601e29c8ba7894eb4 Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Wed, 19 Nov 2025 19:56:44 -0500 Subject: [PATCH] fix: improve marker-node filtering when using islands router (closes #4443) (#4446) --- tachys/src/hydration.rs | 40 ++++++++++++++++++++++++++++++++----- tachys/src/view/any_view.rs | 16 +-------------- tachys/src/view/either.rs | 30 ++-------------------------- tachys/src/view/keyed.rs | 28 -------------------------- 4 files changed, 38 insertions(+), 76 deletions(-) diff --git a/tachys/src/hydration.rs b/tachys/src/hydration.rs index ba9aed73c..8e393af0f 100644 --- a/tachys/src/hydration.rs +++ b/tachys/src/hydration.rs @@ -7,6 +7,9 @@ use std::cell::Cell; use std::{cell::RefCell, panic::Location, rc::Rc}; use web_sys::{Comment, Element, Node, Text}; +#[cfg(feature = "mark_branches")] +const COMMENT_NODE: u16 = 8; + /// Hydration works by walking over the DOM, adding interactivity as needed. /// /// This cursor tracks the location in the DOM that is currently being hydrated. Each that type @@ -43,13 +46,27 @@ where /// /// Does nothing if there is no child. pub fn child(&self) { - //crate::log("advancing to next child of "); - //Rndr::log_node(&self.current()); let mut inner = self.0.borrow_mut(); if let Some(node) = Rndr::first_child(&inner) { *inner = node; } - //drop(inner); + + #[cfg(feature = "mark_branches")] + { + while inner.node_type() == COMMENT_NODE { + if let Some(content) = inner.text_content() { + if content.starts_with("bo") || content.starts_with("bc") { + if let Some(sibling) = Rndr::next_sibling(&inner) { + *inner = sibling; + continue; + } + } + } + + break; + } + } + // //drop(inner); //crate::log(">> which is "); //Rndr::log_node(&self.current()); } @@ -58,12 +75,25 @@ where /// /// Does nothing if there is no sibling. pub fn sibling(&self) { - //crate::log("advancing to next sibling of "); - //Rndr::log_node(&self.current()); let mut inner = self.0.borrow_mut(); if let Some(node) = Rndr::next_sibling(&inner) { *inner = node; } + + #[cfg(feature = "mark_branches")] + { + while inner.node_type() == COMMENT_NODE { + if let Some(content) = inner.text_content() { + if content.starts_with("bo") || content.starts_with("bc") { + if let Some(sibling) = Rndr::next_sibling(&inner) { + *inner = sibling; + continue; + } + } + } + break; + } + } //drop(inner); //crate::log(">> which is "); //Rndr::log_node(&self.current()); diff --git a/tachys/src/view/any_view.rs b/tachys/src/view/any_view.rs index 449937447..8289b406e 100644 --- a/tachys/src/view/any_view.rs +++ b/tachys/src/view/any_view.rs @@ -575,15 +575,7 @@ impl RenderHtml for AnyView { #[cfg(feature = "hydrate")] { if FROM_SERVER { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - let state = - (self.hydrate_from_server)(self.value, cursor, position); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - state + (self.hydrate_from_server)(self.value, cursor, position) } else { panic!( "hydrating AnyView from inside a ViewTemplate is not \ @@ -609,14 +601,8 @@ impl RenderHtml for AnyView { ) -> Self::State { #[cfg(feature = "hydrate")] { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } let state = (self.hydrate_async)(self.value, cursor, position).await; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } state } #[cfg(not(feature = "hydrate"))] diff --git a/tachys/src/view/either.rs b/tachys/src/view/either.rs index 51a35e6b8..a78aeacc5 100644 --- a/tachys/src/view/either.rs +++ b/tachys/src/view/either.rs @@ -411,21 +411,14 @@ where cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - let state = match self { + match self { Either::Left(left) => { Either::Left(left.hydrate::(cursor, position)) } Either::Right(right) => { Either::Right(right.hydrate::(cursor, position)) } - }; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); } - state } async fn hydrate_async( @@ -433,21 +426,14 @@ where cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - let state = match self { + match self { Either::Left(left) => { Either::Left(left.hydrate_async(cursor, position).await) } Either::Right(right) => { Either::Right(right.hydrate_async(cursor, position).await) } - }; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); } - state } fn into_owned(self) -> Self::Owned { @@ -973,17 +959,11 @@ macro_rules! tuples { cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } let state = match self { $([]::$ty(this) => { []::$ty(this.hydrate::(cursor, position)) })* }; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } Self::State { state } } @@ -993,17 +973,11 @@ macro_rules! tuples { cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } let state = match self { $([]::$ty(this) => { []::$ty(this.hydrate_async(cursor, position).await) })* }; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } Self::State { state } } diff --git a/tachys/src/view/keyed.rs b/tachys/src/view/keyed.rs index acd499c25..29f552526 100644 --- a/tachys/src/view/keyed.rs +++ b/tachys/src/view/keyed.rs @@ -322,10 +322,6 @@ where cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - // get parent and position let current = cursor.current(); let parent = if position.get() == Position::FirstChild { @@ -346,22 +342,12 @@ where for (index, item) in items.enumerate() { hashed_items.insert((self.key_fn)(&item)); let (set_index, view) = (self.view_fn)(index, item); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } let item = view.hydrate::(cursor, position); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } rendered_items.push(Some((set_index, item))); } let marker = cursor.next_placeholder(position); position.set(Position::NextChild); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - KeyedState { parent: Some(parent), marker, @@ -375,10 +361,6 @@ where cursor: &Cursor, position: &PositionState, ) -> Self::State { - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - // get parent and position let current = cursor.current(); let parent = if position.get() == Position::FirstChild { @@ -399,22 +381,12 @@ where for (index, item) in items.enumerate() { hashed_items.insert((self.key_fn)(&item)); let (set_index, view) = (self.view_fn)(index, item); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } let item = view.hydrate_async(cursor, position).await; - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } rendered_items.push(Some((set_index, item))); } let marker = cursor.next_placeholder(position); position.set(Position::NextChild); - if cfg!(feature = "mark_branches") { - cursor.advance_to_placeholder(position); - } - KeyedState { parent: Some(parent), marker,