/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 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/. */
/** * ContentIteratorBase is a base class of PostContentIterator, * PreContentIterator and ContentSubtreeIterator. Making each concrete * classes "final", compiler can avoid virtual calls if they are treated * by the users directly.
*/ template <typename NodeType> class ContentIteratorBase { public:
ContentIteratorBase() = delete;
ContentIteratorBase(const ContentIteratorBase&) = delete;
ContentIteratorBase& operator=(const ContentIteratorBase&) = delete; virtual ~ContentIteratorBase();
/** * Callers must guarantee that: * - Neither aStartContainer nor aEndContainer is nullptr. * - aStartOffset and aEndOffset are valid for its container. * - The start point and the end point are in document order.
*/
[[nodiscard]] nsresult InitInternal(const RawRangeBoundary& aStart, const RawRangeBoundary& aEnd);
// Recursively get the deepest first/last child of aRoot. This will return // aRoot itself if it has no children. static nsINode* GetDeepFirstChild(nsINode* aRoot); // If aAllowCrossShadowBoundary is true, it'll continue with the shadow tree // when it reaches to a shadow host. static nsIContent* GetDeepFirstChild(nsIContent* aRoot, bool aAllowCrossShadowBoundary); static nsINode* GetDeepLastChild(nsINode* aRoot); // If aAllowCrossShadowBoundary is true, it'll continue with the shadow tree // when it reaches to a shadow host. static nsIContent* GetDeepLastChild(nsIContent* aRoot, bool aAllowCrossShadowBoundary);
// Get the next/previous sibling of aNode, or its parent's, or grandparent's, // etc. Returns null if aNode and all its ancestors have no next/previous // sibling. // // If aAllowCrossShadowBoundary is true, it'll continue with the shadow host // when it reaches to a shadow root. static nsIContent* GetNextSibling(nsINode* aNode, bool aAllowCrossShadowBoundary = false); static nsIContent* GetPrevSibling(nsINode* aNode, bool aAllowCrossShadowBoundary = false);
// Each concrete class of ContentIteratorBase<RefPtr<nsINode>> may be owned by // another class which may be owned by JS. Therefore, all of them should be in // the cycle collection. However, we cannot make non-refcountable classes only // with the macros. So, we need to make them cycle collectable without the // macros. template <typename NodeType> void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
ContentIteratorBase<NodeType>& aField, constchar* aName, uint32_t aFlags = 0) {
ImplCycleCollectionTraverse(aCallback, aField.mCurNode, aName, aFlags);
ImplCycleCollectionTraverse(aCallback, aField.mFirst, aName, aFlags);
ImplCycleCollectionTraverse(aCallback, aField.mLast, aName, aFlags);
ImplCycleCollectionTraverse(aCallback, aField.mClosestCommonInclusiveAncestor,
aName, aFlags);
}
using SafeContentIteratorBase = ContentIteratorBase<RefPtr<nsINode>>; using UnsafeContentIteratorBase = ContentIteratorBase<nsINode*>;
/** * A simple iterator class for traversing the content in "close tag" order.
*/ class PostContentIterator final : public SafeContentIteratorBase { public:
PostContentIterator() : SafeContentIteratorBase(Order::Post) {}
PostContentIterator(const PostContentIterator&) = delete;
PostContentIterator& operator=(const PostContentIterator&) = delete; virtual ~PostContentIterator() = default; friendvoid ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
PostContentIterator&, constchar*,
uint32_t); friendvoid ImplCycleCollectionUnlink(PostContentIterator&);
};
/** * Different from PostContentIterator, UnsafePostContentIterator does not * grab nodes with strong pointers. Therefore, the user needs to guarantee * that script won't run while this is alive.
*/ class MOZ_STACK_CLASS UnsafePostContentIterator final
: public UnsafeContentIteratorBase { public:
UnsafePostContentIterator() : UnsafeContentIteratorBase(Order::Post) {}
UnsafePostContentIterator(const UnsafePostContentIterator&) = delete;
UnsafePostContentIterator& operator=(const UnsafePostContentIterator&) = delete; virtual ~UnsafePostContentIterator() = default;
};
/** * A simple iterator class for traversing the content in "start tag" order.
*/ class PreContentIterator final : public SafeContentIteratorBase { public:
PreContentIterator() : ContentIteratorBase(Order::Pre) {}
PreContentIterator(const PreContentIterator&) = delete;
PreContentIterator& operator=(const PreContentIterator&) = delete; virtual ~PreContentIterator() = default; friendvoid ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
PreContentIterator&, constchar*,
uint32_t); friendvoid ImplCycleCollectionUnlink(PreContentIterator&);
};
/** * Different from PostContentIterator, UnsafePostContentIterator does not * grab nodes with strong pointers. Therefore, the user needs to guarantee * that script won't run while this is alive.
*/ class MOZ_STACK_CLASS UnsafePreContentIterator final
: public UnsafeContentIteratorBase { public:
UnsafePreContentIterator() : UnsafeContentIteratorBase(Order::Pre) {}
UnsafePreContentIterator(const UnsafePostContentIterator&) = delete;
UnsafePreContentIterator& operator=(const UnsafePostContentIterator&) = delete; virtual ~UnsafePreContentIterator() = default;
};
/** * A simple iterator class for traversing the content in "top subtree" order.
*/ class ContentSubtreeIterator final : public SafeContentIteratorBase { public:
ContentSubtreeIterator() : SafeContentIteratorBase(Order::Pre) {}
ContentSubtreeIterator(const ContentSubtreeIterator&) = delete;
ContentSubtreeIterator& operator=(const ContentSubtreeIterator&) = delete; virtual ~ContentSubtreeIterator() = default;
/** * Initialize the iterator with aRange that does correct things * when the aRange's start and/or the end containers are * in shadow dom. * * If both start and end containers are in light dom, the iterator * won't do anything special. * * When the start container is in shadow dom, the iterator can * find the correct start node by crossing the shadow * boundary when needed. * * When the end container is in shadow dom, the iterator can find * the correct end node by crossing the shadow boundary when * needed. Also when the next node is an ancestor of * the end node, it can correctly iterate into the * subtree of it by crossing the shadow boundary. * * Examples of what nodes will be returned can be found * at test_content_iterator_subtree_shadow_tree.html.
*/
[[nodiscard]] nsresult InitWithAllowCrossShadowBoundary(
dom::AbstractRange* aRange);
[[nodiscard]] virtual nsresult Init(nsINode* aStartContainer,
uint32_t aStartOffset,
nsINode* aEndContainer,
uint32_t aEndOffset) override;
[[nodiscard]] virtual nsresult Init( const RawRangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary) override;
void Next() override; void Prev() override; // Must override these because we don't do PositionAt void First() override; // Must override these because we don't do PositionAt void Last() override;
/** * @return may be nullptr.
*/
nsIContent* DetermineCandidateForFirstContent() const;
/** * @return may be nullptr.
*/
nsIContent* DetermineCandidateForLastContent() const;
/** * @return may be nullptr.
*/
nsIContent* DetermineFirstContent() const;
/** * @return may be nullptr.
*/
nsIContent* DetermineLastContent() const;
/** * Callers must guarantee that mRange isn't nullptr and is positioned.
*/
[[nodiscard]] nsresult InitWithRange();
// Returns the highest inclusive ancestor of aNode that's in the range // (possibly aNode itself). Returns null if aNode is null, or is not itself // in the range. A node is in the range if (node, 0) comes strictly after // the range endpoint, and (node, node.length) comes strictly before it, so // the range's start and end nodes will never be considered "in" it.
nsIContent* GetTopAncestorInRange(nsINode* aNode) const;
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.