/* -*- 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_TeeState_h #define mozilla_dom_TeeState_h #include "mozilla/HoldDropJSObjects.h" #include "nsISupports.h" #include "mozilla/dom/ReadableStream.h" #include "mozilla/dom/ReadableStreamDefaultReader.h" #include "mozilla/dom/Promise.h" namespace mozilla::dom { class ReadableStreamDefaultTeeSourceAlgorithms; enum class TeeBranch : bool { Branch1, Branch2, }; inline TeeBranch OtherTeeBranch(TeeBranch aBranch) { if (aBranch == TeeBranch::Branch1) { return TeeBranch::Branch2; } return TeeBranch::Branch1; } // A closure capturing the free variables in the ReadableStreamTee family of // algorithms. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaulttee // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee struct TeeState : public nsISupports { NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TeeState) static already_AddRefed Create(ReadableStream* aStream, bool aCloneForBranch2, ErrorResult& aRv); ReadableStream* GetStream() const { return mStream; } void SetStream(ReadableStream* aStream) { mStream = aStream; } ReadableStreamGenericReader* GetReader() const { return mReader; } void SetReader(ReadableStreamGenericReader* aReader) { mReader = aReader; } ReadableStreamDefaultReader* GetDefaultReader() const { return mReader->AsDefault(); } bool ReadAgain() const { return mReadAgain; } void SetReadAgain(bool aReadAgain) { mReadAgain = aReadAgain; } // ReadableByteStreamTee uses ReadAgainForBranch{1,2}; bool ReadAgainForBranch1() const { return ReadAgain(); } void SetReadAgainForBranch1(bool aReadAgainForBranch1) { SetReadAgain(aReadAgainForBranch1); } bool ReadAgainForBranch2() const { return mReadAgainForBranch2; } void SetReadAgainForBranch2(bool aReadAgainForBranch2) { mReadAgainForBranch2 = aReadAgainForBranch2; } bool Reading() const { return mReading; } void SetReading(bool aReading) { mReading = aReading; } bool Canceled1() const { return mCanceled1; } void SetCanceled1(bool aCanceled1) { mCanceled1 = aCanceled1; } bool Canceled2() const { return mCanceled2; } void SetCanceled2(bool aCanceled2) { mCanceled2 = aCanceled2; } void SetCanceled(TeeBranch aBranch, bool aCanceled) { aBranch == TeeBranch::Branch1 ? SetCanceled1(aCanceled) : SetCanceled2(aCanceled); } bool Canceled(TeeBranch aBranch) { return aBranch == TeeBranch::Branch1 ? Canceled1() : Canceled2(); } JS::Value Reason1() const { return mReason1; } void SetReason1(JS::Handle aReason1) { mReason1 = aReason1; } JS::Value Reason2() const { return mReason2; } void SetReason2(JS::Handle aReason2) { mReason2 = aReason2; } void SetReason(TeeBranch aBranch, JS::Handle aReason) { aBranch == TeeBranch::Branch1 ? SetReason1(aReason) : SetReason2(aReason); } ReadableStream* Branch1() const { return mBranch1; } void SetBranch1(already_AddRefed aBranch1) { mBranch1 = aBranch1; } ReadableStream* Branch2() const { return mBranch2; } void SetBranch2(already_AddRefed aBranch2) { mBranch2 = aBranch2; } Promise* CancelPromise() const { return mCancelPromise; } void SetCancelPromise(Promise* aCancelPromise) { mCancelPromise = aCancelPromise; } bool CloneForBranch2() const { return mCloneForBranch2; } void setCloneForBranch2(bool aCloneForBranch2) { mCloneForBranch2 = aCloneForBranch2; } // Some code is better served by using an enum into various internal slots to // avoid duplication: Here we provide alternative accessors for that case. ReadableStream* Branch(TeeBranch aBranch) const { return aBranch == TeeBranch::Branch1 ? Branch1() : Branch2(); } void SetReadAgainForBranch(TeeBranch aBranch, bool aValue) { if (aBranch == TeeBranch::Branch1) { SetReadAgainForBranch1(aValue); return; } SetReadAgainForBranch2(aValue); } MOZ_CAN_RUN_SCRIPT void PullCallback(JSContext* aCx, nsIGlobalObject* aGlobal, ErrorResult& aRv); private: TeeState(ReadableStream* aStream, bool aCloneForBranch2); // Implicit: RefPtr mStream; // Step 3. (Step Numbering is based on ReadableStreamDefaultTee) RefPtr mReader; // Step 4. bool mReading = false; // Step 5. // (Aliased to readAgainForBranch1, for the purpose of ReadableByteStreamTee) bool mReadAgain = false; // ReadableByteStreamTee bool mReadAgainForBranch2 = false; // Step 6. bool mCanceled1 = false; // Step 7. bool mCanceled2 = false; // Step 8. JS::Heap mReason1; // Step 9. JS::Heap mReason2; // Step 10. RefPtr mBranch1; // Step 11. RefPtr mBranch2; // Step 12. RefPtr mCancelPromise; // Implicit: bool mCloneForBranch2 = false; virtual ~TeeState() { mozilla::DropJSObjects(this); } }; } // namespace mozilla::dom #endif