/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=4 et sw=2 tw=80: */ /* 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/. */
/* * Implementation of DOM Traversal's TreeWalker
*/
// QueryInterface implementation for TreeWalker
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TreeWalker)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
// Have to pass in dom::TreeWalker because a11y has an a11y::TreeWalker that // passes TreeWalker so refcount logging would get confused on the name // collision.
NS_IMPL_CYCLE_COLLECTING_ADDREF(dom::TreeWalker)
NS_IMPL_CYCLE_COLLECTING_RELEASE(dom::TreeWalker)
while (1) {
nsINode* firstChild; while (filtered != NodeFilter_Binding::FILTER_REJECT &&
(firstChild = node->GetFirstChild())) {
node = firstChild;
filtered = TestNode(node, aResult); if (aResult.Failed()) { return nullptr;
}
if (filtered == NodeFilter_Binding::FILTER_ACCEPT) { // Node found
mCurrentNode = node; return node.forget();
}
}
nsINode* sibling = nullptr;
nsINode* temp = node; do { if (temp == mRoot) break;
sibling = temp->GetNextSibling(); if (sibling) break;
temp = temp->GetParentNode();
} while (temp);
if (!sibling) break;
node = sibling;
// Found a sibling. Either ours or ancestor's
filtered = TestNode(node, aResult); if (aResult.Failed()) { return nullptr;
}
if (filtered == NodeFilter_Binding::FILTER_ACCEPT) { // Node found
mCurrentNode = node; return node.forget();
}
}
return nullptr;
}
/* * TreeWalker helper functions
*/
/* * Implements FirstChild and LastChild which only vary in which direction * they search. * @param aReversed Controls whether we search forwards or backwards * @param aResult Whether we threw or not. * @returns The desired node. Null if no child is found
*/
already_AddRefed<nsINode> TreeWalker::FirstChildInternal(bool aReversed,
ErrorResult& aResult) {
nsCOMPtr<nsINode> node =
aReversed ? mCurrentNode->GetLastChild() : mCurrentNode->GetFirstChild();
while (node) {
int16_t filtered = TestNode(node, aResult); if (aResult.Failed()) { return nullptr;
}
switch (filtered) { case NodeFilter_Binding::FILTER_ACCEPT: // Node found
mCurrentNode = node; return node.forget(); case NodeFilter_Binding::FILTER_SKIP: {
nsINode* child =
aReversed ? node->GetLastChild() : node->GetFirstChild(); if (child) {
node = child; continue;
} break;
} case NodeFilter_Binding::FILTER_REJECT: // Keep searching break;
}
do {
nsINode* sibling =
aReversed ? node->GetPreviousSibling() : node->GetNextSibling(); if (sibling) {
node = sibling; break;
}
/* * Implements NextSibling and PreviousSibling which only vary in which * direction they search. * @param aReversed Controls whether we search forwards or backwards * @param aResult Whether we threw or not. * @returns The desired node. Null if no child is found
*/
already_AddRefed<nsINode> TreeWalker::NextSiblingInternal( bool aReversed, ErrorResult& aResult) {
nsCOMPtr<nsINode> node = mCurrentNode;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.