From 72a1d3ff817e6875e25187225cc7cb6aeb8fd881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 22 Nov 2017 14:15:34 +0100 Subject: [PATCH] Bug 1419554: Teach the restyle root code about elements outside of the flattened tree. r=heycam The textarea is inserted under a Shadow host, with no matching insertion point, so its flattened tree parent node is null. We're treating this case in the restyle root code as "the parent is the document", but that's very wrong. MozReview-Commit-ID: JlzUMRIYaYZ --HG-- extra : rebase_source : feeaf7a7333097aa87b35358172472790f6c74a7 --- dom/base/Element.cpp | 22 ++++++++++++++++------ layout/style/ServoStyleSet.cpp | 17 +++++++++++------ layout/style/crashtests/1419554.html | 9 +++++++++ layout/style/crashtests/crashtests.list | 1 + 4 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 layout/style/crashtests/1419554.html diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 50f5144a7307..d460e80f729f 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -4660,12 +4660,17 @@ NoteDirtyElement(Element* aElement, uint32_t aBits) MOZ_ASSERT(aElement->IsInComposedDoc()); MOZ_ASSERT(aElement->IsStyledByServo()); - Element* parent = aElement->GetFlattenedTreeParentElementForStyle(); - if (MOZ_LIKELY(parent)) { + nsINode* parent = aElement->GetFlattenedTreeParentNodeForStyle(); + if (!parent) { + // The element is not in the flattened tree, bail. + return; + } + + if (MOZ_LIKELY(parent->IsElement())) { // If our parent is unstyled, we can inductively assume that it will be // traversed when the time is right, and that the traversal will reach us // when it happens. Nothing left to do. - if (!parent->HasServoData()) { + if (!parent->AsElement()->HasServoData()) { return; } @@ -4688,7 +4693,7 @@ NoteDirtyElement(Element* aElement, uint32_t aBits) // order to avoid work here, because since the style system keeps style data // in, e.g., subtrees under a leaf frame, missing restyles and such in there // has observable behavior via getComputedStyle, for example. - if (Servo_Element_IsDisplayNone(parent)) { + if (Servo_Element_IsDisplayNone(parent->AsElement())) { return; } } @@ -4698,6 +4703,8 @@ NoteDirtyElement(Element* aElement, uint32_t aBits) shell->EnsureStyleFlush(); } + MOZ_ASSERT(parent->IsElement() || parent == doc); + nsINode* existingRoot = doc->GetServoRestyleRoot(); uint32_t existingBits = existingRoot ? doc->GetServoRestyleRootDirtyBits() : 0; @@ -4714,7 +4721,9 @@ NoteDirtyElement(Element* aElement, uint32_t aBits) // There is an existing restyle root - walk up the tree from our element, // propagating bits as we go. - const bool reachedDocRoot = !parent || !PropagateBits(parent, aBits, existingRoot); + const bool reachedDocRoot = + !parent->IsElement() || + !PropagateBits(parent->AsElement(), aBits, existingRoot); if (!reachedDocRoot || existingRoot == doc) { // We're a descendant of the existing root. All that's left to do is to @@ -4753,7 +4762,8 @@ NoteDirtyElement(Element* aElement, uint32_t aBits) aElement, doc->GetServoRestyleRoot())); MOZ_ASSERT(aElement == doc->GetServoRestyleRoot() || !doc->GetServoRestyleRoot()->IsElement() || - BitsArePropagated(parent, aBits, doc->GetServoRestyleRoot())); + !parent->IsElement() || + BitsArePropagated(parent->AsElement(), aBits, doc->GetServoRestyleRoot())); MOZ_ASSERT(doc->GetServoRestyleRootDirtyBits() & aBits); } diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index d27335de676f..3993d06e4026 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -1344,16 +1344,21 @@ ServoStyleSet::MaybeGCRuleTree() ServoStyleSet::MayTraverseFrom(const Element* aElement) { MOZ_ASSERT(aElement->IsInComposedDoc()); - Element* parent = aElement->GetFlattenedTreeParentElementForStyle(); + nsINode* parent = aElement->GetFlattenedTreeParentNodeForStyle(); if (!parent) { - return true; - } - - if (!parent->HasServoData()) { return false; } - return !Servo_Element_IsDisplayNone(parent); + if (!parent->IsElement()) { + MOZ_ASSERT(parent->IsNodeOfType(nsINode::eDOCUMENT)); + return true; + } + + if (!parent->AsElement()->HasServoData()) { + return false; + } + + return !Servo_Element_IsDisplayNone(parent->AsElement()); } bool diff --git a/layout/style/crashtests/1419554.html b/layout/style/crashtests/1419554.html new file mode 100644 index 000000000000..3a9b917c1989 --- /dev/null +++ b/layout/style/crashtests/1419554.html @@ -0,0 +1,9 @@ + + +
+
diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index e528395d77e4..45a5d712c91b 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -265,3 +265,4 @@ pref(dom.webcomponents.enabled,true) load 1415353.html load 1415021.html # This should have dom.webcomponents.enabled=true, but it leaks the world, see bug 1416296. load 1418059.html skip-if(!stylo) test-pref(dom.animations-api.core.enabled,true) load 1418867.html +pref(dom.webcomponents.enabled,true) load 1419554.html