blitz_dom/mutation_record.rs
1//! Changes to the document, recorded for a script's `MutationObserver`.
2//!
3//! Recording happens in [`crate::DocumentMutator`], because every change
4//! reaches the tree through it: a script's `appendChild`, `innerHTML` and
5//! `setAttribute`, the parser, and the embedder alike. Hooking the script
6//! bindings instead would miss whichever path a binding does not own.
7//!
8//! Two rules keep the log honest and cheap:
9//!
10//! - It is recorded only while the embedder has switched it on
11//! ([`crate::BaseDocument::set_recording_mutations`]), which a script runtime
12//! does while at least one observer is registered. A page with no observers
13//! pays one branch per change.
14//! - Only changes to a node that is in the document are recorded. Building a
15//! detached fragment and then inserting it therefore yields one record for
16//! the insertion, which is what a browser reports, rather than one per node
17//! the fragment was built from. The cost is that an observer watching a
18//! detached node directly hears nothing, which no framework relies on.
19
20use crate::NodeId;
21
22/// One change, in the shape a `MutationRecord` needs.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum DomMutation {
25 /// Children were added to or removed from `target`.
26 ChildList {
27 target: NodeId,
28 added: Vec<NodeId>,
29 removed: Vec<NodeId>,
30 previous_sibling: Option<NodeId>,
31 next_sibling: Option<NodeId>,
32 },
33 /// An attribute of `target` was set or removed. `old_value` is `None` when
34 /// the attribute did not exist before.
35 Attributes {
36 target: NodeId,
37 name: String,
38 old_value: Option<String>,
39 },
40 /// The text of a text or comment node changed.
41 CharacterData { target: NodeId, old_value: String },
42}
43
44/// The most records held between deliveries. A page that rewrites a large
45/// tree while observed without ever yielding to its job queue would otherwise
46/// grow this without bound; past the cap, further changes in that turn are
47/// dropped rather than stored.
48pub(crate) const MUTATION_LOG_CAP: usize = 100_000;