diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /dom/streams/WritableStream.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream/124.0.1.tar.xz firefox-upstream/124.0.1.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/streams/WritableStream.h')
-rw-r--r-- | dom/streams/WritableStream.h | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/dom/streams/WritableStream.h b/dom/streams/WritableStream.h new file mode 100644 index 0000000000..8b380020fe --- /dev/null +++ b/dom/streams/WritableStream.h @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 mozilla_dom_WritableStream_h +#define mozilla_dom_WritableStream_h + +#include "js/TypeDecls.h" +#include "js/Value.h" +#include "mozilla/Attributes.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/QueuingStrategyBinding.h" +#include "mozilla/dom/WritableStreamDefaultController.h" +#include "mozilla/dom/WritableStreamDefaultWriter.h" + +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" + +namespace mozilla::dom { + +class Promise; +class WritableStreamDefaultController; +class WritableStreamDefaultWriter; +class UnderlyingSinkAlgorithmsBase; +class UniqueMessagePortId; +class MessagePort; + +class WritableStream : public nsISupports, public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WritableStream) + + friend class ReadableStream; + + protected: + virtual ~WritableStream(); + + virtual void LastRelease() {} + + // If one extends WritableStream with another cycle collectable class, + // calling HoldJSObjects and DropJSObjects should happen using 'this' of + // that extending class. And in that case Explicit should be passed to the + // constructor of WriteableStream so that it doesn't make those calls. + // See also https://bugzilla.mozilla.org/show_bug.cgi?id=1801214. + enum class HoldDropJSObjectsCaller { Implicit, Explicit }; + + explicit WritableStream(const GlobalObject& aGlobal, + HoldDropJSObjectsCaller aHoldDropCaller); + explicit WritableStream(nsIGlobalObject* aGlobal, + HoldDropJSObjectsCaller aHoldDropCaller); + + public: + // Slot Getter/Setters: + bool Backpressure() const { return mBackpressure; } + void SetBackpressure(bool aBackpressure) { mBackpressure = aBackpressure; } + + Promise* GetCloseRequest() { return mCloseRequest; } + void SetCloseRequest(Promise* aRequest) { mCloseRequest = aRequest; } + + MOZ_KNOWN_LIVE WritableStreamDefaultController* Controller() { + return mController; + } + void SetController(WritableStreamDefaultController& aController) { + MOZ_ASSERT(!mController); + mController = &aController; + } + + Promise* GetInFlightWriteRequest() const { return mInFlightWriteRequest; } + + Promise* GetPendingAbortRequestPromise() const { + return mPendingAbortRequestPromise; + } + + void SetPendingAbortRequest(Promise* aPromise, JS::Handle<JS::Value> aReason, + bool aWasAlreadyErroring) { + mPendingAbortRequestPromise = aPromise; + mPendingAbortRequestReason = aReason; + mPendingAbortRequestWasAlreadyErroring = aWasAlreadyErroring; + } + + WritableStreamDefaultWriter* GetWriter() const { return mWriter; } + void SetWriter(WritableStreamDefaultWriter* aWriter) { mWriter = aWriter; } + + enum class WriterState { Writable, Closed, Erroring, Errored }; + + WriterState State() const { return mState; } + void SetState(const WriterState& aState) { mState = aState; } + + JS::Value StoredError() const { return mStoredError; } + void SetStoredError(JS::Handle<JS::Value> aStoredError) { + mStoredError = aStoredError; + } + + void AppendWriteRequest(RefPtr<Promise>& aRequest) { + mWriteRequests.AppendElement(aRequest); + } + + // CreateWritableStream + MOZ_CAN_RUN_SCRIPT static already_AddRefed<WritableStream> CreateAbstract( + JSContext* aCx, nsIGlobalObject* aGlobal, + UnderlyingSinkAlgorithmsBase* aAlgorithms, double aHighWaterMark, + QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv); + + // WritableStreamCloseQueuedOrInFlight + bool CloseQueuedOrInFlight() const { + return mCloseRequest || mInFlightCloseRequest; + } + + // WritableStreamDealWithRejection + MOZ_CAN_RUN_SCRIPT void DealWithRejection(JSContext* aCx, + JS::Handle<JS::Value> aError, + ErrorResult& aRv); + + // WritableStreamFinishErroring + MOZ_CAN_RUN_SCRIPT void FinishErroring(JSContext* aCx, ErrorResult& aRv); + + // WritableStreamFinishInFlightClose + void FinishInFlightClose(); + + // WritableStreamFinishInFlightCloseWithError + MOZ_CAN_RUN_SCRIPT void FinishInFlightCloseWithError( + JSContext* aCx, JS::Handle<JS::Value> aError, ErrorResult& aRv); + + // WritableStreamFinishInFlightWrite + void FinishInFlightWrite(); + + // WritableStreamFinishInFlightWriteWithError + MOZ_CAN_RUN_SCRIPT void FinishInFlightWriteWithError( + JSContext* aCX, JS::Handle<JS::Value> aError, ErrorResult& aR); + + // WritableStreamHasOperationMarkedInFlight + bool HasOperationMarkedInFlight() const { + return mInFlightWriteRequest || mInFlightCloseRequest; + } + + // WritableStreamMarkCloseRequestInFlight + void MarkCloseRequestInFlight(); + + // WritableStreamMarkFirstWriteRequestInFlight + void MarkFirstWriteRequestInFlight(); + + // WritableStreamRejectCloseAndClosedPromiseIfNeeded + void RejectCloseAndClosedPromiseIfNeeded(); + + // WritableStreamStartErroring + MOZ_CAN_RUN_SCRIPT void StartErroring(JSContext* aCx, + JS::Handle<JS::Value> aReason, + ErrorResult& aRv); + + // WritableStreamUpdateBackpressure + void UpdateBackpressure(bool aBackpressure); + + // [Transferable] + // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-steps + MOZ_CAN_RUN_SCRIPT bool Transfer(JSContext* aCx, + UniqueMessagePortId& aPortId); + // https://html.spec.whatwg.org/multipage/structured-data.html#transfer-receiving-steps + MOZ_CAN_RUN_SCRIPT static already_AddRefed<WritableStream> + ReceiveTransferImpl(JSContext* aCx, nsIGlobalObject* aGlobal, + MessagePort& aPort); + MOZ_CAN_RUN_SCRIPT static bool ReceiveTransfer( + JSContext* aCx, nsIGlobalObject* aGlobal, MessagePort& aPort, + JS::MutableHandle<JSObject*> aReturnObject); + + // Public functions to implement other specs + // https://streams.spec.whatwg.org/#other-specs-ws + + // https://streams.spec.whatwg.org/#writablestream-set-up + protected: + // Sets up the WritableStream. Intended for subclasses. + void SetUpNative(JSContext* aCx, UnderlyingSinkAlgorithmsWrapper& aAlgorithms, + Maybe<double> aHighWaterMark, + QueuingStrategySize* aSizeAlgorithm, ErrorResult& aRv); + + public: + // Creates and sets up a WritableStream. Use SetUpNative for this purpose in + // subclasses. + static already_AddRefed<WritableStream> CreateNative( + JSContext* aCx, nsIGlobalObject& aGlobal, + UnderlyingSinkAlgorithmsWrapper& aAlgorithms, + Maybe<double> aHighWaterMark, QueuingStrategySize* aSizeAlgorithm, + ErrorResult& aRv); + + // The following definitions must only be used on WritableStream instances + // initialized via the above set up algorithm: + + // https://streams.spec.whatwg.org/#writablestream-error + MOZ_CAN_RUN_SCRIPT void ErrorNative(JSContext* aCx, + JS::Handle<JS::Value> aError, + ErrorResult& aRv); + + // IDL layer functions + + nsIGlobalObject* GetParentObject() const { return mGlobal; } + + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + + // IDL methods + + // TODO: Use MOZ_CAN_RUN_SCRIPT when IDL constructors can use it (bug 1749042) + MOZ_CAN_RUN_SCRIPT_BOUNDARY static already_AddRefed<WritableStream> + Constructor(const GlobalObject& aGlobal, + const Optional<JS::Handle<JSObject*>>& aUnderlyingSink, + const QueuingStrategy& aStrategy, ErrorResult& aRv); + + bool Locked() const { return !!mWriter; } + + MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> Abort( + JSContext* cx, JS::Handle<JS::Value> aReason, ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> Close(JSContext* aCx, + ErrorResult& aRv); + + already_AddRefed<WritableStreamDefaultWriter> GetWriter(ErrorResult& aRv); + + protected: + nsCOMPtr<nsIGlobalObject> mGlobal; + + // Internal Slots: + private: + bool mBackpressure = false; + RefPtr<Promise> mCloseRequest; + RefPtr<WritableStreamDefaultController> mController; + RefPtr<Promise> mInFlightWriteRequest; + RefPtr<Promise> mInFlightCloseRequest; + + // We inline all members of [[pendingAbortRequest]] in this class. + // The absence (i.e. undefined) of the [[pendingAbortRequest]] + // is indicated by mPendingAbortRequestPromise = nullptr. + RefPtr<Promise> mPendingAbortRequestPromise; + JS::Heap<JS::Value> mPendingAbortRequestReason; + bool mPendingAbortRequestWasAlreadyErroring = false; + + WriterState mState = WriterState::Writable; + JS::Heap<JS::Value> mStoredError; + RefPtr<WritableStreamDefaultWriter> mWriter; + nsTArray<RefPtr<Promise>> mWriteRequests; + + HoldDropJSObjectsCaller mHoldDropCaller; +}; + +namespace streams_abstract { + +inline bool IsWritableStreamLocked(WritableStream* aStream) { + return aStream->Locked(); +} + +MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WritableStreamAbort( + JSContext* aCx, WritableStream* aStream, JS::Handle<JS::Value> aReason, + ErrorResult& aRv); + +MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WritableStreamClose( + JSContext* aCx, WritableStream* aStream, ErrorResult& aRv); + +already_AddRefed<Promise> WritableStreamAddWriteRequest( + WritableStream* aStream); + +already_AddRefed<WritableStreamDefaultWriter> +AcquireWritableStreamDefaultWriter(WritableStream* aStream, ErrorResult& aRv); + +} // namespace streams_abstract + +} // namespace mozilla::dom + +#endif // mozilla_dom_WritableStream_h |