michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * Implementation of DOM Traversal's nsIDOMNodeIterator michael@0: */ michael@0: michael@0: #ifndef mozilla_dom_NodeIterator_h michael@0: #define mozilla_dom_NodeIterator_h michael@0: michael@0: #include "nsIDOMNodeIterator.h" michael@0: #include "nsTraversal.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsStubMutationObserver.h" michael@0: michael@0: class nsINode; michael@0: class nsIDOMNode; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class NodeIterator MOZ_FINAL : public nsIDOMNodeIterator, michael@0: public nsTraversal, michael@0: public nsStubMutationObserver michael@0: { michael@0: public: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_NSIDOMNODEITERATOR michael@0: michael@0: NodeIterator(nsINode *aRoot, michael@0: uint32_t aWhatToShow, michael@0: const NodeFilterHolder &aFilter); michael@0: virtual ~NodeIterator(); michael@0: michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED michael@0: michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(NodeIterator, nsIDOMNodeIterator) michael@0: michael@0: // WebIDL API michael@0: nsINode* Root() const michael@0: { michael@0: return mRoot; michael@0: } michael@0: nsINode* GetReferenceNode() const michael@0: { michael@0: return mPointer.mNode; michael@0: } michael@0: bool PointerBeforeReferenceNode() const michael@0: { michael@0: return mPointer.mBeforeNode; michael@0: } michael@0: uint32_t WhatToShow() const michael@0: { michael@0: return mWhatToShow; michael@0: } michael@0: already_AddRefed GetFilter() michael@0: { michael@0: return mFilter.ToWebIDLCallback(); michael@0: } michael@0: already_AddRefed NextNode(ErrorResult& aResult) michael@0: { michael@0: return NextOrPrevNode(&NodePointer::MoveToNext, aResult); michael@0: } michael@0: already_AddRefed PreviousNode(ErrorResult& aResult) michael@0: { michael@0: return NextOrPrevNode(&NodePointer::MoveToPrevious, aResult); michael@0: } michael@0: // The XPCOM Detach() is fine for our purposes michael@0: michael@0: JSObject* WrapObject(JSContext *cx); michael@0: michael@0: private: michael@0: struct NodePointer { michael@0: NodePointer() : mNode(nullptr) {} michael@0: NodePointer(nsINode *aNode, bool aBeforeNode); michael@0: michael@0: typedef bool (NodePointer::*MoveToMethodType)(nsINode*); michael@0: bool MoveToNext(nsINode *aRoot); michael@0: bool MoveToPrevious(nsINode *aRoot); michael@0: michael@0: bool MoveForward(nsINode *aRoot, nsINode *aNode); michael@0: void MoveBackward(nsINode *aParent, nsINode *aNode); michael@0: michael@0: void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, nsIContent *aPreviousSibling); michael@0: michael@0: void Clear() { mNode = nullptr; } michael@0: michael@0: nsINode *mNode; michael@0: bool mBeforeNode; michael@0: }; michael@0: michael@0: // Implementation for some of our XPCOM getters michael@0: typedef already_AddRefed (NodeIterator::*NodeGetter)(ErrorResult&); michael@0: inline nsresult ImplNodeGetter(NodeGetter aGetter, nsIDOMNode** aRetval) michael@0: { michael@0: mozilla::ErrorResult rv; michael@0: nsCOMPtr node = (this->*aGetter)(rv); michael@0: if (rv.Failed()) { michael@0: return rv.ErrorCode(); michael@0: } michael@0: *aRetval = node ? node.forget().take()->AsDOMNode() : nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Have to return a strong ref, because the act of testing the node can michael@0: // remove it from the DOM so we're holding the only ref to it. michael@0: already_AddRefed michael@0: NextOrPrevNode(NodePointer::MoveToMethodType aMove, ErrorResult& aResult); michael@0: michael@0: NodePointer mPointer; michael@0: NodePointer mWorkingPointer; michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_dom_NodeIterator_h