js/src/ds/TraceableFifo.h
author Nika Layzell <nika@thelayzells.com>
Wed, 16 Sep 2020 20:47:55 +0000
changeset 549331 ab7d302fd3186b10ada9264528c80f6840e44571
parent 480654 1621ba12b29232e3eafa61a6c0e1bb0770147554
permissions -rw-r--r--
Bug 1659696 - Check PendingInitialization before targeting in window.open, r=kmag This requires adding the flag as a synced field on the BrowsingContext, and checking it in a few more places. Attempts to open a new window in this racy manner will now raise an exception. This should avoid the issue from bug 1658854 by blocking the buggy attempts to load before the nested event loop has been exited. Differential Revision: https://phabricator.services.mozilla.com/D87927

/* -*- 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/. */

#ifndef js_TraceableFifo_h
#define js_TraceableFifo_h

#include "ds/Fifo.h"
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"

namespace js {

// A TraceableFifo is a Fifo with an additional trace method that knows how to
// visit all of the items stored in the Fifo. For Fifos that contain GC things,
// this is usually more convenient than manually iterating and marking the
// contents.
//
// Most types of GC pointers as keys and values can be traced with no extra
// infrastructure. For structs and non-gc-pointer members, ensure that there is
// a specialization of GCPolicy<T> with an appropriate trace method available
// to handle the custom type. Generic helpers can be found in
// js/public/TracingAPI.h. Generic helpers can be found in
// js/public/TracingAPI.h.
//
// Note that although this Fifo's trace will deal correctly with moved items, it
// does not itself know when to barrier or trace items. To function properly it
// must either be used with Rooted, or barriered and traced manually.
template <typename T, size_t MinInlineCapacity = 0,
          typename AllocPolicy = TempAllocPolicy>
class TraceableFifo : public js::Fifo<T, MinInlineCapacity, AllocPolicy> {
  using Base = js::Fifo<T, MinInlineCapacity, AllocPolicy>;

 public:
  explicit TraceableFifo(AllocPolicy alloc = AllocPolicy())
      : Base(std::move(alloc)) {}

  TraceableFifo(TraceableFifo&& rhs) : Base(std::move(rhs)) {}
  TraceableFifo& operator=(TraceableFifo&& rhs) = default;

  TraceableFifo(const TraceableFifo&) = delete;
  TraceableFifo& operator=(const TraceableFifo&) = delete;

  void trace(JSTracer* trc) {
    for (size_t i = 0; i < this->front_.length(); ++i) {
      JS::GCPolicy<T>::trace(trc, &this->front_[i], "fifo element");
    }
    for (size_t i = 0; i < this->rear_.length(); ++i) {
      JS::GCPolicy<T>::trace(trc, &this->rear_[i], "fifo element");
    }
  }
};

template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper> {
  using TF = TraceableFifo<T, Capacity, AllocPolicy>;
  const TF& fifo() const { return static_cast<const Wrapper*>(this)->get(); }

 public:
  size_t length() const { return fifo().length(); }
  bool empty() const { return fifo().empty(); }
  const T& front() const { return fifo().front(); }
};

template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class MutableWrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>,
                                  Wrapper>
    : public WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>,
                                  Wrapper> {
  using TF = TraceableFifo<T, Capacity, AllocPolicy>;
  TF& fifo() { return static_cast<Wrapper*>(this)->get(); }

 public:
  T& front() { return fifo().front(); }

  template <typename U>
  bool pushBack(U&& u) {
    return fifo().pushBack(std::forward<U>(u));
  }
  template <typename... Args>
  bool emplaceBack(Args&&... args) {
    return fifo().emplaceBack(std::forward<Args...>(args...));
  }

  void popFront() { fifo().popFront(); }
  void clear() { fifo().clear(); }
};

}  // namespace js

#endif  // js_TraceableFifo_h