Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / streams / UnderlyingSinkCallbackHelpers.h
blob0717176aca3464df15ec553ea61b5c84f186d67a
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/. */
7 #ifndef mozilla_dom_UnderlyingSinkCallbackHelpers_h
8 #define mozilla_dom_UnderlyingSinkCallbackHelpers_h
10 #include "mozilla/Maybe.h"
11 #include "mozilla/Buffer.h"
12 #include "mozilla/HoldDropJSObjects.h"
13 #include "mozilla/dom/Promise.h"
14 #include "mozilla/dom/UnderlyingSinkBinding.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsISupports.h"
17 #include "nsISupportsImpl.h"
18 #include "nsIAsyncOutputStream.h"
21 * See the comment in UnderlyingSourceCallbackHelpers.h!
23 * A native implementation of these callbacks is however currently not required.
25 namespace mozilla::dom {
27 class WritableStreamDefaultController;
29 class UnderlyingSinkAlgorithmsBase : public nsISupports {
30 public:
31 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
32 NS_DECL_CYCLE_COLLECTION_CLASS(UnderlyingSinkAlgorithmsBase)
34 MOZ_CAN_RUN_SCRIPT virtual void StartCallback(
35 JSContext* aCx, WritableStreamDefaultController& aController,
36 JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv) = 0;
38 MOZ_CAN_RUN_SCRIPT virtual already_AddRefed<Promise> WriteCallback(
39 JSContext* aCx, JS::Handle<JS::Value> aChunk,
40 WritableStreamDefaultController& aController, ErrorResult& aRv) = 0;
42 MOZ_CAN_RUN_SCRIPT virtual already_AddRefed<Promise> CloseCallback(
43 JSContext* aCx, ErrorResult& aRv) = 0;
45 MOZ_CAN_RUN_SCRIPT virtual already_AddRefed<Promise> AbortCallback(
46 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
47 ErrorResult& aRv) = 0;
49 // Implement this when you need to release underlying resources immediately
50 // from closed/errored(aborted) streams, without waiting for GC.
51 virtual void ReleaseObjects() {}
53 protected:
54 virtual ~UnderlyingSinkAlgorithmsBase() = default;
57 // https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller-from-underlying-sink
58 class UnderlyingSinkAlgorithms final : public UnderlyingSinkAlgorithmsBase {
59 public:
60 NS_DECL_ISUPPORTS_INHERITED
61 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
62 UnderlyingSinkAlgorithms, UnderlyingSinkAlgorithmsBase)
64 UnderlyingSinkAlgorithms(nsIGlobalObject* aGlobal,
65 JS::Handle<JSObject*> aUnderlyingSink,
66 UnderlyingSink& aUnderlyingSinkDict)
67 : mGlobal(aGlobal), mUnderlyingSink(aUnderlyingSink) {
68 // Step 6. (implicit Step 2.)
69 if (aUnderlyingSinkDict.mStart.WasPassed()) {
70 mStartCallback = aUnderlyingSinkDict.mStart.Value();
73 // Step 7. (implicit Step 3.)
74 if (aUnderlyingSinkDict.mWrite.WasPassed()) {
75 mWriteCallback = aUnderlyingSinkDict.mWrite.Value();
78 // Step 8. (implicit Step 4.)
79 if (aUnderlyingSinkDict.mClose.WasPassed()) {
80 mCloseCallback = aUnderlyingSinkDict.mClose.Value();
83 // Step 9. (implicit Step 5.)
84 if (aUnderlyingSinkDict.mAbort.WasPassed()) {
85 mAbortCallback = aUnderlyingSinkDict.mAbort.Value();
88 mozilla::HoldJSObjects(this);
91 MOZ_CAN_RUN_SCRIPT void StartCallback(
92 JSContext* aCx, WritableStreamDefaultController& aController,
93 JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv) override;
95 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WriteCallback(
96 JSContext* aCx, JS::Handle<JS::Value> aChunk,
97 WritableStreamDefaultController& aController, ErrorResult& aRv) override;
99 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CloseCallback(
100 JSContext* aCx, ErrorResult& aRv) override;
102 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> AbortCallback(
103 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
104 ErrorResult& aRv) override;
106 protected:
107 ~UnderlyingSinkAlgorithms() override { mozilla::DropJSObjects(this); }
109 private:
110 // Virtually const, but are cycle collected
111 nsCOMPtr<nsIGlobalObject> mGlobal;
112 JS::Heap<JSObject*> mUnderlyingSink;
113 MOZ_KNOWN_LIVE RefPtr<UnderlyingSinkStartCallback> mStartCallback;
114 MOZ_KNOWN_LIVE RefPtr<UnderlyingSinkWriteCallback> mWriteCallback;
115 MOZ_KNOWN_LIVE RefPtr<UnderlyingSinkCloseCallback> mCloseCallback;
116 MOZ_KNOWN_LIVE RefPtr<UnderlyingSinkAbortCallback> mAbortCallback;
119 // https://streams.spec.whatwg.org/#writablestream-set-up
120 // Wrappers defined by the "Set up" methods in the spec.
121 // (closeAlgorithmWrapper, abortAlgorithmWrapper)
122 // This helps you just return nullptr when 1) the algorithm is synchronous, or
123 // 2) an error occurred, as this wrapper will return a resolved or rejected
124 // promise respectively.
125 // Note that StartCallback is only for JS consumers to access the
126 // controller, and thus is no-op here since native consumers can call
127 // `ErrorNative()` etc. without direct controller access.
128 class UnderlyingSinkAlgorithmsWrapper : public UnderlyingSinkAlgorithmsBase {
129 public:
130 void StartCallback(JSContext* aCx,
131 WritableStreamDefaultController& aController,
132 JS::MutableHandle<JS::Value> aRetVal,
133 ErrorResult& aRv) final {
134 // Step 1: Let startAlgorithm be an algorithm that returns undefined.
135 aRetVal.setUndefined();
138 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WriteCallback(
139 JSContext* aCx, JS::Handle<JS::Value> aChunk,
140 WritableStreamDefaultController& aController, ErrorResult& aRv) final;
142 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CloseCallback(
143 JSContext* aCx, ErrorResult& aRv) final;
145 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> AbortCallback(
146 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
147 ErrorResult& aRv) final;
149 virtual already_AddRefed<Promise> WriteCallbackImpl(
150 JSContext* aCx, JS::Handle<JS::Value> aChunk,
151 WritableStreamDefaultController& aController, ErrorResult& aRv) = 0;
153 virtual already_AddRefed<Promise> CloseCallbackImpl(JSContext* aCx,
154 ErrorResult& aRv) {
155 // (closeAlgorithm is optional, give null by default)
156 return nullptr;
159 virtual already_AddRefed<Promise> AbortCallbackImpl(
160 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
161 ErrorResult& aRv) {
162 // (abortAlgorithm is optional, give null by default)
163 return nullptr;
167 class WritableStreamToOutput final : public UnderlyingSinkAlgorithmsWrapper,
168 public nsIOutputStreamCallback {
169 NS_DECL_ISUPPORTS_INHERITED
170 NS_DECL_NSIOUTPUTSTREAMCALLBACK
171 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WritableStreamToOutput,
172 UnderlyingSinkAlgorithmsBase)
174 WritableStreamToOutput(nsIGlobalObject* aParent,
175 nsIAsyncOutputStream* aOutput)
176 : mWritten(0), mParent(aParent), mOutput(aOutput) {}
178 // Streams algorithms
180 already_AddRefed<Promise> WriteCallbackImpl(
181 JSContext* aCx, JS::Handle<JS::Value> aChunk,
182 WritableStreamDefaultController& aController, ErrorResult& aRv) override;
184 // No CloseCallbackImpl() since ReleaseObjects() will call Close()
186 already_AddRefed<Promise> AbortCallbackImpl(
187 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
188 ErrorResult& aRv) override;
190 void ReleaseObjects() override;
192 private:
193 ~WritableStreamToOutput() override = default;
195 void ClearData() {
196 mData = Nothing();
197 mPromise = nullptr;
198 mWritten = 0;
201 uint32_t mWritten;
202 nsCOMPtr<nsIGlobalObject> mParent;
203 nsCOMPtr<nsIAsyncOutputStream> mOutput;
204 RefPtr<Promise> mPromise; // Resolved when entirely written
205 Maybe<Buffer<uint8_t>> mData;
208 } // namespace mozilla::dom
210 #endif