Avoid rooting/unrooting in Node::rev_version (#37885)

The iterator produced by Node::inclusive_ancestors roots the items but
rev_version just drop and unroot them right away. This patch makes it
possible to work on the Node references instead to avoid rooting.

*Describe the changes that this pull request makes here. This will be
the commit message.*

Testing: *Describe how this pull request is tested or why it doesn't
require tests*
Fixes: *Link to an issue this pull requests fixes or remove this line if
there is no issue*

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2025-07-11 00:46:23 -07:00 committed by GitHub
parent edfacec9c8
commit 3c1bc1a92d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 2 deletions

View file

@ -291,6 +291,20 @@ impl<T: DomObject> MutNullableDom<T> {
self.set(None);
value
}
/// Runs the given callback on the object if it's not null.
pub(crate) fn if_is_some<F, R>(&self, cb: F) -> Option<&R>
where
F: FnOnce(&T) -> &R,
{
unsafe {
if let Some(ref value) = *self.ptr.get() {
Some(cb(value))
} else {
None
}
}
}
}
impl<T: DomObject> PartialEq for MutNullableDom<T> {

View file

@ -796,8 +796,15 @@ impl Node {
self.inclusive_descendants_version(),
doc.inclusive_descendants_version(),
) + 1;
for ancestor in self.inclusive_ancestors(ShadowIncluding::No) {
ancestor.inclusive_descendants_version.set(version);
// This `while` loop is equivalent to iterating over the non-shadow-inclusive ancestors
// without creating intermediate rooted DOM objects.
let mut node = &MutNullableDom::new(Some(self));
while let Some(p) = node.if_is_some(|p| {
p.inclusive_descendants_version.set(version);
&p.parent_node
}) {
node = p
}
doc.inclusive_descendants_version.set(version);
}