зеркало из https://github.com/mozilla/gecko-dev.git
Bug 895974. Implement ParentNode on document fragments and documents and move previousElementSibling and nextElementSibling to ChildNode. r=smaug
This commit is contained in:
Родитель
0314f249cd
Коммит
276a31d596
|
@ -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<nsIHTMLCollection>
|
||||
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)
|
||||
|
|
|
@ -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:
|
||||
/**
|
||||
|
|
|
@ -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<nsAutoPtr<nsPropertyTable> > mExtraPropertyTables;
|
||||
|
||||
// Our cached .children collection
|
||||
nsCOMPtr<nsIHTMLCollection> mChildrenCollection;
|
||||
|
||||
// Compatibility mode
|
||||
nsCompatibility mCompatMode;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -416,34 +416,6 @@ Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> 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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -249,6 +249,7 @@ MOCHITEST_FILES_A = \
|
|||
test_bug820909.html \
|
||||
test_bug704063.html \
|
||||
test_bug894874.html \
|
||||
test_bug895974.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_FILES_B = \
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=895974
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 895974</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 895974 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
var frag = document.createDocumentFragment();
|
||||
var span = document.createElement("span");
|
||||
var div = document.createElement("div");
|
||||
var text = document.createTextNode("help");
|
||||
frag.appendChild(document.createTextNode("fail"));
|
||||
frag.appendChild(span);
|
||||
frag.appendChild(text);
|
||||
frag.appendChild(div);
|
||||
frag.appendChild(document.createTextNode("fail"));
|
||||
|
||||
is(text.nextElementSibling, div, "nextElementSibling should work on text");
|
||||
is(text.previousElementSibling, span,
|
||||
"previousElementSibling should work on text");
|
||||
|
||||
is(document.firstElementChild, document.documentElement,
|
||||
"firstElementChild should work on document");
|
||||
is(document.lastElementChild, document.documentElement,
|
||||
"lastElementChild should work on document");
|
||||
is(document.children.length, 1, "Document has one element kid");
|
||||
is(document.children[0], document.documentElement,
|
||||
"Document only element child is <html>");
|
||||
|
||||
is(frag.firstElementChild, span,
|
||||
"firstElementChild should work on document fragment");
|
||||
is(frag.lastElementChild, div,
|
||||
"lastElementChild should work on document fragment");
|
||||
is(frag.children.length, 2, "Document fragment has two element kids");
|
||||
is(frag.children[0], span, "Document fragment first element child is span");
|
||||
is(frag.children[1], div, "Document fragment second element child is div");
|
||||
|
||||
is(document.documentElement.firstElementChild, document.head,
|
||||
"firstElementChild should work on element");
|
||||
is(document.documentElement.lastElementChild, document.body,
|
||||
"lastElementChild should work on element");
|
||||
is(document.documentElement.children.length, 2, "<html> has two element kids");
|
||||
is(document.documentElement.children[0], document.head,
|
||||
"<html> first element child is head");
|
||||
is(document.documentElement.children[1], document.body,
|
||||
"<html> second element child is body");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=895974">Mozilla Bug 895974</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -334,3 +334,4 @@ Document implements XPathEvaluator;
|
|||
Document implements GlobalEventHandlers;
|
||||
Document implements NodeEventHandlers;
|
||||
Document implements TouchEventHandlers;
|
||||
Document implements ParentNode;
|
||||
|
|
|
@ -29,3 +29,5 @@ partial interface DocumentFragment {
|
|||
[Throws]
|
||||
NodeList querySelectorAll(DOMString selectors);
|
||||
};
|
||||
|
||||
DocumentFragment implements ParentNode;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -209,6 +209,7 @@ webidl_files = \
|
|||
PaintRequest.webidl \
|
||||
PaintRequestList.webidl \
|
||||
PannerNode.webidl \
|
||||
ParentNode.webidl \
|
||||
Performance.webidl \
|
||||
PerformanceNavigation.webidl \
|
||||
PerformanceTiming.webidl \
|
||||
|
|
Загрузка…
Ссылка в новой задаче