author | William Chen <wchen@mozilla.com> |
Mon, 09 Feb 2015 10:01:23 -0800 | |
changeset 228576 | 09b002eaa381c992fa255074d482286a7a935681 |
parent 228575 | a4cf56d0e98ff7059ba78e8fdb34f8494cd01186 |
child 228577 | 7a7e30dbc96cf5e3384f72a69e93e5a705ae4440 |
push id | 28264 |
push user | cbook@mozilla.com |
push date | Wed, 11 Feb 2015 13:58:35 +0000 |
treeherder | mozilla-central@38058cb42a0e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1087460 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -987,31 +987,35 @@ Element::CreateShadowRoot(ErrorResult& a protoBinding->SetInheritsStyle(false); // Calling SetPrototypeBinding takes ownership of protoBinding. docInfo->SetPrototypeBinding(NS_LITERAL_CSTRING("shadowroot"), protoBinding); nsRefPtr<ShadowRoot> shadowRoot = new ShadowRoot(this, nodeInfo.forget(), protoBinding); + shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc()); + // Replace the old ShadowRoot with the new one and let the old // ShadowRoot know about the younger ShadowRoot because the old // ShadowRoot is projected into the younger ShadowRoot's shadow // insertion point (if it exists). ShadowRoot* olderShadow = GetShadowRoot(); SetShadowRoot(shadowRoot); if (olderShadow) { olderShadow->SetYoungerShadow(shadowRoot); // Unbind children of older shadow root because they // are no longer in the composed tree. for (nsIContent* child = olderShadow->GetFirstChild(); child; child = child->GetNextSibling()) { child->UnbindFromTree(true, false); } + + olderShadow->SetIsComposedDocParticipant(false); } // xblBinding takes ownership of docInfo. nsRefPtr<nsXBLBinding> xblBinding = new nsXBLBinding(shadowRoot, protoBinding); shadowRoot->SetAssociatedBinding(xblBinding); xblBinding->SetBoundElement(this); SetXBLBinding(xblBinding); @@ -1573,16 +1577,17 @@ Element::BindToTree(nsIDocument* aDocume if (sheet) { mAttrsAndChildren.SetMappedAttrStyleSheet(sheet); } } // Call BindToTree on shadow root children. ShadowRoot* shadowRoot = GetShadowRoot(); if (shadowRoot) { + shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc()); for (nsIContent* child = shadowRoot->GetFirstChild(); child; child = child->GetNextSibling()) { rv = child->BindToTree(nullptr, shadowRoot, shadowRoot->GetBindingParent(), aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); } } @@ -1630,18 +1635,17 @@ Element::UnbindFromTree(bool aDeep, bool NS_PRECONDITION(aDeep || (!GetUncomposedDoc() && !GetBindingParent()), "Shallow unbind won't clear document and binding parent on " "kids!"); RemoveFromIdTable(); // Make sure to unbind this node before doing the kids nsIDocument* document = - HasFlag(NODE_FORCE_XBL_BINDINGS) || IsInShadowTree() ? - OwnerDoc() : GetUncomposedDoc(); + HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetComposedDoc(); if (aNullParent) { if (IsFullScreenAncestor()) { // The element being removed is an ancestor of the full-screen element, // exit full-screen state. nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"), OwnerDoc(), nsContentUtils::eDOM_PROPERTIES, @@ -1751,16 +1755,18 @@ Element::UnbindFromTree(bool aDeep, bool // Unbind children of shadow root. ShadowRoot* shadowRoot = GetShadowRoot(); if (shadowRoot) { for (nsIContent* child = shadowRoot->GetFirstChild(); child; child = child->GetNextSibling()) { child->UnbindFromTree(true, false); } + + shadowRoot->SetIsComposedDocParticipant(false); } } nsICSSDeclaration* Element::GetSMILOverrideStyle() { Element::nsDOMSlots *slots = DOMSlots();
--- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -62,17 +62,17 @@ NS_INTERFACE_MAP_END_INHERITING(Document NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment) NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment) ShadowRoot::ShadowRoot(nsIContent* aContent, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, nsXBLPrototypeBinding* aProtoBinding) : DocumentFragment(aNodeInfo), mPoolHost(aContent), mProtoBinding(aProtoBinding), mShadowElement(nullptr), - mInsertionPointChanged(false) + mInsertionPointChanged(false), mIsComposedDocParticipant(false) { SetHost(aContent); // Nodes in a shadow tree should never store a value // in the subtree root pointer, nodes in the shadow tree // track the subtree root using GetContainingShadow(). ClearSubtreeRootPointer();
--- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -122,16 +122,22 @@ public: const nsAString& aLocalName); already_AddRefed<nsContentList> GetElementsByClassName(const nsAString& aClasses); void GetInnerHTML(nsAString& aInnerHTML); void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError); Element* Host(); ShadowRoot* GetOlderShadowRoot() { return mOlderShadow; } void StyleSheetChanged(); + + bool IsComposedDocParticipant() { return mIsComposedDocParticipant; } + void SetIsComposedDocParticipant(bool aIsComposedDocParticipant) + { + mIsComposedDocParticipant = aIsComposedDocParticipant; + } protected: virtual ~ShadowRoot(); // The pool host is the parent of the nodes that will be distributed // into the insertion points in this ShadowRoot. See |ChangeShadowRoot|. nsCOMPtr<nsIContent> mPoolHost; // An array of content insertion points that are a descendant of the ShadowRoot @@ -166,16 +172,22 @@ protected: // this ShadowRoot was created. nsRefPtr<ShadowRoot> mYoungerShadow; // A boolean that indicates that an insertion point was added or removed // from this ShadowRoot and that the nodes need to be redistributed into // the insertion points. After this flag is set, nodes will be distributed // on the next mutation event. bool mInsertionPointChanged; + + // Flag to indicate whether the descendants of this shadow root are part of the + // composed document. Ideally, we would use a node flag on nodes to + // mark whether it is in the composed document, but we have run out of flags + // so instead we track it here. + bool mIsComposedDocParticipant; }; class ShadowRootStyleSheetList : public StyleSheetList { public: explicit ShadowRootStyleSheetList(ShadowRoot* aShadowRoot); NS_DECL_ISUPPORTS_INHERITED
--- a/dom/base/nsGenericDOMDataNode.cpp +++ b/dom/base/nsGenericDOMDataNode.cpp @@ -108,16 +108,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_ if (slots) { slots->Traverse(cb); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode) nsINode::Unlink(tmp); + // Clear flag here because unlinking slots will clear the + // containing shadow root pointer. + tmp->UnsetFlags(NODE_IS_IN_SHADOW_TREE); + nsDataSlots *slots = tmp->GetExistingDataSlots(); if (slots) { slots->Unlink(); } NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY @@ -557,18 +561,17 @@ nsGenericDOMDataNode::BindToTree(nsIDocu void nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent) { // Unset frame flags; if we need them again later, they'll get set again. UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE); nsIDocument* document = - HasFlag(NODE_FORCE_XBL_BINDINGS) || IsInShadowTree() ? - OwnerDoc() : GetUncomposedDoc(); + HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetComposedDoc(); if (aNullParent) { if (GetParent()) { NS_RELEASE(mParent); } else { mParent = nullptr; } SetParentIsContent(false);
--- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -385,27 +385,18 @@ nsINode::GetTextContentInternal(nsAStrin } nsIDocument* nsINode::GetComposedDocInternal() const { MOZ_ASSERT(HasFlag(NODE_IS_IN_SHADOW_TREE) && IsContent(), "Should only be caled on nodes in the shadow tree."); - // Cross ShadowRoot boundary. ShadowRoot* containingShadow = AsContent()->GetContainingShadow(); - - nsIContent* poolHost = containingShadow->GetPoolHost(); - if (!poolHost) { - // This node is in an older shadow root that does not get projected into - // an insertion point, thus this node can not be in the composed document. - return nullptr; - } - - return poolHost->GetComposedDoc(); + return containingShadow->IsComposedDocParticipant() ? OwnerDoc() : nullptr; } #ifdef DEBUG void nsINode::CheckNotNativeAnonymous() const { if (!IsNodeOfType(eCONTENT)) return;
--- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -515,21 +515,19 @@ public: * @deprecated */ nsIDocument *GetCurrentDoc() const { return GetUncomposedDoc(); } /** - * This method gets the current doc of the node hosting this content - * or the current doc of this content if it is not being hosted. This - * method walks through ShadowRoot boundaries until it reach the host - * that is located in the root of the "tree of trees" (see Shadow DOM - * spec) and returns the current doc for that host. + * This method returns the owner doc if the node is in the + * composed document (as defined in the Shadow DOM spec), otherwise + * it returns null. */ nsIDocument* GetComposedDoc() const { return IsInShadowTree() ? GetComposedDocInternal() : GetUncomposedDoc(); } /**
--- a/dom/html/HTMLShadowElement.cpp +++ b/dom/html/HTMLShadowElement.cpp @@ -141,16 +141,18 @@ HTMLShadowElement::BindToTree(nsIDocumen containingShadow->SetInsertionPointChanged(); } if (mIsInsertionPoint && containingShadow) { // Propagate BindToTree calls to projected shadow root children. ShadowRoot* projectedShadow = containingShadow->GetOlderShadowRoot(); if (projectedShadow) { + projectedShadow->SetIsComposedDocParticipant(IsInComposedDoc()); + for (nsIContent* child = projectedShadow->GetFirstChild(); child; child = child->GetNextSibling()) { rv = child->BindToTree(nullptr, projectedShadow, projectedShadow->GetBindingParent(), aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); } } @@ -168,16 +170,18 @@ HTMLShadowElement::UnbindFromTree(bool a // Propagate UnbindFromTree call to previous projected shadow // root children. ShadowRoot* projectedShadow = oldContainingShadow->GetOlderShadowRoot(); if (projectedShadow) { for (nsIContent* child = projectedShadow->GetFirstChild(); child; child = child->GetNextSibling()) { child->UnbindFromTree(true, false); } + + projectedShadow->SetIsComposedDocParticipant(false); } } nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); if (oldContainingShadow && !GetContainingShadow() && mIsInsertionPoint) { nsTArray<HTMLShadowElement*>& shadowDescendants = oldContainingShadow->ShadowDescendants();
--- a/dom/html/HTMLStyleElement.cpp +++ b/dom/html/HTMLStyleElement.cpp @@ -152,25 +152,24 @@ HTMLStyleElement::BindToTree(nsIDocument return rv; } void HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent) { nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc(); - nsCOMPtr<nsIDocument> oldComposedDoc = GetComposedDoc(); ShadowRoot* oldShadow = GetContainingShadow(); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); - if (GetContainingShadow() && !oldComposedDoc) { - // The style is in a shadow tree and was already not - // in the composed document. Thus the sheet does not - // need to be updated. + if (oldShadow && GetContainingShadow()) { + // The style is in a shadow tree and is still in the + // shadow tree. Thus the sheets in the shadow DOM + // do not need to be updated. return; } UpdateStyleSheetInternal(oldDoc, oldShadow); } nsresult HTMLStyleElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,