tor-browser

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

TransformStreamDefaultController.cpp (9468B)


      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/TransformStreamDefaultController.h"
      8 
      9 #include "TransformerCallbackHelpers.h"
     10 #include "mozilla/Attributes.h"
     11 #include "mozilla/dom/Promise.h"
     12 #include "mozilla/dom/ReadableStream.h"
     13 #include "mozilla/dom/ReadableStreamDefaultController.h"
     14 #include "mozilla/dom/TransformStream.h"
     15 #include "mozilla/dom/TransformStreamDefaultControllerBinding.h"
     16 #include "nsWrapperCache.h"
     17 
     18 namespace mozilla::dom {
     19 
     20 using namespace streams_abstract;
     21 
     22 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TransformStreamDefaultController, mGlobal,
     23                                      mStream, mTransformerAlgorithms)
     24 NS_IMPL_CYCLE_COLLECTING_ADDREF(TransformStreamDefaultController)
     25 NS_IMPL_CYCLE_COLLECTING_RELEASE(TransformStreamDefaultController)
     26 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TransformStreamDefaultController)
     27  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     28  NS_INTERFACE_MAP_ENTRY(nsISupports)
     29 NS_INTERFACE_MAP_END
     30 
     31 TransformStream* TransformStreamDefaultController::Stream() { return mStream; }
     32 
     33 void TransformStreamDefaultController::SetStream(TransformStream& aStream) {
     34  MOZ_ASSERT(!mStream);
     35  mStream = &aStream;
     36 }
     37 
     38 TransformerAlgorithmsBase* TransformStreamDefaultController::Algorithms() {
     39  return mTransformerAlgorithms;
     40 }
     41 
     42 void TransformStreamDefaultController::SetAlgorithms(
     43    TransformerAlgorithmsBase* aTransformerAlgorithms) {
     44  mTransformerAlgorithms = aTransformerAlgorithms;
     45 }
     46 
     47 TransformStreamDefaultController::TransformStreamDefaultController(
     48    nsIGlobalObject* aGlobal)
     49    : mGlobal(aGlobal) {
     50  mozilla::HoldJSObjects(this);
     51 }
     52 
     53 TransformStreamDefaultController::~TransformStreamDefaultController() {
     54  mozilla::DropJSObjects(this);
     55 }
     56 
     57 JSObject* TransformStreamDefaultController::WrapObject(
     58    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
     59  return TransformStreamDefaultController_Binding::Wrap(aCx, this, aGivenProto);
     60 }
     61 
     62 // https://streams.spec.whatwg.org/#ts-default-controller-desired-size
     63 Nullable<double> TransformStreamDefaultController::GetDesiredSize() const {
     64  // Step 1. Let readableController be
     65  // this.[[stream]].[[readable]].[[controller]].
     66  RefPtr<ReadableStreamDefaultController> readableController =
     67      mStream->Readable()->Controller()->AsDefault();
     68 
     69  // Step 2. Return !
     70  // ReadableStreamDefaultControllerGetDesiredSize(readableController).
     71  return ReadableStreamDefaultControllerGetDesiredSize(readableController);
     72 }
     73 
     74 // https://streams.spec.whatwg.org/#rs-default-controller-has-backpressure
     75 // Looks like a readable stream thing but the spec explicitly says this is for
     76 // TransformStream.
     77 static bool ReadableStreamDefaultControllerHasBackpressure(
     78    ReadableStreamDefaultController* aController) {
     79  // Step 1: If ! ReadableStreamDefaultControllerShouldCallPull(controller) is
     80  // true, return false.
     81  // Step 2: Otherwise, return true.
     82  return !ReadableStreamDefaultControllerShouldCallPull(aController);
     83 }
     84 
     85 void TransformStreamDefaultController::Enqueue(JSContext* aCx,
     86                                               JS::Handle<JS::Value> aChunk,
     87                                               ErrorResult& aRv) {
     88  // Step 1: Perform ? TransformStreamDefaultControllerEnqueue(this, chunk).
     89 
     90  // Inlining TransformStreamDefaultControllerEnqueue here.
     91  // https://streams.spec.whatwg.org/#transform-stream-default-controller-enqueue
     92 
     93  // Step 1: Let stream be controller.[[stream]].
     94  RefPtr<TransformStream> stream = mStream;
     95 
     96  // Step 2: Let readableController be stream.[[readable]].[[controller]].
     97  RefPtr<ReadableStreamDefaultController> readableController =
     98      stream->Readable()->Controller()->AsDefault();
     99 
    100  // Step 3: If !
    101  // ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController) is
    102  // false, throw a TypeError exception.
    103  if (!ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
    104          readableController, CloseOrEnqueue::Enqueue, aRv)) {
    105    return;
    106  }
    107 
    108  // Step 4: Let enqueueResult be
    109  // ReadableStreamDefaultControllerEnqueue(readableController, chunk).
    110  ErrorResult rv;
    111  ReadableStreamDefaultControllerEnqueue(aCx, readableController, aChunk, rv);
    112 
    113  // Step 5: If enqueueResult is an abrupt completion,
    114  if (rv.MaybeSetPendingException(aCx)) {
    115    JS::Rooted<JS::Value> error(aCx);
    116    if (!JS_GetPendingException(aCx, &error)) {
    117      // Uncatchable exception; we should mark aRv and return.
    118      aRv.StealExceptionFromJSContext(aCx);
    119      return;
    120    }
    121    JS_ClearPendingException(aCx);
    122 
    123    // Step 5.1: Perform ! TransformStreamErrorWritableAndUnblockWrite(stream,
    124    // enqueueResult.[[Value]]).
    125    TransformStreamErrorWritableAndUnblockWrite(aCx, stream, error, aRv);
    126 
    127    // Step 5.2: Throw stream.[[readable]].[[storedError]].
    128    JS::Rooted<JS::Value> storedError(aCx, stream->Readable()->StoredError());
    129    aRv.MightThrowJSException();
    130    aRv.ThrowJSException(aCx, storedError);
    131    return;
    132  }
    133 
    134  // Step 6: Let backpressure be !
    135  // ReadableStreamDefaultControllerHasBackpressure(readableController).
    136  bool backpressure =
    137      ReadableStreamDefaultControllerHasBackpressure(readableController);
    138 
    139  // Step 7: If backpressure is not stream.[[backpressure]],
    140  if (backpressure != stream->Backpressure()) {
    141    // Step 7.1: Assert: backpressure is true.
    142    MOZ_ASSERT(backpressure);
    143 
    144    // Step 7.2: Perform ! TransformStreamSetBackpressure(true).
    145    stream->SetBackpressure(true);
    146  }
    147 }
    148 
    149 // https://streams.spec.whatwg.org/#ts-default-controller-error
    150 void TransformStreamDefaultController::Error(JSContext* aCx,
    151                                             JS::Handle<JS::Value> aError,
    152                                             ErrorResult& aRv) {
    153  // Step 1: Perform ? TransformStreamDefaultControllerError(this, e).
    154 
    155  // Inlining TransformStreamDefaultControllerError here.
    156  // https://streams.spec.whatwg.org/#transform-stream-default-controller-error
    157 
    158  // Perform ! TransformStreamError(controller.[[stream]], e).
    159  // mStream is set in initialization step and only modified in cycle
    160  // collection.
    161  // TODO: Move mStream initialization to a method/constructor and make it
    162  // MOZ_KNOWN_LIVE again. (See bug 1769854)
    163  TransformStreamError(aCx, MOZ_KnownLive(mStream), aError, aRv);
    164 }
    165 
    166 // https://streams.spec.whatwg.org/#ts-default-controller-terminate
    167 
    168 void TransformStreamDefaultController::Terminate(JSContext* aCx,
    169                                                 ErrorResult& aRv) {
    170  // Step 1: Perform ? TransformStreamDefaultControllerTerminate(this).
    171 
    172  // Inlining TransformStreamDefaultControllerTerminate here.
    173  // https://streams.spec.whatwg.org/#transform-stream-default-controller-terminate
    174 
    175  // Step 1: Let stream be controller.[[stream]].
    176  RefPtr<TransformStream> stream = mStream;
    177 
    178  // Step 2: Let readableController be stream.[[readable]].[[controller]].
    179  RefPtr<ReadableStreamDefaultController> readableController =
    180      stream->Readable()->Controller()->AsDefault();
    181 
    182  // Step 3: Perform ! ReadableStreamDefaultControllerClose(readableController).
    183  ReadableStreamDefaultControllerClose(aCx, readableController, aRv);
    184 
    185  // Step 4: Let error be a TypeError exception indicating that the stream has
    186  // been terminated.
    187  ErrorResult rv;
    188  rv.ThrowTypeError("Terminating the stream");
    189  JS::Rooted<JS::Value> error(aCx);
    190  MOZ_ALWAYS_TRUE(ToJSValue(aCx, std::move(rv), &error));
    191 
    192  // Step 5: Perform ! TransformStreamErrorWritableAndUnblockWrite(stream,
    193  // error).
    194  TransformStreamErrorWritableAndUnblockWrite(aCx, stream, error, aRv);
    195 }
    196 
    197 namespace streams_abstract {
    198 
    199 // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller
    200 void SetUpTransformStreamDefaultController(
    201    JSContext* aCx, TransformStream& aStream,
    202    TransformStreamDefaultController& aController,
    203    TransformerAlgorithmsBase& aTransformerAlgorithms) {
    204  // Step 1. Assert: stream implements TransformStream.
    205  // Step 2. Assert: stream.[[controller]] is undefined.
    206  MOZ_ASSERT(!aStream.Controller());
    207 
    208  // Step 3. Set controller.[[stream]] to stream.
    209  aController.SetStream(aStream);
    210 
    211  // Step 4. Set stream.[[controller]] to controller.
    212  aStream.SetController(aController);
    213 
    214  // Step 5. Set controller.[[transformAlgorithm]] to transformAlgorithm.
    215  // Step 6. Set controller.[[flushAlgorithm]] to flushAlgorithm.
    216  aController.SetAlgorithms(&aTransformerAlgorithms);
    217 }
    218 
    219 // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer
    220 void SetUpTransformStreamDefaultControllerFromTransformer(
    221    JSContext* aCx, TransformStream& aStream,
    222    JS::Handle<JSObject*> aTransformer, Transformer& aTransformerDict) {
    223  // Step 1. Let controller be a new TransformStreamDefaultController.
    224  auto controller =
    225      MakeRefPtr<TransformStreamDefaultController>(aStream.GetParentObject());
    226 
    227  // Step 2 - 5:
    228  auto algorithms = MakeRefPtr<TransformerAlgorithms>(
    229      aStream.GetParentObject(), aTransformer, aTransformerDict);
    230 
    231  // Step 6: Perform ! SetUpTransformStreamDefaultController(stream, controller,
    232  // transformAlgorithm, flushAlgorithm).
    233  SetUpTransformStreamDefaultController(aCx, aStream, *controller, *algorithms);
    234 }
    235 
    236 }  // namespace streams_abstract
    237 
    238 }  // namespace mozilla::dom