diff --git a/content/base/public/Element.h b/content/base/public/Element.h index c907f63433e..dc9cc334895 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -38,7 +38,6 @@ #include "nsEvent.h" #include "nsAttrValue.h" #include "mozilla/dom/BindingDeclarations.h" -#include "nsIHTMLCollection.h" #include "Units.h" class nsIDOMEventListener; @@ -600,36 +599,6 @@ public: ErrorResult& aError); already_AddRefed GetElementsByClassName(const nsAString& aClassNames); - Element* GetFirstElementChild() const; - Element* GetLastElementChild() const; - Element* GetPreviousElementSibling() const - { - nsIContent* previousSibling = GetPreviousSibling(); - while (previousSibling) { - if (previousSibling->IsElement()) { - return previousSibling->AsElement(); - } - previousSibling = previousSibling->GetPreviousSibling(); - } - - return nullptr; - } - Element* GetNextElementSibling() const - { - nsIContent* nextSibling = GetNextSibling(); - while (nextSibling) { - if (nextSibling->IsElement()) { - return nextSibling->AsElement(); - } - nextSibling = nextSibling->GetNextSibling(); - } - - return nullptr; - } - uint32_t ChildElementCount() - { - return Children()->Length(); - } bool MozMatchesSelector(const nsAString& aSelector, ErrorResult& aError); void SetCapture(bool aRetargetToElement) diff --git a/content/base/public/FragmentOrElement.h b/content/base/public/FragmentOrElement.h index 9d5691aaa71..ce4df9199da 100644 --- a/content/base/public/FragmentOrElement.h +++ b/content/base/public/FragmentOrElement.h @@ -23,6 +23,7 @@ #include "nsINodeList.h" // base class #include "nsIWeakReference.h" // base class #include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl +#include "nsIHTMLCollection.h" class ContentUnbinder; class nsContentList; @@ -32,7 +33,6 @@ class nsIControllers; class nsICSSDeclaration; class nsIDocument; class nsDOMStringMap; -class nsIHTMLCollection; class nsINodeInfo; class nsIURI; @@ -229,6 +229,10 @@ public: NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE; nsIHTMLCollection* Children(); + uint32_t ChildElementCount() + { + return Children()->Length(); + } public: /** diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 50d7ac13a5e..090f82c92d8 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -53,6 +53,7 @@ class nsIDOMElement; class nsIDOMNodeList; class nsIDOMXPathExpression; class nsIDOMXPathNSResolver; +class nsIHTMLCollection; class nsILayoutHistoryState; class nsIObjectLoadingContent; class nsIObserver; @@ -2120,6 +2121,10 @@ public: void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv); + // ParentNode + nsIHTMLCollection* Children(); + uint32_t ChildElementCount(); + virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; } virtual JSObject* WrapObject(JSContext *aCx, @@ -2211,6 +2216,9 @@ protected: nsPropertyTable mPropertyTable; nsTArray > mExtraPropertyTables; + // Our cached .children collection + nsCOMPtr mChildrenCollection; + // Compatibility mode nsCompatibility mCompatMode; diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 1fe886487c5..73f4df0235f 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -1590,11 +1590,18 @@ public: return rv.ErrorCode(); } + // ChildNode methods + mozilla::dom::Element* GetPreviousElementSibling() const; + mozilla::dom::Element* GetNextElementSibling() const; /** * Remove this node from its parent, if any. */ void Remove(); + // ParentNode methods + mozilla::dom::Element* GetFirstElementChild() const; + mozilla::dom::Element* GetLastElementChild() const; + protected: // Override this function to create a custom slots class. diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index 86f029d5a96..500d36d3620 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -416,34 +416,6 @@ Element::WrapObject(JSContext *aCx, JS::Handle aScope) return obj; } -Element* -Element::GetFirstElementChild() const -{ - uint32_t i, count = mAttrsAndChildren.ChildCount(); - for (i = 0; i < count; ++i) { - nsIContent* child = mAttrsAndChildren.ChildAt(i); - if (child->IsElement()) { - return child->AsElement(); - } - } - - return nullptr; -} - -Element* -Element::GetLastElementChild() const -{ - uint32_t i = mAttrsAndChildren.ChildCount(); - while (i > 0) { - nsIContent* child = mAttrsAndChildren.ChildAt(--i); - if (child->IsElement()) { - return child->AsElement(); - } - } - - return nullptr; -} - nsDOMTokenList* Element::GetClassList() { diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index d75693da740..89b5d714e65 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1793,6 +1793,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection) // Traverse all our nsCOMArrays. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets) @@ -1877,6 +1878,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder) NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection) tmp->mParentDocument = nullptr; @@ -9475,6 +9477,25 @@ nsIDocument::ObsoleteSheet(const nsAString& aSheetURI, ErrorResult& rv) } } +nsIHTMLCollection* +nsIDocument::Children() +{ + if (!mChildrenCollection) { + mChildrenCollection = new nsContentList(this, kNameSpaceID_Wildcard, + nsGkAtoms::_asterix, + nsGkAtoms::_asterix, + false); + } + + return mChildrenCollection; +} + +uint32_t +nsIDocument::ChildElementCount() +{ + return Children()->Length(); +} + namespace mozilla { // Singleton class to manage the list of fullscreen documents which are the diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index d691d2e1b00..c2a94947d8a 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -1404,6 +1404,34 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex, return NS_OK; } +Element* +nsINode::GetPreviousElementSibling() const +{ + nsIContent* previousSibling = GetPreviousSibling(); + while (previousSibling) { + if (previousSibling->IsElement()) { + return previousSibling->AsElement(); + } + previousSibling = previousSibling->GetPreviousSibling(); + } + + return nullptr; +} + +Element* +nsINode::GetNextElementSibling() const +{ + nsIContent* nextSibling = GetNextSibling(); + while (nextSibling) { + if (nextSibling->IsElement()) { + return nextSibling->AsElement(); + } + nextSibling = nextSibling->GetNextSibling(); + } + + return nullptr; +} + void nsINode::Remove() { @@ -1419,6 +1447,34 @@ nsINode::Remove() parent->RemoveChildAt(uint32_t(index), true); } +Element* +nsINode::GetFirstElementChild() const +{ + for (nsIContent* child = GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (child->IsElement()) { + return child->AsElement(); + } + } + + return nullptr; +} + +Element* +nsINode::GetLastElementChild() const +{ + for (nsIContent* child = GetLastChild(); + child; + child = child->GetPreviousSibling()) { + if (child->IsElement()) { + return child->AsElement(); + } + } + + return nullptr; +} + void nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify, nsIContent* aKid, nsAttrAndChildArray& aChildArray) diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index a148bbd3818..0b5ec03fb52 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -249,6 +249,7 @@ MOCHITEST_FILES_A = \ test_bug820909.html \ test_bug704063.html \ test_bug894874.html \ + test_bug895974.html \ $(NULL) MOCHITEST_FILES_B = \ diff --git a/content/base/test/test_bug895974.html b/content/base/test/test_bug895974.html new file mode 100644 index 00000000000..25499d5a2c1 --- /dev/null +++ b/content/base/test/test_bug895974.html @@ -0,0 +1,69 @@ + + + + + + Test for Bug 895974 + + + + + +Mozilla Bug 895974 +

+ +
+
+ + diff --git a/content/media/test/test_playback_rate_playpause.html b/content/media/test/test_playback_rate_playpause.html index b868a04b905..7c58daf9094 100644 --- a/content/media/test/test_playback_rate_playpause.html +++ b/content/media/test/test_playback_rate_playpause.html @@ -14,6 +14,9 @@ if (navigator.platform.startsWith("Win")) { SimpleTest.expectAssertions(0, 1); } else if (navigator.platform.startsWith("Mac")) { SimpleTest.expectAssertions(0, 2); +} else if (navigator.platform.startsWith("Linux")) { + // Bug 897024 + SimpleTest.expectAssertions(0, 2); } let manager = new MediaTestManager; diff --git a/dom/webidl/ChildNode.webidl b/dom/webidl/ChildNode.webidl index 7032dd4160d..76d448656e1 100644 --- a/dom/webidl/ChildNode.webidl +++ b/dom/webidl/ChildNode.webidl @@ -9,9 +9,10 @@ [NoInterfaceObject] interface ChildNode { -// On Element: -// readonly attribute Element? previousElementSibling; -// readonly attribute Element? nextElementSibling; + [Pure] + readonly attribute Element? previousElementSibling; + [Pure] + readonly attribute Element? nextElementSibling; // Not implemented yet: // void before((Node or DOMString)... nodes); diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 91bb605f3c0..81d84c799c7 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -334,3 +334,4 @@ Document implements XPathEvaluator; Document implements GlobalEventHandlers; Document implements NodeEventHandlers; Document implements TouchEventHandlers; +Document implements ParentNode; diff --git a/dom/webidl/DocumentFragment.webidl b/dom/webidl/DocumentFragment.webidl index 8034ea468d5..45efb296861 100644 --- a/dom/webidl/DocumentFragment.webidl +++ b/dom/webidl/DocumentFragment.webidl @@ -29,3 +29,5 @@ partial interface DocumentFragment { [Throws] NodeList querySelectorAll(DOMString selectors); }; + +DocumentFragment implements ParentNode; diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl index c7ea13b5032..e837e867afc 100644 --- a/dom/webidl/Element.webidl +++ b/dom/webidl/Element.webidl @@ -55,19 +55,6 @@ interface Element : Node { HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); - [Constant] - readonly attribute HTMLCollection children; - [Pure] - readonly attribute Element? firstElementChild; - [Pure] - readonly attribute Element? lastElementChild; - [Pure] - readonly attribute Element? previousElementSibling; - [Pure] - readonly attribute Element? nextElementSibling; - [Pure] - readonly attribute unsigned long childElementCount; - /** * The ratio of font-size-inflated text font size to computed font * size for this element. This will query the element for its primary frame, @@ -199,3 +186,4 @@ partial interface Element { }; Element implements ChildNode; +Element implements ParentNode; diff --git a/dom/webidl/ParentNode.webidl b/dom/webidl/ParentNode.webidl new file mode 100644 index 00000000000..da08b749756 --- /dev/null +++ b/dom/webidl/ParentNode.webidl @@ -0,0 +1,24 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://dom.spec.whatwg.org/#interface-parentnode + */ + +[NoInterfaceObject] +interface ParentNode { + [Constant] + readonly attribute HTMLCollection children; + [Pure] + readonly attribute Element? firstElementChild; + [Pure] + readonly attribute Element? lastElementChild; + [Pure] + readonly attribute unsigned long childElementCount; + + // Not implemented yet + // void prepend((Node or DOMString)... nodes); + // void append((Node or DOMString)... nodes); +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index e98f473856a..f69eec7bc26 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -209,6 +209,7 @@ webidl_files = \ PaintRequest.webidl \ PaintRequestList.webidl \ PannerNode.webidl \ + ParentNode.webidl \ Performance.webidl \ PerformanceNavigation.webidl \ PerformanceTiming.webidl \