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
{
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() {}
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
{
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
;
107 ~UnderlyingSinkAlgorithms() override
{ mozilla::DropJSObjects(this); }
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
{
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
> CloseCallback(
139 JSContext
* aCx
, ErrorResult
& aRv
) final
;
141 MOZ_CAN_RUN_SCRIPT already_AddRefed
<Promise
> AbortCallback(
142 JSContext
* aCx
, const Optional
<JS::Handle
<JS::Value
>>& aReason
,
143 ErrorResult
& aRv
) final
;
145 virtual already_AddRefed
<Promise
> CloseCallbackImpl(JSContext
* aCx
,
147 // (closeAlgorithm is optional, give null by default)
151 virtual already_AddRefed
<Promise
> AbortCallbackImpl(
152 JSContext
* aCx
, const Optional
<JS::Handle
<JS::Value
>>& aReason
,
154 // (abortAlgorithm is optional, give null by default)
159 class WritableStreamToOutput final
: public UnderlyingSinkAlgorithmsWrapper
,
160 public nsIOutputStreamCallback
{
161 NS_DECL_ISUPPORTS_INHERITED
162 NS_DECL_NSIOUTPUTSTREAMCALLBACK
163 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WritableStreamToOutput
,
164 UnderlyingSinkAlgorithmsBase
)
166 WritableStreamToOutput(nsIGlobalObject
* aParent
,
167 nsIAsyncOutputStream
* aOutput
)
168 : mWritten(0), mParent(aParent
), mOutput(aOutput
) {}
170 // Streams algorithms
172 already_AddRefed
<Promise
> WriteCallback(
173 JSContext
* aCx
, JS::Handle
<JS::Value
> aChunk
,
174 WritableStreamDefaultController
& aController
, ErrorResult
& aRv
) override
;
176 // No CloseCallbackImpl() since ReleaseObjects() will call Close()
178 already_AddRefed
<Promise
> AbortCallbackImpl(
179 JSContext
* aCx
, const Optional
<JS::Handle
<JS::Value
>>& aReason
,
180 ErrorResult
& aRv
) override
;
182 void ReleaseObjects() override
;
185 ~WritableStreamToOutput() override
= default;
194 nsCOMPtr
<nsIGlobalObject
> mParent
;
195 nsCOMPtr
<nsIAsyncOutputStream
> mOutput
;
196 RefPtr
<Promise
> mPromise
; // Resolved when entirely written
197 Maybe
<Buffer
<uint8_t>> mData
;
200 } // namespace mozilla::dom