Bug 1324983 - Don't persist styles on elements not in the document. r?emilio
MozReview-Commit-ID: 4Z8IxPS6rfE
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -407,28 +407,39 @@ nsXBLService::IsChromeOrResourceURI(nsIU
return false;
}
// RAII class to invoke StyleNewChildren for Elements in Servo-backed documents
// on destruction.
class MOZ_STACK_CLASS AutoStyleNewChildren
{
public:
- explicit AutoStyleNewChildren(Element* aElement) : mElement(aElement) { MOZ_ASSERT(mElement); }
+ explicit AutoStyleNewChildren(Element* aElement, bool aDoIt)
+ : mElement(aElement)
+ , mDoIt(aDoIt)
+ {
+ MOZ_ASSERT(mElement);
+ }
+
~AutoStyleNewChildren()
{
+ if (!mDoIt) {
+ return;
+ }
+
nsIPresShell* presShell = mElement->OwnerDoc()->GetShell();
ServoStyleSet* servoSet = presShell ? presShell->StyleSet()->GetAsServo() : nullptr;
if (servoSet) {
servoSet->StyleNewChildren(mElement);
}
}
private:
Element* mElement;
+ bool mDoIt;
};
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
nsresult
nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal,
nsXBLBinding** aBinding, bool* aResolveStyle)
@@ -457,17 +468,22 @@ nsXBLService::LoadBindings(nsIContent* a
// There are various places in this function where we shuffle content around
// the subtree and rebind things to and from insertion points. Once all that's
// done, we want to invoke StyleNewChildren to style any unstyled children
// that we may have after bindings have been removed and applied. This includes
// anonymous content created in this function, explicit children for which we
// defer styling until after XBL bindings are applied, and elements whose existing
// style was invalidated by a call to SetXBLInsertionParent.
- AutoStyleNewChildren styleNewChildren(aContent->AsElement());
+ //
+ // However, we skip this styling if aContent is not in the document, since we
+ // should keep such elements unstyled. (There are some odd cases where we do
+ // apply bindings to elements not in the document.)
+ AutoStyleNewChildren styleNewChildren(aContent->AsElement(),
+ aContent->IsInComposedDoc());
nsXBLBinding *binding = aContent->GetXBLBinding();
if (binding) {
if (binding->MarkedForDeath()) {
FlushStyleBindings(aContent);
binding = nullptr;
}
else {
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -54,16 +54,22 @@ Gecko_ChildrenCount(RawGeckoNodeBorrowed
}
bool
Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
{
return aNode->IsElement();
}
+bool
+Gecko_IsInDocument(RawGeckoNodeBorrowed aNode)
+{
+ return aNode->IsInComposedDoc();
+}
+
RawGeckoNodeBorrowedOrNull
Gecko_GetParentNode(RawGeckoNodeBorrowed aNode)
{
return aNode->GetFlattenedTreeParentNodeForStyle();
}
RawGeckoNodeBorrowedOrNull
Gecko_GetFirstChild(RawGeckoNodeBorrowed aNode)
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -78,16 +78,17 @@ extern "C" {
// Object refcounting.
NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
// DOM Traversal.
uint32_t Gecko_ChildrenCount(RawGeckoNodeBorrowed node);
bool Gecko_NodeIsElement(RawGeckoNodeBorrowed node);
+bool Gecko_IsInDocument(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetParentNode(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetFirstChild(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetLastChild(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetPrevSibling(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetNextSibling(RawGeckoNodeBorrowed node);
RawGeckoElementBorrowedOrNull Gecko_GetParentElement(RawGeckoElementBorrowed element);
RawGeckoElementBorrowedOrNull Gecko_GetFirstChildElement(RawGeckoElementBorrowed element);
RawGeckoElementBorrowedOrNull Gecko_GetLastChildElement(RawGeckoElementBorrowed element);