dom/base/NodeIterator.h
author Carsten "Tomcat" Book <cbook@mozilla.com>
Mon, 12 Jan 2015 14:48:15 +0100
changeset 223354 a7f64e53893ef5d4bed1996acce1e0d459b8df8d
parent 223334 12dd1ad43923ac63fa00cdf1484991d5624c4daf
child 223555 3bff2bbe6677f590c280c380202f138ba2a020af
permissions -rw-r--r--
Backed out 12 changesets (bug 1096328) for M11 and M5 Test failures on a CLOSED TREE Backed out changeset 12dd1ad43923 (bug 1096328) Backed out changeset 4a067de94f22 (bug 1096328) Backed out changeset 676112a4f092 (bug 1096328) Backed out changeset e2e64e751ece (bug 1096328) Backed out changeset 9ed945e9a8a5 (bug 1096328) Backed out changeset 47be69b84be5 (bug 1096328) Backed out changeset d6e68ba4846d (bug 1096328) Backed out changeset 899d8cd8c4e8 (bug 1096328) Backed out changeset 55c831086864 (bug 1096328) Backed out changeset 6005fd357342 (bug 1096328) Backed out changeset 0f330a5dd346 (bug 1096328) Backed out changeset c37e10cff765 (bug 1096328)

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * 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 nsIDOMNodeIterator
 */

#ifndef mozilla_dom_NodeIterator_h
#define mozilla_dom_NodeIterator_h

#include "nsIDOMNodeIterator.h"
#include "nsTraversal.h"
#include "nsCycleCollectionParticipant.h"
#include "nsStubMutationObserver.h"

class nsINode;
class nsIDOMNode;

namespace mozilla {
namespace dom {

class NodeIterator MOZ_FINAL : public nsIDOMNodeIterator,
                               public nsTraversal,
                               public nsStubMutationObserver
{
public:
    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    NS_DECL_NSIDOMNODEITERATOR

    NodeIterator(nsINode *aRoot,
                 uint32_t aWhatToShow,
                 const NodeFilterHolder &aFilter);

    NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED

    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(NodeIterator, nsIDOMNodeIterator)

    // WebIDL API
    nsINode* Root() const
    {
        return mRoot;
    }
    nsINode* GetReferenceNode() const
    {
        return mPointer.mNode;
    }
    bool PointerBeforeReferenceNode() const
    {
        return mPointer.mBeforeNode;
    }
    uint32_t WhatToShow() const
    {
        return mWhatToShow;
    }
    already_AddRefed<NodeFilter> GetFilter()
    {
        return mFilter.ToWebIDLCallback();
    }
    already_AddRefed<nsINode> NextNode(ErrorResult& aResult)
    {
        return NextOrPrevNode(&NodePointer::MoveToNext, aResult);
    }
    already_AddRefed<nsINode> PreviousNode(ErrorResult& aResult)
    {
        return NextOrPrevNode(&NodePointer::MoveToPrevious, aResult);
    }
    // The XPCOM Detach() is fine for our purposes

    JSObject* WrapObject(JSContext *cx);

private:
    virtual ~NodeIterator();

    struct NodePointer {
        NodePointer() : mNode(nullptr) {}
        NodePointer(nsINode *aNode, bool aBeforeNode);

        typedef bool (NodePointer::*MoveToMethodType)(nsINode*);
        bool MoveToNext(nsINode *aRoot);
        bool MoveToPrevious(nsINode *aRoot);

        bool MoveForward(nsINode *aRoot, nsINode *aNode);
        void MoveBackward(nsINode *aParent, nsINode *aNode);

        void AdjustAfterRemoval(nsINode *aRoot, nsINode *aContainer, nsIContent *aChild, nsIContent *aPreviousSibling);

        void Clear() { mNode = nullptr; }

        nsINode *mNode;
        bool mBeforeNode;
    };

    // Implementation for some of our XPCOM getters
    typedef already_AddRefed<nsINode> (NodeIterator::*NodeGetter)(ErrorResult&);
    inline nsresult ImplNodeGetter(NodeGetter aGetter, nsIDOMNode** aRetval)
    {
        mozilla::ErrorResult rv;
        nsCOMPtr<nsINode> node = (this->*aGetter)(rv);
        if (rv.Failed()) {
            return rv.ErrorCode();
        }
        *aRetval = node ? node.forget().take()->AsDOMNode() : nullptr;
        return NS_OK;
    }

    // Have to return a strong ref, because the act of testing the node can
    // remove it from the DOM so we're holding the only ref to it.
    already_AddRefed<nsINode>
    NextOrPrevNode(NodePointer::MoveToMethodType aMove, ErrorResult& aResult);

    NodePointer mPointer;
    NodePointer mWorkingPointer;
};

} // namespace dom

} // namespace mozilla

#endif // mozilla_dom_NodeIterator_h