@@ -1,13 +1,13 @@
11use super::change_list::ChangeList;
2−use super::node::{Attribute, ElementNode, Listener, Node, NodeKind, TextNode};
32use super::RootRender;
3+use crate::cached_set::CachedSet;
44use crate::events::EventsRegistry;
5+use crate::node::Node;
56use crate::RenderContext;
67use bumpalo::Bump;
78use futures::future::Future;
89use std::cell::Cell;
910use std::cell::RefCell;
10−use std::cmp;
1111use std::fmt;
1212use std::mem;
1313use std::mem::ManuallyDrop;
@@ -55,10 +55,11 @@ pub(crate) struct VdomInnerExclusive {
5555 // implementation.
5656 component: Option<Box<RootRender>>,
5757
58− dom_buffers: [Bump; 2],
58+ dom_buffers: Option<[Bump; 2]>,
5959 change_list: ManuallyDrop<ChangeList>,
6060 container: crate::Element,
6161 events_registry: Option<Rc<RefCell<EventsRegistry>>>,
62+ cached_set: crate::RefCell<CachedSet>,
6263
6364 // Actually a reference into `self.dom_buffers[0]` or if `self.component` is
6465 // caching renders, into `self.component`'s bump.
@@ -176,11 +177,12 @@ impl Vdom {
176177 },
177178 exclusive: RefCell::new(VdomInnerExclusive {
178179 component: Some(component),
179− dom_buffers,
180+ dom_buffers: Some(dom_buffers),
180181 change_list,
181182 container,
182183 current_root,
183184 events_registry: None,
185+ cached_set: crate::RefCell::new(Default::default()),
184186 }),
185187 });
186188
@@ -250,33 +252,42 @@ impl VdomInnerExclusive {
250252 pub(crate) fn render(&mut self) {
251253 unsafe {
252254 let events_registry = self.events_registry.take().unwrap();
253−
254255 {
255− // All the old listeners are no longer active. We will build a new
256− // set of active listeners when diffing.
257− //
258− // NB: if we end up avoiding diffing cached renders (instead of just
259− // avoiding re-rendering them) then we will need to maintain cached
260− // active listeners, and can't just clear all active listeners and
261− // rebuild them here.
262256 let mut registry = events_registry.borrow_mut();
263− registry.clear_active_listeners();
264257
265258 // Reset the inactive bump arena's pointer.
266− self.dom_buffers[1].reset();
259+ let mut dom_buffers = self.dom_buffers.take().unwrap_throw();
260+ dom_buffers[1].reset();
267261
268262 // Render the new current contents into the inactive bump arena.
269− let mut cx = RenderContext::new(&self.dom_buffers[1]);
263+ let mut cx = RenderContext::new(&dom_buffers[1], &self.cached_set);
270264 let new_contents = self.component.as_ref().unwrap_throw().render(&mut cx);
271265 let new_contents = extend_node_lifetime(new_contents);
272266
273267 // Diff the old contents with the new contents.
274268 let old_contents = self.current_root.take().unwrap();
275− self.diff(&mut registry, old_contents, new_contents.clone());
269+ let mut cache_roots = bumpalo::collections::Vec::new_in(&dom_buffers[1]);
270+ {
271+ let cached_set = self.cached_set.borrow();
272+ crate::diff::diff(
273+ &cached_set,
274+ &mut self.change_list,
275+ &mut registry,
276+ old_contents,
277+ new_contents.clone(),
278+ &mut cache_roots,
279+ );
280+ }
281+
282+ {
283+ // Clean up unused cached renders.
284+ let mut cached_set = self.cached_set.borrow_mut();
285+ cached_set.gc(&mut registry, &cache_roots);
286+ }
276287
277288 // Swap the buffers to make the bump arena with the new contents the
278289 // active arena, and the old one into the inactive arena.
279− self.swap_buffers();
290+ self.swap_buffers(dom_buffers);
280291 self.set_current_root(new_contents);
281292 }
282293
@@ -290,233 +301,17 @@ impl VdomInnerExclusive {
290301 }
291302 }
292303
293− fn swap_buffers(&mut self) {
294− let (first, second) = self.dom_buffers.as_mut().split_at_mut(1);
304+ fn swap_buffers(&mut self, mut dom_buffers: [Bump; 2]) {
305+ debug_assert!(self.dom_buffers.is_none());
306+ let (first, second) = dom_buffers.as_mut().split_at_mut(1);
295307 mem::swap(&mut first[0], &mut second[0]);
308+ self.dom_buffers = Some(dom_buffers);
296309 }
297310
298311 unsafe fn set_current_root(&mut self, current: Node<'static>) {
299312 debug_assert!(self.current_root.is_none());
300313 self.current_root = Some(current);
301314 }
302−
303− fn diff<'a>(&mut self, registry: &mut EventsRegistry, old: Node<'a>, new: Node<'a>) {
304− match (&new.kind, old.kind) {
305− (
306− &NodeKind::Text(TextNode { text: new_text }),
307− NodeKind::Text(TextNode { text: old_text }),
308− ) => {
309− debug!(" both are text nodes");
310− if new_text != old_text {
311− debug!(" text needs updating");
312− self.change_list.emit_set_text(new_text);
313− }
314− }
315− (&NodeKind::Text(_), NodeKind::Element(_)) => {
316− debug!(" replacing a text node with an element");
317− self.create(registry, new);
318− self.change_list.emit_replace_with();
319− }
320− (&NodeKind::Element(_), NodeKind::Text(_)) => {
321− debug!(" replacing an element with a text node");
322− self.create(registry, new);
323− self.change_list.emit_replace_with();
324− }
325− (
326− &NodeKind::Element(ElementNode {
327− tag_name: new_tag_name,
328− listeners: new_listeners,
329− attributes: new_attributes,
330− children: new_children,
331− namespace: new_namespace,
332− }),
333− NodeKind::Element(ElementNode {
334− tag_name: old_tag_name,
335− listeners: old_listeners,
336− attributes: old_attributes,
337− children: old_children,
338− namespace: old_namespace,
339− }),
340− ) => {
341− debug!(" updating an element");
342− if new_tag_name != old_tag_name || new_namespace != old_namespace {
343− debug!(" different tag names or namespaces; creating new element and replacing old element");
344− self.create(registry, new);
345− self.change_list.emit_replace_with();
346− return;
347− }
348− self.diff_listeners(registry, old_listeners, new_listeners);
349− self.diff_attributes(old_attributes, new_attributes);
350− self.diff_children(registry, old_children, new_children);
351− }
352− }
353− }
354−
355− fn diff_listeners<'a>(
356− &mut self,
357− registry: &mut EventsRegistry,
358− old: &'a [Listener<'a>],
359− new: &'a [Listener<'a>],
360− ) {
361− debug!(" updating event listeners");
362−
363− 'outer1: for new_l in new {
364− unsafe {
365− // Safety relies on removing `new_l` from the registry manually
366− // at the end of its lifetime. This happens when we invoke
367− // `clear_active_listeners` at the start of a new rendering
368− // phase.
369− registry.add(new_l);
370− }
371− for old_l in old {
372− if new_l.event == old_l.event {
373− self.change_list.emit_update_event_listener(new_l);
374− continue 'outer1;
375− }
376− }
377− self.change_list.emit_new_event_listener(new_l);
378− }
379−
380− 'outer2: for old_l in old {
381− for new_l in new {
382− if new_l.event == old_l.event {
383− continue 'outer2;
384− }
385− }
386− self.change_list.emit_remove_event_listener(old_l.event);
387− }
388− }
389−
390− fn diff_attributes(&mut self, old: &[Attribute], new: &[Attribute]) {
391− debug!(" updating attributes");
392−
393− // Do O(n^2) passes to add/update and remove attributes, since
394− // there are almost always very few attributes.
395− 'outer: for new_attr in new {
396− if new_attr.is_volatile() {
397− self.change_list
398− .emit_set_attribute(new_attr.name, new_attr.value);
399− } else {
400− for old_attr in old {
401− if old_attr.name == new_attr.name {
402− if old_attr.value != new_attr.value {
403− self.change_list
404− .emit_set_attribute(new_attr.name, new_attr.value);
405− }
406− continue 'outer;
407− }
408− }
409− self.change_list
410− .emit_set_attribute(new_attr.name, new_attr.value);
411− }
412− }
413−
414− 'outer2: for old_attr in old {
415− for new_attr in new {
416− if old_attr.name == new_attr.name {
417− continue 'outer2;
418− }
419− }
420− self.change_list.emit_remove_attribute(old_attr.name);
421− }
422− }
423−
424− fn diff_children<'a>(
425− &mut self,
426− registry: &mut EventsRegistry,
427− old: &'a [Node<'a>],
428− new: &'a [Node<'a>],
429− ) {
430− debug!(" updating children shared by old and new");
431−
432− let num_children_to_diff = cmp::min(new.len(), old.len());
433− let mut new_children = new.iter();
434− let mut old_children = old.iter();
435− let mut pushed = false;
436−
437− for (i, (new_child, old_child)) in new_children
438− .by_ref()
439− .zip(old_children.by_ref())
440− .take(num_children_to_diff)
441− .enumerate()
442− {
443− if i == 0 {
444− self.change_list.emit_push_first_child();
445− pushed = true;
446− } else {
447− debug_assert!(pushed);
448− self.change_list.emit_pop_push_next_sibling();
449− }
450−
451− self.diff(registry, old_child.clone(), new_child.clone());
452− }
453−
454− if old_children.next().is_some() {
455− debug!(" removing extra old children");
456− debug_assert!(new_children.next().is_none());
457− if !pushed {
458− self.change_list.emit_push_first_child();
459− } else {
460− self.change_list.emit_pop_push_next_sibling();
461− }
462− self.change_list.emit_remove_self_and_next_siblings();
463− pushed = false;
464− } else {
465− debug!(" creating new children");
466− for (i, new_child) in new_children.enumerate() {
467− if i == 0 && pushed {
468− self.change_list.emit_pop();
469− pushed = false;
470− }
471− self.create(registry, new_child.clone());
472− self.change_list.emit_append_child();
473− }
474− }
475−
476− debug!(" done updating children");
477− if pushed {
478− self.change_list.emit_pop();
479− }
480− }
481−
482− fn create<'a>(&mut self, registry: &mut EventsRegistry, node: Node<'a>) {
483− match node.kind {
484− NodeKind::Text(TextNode { text }) => {
485− self.change_list.emit_create_text_node(text);
486− }
487− NodeKind::Element(ElementNode {
488− tag_name,
489− listeners,
490− attributes,
491− children,
492− namespace,
493− }) => {
494− if let Some(namespace) = namespace {
495− self.change_list.emit_create_element_ns(tag_name, namespace);
496− } else {
497− self.change_list.emit_create_element(tag_name);
498− }
499− for l in listeners {
500− unsafe {
501− registry.add(l);
502− }
503− self.change_list.emit_new_event_listener(l);
504− }
505− for attr in attributes {
506− if namespace.is_none() || attr.name.starts_with("xmlns") {
507− self.change_list.emit_set_attribute(&attr.name, &attr.value);
508− } else {
509− self.change_list
510− .emit_set_attribute_ns(&attr.name, &attr.value);
511− }
512− }
513− for child in children {
514− self.create(registry, child.clone());
515− self.change_list.emit_append_child();
516− }
517− }
518− }
519− }
520315}
521316
522317fn request_animation_frame(f: &Closure<FnMut()>) {