Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / dom / streams / UnderlyingSinkCallbackHelpers.h
blobc99c8709ce83c9e0a704eb63a3574ca79d80613a
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> 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,
146 ErrorResult& aRv) {
147 // (closeAlgorithm is optional, give null by default)
148 return nullptr;
151 virtual already_AddRefed<Promise> AbortCallbackImpl(
152 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
153 ErrorResult& aRv) {
154 // (abortAlgorithm is optional, give null by default)
155 return nullptr;
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;
184 private:
185 ~WritableStreamToOutput() override = default;
187 void ClearData() {
188 mData = Nothing();
189 mPromise = nullptr;
190 mWritten = 0;
193 uint32_t mWritten;
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
202 #endif