/* -*- Mode: C++; 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/. */

#ifndef mozilla_devtools_DominatorTree__
#define mozilla_devtools_DominatorTree__

#include "mozilla/devtools/HeapSnapshot.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/RefCounted.h"
#include "js/UbiNodeDominatorTree.h"
#include "nsWrapperCache.h"

namespace mozilla {
class ErrorResult;

namespace devtools {

class DominatorTree final : public nsISupports, public nsWrapperCache {
 protected:
  nsCOMPtr<nsISupports> mParent;

  virtual ~DominatorTree() {}

 private:
  JS::ubi::DominatorTree mDominatorTree;
  RefPtr<HeapSnapshot> mHeapSnapshot;

 public:
  explicit DominatorTree(JS::ubi::DominatorTree&& aDominatorTree,
                         HeapSnapshot* aHeapSnapshot, nsISupports* aParent)
      : mParent(aParent),
        mDominatorTree(std::move(aDominatorTree)),
        mHeapSnapshot(aHeapSnapshot) {
    MOZ_ASSERT(aParent);
    MOZ_ASSERT(aHeapSnapshot);
  };

  NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
  NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(DominatorTree);

  nsISupports* GetParentObject() const { return mParent; }

  virtual JSObject* WrapObject(JSContext* aCx,
                               JS::Handle<JSObject*> aGivenProto) override;

  // readonly attribute NodeId root
  uint64_t Root() const { return mDominatorTree.root().identifier(); }

  // [Throws] NodeSize getRetainedSize(NodeId node)
  dom::Nullable<uint64_t> GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv);

  // [Throws] sequence<NodeId>? getImmediatelyDominated(NodeId node);
  void GetImmediatelyDominated(uint64_t aNodeId,
                               dom::Nullable<nsTArray<uint64_t>>& aOutDominated,
                               ErrorResult& aRv);

  // NodeId? getImmediateDominator(NodeId node);
  dom::Nullable<uint64_t> GetImmediateDominator(uint64_t aNodeId) const;
};

}  // namespace devtools
}  // namespace mozilla

#endif  // mozilla_devtools_DominatorTree__
