Bug 1946787 - Avoid creating redundant GradientCache::OnMaxEntriesBreached tasks...
[gecko.git] / dom / streams / TransformStreamDefaultController.cpp
blobbbcb7f94f2dc6fb954f696be610f622d5d3c1d59
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 #include "mozilla/dom/TransformStreamDefaultController.h"
9 #include "TransformerCallbackHelpers.h"
10 #include "mozilla/Attributes.h"
11 #include "mozilla/dom/Promise.h"
12 #include "mozilla/dom/ReadableStream.h"
13 #include "mozilla/dom/ReadableStreamDefaultController.h"
14 #include "mozilla/dom/TransformStream.h"
15 #include "mozilla/dom/TransformStreamDefaultControllerBinding.h"
16 #include "nsWrapperCache.h"
18 namespace mozilla::dom {
20 using namespace streams_abstract;
22 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TransformStreamDefaultController, mGlobal,
23 mStream, mTransformerAlgorithms)
24 NS_IMPL_CYCLE_COLLECTING_ADDREF(TransformStreamDefaultController)
25 NS_IMPL_CYCLE_COLLECTING_RELEASE(TransformStreamDefaultController)
26 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TransformStreamDefaultController)
27 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
28 NS_INTERFACE_MAP_ENTRY(nsISupports)
29 NS_INTERFACE_MAP_END
31 TransformStream* TransformStreamDefaultController::Stream() { return mStream; }
33 void TransformStreamDefaultController::SetStream(TransformStream& aStream) {
34 MOZ_ASSERT(!mStream);
35 mStream = &aStream;
38 TransformerAlgorithmsBase* TransformStreamDefaultController::Algorithms() {
39 return mTransformerAlgorithms;
42 void TransformStreamDefaultController::SetAlgorithms(
43 TransformerAlgorithmsBase* aTransformerAlgorithms) {
44 mTransformerAlgorithms = aTransformerAlgorithms;
47 TransformStreamDefaultController::TransformStreamDefaultController(
48 nsIGlobalObject* aGlobal)
49 : mGlobal(aGlobal) {
50 mozilla::HoldJSObjects(this);
53 TransformStreamDefaultController::~TransformStreamDefaultController() {
54 mozilla::DropJSObjects(this);
57 JSObject* TransformStreamDefaultController::WrapObject(
58 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
59 return TransformStreamDefaultController_Binding::Wrap(aCx, this, aGivenProto);
62 // https://streams.spec.whatwg.org/#ts-default-controller-desired-size
63 Nullable<double> TransformStreamDefaultController::GetDesiredSize() const {
64 // Step 1. Let readableController be
65 // this.[[stream]].[[readable]].[[controller]].
66 RefPtr<ReadableStreamDefaultController> readableController =
67 mStream->Readable()->Controller()->AsDefault();
69 // Step 2. Return !
70 // ReadableStreamDefaultControllerGetDesiredSize(readableController).
71 return ReadableStreamDefaultControllerGetDesiredSize(readableController);
74 // https://streams.spec.whatwg.org/#rs-default-controller-has-backpressure
75 // Looks like a readable stream thing but the spec explicitly says this is for
76 // TransformStream.
77 static bool ReadableStreamDefaultControllerHasBackpressure(
78 ReadableStreamDefaultController* aController) {
79 // Step 1: If ! ReadableStreamDefaultControllerShouldCallPull(controller) is
80 // true, return false.
81 // Step 2: Otherwise, return true.
82 return !ReadableStreamDefaultControllerShouldCallPull(aController);
85 void TransformStreamDefaultController::Enqueue(JSContext* aCx,
86 JS::Handle<JS::Value> aChunk,
87 ErrorResult& aRv) {
88 // Step 1: Perform ? TransformStreamDefaultControllerEnqueue(this, chunk).
90 // Inlining TransformStreamDefaultControllerEnqueue here.
91 // https://streams.spec.whatwg.org/#transform-stream-default-controller-enqueue
93 // Step 1: Let stream be controller.[[stream]].
94 RefPtr<TransformStream> stream = mStream;
96 // Step 2: Let readableController be stream.[[readable]].[[controller]].
97 RefPtr<ReadableStreamDefaultController> readableController =
98 stream->Readable()->Controller()->AsDefault();
100 // Step 3: If !
101 // ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController) is
102 // false, throw a TypeError exception.
103 if (!ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
104 readableController, CloseOrEnqueue::Enqueue, aRv)) {
105 return;
108 // Step 4: Let enqueueResult be
109 // ReadableStreamDefaultControllerEnqueue(readableController, chunk).
110 ErrorResult rv;
111 ReadableStreamDefaultControllerEnqueue(aCx, readableController, aChunk, rv);
113 // Step 5: If enqueueResult is an abrupt completion,
114 if (rv.MaybeSetPendingException(aCx)) {
115 JS::Rooted<JS::Value> error(aCx);
116 if (!JS_GetPendingException(aCx, &error)) {
117 // Uncatchable exception; we should mark aRv and return.
118 aRv.StealExceptionFromJSContext(aCx);
119 return;
121 JS_ClearPendingException(aCx);
123 // Step 5.1: Perform ! TransformStreamErrorWritableAndUnblockWrite(stream,
124 // enqueueResult.[[Value]]).
125 TransformStreamErrorWritableAndUnblockWrite(aCx, stream, error, aRv);
127 // Step 5.2: Throw stream.[[readable]].[[storedError]].
128 JS::Rooted<JS::Value> storedError(aCx, stream->Readable()->StoredError());
129 aRv.MightThrowJSException();
130 aRv.ThrowJSException(aCx, storedError);
131 return;
134 // Step 6: Let backpressure be !
135 // ReadableStreamDefaultControllerHasBackpressure(readableController).
136 bool backpressure =
137 ReadableStreamDefaultControllerHasBackpressure(readableController);
139 // Step 7: If backpressure is not stream.[[backpressure]],
140 if (backpressure != stream->Backpressure()) {
141 // Step 7.1: Assert: backpressure is true.
142 MOZ_ASSERT(backpressure);
144 // Step 7.2: Perform ! TransformStreamSetBackpressure(true).
145 stream->SetBackpressure(true);
149 // https://streams.spec.whatwg.org/#ts-default-controller-error
150 void TransformStreamDefaultController::Error(JSContext* aCx,
151 JS::Handle<JS::Value> aError,
152 ErrorResult& aRv) {
153 // Step 1: Perform ? TransformStreamDefaultControllerError(this, e).
155 // Inlining TransformStreamDefaultControllerError here.
156 // https://streams.spec.whatwg.org/#transform-stream-default-controller-error
158 // Perform ! TransformStreamError(controller.[[stream]], e).
159 // mStream is set in initialization step and only modified in cycle
160 // collection.
161 // TODO: Move mStream initialization to a method/constructor and make it
162 // MOZ_KNOWN_LIVE again. (See bug 1769854)
163 TransformStreamError(aCx, MOZ_KnownLive(mStream), aError, aRv);
166 // https://streams.spec.whatwg.org/#ts-default-controller-terminate
168 void TransformStreamDefaultController::Terminate(JSContext* aCx,
169 ErrorResult& aRv) {
170 // Step 1: Perform ? TransformStreamDefaultControllerTerminate(this).
172 // Inlining TransformStreamDefaultControllerTerminate here.
173 // https://streams.spec.whatwg.org/#transform-stream-default-controller-terminate
175 // Step 1: Let stream be controller.[[stream]].
176 RefPtr<TransformStream> stream = mStream;
178 // Step 2: Let readableController be stream.[[readable]].[[controller]].
179 RefPtr<ReadableStreamDefaultController> readableController =
180 stream->Readable()->Controller()->AsDefault();
182 // Step 3: Perform ! ReadableStreamDefaultControllerClose(readableController).
183 ReadableStreamDefaultControllerClose(aCx, readableController, aRv);
185 // Step 4: Let error be a TypeError exception indicating that the stream has
186 // been terminated.
187 ErrorResult rv;
188 rv.ThrowTypeError("Terminating the stream");
189 JS::Rooted<JS::Value> error(aCx);
190 MOZ_ALWAYS_TRUE(ToJSValue(aCx, std::move(rv), &error));
192 // Step 5: Perform ! TransformStreamErrorWritableAndUnblockWrite(stream,
193 // error).
194 TransformStreamErrorWritableAndUnblockWrite(aCx, stream, error, aRv);
197 namespace streams_abstract {
199 // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller
200 void SetUpTransformStreamDefaultController(
201 JSContext* aCx, TransformStream& aStream,
202 TransformStreamDefaultController& aController,
203 TransformerAlgorithmsBase& aTransformerAlgorithms) {
204 // Step 1. Assert: stream implements TransformStream.
205 // Step 2. Assert: stream.[[controller]] is undefined.
206 MOZ_ASSERT(!aStream.Controller());
208 // Step 3. Set controller.[[stream]] to stream.
209 aController.SetStream(aStream);
211 // Step 4. Set stream.[[controller]] to controller.
212 aStream.SetController(aController);
214 // Step 5. Set controller.[[transformAlgorithm]] to transformAlgorithm.
215 // Step 6. Set controller.[[flushAlgorithm]] to flushAlgorithm.
216 aController.SetAlgorithms(&aTransformerAlgorithms);
219 // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer
220 void SetUpTransformStreamDefaultControllerFromTransformer(
221 JSContext* aCx, TransformStream& aStream,
222 JS::Handle<JSObject*> aTransformer, Transformer& aTransformerDict) {
223 // Step 1. Let controller be a new TransformStreamDefaultController.
224 auto controller =
225 MakeRefPtr<TransformStreamDefaultController>(aStream.GetParentObject());
227 // Step 2 - 5:
228 auto algorithms = MakeRefPtr<TransformerAlgorithms>(
229 aStream.GetParentObject(), aTransformer, aTransformerDict);
231 // Step 6: Perform ! SetUpTransformStreamDefaultController(stream, controller,
232 // transformAlgorithm, flushAlgorithm).
233 SetUpTransformStreamDefaultController(aCx, aStream, *controller, *algorithms);
236 } // namespace streams_abstract
238 } // namespace mozilla::dom