tor-browser

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

WritableStream.h (9864B)


      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_WritableStream_h
      8 #define mozilla_dom_WritableStream_h
      9 
     10 #include "js/TypeDecls.h"
     11 #include "js/Value.h"
     12 #include "mozilla/Attributes.h"
     13 #include "mozilla/ErrorResult.h"
     14 #include "mozilla/dom/BindingDeclarations.h"
     15 #include "mozilla/dom/QueuingStrategyBinding.h"
     16 #include "mozilla/dom/WritableStreamDefaultController.h"
     17 #include "mozilla/dom/WritableStreamDefaultWriter.h"
     18 #include "nsCycleCollectionParticipant.h"
     19 #include "nsWrapperCache.h"
     20 
     21 namespace mozilla::dom {
     22 
     23 class Promise;
     24 class WritableStreamDefaultController;
     25 class WritableStreamDefaultWriter;
     26 class UnderlyingSinkAlgorithmsBase;
     27 class UniqueMessagePortId;
     28 class MessagePort;
     29 
     30 class WritableStream : public nsISupports, public nsWrapperCache {
     31 public:
     32  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     33  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WritableStream)
     34 
     35  friend class ReadableStream;
     36 
     37 protected:
     38  virtual ~WritableStream();
     39 
     40  virtual void LastRelease() {}
     41 
     42  // If one extends WritableStream with another cycle collectable class,
     43  // calling HoldJSObjects and DropJSObjects should happen using 'this' of
     44  // that extending class. And in that case Explicit should be passed to the
     45  // constructor of WriteableStream so that it doesn't make those calls.
     46  // See also https://bugzilla.mozilla.org/show_bug.cgi?id=1801214.
     47  enum class HoldDropJSObjectsCaller { Implicit, Explicit };
     48 
     49  explicit WritableStream(const GlobalObject& aGlobal,
     50                          HoldDropJSObjectsCaller aHoldDropCaller);
     51  explicit WritableStream(nsIGlobalObject* aGlobal,
     52                          HoldDropJSObjectsCaller aHoldDropCaller);
     53 
     54 public:
     55  // Slot Getter/Setters:
     56  bool Backpressure() const { return mBackpressure; }
     57  void SetBackpressure(bool aBackpressure) { mBackpressure = aBackpressure; }
     58 
     59  Promise* GetCloseRequest() { return mCloseRequest; }
     60  void SetCloseRequest(Promise* aRequest) { mCloseRequest = aRequest; }
     61 
     62  MOZ_KNOWN_LIVE WritableStreamDefaultController* Controller() {
     63    return mController;
     64  }
     65  void SetController(WritableStreamDefaultController& aController) {
     66    MOZ_ASSERT(!mController);
     67    mController = &aController;
     68  }
     69 
     70  Promise* GetInFlightWriteRequest() const { return mInFlightWriteRequest; }
     71 
     72  Promise* GetPendingAbortRequestPromise() const {
     73    return mPendingAbortRequestPromise;
     74  }
     75 
     76  void SetPendingAbortRequest(Promise* aPromise, JS::Handle<JS::Value> aReason,
     77                              bool aWasAlreadyErroring) {
     78    mPendingAbortRequestPromise = aPromise;
     79    mPendingAbortRequestReason = aReason;
     80    mPendingAbortRequestWasAlreadyErroring = aWasAlreadyErroring;
     81  }
     82 
     83  WritableStreamDefaultWriter* GetWriter() const { return mWriter; }
     84  void SetWriter(WritableStreamDefaultWriter* aWriter) { mWriter = aWriter; }
     85 
     86  enum class WriterState { Writable, Closed, Erroring, Errored };
     87 
     88  WriterState State() const { return mState; }
     89  void SetState(const WriterState& aState) { mState = aState; }
     90 
     91  JS::Value StoredError() const { return mStoredError; }
     92  void SetStoredError(JS::Handle<JS::Value> aStoredError) {
     93    mStoredError = aStoredError;
     94  }
     95 
     96  void AppendWriteRequest(RefPtr<Promise>& aRequest) {
     97    mWriteRequests.Push(RefPtr<Promise>(aRequest));
     98  }
     99 
    100  // CreateWritableStream
    101  MOZ_CAN_RUN_SCRIPT static already_AddRefed<WritableStream> CreateAbstract(
    102      JSContext* aCx, nsIGlobalObject* aGlobal,
    103      UnderlyingSinkAlgorithmsBase* aAlgorithms, double aHighWaterMark,
    104      QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv);
    105 
    106  // WritableStreamCloseQueuedOrInFlight
    107  bool CloseQueuedOrInFlight() const {
    108    return mCloseRequest || mInFlightCloseRequest;
    109  }
    110 
    111  // WritableStreamDealWithRejection
    112  MOZ_CAN_RUN_SCRIPT void DealWithRejection(JSContext* aCx,
    113                                            JS::Handle<JS::Value> aError,
    114                                            ErrorResult& aRv);
    115 
    116  // WritableStreamFinishErroring
    117  MOZ_CAN_RUN_SCRIPT void FinishErroring(JSContext* aCx, ErrorResult& aRv);
    118 
    119  // WritableStreamFinishInFlightClose
    120  void FinishInFlightClose();
    121 
    122  // WritableStreamFinishInFlightCloseWithError
    123  MOZ_CAN_RUN_SCRIPT void FinishInFlightCloseWithError(
    124      JSContext* aCx, JS::Handle<JS::Value> aError, ErrorResult& aRv);
    125 
    126  // WritableStreamFinishInFlightWrite
    127  void FinishInFlightWrite();
    128 
    129  // WritableStreamFinishInFlightWriteWithError
    130  MOZ_CAN_RUN_SCRIPT void FinishInFlightWriteWithError(
    131      JSContext* aCX, JS::Handle<JS::Value> aError, ErrorResult& aR);
    132 
    133  // WritableStreamHasOperationMarkedInFlight
    134  bool HasOperationMarkedInFlight() const {
    135    return mInFlightWriteRequest || mInFlightCloseRequest;
    136  }
    137 
    138  // WritableStreamMarkCloseRequestInFlight
    139  void MarkCloseRequestInFlight();
    140 
    141  // WritableStreamMarkFirstWriteRequestInFlight
    142  void MarkFirstWriteRequestInFlight();
    143 
    144  // WritableStreamRejectCloseAndClosedPromiseIfNeeded
    145  void RejectCloseAndClosedPromiseIfNeeded();
    146 
    147  // WritableStreamStartErroring
    148  MOZ_CAN_RUN_SCRIPT void StartErroring(JSContext* aCx,
    149                                        JS::Handle<JS::Value> aReason,
    150                                        ErrorResult& aRv);
    151 
    152  // WritableStreamUpdateBackpressure
    153  void UpdateBackpressure(bool aBackpressure);
    154 
    155  // [Transferable]
    156  // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-steps
    157  MOZ_CAN_RUN_SCRIPT bool Transfer(JSContext* aCx,
    158                                   UniqueMessagePortId& aPortId);
    159  // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-receiving-steps
    160  MOZ_CAN_RUN_SCRIPT static already_AddRefed<WritableStream>
    161  ReceiveTransferImpl(JSContext* aCx, nsIGlobalObject* aGlobal,
    162                      MessagePort& aPort);
    163  MOZ_CAN_RUN_SCRIPT static bool ReceiveTransfer(
    164      JSContext* aCx, nsIGlobalObject* aGlobal, MessagePort& aPort,
    165      JS::MutableHandle<JSObject*> aReturnObject);
    166 
    167  // Public functions to implement other specs
    168  // https://streams.spec.whatwg.org/#other-specs-ws
    169 
    170  // https://streams.spec.whatwg.org/#writablestream-set-up
    171 protected:
    172  // Sets up the WritableStream. Intended for subclasses.
    173  void SetUpNative(JSContext* aCx, UnderlyingSinkAlgorithmsWrapper& aAlgorithms,
    174                   Maybe<double> aHighWaterMark,
    175                   QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv);
    176 
    177 public:
    178  // Creates and sets up a WritableStream. Use SetUpNative for this purpose in
    179  // subclasses.
    180  static already_AddRefed<WritableStream> CreateNative(
    181      JSContext* aCx, nsIGlobalObject& aGlobal,
    182      UnderlyingSinkAlgorithmsWrapper& aAlgorithms,
    183      Maybe<double> aHighWaterMark, QueuingStrategySize* aSizeAlgorithm,
    184      ErrorResult& aRv);
    185 
    186  // The following definitions must only be used on WritableStream instances
    187  // initialized via the above set up algorithm:
    188 
    189  // https://streams.spec.whatwg.org/#writablestream-error
    190  MOZ_CAN_RUN_SCRIPT void ErrorNative(JSContext* aCx,
    191                                      JS::Handle<JS::Value> aError,
    192                                      ErrorResult& aRv);
    193 
    194  // IDL layer functions
    195 
    196  nsIGlobalObject* GetParentObject() const { return mGlobal; }
    197 
    198  JSObject* WrapObject(JSContext* aCx,
    199                       JS::Handle<JSObject*> aGivenProto) override;
    200 
    201  // IDL methods
    202 
    203  // TODO: Use MOZ_CAN_RUN_SCRIPT when IDL constructors can use it (bug 1749042)
    204  MOZ_CAN_RUN_SCRIPT_BOUNDARY static already_AddRefed<WritableStream>
    205  Constructor(const GlobalObject& aGlobal,
    206              const Optional<JS::Handle<JSObject*>>& aUnderlyingSink,
    207              const QueuingStrategy& aStrategy, ErrorResult& aRv);
    208 
    209  bool Locked() const { return !!mWriter; }
    210 
    211  MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> Abort(
    212      JSContext* cx, JS::Handle<JS::Value> aReason, ErrorResult& aRv);
    213 
    214  MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> Close(JSContext* aCx,
    215                                                     ErrorResult& aRv);
    216 
    217  already_AddRefed<WritableStreamDefaultWriter> GetWriter(ErrorResult& aRv);
    218 
    219 protected:
    220  nsCOMPtr<nsIGlobalObject> mGlobal;
    221 
    222  // Internal Slots:
    223 private:
    224  bool mBackpressure = false;
    225  RefPtr<Promise> mCloseRequest;
    226  RefPtr<WritableStreamDefaultController> mController;
    227  RefPtr<Promise> mInFlightWriteRequest;
    228  RefPtr<Promise> mInFlightCloseRequest;
    229 
    230  // We inline all members of [[pendingAbortRequest]] in this class.
    231  // The absence (i.e. undefined) of the [[pendingAbortRequest]]
    232  // is indicated by mPendingAbortRequestPromise = nullptr.
    233  RefPtr<Promise> mPendingAbortRequestPromise;
    234  JS::Heap<JS::Value> mPendingAbortRequestReason;
    235  bool mPendingAbortRequestWasAlreadyErroring = false;
    236 
    237  WriterState mState = WriterState::Writable;
    238  JS::Heap<JS::Value> mStoredError;
    239  RefPtr<WritableStreamDefaultWriter> mWriter;
    240  mozilla::Queue<RefPtr<Promise>> mWriteRequests;
    241 
    242  HoldDropJSObjectsCaller mHoldDropCaller;
    243 };
    244 
    245 namespace streams_abstract {
    246 
    247 inline bool IsWritableStreamLocked(WritableStream* aStream) {
    248  return aStream->Locked();
    249 }
    250 
    251 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WritableStreamAbort(
    252    JSContext* aCx, WritableStream* aStream, JS::Handle<JS::Value> aReason,
    253    ErrorResult& aRv);
    254 
    255 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WritableStreamClose(
    256    JSContext* aCx, WritableStream* aStream, ErrorResult& aRv);
    257 
    258 already_AddRefed<Promise> WritableStreamAddWriteRequest(
    259    WritableStream* aStream);
    260 
    261 already_AddRefed<WritableStreamDefaultWriter>
    262 AcquireWritableStreamDefaultWriter(WritableStream* aStream, ErrorResult& aRv);
    263 
    264 }  // namespace streams_abstract
    265 
    266 }  // namespace mozilla::dom
    267 
    268 #endif  // mozilla_dom_WritableStream_h