tor-browser

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

ReadableStreamDefaultController.cpp (21246B)


      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 #include "mozilla/dom/ReadableStreamDefaultController.h"
      8 
      9 #include "js/Exception.h"
     10 #include "js/TypeDecls.h"
     11 #include "js/Value.h"
     12 #include "mozilla/AlreadyAddRefed.h"
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/HoldDropJSObjects.h"
     15 #include "mozilla/dom/Promise-inl.h"
     16 #include "mozilla/dom/Promise.h"
     17 #include "mozilla/dom/ReadableStream.h"
     18 #include "mozilla/dom/ReadableStreamControllerBase.h"
     19 #include "mozilla/dom/ReadableStreamDefaultControllerBinding.h"
     20 #include "mozilla/dom/ReadableStreamDefaultReaderBinding.h"
     21 #include "mozilla/dom/UnderlyingSourceBinding.h"
     22 #include "mozilla/dom/UnderlyingSourceCallbackHelpers.h"
     23 #include "nsCycleCollectionParticipant.h"
     24 #include "nsISupports.h"
     25 
     26 namespace mozilla::dom {
     27 
     28 using namespace streams_abstract;
     29 
     30 NS_IMPL_CYCLE_COLLECTION(ReadableStreamControllerBase, mGlobal, mAlgorithms,
     31                         mStream)
     32 NS_IMPL_CYCLE_COLLECTING_ADDREF(ReadableStreamControllerBase)
     33 NS_IMPL_CYCLE_COLLECTING_RELEASE(ReadableStreamControllerBase)
     34 
     35 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ReadableStreamControllerBase)
     36  NS_INTERFACE_MAP_ENTRY(nsISupports)
     37 NS_INTERFACE_MAP_END
     38 
     39 ReadableStreamControllerBase::ReadableStreamControllerBase(
     40    nsIGlobalObject* aGlobal)
     41    : mGlobal(aGlobal) {}
     42 
     43 void ReadableStreamControllerBase::SetStream(ReadableStream* aStream) {
     44  mStream = aStream;
     45 }
     46 
     47 // Note: Using the individual macros vs NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE
     48 // because I need to specify a manual implementation of
     49 // NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN.
     50 NS_IMPL_CYCLE_COLLECTION_CLASS(ReadableStreamDefaultController)
     51 
     52 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ReadableStreamDefaultController,
     53                                                ReadableStreamControllerBase)
     54  NS_IMPL_CYCLE_COLLECTION_UNLINK(mStrategySizeAlgorithm)
     55  tmp->mQueue.clear();
     56  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     57 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     58 
     59 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
     60    ReadableStreamDefaultController, ReadableStreamControllerBase)
     61  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStrategySizeAlgorithm)
     62 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     63 
     64 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ReadableStreamDefaultController,
     65                                               ReadableStreamControllerBase)
     66  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     67  // Trace the associated queue.
     68  for (const auto& queueEntry : tmp->mQueue) {
     69    aCallbacks.Trace(&queueEntry->mValue, "mQueue.mValue", aClosure);
     70  }
     71 NS_IMPL_CYCLE_COLLECTION_TRACE_END
     72 
     73 NS_IMPL_ADDREF_INHERITED(ReadableStreamDefaultController,
     74                         ReadableStreamControllerBase)
     75 NS_IMPL_RELEASE_INHERITED(ReadableStreamDefaultController,
     76                          ReadableStreamControllerBase)
     77 
     78 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ReadableStreamDefaultController)
     79  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     80 NS_INTERFACE_MAP_END_INHERITING(ReadableStreamControllerBase)
     81 
     82 ReadableStreamDefaultController::ReadableStreamDefaultController(
     83    nsIGlobalObject* aGlobal)
     84    : ReadableStreamControllerBase(aGlobal) {
     85  mozilla::HoldJSObjects(this);
     86 }
     87 
     88 ReadableStreamDefaultController::~ReadableStreamDefaultController() {
     89  // MG:XXX: LinkedLists are required to be empty at destruction, but it seems
     90  //         it is possible to have a controller be destructed while still
     91  //         having entries in its queue.
     92  //
     93  //         This needs to be verified as not indicating some other issue.
     94  mozilla::DropJSObjects(this);
     95  mQueue.clear();
     96 }
     97 
     98 JSObject* ReadableStreamDefaultController::WrapObject(
     99    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
    100  return ReadableStreamDefaultController_Binding::Wrap(aCx, this, aGivenProto);
    101 }
    102 
    103 namespace streams_abstract {
    104 
    105 // https://streams.spec.whatwg.org/#readable-stream-default-controller-can-close-or-enqueue
    106 static bool ReadableStreamDefaultControllerCanCloseOrEnqueue(
    107    ReadableStreamDefaultController* aController) {
    108  // Step 1. Let state be controller.[[stream]].[[state]].
    109  ReadableStream::ReaderState state = aController->Stream()->State();
    110 
    111  // Step 2. If controller.[[closeRequested]] is false and state is "readable",
    112  // return true.
    113  // Step 3. Return false.
    114  return !aController->CloseRequested() &&
    115         state == ReadableStream::ReaderState::Readable;
    116 }
    117 
    118 // https://streams.spec.whatwg.org/#readable-stream-default-controller-can-close-or-enqueue
    119 // This is a variant of ReadableStreamDefaultControllerCanCloseOrEnqueue
    120 // that also throws when the function would return false to improve error
    121 // messages.
    122 bool ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
    123    ReadableStreamDefaultController* aController,
    124    CloseOrEnqueue aCloseOrEnqueue, ErrorResult& aRv) {
    125  // Step 1. Let state be controller.[[stream]].[[state]].
    126  ReadableStream::ReaderState state = aController->Stream()->State();
    127 
    128  nsCString prefix;
    129  if (aCloseOrEnqueue == CloseOrEnqueue::Close) {
    130    prefix = "Cannot close a stream that "_ns;
    131  } else {
    132    prefix = "Cannot enqueue into a stream that "_ns;
    133  }
    134 
    135  switch (state) {
    136    case ReadableStream::ReaderState::Readable:
    137      // Step 2. If controller.[[closeRequested]] is false and
    138      // state is "readable", return true.
    139      // Note: We don't error/check for [[closeRequest]] first, because
    140      // [[closedRequest]] is still true even after the state is "closed".
    141      // This doesn't cause any spec observable difference.
    142      if (!aController->CloseRequested()) {
    143        return true;
    144      }
    145 
    146      // Step 3. Return false.
    147      aRv.ThrowTypeError(prefix + "has already been requested to close."_ns);
    148      return false;
    149 
    150    case ReadableStream::ReaderState::Closed:
    151      aRv.ThrowTypeError(prefix + "is already closed."_ns);
    152      return false;
    153 
    154    case ReadableStream::ReaderState::Errored:
    155      aRv.ThrowTypeError(prefix + "has errored."_ns);
    156      return false;
    157 
    158    default:
    159      MOZ_ASSERT_UNREACHABLE("Unknown ReaderState");
    160      return false;
    161  }
    162 }
    163 
    164 Nullable<double> ReadableStreamDefaultControllerGetDesiredSize(
    165    ReadableStreamDefaultController* aController) {
    166  ReadableStream::ReaderState state = aController->Stream()->State();
    167  if (state == ReadableStream::ReaderState::Errored) {
    168    return nullptr;
    169  }
    170 
    171  if (state == ReadableStream::ReaderState::Closed) {
    172    return 0.0;
    173  }
    174 
    175  return aController->StrategyHWM() - aController->QueueTotalSize();
    176 }
    177 
    178 }  // namespace streams_abstract
    179 
    180 // https://streams.spec.whatwg.org/#rs-default-controller-desired-size
    181 Nullable<double> ReadableStreamDefaultController::GetDesiredSize() {
    182  // Step 1.
    183  return ReadableStreamDefaultControllerGetDesiredSize(this);
    184 }
    185 
    186 namespace streams_abstract {
    187 
    188 // https://streams.spec.whatwg.org/#readable-stream-default-controller-clear-algorithms
    189 //
    190 // Note: nullptr is used to indicate we run the default algorithm at the
    191 //       moment,
    192 //       so the below doesn't quite match the spec, but serves the correct
    193 //       purpose for disconnecting the algorithms from the object graph to allow
    194 //       collection.
    195 //
    196 //       As far as I know, this isn't currently visible, but we need to keep
    197 //       this in mind. This is a weakness of this current implementation, and
    198 //       I'd prefer to have a better answer here eventually.
    199 void ReadableStreamDefaultControllerClearAlgorithms(
    200    ReadableStreamDefaultController* aController) {
    201  // Step 1.
    202  // Step 2.
    203  aController->ClearAlgorithms();
    204 
    205  // Step 3.
    206  aController->setStrategySizeAlgorithm(nullptr);
    207 }
    208 
    209 // https://streams.spec.whatwg.org/#readable-stream-default-controller-close
    210 void ReadableStreamDefaultControllerClose(
    211    JSContext* aCx, ReadableStreamDefaultController* aController,
    212    ErrorResult& aRv) {
    213  // Step 1.
    214  if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(aController)) {
    215    return;
    216  }
    217 
    218  // Step 2.
    219  RefPtr<ReadableStream> stream = aController->Stream();
    220 
    221  // Step 3.
    222  aController->SetCloseRequested(true);
    223 
    224  // Step 4.
    225  if (aController->Queue().isEmpty()) {
    226    // Step 4.1
    227    ReadableStreamDefaultControllerClearAlgorithms(aController);
    228 
    229    // Step 4.2
    230    ReadableStreamClose(aCx, stream, aRv);
    231  }
    232 }
    233 
    234 }  // namespace streams_abstract
    235 
    236 // https://streams.spec.whatwg.org/#rs-default-controller-close
    237 void ReadableStreamDefaultController::Close(JSContext* aCx, ErrorResult& aRv) {
    238  // Step 1.
    239  if (!ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
    240          this, CloseOrEnqueue::Close, aRv)) {
    241    return;
    242  }
    243 
    244  // Step 2.
    245  ReadableStreamDefaultControllerClose(aCx, this, aRv);
    246 }
    247 
    248 namespace streams_abstract {
    249 
    250 MOZ_CAN_RUN_SCRIPT static void ReadableStreamDefaultControllerCallPullIfNeeded(
    251    JSContext* aCx, ReadableStreamDefaultController* aController,
    252    ErrorResult& aRv);
    253 
    254 // https://streams.spec.whatwg.org/#readable-stream-default-controller-enqueue
    255 void ReadableStreamDefaultControllerEnqueue(
    256    JSContext* aCx, ReadableStreamDefaultController* aController,
    257    JS::Handle<JS::Value> aChunk, ErrorResult& aRv) {
    258  // Step 1.
    259  if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(aController)) {
    260    return;
    261  }
    262 
    263  // Step 2.
    264  RefPtr<ReadableStream> stream = aController->Stream();
    265 
    266  // Step 3.
    267  if (IsReadableStreamLocked(stream) &&
    268      ReadableStreamGetNumReadRequests(stream) > 0) {
    269    ReadableStreamFulfillReadRequest(aCx, stream, aChunk, false, aRv);
    270  } else {
    271    // Step 4.1
    272    Optional<JS::Handle<JS::Value>> optionalChunk(aCx, aChunk);
    273 
    274    // Step 4.3 (Re-ordered);
    275    RefPtr<QueuingStrategySize> sizeAlgorithm(
    276        aController->StrategySizeAlgorithm());
    277 
    278    // If !sizeAlgorithm, we return 1, which is inlined from
    279    // https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function
    280    double chunkSize =
    281        sizeAlgorithm
    282            ? sizeAlgorithm->Call(
    283                  optionalChunk, aRv,
    284                  "ReadableStreamDefaultController.[[strategySizeAlgorithm]]",
    285                  CallbackObject::eRethrowExceptions)
    286            : 1.0;
    287 
    288    // If this is an uncatchable exception we can't continue.
    289    if (aRv.IsUncatchableException()) {
    290      return;
    291    }
    292 
    293    // Step 4.2:
    294    if (aRv.MaybeSetPendingException(
    295            aCx, "ReadableStreamDefaultController.enqueue")) {
    296      JS::Rooted<JS::Value> errorValue(aCx);
    297 
    298      JS_GetPendingException(aCx, &errorValue);
    299 
    300      // Step 4.2.1
    301 
    302      ReadableStreamDefaultControllerError(aCx, aController, errorValue, aRv);
    303      if (aRv.Failed()) {
    304        return;
    305      }
    306 
    307      // Step 4.2.2 Caller must treat aRv as if it were a completion
    308      // value
    309      aRv.MightThrowJSException();
    310      aRv.ThrowJSException(aCx, errorValue);
    311      return;
    312    }
    313 
    314    // Step 4.4
    315    EnqueueValueWithSize(aController, aChunk, chunkSize, aRv);
    316 
    317    // Step 4.5
    318    // Note we convert the pending exception to a JS value here, and then
    319    // re-throw it because we save this exception and re-expose it elsewhere
    320    // and there are tests to ensure the identity of these errors are the same.
    321    if (aRv.MaybeSetPendingException(
    322            aCx, "ReadableStreamDefaultController.enqueue")) {
    323      JS::Rooted<JS::Value> errorValue(aCx);
    324 
    325      if (!JS_GetPendingException(aCx, &errorValue)) {
    326        // Uncatchable exception; we should mark aRv and return.
    327        aRv.StealExceptionFromJSContext(aCx);
    328        return;
    329      }
    330      JS_ClearPendingException(aCx);
    331 
    332      // Step 4.5.1
    333      ReadableStreamDefaultControllerError(aCx, aController, errorValue, aRv);
    334      if (aRv.Failed()) {
    335        return;
    336      }
    337 
    338      // Step 4.5.2 Caller must treat aRv as if it were a completion
    339      // value
    340      aRv.MightThrowJSException();
    341      aRv.ThrowJSException(aCx, errorValue);
    342      return;
    343    }
    344  }
    345 
    346  // Step 5.
    347  ReadableStreamDefaultControllerCallPullIfNeeded(aCx, aController, aRv);
    348 }
    349 
    350 }  // namespace streams_abstract
    351 
    352 // https://streams.spec.whatwg.org/#rs-default-controller-close
    353 void ReadableStreamDefaultController::Enqueue(JSContext* aCx,
    354                                              JS::Handle<JS::Value> aChunk,
    355                                              ErrorResult& aRv) {
    356  // Step 1.
    357  if (!ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
    358          this, CloseOrEnqueue::Enqueue, aRv)) {
    359    return;
    360  }
    361 
    362  // Step 2.
    363  ReadableStreamDefaultControllerEnqueue(aCx, this, aChunk, aRv);
    364 }
    365 
    366 void ReadableStreamDefaultController::Error(JSContext* aCx,
    367                                            JS::Handle<JS::Value> aError,
    368                                            ErrorResult& aRv) {
    369  ReadableStreamDefaultControllerError(aCx, this, aError, aRv);
    370 }
    371 
    372 namespace streams_abstract {
    373 
    374 // https://streams.spec.whatwg.org/#readable-stream-default-controller-should-call-pull
    375 bool ReadableStreamDefaultControllerShouldCallPull(
    376    ReadableStreamDefaultController* aController) {
    377  // Step 1.
    378  ReadableStream* stream = aController->Stream();
    379 
    380  // Step 2.
    381  if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(aController)) {
    382    return false;
    383  }
    384 
    385  // Step 3.
    386  if (!aController->Started()) {
    387    return false;
    388  }
    389 
    390  // Step 4.
    391  if (IsReadableStreamLocked(stream) &&
    392      ReadableStreamGetNumReadRequests(stream) > 0) {
    393    return true;
    394  }
    395 
    396  // Step 5.
    397  Nullable<double> desiredSize =
    398      ReadableStreamDefaultControllerGetDesiredSize(aController);
    399 
    400  // Step 6.
    401  MOZ_ASSERT(!desiredSize.IsNull());
    402 
    403  // Step 7 + 8
    404  return desiredSize.Value() > 0;
    405 }
    406 
    407 // https://streams.spec.whatwg.org/#readable-stream-default-controller-error
    408 void ReadableStreamDefaultControllerError(
    409    JSContext* aCx, ReadableStreamDefaultController* aController,
    410    JS::Handle<JS::Value> aValue, ErrorResult& aRv) {
    411  // Step 1.
    412  ReadableStream* stream = aController->Stream();
    413 
    414  // Step 2.
    415  if (stream->State() != ReadableStream::ReaderState::Readable) {
    416    return;
    417  }
    418 
    419  // Step 3.
    420  ResetQueue(aController);
    421 
    422  // Step 4.
    423  ReadableStreamDefaultControllerClearAlgorithms(aController);
    424 
    425  // Step 5.
    426  ReadableStreamError(aCx, stream, aValue, aRv);
    427 }
    428 
    429 // https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed
    430 static void ReadableStreamDefaultControllerCallPullIfNeeded(
    431    JSContext* aCx, ReadableStreamDefaultController* aController,
    432    ErrorResult& aRv) {
    433  // Step 1.
    434  bool shouldPull = ReadableStreamDefaultControllerShouldCallPull(aController);
    435 
    436  // Step 2.
    437  if (!shouldPull) {
    438    return;
    439  }
    440 
    441  // Step 3.
    442  if (aController->Pulling()) {
    443    // Step 3.1
    444    aController->SetPullAgain(true);
    445    // Step 3.2
    446    return;
    447  }
    448 
    449  // Step 4.
    450  MOZ_ASSERT(!aController->PullAgain());
    451 
    452  // Step 5.
    453  aController->SetPulling(true);
    454 
    455  // Step 6.
    456  RefPtr<UnderlyingSourceAlgorithmsBase> algorithms =
    457      aController->GetAlgorithms();
    458  RefPtr<Promise> pullPromise =
    459      algorithms->PullCallback(aCx, *aController, aRv);
    460  if (aRv.Failed()) {
    461    return;
    462  }
    463 
    464  // Step 7 + 8:
    465  pullPromise->AddCallbacksWithCycleCollectedArgs(
    466      [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv,
    467         ReadableStreamDefaultController* mController)
    468          MOZ_CAN_RUN_SCRIPT_BOUNDARY {
    469            // Step 7.1
    470            mController->SetPulling(false);
    471            // Step 7.2
    472            if (mController->PullAgain()) {
    473              // Step 7.2.1
    474              mController->SetPullAgain(false);
    475 
    476              // Step 7.2.2
    477              ErrorResult rv;
    478              ReadableStreamDefaultControllerCallPullIfNeeded(
    479                  aCx, MOZ_KnownLive(mController), aRv);
    480            }
    481          },
    482      [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv,
    483         ReadableStreamDefaultController* mController) {
    484        // Step 8.1
    485        ReadableStreamDefaultControllerError(aCx, mController, aValue, aRv);
    486      },
    487      RefPtr(aController));
    488 }
    489 
    490 // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller
    491 void SetUpReadableStreamDefaultController(
    492    JSContext* aCx, ReadableStream* aStream,
    493    ReadableStreamDefaultController* aController,
    494    UnderlyingSourceAlgorithmsBase* aAlgorithms, double aHighWaterMark,
    495    QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv) {
    496  // Step 1.
    497  MOZ_ASSERT(!aStream->Controller());
    498 
    499  // Step 2.
    500  aController->SetStream(aStream);
    501 
    502  // Step 3.
    503  ResetQueue(aController);
    504 
    505  // Step 4.
    506  aController->SetStarted(false);
    507  aController->SetCloseRequested(false);
    508  aController->SetPullAgain(false);
    509  aController->SetPulling(false);
    510 
    511  // Step 5.
    512  aController->setStrategySizeAlgorithm(aSizeAlgorithm);
    513  aController->SetStrategyHWM(aHighWaterMark);
    514 
    515  // Step 6.
    516  // Step 7.
    517  aController->SetAlgorithms(*aAlgorithms);
    518 
    519  // Step 8.
    520  aStream->SetController(*aController);
    521 
    522  // Step 9. Default algorithm returns undefined. See Step 2 of
    523  // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller
    524  JS::Rooted<JS::Value> startResult(aCx, JS::UndefinedValue());
    525  RefPtr<ReadableStreamDefaultController> controller = aController;
    526  aAlgorithms->StartCallback(aCx, *controller, &startResult, aRv);
    527  if (aRv.Failed()) {
    528    return;
    529  }
    530 
    531  // Step 10.
    532  RefPtr<Promise> startPromise =
    533      Promise::CreateInfallible(aStream->GetParentObject());
    534  startPromise->MaybeResolve(startResult);
    535 
    536  // Step 11 & 12:
    537  startPromise->AddCallbacksWithCycleCollectedArgs(
    538      [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv,
    539         ReadableStreamDefaultController* aController)
    540          MOZ_CAN_RUN_SCRIPT_BOUNDARY {
    541            MOZ_ASSERT(aController);
    542 
    543            // Step 11.1
    544            aController->SetStarted(true);
    545 
    546            // Step 11.2
    547            aController->SetPulling(false);
    548 
    549            // Step 11.3
    550            aController->SetPullAgain(false);
    551 
    552            // Step 11.4:
    553            ReadableStreamDefaultControllerCallPullIfNeeded(
    554                aCx, MOZ_KnownLive(aController), aRv);
    555          },
    556 
    557      [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv,
    558         ReadableStreamDefaultController* aController) {
    559        // Step 12.1
    560        ReadableStreamDefaultControllerError(aCx, aController, aValue, aRv);
    561      },
    562      RefPtr(aController));
    563 }
    564 
    565 // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source
    566 void SetupReadableStreamDefaultControllerFromUnderlyingSource(
    567    JSContext* aCx, ReadableStream* aStream,
    568    JS::Handle<JSObject*> aUnderlyingSource,
    569    UnderlyingSource& aUnderlyingSourceDict, double aHighWaterMark,
    570    QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv) {
    571  // Step 1.
    572  RefPtr<ReadableStreamDefaultController> controller =
    573      new ReadableStreamDefaultController(aStream->GetParentObject());
    574 
    575  // Step 2 - 7
    576  RefPtr<UnderlyingSourceAlgorithms> algorithms =
    577      new UnderlyingSourceAlgorithms(aStream->GetParentObject(),
    578                                     aUnderlyingSource, aUnderlyingSourceDict);
    579 
    580  // Step 8:
    581  SetUpReadableStreamDefaultController(aCx, aStream, controller, algorithms,
    582                                       aHighWaterMark, aSizeAlgorithm, aRv);
    583 }
    584 
    585 }  // namespace streams_abstract
    586 
    587 // https://streams.spec.whatwg.org/#rs-default-controller-private-cancel
    588 already_AddRefed<Promise> ReadableStreamDefaultController::CancelSteps(
    589    JSContext* aCx, JS::Handle<JS::Value> aReason, ErrorResult& aRv) {
    590  // Step 1.
    591  ResetQueue(this);
    592 
    593  // Step 2.
    594  Optional<JS::Handle<JS::Value>> errorOption(aCx, aReason);
    595  RefPtr<UnderlyingSourceAlgorithmsBase> algorithms = mAlgorithms;
    596  RefPtr<Promise> result = algorithms->CancelCallback(aCx, errorOption, aRv);
    597  if (aRv.Failed()) {
    598    return nullptr;
    599  }
    600 
    601  // Step 3.
    602  ReadableStreamDefaultControllerClearAlgorithms(this);
    603 
    604  // Step 4.
    605  return result.forget();
    606 }
    607 
    608 // https://streams.spec.whatwg.org/#rs-default-controller-private-pull
    609 void ReadableStreamDefaultController::PullSteps(JSContext* aCx,
    610                                                ReadRequest* aReadRequest,
    611                                                ErrorResult& aRv) {
    612  // Step 1.
    613  RefPtr<ReadableStream> stream = mStream;
    614 
    615  // Step 2.
    616  if (!mQueue.isEmpty()) {
    617    // Step 2.1
    618    JS::Rooted<JS::Value> chunk(aCx);
    619    DequeueValue(this, &chunk);
    620 
    621    // Step 2.2
    622    if (CloseRequested() && mQueue.isEmpty()) {
    623      // Step 2.2.1
    624      ReadableStreamDefaultControllerClearAlgorithms(this);
    625      // Step 2.2.2
    626      ReadableStreamClose(aCx, stream, aRv);
    627      if (aRv.Failed()) {
    628        return;
    629      }
    630    } else {
    631      // Step 2.3
    632      ReadableStreamDefaultControllerCallPullIfNeeded(aCx, this, aRv);
    633      if (aRv.Failed()) {
    634        return;
    635      }
    636    }
    637 
    638    // Step 2.4
    639    aReadRequest->ChunkSteps(aCx, chunk, aRv);
    640  } else {
    641    // Step 3.
    642    // Step 3.1
    643    ReadableStreamAddReadRequest(stream, aReadRequest);
    644    // Step 3.2
    645    ReadableStreamDefaultControllerCallPullIfNeeded(aCx, this, aRv);
    646  }
    647 }
    648 
    649 // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultcontroller-releasesteps
    650 void ReadableStreamDefaultController::ReleaseSteps() {
    651  // Step 1. Return.
    652 }
    653 
    654 }  // namespace mozilla::dom