Skip to content

Commit

Permalink
Bug 1873649: Do not eagerly seek prev and next siblings DOM mutation …
Browse files Browse the repository at this point in the history
…invalidation. r=firefox-style-system-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D198052
  • Loading branch information
dshin-moz committed Jan 11, 2024
1 parent 7d70fa6 commit 966bb4e
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 18 deletions.
15 changes: 6 additions & 9 deletions layout/base/RestyleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,17 +440,9 @@ void RestyleManager::ContentRemoved(nsIContent* aOldChild,
// invalidated.
IncrementUndisplayedRestyleGeneration();
}
Element* nextSibling = aFollowingSibling
? aFollowingSibling->IsElement()
? aFollowingSibling->AsElement()
: aFollowingSibling->GetNextElementSibling()
: nullptr;
if (aOldChild->IsElement()) {
Element* prevSibling = aFollowingSibling
? aFollowingSibling->GetPreviousElementSibling()
: container->GetLastElementChild();
StyleSet()->MaybeInvalidateForElementRemove(*aOldChild->AsElement(),
prevSibling, nextSibling);
aFollowingSibling);
}

const auto selectorFlags =
Expand Down Expand Up @@ -512,6 +504,11 @@ void RestyleManager::ContentRemoved(nsIContent* aOldChild,
// Restyle all later siblings.
RestyleSiblingsStartingWith(aFollowingSibling);
if (selectorFlags & NodeSelectorFlags::HasSlowSelectorNthAll) {
Element* nextSibling =
aFollowingSibling ? aFollowingSibling->IsElement()
? aFollowingSibling->AsElement()
: aFollowingSibling->GetNextElementSibling()
: nullptr;
StyleSet()->MaybeInvalidateRelativeSelectorForNthDependencyFromSibling(
nextSibling);
}
Expand Down
5 changes: 2 additions & 3 deletions layout/style/ServoStyleSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1441,10 +1441,9 @@ void ServoStyleSet::MaybeInvalidateForElementAppend(const Element& aElement) {
}

void ServoStyleSet::MaybeInvalidateForElementRemove(
const Element& aElement, const Element* aPrevSibling,
const Element* aNextSibling) {
const Element& aElement, const nsIContent* aFollowingSibling) {
Servo_StyleSet_MaybeInvalidateRelativeSelectorForRemoval(
mRawData.get(), &aElement, aPrevSibling, aNextSibling);
mRawData.get(), &aElement, aFollowingSibling);
}

bool ServoStyleSet::MightHaveNthOfAttributeDependency(
Expand Down
3 changes: 1 addition & 2 deletions layout/style/ServoStyleSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,7 @@ class ServoStyleSet {
* the relative selector to ancestors/previous siblings.
*/
void MaybeInvalidateForElementRemove(const dom::Element& aElement,
const dom::Element* aPrevSibling,
const dom::Element* aNextSibling);
const nsIContent* aFollowingSibling);

/**
* Returns true if a change in event state on an element might require
Expand Down
39 changes: 39 additions & 0 deletions servo/components/style/gecko/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,45 @@ impl<'ln> GeckoNode<'ln> {
fn contains_non_whitespace_content(&self) -> bool {
unsafe { Gecko_IsSignificantChild(self.0, false) }
}

/// Returns the previous sibling of this node that is an element.
#[inline]
pub fn prev_sibling_element(&self) -> Option<GeckoElement> {
let mut prev = self.prev_sibling();
while let Some(p) = prev {
if let Some(e) = p.as_element() {
return Some(e);
}
prev = p.prev_sibling();
}
None
}

/// Returns the next sibling of this node that is an element.
#[inline]
pub fn next_sibling_element(&self) -> Option<GeckoElement> {
let mut next = self.next_sibling();
while let Some(n) = next {
if let Some(e) = n.as_element() {
return Some(e);
}
next = n.next_sibling();
}
None
}

/// Returns last child sibling of this node that is an element.
#[inline]
pub fn last_child_element(&self) -> Option<GeckoElement<'ln>> {
let last = match self.last_child() {
Some(n) => n,
None => return None,
};
if let Some(e) = last.as_element() {
return Some(e);
}
None
}
}

impl<'ln> NodeInfo for GeckoNode<'ln> {
Expand Down
29 changes: 25 additions & 4 deletions servo/ports/geckolib/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7383,17 +7383,38 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForAppend(
}
}

fn get_siblings_of_element<'e>(
element: GeckoElement<'e>,
following_node: &'e Option<GeckoNode<'e>>,
) -> (Option<GeckoElement<'e>>, Option<GeckoElement<'e>>) {
let node = match following_node {
Some(n) => n,
None => return match element.as_node().parent_node() {
Some(p) => (p.last_child_element(), None),
None => (None, None),
},
};

(node.prev_sibling_element(), node.next_sibling_element())
}

#[no_mangle]
pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForRemoval(
raw_data: &PerDocumentStyleData,
element: &RawGeckoElement,
prev_sibling: Option<&RawGeckoElement>,
next_sibling: Option<&RawGeckoElement>,
following_node: Option<&RawGeckoNode>,
) {
let element = GeckoElement(element);

let next_sibling = next_sibling.map(|e| GeckoElement(e));
let prev_sibling = prev_sibling.map(|e| GeckoElement(e));
// This element was in-tree, so we can safely say that if it was not on
// the relative selector search path, its removal will not invalidate any
// relative selector.
if element.relative_selector_search_direction().is_none() {
return;
}
let following_node = following_node.map(GeckoNode);
let (prev_sibling, next_sibling) =
get_siblings_of_element(element, &following_node);
let data = raw_data.borrow();
let quirks_mode: QuirksMode = data.stylist.quirks_mode();

Expand Down

0 comments on commit 966bb4e

Please sign in to comment.