@@ -1,18 +1,19 @@
1use crate::{
1use crate::{
2 cached_set::{CacheId, CachedSet},
2 cached_set::{CacheId, CachedSet},
3− change_list::ChangeList,
3+ change_list::ChangeListBuilder,
4 events::EventsRegistry,
4 events::EventsRegistry,
5 node::{Attribute, ElementNode, Listener, Node, NodeKind, TextNode},
5 node::{Attribute, ElementNode, Listener, Node, NodeKind, TextNode},
7use std::cmp;
8use std::cmp;
9pub(crate) fn diff(
10pub(crate) fn diff(
10 cached_set: &CachedSet,
11 cached_set: &CachedSet,
11− change_list: &mut ChangeList,
12+ change_list: &mut ChangeListBuilder,
12 registry: &mut EventsRegistry,
13 registry: &mut EventsRegistry,
13 old: Node,
14 old: Node,
14 new: Node,
15 new: Node,
15− cached_roots: &mut bumpalo::collections::Vec<CacheId>,
16+ cached_roots: &mut FxHashSet<CacheId>,
17 match (&new.kind, &old.kind) {
18 match (&new.kind, &old.kind) {
@@ -22,7 +23,7 @@ pub(crate) fn diff(
22 debug!(" both are text nodes");
23 debug!(" both are text nodes");
23 if new_text != old_text {
24 if new_text != old_text {
24 debug!(" text needs updating");
25 debug!(" text needs updating");
25− change_list.emit_set_text(new_text);
26+ change_list.set_text(new_text);
@@ -30,7 +31,7 @@ pub(crate) fn diff(
30 debug!(" replacing a text node with an element");
31 debug!(" replacing a text node with an element");
31 create(cached_set, change_list, registry, new, cached_roots);
32 create(cached_set, change_list, registry, new, cached_roots);
32 registry.remove_subtree(&old);
33 registry.remove_subtree(&old);
33− change_list.emit_replace_with();
34+ change_list.replace_with();
36 (&NodeKind::Element(_), &NodeKind::Text(_)) => {
37 (&NodeKind::Element(_), &NodeKind::Text(_)) => {
@@ -38,7 +39,7 @@ pub(crate) fn diff(
38 create(cached_set, change_list, registry, new, cached_roots);
39 create(cached_set, change_list, registry, new, cached_roots);
39 // Note: text nodes cannot have event listeners, so we don't need to
40 // Note: text nodes cannot have event listeners, so we don't need to
40 // remove the old node's listeners from our registry her.
41 // remove the old node's listeners from our registry her.
41− change_list.emit_replace_with();
42+ change_list.replace_with();
@@ -62,7 +63,7 @@ pub(crate) fn diff(
62 debug!(" different tag names or namespaces; creating new element and replacing old element");
63 debug!(" different tag names or namespaces; creating new element and replacing old element");
63 create(cached_set, change_list, registry, new, cached_roots);
64 create(cached_set, change_list, registry, new, cached_roots);
64 registry.remove_subtree(&old);
65 registry.remove_subtree(&old);
65− change_list.emit_replace_with();
66+ change_list.replace_with();
68 diff_listeners(change_list, registry, old_listeners, new_listeners);
69 diff_listeners(change_list, registry, old_listeners, new_listeners);
@@ -79,7 +80,7 @@ pub(crate) fn diff(
80 // Both the new and old nodes are cached.
81 // Both the new and old nodes are cached.
81 (&NodeKind::Cached(ref new), &NodeKind::Cached(ref old)) => {
82 (&NodeKind::Cached(ref new), &NodeKind::Cached(ref old)) => {
82− cached_roots.push(new.id);
83+ cached_roots.insert(new.id);
84 if new.id == old.id {
85 if new.id == old.id {
85 // This is the same cached node, so nothing has changed!
86 // This is the same cached node, so nothing has changed!
@@ -95,11 +96,11 @@ pub(crate) fn diff(
95 // we assume that they are pretty different, and it isn't worth diffing
96 // we assume that they are pretty different, and it isn't worth diffing
96 // the subtrees, so we just create the new cached node afresh.
97 // the subtrees, so we just create the new cached node afresh.
97 (&NodeKind::Cached(ref c), _) => {
98 (&NodeKind::Cached(ref c), _) => {
98− cached_roots.push(c.id);
99+ cached_roots.insert(c.id);
99 let new = cached_set.get(c.id);
100 let new = cached_set.get(c.id);
100 create(cached_set, change_list, registry, new, cached_roots);
101 create(cached_set, change_list, registry, new, cached_roots);
101 registry.remove_subtree(&old);
102 registry.remove_subtree(&old);
102− change_list.emit_replace_with();
103+ change_list.replace_with();
105 // Old cached node and new non-cached node. Again, assume that they are
106 // Old cached node and new non-cached node. Again, assume that they are
@@ -107,13 +108,13 @@ pub(crate) fn diff(
107 (_, &NodeKind::Cached(_)) => {
108 (_, &NodeKind::Cached(_)) => {
108 create(cached_set, change_list, registry, new, cached_roots);
109 create(cached_set, change_list, registry, new, cached_roots);
109 registry.remove_subtree(&old);
110 registry.remove_subtree(&old);
110− change_list.emit_replace_with();
111+ change_list.replace_with();
115fn diff_listeners(
116fn diff_listeners(
116− change_list: &mut ChangeList,
117+ change_list: &mut ChangeListBuilder,
117 registry: &mut EventsRegistry,
118 registry: &mut EventsRegistry,
118 old: &[Listener],
119 old: &[Listener],
119 new: &[Listener],
120 new: &[Listener],
@@ -130,12 +131,12 @@ fn diff_listeners(
131 for old_l in old {
132 for old_l in old {
132 if new_l.event == old_l.event {
133 if new_l.event == old_l.event {
133− change_list.emit_update_event_listener(new_l);
134+ change_list.update_event_listener(new_l);
134 continue 'outer1;
135 continue 'outer1;
138− change_list.emit_new_event_listener(new_l);
139+ change_list.new_event_listener(new_l);
141 'outer2: for old_l in old {
142 'outer2: for old_l in old {
@@ -146,28 +147,28 @@ fn diff_listeners(
146 continue 'outer2;
147 continue 'outer2;
149− change_list.emit_remove_event_listener(old_l.event);
150+ change_list.remove_event_listener(old_l.event);
153−fn diff_attributes(change_list: &mut ChangeList, old: &[Attribute], new: &[Attribute]) {
154+fn diff_attributes(change_list: &mut ChangeListBuilder, old: &[Attribute], new: &[Attribute]) {
154 debug!(" updating attributes");
155 debug!(" updating attributes");
156 // Do O(n^2) passes to add/update and remove attributes, since
157 // Do O(n^2) passes to add/update and remove attributes, since
157 // there are almost always very few attributes.
158 // there are almost always very few attributes.
158 'outer: for new_attr in new {
159 'outer: for new_attr in new {
159 if new_attr.is_volatile() {
160 if new_attr.is_volatile() {
160− change_list.emit_set_attribute(new_attr.name, new_attr.value);
161+ change_list.set_attribute(new_attr.name, new_attr.value);
162 for old_attr in old {
163 for old_attr in old {
163 if old_attr.name == new_attr.name {
164 if old_attr.name == new_attr.name {
164 if old_attr.value != new_attr.value {
165 if old_attr.value != new_attr.value {
165− change_list.emit_set_attribute(new_attr.name, new_attr.value);
166+ change_list.set_attribute(new_attr.name, new_attr.value);
167 continue 'outer;
168 continue 'outer;
170− change_list.emit_set_attribute(new_attr.name, new_attr.value);
171+ change_list.set_attribute(new_attr.name, new_attr.value);
@@ -177,17 +178,17 @@ fn diff_attributes(change_list: &mut ChangeList, old: &[Attribute], new: &[Attri
177 continue 'outer2;
178 continue 'outer2;
180− change_list.emit_remove_attribute(old_attr.name);
181+ change_list.remove_attribute(old_attr.name);
184fn diff_children(
185fn diff_children(
185 cached_set: &CachedSet,
186 cached_set: &CachedSet,
186− change_list: &mut ChangeList,
187+ change_list: &mut ChangeListBuilder,
187 registry: &mut EventsRegistry,
188 registry: &mut EventsRegistry,
188 old: &[Node],
189 old: &[Node],
189 new: &[Node],
190 new: &[Node],
190− cached_roots: &mut bumpalo::collections::Vec<CacheId>,
191+ cached_roots: &mut FxHashSet<CacheId>,
192 debug!(" updating children shared by old and new");
193 debug!(" updating children shared by old and new");
@@ -203,11 +204,11 @@ fn diff_children(
203 .enumerate()
204 .enumerate()
205 if i == 0 {
206 if i == 0 {
206− change_list.emit_push_first_child();
207+ change_list.push_first_child();
207 pushed = true;
208 pushed = true;
209 debug_assert!(pushed);
210 debug_assert!(pushed);
210− change_list.emit_pop_push_next_sibling();
211+ change_list.pop_push_next_sibling();
@@ -223,18 +224,18 @@ fn diff_children(
223 if old_children.next().is_some() {
224 if old_children.next().is_some() {
224 debug!(" removing extra old children");
225 debug!(" removing extra old children");
225 debug_assert!(new_children.next().is_none());
226 debug_assert!(new_children.next().is_none());
226− if !pushed {
227+ if pushed {
227− change_list.emit_push_first_child();
228+ change_list.pop_push_next_sibling();
229− change_list.emit_pop_push_next_sibling();
230+ change_list.push_first_child();
231− change_list.emit_remove_self_and_next_siblings();
232+ change_list.remove_self_and_next_siblings();
232 pushed = false;
233 pushed = false;
234 debug!(" creating new children");
235 debug!(" creating new children");
235 for (i, new_child) in new_children.enumerate() {
236 for (i, new_child) in new_children.enumerate() {
236 if i == 0 && pushed {
237 if i == 0 && pushed {
237− change_list.emit_pop();
238+ change_list.pop();
238 pushed = false;
239 pushed = false;
@@ -244,26 +245,26 @@ fn diff_children(
244 new_child.clone(),
245 new_child.clone(),
245 cached_roots,
246 cached_roots,
247− change_list.emit_append_child();
248+ change_list.append_child();
251 debug!(" done updating children");
252 debug!(" done updating children");
252 if pushed {
253 if pushed {
253− change_list.emit_pop();
254+ change_list.pop();
257fn create(
258fn create(
258 cached_set: &CachedSet,
259 cached_set: &CachedSet,
259− change_list: &mut ChangeList,
260+ change_list: &mut ChangeListBuilder,
260 registry: &mut EventsRegistry,
261 registry: &mut EventsRegistry,
261 node: Node,
262 node: Node,
262− cached_roots: &mut bumpalo::collections::Vec<CacheId>,
263+ cached_roots: &mut FxHashSet<CacheId>,
264 match node.kind {
265 match node.kind {
265 NodeKind::Text(TextNode { text }) => {
266 NodeKind::Text(TextNode { text }) => {
266− change_list.emit_create_text_node(text);
267+ change_list.create_text_node(text);
268 NodeKind::Element(ElementNode {
269 NodeKind::Element(ElementNode {
269 tag_name,
270 tag_name,
@@ -273,22 +274,18 @@ fn create(
273 namespace,
274 namespace,
275 if let Some(namespace) = namespace {
276 if let Some(namespace) = namespace {
276− change_list.emit_create_element_ns(tag_name, namespace);
277+ change_list.create_element_ns(tag_name, namespace);
278− change_list.emit_create_element(tag_name);
279+ change_list.create_element(tag_name);
280 for l in listeners {
281 for l in listeners {
282 registry.add(l);
283 registry.add(l);
284− change_list.emit_new_event_listener(l);
285+ change_list.new_event_listener(l);
286 for attr in attributes {
287 for attr in attributes {
287− if namespace.is_none() || attr.name.starts_with("xmlns") {
288+ change_list.set_attribute(&attr.name, &attr.value);
288− change_list.emit_set_attribute(&attr.name, &attr.value);
290− change_list.emit_set_attribute_ns(&attr.name, &attr.value);
293 for child in children {
290 for child in children {
@@ -298,11 +295,11 @@ fn create(
298 child.clone(),
295 child.clone(),
299 cached_roots,
296 cached_roots,
301− change_list.emit_append_child();
298+ change_list.append_child();
304 NodeKind::Cached(c) => {
301 NodeKind::Cached(c) => {
305− cached_roots.push(c.id);
302+ cached_roots.insert(c.id);
306 let node = cached_set.get(c.id);
303 let node = cached_set.get(c.id);
307 create(cached_set, change_list, registry, node, cached_roots)
304 create(cached_set, change_list, registry, node, cached_roots)