tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

QueueWithSizes.h (4798B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_QueueWithSizes_h
      8 #define mozilla_dom_QueueWithSizes_h
      9 
     10 #include <cmath>
     11 
     12 #include "js/TypeDecls.h"
     13 #include "js/Value.h"
     14 #include "mozilla/ErrorResult.h"
     15 #include "mozilla/UniquePtr.h"
     16 #include "nsTArray.h"
     17 
     18 namespace mozilla::dom {
     19 
     20 // Note: Consumers of QueueWithSize need to ensure it is traced. See
     21 // ReadableStreamDefaultController.cpp for an example.
     22 
     23 struct ValueWithSize : LinkedListElement<ValueWithSize> {
     24  ValueWithSize(JS::Handle<JS::Value> aValue, double aSize)
     25      : mValue(aValue), mSize(aSize) {};
     26 
     27  JS::Heap<JS::Value> mValue;
     28  double mSize = 0.0f;
     29 };
     30 
     31 // This type is a little tricky lifetime wise: Despite the fact that we're
     32 // talking about linked list of VaueWithSize, what is actually stored in the
     33 // list are dynamically allocated ValueWithSize*. As a result, these have to be
     34 // deleted. There are two ways this lifetime is managed:
     35 //
     36 // 1. In DequeueValue we pop the first element into a UniquePtr, so that it is
     37 //    correctly cleaned up at destruction time.
     38 // 2. We use an AutoCleanLinkedList which will delete elements when destroyed
     39 //    or `clear`ed.
     40 using QueueWithSizes = AutoCleanLinkedList<ValueWithSize>;
     41 
     42 // https://streams.spec.whatwg.org/#is-non-negative-number
     43 inline bool IsNonNegativeNumber(double v) {
     44  // Step 1. Implicit.
     45  // Step 2.
     46  if (std::isnan(v)) {
     47    return false;
     48  }
     49 
     50  // Step 3.
     51  return !(v < 0);
     52 }
     53 
     54 // https://streams.spec.whatwg.org/#enqueue-value-with-size
     55 template <class QueueContainingClass>
     56 inline void EnqueueValueWithSize(QueueContainingClass aContainer,
     57                                 JS::Handle<JS::Value> aValue, double aSize,
     58                                 ErrorResult& aRv) {
     59  // Step 1. Assert: container has [[queue]] and [[queueTotalSize]] internal
     60  // slots. (Implicit by template instantiation.)
     61  // Step 2. If ! IsNonNegativeNumber(size) is false, throw a RangeError
     62  // exception.
     63  if (!IsNonNegativeNumber(aSize)) {
     64    aRv.ThrowRangeError("invalid size");
     65    return;
     66  }
     67 
     68  // Step 3. If size is +∞, throw a RangeError exception.
     69  if (std::isinf(aSize)) {
     70    aRv.ThrowRangeError("Infinite queue size");
     71    return;
     72  }
     73 
     74  // Step 4. Append a new value-with-size with value value and size size to
     75  // container.[[queue]].
     76  // (See the comment on QueueWithSizes for the lifetime reasoning around this
     77  // allocation.)
     78  ValueWithSize* valueWithSize = new ValueWithSize(aValue, aSize);
     79  aContainer->Queue().insertBack(valueWithSize);
     80  // Step 5. Set container.[[queueTotalSize]] to container.[[queueTotalSize]] +
     81  // size.
     82  aContainer->SetQueueTotalSize(aContainer->QueueTotalSize() + aSize);
     83 }
     84 
     85 // https://streams.spec.whatwg.org/#dequeue-value
     86 template <class QueueContainingClass>
     87 inline void DequeueValue(QueueContainingClass aContainer,
     88                         JS::MutableHandle<JS::Value> aResultValue) {
     89  // Step 1. Implicit via template instantiation.
     90  // Step 2.
     91  MOZ_ASSERT(!aContainer->Queue().isEmpty());
     92 
     93  // Step 3+4
     94  // UniquePtr to ensure memory is freed.
     95  UniquePtr<ValueWithSize> valueWithSize(aContainer->Queue().popFirst());
     96 
     97  // Step 5.
     98  aContainer->SetQueueTotalSize(aContainer->QueueTotalSize() -
     99                                valueWithSize->mSize);
    100 
    101  // Step 6.
    102  if (aContainer->QueueTotalSize() < 0) {
    103    aContainer->SetQueueTotalSize(0);
    104  }
    105 
    106  // Step 7.
    107  aResultValue.set(valueWithSize->mValue);
    108 }
    109 
    110 // https://streams.spec.whatwg.org/#peek-queue-value
    111 template <class QueueContainingClass>
    112 inline void PeekQueueValue(QueueContainingClass aContainer,
    113                           JS::MutableHandle<JS::Value> aResultValue) {
    114  // Step 1. Assert: container has [[queue]] and [[queueTotalSize]] internal
    115  // slots.
    116  // Step 2. Assert: container.[[queue]] is not empty.
    117  MOZ_ASSERT(!aContainer->Queue().isEmpty());
    118 
    119  // Step 3. Let valueWithSize be container.[[queue]][0].
    120  ValueWithSize* valueWithSize = aContainer->Queue().getFirst();
    121 
    122  // Step 4. Return valueWithSize’s value.
    123  aResultValue.set(valueWithSize->mValue);
    124 }
    125 
    126 // https://streams.spec.whatwg.org/#reset-queue
    127 template <class QueueContainingClass>
    128 inline void ResetQueue(QueueContainingClass aContainer) {
    129  // Step 1. Assert: container has [[queue]] and [[queueTotalSize]] internal
    130  // slots. (implicit)
    131 
    132  // Step 2. Set container.[[queue]] to a new empty list.
    133  aContainer->Queue().clear();
    134 
    135  // Step 3. Set container.[[queueTotalSize]] to 0.
    136  aContainer->SetQueueTotalSize(0.0);
    137 }
    138 
    139 }  // namespace mozilla::dom
    140 
    141 #endif