summaryrefslogtreecommitdiffstats
path: root/dom/streams/TeeState.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/streams/TeeState.h')
-rw-r--r--dom/streams/TeeState.h179
1 files changed, 179 insertions, 0 deletions
diff --git a/dom/streams/TeeState.h b/dom/streams/TeeState.h
new file mode 100644
index 0000000000..9a688be662
--- /dev/null
+++ b/dom/streams/TeeState.h
@@ -0,0 +1,179 @@
+/* -*- 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<TeeState> 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<JS::Value> aReason1) { mReason1 = aReason1; }
+
+ JS::Value Reason2() const { return mReason2; }
+ void SetReason2(JS::Handle<JS::Value> aReason2) { mReason2 = aReason2; }
+
+ void SetReason(TeeBranch aBranch, JS::Handle<JS::Value> aReason) {
+ aBranch == TeeBranch::Branch1 ? SetReason1(aReason) : SetReason2(aReason);
+ }
+
+ ReadableStream* Branch1() const { return mBranch1; }
+ void SetBranch1(already_AddRefed<ReadableStream> aBranch1) {
+ mBranch1 = aBranch1;
+ }
+
+ ReadableStream* Branch2() const { return mBranch2; }
+ void SetBranch2(already_AddRefed<ReadableStream> 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<ReadableStream> mStream;
+
+ // Step 3. (Step Numbering is based on ReadableStreamDefaultTee)
+ RefPtr<ReadableStreamGenericReader> 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<JS::Value> mReason1;
+
+ // Step 9.
+ JS::Heap<JS::Value> mReason2;
+
+ // Step 10.
+ RefPtr<ReadableStream> mBranch1;
+
+ // Step 11.
+ RefPtr<ReadableStream> mBranch2;
+
+ // Step 12.
+ RefPtr<Promise> mCancelPromise;
+
+ // Implicit:
+ bool mCloneForBranch2 = false;
+
+ virtual ~TeeState() { mozilla::DropJSObjects(this); }
+};
+
+} // namespace mozilla::dom
+#endif