@@ -196,22 +196,28 @@ impl DynamicDomSlot {
196196 }
197197
198198 fn with_next_sibling < R > ( & self , f : impl FnOnce ( Option < & Node > ) -> R ) -> R {
199- // we use an iterative approach to traverse a possible long chain for references
200- // see for example issue #3043 why a recursive call is impossible for large lists in vdom
201-
202- // TODO: there could be some data structure that performs better here. E.g. a balanced tree
203- // with parent pointers come to mind, but they are a bit fiddly to implement in rust
204- let mut this = self . target . clone ( ) ;
199+ // We use an iterative approach to traverse a possible long chain of references.
200+ // See issue #3043 for why a recursive call is impossible for large lists in vdom.
201+ //
202+ // We traverse via raw pointers to avoid Rc refcount overhead (clone + drop) per hop.
203+ //
204+ // SAFETY: All RefCells in the chain are valid for the duration of this traversal:
205+ // - `self.target` (Rc) is alive because `self` is borrowed
206+ // - Each DomSlot::Chained(DynamicDomSlot { target }) in the chain holds a strong Rc to the
207+ // next RefCell, so all links are transitively kept alive
208+ // - Yew is single-threaded and this function does not yield, so no mutable borrow (e.g.
209+ // from reassign()) can occur on any RefCell in the chain during traversal
210+ // - Each RefCell::borrow() is dropped before advancing to the next hop
211+ let mut ptr: * const RefCell < DomSlot > = Rc :: as_ptr ( & self . target ) ;
205212 loop {
206- // v------- borrow lives for this match expression
207- let next_this = match & this. borrow ( ) . variant {
213+ let cell = unsafe { & * ptr } ;
214+ let slot_ref = cell. borrow ( ) ;
215+ match & slot_ref. variant {
208216 DomSlotVariant :: Node ( ref n) => break f ( n. as_ref ( ) ) ,
209- // We clone an Rc here temporarily, so that we don't have to consume stack
210- // space. The alternative would be to keep the
211- // `Ref<'_, DomSlot>` above in some temporary buffer
212- DomSlotVariant :: Chained ( ref chain) => chain. target . clone ( ) ,
213- } ;
214- this = next_this;
217+ DomSlotVariant :: Chained ( ref chain) => {
218+ ptr = Rc :: as_ptr ( & chain. target ) ;
219+ }
220+ }
215221 }
216222 }
217223}
0 commit comments